[arm] Make ADDi into a function, since it's doing a lot of work
authorVladimir Vukicevic <vladimir@pobox.com>
Fri, 05 Sep 2008 17:14:05 -0700
changeset 19059 0d0354ea085b7d3054a36a877951a51a3cc55886
parent 19058 f821f6cfe0435bb631f6a1b62fe18e213e6a33fc
child 19060 678377cbc8786755ce5e62b414ce8766659f5660
push id1930
push usermrbkap@mozilla.com
push dateWed, 10 Sep 2008 06:40:47 +0000
treeherderautoland@ee61af1469cd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.1b1pre
[arm] Make ADDi into a function, since it's doing a lot of work
js/src/nanojit/NativeARM.cpp
js/src/nanojit/NativeARM.h
--- a/js/src/nanojit/NativeARM.cpp
+++ b/js/src/nanojit/NativeARM.cpp
@@ -875,16 +875,59 @@ Assembler::B_cond_chk(ConditionCode _c, 
         *(--_nIns) = (NIns)(_t);
         *(--_nIns) = (NIns)( COND_AL | (0xA<<24) | ((-4)>>2) & 0xFFFFFF );
         *(--_nIns) = (NIns)( ((_c)<<28) | (0x51<<20) | (PC<<16) | (PC<<12) | 0x0 );
     }
 
     asm_output2("%s %p", _c == AL ? "jmp" : "b(cnd)", (void*)(_t));
 }
 
+void
+Assembler::asm_add_imm(Register rd, Register rn, int32_t imm)
+{
+
+    int rot = 16;
+    uint32_t immval;
+    bool pos;
+
+    if (imm >= 0) {
+        immval = (uint32_t) imm;
+        pos = true;
+    } else {
+        immval = (uint32_t) (-imm);
+        pos = false;
+    }
+
+    while (immval && ((immval & 0x3) == 0)) {
+        immval >>= 2;
+        rot--;
+    }
+
+    rot &= 0xf;
+
+    if (immval < 256) {
+        underrunProtect(4);
+        if (pos)
+            *(--_nIns) = (NIns)( COND_AL | OP_IMM | OP_STAT | (1<<23) | (rn<<16) | (rd<<12) | (rot << 8) | immval );
+        else
+            *(--_nIns) = (NIns)( COND_AL | OP_IMM | OP_STAT | (1<<22) | (rn<<16) | (rd<<12) | (rot << 8) | immval );
+        asm_output3("add %s,%s,%d",gpn(rd),gpn(rn),imm);
+    } else {
+        // add scratch to rn, after loading the value into scratch.
+
+        // make sure someone isn't trying to use Scratch as an operand
+        NanoAssert(rn != Scratch);
+
+        *(--_nIns) = (NIns)( COND_AL | OP_STAT | (1<<23) | (rn<<16) | (rd<<12) | (Scratch));
+        asm_output3("add %s,%s,%s",gpn(rd),gpn(rn),gpn(Scratch));
+
+        LD32_nochk(Scratch, imm);
+    }
+}
+
 /*
  * VFP
  */
 
 #ifdef NJ_ARM_VFP
 
 void
 Assembler::asm_i2f(LInsp ins)
--- a/js/src/nanojit/NativeARM.h
+++ b/js/src/nanojit/NativeARM.h
@@ -195,16 +195,17 @@ verbose_only( extern const char* regName
     void BL_far(NIns*);                                                 \
     void CALL(const CallInfo*);                                         \
     void B_cond_chk(ConditionCode, NIns*, bool);                        \
     void underrunProtect(int bytes);                                    \
     bool has_cmov;                                                      \
     void nativePageReset();                                             \
     void nativePageSetup();                                             \
     void asm_quad_nochk(Register, const int32_t*);                      \
+    void asm_add_imm(Register, Register, int32_t);                      \
     int* _nSlot;                                                        \
     int* _nExitSlot;
 
 
 #define asm_farg(i) NanoAssert(false)
 
 //printf("jmp_l_n count=%d, nins=%X, %X = %X\n", (_c), nins, _nIns, ((intptr_t)(nins+(_c))-(intptr_t)_nIns - 4) );
 
@@ -303,58 +304,19 @@ typedef enum {
 #define arm_ADD(_d,_n,_m) do {                                          \
         underrunProtect(4);                                             \
         *(--_nIns) = (NIns)( COND_AL | OP_STAT | (1<<23) | ((_n)<<16) | ((_d)<<12) | (_m)); \
         asm_output3("add %s,%s+%s",gpn(_d),gpn(_n),gpn(_m)); } while(0)
 
 // _l = _l + _r
 #define ADD(_l,_r)   arm_ADD(_l,_l,_r)
 
-// TODO: we can do better here, since we can rotate the 8-bit immediate left by
-// an even number of bits; should count zeros at the end.
-
 // Note that this sometimes converts negative immediate values to a to a sub.
 // _d = _r + _imm
-#define arm_ADDi(_d,_n,_imm)   do {                                     \
-        if ((_imm) > -256 && (_imm) < 256) {                            \
-            underrunProtect(4);                                         \
-            if ((_imm)>=0)                                              \
-                *(--_nIns) = (NIns)( COND_AL | OP_IMM | OP_STAT | (1<<23) | ((_n)<<16) | ((_d)<<12) | ((_imm)&0xFF) ); \
-            else                                                        \
-                *(--_nIns) = (NIns)( COND_AL | OP_IMM | OP_STAT | (1<<22) | ((_n)<<16) | ((_d)<<12) | ((-(_imm))&0xFF) ); \
-        } else {                                                        \
-            if ((_imm)>=0) {                                            \
-                if ((_imm)<=1020 && (((_imm)&3)==0) ) {                 \
-                    underrunProtect(4);                                 \
-                    *(--_nIns) = (NIns)( COND_AL | OP_IMM | OP_STAT | (1<<23) | ((_n)<<16) | ((_d)<<12) | (15<<8)| ((_imm)>>2) ); \
-                } else {                                                \
-                    underrunProtect(4+LD32_size);                       \
-                    *(--_nIns) = (NIns)( COND_AL | OP_STAT | (1<<23) | ((_n)<<16) | ((_d)<<12) | (Scratch)); \
-                    LD32_nochk(Scratch, _imm);                          \
-                }                                                       \
-            } else {                                                    \
-                underrunProtect(4+LD32_size);                           \
-                *(--_nIns) = (NIns)( COND_AL | OP_STAT | (1<<22) | ((_n)<<16) | ((_d)<<12) | (Scratch)); \
-                LD32_nochk(Scratch, -(_imm));                           \
-            }                                                           \
-        }                                                               \
-        asm_output3("add %s,%s,%d",gpn(_d),gpn(_n),(_imm));             \
-    } while(0)
-
-/*
- * There used to be a :
-                if ((_imm)>=-510) {                                     \
-                    underrunProtect(8);                                 \
-                    int rem = -(_imm) - 255;                            \
-                    *(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<22) | ((_n)<<16) | ((_d)<<12) | ((rem)&0xFF) ); \
-                    *(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<22) | ((_n)<<16) | ((_d)<<12) | (0xFF) ); \
-                } else {                                               
- * above, but if we do that we can't really update the status registers.  So don't do that.
- */
-
+#define arm_ADDi(_d,_n,_imm)   asm_add_imm(_d,_n,_imm)
 #define ADDi(_r,_imm)  arm_ADDi(_r,_r,_imm)
 
 // _l = _l - _r
 #define SUB(_l,_r)  do {                                                \
         underrunProtect(4);                                             \
         *(--_nIns) = (NIns)( COND_AL | (1<<22) | ((_l)<<16) | ((_l)<<12) | (_r)); \
         asm_output2("sub %s,%s",gpn(_l),gpn(_r)); } while(0)