Mercurial > hg > graal-compiler
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 ); |