comparison src/cpu/x86/vm/x86_32.ad @ 1920:2fe998383789

6997311: SIGFPE in new long division asm code Summary: use unsigned DIV instruction Reviewed-by: never
author kvn
date Sat, 06 Nov 2010 18:52:07 -0700
parents ae065c367d93
children 2f644f85485d
comparison
equal deleted inserted replaced
1919:d0895dfaf7cc 1920:2fe998383789
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 );