Method prologue and epilogues, add missing x86 functionality.
Enables compiling and running a number of JNI internal managed code
methods on the host.
Change-Id: I56fceb813d0cb24637bc784ba57f2d1d16911d48
diff --git a/src/compiler/codegen/x86/X86/Factory.cc b/src/compiler/codegen/x86/X86/Factory.cc
index 9746707..c28bae9 100644
--- a/src/compiler/codegen/x86/X86/Factory.cc
+++ b/src/compiler/codegen/x86/X86/Factory.cc
@@ -25,13 +25,26 @@
*/
//FIXME: restore "static" when usage uncovered
-/*static*/ int coreRegs[] = {rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI};
+/*static*/ int coreRegs[] = {
+ rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI
+#ifdef TARGET_REX_SUPPORT
+ r8, r9, r10, r11, r12, r13, r14, 15
+#endif
+};
/*static*/ int reservedRegs[] = {rSP};
/*static*/ int coreTemps[] = {rAX, rCX, rDX};
-/*static*/ int fpRegs[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, fr8, fr9,
- fr10, fr11, fr12, fr13, fr14, fr15};
-/*static*/ int fpTemps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, fr8, fr9,
- fr10, fr11, fr12, fr13, fr14, fr15};
+/*static*/ int fpRegs[] = {
+ fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
+#ifdef TARGET_REX_SUPPORT
+ fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15
+#endif
+};
+/*static*/ int fpTemps[] = {
+ fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
+#ifdef TARGET_REX_SUPPORT
+ fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15
+#endif
+};
void genBarrier(CompilationUnit *cUnit);
void storePair(CompilationUnit *cUnit, int base, int lowReg,
@@ -45,36 +58,29 @@
LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
{
- UNIMPLEMENTED(WARNING) << "fpRegCopy";
- return NULL;
-#if 0
int opcode;
/* must be both DOUBLE or both not DOUBLE */
DCHECK_EQ(DOUBLEREG(rDest),DOUBLEREG(rSrc));
if (DOUBLEREG(rDest)) {
- opcode = kX86Fmovd;
+ opcode = kX86MovsdRR;
} else {
if (SINGLEREG(rDest)) {
if (SINGLEREG(rSrc)) {
- opcode = kX86Fmovs;
- } else {
- /* note the operands are swapped for the mtc1 instr */
- int tOpnd = rSrc;
- rSrc = rDest;
- rDest = tOpnd;
- opcode = kX86Mtc1;
+ opcode = kX86MovssRR;
+ } else { // Fpr <- Gpr
+ opcode = kX86MovdxrRR;
}
- } else {
+ } else { // Gpr <- Fpr
DCHECK(SINGLEREG(rSrc));
- opcode = kX86Mfc1;
+ opcode = kX86MovdrxRR;
}
}
+ DCHECK((EncodingMap[opcode].flags & IS_BINARY_OP) != 0);
LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rSrc, rDest);
if (rDest == rSrc) {
res->flags.isNop = true;
}
return res;
-#endif
}
/*
@@ -123,277 +129,186 @@
#endif
}
-LIR *opNone(CompilationUnit *cUnit, OpKind op)
-{
- UNIMPLEMENTED(WARNING) << "opNone";
- return NULL;
-#if 0
- LIR *res;
- X86OpCode opcode = kX86Nop;
- switch (op) {
- case kOpUncondBr:
- opcode = kX86B;
- break;
- default:
- LOG(FATAL) << "Bad case in opNone";
- }
- res = newLIR0(cUnit, opcode);
- return res;
-#endif
+LIR* opBranchUnconditional(CompilationUnit *cUnit, OpKind op) {
+ CHECK_EQ(op, kOpUncondBr);
+ return newLIR1(cUnit, kX86Jmp, 0 /* offset to be patched */ );
}
LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
-LIR* opBranchUnconditional(CompilationUnit* cUnit, OpKind op)
-{
- UNIMPLEMENTED(WARNING) << "opBranchUnconditional";
- return NULL;
-}
-
+X86ConditionCode oatX86ConditionEncoding(ConditionCode cond);
LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
{
- UNIMPLEMENTED(WARNING) << "opCondBranch";
- return NULL;
+ LIR* branch = newLIR2(cUnit, kX86Jcc, 0 /* offset to be patched */,
+ oatX86ConditionEncoding(cc));
+ branch->target = target;
+ return branch;
}
-LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
+LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc) {
+ X86OpCode opcode = kX86Bkpt;
+ switch (op) {
+ case kOpNeg: opcode = kX86Neg32R; break;
+ case kOpBlx: opcode = kX86CallR; break;
+ default:
+ LOG(FATAL) << "Bad case in opReg " << op;
+ }
+ return newLIR1(cUnit, opcode, rDestSrc);
+}
+
+LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int value) {
+ X86OpCode opcode = kX86Bkpt;
+ bool byteImm = IS_SIMM8(value);
+ switch (op) {
+ case kOpLsl: opcode = kX86Sal32RI; break;
+ case kOpLsr: opcode = kX86Shr32RI; break;
+ case kOpAsr: opcode = kX86Sar32RI; break;
+ case kOpAdd: opcode = byteImm ? kX86Add32RI8 : kX86Add32RI; break;
+ case kOpOr: opcode = byteImm ? kX86Or32RI8 : kX86Or32RI; break;
+ case kOpAdc: opcode = byteImm ? kX86Adc32RI8 : kX86Adc32RI; break;
+ //case kOpSbb: opcode = kX86Sbb32RI; break;
+ case kOpAnd: opcode = byteImm ? kX86And32RI8 : kX86And32RI; break;
+ case kOpSub: opcode = byteImm ? kX86Sub32RI8 : kX86Sub32RI; break;
+ case kOpXor: opcode = byteImm ? kX86Xor32RI8 : kX86Xor32RI; break;
+ case kOpCmp: opcode = byteImm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
+ case kOpMov: {
+ if (value == 0) { // turn "mov reg, 0" into "xor reg, reg"
+ opcode = kX86Xor32RR;
+ value = rDestSrc1;
+ } else {
+ opcode = kX86Mov32RI;
+ }
+ break;
+ }
+ case kOpMul:
+ opcode = byteImm ? kX86Imul32RRI8 : kX86Imul32RRI;
+ return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, value);
+ default:
+ LOG(FATAL) << "Bad case in opRegImm " << op;
+ }
+ return newLIR2(cUnit, opcode, rDestSrc1, value);
+}
+
+LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
{
- UNIMPLEMENTED(WARNING) << "opReg";
- return NULL;
-#if 0
X86OpCode opcode = kX86Nop;
switch (op) {
- case kOpBlx:
- opcode = kX86Jalr;
- break;
- case kOpBx:
- return newLIR1(cUnit, kX86Jr, rDestSrc);
- break;
- default:
- LOG(FATAL) << "Bad case in opReg";
- }
- return newLIR2(cUnit, opcode, r_RA, rDestSrc);
-#endif
-}
-
-LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
- int rSrc1, int value);
-LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
- int value)
-{
- UNIMPLEMENTED(WARNING) << "opRegImm";
- return NULL;
-#if 0
- LIR *res;
- bool neg = (value < 0);
- int absValue = (neg) ? -value : value;
- bool shortForm = (absValue & 0xff) == absValue;
- X86OpCode opcode = kX86Nop;
- switch (op) {
- case kOpAdd:
- return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
- break;
- case kOpSub:
- return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
- break;
- default:
- LOG(FATAL) << "Bad case in opRegImm";
- break;
- }
- if (shortForm)
- res = newLIR2(cUnit, opcode, rDestSrc1, absValue);
- else {
- int rScratch = oatAllocTemp(cUnit);
- res = loadConstant(cUnit, rScratch, value);
- if (op == kOpCmp)
- newLIR2(cUnit, opcode, rDestSrc1, rScratch);
- else
- newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rScratch);
- }
- return res;
-#endif
-}
-
-LIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
- int rSrc1, int rSrc2)
-{
- UNIMPLEMENTED(WARNING) << "opRegRegReg";
- return NULL;
-#if 0
- X86OpCode opcode = kX86Nop;
- switch (op) {
- case kOpAdd:
- opcode = kX86Addu;
- break;
- case kOpSub:
- opcode = kX86Subu;
- break;
- case kOpAnd:
- opcode = kX86And;
- break;
- case kOpMul:
- opcode = kX86Mul;
- break;
- case kOpOr:
- opcode = kX86Or;
- break;
- case kOpXor:
- opcode = kX86Xor;
- break;
- case kOpLsl:
- opcode = kX86Sllv;
- break;
- case kOpLsr:
- opcode = kX86Srlv;
- break;
- case kOpAsr:
- opcode = kX86Srav;
- break;
- case kOpAdc:
- case kOpSbc:
- LOG(FATAL) << "No carry bit on MIPS";
- break;
- default:
- LOG(FATAL) << "bad case in opRegRegReg";
- break;
- }
- return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
-#endif
-}
-
-LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
- int rSrc1, int value)
-{
- UNIMPLEMENTED(WARNING) << "opRegRegImm";
- return NULL;
-#if 0
- LIR *res;
- X86OpCode opcode = kX86Nop;
- bool shortForm = true;
-
- switch(op) {
- case kOpAdd:
- if (IS_SIMM16(value)) {
- opcode = kX86Addiu;
- }
- else {
- shortForm = false;
- opcode = kX86Addu;
- }
- break;
- case kOpSub:
- if (IS_SIMM16((-value))) {
- value = -value;
- opcode = kX86Addiu;
- }
- else {
- shortForm = false;
- opcode = kX86Subu;
- }
- break;
- case kOpLsl:
- DCHECK(value >= 0 && value <= 31);
- opcode = kX86Sll;
- break;
- case kOpLsr:
- DCHECK(value >= 0 && value <= 31);
- opcode = kX86Srl;
- break;
- case kOpAsr:
- DCHECK(value >= 0 && value <= 31);
- opcode = kX86Sra;
- break;
- case kOpAnd:
- if (IS_UIMM16((value))) {
- opcode = kX86Andi;
- }
- else {
- shortForm = false;
- opcode = kX86And;
- }
- break;
- case kOpOr:
- if (IS_UIMM16((value))) {
- opcode = kX86Ori;
- }
- else {
- shortForm = false;
- opcode = kX86Or;
- }
- break;
- case kOpXor:
- if (IS_UIMM16((value))) {
- opcode = kX86Xori;
- }
- else {
- shortForm = false;
- opcode = kX86Xor;
- }
- break;
- case kOpMul:
- shortForm = false;
- opcode = kX86Mul;
- break;
- default:
- LOG(FATAL) << "Bad case in opRegRegImm";
- break;
- }
-
- if (shortForm)
- res = newLIR3(cUnit, opcode, rDest, rSrc1, value);
- else {
- if (rDest != rSrc1) {
- res = loadConstant(cUnit, rDest, value);
- newLIR3(cUnit, opcode, rDest, rSrc1, rDest);
- } else {
- int rScratch = oatAllocTemp(cUnit);
- res = loadConstant(cUnit, rScratch, value);
- newLIR3(cUnit, opcode, rDest, rSrc1, rScratch);
- }
- }
- return res;
-#endif
-}
-
-LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
- int rSrc2)
-{
- UNIMPLEMENTED(WARNING) << "opRegReg";
- return NULL;
-#if 0
- X86OpCode opcode = kX86Nop;
- LIR *res;
- switch (op) {
- case kOpMov:
- opcode = kX86Move;
- break;
- case kOpMvn:
- return newLIR3(cUnit, kX86Nor, rDestSrc1, rSrc2, r_ZERO);
- case kOpNeg:
- return newLIR3(cUnit, kX86Subu, rDestSrc1, r_ZERO, rSrc2);
- case kOpAdd:
- case kOpAnd:
- case kOpMul:
- case kOpOr:
- case kOpSub:
- case kOpXor:
- return opRegRegReg(cUnit, op, rDestSrc1, rDestSrc1, rSrc2);
- case kOp2Byte:
- res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 24);
- opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 24);
- return res;
- case kOp2Short:
- res = opRegRegImm(cUnit, kOpLsl, rDestSrc1, rSrc2, 16);
- opRegRegImm(cUnit, kOpAsr, rDestSrc1, rDestSrc1, 16);
- return res;
- case kOp2Char:
- return newLIR3(cUnit, kX86Andi, rDestSrc1, rSrc2, 0xFFFF);
- default:
- LOG(FATAL) << "Bad case in opRegReg";
- break;
+ // X86 unary opcodes
+ case kOpMvn:
+ opRegCopy(cUnit, rDestSrc1, rSrc2);
+ return opReg(cUnit, kOpNot, rDestSrc1);
+ case kOpNeg:
+ opRegCopy(cUnit, rDestSrc1, rSrc2);
+ return opReg(cUnit, kOpNeg, rDestSrc1);
+ // X86 binary opcodes
+ case kOpSub: opcode = kX86Sub32RR; break;
+ case kOpSbc: opcode = kX86Sbb32RR; break;
+ case kOpLsl: opcode = kX86Sal32RC; break;
+ case kOpLsr: opcode = kX86Shr32RC; break;
+ case kOpAsr: opcode = kX86Sar32RC; break;
+ case kOpMov: opcode = kX86Mov32RR; break;
+ case kOpCmp: opcode = kX86Cmp32RR; break;
+ case kOpAdd: opcode = kX86Add32RR; break;
+ case kOpAdc: opcode = kX86Adc32RR; break;
+ case kOpAnd: opcode = kX86And32RR; break;
+ case kOpOr: opcode = kX86Or32RR; break;
+ case kOpXor: opcode = kX86Xor32RR; break;
+ case kOp2Byte: opcode = kX86Movsx8RR; break;
+ case kOp2Short: opcode = kX86Movsx16RR; break;
+ case kOp2Char: opcode = kX86Movzx16RR; break;
+ case kOpMul: opcode = kX86Imul32RR; break;
+ default:
+ LOG(FATAL) << "Bad case in opRegReg " << op;
+ break;
}
return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
-#endif
+}
+
+LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase, int offset) {
+ X86OpCode opcode = kX86Nop;
+ switch (op) {
+ // X86 binary opcodes
+ case kOpSub: opcode = kX86Sub32RM; break;
+ case kOpMov: opcode = kX86Mov32RM; break;
+ case kOpCmp: opcode = kX86Cmp32RM; break;
+ case kOpAdd: opcode = kX86Add32RM; break;
+ case kOpAnd: opcode = kX86And32RM; break;
+ case kOpOr: opcode = kX86Or32RM; break;
+ case kOpXor: opcode = kX86Xor32RM; break;
+ case kOp2Byte: opcode = kX86Movsx8RM; break;
+ case kOp2Short: opcode = kX86Movsx16RM; break;
+ case kOp2Char: opcode = kX86Movzx16RM; break;
+ case kOpMul:
+ default:
+ LOG(FATAL) << "Bad case in opRegReg " << op;
+ break;
+ }
+ return newLIR3(cUnit, opcode, rDest, rBase, offset);
+}
+
+LIR* opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc1, int rSrc2) {
+ if (rDest != rSrc1 && rDest != rSrc2) {
+ if (op == kOpAdd) { // lea special case, except can't encode rbp as base
+ if (rSrc1 == rSrc2) {
+ return opRegImm(cUnit, kOpLsl, rDest, 1);
+ } else if (rSrc1 != rBP) {
+ return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc1 /* base */,
+ rSrc2 /* index */, 0 /* scale */, 0 /* disp */);
+ } else {
+ return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc2 /* base */,
+ rSrc1 /* index */, 0 /* scale */, 0 /* disp */);
+ }
+ } else {
+ opRegCopy(cUnit, rDest, rSrc1);
+ return opRegReg(cUnit, op, rDest, rSrc2);
+ }
+ } else if (rDest == rSrc1) {
+ return opRegReg(cUnit, op, rDest, rSrc2);
+ } else { // rDest == rSrc2
+ switch (op) {
+ case kOpSub: // non-commutative
+ opReg(cUnit, kOpNeg, rDest);
+ op = kOpAdd;
+ break;
+ case kOpSbc:
+ case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
+ int tReg = oatAllocTemp(cUnit);
+ opRegCopy(cUnit, tReg, rSrc1);
+ opRegReg(cUnit, op, tReg, rSrc2);
+ LIR* res = opRegCopy(cUnit, rDest, tReg);
+ oatFreeTemp(cUnit, tReg);
+ return res;
+ }
+ case kOpAdd: // commutative
+ case kOpOr:
+ case kOpAdc:
+ case kOpAnd:
+ case kOpXor:
+ break;
+ default:
+ LOG(FATAL) << "Bad case in opRegRegReg " << op;
+ }
+ return opRegReg(cUnit, op, rDest, rSrc1);
+ }
+}
+
+LIR* opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc, int value) {
+ if (op == kOpMul) {
+ X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
+ return newLIR3(cUnit, opcode, rDest, rSrc, value);
+ }
+ if (op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
+ return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc /* base */,
+ r4sib_no_index /* index */, value /* scale */, value /* disp */);
+ }
+ if (rDest != rSrc) {
+ if (op == kOpAdd) { // lea add special case
+ return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc /* base */,
+ r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
+ }
+ opRegCopy(cUnit, rDest, rSrc);
+ }
+ return opRegImm(cUnit, op, rDest, value);
}
LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
@@ -567,209 +482,175 @@
#endif
}
-LIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
- int displacement, int rDest, int rDestHi,
- OpSize size, int sReg)
-/*
- * Load value from base + displacement. Optionally perform null check
- * on base (which must have an associated sReg and MIR). If not
- * performing null check, incoming MIR can be null. IMPORTANT: this
- * code must not allocate any new temps. If a new register is needed
- * and base and dest are the same, spill some other register to
- * rlp and then restore.
- */
-{
- UNIMPLEMENTED(WARNING) << "loadBaseDispBody";
- return NULL;
-#if 0
- LIR *res;
- LIR *load = NULL;
- LIR *load2 = NULL;
- X86OpCode opcode = kX86Nop;
- bool shortForm = IS_SIMM16(displacement);
- bool pair = false;
-
- switch (size) {
- case kLong:
- case kDouble:
- pair = true;
- opcode = kX86Lw;
- if (FPREG(rDest)) {
- opcode = kX86Flwc1;
- if (DOUBLEREG(rDest)) {
- rDest = rDest - FP_DOUBLE;
- } else {
- DCHECK(FPREG(rDestHi));
- DCHECK(rDest == (rDestHi - 1));
- }
- rDestHi = rDest + 1;
- }
- shortForm = IS_SIMM16_2WORD(displacement);
- DCHECK_EQ((displacement & 0x3), 0);
- break;
- case kWord:
- case kSingle:
- opcode = kX86Lw;
- if (FPREG(rDest)) {
- opcode = kX86Flwc1;
- DCHECK(SINGLEREG(rDest));
- }
- DCHECK_EQ((displacement & 0x3), 0);
- break;
- case kUnsignedHalf:
- opcode = kX86Lhu;
- DCHECK_EQ((displacement & 0x1), 0);
- break;
- case kSignedHalf:
- opcode = kX86Lh;
- DCHECK_EQ((displacement & 0x1), 0);
- break;
- case kUnsignedByte:
- opcode = kX86Lbu;
- break;
- case kSignedByte:
- opcode = kX86Lb;
- break;
- default:
- LOG(FATAL) << "Bad case in loadBaseIndexedBody";
- }
-
- if (shortForm) {
- if (!pair) {
- load = res = newLIR3(cUnit, opcode, rDest, displacement, rBase);
+LIR* loadBaseIndexedDisp(CompilationUnit *cUnit, MIR *mir,
+ int rBase, int rIndex, int scale, int displacement,
+ int rDest, int rDestHi,
+ OpSize size, int sReg) {
+ LIR *load = NULL;
+ LIR *load2 = NULL;
+ bool isArray = rIndex != INVALID_REG;
+ bool pair = false;
+ bool is64bit = false;
+ X86OpCode opcode = kX86Nop;
+ switch (size) {
+ case kLong:
+ case kDouble:
+ is64bit = true;
+ if (FPREG(rDest)) {
+ opcode = isArray ? kX86MovsdRA : kX86MovsdRM;
+ if (DOUBLEREG(rDest)) {
+ rDest = rDest - FP_DOUBLE;
} else {
- load = res = newLIR3(cUnit, opcode, rDest, displacement + LOWORD_OFFSET, rBase);
- load2 = newLIR3(cUnit, opcode, rDestHi, displacement + HIWORD_OFFSET, rBase);
+ DCHECK(FPREG(rDestHi));
+ DCHECK(rDest == (rDestHi - 1));
}
+ rDestHi = rDest + 1;
+ } else {
+ pair = true;
+ opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
+ }
+ // TODO: double store is to unaligned address
+ DCHECK_EQ((displacement & 0x3), 0);
+ break;
+ case kWord:
+ case kSingle:
+ opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
+ if (FPREG(rDest)) {
+ opcode = isArray ? kX86MovssRA : kX86MovssRM;
+ DCHECK(SINGLEREG(rDest));
+ }
+ DCHECK_EQ((displacement & 0x3), 0);
+ break;
+ case kUnsignedHalf:
+ opcode = isArray ? kX86Movzx16RA : kX86Movzx16RM;
+ DCHECK_EQ((displacement & 0x1), 0);
+ break;
+ case kSignedHalf:
+ opcode = isArray ? kX86Movsx16RA : kX86Movsx16RM;
+ DCHECK_EQ((displacement & 0x1), 0);
+ break;
+ case kUnsignedByte:
+ opcode = isArray ? kX86Movzx8RA : kX86Movzx8RM;
+ break;
+ case kSignedByte:
+ opcode = isArray ? kX86Movsx8RA : kX86Movsx8RM;
+ break;
+ default:
+ LOG(FATAL) << "Bad case in loadBaseIndexedDispBody";
+ }
+
+ if (!isArray) {
+ if (!pair) {
+ load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
} else {
- if (pair) {
- int rTmp = oatAllocFreeTemp(cUnit);
- res = opRegRegImm(cUnit, kOpAdd, rTmp, rBase, displacement);
- load = newLIR3(cUnit, opcode, rDest, LOWORD_OFFSET, rTmp);
- load2 = newLIR3(cUnit, opcode, rDestHi, HIWORD_OFFSET, rTmp);
- oatFreeTemp(cUnit, rTmp);
- } else {
- int rTmp = (rBase == rDest) ? oatAllocFreeTemp(cUnit)
- : rDest;
- res = loadConstant(cUnit, rTmp, displacement);
- load = newLIR3(cUnit, opcode, rDest, rBase, rTmp);
- if (rTmp != rDest)
- oatFreeTemp(cUnit, rTmp);
- }
+ load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
+ load2 = newLIR3(cUnit, opcode, rDestHi, rBase, displacement + HIWORD_OFFSET);
}
-
if (rBase == rSP) {
- if (load != NULL)
- annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
- true /* isLoad */);
- if (load2 != NULL)
- annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
- true /* isLoad */);
+ annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
+ true /* isLoad */, is64bit);
+ if (is64bit) {
+ annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
+ true /* isLoad */, is64bit);
+ }
}
- return load;
-#endif
+ } else {
+ if (!pair) {
+ load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale, displacement + LOWORD_OFFSET);
+ } else {
+ load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale, displacement + LOWORD_OFFSET);
+ load2 = newLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale, displacement + HIWORD_OFFSET);
+ }
+ }
+
+ return load;
}
-LIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
- int displacement, int rDest, OpSize size,
- int sReg)
-{
- return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1,
- size, sReg);
+LIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir,
+ int rBase, int displacement,
+ int rDest,
+ OpSize size, int sReg) {
+ return loadBaseIndexedDisp(cUnit, mir, rBase, INVALID_REG, 0, displacement,
+ rDest, INVALID_REG, size, sReg);
}
-LIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
- int displacement, int rDestLo, int rDestHi,
- int sReg)
-{
- return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
- kLong, sReg);
+LIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir,
+ int rBase, int displacement,
+ int rDestLo, int rDestHi,
+ int sReg) {
+ return loadBaseIndexedDisp(cUnit, mir, rBase, INVALID_REG, 0, displacement,
+ rDestLo, rDestHi, kLong, sReg);
}
LIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
- int displacement, int rSrc, int rSrcHi,
- OpSize size)
+ int displacement, int rSrc, int rSrcHi,
+ OpSize size)
{
- UNIMPLEMENTED(WARNING) << "storeBaseDispBody";
- return NULL;
-#if 0
- LIR *res;
- LIR *store = NULL;
- LIR *store2 = NULL;
- X86OpCode opcode = kX86Nop;
- bool shortForm = IS_SIMM16(displacement);
- bool pair = false;
-
- switch (size) {
- case kLong:
- case kDouble:
- pair = true;
- opcode = kX86Sw;
- if (FPREG(rSrc)) {
- opcode = kX86Fswc1;
- if (DOUBLEREG(rSrc)) {
- rSrc = rSrc - FP_DOUBLE;
- } else {
- DCHECK(FPREG(rSrcHi));
- DCHECK_EQ(rSrc, (rSrcHi - 1));
- }
- rSrcHi = rSrc + 1;
- }
- shortForm = IS_SIMM16_2WORD(displacement);
- DCHECK_EQ((displacement & 0x3), 0);
- break;
- case kWord:
- case kSingle:
- opcode = kX86Sw;
- if (FPREG(rSrc)) {
- opcode = kX86Fswc1;
- DCHECK(SINGLEREG(rSrc));
- }
- DCHECK_EQ((displacement & 0x3), 0);
- break;
- case kUnsignedHalf:
- case kSignedHalf:
- opcode = kX86Sh;
- DCHECK_EQ((displacement & 0x1), 0);
- break;
- case kUnsignedByte:
- case kSignedByte:
- opcode = kX86Sb;
- break;
- default:
- LOG(FATAL) << "Bad case in storeBaseIndexedBody";
- }
-
- if (shortForm) {
- if (!pair) {
- store = res = newLIR3(cUnit, opcode, rSrc, displacement, rBase);
+ LIR *res = NULL;
+ LIR *store = NULL;
+ LIR *store2 = NULL;
+ X86OpCode opcode = kX86Bkpt;
+ bool pair = false;
+ bool is64bit = false;
+ switch (size) {
+ case kLong:
+ case kDouble:
+ is64bit = true;
+ if (FPREG(rSrc)) {
+ pair = false;
+ opcode = kX86MovsdMR;
+ if (DOUBLEREG(rSrc)) {
+ rSrc = rSrc - FP_DOUBLE;
} else {
- store = res = newLIR3(cUnit, opcode, rSrc, displacement + LOWORD_OFFSET, rBase);
- store2 = newLIR3(cUnit, opcode, rSrcHi, displacement + HIWORD_OFFSET, rBase);
+ DCHECK(FPREG(rSrcHi));
+ DCHECK_EQ(rSrc, (rSrcHi - 1));
}
- } else {
- int rScratch = oatAllocTemp(cUnit);
- res = opRegRegImm(cUnit, kOpAdd, rScratch, rBase, displacement);
- if (!pair) {
- store = newLIR3(cUnit, opcode, rSrc, 0, rScratch);
- } else {
- store = newLIR3(cUnit, opcode, rSrc, LOWORD_OFFSET, rScratch);
- store2 = newLIR3(cUnit, opcode, rSrcHi, HIWORD_OFFSET, rScratch);
- }
- oatFreeTemp(cUnit, rScratch);
- }
+ rSrcHi = rSrc + 1;
+ } else {
+ pair = true;
+ opcode = kX86Mov32MR;
+ }
+ // TODO: double store is to unaligned address
+ DCHECK_EQ((displacement & 0x3), 0);
+ break;
+ case kWord:
+ case kSingle:
+ opcode = kX86Mov32MR;
+ if (FPREG(rSrc)) {
+ opcode = kX86MovssMR;
+ DCHECK(SINGLEREG(rSrc));
+ }
+ DCHECK_EQ((displacement & 0x3), 0);
+ break;
+ case kUnsignedHalf:
+ case kSignedHalf:
+ opcode = kX86Mov16MR;
+ DCHECK_EQ((displacement & 0x1), 0);
+ break;
+ case kUnsignedByte:
+ case kSignedByte:
+ opcode = kX86Mov8MR;
+ break;
+ default:
+ LOG(FATAL) << "Bad case in storeBaseIndexedBody";
+ }
- if (rBase == rSP) {
- if (store != NULL)
- annotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
- false /* isLoad */);
- if (store2 != NULL)
- annotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
- false /* isLoad */);
- }
+ if (!pair) {
+ store = res = newLIR3(cUnit, opcode, rBase, displacement, rSrc);
+ } else {
+ store = res = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
+ store2 = newLIR3(cUnit, opcode, rBase, displacement + HIWORD_OFFSET, rSrcHi);
+ }
- return res;
-#endif
+ if (rBase == rSP) {
+ annotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2,
+ false /* isLoad */, is64bit);
+ if (pair) {
+ annotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
+ false /* isLoad */, is64bit);
+ }
+ }
+ return res;
}
LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,