Bug 536153 - NativeARM.cpp: Incorrect use ALUr_shi to generate compare insns. r=Jacob.Bramley.
authorJulian Seward <jseward@acm.org>
Thu, 28 Jan 2010 09:31:38 +1100
changeset 37771 be0d7c213c90148f1fc2ab4f134932001b0cabe3
parent 37770 ec77f24175bf6322cc83e2b54eb9b96153410f12
child 37772 9beb3e961a1f2d7678c8b39719d80dea3d437dc6
push id11426
push userrsayre@mozilla.com
push dateSun, 31 Jan 2010 16:36:36 +0000
treeherderautoland@3048d03980e7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersJacob.Bramley
bugs536153
milestone1.9.3a1pre
Bug 536153 - NativeARM.cpp: Incorrect use ALUr_shi to generate compare insns. r=Jacob.Bramley.
js/src/nanojit/NativeARM.cpp
js/src/nanojit/NativeARM.h
--- a/js/src/nanojit/NativeARM.cpp
+++ b/js/src/nanojit/NativeARM.cpp
@@ -2441,16 +2441,17 @@ Assembler::asm_arith(LInsp ins)
     } else {
         rb = asm_binop_rhs_reg(ins);
         if (!isKnownReg(rb))
             rb = findRegFor(rhs, allow);
         allow &= ~rmask(rb);
     }
     NanoAssert(isKnownReg(rb));
 
+    const Register SBZ = (Register)0;
     switch (op)
     {
         case LIR_iaddp: ADDs(rr, ra, rb, 0);    break;
         case LIR_add:   ADDs(rr, ra, rb, 1);    break;
         case LIR_sub:   SUBs(rr, ra, rb, 1);    break;
         case LIR_and:   ANDs(rr, ra, rb, 0);    break;
         case LIR_or:    ORRs(rr, ra, rb, 0);    break;
         case LIR_xor:   EORs(rr, ra, rb, 0);    break;
@@ -2467,29 +2468,29 @@ Assembler::asm_arith(LInsp ins)
                 // IP is used to temporarily store the high word of the result from
                 // SMULL, so we make use of this to perform an overflow check, as
                 // ARM's MUL instruction can't set the overflow flag by itself.
                 // We can check for overflow using the following:
                 //   SMULL  rr, ip, ra, rb
                 //   CMP    ip, rr, ASR #31
                 // An explanation can be found in bug 521161. This sets Z if we did
                 // _not_ overflow, and clears it if we did.
-                ALUr_shi(AL, cmp, 1, IP, IP, rr, ASR_imm, 31);
+                ALUr_shi(AL, cmp, 1, SBZ, IP, rr, ASR_imm, 31);
                 SMULL(rr, IP, rb, ra);
             } else {
                 // config.arm_arch is ARMv5 (or below) and rr == rb, so we must
                 // find a different way to encode the instruction.
 
                 // If possible, swap the arguments to avoid the restriction.
                 if (rr != ra) {
                     // We know that rr == rb, so this will be something like
                     // rX = rY * rX.
                     // Other than swapping ra and rb, this works in the same as
                     // as the ARMv6+ case, above.
-                    ALUr_shi(AL, cmp, 1, IP, IP, rr, ASR_imm, 31);
+                    ALUr_shi(AL, cmp, 1, SBZ, IP, rr, ASR_imm, 31);
                     SMULL(rr, IP, ra, rb);
                 } else {
                     // We're trying to do rX = rX * rX, but we also need to
                     // check for overflow so we would need two extra registers
                     // on ARMv5 and below. We achieve this by observing the
                     // following:
                     //   - abs(rX)*abs(rX) = rX*rX, so we force the input to be
                     //     positive to simplify the detection logic.
@@ -2506,18 +2507,18 @@ Assembler::asm_arith(LInsp ins)
                     // MOVS     IP, rX      // Put abs(rX) into IP.
                     // RSBMI    IP, IP, #0  // ...
                     // MUL      rX, IP, IP  // Do the actual multiplication.
                     // MOVS     IP, IP, LSR #16 // Check that abs(arg)<=0xffff
                     // CMPEQ    IP, rX, ASR #31 // Check that result[31] == 0
 
                     NanoAssert(rr != IP);
 
-                    ALUr_shi(AL, cmp, 1, IP, rr, rr, ASR_imm, 31);
-                    ALUr_shi(AL, mov, 1, IP, IP, IP, LSR_imm, 16);
+                    ALUr_shi(AL, cmp, 1, SBZ, rr, rr, ASR_imm, 31);
+                    ALUr_shi(AL, mov, 1, IP, SBZ, IP, LSR_imm, 16);
                     MUL(rr, IP, IP);
                     ALUi(MI, rsb, 0, IP, IP, 0);
                     ALUr(AL, mov, 1, IP, ra, ra);
                 }
             }
             break;
 
         // The shift operations need a mask to match the JavaScript
--- a/js/src/nanojit/NativeARM.h
+++ b/js/src/nanojit/NativeARM.h
@@ -344,32 +344,34 @@ enum {
             asm_output("%s%s%s %s, %s, %s", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rl), gpn(rr));\
         }\
     } while (0)
 
 // ALU operation with two register arguments, with rr operated on by a shift and shift immediate
 //  S   - bit, 0 or 1, whether the CPSR register is updated
 //  rd  - destination register
 //  rl  - first (left) operand register
-//  rr  - first (left) operand register
+//  rr  - second (right) operand register
 //  sh  - a ShiftOperator
 //  imm - immediate argument to shift operator, 5 bits (0..31)
 #define ALUr_shi(cond, op, S, rd, rl, rr, sh, imm) do {\
         underrunProtect(4);\
         NanoAssert(IsCond(cond));\
         NanoAssert(IsOp(op));\
         NanoAssert(((S)==0) || ((S)==1));\
         NanoAssert(IsGpReg(rd) && IsGpReg(rl) && IsGpReg(rr));\
         NanoAssert(IsShift(sh));\
         NanoAssert((imm)>=0 && (imm)<32);\
         *(--_nIns) = (NIns) ((cond)<<28 |(ARM_##op)<<21 | (S)<<20 | (rl)<<16 | (rd)<<12 | (imm)<<7 | (sh)<<4 | (rr));\
         if (ARM_##op == ARM_mov || ARM_##op == ARM_mvn) {               \
+            NanoAssert(rl==0);                                          \
             asm_output("%s%s%s %s, %s, %s #%d", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rr), shiftNames[sh], (imm));\
         } else if (ARM_##op >= ARM_tst && ARM_##op <= ARM_cmn) {         \
             NanoAssert(S==1);\
+            NanoAssert(rd==0);\
             asm_output("%s%s  %s, %s, %s #%d", #op, condNames[cond], gpn(rl), gpn(rr), shiftNames[sh], (imm));\
         } else {                                                        \
             asm_output("%s%s%s %s, %s, %s, %s #%d", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rl), gpn(rr), shiftNames[sh], (imm));\
         }\
     } while (0)
 
 // ALU operation with two register arguments, with rr operated on by a shift and shift register
 //  S   - bit, 0 or 1, whether the CPSR register is updated