[arm] b=481761; Finish up ALU op conversions; r=graydon

This commit is contained in:
Vladimir Vukicevic 2009-03-20 15:53:14 -07:00
parent b992e5da9e
commit d0fa8fe9c9
2 changed files with 175 additions and 193 deletions

View File

@ -100,7 +100,7 @@ Assembler::genPrologue()
// Make room on stack for what we are doing
if (amt)
SUBi(SP, amt);
SUBi(SP, SP, amt);
verbose_only( verbose_outputf(" %p:",_nIns); )
verbose_only( verbose_output(" patch entry"); )
@ -475,7 +475,7 @@ Assembler::asm_restore(LInsp i, Reservation *resv, Register r)
FLDD(r, FP, d);
} else {
FLDD(r, IP, 0);
arm_ADDi(IP, FP, d);
ADDi(IP, FP, d);
}
} else {
LDR(r, FP, d);
@ -498,7 +498,7 @@ Assembler::asm_spill(Register rr, int d, bool pop, bool quad)
FSTD(rr, FP, d);
} else {
FSTD(rr, IP, 0);
arm_ADDi(IP, FP, d);
ADDi(IP, FP, d);
}
} else {
STR(rr, FP, d);
@ -529,7 +529,7 @@ Assembler::asm_load64(LInsp ins)
if (rr != UnknownReg) {
if (!isS8(offset >> 2) || (offset&3) != 0) {
FLDD(rr,IP,0);
arm_ADDi(IP, rb, offset);
ADDi(IP, rb, offset);
} else {
FLDD(rr,rb,offset);
}
@ -583,7 +583,7 @@ Assembler::asm_store64(LInsp value, int dr, LInsp base)
FSTD(rv, baseReg, baseOffset);
if (!isS8(dr)) {
arm_ADDi(IP, rb, dr);
ADDi(IP, rb, dr);
}
// if it's a constant, make sure our baseReg/baseOffset location
@ -739,7 +739,7 @@ Assembler::asm_pusharg(LInsp arg)
STR_preindex(argRes->reg, SP, -4);
} else {
FSTD(argRes->reg, SP, 0);
SUBi(SP, 8);
SUBi(SP, SP, 8);
}
} else {
int d = findMemFor(arg);
@ -945,9 +945,8 @@ Assembler::B_cond_chk(ConditionCode _c, NIns* _t, bool _chk)
}
void
Assembler::asm_add_imm(Register rd, Register rn, int32_t imm)
Assembler::asm_add_imm(Register rd, Register rn, int32_t imm, int stat)
{
int rot = 16;
uint32_t immval;
bool pos;
@ -968,25 +967,56 @@ Assembler::asm_add_imm(Register rd, Register rn, int32_t imm)
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_output("add %s,%s,%d",gpn(rd),gpn(rn),imm);
} else {
if (pos) {
ALUi_rot(AL, add, stat, rd, rn, immval, rot);
} else {
ALUi_rot(AL, sub, stat, rd, rn, immval, rot);
}
} else {
// add scratch to rn, after loading the value into scratch.
// make sure someone isn't trying to use IP as an operand
NanoAssert(rn != IP);
*(--_nIns) = (NIns)( COND_AL | OP_STAT | (1<<23) | (rn<<16) | (rd<<12) | (IP));
asm_output("add %s,%s,%s",gpn(rd),gpn(rn),gpn(IP));
ALUr(AL, add, stat, rd, rn, IP);
LD32_nochk(IP, imm);
}
}
void
Assembler::asm_sub_imm(Register rd, Register rn, int32_t imm, int stat)
{
if (imm > -256 && imm < 256) {
if (imm >= 0)
ALUi(AL, sub, stat, rd, rn, imm);
else
ALUi(AL, add, stat, rd, rn, -imm);
} else if (imm >= 0) {
if (imm <= 510) {
/* between 0 and 510, inclusive */
int rem = imm - 255;
NanoAssert(rem < 256);
ALUi(AL, sub, stat, rd, rn, rem & 0xff);
ALUi(AL, sub, stat, rd, rn, 0xff);
} else {
/* more than 510 */
NanoAssert(r != IP);
ALUr(AL, sub, stat, rd, rn, IP);
LD32_nochk(IP, imm);
}
} else {
if (imm >= -510) {
/* between -510 and -1, inclusive */
int rem = -imm - 255;
ALUi(AL, add, stat, rd, rn, rem & 0xff);
ALUi(AL, add, stat, rd, rn, 0xff);
} else {
/* less than -510 */
NanoAssert(r != IP);
ALUr(AL, add, stat, rd, rn, IP);
LD32_nochk(IP, -imm);
}
}
}
/*
* VFP
*/
@ -1205,10 +1235,11 @@ Assembler::asm_cmp(LIns *cond)
Register r = findRegFor(lhs, GpRegs);
TEST(r,r);
// No 64-bit immediates so fall-back to below
}
else if (!rhs->isQuad()) {
} else if (!rhs->isQuad()) {
Register r = getBaseReg(lhs, c, GpRegs);
CMPi(r, c);
asm_cmpi(r, c);
} else {
NanoAssert(0);
}
} else {
findRegFor2(GpRegs, lhs, rA, rhs, rB);
@ -1218,6 +1249,28 @@ Assembler::asm_cmp(LIns *cond)
}
}
void
Assembler::asm_cmpi(Register r, int32_t imm)
{
if (imm < 0) {
if (imm > -256) {
ALUi(AL, cmn, 1, 0, r, -imm);
} else {
underrunProtect(4 + LD32_size);
CMP(r, IP);
LD32_nochk(IP, imm);
}
} else {
if (imm < 256) {
ALUi(AL, cmp, 1, 0, r, imm);
} else {
underrunProtect(4 + LD32_size);
CMP(r, IP);
LD32_nochk(IP, imm);
}
}
}
void
Assembler::asm_loop(LInsp ins, NInsList& loopJumps)
{
@ -1321,55 +1374,53 @@ Assembler::asm_arith(LInsp ins)
if (rA == 0 || (ra = rA->reg) == UnknownReg)
ra = findSpecificRegFor(lhs, rr);
// else, rA already has a register assigned.
NanoAssert(ra != UnknownReg);
if (forceReg) {
if (lhs == rhs)
rb = ra;
if (op == LIR_add || op == LIR_addp)
ADD(rr, rb);
ADDs(rr, ra, rb, 1);
else if (op == LIR_sub)
SUB(rr, rb);
SUB(rr, ra, rb);
else if (op == LIR_mul)
MUL(rr, rb);
else if (op == LIR_and)
AND(rr, rr, rb);
AND(rr, ra, rb);
else if (op == LIR_or)
ORR(rr, rr, rb);
ORR(rr, ra, rb);
else if (op == LIR_xor)
EOR(rr, rr, rb);
EOR(rr, ra, rb);
else if (op == LIR_lsh)
SHL(rr, rb);
SHL(rr, ra, rb);
else if (op == LIR_rsh)
SAR(rr, rb);
SAR(rr, ra, rb);
else if (op == LIR_ush)
SHR(rr, rb);
SHR(rr, ra, rb);
else
NanoAssertMsg(0, "Unsupported");
} else {
int c = rhs->constval();
if (op == LIR_add || op == LIR_addp)
ADDi(rr, c);
ADDi(rr, ra, c);
else if (op == LIR_sub)
SUBi(rr, c);
SUBi(rr, ra, c);
else if (op == LIR_and)
ANDi(rr, rr, c);
ANDi(rr, ra, c);
else if (op == LIR_or)
ORRi(rr, rr, c);
ORRi(rr, ra, c);
else if (op == LIR_xor)
EORi(rr, rr, c);
EORi(rr, ra, c);
else if (op == LIR_lsh)
SHLi(rr, c);
SHLi(rr, ra, c);
else if (op == LIR_rsh)
SARi(rr, c);
SARi(rr, ra, c);
else if (op == LIR_ush)
SHRi(rr, c);
SHRi(rr, ra, c);
else
NanoAssertMsg(0, "Unsupported");
}
if (rr != ra)
MOV(rr,ra);
}
void
@ -1385,14 +1436,12 @@ Assembler::asm_neg_not(LInsp ins)
if (rA == 0 || (ra=rA->reg) == UnknownReg)
ra = findSpecificRegFor(lhs, rr);
// else, rA already has a register assigned.
NanoAssert(ra != UnknownReg);
if (op == LIR_not)
NOT(rr);
MVN(rr, ra);
else
NEG(rr);
if ( rr != ra )
MOV(rr,ra);
RSBS(rr, ra);
}
void

View File

@ -208,7 +208,9 @@ verbose_only( extern const char* shiftNames[]; )
void nativePageReset(); \
void nativePageSetup(); \
void asm_quad_nochk(Register, const int32_t*); \
void asm_add_imm(Register, Register, int32_t); \
void asm_add_imm(Register, Register, int32_t, int stat = 0); \
void asm_sub_imm(Register, Register, int32_t, int stat = 0); \
void asm_cmpi(Register, int32_t imm); \
int* _nSlot; \
int* _nExitSlot;
@ -299,6 +301,26 @@ enum {
asm_output("%s%s%s %s, %s, #0x%X", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rl), (imm));\
} while (0)
// ALU operation with register and rotated 8-bit immediate arguments
// S - bit, 0 or 1, whether the CPSR register is updated
// rd - destination register
// rl - first (left) operand register
// imm - immediate (max 8 bits)
// rot - rotation to apply to imm
#define ALUi_rot(cond, op, S, rd, rl, imm, rot) do {\
underrunProtect(4);\
NanoAssert(isU8(imm));\
*(--_nIns) = (NIns) ((cond)<<28 | OP_IMM | (ARM_##op)<<21 | (S)<<20 | (rl)<<16 | (rd)<<12 | (rot)<<8 | (imm));\
if (ARM_##op == ARM_mov || ARM_##op == ARM_mvn)\
asm_output("%s%s%s %s, #0x%X, %d", #op, condNames[cond], (S)?"s":"", gpn(rd), (imm), (rot)*2);\
else if (ARM_##op >= ARM_tst && ARM_##op <= ARM_cmn) {\
NanoAssert(S==1);\
asm_output("%s%s %s, #0x%X, %d", #op, condNames[cond], gpn(rl), (imm), (rot)*2);\
} else\
asm_output("%s%s%s %s, %s, #0x%X, %d", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rl), (imm), (rot)*2);\
} while (0)
// ALU operation with two register arguments
// S - bit, 0 or 1, whether the CPSR register is updated
// rd - destination register
@ -316,7 +338,7 @@ enum {
asm_output("%s%s%s %s, %s, %s", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rl), gpn(rr));\
} while (0)
// ALU operator with two register arguments, with rr operated on by a shift and shift immediate
// 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
@ -336,12 +358,24 @@ enum {
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
// rd - destination register
// rl - first (left) operand register
// rr - first (left) operand register
// sh - a ShiftOperator
// rs - shift operand register
#define ALUr_shr(cond, op, S, rd, rl, rr, sh, rs) do {\
underrunProtect(4);\
*(--_nIns) = (NIns) ((cond)<<28 |(ARM_##op)<<21 | (S)<<20 | (rl)<<16 | (rd)<<12 | (rs)<<8 | (sh)<<4 | (rr));\
if (ARM_##op == ARM_mov || ARM_##op == ARM_mvn)\
asm_output("%s%s%s %s, %s, %s %s", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rr), shiftNames[sh], gpn(rs));\
else if (ARM_##op >= ARM_tst && ARM_##op <= ARM_cmn) {\
NanoAssert(S==1);\
asm_output("%s%s %s, %s, %s %s", #op, condNames[cond], gpn(rl), gpn(rr), shiftNames[sh], gpn(rs));\
} else\
asm_output("%s%s%s %s, %s, %s, %s %s", #op, condNames[cond], (S)?"s":"", gpn(rd), gpn(rl), gpn(rr), shiftNames[sh], gpn(rs));\
} while (0)
// _d = _l OR _r
#define ORR(_d,_l,_r) ALUr(AL, orr, 0, _d, _l, _r)
@ -361,60 +395,23 @@ enum {
// _d = _l ^ _imm
#define EORi(_d,_l,_imm) ALUi(AL, eor, 0, _d, _l, _imm)
// _d = _n + _m
#define arm_ADD(_d,_n,_m) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | OP_STAT | (1<<23) | ((_n)<<16) | ((_d)<<12) | (_m)); \
asm_output("add %s,%s+%s",gpn(_d),gpn(_n),gpn(_m)); } while(0)
// _d = _l + _r; update flags
#define ADD(_d,_l,_r) ALUr(AL, add, 1, _d, _l, _r)
// _l = _l + _r
#define ADD(_l,_r) arm_ADD(_l,_l,_r)
// _d = _l + _r; update flags if _stat == 1
#define ADDs(_d,_l,_r,_stat) ALUr(AL, add, _stat, _d, _l, _r)
// Note that this sometimes converts negative immediate values to a to a sub.
// _d = _r + _imm
#define arm_ADDi(_d,_n,_imm) asm_add_imm(_d,_n,_imm)
#define ADDi(_r,_imm) arm_ADDi(_r,_r,_imm)
// _d = _l + _imm; update flags
#define ADDi(_d,_l,_imm) asm_add_imm(_d, _l, _imm, 1)
// _l = _l - _r
#define SUB(_l,_r) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (1<<22) | ((_l)<<16) | ((_l)<<12) | (_r)); \
asm_output("sub %s,%s",gpn(_l),gpn(_r)); } while(0)
// _d = _l + _imm; update flags if _stat == 1
#define ADDis(_d,_l,_imm,_stat) asm_add_imm(_d, _l, _imm, _stat)
// _r = _r - _imm
#define SUBi(_r,_imm) do { \
if ((_imm)>-256 && (_imm)<256) { \
underrunProtect(4); \
if ((_imm)>=0) *(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<22) | ((_r)<<16) | ((_r)<<12) | ((_imm)&0xFF) ); \
else *(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<23) | ((_r)<<16) | ((_r)<<12) | ((-(_imm))&0xFF) ); \
} else { \
if ((_imm)>=0) { \
if ((_imm)<=510) { \
underrunProtect(8); \
int rem = (_imm) - 255; \
NanoAssert(rem<256); \
*(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<22) | ((_r)<<16) | ((_r)<<12) | (rem&0xFF) ); \
*(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<22) | ((_r)<<16) | ((_r)<<12) | (0xFF) ); \
} else { \
underrunProtect(4+LD32_size); \
*(--_nIns) = (NIns)( COND_AL | (1<<22) | ((_r)<<16) | ((_r)<<12) | (IP)); \
LD32_nochk(IP, _imm); \
} \
} else { \
if ((_imm)>=-510) { \
underrunProtect(8); \
int rem = -(_imm) - 255; \
*(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<23) | ((_r)<<16) | ((_r)<<12) | ((rem)&0xFF) ); \
*(--_nIns) = (NIns)( COND_AL | OP_IMM | (1<<23) | ((_r)<<16) | ((_r)<<12) | (0xFF) ); \
} else { \
underrunProtect(4+LD32_size); \
*(--_nIns) = (NIns)( COND_AL | (1<<23) | ((_r)<<16) | ((_r)<<12) | (IP)); \
LD32_nochk(IP, -(_imm)); \
} \
} \
} \
asm_output("sub %s,%d",gpn(_r),(_imm)); \
} while (0)
// _d = _l - _r; update flags
#define SUB(_d,_l,_r) ALUr(AL, sub, 1, _d, _l, _r)
// _d = _l - _imm; update flags
#define SUBi(_d,_l,_imm) asm_sub_imm(_d, _l, _imm, 1)
// _l = _l * _r
#define MUL(_l,_r) do { \
@ -422,106 +419,42 @@ enum {
*(--_nIns) = (NIns)( COND_AL | (_l)<<16 | (_l)<<8 | 0x90 | (_r) ); \
asm_output("mul %s,%s",gpn(_l),gpn(_r)); } while(0)
// _d = 0 - _r
#define RSBS(_d,_r) ALUi(AL, rsb, 1, _d, _r, 0)
// RSBS
// _r = -_r
#define NEG(_r) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x27<<20) | ((_r)<<16) | ((_r)<<12) ); \
asm_output("neg %s",gpn(_r)); } while(0)
// _d = ~_r (one's compliment)
#define MVN(_d,_r) ALUr(AL, mvn, 0, _d, 0, _r)
// MVNS
// _r = !_r
#define NOT(_r) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x1F<<20) | ((_r)<<12) | (_r) ); \
asm_output("mvn %s",gpn(_r)); } while(0)
// MOVS _d, _r, LSR <_s>
// _d = _r >> _s
#define SHR(_d,_r,_s) ALUr_shr(AL, mov, 1, _d, 0, _r, LSR_reg, _s)
// MOVS _r, _r, LSR <_s>
// _r = _r >> _s
#define SHR(_r,_s) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x1B<<20) | ((_r)<<12) | ((_s)<<8) | (LSR_reg<<4) | (_r) ); \
asm_output("shr %s,%s",gpn(_r),gpn(_s)); } while(0)
// MOVS _r, _r, LSR #_imm
// _r = _r >> _imm
#define SHRi(_r,_imm) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x1B<<20) | ((_r)<<12) | ((_imm)<<7) | (LSR_imm<<4) | (_r) ); \
asm_output("shr %s,%d",gpn(_r),_imm); } while(0)
// MOVS _r, _r, ASR <_s>
// _r = _r >> _s
#define SAR(_r,_s) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x1B<<20) | ((_r)<<12) | ((_s)<<8) | (ASR_reg<<4) | (_r) ); \
asm_output("asr %s,%s",gpn(_r),gpn(_s)); } while(0)
// MOVS _d, _r, LSR #_imm
// _d = _r >> _imm
#define SHRi(_d,_r,_imm) ALUr_shi(AL, mov, 1, _d, 0, _r, LSR_imm, _imm)
// MOVS _d, _r, ASR <_s>
// _d = _r >> _s
#define SAR(_d,_r,_s) ALUr_shr(AL, mov, 1, _d, 0, _r, ASR_reg, _s)
// MOVS _r, _r, ASR #_imm
// _r = _r >> _imm
#define SARi(_r,_imm) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x1B<<20) | ((_r)<<12) | ((_imm)<<7) | (ASR_imm<<4) | (_r) ); \
asm_output("asr %s,%d",gpn(_r),_imm); } while(0)
// _d = _r >> _imm
#define SARi(_d,_r,_imm) ALUr_shi(AL, mov, 1, _d, 0, _r, ASR_imm, _imm)
// MOVS _r, _r, LSL <_s>
// _r = _r << _s
#define SHL(_r,_s) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x1B<<20) | ((_r)<<12) | ((_s)<<8) | (LSL_reg<<4) | (_r) ); \
asm_output("lsl %s,%s",gpn(_r),gpn(_s)); } while(0)
// MOVS _d, _r, LSL <_s>
// _d = _r << _s
#define SHL(_d, _r, _s) ALUr_shr(AL, mov, 1, _d, 0, _r, LSL_reg, _s)
// MOVS _r, _r, LSL #_imm
// _r = _r << _imm
#define SHLi(_r,_imm) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x1B<<20) | ((_r)<<12) | ((_imm)<<7) | (LSL_imm<<4) | (_r) ); \
asm_output("lsl %s,%d",gpn(_r),(_imm)); } while(0)
// MOVS _d, _r, LSL #_imm
// _d = _r << _imm
#define SHLi(_d, _r, _imm) ALUr_shi(AL, mov, 1, _d, 0, _r, LSL_imm, _imm)
// TST
#define TEST(_d,_s) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x11<<20) | ((_d)<<16) | (_s) ); \
asm_output("test %s,%s",gpn(_d),gpn(_s)); } while(0)
#define TSTi(_d,_imm) do { \
underrunProtect(4); \
NanoAssert(((_imm) & 0xff) == (_imm)); \
*(--_nIns) = (NIns)( COND_AL | OP_IMM | (0x11<<20) | ((_d) << 16) | (0xF<<12) | ((_imm) & 0xff) ); \
asm_output("tst %s,#0x%x", gpn(_d), _imm); \
} while (0);
#define TEST(_l,_r) ALUr(AL, tst, 1, 0, _l, _r)
#define TSTi(_d,_imm) ALUi(AL, tst, 1, 0, _d, _imm)
// CMP
#define CMP(_l,_r) do { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x015<<20) | ((_l)<<16) | (_r) ); \
asm_output("cmp %s,%s",gpn(_l),gpn(_r)); } while(0)
// CMP (or CMN)
#define CMPi(_r,_imm) do { \
if (_imm<0) { \
if ((_imm)>-256) { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x37<<20) | ((_r)<<16) | (-(_imm)) ); \
} else { \
underrunProtect(4+LD32_size); \
*(--_nIns) = (NIns)( COND_AL | (0x17<<20) | ((_r)<<16) | (IP) ); \
LD32_nochk(IP, (_imm)); \
} \
} else { \
if ((_imm)<256) { \
underrunProtect(4); \
*(--_nIns) = (NIns)( COND_AL | (0x035<<20) | ((_r)<<16) | ((_imm)&0xFF) ); \
} else { \
underrunProtect(4+LD32_size); \
*(--_nIns) = (NIns)( COND_AL | (0x015<<20) | ((_r)<<16) | (IP) ); \
LD32_nochk(IP, (_imm)); \
} \
} \
asm_output("cmp %s,0x%x",gpn(_r),(_imm)); \
} while(0)
#define CMP(_l,_r) ALUr(AL, cmp, 1, 0, _l, _r)
// MOV
#define MOV(_d,_s) do { \