diff --git a/js/src/nanojit/NativeARM.cpp b/js/src/nanojit/NativeARM.cpp index a954507168b..c9707624a98 100644 --- a/js/src/nanojit/NativeARM.cpp +++ b/js/src/nanojit/NativeARM.cpp @@ -880,6 +880,49 @@ Assembler::B_cond_chk(ConditionCode _c, NIns* _t, bool _chk) 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 */ diff --git a/js/src/nanojit/NativeARM.h b/js/src/nanojit/NativeARM.h index 20ed5f3fa2f..60996f204eb 100644 --- a/js/src/nanojit/NativeARM.h +++ b/js/src/nanojit/NativeARM.h @@ -200,6 +200,7 @@ verbose_only( extern const char* regNames[]; ) void nativePageReset(); \ void nativePageSetup(); \ void asm_quad_nochk(Register, const int32_t*); \ + void asm_add_imm(Register, Register, int32_t); \ int* _nSlot; \ int* _nExitSlot; @@ -308,48 +309,9 @@ typedef enum { // _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