]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Fix signed division of a negative value by a positive power of two on x86.
authorKlaus Treichel <ktreichel@web.de>
Sat, 29 Mar 2008 18:45:24 +0000 (18:45 +0000)
committerKlaus Treichel <ktreichel@web.de>
Sat, 29 Mar 2008 18:45:24 +0000 (18:45 +0000)
ChangeLog
jit/jit-rules-x86.ins

index 8d49d03095f9b0a5b1f9d5ff2b95e63977e01212..d082236c6b0e1b671842e24268fcaad29abdd04d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2008-03-29  Klaus treichel  <ktreichel@web.de>
+
+       * jit/jit-rules-x86.ins: Fix signed division of negative values by a
+       constant positive power of two.
+
 2008-03-29  Klaus Treichel  <ktreichel@web.de>
 
        * jit/jit-apply.c, tools/gen-apply.c: changes to apply needed for
index 358155a58a303670341430a226aaaa4edc54224a..57fa4a054d24d7ff1ce3ae440b3ae98c5c83bc38 100644 (file)
@@ -584,13 +584,26 @@ JIT_OP_IDIV: more_space
                x86_patch(patch, inst);
                x86_neg_reg(inst, $1);
        }
-       [reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
+       [reg, imm, scratch reg, if("$2 == 2")] -> {
+               x86_mov_reg_reg(inst, $3, $1, 4);
+               x86_shift_reg_imm(inst, X86_SHR, $3, 0x1f);
+               x86_alu_reg_reg(inst, X86_ADD, $1, $3);
+               x86_shift_reg_imm(inst, X86_SAR, $1, 1);
+       }
+       [reg, imm, scratch reg, if("($2 > 0) && (((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
                /* x & (x - 1) is equal to zero if x is a power of 2  */
-               jit_nuint shift, value = $2 >> 1;
+               /* This code is generated by gcc for pentium. */
+               /* We use this code because cmov is not available on all i386 cpus */
+               jit_nuint shift, temp, value = $2 >> 1;
                for(shift = 0; value; value >>= 1)
                {
                    ++shift;
                }
+               temp = 32 - shift;
+               x86_mov_reg_reg(inst, $3, $1, 4);
+               x86_shift_reg_imm(inst, X86_SAR, $3, 0x1f);
+               x86_shift_reg_imm(inst, X86_SHR, $3, temp);
+               x86_alu_reg_reg(inst, X86_ADD, $1, $3);
                x86_shift_reg_imm(inst, X86_SAR, $1, shift);
        }
        [reg("eax"), imm, scratch reg, scratch reg("edx")] -> {