8861 instruct divL_eReg_imm32( eADXRegL dst, immL32 imm, eRegI tmp, eRegI tmp2, eFlagsReg cr ) %{ |
8861 instruct divL_eReg_imm32( eADXRegL dst, immL32 imm, eRegI tmp, eRegI tmp2, eFlagsReg cr ) %{ |
8862 match(Set dst (DivL dst imm)); |
8862 match(Set dst (DivL dst imm)); |
8863 effect( TEMP tmp, TEMP tmp2, KILL cr ); |
8863 effect( TEMP tmp, TEMP tmp2, KILL cr ); |
8864 ins_cost(1000); |
8864 ins_cost(1000); |
8865 format %{ "MOV $tmp,abs($imm) # ldiv EDX:EAX,$imm\n\t" |
8865 format %{ "MOV $tmp,abs($imm) # ldiv EDX:EAX,$imm\n\t" |
|
8866 "XOR $tmp2,$tmp2\n\t" |
8866 "CMP $tmp,EDX\n\t" |
8867 "CMP $tmp,EDX\n\t" |
8867 "JA,s fast\n\t" |
8868 "JA,s fast\n\t" |
8868 "MOV $tmp2,EAX\n\t" |
8869 "MOV $tmp2,EAX\n\t" |
8869 "MOV EAX,EDX\n\t" |
8870 "MOV EAX,EDX\n\t" |
8870 "SAR EDX,31\n\t" |
8871 "MOV EDX,0\n\t" |
8871 "IDIV $tmp\n\t" |
8872 "JLE,s pos\n\t" |
8872 "XCHG EAX,$tmp2 \n\t" |
8873 "LNEG EAX : $tmp2\n\t" |
8873 "IDIV $tmp\n\t" |
8874 "DIV $tmp # unsigned division\n\t" |
8874 "CDQ\n\t" |
8875 "XCHG EAX,$tmp2\n\t" |
8875 "ADD EDX,$tmp2\n\t" |
8876 "DIV $tmp\n\t" |
|
8877 "LNEG $tmp2 : EAX\n\t" |
8876 "JMP,s done\n" |
8878 "JMP,s done\n" |
|
8879 "pos:\n\t" |
|
8880 "DIV $tmp\n\t" |
|
8881 "XCHG EAX,$tmp2\n" |
8877 "fast:\n\t" |
8882 "fast:\n\t" |
8878 "IDIV $tmp\n\t" |
8883 "DIV $tmp\n" |
8879 "XOR EDX,EDX\n" |
|
8880 "done:\n\t" |
8884 "done:\n\t" |
|
8885 "MOV EDX,$tmp2\n\t" |
8881 "NEG EDX:EAX # if $imm < 0" %} |
8886 "NEG EDX:EAX # if $imm < 0" %} |
8882 ins_encode %{ |
8887 ins_encode %{ |
8883 int con = (int)$imm$$constant; |
8888 int con = (int)$imm$$constant; |
8884 assert(con != 0 && con != -1 && con != min_jint, "wrong divisor"); |
8889 assert(con != 0 && con != -1 && con != min_jint, "wrong divisor"); |
8885 int pcon = (con > 0) ? con : -con; |
8890 int pcon = (con > 0) ? con : -con; |
8886 Label Lfast, Ldone; |
8891 Label Lfast, Lpos, Ldone; |
8887 |
8892 |
8888 __ movl($tmp$$Register, pcon); |
8893 __ movl($tmp$$Register, pcon); |
|
8894 __ xorl($tmp2$$Register,$tmp2$$Register); |
8889 __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register)); |
8895 __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register)); |
8890 __ jccb(Assembler::above, Lfast); |
8896 __ jccb(Assembler::above, Lfast); // result fits into 32 bit |
8891 |
8897 |
8892 __ movl($tmp2$$Register, $dst$$Register); // save |
8898 __ movl($tmp2$$Register, $dst$$Register); // save |
8893 __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); |
8899 __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); |
8894 __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // src sign |
8900 __ movl(HIGH_FROM_LOW($dst$$Register),0); // preserve flags |
8895 __ idivl($tmp$$Register); |
8901 __ jccb(Assembler::lessEqual, Lpos); // result is positive |
|
8902 |
|
8903 // Negative dividend. |
|
8904 // convert value to positive to use unsigned division |
|
8905 __ lneg($dst$$Register, $tmp2$$Register); |
|
8906 __ divl($tmp$$Register); |
8896 __ xchgl($dst$$Register, $tmp2$$Register); |
8907 __ xchgl($dst$$Register, $tmp2$$Register); |
8897 __ idivl($tmp$$Register); |
8908 __ divl($tmp$$Register); |
8898 __ cdql(); |
8909 // revert result back to negative |
8899 __ addl(HIGH_FROM_LOW($dst$$Register),$tmp2$$Register); |
8910 __ lneg($tmp2$$Register, $dst$$Register); |
8900 __ jmpb(Ldone); |
8911 __ jmpb(Ldone); |
8901 |
8912 |
|
8913 __ bind(Lpos); |
|
8914 __ divl($tmp$$Register); // Use unsigned division |
|
8915 __ xchgl($dst$$Register, $tmp2$$Register); |
|
8916 // Fallthrow for final divide, tmp2 has 32 bit hi result |
|
8917 |
8902 __ bind(Lfast); |
8918 __ bind(Lfast); |
8903 // fast path: src is positive and result fits into 32 bit |
8919 // fast path: src is positive |
8904 __ idivl($tmp$$Register); |
8920 __ divl($tmp$$Register); // Use unsigned division |
8905 __ xorl(HIGH_FROM_LOW($dst$$Register),HIGH_FROM_LOW($dst$$Register)); |
|
8906 |
8921 |
8907 __ bind(Ldone); |
8922 __ bind(Ldone); |
|
8923 __ movl(HIGH_FROM_LOW($dst$$Register),$tmp2$$Register); |
8908 if (con < 0) { |
8924 if (con < 0) { |
8909 __ lneg(HIGH_FROM_LOW($dst$$Register), $dst$$Register); |
8925 __ lneg(HIGH_FROM_LOW($dst$$Register), $dst$$Register); |
8910 } |
8926 } |
8911 %} |
8927 %} |
8912 ins_pipe( pipe_slow ); |
8928 ins_pipe( pipe_slow ); |
8920 format %{ "MOV $tmp,abs($imm) # lrem EDX:EAX,$imm\n\t" |
8936 format %{ "MOV $tmp,abs($imm) # lrem EDX:EAX,$imm\n\t" |
8921 "CMP $tmp,EDX\n\t" |
8937 "CMP $tmp,EDX\n\t" |
8922 "JA,s fast\n\t" |
8938 "JA,s fast\n\t" |
8923 "MOV $tmp2,EAX\n\t" |
8939 "MOV $tmp2,EAX\n\t" |
8924 "MOV EAX,EDX\n\t" |
8940 "MOV EAX,EDX\n\t" |
8925 "SAR EDX,31\n\t" |
8941 "MOV EDX,0\n\t" |
8926 "IDIV $tmp\n\t" |
8942 "JLE,s pos\n\t" |
|
8943 "LNEG EAX : $tmp2\n\t" |
|
8944 "DIV $tmp # unsigned division\n\t" |
|
8945 "MOV EAX,$tmp2\n\t" |
|
8946 "DIV $tmp\n\t" |
|
8947 "NEG EDX\n\t" |
|
8948 "JMP,s done\n" |
|
8949 "pos:\n\t" |
|
8950 "DIV $tmp\n\t" |
8927 "MOV EAX,$tmp2\n" |
8951 "MOV EAX,$tmp2\n" |
8928 "fast:\n\t" |
8952 "fast:\n\t" |
8929 "IDIV $tmp\n\t" |
8953 "DIV $tmp\n" |
|
8954 "done:\n\t" |
8930 "MOV EAX,EDX\n\t" |
8955 "MOV EAX,EDX\n\t" |
8931 "SAR EDX,31\n\t" %} |
8956 "SAR EDX,31\n\t" %} |
8932 ins_encode %{ |
8957 ins_encode %{ |
8933 int con = (int)$imm$$constant; |
8958 int con = (int)$imm$$constant; |
8934 assert(con != 0 && con != -1 && con != min_jint, "wrong divisor"); |
8959 assert(con != 0 && con != -1 && con != min_jint, "wrong divisor"); |
8935 int pcon = (con > 0) ? con : -con; |
8960 int pcon = (con > 0) ? con : -con; |
8936 Label Lfast; |
8961 Label Lfast, Lpos, Ldone; |
8937 |
8962 |
8938 __ movl($tmp$$Register, pcon); |
8963 __ movl($tmp$$Register, pcon); |
8939 __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register)); |
8964 __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register)); |
8940 __ jccb(Assembler::above, Lfast); // src is positive and result fits into 32 bit |
8965 __ jccb(Assembler::above, Lfast); // src is positive and result fits into 32 bit |
8941 |
8966 |
8942 __ movl($tmp2$$Register, $dst$$Register); // save |
8967 __ movl($tmp2$$Register, $dst$$Register); // save |
8943 __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); |
8968 __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); |
8944 __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // src sign |
8969 __ movl(HIGH_FROM_LOW($dst$$Register),0); // preserve flags |
8945 __ idivl($tmp$$Register); |
8970 __ jccb(Assembler::lessEqual, Lpos); // result is positive |
|
8971 |
|
8972 // Negative dividend. |
|
8973 // convert value to positive to use unsigned division |
|
8974 __ lneg($dst$$Register, $tmp2$$Register); |
|
8975 __ divl($tmp$$Register); |
8946 __ movl($dst$$Register, $tmp2$$Register); |
8976 __ movl($dst$$Register, $tmp2$$Register); |
|
8977 __ divl($tmp$$Register); |
|
8978 // revert remainder back to negative |
|
8979 __ negl(HIGH_FROM_LOW($dst$$Register)); |
|
8980 __ jmpb(Ldone); |
|
8981 |
|
8982 __ bind(Lpos); |
|
8983 __ divl($tmp$$Register); |
|
8984 __ movl($dst$$Register, $tmp2$$Register); |
8947 |
8985 |
8948 __ bind(Lfast); |
8986 __ bind(Lfast); |
8949 __ idivl($tmp$$Register); |
8987 // fast path: src is positive |
|
8988 __ divl($tmp$$Register); |
|
8989 |
|
8990 __ bind(Ldone); |
8950 __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); |
8991 __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register)); |
8951 __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // result sign |
8992 __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // result sign |
8952 |
8993 |
8953 %} |
8994 %} |
8954 ins_pipe( pipe_slow ); |
8995 ins_pipe( pipe_slow ); |