[Compiler] use Art indentation standard
First of several CLs to bring code closer to alignment with Art and LLVM
standards. Move to 2-space indenting. Sticking with 80-col line
length (which LLVM apparently also wants). LLVM also prefers camel
case names, so keeping Dalvik convention there as well (for now).
Change-Id: I351ab234e640678d97747377cccdd6df0a770f4a
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index 9326faf..c20151e 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -31,129 +31,121 @@
bool genNegLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
RegLocation rlSrc)
{
- rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- int zReg = oatAllocTemp(cUnit);
- loadConstantNoClobber(cUnit, zReg, 0);
- // Check for destructive overlap
- if (rlResult.lowReg == rlSrc.highReg) {
- int tReg = oatAllocTemp(cUnit);
- opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
- zReg, rlSrc.lowReg);
- opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
- zReg, tReg);
- oatFreeTemp(cUnit, tReg);
- } else {
- opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
- zReg, rlSrc.lowReg);
- opRegRegReg(cUnit, kOpSbc, rlResult.highReg,
- zReg, rlSrc.highReg);
- }
- oatFreeTemp(cUnit, zReg);
- storeValueWide(cUnit, rlDest, rlResult);
- return false;
+ rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ int zReg = oatAllocTemp(cUnit);
+ loadConstantNoClobber(cUnit, zReg, 0);
+ // Check for destructive overlap
+ if (rlResult.lowReg == rlSrc.highReg) {
+ int tReg = oatAllocTemp(cUnit);
+ opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg);
+ opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, tReg);
+ oatFreeTemp(cUnit, tReg);
+ } else {
+ opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg);
+ opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, rlSrc.highReg);
+ }
+ oatFreeTemp(cUnit, zReg);
+ storeValueWide(cUnit, rlDest, rlResult);
+ return false;
}
int loadHelper(CompilationUnit* cUnit, int offset)
{
- loadWordDisp(cUnit, rSELF, offset, rLR);
- return rLR;
+ loadWordDisp(cUnit, rSELF, offset, rLR);
+ return rLR;
}
void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
{
- int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
+ int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
+ /*
+ * On entry, r0, r1, r2 & r3 are live. Let the register allocation
+ * mechanism know so it doesn't try to use any of them when
+ * expanding the frame or flushing. This leaves the utility
+ * code with a single temp: r12. This should be enough.
+ */
+ oatLockTemp(cUnit, r0);
+ oatLockTemp(cUnit, r1);
+ oatLockTemp(cUnit, r2);
+ oatLockTemp(cUnit, r3);
+
+ /*
+ * We can safely skip the stack overflow check if we're
+ * a leaf *and* our frame size < fudge factor.
+ */
+ bool skipOverflowCheck = ((cUnit->attrs & METHOD_IS_LEAF) &&
+ ((size_t)cUnit->frameSize <
+ Thread::kStackOverflowReservedBytes));
+ newLIR0(cUnit, kPseudoMethodEntry);
+ if (!skipOverflowCheck) {
+ /* Load stack limit */
+ loadWordDisp(cUnit, rSELF, Thread::StackEndOffset().Int32Value(), r12);
+ }
+ /* Spill core callee saves */
+ newLIR1(cUnit, kThumb2Push, cUnit->coreSpillMask);
+ /* Need to spill any FP regs? */
+ if (cUnit->numFPSpills) {
/*
- * On entry, r0, r1, r2 & r3 are live. Let the register allocation
- * mechanism know so it doesn't try to use any of them when
- * expanding the frame or flushing. This leaves the utility
- * code with a single temp: r12. This should be enough.
+ * NOTE: fp spills are a little different from core spills in that
+ * they are pushed as a contiguous block. When promoting from
+ * the fp set, we must allocate all singles from s16..highest-promoted
*/
- oatLockTemp(cUnit, r0);
- oatLockTemp(cUnit, r1);
- oatLockTemp(cUnit, r2);
- oatLockTemp(cUnit, r3);
+ newLIR1(cUnit, kThumb2VPushCS, cUnit->numFPSpills);
+ }
+ if (!skipOverflowCheck) {
+ opRegRegImm(cUnit, kOpSub, rLR, rSP, cUnit->frameSize - (spillCount * 4));
+ genRegRegCheck(cUnit, kCondCc, rLR, r12, NULL, kThrowStackOverflow);
+ opRegCopy(cUnit, rSP, rLR); // Establish stack
+ } else {
+ opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4));
+ }
- /*
- * We can safely skip the stack overflow check if we're
- * a leaf *and* our frame size < fudge factor.
- */
- bool skipOverflowCheck = ((cUnit->attrs & METHOD_IS_LEAF) &&
- ((size_t)cUnit->frameSize <
- Thread::kStackOverflowReservedBytes));
- newLIR0(cUnit, kPseudoMethodEntry);
- if (!skipOverflowCheck) {
- /* Load stack limit */
- loadWordDisp(cUnit, rSELF,
- Thread::StackEndOffset().Int32Value(), r12);
- }
- /* Spill core callee saves */
- newLIR1(cUnit, kThumb2Push, cUnit->coreSpillMask);
- /* Need to spill any FP regs? */
- if (cUnit->numFPSpills) {
- /*
- * NOTE: fp spills are a little different from core spills in that
- * they are pushed as a contiguous block. When promoting from
- * the fp set, we must allocate all singles from s16..highest-promoted
- */
- newLIR1(cUnit, kThumb2VPushCS, cUnit->numFPSpills);
- }
- if (!skipOverflowCheck) {
- opRegRegImm(cUnit, kOpSub, rLR, rSP,
- cUnit->frameSize - (spillCount * 4));
- genRegRegCheck(cUnit, kCondCc, rLR, r12, NULL,
- kThrowStackOverflow);
- opRegCopy(cUnit, rSP, rLR); // Establish stack
- } else {
- opRegImm(cUnit, kOpSub, rSP,
- cUnit->frameSize - (spillCount * 4));
- }
+ flushIns(cUnit);
- flushIns(cUnit);
+ if (cUnit->genDebugger) {
+ // Refresh update debugger callout
+ loadWordDisp(cUnit, rSELF,
+ ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode), rSUSPEND);
+ genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY);
+ }
- if (cUnit->genDebugger) {
- // Refresh update debugger callout
- loadWordDisp(cUnit, rSELF,
- ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode), rSUSPEND);
- genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY);
- }
-
- oatFreeTemp(cUnit, r0);
- oatFreeTemp(cUnit, r1);
- oatFreeTemp(cUnit, r2);
- oatFreeTemp(cUnit, r3);
+ oatFreeTemp(cUnit, r0);
+ oatFreeTemp(cUnit, r1);
+ oatFreeTemp(cUnit, r2);
+ oatFreeTemp(cUnit, r3);
}
void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)
{
- int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
- /*
- * In the exit path, r0/r1 are live - make sure they aren't
- * allocated by the register utilities as temps.
- */
- oatLockTemp(cUnit, r0);
- oatLockTemp(cUnit, r1);
+ int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
+ /*
+ * In the exit path, r0/r1 are live - make sure they aren't
+ * allocated by the register utilities as temps.
+ */
+ oatLockTemp(cUnit, r0);
+ oatLockTemp(cUnit, r1);
- newLIR0(cUnit, kPseudoMethodExit);
- /* If we're compiling for the debugger, generate an update callout */
- if (cUnit->genDebugger) {
- genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT);
- }
- opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize - (spillCount * 4));
- /* Need to restore any FP callee saves? */
- if (cUnit->numFPSpills) {
- newLIR1(cUnit, kThumb2VPopCS, cUnit->numFPSpills);
- }
- if (cUnit->coreSpillMask & (1 << rLR)) {
- /* Unspill rLR to rPC */
- cUnit->coreSpillMask &= ~(1 << rLR);
- cUnit->coreSpillMask |= (1 << rPC);
- }
- newLIR1(cUnit, kThumb2Pop, cUnit->coreSpillMask);
- if (!(cUnit->coreSpillMask & (1 << rPC))) {
- /* We didn't pop to rPC, so must do a bv rLR */
- newLIR1(cUnit, kThumbBx, rLR);
- }
+ newLIR0(cUnit, kPseudoMethodExit);
+ /* If we're compiling for the debugger, generate an update callout */
+ if (cUnit->genDebugger) {
+ genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT);
+ }
+ opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize - (spillCount * 4));
+ /* Need to restore any FP callee saves? */
+ if (cUnit->numFPSpills) {
+ newLIR1(cUnit, kThumb2VPopCS, cUnit->numFPSpills);
+ }
+ if (cUnit->coreSpillMask & (1 << rLR)) {
+ /* Unspill rLR to rPC */
+ cUnit->coreSpillMask &= ~(1 << rLR);
+ cUnit->coreSpillMask |= (1 << rPC);
+ }
+ newLIR1(cUnit, kThumb2Pop, cUnit->coreSpillMask);
+ if (!(cUnit->coreSpillMask & (1 << rPC))) {
+ /* We didn't pop to rPC, so must do a bv rLR */
+ newLIR1(cUnit, kThumbBx, rLR);
+ }
}
/*
@@ -163,55 +155,55 @@
*/
void removeRedundantBranches(CompilationUnit* cUnit)
{
- LIR* thisLIR;
+ LIR* thisLIR;
- for (thisLIR = (LIR*) cUnit->firstLIRInsn;
- thisLIR != (LIR*) cUnit->lastLIRInsn;
- thisLIR = NEXT_LIR(thisLIR)) {
+ for (thisLIR = (LIR*) cUnit->firstLIRInsn;
+ thisLIR != (LIR*) cUnit->lastLIRInsn;
+ thisLIR = NEXT_LIR(thisLIR)) {
- /* Branch to the next instruction */
- if ((thisLIR->opcode == kThumbBUncond) ||
- (thisLIR->opcode == kThumb2BUncond)) {
- LIR* nextLIR = thisLIR;
+ /* Branch to the next instruction */
+ if ((thisLIR->opcode == kThumbBUncond) ||
+ (thisLIR->opcode == kThumb2BUncond)) {
+ LIR* nextLIR = thisLIR;
- while (true) {
- nextLIR = NEXT_LIR(nextLIR);
+ while (true) {
+ nextLIR = NEXT_LIR(nextLIR);
- /*
- * Is the branch target the next instruction?
- */
- if (nextLIR == (LIR*) thisLIR->target) {
- thisLIR->flags.isNop = true;
- break;
- }
-
- /*
- * Found real useful stuff between the branch and the target.
- * Need to explicitly check the lastLIRInsn here because it
- * might be the last real instruction.
- */
- if (!isPseudoOpcode(nextLIR->opcode) ||
- (nextLIR = (LIR*) cUnit->lastLIRInsn))
- break;
- }
+ /*
+ * Is the branch target the next instruction?
+ */
+ if (nextLIR == (LIR*) thisLIR->target) {
+ thisLIR->flags.isNop = true;
+ break;
}
+
+ /*
+ * Found real useful stuff between the branch and the target.
+ * Need to explicitly check the lastLIRInsn here because it
+ * might be the last real instruction.
+ */
+ if (!isPseudoOpcode(nextLIR->opcode) ||
+ (nextLIR = (LIR*) cUnit->lastLIRInsn))
+ break;
+ }
}
+ }
}
/* Common initialization routine for an architecture family */
bool oatArchInit()
{
- int i;
+ int i;
- for (i = 0; i < kArmLast; i++) {
- if (EncodingMap[i].opcode != i) {
- LOG(FATAL) << "Encoding order for " << EncodingMap[i].name <<
- " is wrong: expecting " << i << ", seeing " <<
- (int)EncodingMap[i].opcode;
- }
+ for (i = 0; i < kArmLast; i++) {
+ if (EncodingMap[i].opcode != i) {
+ LOG(FATAL) << "Encoding order for " << EncodingMap[i].name
+ << " is wrong: expecting " << i << ", seeing "
+ << (int)EncodingMap[i].opcode;
}
+ }
- return oatArchVariantInit();
+ return oatArchVariantInit();
}
} // namespace art
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index 4346bda..725200a 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -24,109 +24,109 @@
ArmConditionCode oatArmConditionEncoding(ConditionCode code)
{
- ArmConditionCode res;
- switch (code) {
- case kCondEq: res = kArmCondEq; break;
- case kCondNe: res = kArmCondNe; break;
- case kCondCs: res = kArmCondCs; break;
- case kCondCc: res = kArmCondCc; break;
- case kCondMi: res = kArmCondMi; break;
- case kCondPl: res = kArmCondPl; break;
- case kCondVs: res = kArmCondVs; break;
- case kCondVc: res = kArmCondVc; break;
- case kCondHi: res = kArmCondHi; break;
- case kCondLs: res = kArmCondLs; break;
- case kCondGe: res = kArmCondGe; break;
- case kCondLt: res = kArmCondLt; break;
- case kCondGt: res = kArmCondGt; break;
- case kCondLe: res = kArmCondLe; break;
- case kCondAl: res = kArmCondAl; break;
- case kCondNv: res = kArmCondNv; break;
- default:
- LOG(FATAL) << "Bad condition code" << (int)code;
- res = (ArmConditionCode)0; // Quiet gcc
- }
- return res;
+ ArmConditionCode res;
+ switch (code) {
+ case kCondEq: res = kArmCondEq; break;
+ case kCondNe: res = kArmCondNe; break;
+ case kCondCs: res = kArmCondCs; break;
+ case kCondCc: res = kArmCondCc; break;
+ case kCondMi: res = kArmCondMi; break;
+ case kCondPl: res = kArmCondPl; break;
+ case kCondVs: res = kArmCondVs; break;
+ case kCondVc: res = kArmCondVc; break;
+ case kCondHi: res = kArmCondHi; break;
+ case kCondLs: res = kArmCondLs; break;
+ case kCondGe: res = kArmCondGe; break;
+ case kCondLt: res = kArmCondLt; break;
+ case kCondGt: res = kArmCondGt; break;
+ case kCondLe: res = kArmCondLe; break;
+ case kCondAl: res = kArmCondAl; break;
+ case kCondNv: res = kArmCondNv; break;
+ default:
+ LOG(FATAL) << "Bad condition code" << (int)code;
+ res = (ArmConditionCode)0; // Quiet gcc
+ }
+ return res;
}
static const char* coreRegNames[16] = {
- "r0",
- "r1",
- "r2",
- "r3",
- "r4",
- "r5",
- "r6",
- "r7",
- "r8",
- "rSELF",
- "r10",
- "r11",
- "r12",
- "sp",
- "lr",
- "pc",
+ "r0",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ "r6",
+ "r7",
+ "r8",
+ "rSELF",
+ "r10",
+ "r11",
+ "r12",
+ "sp",
+ "lr",
+ "pc",
};
static const char* shiftNames[4] = {
- "lsl",
- "lsr",
- "asr",
- "ror"};
+ "lsl",
+ "lsr",
+ "asr",
+ "ror"};
/* Decode and print a ARM register name */
char* decodeRegList(int opcode, int vector, char* buf)
{
- int i;
- bool printed = false;
- buf[0] = 0;
- for (i = 0; i < 16; i++, vector >>= 1) {
- if (vector & 0x1) {
- int regId = i;
- if (opcode == kThumbPush && i == 8) {
- regId = r14lr;
- } else if (opcode == kThumbPop && i == 8) {
- regId = r15pc;
- }
- if (printed) {
- sprintf(buf + strlen(buf), ", r%d", regId);
- } else {
- printed = true;
- sprintf(buf, "r%d", regId);
- }
- }
+ int i;
+ bool printed = false;
+ buf[0] = 0;
+ for (i = 0; i < 16; i++, vector >>= 1) {
+ if (vector & 0x1) {
+ int regId = i;
+ if (opcode == kThumbPush && i == 8) {
+ regId = r14lr;
+ } else if (opcode == kThumbPop && i == 8) {
+ regId = r15pc;
+ }
+ if (printed) {
+ sprintf(buf + strlen(buf), ", r%d", regId);
+ } else {
+ printed = true;
+ sprintf(buf, "r%d", regId);
+ }
}
- return buf;
+ }
+ return buf;
}
char* decodeFPCSRegList(int count, int base, char* buf)
{
- sprintf(buf, "s%d", base);
- for (int i = 1; i < count; i++) {
- sprintf(buf + strlen(buf), ", s%d",base + i);
- }
- return buf;
+ sprintf(buf, "s%d", base);
+ for (int i = 1; i < count; i++) {
+ sprintf(buf + strlen(buf), ", s%d",base + i);
+ }
+ return buf;
}
int expandImmediate(int value)
{
- int mode = (value & 0xf00) >> 8;
- u4 bits = value & 0xff;
- switch (mode) {
- case 0:
- return bits;
- case 1:
- return (bits << 16) | bits;
- case 2:
- return (bits << 24) | (bits << 8);
- case 3:
- return (bits << 24) | (bits << 16) | (bits << 8) | bits;
- default:
- break;
- }
- bits = (bits | 0x80) << 24;
- return bits >> (((value & 0xf80) >> 7) - 8);
+ int mode = (value & 0xf00) >> 8;
+ u4 bits = value & 0xff;
+ switch (mode) {
+ case 0:
+ return bits;
+ case 1:
+ return (bits << 16) | bits;
+ case 2:
+ return (bits << 24) | (bits << 8);
+ case 3:
+ return (bits << 24) | (bits << 16) | (bits << 8) | bits;
+ default:
+ break;
+ }
+ bits = (bits | 0x80) << 24;
+ return bits >> (((value & 0xf80) >> 7) - 8);
}
const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
@@ -135,190 +135,188 @@
* Interpret a format string and build a string no longer than size
* See format key in Assemble.c.
*/
-std::string buildInsnString(const char* fmt, LIR* lir,
- unsigned char* baseAddr)
+std::string buildInsnString(const char* fmt, LIR* lir, unsigned char* baseAddr)
{
- std::string buf;
- int i;
- const char* fmtEnd = &fmt[strlen(fmt)];
- char tbuf[256];
- const char* name;
- char nc;
- while (fmt < fmtEnd) {
- int operand;
- if (*fmt == '!') {
- fmt++;
- DCHECK_LT(fmt, fmtEnd);
- nc = *fmt++;
- if (nc=='!') {
- strcpy(tbuf, "!");
- } else {
- DCHECK_LT(fmt, fmtEnd);
- DCHECK_LT((unsigned)(nc-'0'), 4U);
- operand = lir->operands[nc-'0'];
- switch (*fmt++) {
- case 'H':
- if (operand != 0) {
- sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
- operand >> 2);
- } else {
- strcpy(tbuf,"");
- }
- break;
- case 'B':
- switch (operand) {
- case kSY:
- name = "sy";
- break;
- case kST:
- name = "st";
- break;
- case kISH:
- name = "ish";
- break;
- case kISHST:
- name = "ishst";
- break;
- case kNSH:
- name = "nsh";
- break;
- case kNSHST:
- name = "shst";
- break;
- default:
- name = "DecodeError2";
- break;
- }
- strcpy(tbuf, name);
- break;
- case 'b':
- strcpy(tbuf,"0000");
- for (i=3; i>= 0; i--) {
- tbuf[i] += operand & 1;
- operand >>= 1;
- }
- break;
- case 'n':
- operand = ~expandImmediate(operand);
- sprintf(tbuf,"%d [%#x]", operand, operand);
- break;
- case 'm':
- operand = expandImmediate(operand);
- sprintf(tbuf,"%d [%#x]", operand, operand);
- break;
- case 's':
- sprintf(tbuf,"s%d",operand & FP_REG_MASK);
- break;
- case 'S':
- sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
- break;
- case 'h':
- sprintf(tbuf,"%04x", operand);
- break;
- case 'M':
- case 'd':
- sprintf(tbuf,"%d", operand);
- break;
- case 'C':
- sprintf(tbuf,"%s",coreRegNames[operand]);
- break;
- case 'E':
- sprintf(tbuf,"%d", operand*4);
- break;
- case 'F':
- sprintf(tbuf,"%d", operand*2);
- break;
- case 'c':
- strcpy(tbuf, ccNames[operand]);
- break;
- case 't':
- sprintf(tbuf,"0x%08x (L%p)",
- (int) baseAddr + lir->offset + 4 +
- (operand << 1),
- lir->target);
- break;
- case 'u': {
- int offset_1 = lir->operands[0];
- int offset_2 = NEXT_LIR(lir)->operands[0];
- intptr_t target =
- ((((intptr_t) baseAddr + lir->offset + 4) &
- ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
- 0xfffffffc;
- sprintf(tbuf, "%p", (void *) target);
- break;
- }
+ std::string buf;
+ int i;
+ const char* fmtEnd = &fmt[strlen(fmt)];
+ char tbuf[256];
+ const char* name;
+ char nc;
+ while (fmt < fmtEnd) {
+ int operand;
+ if (*fmt == '!') {
+ fmt++;
+ DCHECK_LT(fmt, fmtEnd);
+ nc = *fmt++;
+ if (nc=='!') {
+ strcpy(tbuf, "!");
+ } else {
+ DCHECK_LT(fmt, fmtEnd);
+ DCHECK_LT((unsigned)(nc-'0'), 4U);
+ operand = lir->operands[nc-'0'];
+ switch (*fmt++) {
+ case 'H':
+ if (operand != 0) {
+ sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3], operand >> 2);
+ } else {
+ strcpy(tbuf,"");
+ }
+ break;
+ case 'B':
+ switch (operand) {
+ case kSY:
+ name = "sy";
+ break;
+ case kST:
+ name = "st";
+ break;
+ case kISH:
+ name = "ish";
+ break;
+ case kISHST:
+ name = "ishst";
+ break;
+ case kNSH:
+ name = "nsh";
+ break;
+ case kNSHST:
+ name = "shst";
+ break;
+ default:
+ name = "DecodeError2";
+ break;
+ }
+ strcpy(tbuf, name);
+ break;
+ case 'b':
+ strcpy(tbuf,"0000");
+ for (i=3; i>= 0; i--) {
+ tbuf[i] += operand & 1;
+ operand >>= 1;
+ }
+ break;
+ case 'n':
+ operand = ~expandImmediate(operand);
+ sprintf(tbuf,"%d [%#x]", operand, operand);
+ break;
+ case 'm':
+ operand = expandImmediate(operand);
+ sprintf(tbuf,"%d [%#x]", operand, operand);
+ break;
+ case 's':
+ sprintf(tbuf,"s%d",operand & FP_REG_MASK);
+ break;
+ case 'S':
+ sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
+ break;
+ case 'h':
+ sprintf(tbuf,"%04x", operand);
+ break;
+ case 'M':
+ case 'd':
+ sprintf(tbuf,"%d", operand);
+ break;
+ case 'C':
+ sprintf(tbuf,"%s",coreRegNames[operand]);
+ break;
+ case 'E':
+ sprintf(tbuf,"%d", operand*4);
+ break;
+ case 'F':
+ sprintf(tbuf,"%d", operand*2);
+ break;
+ case 'c':
+ strcpy(tbuf, ccNames[operand]);
+ break;
+ case 't':
+ sprintf(tbuf,"0x%08x (L%p)",
+ (int) baseAddr + lir->offset + 4 +
+ (operand << 1),
+ lir->target);
+ break;
+ case 'u': {
+ int offset_1 = lir->operands[0];
+ int offset_2 = NEXT_LIR(lir)->operands[0];
+ intptr_t target =
+ ((((intptr_t) baseAddr + lir->offset + 4) &
+ ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
+ 0xfffffffc;
+ sprintf(tbuf, "%p", (void *) target);
+ break;
+ }
- /* Nothing to print for BLX_2 */
- case 'v':
- strcpy(tbuf, "see above");
- break;
- case 'R':
- decodeRegList(lir->opcode, operand, tbuf);
- break;
- case 'P':
- decodeFPCSRegList(operand, 16, tbuf);
- break;
- case 'Q':
- decodeFPCSRegList(operand, 0, tbuf);
- break;
- default:
- strcpy(tbuf,"DecodeError1");
- break;
- }
- buf += tbuf;
- }
- } else {
- buf += *fmt++;
+ /* Nothing to print for BLX_2 */
+ case 'v':
+ strcpy(tbuf, "see above");
+ break;
+ case 'R':
+ decodeRegList(lir->opcode, operand, tbuf);
+ break;
+ case 'P':
+ decodeFPCSRegList(operand, 16, tbuf);
+ break;
+ case 'Q':
+ decodeFPCSRegList(operand, 0, tbuf);
+ break;
+ default:
+ strcpy(tbuf,"DecodeError1");
+ break;
}
+ buf += tbuf;
+ }
+ } else {
+ buf += *fmt++;
}
- return buf;
+ }
+ return buf;
}
void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
{
- char buf[256];
- buf[0] = 0;
- LIR* armLIR = (LIR*) lir;
+ char buf[256];
+ buf[0] = 0;
+ LIR* armLIR = (LIR*) lir;
- if (mask == ENCODE_ALL) {
- strcpy(buf, "all");
- } else {
- char num[8];
- int i;
+ if (mask == ENCODE_ALL) {
+ strcpy(buf, "all");
+ } else {
+ char num[8];
+ int i;
- for (i = 0; i < kRegEnd; i++) {
- if (mask & (1ULL << i)) {
- sprintf(num, "%d ", i);
- strcat(buf, num);
- }
- }
-
- if (mask & ENCODE_CCODE) {
- strcat(buf, "cc ");
- }
- if (mask & ENCODE_FP_STATUS) {
- strcat(buf, "fpcc ");
- }
-
- /* Memory bits */
- if (armLIR && (mask & ENCODE_DALVIK_REG)) {
- sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
- (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
- }
- if (mask & ENCODE_LITERAL) {
- strcat(buf, "lit ");
- }
-
- if (mask & ENCODE_HEAP_REF) {
- strcat(buf, "heap ");
- }
- if (mask & ENCODE_MUST_NOT_ALIAS) {
- strcat(buf, "noalias ");
- }
+ for (i = 0; i < kRegEnd; i++) {
+ if (mask & (1ULL << i)) {
+ sprintf(num, "%d ", i);
+ strcat(buf, num);
+ }
}
- if (buf[0]) {
- LOG(INFO) << prefix << ": " << buf;
+
+ if (mask & ENCODE_CCODE) {
+ strcat(buf, "cc ");
}
+ if (mask & ENCODE_FP_STATUS) {
+ strcat(buf, "fpcc ");
+ }
+
+ /* Memory bits */
+ if (armLIR && (mask & ENCODE_DALVIK_REG)) {
+ sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
+ (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
+ }
+ if (mask & ENCODE_LITERAL) {
+ strcat(buf, "lit ");
+ }
+
+ if (mask & ENCODE_HEAP_REF) {
+ strcat(buf, "heap ");
+ }
+ if (mask & ENCODE_MUST_NOT_ALIAS) {
+ strcat(buf, "noalias ");
+ }
+ }
+ if (buf[0]) {
+ LOG(INFO) << prefix << ": " << buf;
+ }
}
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 484892a..fc5aa40 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -132,20 +132,20 @@
#define LOC_C_RETURN_WIDE_DOUBLE LOC_C_RETURN_WIDE
enum ResourceEncodingPos {
- kGPReg0 = 0,
- kRegSP = 13,
- kRegLR = 14,
- kRegPC = 15,
- kFPReg0 = 16,
- kFPReg16 = 32,
- kRegEnd = 48,
- kCCode = kRegEnd,
- kFPStatus, // FP status word
- // The following four bits are for memory disambiguation
- kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
- kLiteral, // 2 Literal pool (can be fully disambiguated)
- kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
- kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
+ kGPReg0 = 0,
+ kRegSP = 13,
+ kRegLR = 14,
+ kRegPC = 15,
+ kFPReg0 = 16,
+ kFPReg16 = 32,
+ kRegEnd = 48,
+ kCCode = kRegEnd,
+ kFPStatus, // FP status word
+ // The following four bits are for memory disambiguation
+ kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
+ kLiteral, // 2 Literal pool (can be fully disambiguated)
+ kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
+ kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
};
#define ENCODE_REG_LIST(N) ((u8) N)
@@ -164,7 +164,7 @@
#define ENCODE_ALL (~0ULL)
#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
- ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
+ ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
@@ -176,73 +176,73 @@
* rPC, rFP, and rSELF are for architecture-independent code to use.
*/
enum NativeRegisterPool {
- r0 = 0,
- r1 = 1,
- r2 = 2,
- r3 = 3,
- rSUSPEND = 4,
- r5 = 5,
- r6 = 6,
- r7 = 7,
- r8 = 8,
- rSELF = 9,
- r10 = 10,
- r11 = 11,
- r12 = 12,
- r13sp = 13,
- rSP = 13,
- r14lr = 14,
- rLR = 14,
- r15pc = 15,
- rPC = 15,
- fr0 = 0 + FP_REG_OFFSET,
- fr1 = 1 + FP_REG_OFFSET,
- fr2 = 2 + FP_REG_OFFSET,
- fr3 = 3 + FP_REG_OFFSET,
- fr4 = 4 + FP_REG_OFFSET,
- fr5 = 5 + FP_REG_OFFSET,
- fr6 = 6 + FP_REG_OFFSET,
- fr7 = 7 + FP_REG_OFFSET,
- fr8 = 8 + FP_REG_OFFSET,
- fr9 = 9 + FP_REG_OFFSET,
- fr10 = 10 + FP_REG_OFFSET,
- fr11 = 11 + FP_REG_OFFSET,
- fr12 = 12 + FP_REG_OFFSET,
- fr13 = 13 + FP_REG_OFFSET,
- fr14 = 14 + FP_REG_OFFSET,
- fr15 = 15 + FP_REG_OFFSET,
- fr16 = 16 + FP_REG_OFFSET,
- fr17 = 17 + FP_REG_OFFSET,
- fr18 = 18 + FP_REG_OFFSET,
- fr19 = 19 + FP_REG_OFFSET,
- fr20 = 20 + FP_REG_OFFSET,
- fr21 = 21 + FP_REG_OFFSET,
- fr22 = 22 + FP_REG_OFFSET,
- fr23 = 23 + FP_REG_OFFSET,
- fr24 = 24 + FP_REG_OFFSET,
- fr25 = 25 + FP_REG_OFFSET,
- fr26 = 26 + FP_REG_OFFSET,
- fr27 = 27 + FP_REG_OFFSET,
- fr28 = 28 + FP_REG_OFFSET,
- fr29 = 29 + FP_REG_OFFSET,
- fr30 = 30 + FP_REG_OFFSET,
- fr31 = 31 + FP_REG_OFFSET,
- dr0 = fr0 + FP_DOUBLE,
- dr1 = fr2 + FP_DOUBLE,
- dr2 = fr4 + FP_DOUBLE,
- dr3 = fr6 + FP_DOUBLE,
- dr4 = fr8 + FP_DOUBLE,
- dr5 = fr10 + FP_DOUBLE,
- dr6 = fr12 + FP_DOUBLE,
- dr7 = fr14 + FP_DOUBLE,
- dr8 = fr16 + FP_DOUBLE,
- dr9 = fr18 + FP_DOUBLE,
- dr10 = fr20 + FP_DOUBLE,
- dr11 = fr22 + FP_DOUBLE,
- dr12 = fr24 + FP_DOUBLE,
- dr13 = fr26 + FP_DOUBLE,
- dr14 = fr28 + FP_DOUBLE,
- dr15 = fr30 + FP_DOUBLE,
+ r0 = 0,
+ r1 = 1,
+ r2 = 2,
+ r3 = 3,
+ rSUSPEND = 4,
+ r5 = 5,
+ r6 = 6,
+ r7 = 7,
+ r8 = 8,
+ rSELF = 9,
+ r10 = 10,
+ r11 = 11,
+ r12 = 12,
+ r13sp = 13,
+ rSP = 13,
+ r14lr = 14,
+ rLR = 14,
+ r15pc = 15,
+ rPC = 15,
+ fr0 = 0 + FP_REG_OFFSET,
+ fr1 = 1 + FP_REG_OFFSET,
+ fr2 = 2 + FP_REG_OFFSET,
+ fr3 = 3 + FP_REG_OFFSET,
+ fr4 = 4 + FP_REG_OFFSET,
+ fr5 = 5 + FP_REG_OFFSET,
+ fr6 = 6 + FP_REG_OFFSET,
+ fr7 = 7 + FP_REG_OFFSET,
+ fr8 = 8 + FP_REG_OFFSET,
+ fr9 = 9 + FP_REG_OFFSET,
+ fr10 = 10 + FP_REG_OFFSET,
+ fr11 = 11 + FP_REG_OFFSET,
+ fr12 = 12 + FP_REG_OFFSET,
+ fr13 = 13 + FP_REG_OFFSET,
+ fr14 = 14 + FP_REG_OFFSET,
+ fr15 = 15 + FP_REG_OFFSET,
+ fr16 = 16 + FP_REG_OFFSET,
+ fr17 = 17 + FP_REG_OFFSET,
+ fr18 = 18 + FP_REG_OFFSET,
+ fr19 = 19 + FP_REG_OFFSET,
+ fr20 = 20 + FP_REG_OFFSET,
+ fr21 = 21 + FP_REG_OFFSET,
+ fr22 = 22 + FP_REG_OFFSET,
+ fr23 = 23 + FP_REG_OFFSET,
+ fr24 = 24 + FP_REG_OFFSET,
+ fr25 = 25 + FP_REG_OFFSET,
+ fr26 = 26 + FP_REG_OFFSET,
+ fr27 = 27 + FP_REG_OFFSET,
+ fr28 = 28 + FP_REG_OFFSET,
+ fr29 = 29 + FP_REG_OFFSET,
+ fr30 = 30 + FP_REG_OFFSET,
+ fr31 = 31 + FP_REG_OFFSET,
+ dr0 = fr0 + FP_DOUBLE,
+ dr1 = fr2 + FP_DOUBLE,
+ dr2 = fr4 + FP_DOUBLE,
+ dr3 = fr6 + FP_DOUBLE,
+ dr4 = fr8 + FP_DOUBLE,
+ dr5 = fr10 + FP_DOUBLE,
+ dr6 = fr12 + FP_DOUBLE,
+ dr7 = fr14 + FP_DOUBLE,
+ dr8 = fr16 + FP_DOUBLE,
+ dr9 = fr18 + FP_DOUBLE,
+ dr10 = fr20 + FP_DOUBLE,
+ dr11 = fr22 + FP_DOUBLE,
+ dr12 = fr24 + FP_DOUBLE,
+ dr13 = fr26 + FP_DOUBLE,
+ dr14 = fr28 + FP_DOUBLE,
+ dr15 = fr30 + FP_DOUBLE,
};
/* Target-independent aliases */
@@ -256,30 +256,30 @@
/* Shift encodings */
enum ArmShiftEncodings {
- kArmLsl = 0x0,
- kArmLsr = 0x1,
- kArmAsr = 0x2,
- kArmRor = 0x3
+ kArmLsl = 0x0,
+ kArmLsr = 0x1,
+ kArmAsr = 0x2,
+ kArmRor = 0x3
};
/* Thumb condition encodings */
enum ArmConditionCode {
- kArmCondEq = 0x0, /* 0000 */
- kArmCondNe = 0x1, /* 0001 */
- kArmCondCs = 0x2, /* 0010 */
- kArmCondCc = 0x3, /* 0011 */
- kArmCondMi = 0x4, /* 0100 */
- kArmCondPl = 0x5, /* 0101 */
- kArmCondVs = 0x6, /* 0110 */
- kArmCondVc = 0x7, /* 0111 */
- kArmCondHi = 0x8, /* 1000 */
- kArmCondLs = 0x9, /* 1001 */
- kArmCondGe = 0xa, /* 1010 */
- kArmCondLt = 0xb, /* 1011 */
- kArmCondGt = 0xc, /* 1100 */
- kArmCondLe = 0xd, /* 1101 */
- kArmCondAl = 0xe, /* 1110 */
- kArmCondNv = 0xf, /* 1111 */
+ kArmCondEq = 0x0, /* 0000 */
+ kArmCondNe = 0x1, /* 0001 */
+ kArmCondCs = 0x2, /* 0010 */
+ kArmCondCc = 0x3, /* 0011 */
+ kArmCondMi = 0x4, /* 0100 */
+ kArmCondPl = 0x5, /* 0101 */
+ kArmCondVs = 0x6, /* 0110 */
+ kArmCondVc = 0x7, /* 0111 */
+ kArmCondHi = 0x8, /* 1000 */
+ kArmCondLs = 0x9, /* 1001 */
+ kArmCondGe = 0xa, /* 1010 */
+ kArmCondLt = 0xb, /* 1011 */
+ kArmCondGt = 0xc, /* 1100 */
+ kArmCondLe = 0xd, /* 1101 */
+ kArmCondAl = 0xe, /* 1110 */
+ kArmCondNv = 0xf, /* 1111 */
};
#define isPseudoOpcode(opcode) ((int)(opcode) < 0)
@@ -290,383 +290,383 @@
* Assemble.cc.
*/
enum ArmOpcode {
- kPseudoIntrinsicRetry = -16,
- kPseudoSuspendTarget = -15,
- kPseudoThrowTarget = -14,
- kPseudoCaseLabel = -13,
- kPseudoMethodEntry = -12,
- kPseudoMethodExit = -11,
- kPseudoBarrier = -10,
- kPseudoExtended = -9,
- kPseudoSSARep = -8,
- kPseudoEntryBlock = -7,
- kPseudoExitBlock = -6,
- kPseudoTargetLabel = -5,
- kPseudoDalvikByteCodeBoundary = -4,
- kPseudoPseudoAlign4 = -3,
- kPseudoEHBlockLabel = -2,
- kPseudoNormalBlockLabel = -1,
- /************************************************************************/
- kArm16BitData, /* DATA [0] rd[15..0] */
- kThumbAdcRR, /* adc [0100000101] rm[5..3] rd[2..0] */
- kThumbAddRRI3, /* add(1) [0001110] imm_3[8..6] rn[5..3] rd[2..0]*/
- kThumbAddRI8, /* add(2) [00110] rd[10..8] imm_8[7..0] */
- kThumbAddRRR, /* add(3) [0001100] rm[8..6] rn[5..3] rd[2..0] */
- kThumbAddRRLH, /* add(4) [01000100] H12[01] rm[5..3] rd[2..0] */
- kThumbAddRRHL, /* add(4) [01001000] H12[10] rm[5..3] rd[2..0] */
- kThumbAddRRHH, /* add(4) [01001100] H12[11] rm[5..3] rd[2..0] */
- kThumbAddPcRel, /* add(5) [10100] rd[10..8] imm_8[7..0] */
- kThumbAddSpRel, /* add(6) [10101] rd[10..8] imm_8[7..0] */
- kThumbAddSpI7, /* add(7) [101100000] imm_7[6..0] */
- kThumbAndRR, /* and [0100000000] rm[5..3] rd[2..0] */
- kThumbAsrRRI5, /* asr(1) [00010] imm_5[10..6] rm[5..3] rd[2..0] */
- kThumbAsrRR, /* asr(2) [0100000100] rs[5..3] rd[2..0] */
- kThumbBCond, /* b(1) [1101] cond[11..8] offset_8[7..0] */
- kThumbBUncond, /* b(2) [11100] offset_11[10..0] */
- kThumbBicRR, /* bic [0100001110] rm[5..3] rd[2..0] */
- kThumbBkpt, /* bkpt [10111110] imm_8[7..0] */
- kThumbBlx1, /* blx(1) [111] H[10] offset_11[10..0] */
- kThumbBlx2, /* blx(1) [111] H[01] offset_11[10..0] */
- kThumbBl1, /* blx(1) [111] H[10] offset_11[10..0] */
- kThumbBl2, /* blx(1) [111] H[11] offset_11[10..0] */
- kThumbBlxR, /* blx(2) [010001111] rm[6..3] [000] */
- kThumbBx, /* bx [010001110] H2[6..6] rm[5..3] SBZ[000] */
- kThumbCmnRR, /* cmn [0100001011] rm[5..3] rd[2..0] */
- kThumbCmpRI8, /* cmp(1) [00101] rn[10..8] imm_8[7..0] */
- kThumbCmpRR, /* cmp(2) [0100001010] rm[5..3] rd[2..0] */
- kThumbCmpLH, /* cmp(3) [01000101] H12[01] rm[5..3] rd[2..0] */
- kThumbCmpHL, /* cmp(3) [01000110] H12[10] rm[5..3] rd[2..0] */
- kThumbCmpHH, /* cmp(3) [01000111] H12[11] rm[5..3] rd[2..0] */
- kThumbEorRR, /* eor [0100000001] rm[5..3] rd[2..0] */
- kThumbLdmia, /* ldmia [11001] rn[10..8] reglist [7..0] */
- kThumbLdrRRI5, /* ldr(1) [01101] imm_5[10..6] rn[5..3] rd[2..0] */
- kThumbLdrRRR, /* ldr(2) [0101100] rm[8..6] rn[5..3] rd[2..0] */
- kThumbLdrPcRel, /* ldr(3) [01001] rd[10..8] imm_8[7..0] */
- kThumbLdrSpRel, /* ldr(4) [10011] rd[10..8] imm_8[7..0] */
- kThumbLdrbRRI5, /* ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0] */
- kThumbLdrbRRR, /* ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0] */
- kThumbLdrhRRI5, /* ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0] */
- kThumbLdrhRRR, /* ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] */
- kThumbLdrsbRRR, /* ldrsb [0101011] rm[8..6] rn[5..3] rd[2..0] */
- kThumbLdrshRRR, /* ldrsh [0101111] rm[8..6] rn[5..3] rd[2..0] */
- kThumbLslRRI5, /* lsl(1) [00000] imm_5[10..6] rm[5..3] rd[2..0] */
- kThumbLslRR, /* lsl(2) [0100000010] rs[5..3] rd[2..0] */
- kThumbLsrRRI5, /* lsr(1) [00001] imm_5[10..6] rm[5..3] rd[2..0] */
- kThumbLsrRR, /* lsr(2) [0100000011] rs[5..3] rd[2..0] */
- kThumbMovImm, /* mov(1) [00100] rd[10..8] imm_8[7..0] */
- kThumbMovRR, /* mov(2) [0001110000] rn[5..3] rd[2..0] */
- kThumbMovRR_H2H, /* mov(3) [01000111] H12[11] rm[5..3] rd[2..0] */
- kThumbMovRR_H2L, /* mov(3) [01000110] H12[01] rm[5..3] rd[2..0] */
- kThumbMovRR_L2H, /* mov(3) [01000101] H12[10] rm[5..3] rd[2..0] */
- kThumbMul, /* mul [0100001101] rm[5..3] rd[2..0] */
- kThumbMvn, /* mvn [0100001111] rm[5..3] rd[2..0] */
- kThumbNeg, /* neg [0100001001] rm[5..3] rd[2..0] */
- kThumbOrr, /* orr [0100001100] rm[5..3] rd[2..0] */
- kThumbPop, /* pop [1011110] r[8..8] rl[7..0] */
- kThumbPush, /* push [1011010] r[8..8] rl[7..0] */
- kThumbRorRR, /* ror [0100000111] rs[5..3] rd[2..0] */
- kThumbSbc, /* sbc [0100000110] rm[5..3] rd[2..0] */
- kThumbStmia, /* stmia [11000] rn[10..8] reglist [7.. 0] */
- kThumbStrRRI5, /* str(1) [01100] imm_5[10..6] rn[5..3] rd[2..0] */
- kThumbStrRRR, /* str(2) [0101000] rm[8..6] rn[5..3] rd[2..0] */
- kThumbStrSpRel, /* str(3) [10010] rd[10..8] imm_8[7..0] */
- kThumbStrbRRI5, /* strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0] */
- kThumbStrbRRR, /* strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0] */
- kThumbStrhRRI5, /* strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0] */
- kThumbStrhRRR, /* strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0] */
- kThumbSubRRI3, /* sub(1) [0001111] imm_3[8..6] rn[5..3] rd[2..0]*/
- kThumbSubRI8, /* sub(2) [00111] rd[10..8] imm_8[7..0] */
- kThumbSubRRR, /* sub(3) [0001101] rm[8..6] rn[5..3] rd[2..0] */
- kThumbSubSpI7, /* sub(4) [101100001] imm_7[6..0] */
- kThumbSwi, /* swi [11011111] imm_8[7..0] */
- kThumbTst, /* tst [0100001000] rm[5..3] rn[2..0] */
- kThumb2Vldrs, /* vldr low sx [111011011001] rn[19..16] rd[15-12]
- [1010] imm_8[7..0] */
- kThumb2Vldrd, /* vldr low dx [111011011001] rn[19..16] rd[15-12]
- [1011] imm_8[7..0] */
- kThumb2Vmuls, /* vmul vd, vn, vm [111011100010] rn[19..16]
- rd[15-12] [10100000] rm[3..0] */
- kThumb2Vmuld, /* vmul vd, vn, vm [111011100010] rn[19..16]
- rd[15-12] [10110000] rm[3..0] */
- kThumb2Vstrs, /* vstr low sx [111011011000] rn[19..16] rd[15-12]
- [1010] imm_8[7..0] */
- kThumb2Vstrd, /* vstr low dx [111011011000] rn[19..16] rd[15-12]
- [1011] imm_8[7..0] */
- kThumb2Vsubs, /* vsub vd, vn, vm [111011100011] rn[19..16]
- rd[15-12] [10100040] rm[3..0] */
- kThumb2Vsubd, /* vsub vd, vn, vm [111011100011] rn[19..16]
- rd[15-12] [10110040] rm[3..0] */
- kThumb2Vadds, /* vadd vd, vn, vm [111011100011] rn[19..16]
- rd[15-12] [10100000] rm[3..0] */
- kThumb2Vaddd, /* vadd vd, vn, vm [111011100011] rn[19..16]
- rd[15-12] [10110000] rm[3..0] */
- kThumb2Vdivs, /* vdiv vd, vn, vm [111011101000] rn[19..16]
- rd[15-12] [10100000] rm[3..0] */
- kThumb2Vdivd, /* vdiv vd, vn, vm [111011101000] rn[19..16]
- rd[15-12] [10110000] rm[3..0] */
- kThumb2VcvtIF, /* vcvt.F32 vd, vm [1110111010111000] vd[15..12]
- [10101100] vm[3..0] */
- kThumb2VcvtID, /* vcvt.F64 vd, vm [1110111010111000] vd[15..12]
- [10111100] vm[3..0] */
- kThumb2VcvtFI, /* vcvt.S32.F32 vd, vm [1110111010111101] vd[15..12]
- [10101100] vm[3..0] */
- kThumb2VcvtDI, /* vcvt.S32.F32 vd, vm [1110111010111101] vd[15..12]
- [10111100] vm[3..0] */
- kThumb2VcvtFd, /* vcvt.F64.F32 vd, vm [1110111010110111] vd[15..12]
- [10101100] vm[3..0] */
- kThumb2VcvtDF, /* vcvt.F32.F64 vd, vm [1110111010110111] vd[15..12]
- [10111100] vm[3..0] */
- kThumb2Vsqrts, /* vsqrt.f32 vd, vm [1110111010110001] vd[15..12]
- [10101100] vm[3..0] */
- kThumb2Vsqrtd, /* vsqrt.f64 vd, vm [1110111010110001] vd[15..12]
- [10111100] vm[3..0] */
- kThumb2MovImmShift, /* mov(T2) rd, #<const> [11110] i [00001001111]
- imm3 rd[11..8] imm8 */
- kThumb2MovImm16, /* mov(T3) rd, #<const> [11110] i [0010100] imm4 [0]
- imm3 rd[11..8] imm8 */
- kThumb2StrRRI12, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
- rn[19..16] rt[15..12] imm12[11..0] */
- kThumb2LdrRRI12, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
- rn[19..16] rt[15..12] imm12[11..0] */
- kThumb2StrRRI8Predec, /* str(Imm,T4) rd,[rn,#-imm8] [111110000100]
- rn[19..16] rt[15..12] [1100] imm[7..0]*/
- kThumb2LdrRRI8Predec, /* ldr(Imm,T4) rd,[rn,#-imm8] [111110000101]
- rn[19..16] rt[15..12] [1100] imm[7..0]*/
- kThumb2Cbnz, /* cbnz rd,<label> [101110] i [1] imm5[7..3]
- rn[2..0] */
- kThumb2Cbz, /* cbn rd,<label> [101100] i [1] imm5[7..3]
- rn[2..0] */
- kThumb2AddRRI12, /* add rd, rn, #imm12 [11110] i [100000] rn[19..16]
- [0] imm3[14..12] rd[11..8] imm8[7..0] */
- kThumb2MovRR, /* mov rd, rm [11101010010011110000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2Vmovs, /* vmov.f32 vd, vm [111011101] D [110000]
- vd[15..12] 101001] M [0] vm[3..0] */
- kThumb2Vmovd, /* vmov.f64 vd, vm [111011101] D [110000]
- vd[15..12] 101101] M [0] vm[3..0] */
- kThumb2Ldmia, /* ldmia [111010001001[ rn[19..16] mask[15..0] */
- kThumb2Stmia, /* stmia [111010001000[ rn[19..16] mask[15..0] */
- kThumb2AddRRR, /* add [111010110000] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2SubRRR, /* sub [111010111010] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2SbcRRR, /* sbc [111010110110] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2CmpRR, /* cmp [111010111011] rn[19..16] [0000] [1111]
- [0000] rm[3..0] */
- kThumb2SubRRI12, /* sub rd, rn, #imm12 [11110] i [01010] rn[19..16]
- [0] imm3[14..12] rd[11..8] imm8[7..0] */
- kThumb2MvnImm12, /* mov(T2) rd, #<const> [11110] i [00011011110]
- imm3 rd[11..8] imm8 */
- kThumb2Sel, /* sel rd, rn, rm [111110101010] rn[19-16] rd[11-8]
- rm[3-0] */
- kThumb2Ubfx, /* ubfx rd,rn,#lsb,#width [111100111100] rn[19..16]
- [0] imm3[14-12] rd[11-8] w[4-0] */
- kThumb2Sbfx, /* ubfx rd,rn,#lsb,#width [111100110100] rn[19..16]
- [0] imm3[14-12] rd[11-8] w[4-0] */
- kThumb2LdrRRR, /* ldr rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2LdrhRRR, /* ldrh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2LdrshRRR, /* ldrsh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2LdrbRRR, /* ldrb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2LdrsbRRR, /* ldrsb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2StrRRR, /* str rt,[rn,rm,LSL #imm] [111110000100] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2StrhRRR, /* str rt,[rn,rm,LSL #imm] [111110000010] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2StrbRRR, /* str rt,[rn,rm,LSL #imm] [111110000000] rn[19-16]
- rt[15-12] [000000] imm[5-4] rm[3-0] */
- kThumb2LdrhRRI12, /* ldrh rt,[rn,#imm12] [111110001011]
- rt[15..12] rn[19..16] imm12[11..0] */
- kThumb2LdrshRRI12, /* ldrsh rt,[rn,#imm12] [111110011011]
- rt[15..12] rn[19..16] imm12[11..0] */
- kThumb2LdrbRRI12, /* ldrb rt,[rn,#imm12] [111110001001]
- rt[15..12] rn[19..16] imm12[11..0] */
- kThumb2LdrsbRRI12, /* ldrsb rt,[rn,#imm12] [111110011001]
- rt[15..12] rn[19..16] imm12[11..0] */
- kThumb2StrhRRI12, /* strh rt,[rn,#imm12] [111110001010]
- rt[15..12] rn[19..16] imm12[11..0] */
- kThumb2StrbRRI12, /* strb rt,[rn,#imm12] [111110001000]
- rt[15..12] rn[19..16] imm12[11..0] */
- kThumb2Pop, /* pop [1110100010111101] list[15-0]*/
- kThumb2Push, /* push [1110100100101101] list[15-0]*/
- kThumb2CmpRI8, /* cmp rn, #<const> [11110] i [011011] rn[19-16] [0]
- imm3 [1111] imm8[7..0] */
- kThumb2AdcRRR, /* adc [111010110101] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2AndRRR, /* and [111010100000] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2BicRRR, /* bic [111010100010] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2CmnRR, /* cmn [111010110001] rn[19..16] [0000] [1111]
- [0000] rm[3..0] */
- kThumb2EorRRR, /* eor [111010101000] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2MulRRR, /* mul [111110110000] rn[19..16] [1111] rd[11..8]
- [0000] rm[3..0] */
- kThumb2MnvRR, /* mvn [11101010011011110] rd[11-8] [0000]
- rm[3..0] */
- kThumb2RsubRRI8, /* rsub [111100011100] rn[19..16] [0000] rd[11..8]
- imm8[7..0] */
- kThumb2NegRR, /* actually rsub rd, rn, #0 */
- kThumb2OrrRRR, /* orr [111010100100] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2TstRR, /* tst [111010100001] rn[19..16] [0000] [1111]
- [0000] rm[3..0] */
- kThumb2LslRRR, /* lsl [111110100000] rn[19..16] [1111] rd[11..8]
- [0000] rm[3..0] */
- kThumb2LsrRRR, /* lsr [111110100010] rn[19..16] [1111] rd[11..8]
- [0000] rm[3..0] */
- kThumb2AsrRRR, /* asr [111110100100] rn[19..16] [1111] rd[11..8]
- [0000] rm[3..0] */
- kThumb2RorRRR, /* ror [111110100110] rn[19..16] [1111] rd[11..8]
- [0000] rm[3..0] */
- kThumb2LslRRI5, /* lsl [11101010010011110] imm[14.12] rd[11..8]
- [00] rm[3..0] */
- kThumb2LsrRRI5, /* lsr [11101010010011110] imm[14.12] rd[11..8]
- [01] rm[3..0] */
- kThumb2AsrRRI5, /* asr [11101010010011110] imm[14.12] rd[11..8]
- [10] rm[3..0] */
- kThumb2RorRRI5, /* ror [11101010010011110] imm[14.12] rd[11..8]
- [11] rm[3..0] */
- kThumb2BicRRI8, /* bic [111100000010] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2AndRRI8, /* bic [111100000000] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2OrrRRI8, /* orr [111100000100] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2EorRRI8, /* eor [111100001000] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2AddRRI8, /* add [111100001000] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2AdcRRI8, /* adc [111100010101] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2SubRRI8, /* sub [111100011011] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2SbcRRI8, /* sbc [111100010111] rn[19..16] [0] imm3
- rd[11..8] imm8 */
- kThumb2It, /* it [10111111] firstcond[7-4] mask[3-0] */
- kThumb2Fmstat, /* fmstat [11101110111100011111101000010000] */
- kThumb2Vcmpd, /* vcmp [111011101] D [11011] rd[15-12] [1011]
- E [1] M [0] rm[3-0] */
- kThumb2Vcmps, /* vcmp [111011101] D [11010] rd[15-12] [1011]
- E [1] M [0] rm[3-0] */
- kThumb2LdrPcRel12, /* ldr rd,[pc,#imm12] [1111100011011111] rt[15-12]
- imm12[11-0] */
- kThumb2BCond, /* b<c> [1110] S cond[25-22] imm6[21-16] [10]
- J1 [0] J2 imm11[10..0] */
- kThumb2Vmovd_RR, /* vmov [111011101] D [110000] vd[15-12 [101101]
- M [0] vm[3-0] */
- kThumb2Vmovs_RR, /* vmov [111011101] D [110000] vd[15-12 [101001]
- M [0] vm[3-0] */
- kThumb2Fmrs, /* vmov [111011100000] vn[19-16] rt[15-12] [1010]
- N [0010000] */
- kThumb2Fmsr, /* vmov [111011100001] vn[19-16] rt[15-12] [1010]
- N [0010000] */
- kThumb2Fmrrd, /* vmov [111011000100] rt2[19-16] rt[15-12]
- [101100] M [1] vm[3-0] */
- kThumb2Fmdrr, /* vmov [111011000101] rt2[19-16] rt[15-12]
- [101100] M [1] vm[3-0] */
- kThumb2Vabsd, /* vabs.f64 [111011101] D [110000] rd[15-12]
- [1011110] M [0] vm[3-0] */
- kThumb2Vabss, /* vabs.f32 [111011101] D [110000] rd[15-12]
- [1010110] M [0] vm[3-0] */
- kThumb2Vnegd, /* vneg.f64 [111011101] D [110000] rd[15-12]
- [1011110] M [0] vm[3-0] */
- kThumb2Vnegs, /* vneg.f32 [111011101] D [110000] rd[15-12]
- [1010110] M [0] vm[3-0] */
- kThumb2Vmovs_IMM8, /* vmov.f32 [111011101] D [11] imm4h[19-16] vd[15-12]
- [10100000] imm4l[3-0] */
- kThumb2Vmovd_IMM8, /* vmov.f64 [111011101] D [11] imm4h[19-16] vd[15-12]
- [10110000] imm4l[3-0] */
- kThumb2Mla, /* mla [111110110000] rn[19-16] ra[15-12] rd[7-4]
- [0000] rm[3-0] */
- kThumb2Umull, /* umull [111110111010] rn[19-16], rdlo[15-12]
- rdhi[11-8] [0000] rm[3-0] */
- kThumb2Ldrex, /* ldrex [111010000101] rn[19-16] rt[11-8] [1111]
- imm8[7-0] */
- kThumb2Strex, /* strex [111010000100] rn[19-16] rt[11-8] rd[11-8]
- imm8[7-0] */
- kThumb2Clrex, /* clrex [111100111011111110000111100101111] */
- kThumb2Bfi, /* bfi [111100110110] rn[19-16] [0] imm3[14-12]
- rd[11-8] imm2[7-6] [0] msb[4-0] */
- kThumb2Bfc, /* bfc [11110011011011110] [0] imm3[14-12]
- rd[11-8] imm2[7-6] [0] msb[4-0] */
- kThumb2Dmb, /* dmb [1111001110111111100011110101] option[3-0] */
- kThumb2LdrPcReln12, /* ldr rd,[pc,-#imm12] [1111100011011111] rt[15-12]
- imm12[11-0] */
- kThumb2Stm, /* stm <list> [111010010000] rn[19-16] 000 rl[12-0] */
- kThumbUndefined, /* undefined [11011110xxxxxxxx] */
- kThumb2VPopCS, /* vpop <list of callee save fp singles (s16+) */
- kThumb2VPushCS, /* vpush <list callee save fp singles (s16+) */
- kThumb2Vldms, /* vldms rd, <list> */
- kThumb2Vstms, /* vstms rd, <list> */
- kThumb2BUncond, /* b <label> */
- kThumb2MovImm16H, /* similar to kThumb2MovImm16, but target high hw */
- kThumb2AddPCR, /* Thumb2 2-operand add with hard-coded PC target */
- kThumb2Adr, /* Special purpose encoding of ADR for switch tables */
- kThumb2MovImm16LST, /* Special purpose version for switch table use */
- kThumb2MovImm16HST, /* Special purpose version for switch table use */
- kThumb2LdmiaWB, /* ldmia [111010011001[ rn[19..16] mask[15..0] */
- kThumb2SubsRRI12, /* setflags encoding */
- kThumb2OrrRRRs, /* orrx [111010100101] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2Push1, /* t3 encoding of push */
- kThumb2Pop1, /* t3 encoding of pop */
- kThumb2RsubRRR, /* rsb [111010111101] rn[19..16] [0000] rd[11..8]
- [0000] rm[3..0] */
- kThumb2Smull, /* smull [111110111000] rn[19-16], rdlo[15-12]
- rdhi[11-8] [0000] rm[3-0] */
- kArmLast,
+ kPseudoIntrinsicRetry = -16,
+ kPseudoSuspendTarget = -15,
+ kPseudoThrowTarget = -14,
+ kPseudoCaseLabel = -13,
+ kPseudoMethodEntry = -12,
+ kPseudoMethodExit = -11,
+ kPseudoBarrier = -10,
+ kPseudoExtended = -9,
+ kPseudoSSARep = -8,
+ kPseudoEntryBlock = -7,
+ kPseudoExitBlock = -6,
+ kPseudoTargetLabel = -5,
+ kPseudoDalvikByteCodeBoundary = -4,
+ kPseudoPseudoAlign4 = -3,
+ kPseudoEHBlockLabel = -2,
+ kPseudoNormalBlockLabel = -1,
+ /************************************************************************/
+ kArm16BitData, /* DATA [0] rd[15..0] */
+ kThumbAdcRR, /* adc [0100000101] rm[5..3] rd[2..0] */
+ kThumbAddRRI3, /* add(1) [0001110] imm_3[8..6] rn[5..3] rd[2..0]*/
+ kThumbAddRI8, /* add(2) [00110] rd[10..8] imm_8[7..0] */
+ kThumbAddRRR, /* add(3) [0001100] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbAddRRLH, /* add(4) [01000100] H12[01] rm[5..3] rd[2..0] */
+ kThumbAddRRHL, /* add(4) [01001000] H12[10] rm[5..3] rd[2..0] */
+ kThumbAddRRHH, /* add(4) [01001100] H12[11] rm[5..3] rd[2..0] */
+ kThumbAddPcRel, /* add(5) [10100] rd[10..8] imm_8[7..0] */
+ kThumbAddSpRel, /* add(6) [10101] rd[10..8] imm_8[7..0] */
+ kThumbAddSpI7, /* add(7) [101100000] imm_7[6..0] */
+ kThumbAndRR, /* and [0100000000] rm[5..3] rd[2..0] */
+ kThumbAsrRRI5, /* asr(1) [00010] imm_5[10..6] rm[5..3] rd[2..0] */
+ kThumbAsrRR, /* asr(2) [0100000100] rs[5..3] rd[2..0] */
+ kThumbBCond, /* b(1) [1101] cond[11..8] offset_8[7..0] */
+ kThumbBUncond, /* b(2) [11100] offset_11[10..0] */
+ kThumbBicRR, /* bic [0100001110] rm[5..3] rd[2..0] */
+ kThumbBkpt, /* bkpt [10111110] imm_8[7..0] */
+ kThumbBlx1, /* blx(1) [111] H[10] offset_11[10..0] */
+ kThumbBlx2, /* blx(1) [111] H[01] offset_11[10..0] */
+ kThumbBl1, /* blx(1) [111] H[10] offset_11[10..0] */
+ kThumbBl2, /* blx(1) [111] H[11] offset_11[10..0] */
+ kThumbBlxR, /* blx(2) [010001111] rm[6..3] [000] */
+ kThumbBx, /* bx [010001110] H2[6..6] rm[5..3] SBZ[000] */
+ kThumbCmnRR, /* cmn [0100001011] rm[5..3] rd[2..0] */
+ kThumbCmpRI8, /* cmp(1) [00101] rn[10..8] imm_8[7..0] */
+ kThumbCmpRR, /* cmp(2) [0100001010] rm[5..3] rd[2..0] */
+ kThumbCmpLH, /* cmp(3) [01000101] H12[01] rm[5..3] rd[2..0] */
+ kThumbCmpHL, /* cmp(3) [01000110] H12[10] rm[5..3] rd[2..0] */
+ kThumbCmpHH, /* cmp(3) [01000111] H12[11] rm[5..3] rd[2..0] */
+ kThumbEorRR, /* eor [0100000001] rm[5..3] rd[2..0] */
+ kThumbLdmia, /* ldmia [11001] rn[10..8] reglist [7..0] */
+ kThumbLdrRRI5, /* ldr(1) [01101] imm_5[10..6] rn[5..3] rd[2..0] */
+ kThumbLdrRRR, /* ldr(2) [0101100] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbLdrPcRel, /* ldr(3) [01001] rd[10..8] imm_8[7..0] */
+ kThumbLdrSpRel, /* ldr(4) [10011] rd[10..8] imm_8[7..0] */
+ kThumbLdrbRRI5, /* ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0] */
+ kThumbLdrbRRR, /* ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbLdrhRRI5, /* ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0] */
+ kThumbLdrhRRR, /* ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbLdrsbRRR, /* ldrsb [0101011] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbLdrshRRR, /* ldrsh [0101111] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbLslRRI5, /* lsl(1) [00000] imm_5[10..6] rm[5..3] rd[2..0] */
+ kThumbLslRR, /* lsl(2) [0100000010] rs[5..3] rd[2..0] */
+ kThumbLsrRRI5, /* lsr(1) [00001] imm_5[10..6] rm[5..3] rd[2..0] */
+ kThumbLsrRR, /* lsr(2) [0100000011] rs[5..3] rd[2..0] */
+ kThumbMovImm, /* mov(1) [00100] rd[10..8] imm_8[7..0] */
+ kThumbMovRR, /* mov(2) [0001110000] rn[5..3] rd[2..0] */
+ kThumbMovRR_H2H, /* mov(3) [01000111] H12[11] rm[5..3] rd[2..0] */
+ kThumbMovRR_H2L, /* mov(3) [01000110] H12[01] rm[5..3] rd[2..0] */
+ kThumbMovRR_L2H, /* mov(3) [01000101] H12[10] rm[5..3] rd[2..0] */
+ kThumbMul, /* mul [0100001101] rm[5..3] rd[2..0] */
+ kThumbMvn, /* mvn [0100001111] rm[5..3] rd[2..0] */
+ kThumbNeg, /* neg [0100001001] rm[5..3] rd[2..0] */
+ kThumbOrr, /* orr [0100001100] rm[5..3] rd[2..0] */
+ kThumbPop, /* pop [1011110] r[8..8] rl[7..0] */
+ kThumbPush, /* push [1011010] r[8..8] rl[7..0] */
+ kThumbRorRR, /* ror [0100000111] rs[5..3] rd[2..0] */
+ kThumbSbc, /* sbc [0100000110] rm[5..3] rd[2..0] */
+ kThumbStmia, /* stmia [11000] rn[10..8] reglist [7.. 0] */
+ kThumbStrRRI5, /* str(1) [01100] imm_5[10..6] rn[5..3] rd[2..0] */
+ kThumbStrRRR, /* str(2) [0101000] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbStrSpRel, /* str(3) [10010] rd[10..8] imm_8[7..0] */
+ kThumbStrbRRI5, /* strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0] */
+ kThumbStrbRRR, /* strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbStrhRRI5, /* strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0] */
+ kThumbStrhRRR, /* strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbSubRRI3, /* sub(1) [0001111] imm_3[8..6] rn[5..3] rd[2..0]*/
+ kThumbSubRI8, /* sub(2) [00111] rd[10..8] imm_8[7..0] */
+ kThumbSubRRR, /* sub(3) [0001101] rm[8..6] rn[5..3] rd[2..0] */
+ kThumbSubSpI7, /* sub(4) [101100001] imm_7[6..0] */
+ kThumbSwi, /* swi [11011111] imm_8[7..0] */
+ kThumbTst, /* tst [0100001000] rm[5..3] rn[2..0] */
+ kThumb2Vldrs, /* vldr low sx [111011011001] rn[19..16] rd[15-12]
+ [1010] imm_8[7..0] */
+ kThumb2Vldrd, /* vldr low dx [111011011001] rn[19..16] rd[15-12]
+ [1011] imm_8[7..0] */
+ kThumb2Vmuls, /* vmul vd, vn, vm [111011100010] rn[19..16]
+ rd[15-12] [10100000] rm[3..0] */
+ kThumb2Vmuld, /* vmul vd, vn, vm [111011100010] rn[19..16]
+ rd[15-12] [10110000] rm[3..0] */
+ kThumb2Vstrs, /* vstr low sx [111011011000] rn[19..16] rd[15-12]
+ [1010] imm_8[7..0] */
+ kThumb2Vstrd, /* vstr low dx [111011011000] rn[19..16] rd[15-12]
+ [1011] imm_8[7..0] */
+ kThumb2Vsubs, /* vsub vd, vn, vm [111011100011] rn[19..16]
+ rd[15-12] [10100040] rm[3..0] */
+ kThumb2Vsubd, /* vsub vd, vn, vm [111011100011] rn[19..16]
+ rd[15-12] [10110040] rm[3..0] */
+ kThumb2Vadds, /* vadd vd, vn, vm [111011100011] rn[19..16]
+ rd[15-12] [10100000] rm[3..0] */
+ kThumb2Vaddd, /* vadd vd, vn, vm [111011100011] rn[19..16]
+ rd[15-12] [10110000] rm[3..0] */
+ kThumb2Vdivs, /* vdiv vd, vn, vm [111011101000] rn[19..16]
+ rd[15-12] [10100000] rm[3..0] */
+ kThumb2Vdivd, /* vdiv vd, vn, vm [111011101000] rn[19..16]
+ rd[15-12] [10110000] rm[3..0] */
+ kThumb2VcvtIF, /* vcvt.F32 vd, vm [1110111010111000] vd[15..12]
+ [10101100] vm[3..0] */
+ kThumb2VcvtID, /* vcvt.F64 vd, vm [1110111010111000] vd[15..12]
+ [10111100] vm[3..0] */
+ kThumb2VcvtFI, /* vcvt.S32.F32 vd, vm [1110111010111101] vd[15..12]
+ [10101100] vm[3..0] */
+ kThumb2VcvtDI, /* vcvt.S32.F32 vd, vm [1110111010111101] vd[15..12]
+ [10111100] vm[3..0] */
+ kThumb2VcvtFd, /* vcvt.F64.F32 vd, vm [1110111010110111] vd[15..12]
+ [10101100] vm[3..0] */
+ kThumb2VcvtDF, /* vcvt.F32.F64 vd, vm [1110111010110111] vd[15..12]
+ [10111100] vm[3..0] */
+ kThumb2Vsqrts, /* vsqrt.f32 vd, vm [1110111010110001] vd[15..12]
+ [10101100] vm[3..0] */
+ kThumb2Vsqrtd, /* vsqrt.f64 vd, vm [1110111010110001] vd[15..12]
+ [10111100] vm[3..0] */
+ kThumb2MovImmShift,/* mov(T2) rd, #<const> [11110] i [00001001111]
+ imm3 rd[11..8] imm8 */
+ kThumb2MovImm16, /* mov(T3) rd, #<const> [11110] i [0010100] imm4 [0]
+ imm3 rd[11..8] imm8 */
+ kThumb2StrRRI12, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
+ rn[19..16] rt[15..12] imm12[11..0] */
+ kThumb2LdrRRI12, /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
+ rn[19..16] rt[15..12] imm12[11..0] */
+ kThumb2StrRRI8Predec, /* str(Imm,T4) rd,[rn,#-imm8] [111110000100]
+ rn[19..16] rt[15..12] [1100] imm[7..0]*/
+ kThumb2LdrRRI8Predec, /* ldr(Imm,T4) rd,[rn,#-imm8] [111110000101]
+ rn[19..16] rt[15..12] [1100] imm[7..0]*/
+ kThumb2Cbnz, /* cbnz rd,<label> [101110] i [1] imm5[7..3]
+ rn[2..0] */
+ kThumb2Cbz, /* cbn rd,<label> [101100] i [1] imm5[7..3]
+ rn[2..0] */
+ kThumb2AddRRI12, /* add rd, rn, #imm12 [11110] i [100000] rn[19..16]
+ [0] imm3[14..12] rd[11..8] imm8[7..0] */
+ kThumb2MovRR, /* mov rd, rm [11101010010011110000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2Vmovs, /* vmov.f32 vd, vm [111011101] D [110000]
+ vd[15..12] 101001] M [0] vm[3..0] */
+ kThumb2Vmovd, /* vmov.f64 vd, vm [111011101] D [110000]
+ vd[15..12] 101101] M [0] vm[3..0] */
+ kThumb2Ldmia, /* ldmia [111010001001[ rn[19..16] mask[15..0] */
+ kThumb2Stmia, /* stmia [111010001000[ rn[19..16] mask[15..0] */
+ kThumb2AddRRR, /* add [111010110000] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2SubRRR, /* sub [111010111010] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2SbcRRR, /* sbc [111010110110] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2CmpRR, /* cmp [111010111011] rn[19..16] [0000] [1111]
+ [0000] rm[3..0] */
+ kThumb2SubRRI12, /* sub rd, rn, #imm12 [11110] i [01010] rn[19..16]
+ [0] imm3[14..12] rd[11..8] imm8[7..0] */
+ kThumb2MvnImm12, /* mov(T2) rd, #<const> [11110] i [00011011110]
+ imm3 rd[11..8] imm8 */
+ kThumb2Sel, /* sel rd, rn, rm [111110101010] rn[19-16] rd[11-8]
+ rm[3-0] */
+ kThumb2Ubfx, /* ubfx rd,rn,#lsb,#width [111100111100] rn[19..16]
+ [0] imm3[14-12] rd[11-8] w[4-0] */
+ kThumb2Sbfx, /* ubfx rd,rn,#lsb,#width [111100110100] rn[19..16]
+ [0] imm3[14-12] rd[11-8] w[4-0] */
+ kThumb2LdrRRR, /* ldr rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2LdrhRRR, /* ldrh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2LdrshRRR, /* ldrsh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2LdrbRRR, /* ldrb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2LdrsbRRR, /* ldrsb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2StrRRR, /* str rt,[rn,rm,LSL #imm] [111110000100] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2StrhRRR, /* str rt,[rn,rm,LSL #imm] [111110000010] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2StrbRRR, /* str rt,[rn,rm,LSL #imm] [111110000000] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ kThumb2LdrhRRI12, /* ldrh rt,[rn,#imm12] [111110001011]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kThumb2LdrshRRI12, /* ldrsh rt,[rn,#imm12] [111110011011]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kThumb2LdrbRRI12, /* ldrb rt,[rn,#imm12] [111110001001]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kThumb2LdrsbRRI12, /* ldrsb rt,[rn,#imm12] [111110011001]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kThumb2StrhRRI12, /* strh rt,[rn,#imm12] [111110001010]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kThumb2StrbRRI12, /* strb rt,[rn,#imm12] [111110001000]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ kThumb2Pop, /* pop [1110100010111101] list[15-0]*/
+ kThumb2Push, /* push [1110100100101101] list[15-0]*/
+ kThumb2CmpRI8, /* cmp rn, #<const> [11110] i [011011] rn[19-16] [0]
+ imm3 [1111] imm8[7..0] */
+ kThumb2AdcRRR, /* adc [111010110101] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2AndRRR, /* and [111010100000] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2BicRRR, /* bic [111010100010] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2CmnRR, /* cmn [111010110001] rn[19..16] [0000] [1111]
+ [0000] rm[3..0] */
+ kThumb2EorRRR, /* eor [111010101000] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2MulRRR, /* mul [111110110000] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2MnvRR, /* mvn [11101010011011110] rd[11-8] [0000]
+ rm[3..0] */
+ kThumb2RsubRRI8, /* rsub [111100011100] rn[19..16] [0000] rd[11..8]
+ imm8[7..0] */
+ kThumb2NegRR, /* actually rsub rd, rn, #0 */
+ kThumb2OrrRRR, /* orr [111010100100] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2TstRR, /* tst [111010100001] rn[19..16] [0000] [1111]
+ [0000] rm[3..0] */
+ kThumb2LslRRR, /* lsl [111110100000] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2LsrRRR, /* lsr [111110100010] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2AsrRRR, /* asr [111110100100] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2RorRRR, /* ror [111110100110] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2LslRRI5, /* lsl [11101010010011110] imm[14.12] rd[11..8]
+ [00] rm[3..0] */
+ kThumb2LsrRRI5, /* lsr [11101010010011110] imm[14.12] rd[11..8]
+ [01] rm[3..0] */
+ kThumb2AsrRRI5, /* asr [11101010010011110] imm[14.12] rd[11..8]
+ [10] rm[3..0] */
+ kThumb2RorRRI5, /* ror [11101010010011110] imm[14.12] rd[11..8]
+ [11] rm[3..0] */
+ kThumb2BicRRI8, /* bic [111100000010] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2AndRRI8, /* bic [111100000000] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2OrrRRI8, /* orr [111100000100] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2EorRRI8, /* eor [111100001000] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2AddRRI8, /* add [111100001000] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2AdcRRI8, /* adc [111100010101] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2SubRRI8, /* sub [111100011011] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2SbcRRI8, /* sbc [111100010111] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ kThumb2It, /* it [10111111] firstcond[7-4] mask[3-0] */
+ kThumb2Fmstat, /* fmstat [11101110111100011111101000010000] */
+ kThumb2Vcmpd, /* vcmp [111011101] D [11011] rd[15-12] [1011]
+ E [1] M [0] rm[3-0] */
+ kThumb2Vcmps, /* vcmp [111011101] D [11010] rd[15-12] [1011]
+ E [1] M [0] rm[3-0] */
+ kThumb2LdrPcRel12, /* ldr rd,[pc,#imm12] [1111100011011111] rt[15-12]
+ imm12[11-0] */
+ kThumb2BCond, /* b<c> [1110] S cond[25-22] imm6[21-16] [10]
+ J1 [0] J2 imm11[10..0] */
+ kThumb2Vmovd_RR, /* vmov [111011101] D [110000] vd[15-12 [101101]
+ M [0] vm[3-0] */
+ kThumb2Vmovs_RR, /* vmov [111011101] D [110000] vd[15-12 [101001]
+ M [0] vm[3-0] */
+ kThumb2Fmrs, /* vmov [111011100000] vn[19-16] rt[15-12] [1010]
+ N [0010000] */
+ kThumb2Fmsr, /* vmov [111011100001] vn[19-16] rt[15-12] [1010]
+ N [0010000] */
+ kThumb2Fmrrd, /* vmov [111011000100] rt2[19-16] rt[15-12]
+ [101100] M [1] vm[3-0] */
+ kThumb2Fmdrr, /* vmov [111011000101] rt2[19-16] rt[15-12]
+ [101100] M [1] vm[3-0] */
+ kThumb2Vabsd, /* vabs.f64 [111011101] D [110000] rd[15-12]
+ [1011110] M [0] vm[3-0] */
+ kThumb2Vabss, /* vabs.f32 [111011101] D [110000] rd[15-12]
+ [1010110] M [0] vm[3-0] */
+ kThumb2Vnegd, /* vneg.f64 [111011101] D [110000] rd[15-12]
+ [1011110] M [0] vm[3-0] */
+ kThumb2Vnegs, /* vneg.f32 [111011101] D [110000] rd[15-12]
+ [1010110] M [0] vm[3-0] */
+ kThumb2Vmovs_IMM8, /* vmov.f32 [111011101] D [11] imm4h[19-16] vd[15-12]
+ [10100000] imm4l[3-0] */
+ kThumb2Vmovd_IMM8, /* vmov.f64 [111011101] D [11] imm4h[19-16] vd[15-12]
+ [10110000] imm4l[3-0] */
+ kThumb2Mla, /* mla [111110110000] rn[19-16] ra[15-12] rd[7-4]
+ [0000] rm[3-0] */
+ kThumb2Umull, /* umull [111110111010] rn[19-16], rdlo[15-12]
+ rdhi[11-8] [0000] rm[3-0] */
+ kThumb2Ldrex, /* ldrex [111010000101] rn[19-16] rt[11-8] [1111]
+ imm8[7-0] */
+ kThumb2Strex, /* strex [111010000100] rn[19-16] rt[11-8] rd[11-8]
+ imm8[7-0] */
+ kThumb2Clrex, /* clrex [111100111011111110000111100101111] */
+ kThumb2Bfi, /* bfi [111100110110] rn[19-16] [0] imm3[14-12]
+ rd[11-8] imm2[7-6] [0] msb[4-0] */
+ kThumb2Bfc, /* bfc [11110011011011110] [0] imm3[14-12]
+ rd[11-8] imm2[7-6] [0] msb[4-0] */
+ kThumb2Dmb, /* dmb [1111001110111111100011110101] option[3-0] */
+ kThumb2LdrPcReln12,/* ldr rd,[pc,-#imm12] [1111100011011111] rt[15-12]
+ imm12[11-0] */
+ kThumb2Stm, /* stm <list> [111010010000] rn[19-16] 000 rl[12-0] */
+ kThumbUndefined, /* undefined [11011110xxxxxxxx] */
+ kThumb2VPopCS, /* vpop <list of callee save fp singles (s16+) */
+ kThumb2VPushCS, /* vpush <list callee save fp singles (s16+) */
+ kThumb2Vldms, /* vldms rd, <list> */
+ kThumb2Vstms, /* vstms rd, <list> */
+ kThumb2BUncond, /* b <label> */
+ kThumb2MovImm16H, /* similar to kThumb2MovImm16, but target high hw */
+ kThumb2AddPCR, /* Thumb2 2-operand add with hard-coded PC target */
+ kThumb2Adr, /* Special purpose encoding of ADR for switch tables */
+ kThumb2MovImm16LST,/* Special purpose version for switch table use */
+ kThumb2MovImm16HST,/* Special purpose version for switch table use */
+ kThumb2LdmiaWB, /* ldmia [111010011001[ rn[19..16] mask[15..0] */
+ kThumb2SubsRRI12, /* setflags encoding */
+ kThumb2OrrRRRs, /* orrx [111010100101] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2Push1, /* t3 encoding of push */
+ kThumb2Pop1, /* t3 encoding of pop */
+ kThumb2RsubRRR, /* rsb [111010111101] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ kThumb2Smull, /* smull [111110111000] rn[19-16], rdlo[15-12]
+ rdhi[11-8] [0000] rm[3-0] */
+ kArmLast,
};
/* DMB option encodings */
enum ArmOpDmbOptions {
- kSY = 0xf,
- kST = 0xe,
- kISH = 0xb,
- kISHST = 0xa,
- kNSH = 0x7,
- kNSHST = 0x6
+ kSY = 0xf,
+ kST = 0xe,
+ kISH = 0xb,
+ kISHST = 0xa,
+ kNSH = 0x7,
+ kNSHST = 0x6
};
/* Bit flags describing the behavior of each native opcode */
enum ArmOpFeatureFlags {
- kIsBranch = 0,
- kRegDef0,
- kRegDef1,
- kRegDefSP,
- kRegDefLR,
- kRegDefList0,
- kRegDefList1,
- kRegDefFPCSList0,
- kRegDefFPCSList2,
- kRegDefList2,
- kRegUse0,
- kRegUse1,
- kRegUse2,
- kRegUse3,
- kRegUseSP,
- kRegUsePC,
- kRegUseList0,
- kRegUseList1,
- kRegUseFPCSList0,
- kRegUseFPCSList2,
- kNoOperand,
- kIsUnaryOp,
- kIsBinaryOp,
- kIsTertiaryOp,
- kIsQuadOp,
- kIsIT,
- kSetsCCodes,
- kUsesCCodes,
- kMemLoad,
- kMemStore,
- kPCRelFixup,
+ kIsBranch = 0,
+ kRegDef0,
+ kRegDef1,
+ kRegDefSP,
+ kRegDefLR,
+ kRegDefList0,
+ kRegDefList1,
+ kRegDefFPCSList0,
+ kRegDefFPCSList2,
+ kRegDefList2,
+ kRegUse0,
+ kRegUse1,
+ kRegUse2,
+ kRegUse3,
+ kRegUseSP,
+ kRegUsePC,
+ kRegUseList0,
+ kRegUseList1,
+ kRegUseFPCSList0,
+ kRegUseFPCSList2,
+ kNoOperand,
+ kIsUnaryOp,
+ kIsBinaryOp,
+ kIsTertiaryOp,
+ kIsQuadOp,
+ kIsIT,
+ kSetsCCodes,
+ kUsesCCodes,
+ kMemLoad,
+ kMemStore,
+ kPCRelFixup,
};
#define IS_LOAD (1 << kMemLoad)
@@ -713,41 +713,41 @@
/* Instruction assembly fieldLoc kind */
enum ArmEncodingKind {
- kFmtUnused,
- kFmtBitBlt, /* Bit string using end/start */
- kFmtDfp, /* Double FP reg */
- kFmtSfp, /* Single FP reg */
- kFmtModImm, /* Shifted 8-bit immed using [26,14..12,7..0] */
- kFmtImm16, /* Zero-extended immed using [26,19..16,14..12,7..0] */
- kFmtImm6, /* Encoded branch target using [9,7..3]0 */
- kFmtImm12, /* Zero-extended immediate using [26,14..12,7..0] */
- kFmtShift, /* Shift descriptor, [14..12,7..4] */
- kFmtLsb, /* least significant bit using [14..12][7..6] */
- kFmtBWidth, /* bit-field width, encoded as width-1 */
- kFmtShift5, /* Shift count, [14..12,7..6] */
- kFmtBrOffset, /* Signed extended [26,11,13,21-16,10-0]:0 */
- kFmtFPImm, /* Encoded floating point immediate */
- kFmtOff24, /* 24-bit Thumb2 unconditional branch encoding */
+ kFmtUnused,
+ kFmtBitBlt, /* Bit string using end/start */
+ kFmtDfp, /* Double FP reg */
+ kFmtSfp, /* Single FP reg */
+ kFmtModImm, /* Shifted 8-bit immed using [26,14..12,7..0] */
+ kFmtImm16, /* Zero-extended immed using [26,19..16,14..12,7..0] */
+ kFmtImm6, /* Encoded branch target using [9,7..3]0 */
+ kFmtImm12, /* Zero-extended immediate using [26,14..12,7..0] */
+ kFmtShift, /* Shift descriptor, [14..12,7..4] */
+ kFmtLsb, /* least significant bit using [14..12][7..6] */
+ kFmtBWidth, /* bit-field width, encoded as width-1 */
+ kFmtShift5, /* Shift count, [14..12,7..6] */
+ kFmtBrOffset, /* Signed extended [26,11,13,21-16,10-0]:0 */
+ kFmtFPImm, /* Encoded floating point immediate */
+ kFmtOff24, /* 24-bit Thumb2 unconditional branch encoding */
};
/* Struct used to define the snippet positions for each Thumb opcode */
struct ArmEncodingMap {
- u4 skeleton;
- struct {
- ArmEncodingKind kind;
- int end; /* end for kFmtBitBlt, 1-bit slice end for FP regs */
- int start; /* start for kFmtBitBlt, 4-bit slice end for FP regs */
- } fieldLoc[4];
- ArmOpcode opcode;
- int flags;
- const char* name;
- const char* fmt;
- int size; /* Size in bytes */
+ u4 skeleton;
+ struct {
+ ArmEncodingKind kind;
+ int end; /* end for kFmtBitBlt, 1-bit slice end for FP regs */
+ int start; /* start for kFmtBitBlt, 4-bit slice end for FP regs */
+ } fieldLoc[4];
+ ArmOpcode opcode;
+ int flags;
+ const char* name;
+ const char* fmt;
+ int size; /* Size in bytes */
};
/* Keys for target-specific scheduling and other optimization hints */
enum ArmTargetOptHints {
- kMaxHoistDistance,
+ kMaxHoistDistance,
};
extern const ArmEncodingMap EncodingMap[kArmLast];
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index 89bff5e..bf7c1c7 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -35,8 +35,8 @@
void oatAdjustSpillMask(CompilationUnit* cUnit)
{
- cUnit->coreSpillMask |= (1 << rLR);
- cUnit->numCoreSpills++;
+ cUnit->coreSpillMask |= (1 << rLR);
+ cUnit->numCoreSpills++;
}
/*
@@ -47,143 +47,140 @@
*/
void oatMarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg)
{
- DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
- reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
- // Ensure fpVmapTable is large enough
- int tableSize = cUnit->fpVmapTable.size();
- for (int i = tableSize; i < (reg + 1); i++) {
- cUnit->fpVmapTable.push_back(INVALID_VREG);
- }
- // Add the current mapping
- cUnit->fpVmapTable[reg] = vReg;
- // Size of fpVmapTable is high-water mark, use to set mask
- cUnit->numFPSpills = cUnit->fpVmapTable.size();
- cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
+ DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
+ reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
+ // Ensure fpVmapTable is large enough
+ int tableSize = cUnit->fpVmapTable.size();
+ for (int i = tableSize; i < (reg + 1); i++) {
+ cUnit->fpVmapTable.push_back(INVALID_VREG);
+ }
+ // Add the current mapping
+ cUnit->fpVmapTable[reg] = vReg;
+ // Size of fpVmapTable is high-water mark, use to set mask
+ cUnit->numFPSpills = cUnit->fpVmapTable.size();
+ cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
}
void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
{
- RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
- RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
- DCHECK(info1 && info2 && info1->pair && info2->pair &&
- (info1->partner == info2->reg) &&
- (info2->partner == info1->reg));
- if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
- if (!(info1->isTemp && info2->isTemp)) {
- /* Should not happen. If it does, there's a problem in evalLoc */
- LOG(FATAL) << "Long half-temp, half-promoted";
- }
-
- info1->dirty = false;
- info2->dirty = false;
- if (SRegToVReg(cUnit, info2->sReg) <
- SRegToVReg(cUnit, info1->sReg))
- info1 = info2;
- int vReg = SRegToVReg(cUnit, info1->sReg);
- oatFlushRegWideImpl(cUnit, rSP,
- oatVRegOffset(cUnit, vReg),
- info1->reg, info1->partner);
+ RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
+ RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
+ DCHECK(info1 && info2 && info1->pair && info2->pair &&
+ (info1->partner == info2->reg) &&
+ (info2->partner == info1->reg));
+ if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
+ if (!(info1->isTemp && info2->isTemp)) {
+ /* Should not happen. If it does, there's a problem in evalLoc */
+ LOG(FATAL) << "Long half-temp, half-promoted";
}
+
+ info1->dirty = false;
+ info2->dirty = false;
+ if (SRegToVReg(cUnit, info2->sReg) <
+ SRegToVReg(cUnit, info1->sReg))
+ info1 = info2;
+ int vReg = SRegToVReg(cUnit, info1->sReg);
+ oatFlushRegWideImpl(cUnit, rSP, oatVRegOffset(cUnit, vReg),
+ info1->reg, info1->partner);
+ }
}
void oatFlushReg(CompilationUnit* cUnit, int reg)
{
- RegisterInfo* info = oatGetRegInfo(cUnit, reg);
- if (info->live && info->dirty) {
- info->dirty = false;
- int vReg = SRegToVReg(cUnit, info->sReg);
- oatFlushRegImpl(cUnit, rSP,
- oatVRegOffset(cUnit, vReg),
- reg, kWord);
- }
+ RegisterInfo* info = oatGetRegInfo(cUnit, reg);
+ if (info->live && info->dirty) {
+ info->dirty = false;
+ int vReg = SRegToVReg(cUnit, info->sReg);
+ oatFlushRegImpl(cUnit, rSP, oatVRegOffset(cUnit, vReg), reg, kWord);
+ }
}
/* Give access to the target-dependent FP register encoding to common code */
bool oatIsFpReg(int reg) {
- return FPREG(reg);
+ return FPREG(reg);
}
uint32_t oatFpRegMask() {
- return FP_REG_MASK;
+ return FP_REG_MASK;
}
/* Clobber all regs that might be used by an external C call */
void oatClobberCalleeSave(CompilationUnit *cUnit)
{
- oatClobber(cUnit, r0);
- oatClobber(cUnit, r1);
- oatClobber(cUnit, r2);
- oatClobber(cUnit, r3);
- oatClobber(cUnit, r12);
- oatClobber(cUnit, r14lr);
- oatClobber(cUnit, fr0);
- oatClobber(cUnit, fr1);
- oatClobber(cUnit, fr2);
- oatClobber(cUnit, fr3);
- oatClobber(cUnit, fr4);
- oatClobber(cUnit, fr5);
- oatClobber(cUnit, fr6);
- oatClobber(cUnit, fr7);
- oatClobber(cUnit, fr8);
- oatClobber(cUnit, fr9);
- oatClobber(cUnit, fr10);
- oatClobber(cUnit, fr11);
- oatClobber(cUnit, fr12);
- oatClobber(cUnit, fr13);
- oatClobber(cUnit, fr14);
- oatClobber(cUnit, fr15);
+ oatClobber(cUnit, r0);
+ oatClobber(cUnit, r1);
+ oatClobber(cUnit, r2);
+ oatClobber(cUnit, r3);
+ oatClobber(cUnit, r12);
+ oatClobber(cUnit, r14lr);
+ oatClobber(cUnit, fr0);
+ oatClobber(cUnit, fr1);
+ oatClobber(cUnit, fr2);
+ oatClobber(cUnit, fr3);
+ oatClobber(cUnit, fr4);
+ oatClobber(cUnit, fr5);
+ oatClobber(cUnit, fr6);
+ oatClobber(cUnit, fr7);
+ oatClobber(cUnit, fr8);
+ oatClobber(cUnit, fr9);
+ oatClobber(cUnit, fr10);
+ oatClobber(cUnit, fr11);
+ oatClobber(cUnit, fr12);
+ oatClobber(cUnit, fr13);
+ oatClobber(cUnit, fr14);
+ oatClobber(cUnit, fr15);
}
extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
{
- RegLocation res = LOC_C_RETURN_WIDE;
- res.lowReg = r2;
- res.highReg = r3;
- oatClobber(cUnit, r2);
- oatClobber(cUnit, r3);
- oatMarkInUse(cUnit, r2);
- oatMarkInUse(cUnit, r3);
- oatMarkPair(cUnit, res.lowReg, res.highReg);
- return res;
+ RegLocation res = LOC_C_RETURN_WIDE;
+ res.lowReg = r2;
+ res.highReg = r3;
+ oatClobber(cUnit, r2);
+ oatClobber(cUnit, r3);
+ oatMarkInUse(cUnit, r2);
+ oatMarkInUse(cUnit, r3);
+ oatMarkPair(cUnit, res.lowReg, res.highReg);
+ return res;
}
extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
{
- RegLocation res = LOC_C_RETURN;
- res.lowReg = r1;
- oatClobber(cUnit, r1);
- oatMarkInUse(cUnit, r1);
- return res;
+ RegLocation res = LOC_C_RETURN;
+ res.lowReg = r1;
+ oatClobber(cUnit, r1);
+ oatMarkInUse(cUnit, r1);
+ return res;
}
extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
{
- return FPREG(reg) ? &cUnit->regPool->FPRegs[reg & FP_REG_MASK]
- : &cUnit->regPool->coreRegs[reg];
+ return FPREG(reg) ? &cUnit->regPool->FPRegs[reg & FP_REG_MASK]
+ : &cUnit->regPool->coreRegs[reg];
}
/* To be used when explicitly managing register use */
extern void oatLockCallTemps(CompilationUnit* cUnit)
{
- oatLockTemp(cUnit, r0);
- oatLockTemp(cUnit, r1);
- oatLockTemp(cUnit, r2);
- oatLockTemp(cUnit, r3);
+ oatLockTemp(cUnit, r0);
+ oatLockTemp(cUnit, r1);
+ oatLockTemp(cUnit, r2);
+ oatLockTemp(cUnit, r3);
}
/* To be used when explicitly managing register use */
extern void oatFreeCallTemps(CompilationUnit* cUnit)
{
- oatFreeTemp(cUnit, r0);
- oatFreeTemp(cUnit, r1);
- oatFreeTemp(cUnit, r2);
- oatFreeTemp(cUnit, r3);
+ oatFreeTemp(cUnit, r0);
+ oatFreeTemp(cUnit, r1);
+ oatFreeTemp(cUnit, r2);
+ oatFreeTemp(cUnit, r3);
}
/* Convert an instruction to a NOP */
void oatNopLIR( LIR* lir)
{
- ((LIR*)lir)->flags.isNop = true;
+ ((LIR*)lir)->flags.isNop = true;
}
} // namespace art
diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc
index 1d1442a..aca146e 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -991,393 +991,382 @@
* instruction.
*/
AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit,
- intptr_t startAddr)
+ intptr_t startAddr)
{
- LIR* lir;
- AssemblerStatus res = kSuccess; // Assume success
+ LIR* lir;
+ AssemblerStatus res = kSuccess; // Assume success
- for (lir = (LIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
+ for (lir = (LIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
- if (lir->opcode < 0) {
- if ((lir->opcode == kPseudoPseudoAlign4) &&
- /* 1 means padding is needed */
- (lir->operands[0] == 1)) {
- cUnit->codeBuffer.push_back(PADDING_MOV_R5_R5 & 0xFF);
- cUnit->codeBuffer.push_back((PADDING_MOV_R5_R5 >> 8) & 0xFF);
- }
- continue;
- }
-
- if (lir->flags.isNop) {
- continue;
- }
-
- /*
- * For PC-relative displacements we won't know if the
- * selected instruction will work until late (i.e. - now).
- * If something doesn't fit, we must replace the short-form
- * operation with a longer-form one. Note, though, that this
- * can change code we've already processed, so we'll need to
- * re-calculate offsets and restart. To limit the number of
- * restarts, the entire list will be scanned and patched.
- * Of course, the patching itself may cause new overflows so this
- * is an iterative process.
- */
- if (lir->flags.pcRelFixup) {
- if (lir->opcode == kThumbLdrPcRel ||
- lir->opcode == kThumb2LdrPcRel12 ||
- lir->opcode == kThumbAddPcRel ||
- ((lir->opcode == kThumb2Vldrd) && (lir->operands[1] == r15pc)) ||
- ((lir->opcode == kThumb2Vldrs) && (lir->operands[1] == r15pc))) {
- /*
- * PC-relative loads are mostly used to load immediates
- * that are too large to materialize directly in one shot.
- * However, if the load displacement exceeds the limit,
- * we revert to a 2-instruction materialization sequence.
- */
- LIR *lirTarget = (LIR *) lir->target;
- intptr_t pc = (lir->offset + 4) & ~3;
- intptr_t target = lirTarget->offset;
- int delta = target - pc;
- if (delta & 0x3) {
- LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
- }
- // First, a sanity check for cases we shouldn't see now
- if (((lir->opcode == kThumbAddPcRel) && (delta > 1020)) ||
- ((lir->opcode == kThumbLdrPcRel) && (delta > 1020))) {
- // Shouldn't happen in current codegen.
- LOG(FATAL) << "Unexpected pc-rel offset " << delta;
- }
- // Now, check for the two difficult cases
- if (((lir->opcode == kThumb2LdrPcRel12) && (delta > 4091)) ||
- ((lir->opcode == kThumb2Vldrs) && (delta > 1020)) ||
- ((lir->opcode == kThumb2Vldrd) && (delta > 1020))) {
- /*
- * Note: because rLR may be used to fix up out-of-range
- * vldrs/vldrd we include REG_DEF_LR in the resource
- * masks for these instructions.
- */
- int baseReg = (lir->opcode == kThumb2LdrPcRel12) ?
- lir->operands[0] : rLR;
-
- // Add new Adr to generate the address
- LIR* newAdr = rawLIR(cUnit, lir->dalvikOffset, kThumb2Adr,
- baseReg, 0, 0, 0, 0, lir->target);
- oatInsertLIRBefore((LIR*)lir, (LIR*)newAdr);
-
- // Convert to normal load
- if (lir->opcode == kThumb2LdrPcRel12) {
- lir->opcode = kThumb2LdrRRI12;
- }
- // Change the load to be relative to the new Adr base
- lir->operands[1] = baseReg;
- lir->operands[2] = 0;
- oatSetupResourceMasks(lir);
- res = kRetryAll;
- } else {
- if ((lir->opcode == kThumb2Vldrs) ||
- (lir->opcode == kThumb2Vldrd)) {
- lir->operands[2] = delta >> 2;
- } else {
- lir->operands[1] = (lir->opcode == kThumb2LdrPcRel12) ?
- delta : delta >> 2;
- }
- }
- } else if (lir->opcode == kThumb2Cbnz || lir->opcode == kThumb2Cbz) {
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t pc = lir->offset + 4;
- intptr_t target = targetLIR->offset;
- int delta = target - pc;
- if (delta > 126 || delta < 0) {
- /*
- * Convert to cmp rx,#0 / b[eq/ne] tgt pair
- * Make new branch instruction and insert after
- */
- LIR* newInst =
- rawLIR(cUnit, lir->dalvikOffset, kThumbBCond, 0,
- (lir->opcode == kThumb2Cbz) ? kArmCondEq : kArmCondNe,
- 0, 0, 0, lir->target);
- oatInsertLIRAfter((LIR *)lir, (LIR *)newInst);
- /* Convert the cb[n]z to a cmp rx, #0 ] */
- lir->opcode = kThumbCmpRI8;
- /* operand[0] is src1 in both cb[n]z & CmpRI8 */
- lir->operands[1] = 0;
- lir->target = 0;
- oatSetupResourceMasks(lir);
- res = kRetryAll;
- } else {
- lir->operands[1] = delta >> 1;
- }
- } else if (lir->opcode == kThumb2Push ||
- lir->opcode == kThumb2Pop) {
- if (__builtin_popcount(lir->operands[0]) == 1) {
- /*
- * The standard push/pop multiple instruction
- * requires at least two registers in the list.
- * If we've got just one, switch to the single-reg
- * encoding.
- */
- lir->opcode = (lir->opcode == kThumb2Push)
- ? kThumb2Push1 : kThumb2Pop1;
- int reg = 0;
- while (lir->operands[0]) {
- if (lir->operands[0] & 0x1) {
- break;
- } else {
- reg++;
- lir->operands[0] >>= 1;
- }
- }
- lir->operands[0] = reg;
- oatSetupResourceMasks(lir);
- res = kRetryAll;
- }
- } else if (lir->opcode == kThumbBCond ||
- lir->opcode == kThumb2BCond) {
- LIR *targetLIR = (LIR *) lir->target;
- int delta = 0;
- DCHECK(targetLIR);
- intptr_t pc = lir->offset + 4;
- intptr_t target = targetLIR->offset;
- delta = target - pc;
- if ((lir->opcode == kThumbBCond) &&
- (delta > 254 || delta < -256)) {
- lir->opcode = kThumb2BCond;
- oatSetupResourceMasks(lir);
- res = kRetryAll;
- }
- lir->operands[0] = delta >> 1;
- } else if (lir->opcode == kThumb2BUncond) {
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t pc = lir->offset + 4;
- intptr_t target = targetLIR->offset;
- int delta = target - pc;
- lir->operands[0] = delta >> 1;
- if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) &&
- lir->operands[0] == 0) { // Useless branch
- lir->flags.isNop = true;
- res = kRetryAll;
- }
- } else if (lir->opcode == kThumbBUncond) {
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t pc = lir->offset + 4;
- intptr_t target = targetLIR->offset;
- int delta = target - pc;
- if (delta > 2046 || delta < -2048) {
- // Convert to Thumb2BCond w/ kArmCondAl
- lir->opcode = kThumb2BUncond;
- lir->operands[0] = 0;
- oatSetupResourceMasks(lir);
- res = kRetryAll;
- } else {
- lir->operands[0] = delta >> 1;
- if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) &&
- lir->operands[0] == -1) { // Useless branch
- lir->flags.isNop = true;
- res = kRetryAll;
- }
- }
- } else if (lir->opcode == kThumbBlx1) {
- DCHECK(NEXT_LIR(lir)->opcode == kThumbBlx2);
- /* curPC is Thumb */
- intptr_t curPC = (startAddr + lir->offset + 4) & ~3;
- intptr_t target = lir->operands[1];
-
- /* Match bit[1] in target with base */
- if (curPC & 0x2) {
- target |= 0x2;
- }
- int delta = target - curPC;
- DCHECK((delta >= -(1<<22)) && (delta <= ((1<<22)-2)));
-
- lir->operands[0] = (delta >> 12) & 0x7ff;
- NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
- } else if (lir->opcode == kThumbBl1) {
- DCHECK(NEXT_LIR(lir)->opcode == kThumbBl2);
- /* Both curPC and target are Thumb */
- intptr_t curPC = startAddr + lir->offset + 4;
- intptr_t target = lir->operands[1];
-
- int delta = target - curPC;
- DCHECK((delta >= -(1<<22)) && (delta <= ((1<<22)-2)));
-
- lir->operands[0] = (delta >> 12) & 0x7ff;
- NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
- } else if (lir->opcode == kThumb2Adr) {
- SwitchTable *tabRec = (SwitchTable*)lir->operands[2];
- LIR* target = (LIR*)lir->target;
- int targetDisp = tabRec ? tabRec->offset
- : target->offset;
- int disp = targetDisp - ((lir->offset + 4) & ~3);
- if (disp < 4096) {
- lir->operands[1] = disp;
- } else {
- // convert to ldimm16l, ldimm16h, add tgt, pc, operands[0]
- LIR *newMov16L =
- rawLIR(cUnit, lir->dalvikOffset, kThumb2MovImm16LST,
- lir->operands[0], 0, (intptr_t)lir, (intptr_t)tabRec,
- 0, lir->target);
- oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16L);
- LIR *newMov16H =
- rawLIR(cUnit, lir->dalvikOffset, kThumb2MovImm16HST,
- lir->operands[0], 0, (intptr_t)lir, (intptr_t)tabRec,
- 0, lir->target);
- oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16H);
- lir->opcode = kThumb2AddRRR;
- lir->operands[1] = rPC;
- lir->operands[2] = lir->operands[0];
- oatSetupResourceMasks(lir);
- res = kRetryAll;
- }
- } else if (lir->opcode == kThumb2MovImm16LST) {
- // operands[1] should hold disp, [2] has add, [3] has tabRec
- LIR *addPCInst = (LIR*)lir->operands[2];
- SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
- // If tabRec is null, this is a literal load. Use target
- LIR* target = (LIR*)lir->target;
- int targetDisp = tabRec ? tabRec->offset
- : target->offset;
- lir->operands[1] = (targetDisp -
- (addPCInst->offset + 4)) & 0xffff;
- } else if (lir->opcode == kThumb2MovImm16HST) {
- // operands[1] should hold disp, [2] has add, [3] has tabRec
- LIR *addPCInst = (LIR*)lir->operands[2];
- SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
- // If tabRec is null, this is a literal load. Use target
- LIR* target = (LIR*)lir->target;
- int targetDisp = tabRec ? tabRec->offset
- : target->offset;
- lir->operands[1] = ((targetDisp -
- (addPCInst->offset + 4)) >> 16) & 0xffff;
- }
- }
- /*
- * If one of the pc-relative instructions expanded we'll have
- * to make another pass. Don't bother to fully assemble the
- * instruction.
- */
- if (res != kSuccess) {
- continue;
- }
- const ArmEncodingMap *encoder = &EncodingMap[lir->opcode];
- u4 bits = encoder->skeleton;
- int i;
- for (i = 0; i < 4; i++) {
- u4 operand;
- u4 value;
- operand = lir->operands[i];
- switch (encoder->fieldLoc[i].kind) {
- case kFmtUnused:
- break;
- case kFmtFPImm:
- value = ((operand & 0xF0) >> 4) << encoder->fieldLoc[i].end;
- value |= (operand & 0x0F) << encoder->fieldLoc[i].start;
- bits |= value;
- break;
- case kFmtBrOffset:
- value = ((operand & 0x80000) >> 19) << 26;
- value |= ((operand & 0x40000) >> 18) << 11;
- value |= ((operand & 0x20000) >> 17) << 13;
- value |= ((operand & 0x1f800) >> 11) << 16;
- value |= (operand & 0x007ff);
- bits |= value;
- break;
- case kFmtShift5:
- value = ((operand & 0x1c) >> 2) << 12;
- value |= (operand & 0x03) << 6;
- bits |= value;
- break;
- case kFmtShift:
- value = ((operand & 0x70) >> 4) << 12;
- value |= (operand & 0x0f) << 4;
- bits |= value;
- break;
- case kFmtBWidth:
- value = operand - 1;
- bits |= value;
- break;
- case kFmtLsb:
- value = ((operand & 0x1c) >> 2) << 12;
- value |= (operand & 0x03) << 6;
- bits |= value;
- break;
- case kFmtImm6:
- value = ((operand & 0x20) >> 5) << 9;
- value |= (operand & 0x1f) << 3;
- bits |= value;
- break;
- case kFmtBitBlt:
- value = (operand << encoder->fieldLoc[i].start) &
- ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
- bits |= value;
- break;
- case kFmtDfp: {
- DCHECK(DOUBLEREG(operand));
- DCHECK((operand & 0x1) == 0);
- int regName = (operand & FP_REG_MASK) >> 1;
- /* Snag the 1-bit slice and position it */
- value = ((regName & 0x10) >> 4) <<
- encoder->fieldLoc[i].end;
- /* Extract and position the 4-bit slice */
- value |= (regName & 0x0f) <<
- encoder->fieldLoc[i].start;
- bits |= value;
- break;
- }
- case kFmtSfp:
- DCHECK(SINGLEREG(operand));
- /* Snag the 1-bit slice and position it */
- value = (operand & 0x1) <<
- encoder->fieldLoc[i].end;
- /* Extract and position the 4-bit slice */
- value |= ((operand & 0x1e) >> 1) <<
- encoder->fieldLoc[i].start;
- bits |= value;
- break;
- case kFmtImm12:
- case kFmtModImm:
- value = ((operand & 0x800) >> 11) << 26;
- value |= ((operand & 0x700) >> 8) << 12;
- value |= operand & 0x0ff;
- bits |= value;
- break;
- case kFmtImm16:
- value = ((operand & 0x0800) >> 11) << 26;
- value |= ((operand & 0xf000) >> 12) << 16;
- value |= ((operand & 0x0700) >> 8) << 12;
- value |= operand & 0x0ff;
- bits |= value;
- break;
- case kFmtOff24: {
- u4 signbit = (operand >> 31) & 0x1;
- u4 i1 = (operand >> 22) & 0x1;
- u4 i2 = (operand >> 21) & 0x1;
- u4 imm10 = (operand >> 11) & 0x03ff;
- u4 imm11 = operand & 0x07ff;
- u4 j1 = (i1 ^ signbit) ? 0 : 1;
- u4 j2 = (i2 ^ signbit) ? 0 : 1;
- value = (signbit << 26) | (j1 << 13) | (j2 << 11) |
- (imm10 << 16) | imm11;
- bits |= value;
- }
- break;
- default:
- LOG(FATAL) << "Bad fmt:" << (int)encoder->fieldLoc[i].kind;
- }
- }
- if (encoder->size == 4) {
- cUnit->codeBuffer.push_back((bits >> 16) & 0xff);
- cUnit->codeBuffer.push_back((bits >> 24) & 0xff);
- }
- cUnit->codeBuffer.push_back(bits & 0xff);
- cUnit->codeBuffer.push_back((bits >> 8) & 0xff);
+ if (lir->opcode < 0) {
+ /* 1 means padding is needed */
+ if ((lir->opcode == kPseudoPseudoAlign4) && (lir->operands[0] == 1)) {
+ cUnit->codeBuffer.push_back(PADDING_MOV_R5_R5 & 0xFF);
+ cUnit->codeBuffer.push_back((PADDING_MOV_R5_R5 >> 8) & 0xFF);
+ }
+ continue;
}
- return res;
+
+ if (lir->flags.isNop) {
+ continue;
+ }
+
+ /*
+ * For PC-relative displacements we won't know if the
+ * selected instruction will work until late (i.e. - now).
+ * If something doesn't fit, we must replace the short-form
+ * operation with a longer-form one. Note, though, that this
+ * can change code we've already processed, so we'll need to
+ * re-calculate offsets and restart. To limit the number of
+ * restarts, the entire list will be scanned and patched.
+ * Of course, the patching itself may cause new overflows so this
+ * is an iterative process.
+ */
+ if (lir->flags.pcRelFixup) {
+ if (lir->opcode == kThumbLdrPcRel ||
+ lir->opcode == kThumb2LdrPcRel12 ||
+ lir->opcode == kThumbAddPcRel ||
+ ((lir->opcode == kThumb2Vldrd) && (lir->operands[1] == r15pc)) ||
+ ((lir->opcode == kThumb2Vldrs) && (lir->operands[1] == r15pc))) {
+ /*
+ * PC-relative loads are mostly used to load immediates
+ * that are too large to materialize directly in one shot.
+ * However, if the load displacement exceeds the limit,
+ * we revert to a 2-instruction materialization sequence.
+ */
+ LIR *lirTarget = (LIR *) lir->target;
+ intptr_t pc = (lir->offset + 4) & ~3;
+ intptr_t target = lirTarget->offset;
+ int delta = target - pc;
+ if (delta & 0x3) {
+ LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
+ }
+ // First, a sanity check for cases we shouldn't see now
+ if (((lir->opcode == kThumbAddPcRel) && (delta > 1020)) ||
+ ((lir->opcode == kThumbLdrPcRel) && (delta > 1020))) {
+ // Shouldn't happen in current codegen.
+ LOG(FATAL) << "Unexpected pc-rel offset " << delta;
+ }
+ // Now, check for the two difficult cases
+ if (((lir->opcode == kThumb2LdrPcRel12) && (delta > 4091)) ||
+ ((lir->opcode == kThumb2Vldrs) && (delta > 1020)) ||
+ ((lir->opcode == kThumb2Vldrd) && (delta > 1020))) {
+ /*
+ * Note: because rLR may be used to fix up out-of-range
+ * vldrs/vldrd we include REG_DEF_LR in the resource
+ * masks for these instructions.
+ */
+ int baseReg = (lir->opcode == kThumb2LdrPcRel12) ?
+ lir->operands[0] : rLR;
+
+ // Add new Adr to generate the address
+ LIR* newAdr = rawLIR(cUnit, lir->dalvikOffset, kThumb2Adr,
+ baseReg, 0, 0, 0, 0, lir->target);
+ oatInsertLIRBefore((LIR*)lir, (LIR*)newAdr);
+
+ // Convert to normal load
+ if (lir->opcode == kThumb2LdrPcRel12) {
+ lir->opcode = kThumb2LdrRRI12;
+ }
+ // Change the load to be relative to the new Adr base
+ lir->operands[1] = baseReg;
+ lir->operands[2] = 0;
+ oatSetupResourceMasks(lir);
+ res = kRetryAll;
+ } else {
+ if ((lir->opcode == kThumb2Vldrs) ||
+ (lir->opcode == kThumb2Vldrd)) {
+ lir->operands[2] = delta >> 2;
+ } else {
+ lir->operands[1] = (lir->opcode == kThumb2LdrPcRel12) ? delta :
+ delta >> 2;
+ }
+ }
+ } else if (lir->opcode == kThumb2Cbnz || lir->opcode == kThumb2Cbz) {
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
+ int delta = target - pc;
+ if (delta > 126 || delta < 0) {
+ /*
+ * Convert to cmp rx,#0 / b[eq/ne] tgt pair
+ * Make new branch instruction and insert after
+ */
+ LIR* newInst =
+ rawLIR(cUnit, lir->dalvikOffset, kThumbBCond, 0,
+ (lir->opcode == kThumb2Cbz) ? kArmCondEq : kArmCondNe,
+ 0, 0, 0, lir->target);
+ oatInsertLIRAfter((LIR *)lir, (LIR *)newInst);
+ /* Convert the cb[n]z to a cmp rx, #0 ] */
+ lir->opcode = kThumbCmpRI8;
+ /* operand[0] is src1 in both cb[n]z & CmpRI8 */
+ lir->operands[1] = 0;
+ lir->target = 0;
+ oatSetupResourceMasks(lir);
+ res = kRetryAll;
+ } else {
+ lir->operands[1] = delta >> 1;
+ }
+ } else if (lir->opcode == kThumb2Push || lir->opcode == kThumb2Pop) {
+ if (__builtin_popcount(lir->operands[0]) == 1) {
+ /*
+ * The standard push/pop multiple instruction
+ * requires at least two registers in the list.
+ * If we've got just one, switch to the single-reg
+ * encoding.
+ */
+ lir->opcode = (lir->opcode == kThumb2Push) ? kThumb2Push1 :
+ kThumb2Pop1;
+ int reg = 0;
+ while (lir->operands[0]) {
+ if (lir->operands[0] & 0x1) {
+ break;
+ } else {
+ reg++;
+ lir->operands[0] >>= 1;
+ }
+ }
+ lir->operands[0] = reg;
+ oatSetupResourceMasks(lir);
+ res = kRetryAll;
+ }
+ } else if (lir->opcode == kThumbBCond || lir->opcode == kThumb2BCond) {
+ LIR *targetLIR = (LIR *) lir->target;
+ int delta = 0;
+ DCHECK(targetLIR);
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
+ delta = target - pc;
+ if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) {
+ lir->opcode = kThumb2BCond;
+ oatSetupResourceMasks(lir);
+ res = kRetryAll;
+ }
+ lir->operands[0] = delta >> 1;
+ } else if (lir->opcode == kThumb2BUncond) {
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
+ int delta = target - pc;
+ lir->operands[0] = delta >> 1;
+ if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) &&
+ lir->operands[0] == 0) { // Useless branch
+ lir->flags.isNop = true;
+ res = kRetryAll;
+ }
+ } else if (lir->opcode == kThumbBUncond) {
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
+ int delta = target - pc;
+ if (delta > 2046 || delta < -2048) {
+ // Convert to Thumb2BCond w/ kArmCondAl
+ lir->opcode = kThumb2BUncond;
+ lir->operands[0] = 0;
+ oatSetupResourceMasks(lir);
+ res = kRetryAll;
+ } else {
+ lir->operands[0] = delta >> 1;
+ if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) &&
+ lir->operands[0] == -1) { // Useless branch
+ lir->flags.isNop = true;
+ res = kRetryAll;
+ }
+ }
+ } else if (lir->opcode == kThumbBlx1) {
+ DCHECK(NEXT_LIR(lir)->opcode == kThumbBlx2);
+ /* curPC is Thumb */
+ intptr_t curPC = (startAddr + lir->offset + 4) & ~3;
+ intptr_t target = lir->operands[1];
+
+ /* Match bit[1] in target with base */
+ if (curPC & 0x2) {
+ target |= 0x2;
+ }
+ int delta = target - curPC;
+ DCHECK((delta >= -(1<<22)) && (delta <= ((1<<22)-2)));
+
+ lir->operands[0] = (delta >> 12) & 0x7ff;
+ NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
+ } else if (lir->opcode == kThumbBl1) {
+ DCHECK(NEXT_LIR(lir)->opcode == kThumbBl2);
+ /* Both curPC and target are Thumb */
+ intptr_t curPC = startAddr + lir->offset + 4;
+ intptr_t target = lir->operands[1];
+
+ int delta = target - curPC;
+ DCHECK((delta >= -(1<<22)) && (delta <= ((1<<22)-2)));
+
+ lir->operands[0] = (delta >> 12) & 0x7ff;
+ NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
+ } else if (lir->opcode == kThumb2Adr) {
+ SwitchTable *tabRec = (SwitchTable*)lir->operands[2];
+ LIR* target = (LIR*)lir->target;
+ int targetDisp = tabRec ? tabRec->offset
+ : target->offset;
+ int disp = targetDisp - ((lir->offset + 4) & ~3);
+ if (disp < 4096) {
+ lir->operands[1] = disp;
+ } else {
+ // convert to ldimm16l, ldimm16h, add tgt, pc, operands[0]
+ LIR *newMov16L =
+ rawLIR(cUnit, lir->dalvikOffset, kThumb2MovImm16LST,
+ lir->operands[0], 0, (intptr_t)lir, (intptr_t)tabRec,
+ 0, lir->target);
+ oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16L);
+ LIR *newMov16H =
+ rawLIR(cUnit, lir->dalvikOffset, kThumb2MovImm16HST,
+ lir->operands[0], 0, (intptr_t)lir, (intptr_t)tabRec,
+ 0, lir->target);
+ oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16H);
+ lir->opcode = kThumb2AddRRR;
+ lir->operands[1] = rPC;
+ lir->operands[2] = lir->operands[0];
+ oatSetupResourceMasks(lir);
+ res = kRetryAll;
+ }
+ } else if (lir->opcode == kThumb2MovImm16LST) {
+ // operands[1] should hold disp, [2] has add, [3] has tabRec
+ LIR *addPCInst = (LIR*)lir->operands[2];
+ SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
+ // If tabRec is null, this is a literal load. Use target
+ LIR* target = (LIR*)lir->target;
+ int targetDisp = tabRec ? tabRec->offset : target->offset;
+ lir->operands[1] = (targetDisp - (addPCInst->offset + 4)) & 0xffff;
+ } else if (lir->opcode == kThumb2MovImm16HST) {
+ // operands[1] should hold disp, [2] has add, [3] has tabRec
+ LIR *addPCInst = (LIR*)lir->operands[2];
+ SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
+ // If tabRec is null, this is a literal load. Use target
+ LIR* target = (LIR*)lir->target;
+ int targetDisp = tabRec ? tabRec->offset : target->offset;
+ lir->operands[1] =
+ ((targetDisp - (addPCInst->offset + 4)) >> 16) & 0xffff;
+ }
+ }
+ /*
+ * If one of the pc-relative instructions expanded we'll have
+ * to make another pass. Don't bother to fully assemble the
+ * instruction.
+ */
+ if (res != kSuccess) {
+ continue;
+ }
+ const ArmEncodingMap *encoder = &EncodingMap[lir->opcode];
+ u4 bits = encoder->skeleton;
+ int i;
+ for (i = 0; i < 4; i++) {
+ u4 operand;
+ u4 value;
+ operand = lir->operands[i];
+ switch (encoder->fieldLoc[i].kind) {
+ case kFmtUnused:
+ break;
+ case kFmtFPImm:
+ value = ((operand & 0xF0) >> 4) << encoder->fieldLoc[i].end;
+ value |= (operand & 0x0F) << encoder->fieldLoc[i].start;
+ bits |= value;
+ break;
+ case kFmtBrOffset:
+ value = ((operand & 0x80000) >> 19) << 26;
+ value |= ((operand & 0x40000) >> 18) << 11;
+ value |= ((operand & 0x20000) >> 17) << 13;
+ value |= ((operand & 0x1f800) >> 11) << 16;
+ value |= (operand & 0x007ff);
+ bits |= value;
+ break;
+ case kFmtShift5:
+ value = ((operand & 0x1c) >> 2) << 12;
+ value |= (operand & 0x03) << 6;
+ bits |= value;
+ break;
+ case kFmtShift:
+ value = ((operand & 0x70) >> 4) << 12;
+ value |= (operand & 0x0f) << 4;
+ bits |= value;
+ break;
+ case kFmtBWidth:
+ value = operand - 1;
+ bits |= value;
+ break;
+ case kFmtLsb:
+ value = ((operand & 0x1c) >> 2) << 12;
+ value |= (operand & 0x03) << 6;
+ bits |= value;
+ break;
+ case kFmtImm6:
+ value = ((operand & 0x20) >> 5) << 9;
+ value |= (operand & 0x1f) << 3;
+ bits |= value;
+ break;
+ case kFmtBitBlt:
+ value = (operand << encoder->fieldLoc[i].start) &
+ ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
+ bits |= value;
+ break;
+ case kFmtDfp: {
+ DCHECK(DOUBLEREG(operand));
+ DCHECK((operand & 0x1) == 0);
+ int regName = (operand & FP_REG_MASK) >> 1;
+ /* Snag the 1-bit slice and position it */
+ value = ((regName & 0x10) >> 4) << encoder->fieldLoc[i].end;
+ /* Extract and position the 4-bit slice */
+ value |= (regName & 0x0f) << encoder->fieldLoc[i].start;
+ bits |= value;
+ break;
+ }
+ case kFmtSfp:
+ DCHECK(SINGLEREG(operand));
+ /* Snag the 1-bit slice and position it */
+ value = (operand & 0x1) << encoder->fieldLoc[i].end;
+ /* Extract and position the 4-bit slice */
+ value |= ((operand & 0x1e) >> 1) << encoder->fieldLoc[i].start;
+ bits |= value;
+ break;
+ case kFmtImm12:
+ case kFmtModImm:
+ value = ((operand & 0x800) >> 11) << 26;
+ value |= ((operand & 0x700) >> 8) << 12;
+ value |= operand & 0x0ff;
+ bits |= value;
+ break;
+ case kFmtImm16:
+ value = ((operand & 0x0800) >> 11) << 26;
+ value |= ((operand & 0xf000) >> 12) << 16;
+ value |= ((operand & 0x0700) >> 8) << 12;
+ value |= operand & 0x0ff;
+ bits |= value;
+ break;
+ case kFmtOff24: {
+ u4 signbit = (operand >> 31) & 0x1;
+ u4 i1 = (operand >> 22) & 0x1;
+ u4 i2 = (operand >> 21) & 0x1;
+ u4 imm10 = (operand >> 11) & 0x03ff;
+ u4 imm11 = operand & 0x07ff;
+ u4 j1 = (i1 ^ signbit) ? 0 : 1;
+ u4 j2 = (i2 ^ signbit) ? 0 : 1;
+ value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm10 << 16) |
+ imm11;
+ bits |= value;
+ }
+ break;
+ default:
+ LOG(FATAL) << "Bad fmt:" << (int)encoder->fieldLoc[i].kind;
+ }
+ }
+ if (encoder->size == 4) {
+ cUnit->codeBuffer.push_back((bits >> 16) & 0xff);
+ cUnit->codeBuffer.push_back((bits >> 24) & 0xff);
+ }
+ cUnit->codeBuffer.push_back(bits & 0xff);
+ cUnit->codeBuffer.push_back((bits >> 8) & 0xff);
+ }
+ return res;
}
int oatGetInsnSize(LIR* lir)
{
- return EncodingMap[lir->opcode].size;
+ return EncodingMap[lir->opcode].size;
}
/*
@@ -1385,29 +1374,29 @@
*/
int oatAssignInsnOffsets(CompilationUnit* cUnit)
{
- LIR* armLIR;
- int offset = 0;
+ LIR* armLIR;
+ int offset = 0;
- for (armLIR = (LIR *) cUnit->firstLIRInsn;
- armLIR;
- armLIR = NEXT_LIR(armLIR)) {
- armLIR->offset = offset;
- if (armLIR->opcode >= 0) {
- if (!armLIR->flags.isNop) {
- offset += armLIR->flags.size;
- }
- } else if (armLIR->opcode == kPseudoPseudoAlign4) {
- if (offset & 0x2) {
- offset += 2;
- armLIR->operands[0] = 1;
- } else {
- armLIR->operands[0] = 0;
- }
- }
- /* Pseudo opcodes don't consume space */
+ for (armLIR = (LIR *) cUnit->firstLIRInsn;
+ armLIR;
+ armLIR = NEXT_LIR(armLIR)) {
+ armLIR->offset = offset;
+ if (armLIR->opcode >= 0) {
+ if (!armLIR->flags.isNop) {
+ offset += armLIR->flags.size;
+ }
+ } else if (armLIR->opcode == kPseudoPseudoAlign4) {
+ if (offset & 0x2) {
+ offset += 2;
+ armLIR->operands[0] = 1;
+ } else {
+ armLIR->operands[0] = 0;
+ }
}
+ /* Pseudo opcodes don't consume space */
+ }
- return offset;
+ return offset;
}
} // namespace art
diff --git a/src/compiler/codegen/arm/Codegen.h b/src/compiler/codegen/arm/Codegen.h
index f467d4f..10f5e38 100644
--- a/src/compiler/codegen/arm/Codegen.h
+++ b/src/compiler/codegen/arm/Codegen.h
@@ -36,12 +36,12 @@
/* Forward declaraton the portable versions due to circular dependency */
bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2);
+ RegLocation rlDest, RegLocation rlSrc1,
+ RegLocation rlSrc2);
bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2);
+ RegLocation rlDest, RegLocation rlSrc1,
+ RegLocation rlSrc2);
bool genConversionPortable(CompilationUnit* cUnit, MIR* mir);
@@ -64,10 +64,10 @@
*/
inline RegisterClass oatRegClassBySize(OpSize size)
{
- return (size == kUnsignedHalf ||
- size == kSignedHalf ||
- size == kUnsignedByte ||
- size == kSignedByte ) ? kCoreReg : kAnyReg;
+ return (size == kUnsignedHalf ||
+ size == kSignedHalf ||
+ size == kUnsignedByte ||
+ size == kSignedByte ) ? kCoreReg : kAnyReg;
}
/*
@@ -79,12 +79,12 @@
*/
#if __BYTE_ORDER == __LITTLE_ENDIAN
inline s4 s4FromSwitchData(const void* switchData) {
- return *(s4*) switchData;
+ return *(s4*) switchData;
}
#else
inline s4 s4FromSwitchData(const void* switchData) {
- u2* data = switchData;
- return data[0] | (((s4) data[1]) << 16);
+ u2* data = switchData;
+ return data[0] | (((s4) data[1]) << 16);
}
#endif
@@ -92,7 +92,6 @@
extern void oatSetupResourceMasks(LIR* lir);
-extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest,
- int rSrc);
+extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc);
} // namespace art
diff --git a/src/compiler/codegen/arm/FP/Thumb2VFP.cc b/src/compiler/codegen/arm/FP/Thumb2VFP.cc
index 380c014..fbce1f5 100644
--- a/src/compiler/codegen/arm/FP/Thumb2VFP.cc
+++ b/src/compiler/codegen/arm/FP/Thumb2VFP.cc
@@ -19,280 +19,277 @@
bool genArithOpFloat(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
RegLocation rlSrc1, RegLocation rlSrc2)
{
- int op = kThumbBkpt;
- RegLocation rlResult;
+ int op = kThumbBkpt;
+ RegLocation rlResult;
- /*
- * Don't attempt to optimize register usage since these opcodes call out to
- * the handlers.
- */
- switch (mir->dalvikInsn.opcode) {
- case Instruction::ADD_FLOAT_2ADDR:
- case Instruction::ADD_FLOAT:
- op = kThumb2Vadds;
- break;
- case Instruction::SUB_FLOAT_2ADDR:
- case Instruction::SUB_FLOAT:
- op = kThumb2Vsubs;
- break;
- case Instruction::DIV_FLOAT_2ADDR:
- case Instruction::DIV_FLOAT:
- op = kThumb2Vdivs;
- break;
- case Instruction::MUL_FLOAT_2ADDR:
- case Instruction::MUL_FLOAT:
- op = kThumb2Vmuls;
- break;
- case Instruction::REM_FLOAT_2ADDR:
- case Instruction::REM_FLOAT:
- case Instruction::NEG_FLOAT: {
- return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1,
- rlSrc2);
- }
- default:
- return true;
+ /*
+ * Don't attempt to optimize register usage since these opcodes call out to
+ * the handlers.
+ */
+ switch (mir->dalvikInsn.opcode) {
+ case Instruction::ADD_FLOAT_2ADDR:
+ case Instruction::ADD_FLOAT:
+ op = kThumb2Vadds;
+ break;
+ case Instruction::SUB_FLOAT_2ADDR:
+ case Instruction::SUB_FLOAT:
+ op = kThumb2Vsubs;
+ break;
+ case Instruction::DIV_FLOAT_2ADDR:
+ case Instruction::DIV_FLOAT:
+ op = kThumb2Vdivs;
+ break;
+ case Instruction::MUL_FLOAT_2ADDR:
+ case Instruction::MUL_FLOAT:
+ op = kThumb2Vmuls;
+ break;
+ case Instruction::REM_FLOAT_2ADDR:
+ case Instruction::REM_FLOAT:
+ case Instruction::NEG_FLOAT: {
+ return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
}
- rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
- rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
- rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR3(cUnit, (ArmOpcode)op, rlResult.lowReg, rlSrc1.lowReg,
- rlSrc2.lowReg);
- storeValue(cUnit, rlDest, rlResult);
- return false;
+ default:
+ return true;
+ }
+ rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
+ rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
+ rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
+ newLIR3(cUnit, (ArmOpcode)op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
+ storeValue(cUnit, rlDest, rlResult);
+ return false;
}
bool genArithOpDouble(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
RegLocation rlSrc1, RegLocation rlSrc2)
{
- int op = kThumbBkpt;
- RegLocation rlResult;
+ int op = kThumbBkpt;
+ RegLocation rlResult;
- switch (mir->dalvikInsn.opcode) {
- case Instruction::ADD_DOUBLE_2ADDR:
- case Instruction::ADD_DOUBLE:
- op = kThumb2Vaddd;
- break;
- case Instruction::SUB_DOUBLE_2ADDR:
- case Instruction::SUB_DOUBLE:
- op = kThumb2Vsubd;
- break;
- case Instruction::DIV_DOUBLE_2ADDR:
- case Instruction::DIV_DOUBLE:
- op = kThumb2Vdivd;
- break;
- case Instruction::MUL_DOUBLE_2ADDR:
- case Instruction::MUL_DOUBLE:
- op = kThumb2Vmuld;
- break;
- case Instruction::REM_DOUBLE_2ADDR:
- case Instruction::REM_DOUBLE:
- case Instruction::NEG_DOUBLE: {
- return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
- rlSrc2);
- }
- default:
- return true;
+ switch (mir->dalvikInsn.opcode) {
+ case Instruction::ADD_DOUBLE_2ADDR:
+ case Instruction::ADD_DOUBLE:
+ op = kThumb2Vaddd;
+ break;
+ case Instruction::SUB_DOUBLE_2ADDR:
+ case Instruction::SUB_DOUBLE:
+ op = kThumb2Vsubd;
+ break;
+ case Instruction::DIV_DOUBLE_2ADDR:
+ case Instruction::DIV_DOUBLE:
+ op = kThumb2Vdivd;
+ break;
+ case Instruction::MUL_DOUBLE_2ADDR:
+ case Instruction::MUL_DOUBLE:
+ op = kThumb2Vmuld;
+ break;
+ case Instruction::REM_DOUBLE_2ADDR:
+ case Instruction::REM_DOUBLE:
+ case Instruction::NEG_DOUBLE: {
+ return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
}
+ default:
+ return true;
+ }
- rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
- DCHECK(rlSrc1.wide);
- rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
- DCHECK(rlSrc2.wide);
- rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
- DCHECK(rlDest.wide);
- DCHECK(rlResult.wide);
- newLIR3(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
- S2D(rlSrc1.lowReg, rlSrc1.highReg),
- S2D(rlSrc2.lowReg, rlSrc2.highReg));
- storeValueWide(cUnit, rlDest, rlResult);
- return false;
+ rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
+ DCHECK(rlSrc1.wide);
+ rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
+ DCHECK(rlSrc2.wide);
+ rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
+ DCHECK(rlDest.wide);
+ DCHECK(rlResult.wide);
+ newLIR3(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
+ S2D(rlSrc1.lowReg, rlSrc1.highReg),
+ S2D(rlSrc2.lowReg, rlSrc2.highReg));
+ storeValueWide(cUnit, rlDest, rlResult);
+ return false;
}
bool genConversion(CompilationUnit* cUnit, MIR* mir)
{
- Instruction::Code opcode = mir->dalvikInsn.opcode;
- int op = kThumbBkpt;
- bool longSrc = false;
- bool longDest = false;
- int srcReg;
- RegLocation rlSrc;
- RegLocation rlDest;
- RegLocation rlResult;
+ Instruction::Code opcode = mir->dalvikInsn.opcode;
+ int op = kThumbBkpt;
+ bool longSrc = false;
+ bool longDest = false;
+ int srcReg;
+ RegLocation rlSrc;
+ RegLocation rlDest;
+ RegLocation rlResult;
- switch (opcode) {
- case Instruction::INT_TO_FLOAT:
- longSrc = false;
- longDest = false;
- op = kThumb2VcvtIF;
- break;
- case Instruction::FLOAT_TO_INT:
- longSrc = false;
- longDest = false;
- op = kThumb2VcvtFI;
- break;
- case Instruction::DOUBLE_TO_FLOAT:
- longSrc = true;
- longDest = false;
- op = kThumb2VcvtDF;
- break;
- case Instruction::FLOAT_TO_DOUBLE:
- longSrc = false;
- longDest = true;
- op = kThumb2VcvtFd;
- break;
- case Instruction::INT_TO_DOUBLE:
- longSrc = false;
- longDest = true;
- op = kThumb2VcvtID;
- break;
- case Instruction::DOUBLE_TO_INT:
- longSrc = true;
- longDest = false;
- op = kThumb2VcvtDI;
- break;
- case Instruction::LONG_TO_DOUBLE:
- case Instruction::FLOAT_TO_LONG:
- case Instruction::LONG_TO_FLOAT:
- case Instruction::DOUBLE_TO_LONG:
- return genConversionPortable(cUnit, mir);
- default:
- return true;
- }
- if (longSrc) {
- rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
- srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
- } else {
- rlSrc = oatGetSrc(cUnit, mir, 0);
- rlSrc = loadValue(cUnit, rlSrc, kFPReg);
- srcReg = rlSrc.lowReg;
- }
- if (longDest) {
- rlDest = oatGetDestWide(cUnit, mir, 0, 1);
- rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR2(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
- srcReg);
- storeValueWide(cUnit, rlDest, rlResult);
- } else {
- rlDest = oatGetDest(cUnit, mir, 0);
- rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
- storeValue(cUnit, rlDest, rlResult);
- }
- return false;
+ switch (opcode) {
+ case Instruction::INT_TO_FLOAT:
+ longSrc = false;
+ longDest = false;
+ op = kThumb2VcvtIF;
+ break;
+ case Instruction::FLOAT_TO_INT:
+ longSrc = false;
+ longDest = false;
+ op = kThumb2VcvtFI;
+ break;
+ case Instruction::DOUBLE_TO_FLOAT:
+ longSrc = true;
+ longDest = false;
+ op = kThumb2VcvtDF;
+ break;
+ case Instruction::FLOAT_TO_DOUBLE:
+ longSrc = false;
+ longDest = true;
+ op = kThumb2VcvtFd;
+ break;
+ case Instruction::INT_TO_DOUBLE:
+ longSrc = false;
+ longDest = true;
+ op = kThumb2VcvtID;
+ break;
+ case Instruction::DOUBLE_TO_INT:
+ longSrc = true;
+ longDest = false;
+ op = kThumb2VcvtDI;
+ break;
+ case Instruction::LONG_TO_DOUBLE:
+ case Instruction::FLOAT_TO_LONG:
+ case Instruction::LONG_TO_FLOAT:
+ case Instruction::DOUBLE_TO_LONG:
+ return genConversionPortable(cUnit, mir);
+ default:
+ return true;
+ }
+ if (longSrc) {
+ rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+ rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
+ srcReg = S2D(rlSrc.lowReg, rlSrc.highReg);
+ } else {
+ rlSrc = oatGetSrc(cUnit, mir, 0);
+ rlSrc = loadValue(cUnit, rlSrc, kFPReg);
+ srcReg = rlSrc.lowReg;
+ }
+ if (longDest) {
+ rlDest = oatGetDestWide(cUnit, mir, 0, 1);
+ rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
+ newLIR2(cUnit, (ArmOpcode)op, S2D(rlResult.lowReg, rlResult.highReg),
+ srcReg);
+ storeValueWide(cUnit, rlDest, rlResult);
+ } else {
+ rlDest = oatGetDest(cUnit, mir, 0);
+ rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
+ newLIR2(cUnit, (ArmOpcode)op, rlResult.lowReg, srcReg);
+ storeValue(cUnit, rlDest, rlResult);
+ }
+ return false;
}
void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
bool gtBias, bool isDouble)
{
- LIR* labelList = (LIR*)cUnit->blockLabelList;
- LIR* target = &labelList[bb->taken->id];
- RegLocation rlSrc1;
- RegLocation rlSrc2;
- if (isDouble) {
- rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1);
- rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3);
- rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
- rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
- newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
- S2D(rlSrc2.lowReg, rlSrc2.highReg));
- } else {
- rlSrc1 = oatGetSrc(cUnit, mir, 0);
- rlSrc2 = oatGetSrc(cUnit, mir, 1);
- rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
- rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
- newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
- }
- newLIR0(cUnit, kThumb2Fmstat);
- ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
- switch(ccode) {
- case kCondEq:
- case kCondNe:
- break;
- case kCondLt:
- if (gtBias) {
- ccode = kCondMi;
- }
- break;
- case kCondLe:
- if (gtBias) {
- ccode = kCondLs;
- }
- break;
- case kCondGt:
- if (gtBias) {
- ccode = kCondHi;
- }
- break;
- case kCondGe:
- if (gtBias) {
- ccode = kCondCs;
- }
- break;
- default:
- LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
- }
- opCondBranch(cUnit, ccode, target);
+ LIR* labelList = (LIR*)cUnit->blockLabelList;
+ LIR* target = &labelList[bb->taken->id];
+ RegLocation rlSrc1;
+ RegLocation rlSrc2;
+ if (isDouble) {
+ rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1);
+ rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3);
+ rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
+ rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
+ newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
+ S2D(rlSrc2.lowReg, rlSrc2.highReg));
+ } else {
+ rlSrc1 = oatGetSrc(cUnit, mir, 0);
+ rlSrc2 = oatGetSrc(cUnit, mir, 1);
+ rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
+ rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
+ newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
+ }
+ newLIR0(cUnit, kThumb2Fmstat);
+ ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
+ switch(ccode) {
+ case kCondEq:
+ case kCondNe:
+ break;
+ case kCondLt:
+ if (gtBias) {
+ ccode = kCondMi;
+ }
+ break;
+ case kCondLe:
+ if (gtBias) {
+ ccode = kCondLs;
+ }
+ break;
+ case kCondGt:
+ if (gtBias) {
+ ccode = kCondHi;
+ }
+ break;
+ case kCondGe:
+ if (gtBias) {
+ ccode = kCondCs;
+ }
+ break;
+ default:
+ LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
+ }
+ opCondBranch(cUnit, ccode, target);
}
bool genCmpFP(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
- RegLocation rlSrc1, RegLocation rlSrc2)
+ RegLocation rlSrc1, RegLocation rlSrc2)
{
- bool isDouble;
- int defaultResult;
- RegLocation rlResult;
+ bool isDouble;
+ int defaultResult;
+ RegLocation rlResult;
- switch (mir->dalvikInsn.opcode) {
- case Instruction::CMPL_FLOAT:
- isDouble = false;
- defaultResult = -1;
- break;
- case Instruction::CMPG_FLOAT:
- isDouble = false;
- defaultResult = 1;
- break;
- case Instruction::CMPL_DOUBLE:
- isDouble = true;
- defaultResult = -1;
- break;
- case Instruction::CMPG_DOUBLE:
- isDouble = true;
- defaultResult = 1;
- break;
- default:
- return true;
- }
- if (isDouble) {
- rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
- rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
- oatClobberSReg(cUnit, rlDest.sRegLow);
- rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- loadConstant(cUnit, rlResult.lowReg, defaultResult);
- newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
- S2D(rlSrc2.lowReg, rlSrc2.highReg));
- } else {
- rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
- rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
- oatClobberSReg(cUnit, rlDest.sRegLow);
- rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- loadConstant(cUnit, rlResult.lowReg, defaultResult);
- newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
- }
- DCHECK(!FPREG(rlResult.lowReg));
- newLIR0(cUnit, kThumb2Fmstat);
+ switch (mir->dalvikInsn.opcode) {
+ case Instruction::CMPL_FLOAT:
+ isDouble = false;
+ defaultResult = -1;
+ break;
+ case Instruction::CMPG_FLOAT:
+ isDouble = false;
+ defaultResult = 1;
+ break;
+ case Instruction::CMPL_DOUBLE:
+ isDouble = true;
+ defaultResult = -1;
+ break;
+ case Instruction::CMPG_DOUBLE:
+ isDouble = true;
+ defaultResult = 1;
+ break;
+ default:
+ return true;
+ }
+ if (isDouble) {
+ rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
+ rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
+ oatClobberSReg(cUnit, rlDest.sRegLow);
+ rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ loadConstant(cUnit, rlResult.lowReg, defaultResult);
+ newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
+ S2D(rlSrc2.lowReg, rlSrc2.highReg));
+ } else {
+ rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
+ rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
+ oatClobberSReg(cUnit, rlDest.sRegLow);
+ rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ loadConstant(cUnit, rlResult.lowReg, defaultResult);
+ newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
+ }
+ DCHECK(!FPREG(rlResult.lowReg));
+ newLIR0(cUnit, kThumb2Fmstat);
- opIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
- newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
- modifiedImmediate(-defaultResult)); // Must not alter ccodes
- genBarrier(cUnit);
+ opIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, "");
+ newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg,
+ modifiedImmediate(-defaultResult)); // Must not alter ccodes
+ genBarrier(cUnit);
- opIT(cUnit, kArmCondEq, "");
- loadConstant(cUnit, rlResult.lowReg, 0);
- genBarrier(cUnit);
+ opIT(cUnit, kArmCondEq, "");
+ loadConstant(cUnit, rlResult.lowReg, 0);
+ genBarrier(cUnit);
- storeValue(cUnit, rlDest, rlResult);
- return false;
+ storeValue(cUnit, rlDest, rlResult);
+ return false;
}
} // namespace art
diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc
index 0fe937a..533f8b4 100644
--- a/src/compiler/codegen/arm/Thumb2/Factory.cc
+++ b/src/compiler/codegen/arm/Thumb2/Factory.cc
@@ -37,62 +37,62 @@
int encodeImmSingle(int value)
{
- int res;
- int bitA = (value & 0x80000000) >> 31;
- int notBitB = (value & 0x40000000) >> 30;
- int bitB = (value & 0x20000000) >> 29;
- int bSmear = (value & 0x3e000000) >> 25;
- int slice = (value & 0x01f80000) >> 19;
- int zeroes = (value & 0x0007ffff);
- if (zeroes != 0)
- return -1;
- if (bitB) {
- if ((notBitB != 0) || (bSmear != 0x1f))
- return -1;
- } else {
- if ((notBitB != 1) || (bSmear != 0x0))
- return -1;
- }
- res = (bitA << 7) | (bitB << 6) | slice;
- return res;
+ int res;
+ int bitA = (value & 0x80000000) >> 31;
+ int notBitB = (value & 0x40000000) >> 30;
+ int bitB = (value & 0x20000000) >> 29;
+ int bSmear = (value & 0x3e000000) >> 25;
+ int slice = (value & 0x01f80000) >> 19;
+ int zeroes = (value & 0x0007ffff);
+ if (zeroes != 0)
+ return -1;
+ if (bitB) {
+ if ((notBitB != 0) || (bSmear != 0x1f))
+ return -1;
+ } else {
+ if ((notBitB != 1) || (bSmear != 0x0))
+ return -1;
+ }
+ res = (bitA << 7) | (bitB << 6) | slice;
+ return res;
}
LIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest, int value)
{
- int encodedImm = encodeImmSingle(value);
- DCHECK(SINGLEREG(rDest));
- if (encodedImm >= 0) {
- return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
- }
- LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
- if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, &cUnit->literalList, value);
- }
- LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs,
- rDest, r15pc, 0, 0, 0, dataTarget);
- setMemRefType(loadPcRel, true, kLiteral);
- loadPcRel->aliasInfo = (intptr_t)dataTarget;
- oatAppendLIR(cUnit, (LIR* ) loadPcRel);
- return loadPcRel;
+ int encodedImm = encodeImmSingle(value);
+ DCHECK(SINGLEREG(rDest));
+ if (encodedImm >= 0) {
+ return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
+ }
+ LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->literalList, value);
+ }
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs,
+ rDest, r15pc, 0, 0, 0, dataTarget);
+ setMemRefType(loadPcRel, true, kLiteral);
+ loadPcRel->aliasInfo = (intptr_t)dataTarget;
+ oatAppendLIR(cUnit, (LIR* ) loadPcRel);
+ return loadPcRel;
}
int leadingZeros(u4 val)
{
- u4 alt;
- int n;
- int count;
+ u4 alt;
+ int n;
+ int count;
- count = 16;
- n = 32;
- do {
- alt = val >> count;
- if (alt != 0) {
- n = n - count;
- val = alt;
- }
- count >>= 1;
- } while (count);
- return n - val;
+ count = 16;
+ n = 32;
+ do {
+ alt = val >> count;
+ if (alt != 0) {
+ n = n - count;
+ val = alt;
+ }
+ count >>= 1;
+ } while (count);
+ return n - val;
}
/*
@@ -107,20 +107,20 @@
/* Note: case of value==0 must use 0:000:0:0000000 encoding */
if (value <= 0xFF)
- return b0; // 0:000:a:bcdefgh
+ return b0; // 0:000:a:bcdefgh
if (value == ((b0 << 16) | b0))
- return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
+ return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
- return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
+ return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
b0 = (value >> 8) & 0xff;
if (value == ((b0 << 24) | (b0 << 8)))
- return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
+ return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
/* Can we do it with rotation? */
zLeading = leadingZeros(value);
zTrailing = 32 - leadingZeros(~value & (value - 1));
/* A run of eight or fewer active bits? */
if ((zLeading + zTrailing) < 24)
- return -1; /* No - bail */
+ return -1; /* No - bail */
/* left-justify the constant, discarding msb (known to be 1) */
value <<= zLeading + 1;
/* Create bcdefgh */
@@ -139,443 +139,441 @@
*/
LIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest, int value)
{
- LIR* res;
- int modImm;
+ LIR* res;
+ int modImm;
- if (FPREG(rDest)) {
- return loadFPConstantValue(cUnit, rDest, value);
- }
+ if (FPREG(rDest)) {
+ return loadFPConstantValue(cUnit, rDest, value);
+ }
- /* See if the value can be constructed cheaply */
- if (LOWREG(rDest) && (value >= 0) && (value <= 255)) {
- return newLIR2(cUnit, kThumbMovImm, rDest, value);
- }
- /* Check Modified immediate special cases */
- modImm = modifiedImmediate(value);
- if (modImm >= 0) {
- res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
- return res;
- }
- modImm = modifiedImmediate(~value);
- if (modImm >= 0) {
- res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm);
- return res;
- }
- /* 16-bit immediate? */
- if ((value & 0xffff) == value) {
- res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
- return res;
- }
- /* No shortcut - go ahead and use literal pool */
- LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
- if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, &cUnit->literalList, value);
- }
- LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
- kThumb2LdrPcRel12, rDest, 0, 0, 0, 0, dataTarget);
- setMemRefType(loadPcRel, true, kLiteral);
- loadPcRel->aliasInfo = (intptr_t)dataTarget;
- res = loadPcRel;
- oatAppendLIR(cUnit, (LIR* ) loadPcRel);
-
- /*
- * To save space in the constant pool, we use the ADD_RRI8 instruction to
- * add up to 255 to an existing constant value.
- */
- if (dataTarget->operands[0] != value) {
- opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
- }
+ /* See if the value can be constructed cheaply */
+ if (LOWREG(rDest) && (value >= 0) && (value <= 255)) {
+ return newLIR2(cUnit, kThumbMovImm, rDest, value);
+ }
+ /* Check Modified immediate special cases */
+ modImm = modifiedImmediate(value);
+ if (modImm >= 0) {
+ res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
return res;
+ }
+ modImm = modifiedImmediate(~value);
+ if (modImm >= 0) {
+ res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm);
+ return res;
+ }
+ /* 16-bit immediate? */
+ if ((value & 0xffff) == value) {
+ res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
+ return res;
+ }
+ /* No shortcut - go ahead and use literal pool */
+ LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->literalList, value);
+ }
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
+ kThumb2LdrPcRel12, rDest, 0, 0, 0, 0, dataTarget);
+ setMemRefType(loadPcRel, true, kLiteral);
+ loadPcRel->aliasInfo = (intptr_t)dataTarget;
+ res = loadPcRel;
+ oatAppendLIR(cUnit, (LIR* ) loadPcRel);
+
+ /*
+ * To save space in the constant pool, we use the ADD_RRI8 instruction to
+ * add up to 255 to an existing constant value.
+ */
+ if (dataTarget->operands[0] != value) {
+ opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
+ }
+ return res;
}
LIR* opBranchUnconditional(CompilationUnit* cUnit, OpKind op)
{
- DCHECK_EQ(op, kOpUncondBr);
- return newLIR1(cUnit, kThumbBUncond, 0 /* offset to be patched */);
+ DCHECK_EQ(op, kOpUncondBr);
+ return newLIR1(cUnit, kThumbBUncond, 0 /* offset to be patched */);
}
LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
{
- LIR* branch = newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */,
- oatArmConditionEncoding(cc));
- branch->target = target;
- return branch;
+ LIR* branch = newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */,
+ oatArmConditionEncoding(cc));
+ branch->target = target;
+ return branch;
}
LIR* opReg(CompilationUnit* cUnit, OpKind op, int rDestSrc)
{
- ArmOpcode opcode = kThumbBkpt;
- switch (op) {
- case kOpBlx:
- opcode = kThumbBlxR;
- break;
- default:
- LOG(FATAL) << "Bad opcode " << (int)op;
- }
- return newLIR1(cUnit, opcode, rDestSrc);
+ ArmOpcode opcode = kThumbBkpt;
+ switch (op) {
+ case kOpBlx:
+ opcode = kThumbBlxR;
+ break;
+ default:
+ LOG(FATAL) << "Bad opcode " << (int)op;
+ }
+ return newLIR1(cUnit, opcode, rDestSrc);
}
LIR* opRegRegShift(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
int rSrc2, int shift)
{
- bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
- ArmOpcode opcode = kThumbBkpt;
- switch (op) {
- case kOpAdc:
- opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
- break;
- case kOpAnd:
- opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
- break;
- case kOpBic:
- opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
- break;
- case kOpCmn:
- DCHECK_EQ(shift, 0);
- opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
- break;
- case kOpCmp:
- if (thumbForm)
- opcode = kThumbCmpRR;
- else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
- opcode = kThumbCmpHH;
- else if ((shift == 0) && LOWREG(rDestSrc1))
- opcode = kThumbCmpLH;
- else if (shift == 0)
- opcode = kThumbCmpHL;
- else
- opcode = kThumb2CmpRR;
- break;
- case kOpXor:
- opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
- break;
- case kOpMov:
- DCHECK_EQ(shift, 0);
- if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
- opcode = kThumbMovRR;
- else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
- opcode = kThumbMovRR_H2H;
- else if (LOWREG(rDestSrc1))
- opcode = kThumbMovRR_H2L;
- else
- opcode = kThumbMovRR_L2H;
- break;
- case kOpMul:
- DCHECK_EQ(shift, 0);
- opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
- break;
- case kOpMvn:
- opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
- break;
- case kOpNeg:
- DCHECK_EQ(shift, 0);
- opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
- break;
- case kOpOr:
- opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
- break;
- case kOpSbc:
- opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
- break;
- case kOpTst:
- opcode = (thumbForm) ? kThumbTst : kThumb2TstRR;
- break;
- case kOpLsl:
- DCHECK_EQ(shift, 0);
- opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
- break;
- case kOpLsr:
- DCHECK_EQ(shift, 0);
- opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
- break;
- case kOpAsr:
- DCHECK_EQ(shift, 0);
- opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
- break;
- case kOpRor:
- DCHECK_EQ(shift, 0);
- opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
- break;
- case kOpAdd:
- opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
- break;
- case kOpSub:
- opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
- break;
- case kOp2Byte:
- DCHECK_EQ(shift, 0);
- return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
- case kOp2Short:
- DCHECK_EQ(shift, 0);
- return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
- case kOp2Char:
- DCHECK_EQ(shift, 0);
- return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
- default:
- LOG(FATAL) << "Bad opcode: " << (int)op;
- break;
- }
- DCHECK_GE(static_cast<int>(opcode), 0);
- if (EncodingMap[opcode].flags & IS_BINARY_OP)
- return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
- else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
- if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift)
- return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift);
- else
- return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2);
- } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
- return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift);
- else {
- LOG(FATAL) << "Unexpected encoding operand count";
- return NULL;
- }
+ bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
+ ArmOpcode opcode = kThumbBkpt;
+ switch (op) {
+ case kOpAdc:
+ opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
+ break;
+ case kOpAnd:
+ opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
+ break;
+ case kOpBic:
+ opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
+ break;
+ case kOpCmn:
+ DCHECK_EQ(shift, 0);
+ opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
+ break;
+ case kOpCmp:
+ if (thumbForm)
+ opcode = kThumbCmpRR;
+ else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+ opcode = kThumbCmpHH;
+ else if ((shift == 0) && LOWREG(rDestSrc1))
+ opcode = kThumbCmpLH;
+ else if (shift == 0)
+ opcode = kThumbCmpHL;
+ else
+ opcode = kThumb2CmpRR;
+ break;
+ case kOpXor:
+ opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
+ break;
+ case kOpMov:
+ DCHECK_EQ(shift, 0);
+ if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
+ opcode = kThumbMovRR;
+ else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+ opcode = kThumbMovRR_H2H;
+ else if (LOWREG(rDestSrc1))
+ opcode = kThumbMovRR_H2L;
+ else
+ opcode = kThumbMovRR_L2H;
+ break;
+ case kOpMul:
+ DCHECK_EQ(shift, 0);
+ opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
+ break;
+ case kOpMvn:
+ opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
+ break;
+ case kOpNeg:
+ DCHECK_EQ(shift, 0);
+ opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
+ break;
+ case kOpOr:
+ opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
+ break;
+ case kOpSbc:
+ opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
+ break;
+ case kOpTst:
+ opcode = (thumbForm) ? kThumbTst : kThumb2TstRR;
+ break;
+ case kOpLsl:
+ DCHECK_EQ(shift, 0);
+ opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
+ break;
+ case kOpLsr:
+ DCHECK_EQ(shift, 0);
+ opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
+ break;
+ case kOpAsr:
+ DCHECK_EQ(shift, 0);
+ opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
+ break;
+ case kOpRor:
+ DCHECK_EQ(shift, 0);
+ opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
+ break;
+ case kOpAdd:
+ opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
+ break;
+ case kOpSub:
+ opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
+ break;
+ case kOp2Byte:
+ DCHECK_EQ(shift, 0);
+ return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
+ case kOp2Short:
+ DCHECK_EQ(shift, 0);
+ return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
+ case kOp2Char:
+ DCHECK_EQ(shift, 0);
+ return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
+ default:
+ LOG(FATAL) << "Bad opcode: " << (int)op;
+ break;
+ }
+ DCHECK_GE(static_cast<int>(opcode), 0);
+ if (EncodingMap[opcode].flags & IS_BINARY_OP)
+ return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
+ else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
+ if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift)
+ return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift);
+ else
+ return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2);
+ } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
+ return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift);
+ else {
+ LOG(FATAL) << "Unexpected encoding operand count";
+ return NULL;
+ }
}
LIR* opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2)
{
- return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
+ return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
}
LIR* opRegRegRegShift(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
- int rSrc2, int shift)
+ int rSrc2, int shift)
{
- ArmOpcode opcode = kThumbBkpt;
- bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
- LOWREG(rSrc2);
- switch (op) {
- case kOpAdd:
- opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
- break;
- case kOpSub:
- opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
- break;
- case kOpRsub:
- opcode = kThumb2RsubRRR;
- break;
- case kOpAdc:
- opcode = kThumb2AdcRRR;
- break;
- case kOpAnd:
- opcode = kThumb2AndRRR;
- break;
- case kOpBic:
- opcode = kThumb2BicRRR;
- break;
- case kOpXor:
- opcode = kThumb2EorRRR;
- break;
- case kOpMul:
- DCHECK_EQ(shift, 0);
- opcode = kThumb2MulRRR;
- break;
- case kOpOr:
- opcode = kThumb2OrrRRR;
- break;
- case kOpSbc:
- opcode = kThumb2SbcRRR;
- break;
- case kOpLsl:
- DCHECK_EQ(shift, 0);
- opcode = kThumb2LslRRR;
- break;
- case kOpLsr:
- DCHECK_EQ(shift, 0);
- opcode = kThumb2LsrRRR;
- break;
- case kOpAsr:
- DCHECK_EQ(shift, 0);
- opcode = kThumb2AsrRRR;
- break;
- case kOpRor:
- DCHECK_EQ(shift, 0);
- opcode = kThumb2RorRRR;
- break;
- default:
- LOG(FATAL) << "Bad opcode: " << (int)op;
- break;
- }
- DCHECK_GE(static_cast<int>(opcode), 0);
- if (EncodingMap[opcode].flags & IS_QUAD_OP)
- return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift);
- else {
- DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
- return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
- }
+ ArmOpcode opcode = kThumbBkpt;
+ bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
+ LOWREG(rSrc2);
+ switch (op) {
+ case kOpAdd:
+ opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
+ break;
+ case kOpSub:
+ opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
+ break;
+ case kOpRsub:
+ opcode = kThumb2RsubRRR;
+ break;
+ case kOpAdc:
+ opcode = kThumb2AdcRRR;
+ break;
+ case kOpAnd:
+ opcode = kThumb2AndRRR;
+ break;
+ case kOpBic:
+ opcode = kThumb2BicRRR;
+ break;
+ case kOpXor:
+ opcode = kThumb2EorRRR;
+ break;
+ case kOpMul:
+ DCHECK_EQ(shift, 0);
+ opcode = kThumb2MulRRR;
+ break;
+ case kOpOr:
+ opcode = kThumb2OrrRRR;
+ break;
+ case kOpSbc:
+ opcode = kThumb2SbcRRR;
+ break;
+ case kOpLsl:
+ DCHECK_EQ(shift, 0);
+ opcode = kThumb2LslRRR;
+ break;
+ case kOpLsr:
+ DCHECK_EQ(shift, 0);
+ opcode = kThumb2LsrRRR;
+ break;
+ case kOpAsr:
+ DCHECK_EQ(shift, 0);
+ opcode = kThumb2AsrRRR;
+ break;
+ case kOpRor:
+ DCHECK_EQ(shift, 0);
+ opcode = kThumb2RorRRR;
+ break;
+ default:
+ LOG(FATAL) << "Bad opcode: " << (int)op;
+ break;
+ }
+ DCHECK_GE(static_cast<int>(opcode), 0);
+ if (EncodingMap[opcode].flags & IS_QUAD_OP)
+ return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift);
+ else {
+ DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
+ return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
+ }
}
LIR* opRegRegReg(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
int rSrc2)
{
- return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
+ return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
}
LIR* opRegRegImm(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
int value)
{
- LIR* res;
- bool neg = (value < 0);
- int absValue = (neg) ? -value : value;
- ArmOpcode opcode = kThumbBkpt;
- ArmOpcode altOpcode = kThumbBkpt;
- bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
- int modImm = modifiedImmediate(value);
- int modImmNeg = modifiedImmediate(-value);
+ LIR* res;
+ bool neg = (value < 0);
+ int absValue = (neg) ? -value : value;
+ ArmOpcode opcode = kThumbBkpt;
+ ArmOpcode altOpcode = kThumbBkpt;
+ bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
+ int modImm = modifiedImmediate(value);
+ int modImmNeg = modifiedImmediate(-value);
- switch (op) {
- case kOpLsl:
- if (allLowRegs)
- return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
- else
- return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
- case kOpLsr:
- if (allLowRegs)
- return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
- else
- return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
- case kOpAsr:
- if (allLowRegs)
- return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
- else
- return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
- case kOpRor:
- return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
- case kOpAdd:
- if (LOWREG(rDest) && (rSrc1 == r13sp) &&
- (value <= 1020) && ((value & 0x3)==0)) {
- return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1,
- value >> 2);
- } else if (LOWREG(rDest) && (rSrc1 == r15pc) &&
- (value <= 1020) && ((value & 0x3)==0)) {
- return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1,
- value >> 2);
- }
- // Note: intentional fallthrough
- case kOpSub:
- if (allLowRegs && ((absValue & 0x7) == absValue)) {
- if (op == kOpAdd)
- opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
- else
- opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
- return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
- } else if ((absValue & 0xff) == absValue) {
- if (op == kOpAdd)
- opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
- else
- opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
- return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
- }
- if (modImmNeg >= 0) {
- op = (op == kOpAdd) ? kOpSub : kOpAdd;
- modImm = modImmNeg;
- }
- if (op == kOpSub) {
- opcode = kThumb2SubRRI8;
- altOpcode = kThumb2SubRRR;
- } else {
- opcode = kThumb2AddRRI8;
- altOpcode = kThumb2AddRRR;
- }
- break;
- case kOpAdc:
- opcode = kThumb2AdcRRI8;
- altOpcode = kThumb2AdcRRR;
- break;
- case kOpSbc:
- opcode = kThumb2SbcRRI8;
- altOpcode = kThumb2SbcRRR;
- break;
- case kOpOr:
- opcode = kThumb2OrrRRI8;
- altOpcode = kThumb2OrrRRR;
- break;
- case kOpAnd:
- opcode = kThumb2AndRRI8;
- altOpcode = kThumb2AndRRR;
- break;
- case kOpXor:
- opcode = kThumb2EorRRI8;
- altOpcode = kThumb2EorRRR;
- break;
- case kOpMul:
- //TUNING: power of 2, shift & add
- modImm = -1;
- altOpcode = kThumb2MulRRR;
- break;
- case kOpCmp: {
- int modImm = modifiedImmediate(value);
- LIR* res;
- if (modImm >= 0) {
- res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
- } else {
- int rTmp = oatAllocTemp(cUnit);
- res = loadConstant(cUnit, rTmp, value);
- opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
- oatFreeTemp(cUnit, rTmp);
- }
- return res;
- }
- default:
- LOG(FATAL) << "Bad opcode: " << (int)op;
- }
-
- if (modImm >= 0) {
- return newLIR3(cUnit, opcode, rDest, rSrc1, modImm);
- } else {
- int rScratch = oatAllocTemp(cUnit);
- loadConstant(cUnit, rScratch, value);
- if (EncodingMap[altOpcode].flags & IS_QUAD_OP)
- res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0);
+ switch (op) {
+ case kOpLsl:
+ if (allLowRegs)
+ return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
+ else
+ return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
+ case kOpLsr:
+ if (allLowRegs)
+ return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
+ else
+ return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
+ case kOpAsr:
+ if (allLowRegs)
+ return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
+ else
+ return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
+ case kOpRor:
+ return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
+ case kOpAdd:
+ if (LOWREG(rDest) && (rSrc1 == r13sp) &&
+ (value <= 1020) && ((value & 0x3)==0)) {
+ return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1, value >> 2);
+ } else if (LOWREG(rDest) && (rSrc1 == r15pc) &&
+ (value <= 1020) && ((value & 0x3)==0)) {
+ return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1, value >> 2);
+ }
+ // Note: intentional fallthrough
+ case kOpSub:
+ if (allLowRegs && ((absValue & 0x7) == absValue)) {
+ if (op == kOpAdd)
+ opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
else
- res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch);
- oatFreeTemp(cUnit, rScratch);
- return res;
+ opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
+ return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
+ } else if ((absValue & 0xff) == absValue) {
+ if (op == kOpAdd)
+ opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
+ else
+ opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
+ return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
+ }
+ if (modImmNeg >= 0) {
+ op = (op == kOpAdd) ? kOpSub : kOpAdd;
+ modImm = modImmNeg;
+ }
+ if (op == kOpSub) {
+ opcode = kThumb2SubRRI8;
+ altOpcode = kThumb2SubRRR;
+ } else {
+ opcode = kThumb2AddRRI8;
+ altOpcode = kThumb2AddRRR;
+ }
+ break;
+ case kOpAdc:
+ opcode = kThumb2AdcRRI8;
+ altOpcode = kThumb2AdcRRR;
+ break;
+ case kOpSbc:
+ opcode = kThumb2SbcRRI8;
+ altOpcode = kThumb2SbcRRR;
+ break;
+ case kOpOr:
+ opcode = kThumb2OrrRRI8;
+ altOpcode = kThumb2OrrRRR;
+ break;
+ case kOpAnd:
+ opcode = kThumb2AndRRI8;
+ altOpcode = kThumb2AndRRR;
+ break;
+ case kOpXor:
+ opcode = kThumb2EorRRI8;
+ altOpcode = kThumb2EorRRR;
+ break;
+ case kOpMul:
+ //TUNING: power of 2, shift & add
+ modImm = -1;
+ altOpcode = kThumb2MulRRR;
+ break;
+ case kOpCmp: {
+ int modImm = modifiedImmediate(value);
+ LIR* res;
+ if (modImm >= 0) {
+ res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
+ } else {
+ int rTmp = oatAllocTemp(cUnit);
+ res = loadConstant(cUnit, rTmp, value);
+ opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
+ oatFreeTemp(cUnit, rTmp);
+ }
+ return res;
}
+ default:
+ LOG(FATAL) << "Bad opcode: " << (int)op;
+ }
+
+ if (modImm >= 0) {
+ return newLIR3(cUnit, opcode, rDest, rSrc1, modImm);
+ } else {
+ int rScratch = oatAllocTemp(cUnit);
+ loadConstant(cUnit, rScratch, value);
+ if (EncodingMap[altOpcode].flags & IS_QUAD_OP)
+ res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0);
+ else
+ res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch);
+ oatFreeTemp(cUnit, rScratch);
+ return res;
+ }
}
/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value)
{
- bool neg = (value < 0);
- int absValue = (neg) ? -value : value;
- bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
- ArmOpcode opcode = kThumbBkpt;
- switch (op) {
- case kOpAdd:
- if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
- DCHECK_EQ((value & 0x3), 0);
- return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
- } else if (shortForm) {
- opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
- }
- break;
- case kOpSub:
- if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
- DCHECK_EQ((value & 0x3), 0);
- return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
- } else if (shortForm) {
- opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
- }
- break;
- case kOpCmp:
- if (LOWREG(rDestSrc1) && shortForm)
- opcode = (shortForm) ? kThumbCmpRI8 : kThumbCmpRR;
- else if (LOWREG(rDestSrc1))
- opcode = kThumbCmpRR;
- else {
- shortForm = false;
- opcode = kThumbCmpHL;
- }
- break;
- default:
- /* Punt to opRegRegImm - if bad case catch it there */
- shortForm = false;
- break;
- }
- if (shortForm)
- return newLIR2(cUnit, opcode, rDestSrc1, absValue);
- else {
- return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
- }
+ bool neg = (value < 0);
+ int absValue = (neg) ? -value : value;
+ bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
+ ArmOpcode opcode = kThumbBkpt;
+ switch (op) {
+ case kOpAdd:
+ if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
+ DCHECK_EQ((value & 0x3), 0);
+ return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
+ } else if (shortForm) {
+ opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
+ }
+ break;
+ case kOpSub:
+ if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
+ DCHECK_EQ((value & 0x3), 0);
+ return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
+ } else if (shortForm) {
+ opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
+ }
+ break;
+ case kOpCmp:
+ if (LOWREG(rDestSrc1) && shortForm)
+ opcode = (shortForm) ? kThumbCmpRI8 : kThumbCmpRR;
+ else if (LOWREG(rDestSrc1))
+ opcode = kThumbCmpRR;
+ else {
+ shortForm = false;
+ opcode = kThumbCmpHL;
+ }
+ break;
+ default:
+ /* Punt to opRegRegImm - if bad case catch it there */
+ shortForm = false;
+ break;
+ }
+ if (shortForm)
+ return newLIR2(cUnit, opcode, rDestSrc1, absValue);
+ else {
+ return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
+ }
}
/*
@@ -584,193 +582,191 @@
*/
int encodeImmDoubleHigh(int value)
{
- int res;
- int bitA = (value & 0x80000000) >> 31;
- int notBitB = (value & 0x40000000) >> 30;
- int bitB = (value & 0x20000000) >> 29;
- int bSmear = (value & 0x3fc00000) >> 22;
- int slice = (value & 0x003f0000) >> 16;
- int zeroes = (value & 0x0000ffff);
- if (zeroes != 0)
- return -1;
- if (bitB) {
- if ((notBitB != 0) || (bSmear != 0xff))
- return -1;
- } else {
- if ((notBitB != 1) || (bSmear != 0x0))
- return -1;
- }
- res = (bitA << 7) | (bitB << 6) | slice;
- return res;
+ int res;
+ int bitA = (value & 0x80000000) >> 31;
+ int notBitB = (value & 0x40000000) >> 30;
+ int bitB = (value & 0x20000000) >> 29;
+ int bSmear = (value & 0x3fc00000) >> 22;
+ int slice = (value & 0x003f0000) >> 16;
+ int zeroes = (value & 0x0000ffff);
+ if (zeroes != 0)
+ return -1;
+ if (bitB) {
+ if ((notBitB != 0) || (bSmear != 0xff))
+ return -1;
+ } else {
+ if ((notBitB != 1) || (bSmear != 0x0))
+ return -1;
+ }
+ res = (bitA << 7) | (bitB << 6) | slice;
+ return res;
}
int encodeImmDouble(int valLo, int valHi)
{
- int res = -1;
- if (valLo == 0)
- res = encodeImmDoubleHigh(valHi);
- return res;
+ int res = -1;
+ if (valLo == 0)
+ res = encodeImmDoubleHigh(valHi);
+ return res;
}
LIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo, int rDestHi,
- int valLo, int valHi)
+ int valLo, int valHi)
{
- int encodedImm = encodeImmDouble(valLo, valHi);
- LIR* res;
- if (FPREG(rDestLo)) {
- if (encodedImm >= 0) {
- res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi),
- encodedImm);
- } else {
- LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo,
- valHi);
- if (dataTarget == NULL) {
- dataTarget = addWideData(cUnit, &cUnit->literalList, valLo,
- valHi);
- }
- LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
- kThumb2Vldrd, S2D(rDestLo, rDestHi),
- r15pc, 0, 0, 0, dataTarget);
- setMemRefType(loadPcRel, true, kLiteral);
- loadPcRel->aliasInfo = (intptr_t)dataTarget;
- oatAppendLIR(cUnit, (LIR* ) loadPcRel);
- res = loadPcRel;
- }
+ int encodedImm = encodeImmDouble(valLo, valHi);
+ LIR* res;
+ if (FPREG(rDestLo)) {
+ if (encodedImm >= 0) {
+ res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi),
+ encodedImm);
} else {
- res = loadConstantNoClobber(cUnit, rDestLo, valLo);
- loadConstantNoClobber(cUnit, rDestHi, valHi);
+ LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo, valHi);
+ if (dataTarget == NULL) {
+ dataTarget = addWideData(cUnit, &cUnit->literalList, valLo, valHi);
+ }
+ LIR* loadPcRel =
+ rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrd,
+ S2D(rDestLo, rDestHi), r15pc, 0, 0, 0, dataTarget);
+ setMemRefType(loadPcRel, true, kLiteral);
+ loadPcRel->aliasInfo = (intptr_t)dataTarget;
+ oatAppendLIR(cUnit, (LIR* ) loadPcRel);
+ res = loadPcRel;
}
- return res;
+ } else {
+ res = loadConstantNoClobber(cUnit, rDestLo, valLo);
+ loadConstantNoClobber(cUnit, rDestHi, valHi);
+ }
+ return res;
}
int encodeShift(int code, int amount) {
- return ((amount & 0x1f) << 2) | code;
+ return ((amount & 0x1f) << 2) | code;
}
LIR* loadBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rDest,
int scale, OpSize size)
{
- bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
- LIR* load;
- ArmOpcode opcode = kThumbBkpt;
- bool thumbForm = (allLowRegs && (scale == 0));
- int regPtr;
+ bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
+ LIR* load;
+ ArmOpcode opcode = kThumbBkpt;
+ bool thumbForm = (allLowRegs && (scale == 0));
+ int regPtr;
- if (FPREG(rDest)) {
- if (SINGLEREG(rDest)) {
- DCHECK((size == kWord) || (size == kSingle));
- opcode = kThumb2Vldrs;
- size = kSingle;
- } else {
- DCHECK(DOUBLEREG(rDest));
- DCHECK((size == kLong) || (size == kDouble));
- DCHECK((rDest & 0x1) == 0);
- opcode = kThumb2Vldrd;
- size = kDouble;
- }
+ if (FPREG(rDest)) {
+ if (SINGLEREG(rDest)) {
+ DCHECK((size == kWord) || (size == kSingle));
+ opcode = kThumb2Vldrs;
+ size = kSingle;
} else {
- if (size == kSingle)
- size = kWord;
+ DCHECK(DOUBLEREG(rDest));
+ DCHECK((size == kLong) || (size == kDouble));
+ DCHECK((rDest & 0x1) == 0);
+ opcode = kThumb2Vldrd;
+ size = kDouble;
}
+ } else {
+ if (size == kSingle)
+ size = kWord;
+ }
- switch (size) {
- case kDouble: // fall-through
- case kSingle:
- regPtr = oatAllocTemp(cUnit);
- if (scale) {
- newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
- encodeShift(kArmLsl, scale));
- } else {
- opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
- }
- load = newLIR3(cUnit, opcode, rDest, regPtr, 0);
- oatFreeTemp(cUnit, regPtr);
- return load;
- case kWord:
- opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
- break;
- case kUnsignedHalf:
- opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
- break;
- case kSignedHalf:
- opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
- break;
- case kUnsignedByte:
- opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
- break;
- case kSignedByte:
- opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
- break;
- default:
- LOG(FATAL) << "Bad size: " << (int)size;
- }
- if (thumbForm)
- load = newLIR3(cUnit, opcode, rDest, rBase, rIndex);
- else
- load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale);
+ switch (size) {
+ case kDouble: // fall-through
+ case kSingle:
+ regPtr = oatAllocTemp(cUnit);
+ if (scale) {
+ newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
+ encodeShift(kArmLsl, scale));
+ } else {
+ opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
+ }
+ load = newLIR3(cUnit, opcode, rDest, regPtr, 0);
+ oatFreeTemp(cUnit, regPtr);
+ return load;
+ case kWord:
+ opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
+ break;
+ case kUnsignedHalf:
+ opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
+ break;
+ case kSignedHalf:
+ opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
+ break;
+ case kUnsignedByte:
+ opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
+ break;
+ case kSignedByte:
+ opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
+ break;
+ default:
+ LOG(FATAL) << "Bad size: " << (int)size;
+ }
+ if (thumbForm)
+ load = newLIR3(cUnit, opcode, rDest, rBase, rIndex);
+ else
+ load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale);
- return load;
+ return load;
}
LIR* storeBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rSrc,
int scale, OpSize size)
{
- bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
- LIR* store;
- ArmOpcode opcode = kThumbBkpt;
- bool thumbForm = (allLowRegs && (scale == 0));
- int regPtr;
+ bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
+ LIR* store;
+ ArmOpcode opcode = kThumbBkpt;
+ bool thumbForm = (allLowRegs && (scale == 0));
+ int regPtr;
- if (FPREG(rSrc)) {
- if (SINGLEREG(rSrc)) {
- DCHECK((size == kWord) || (size == kSingle));
- opcode = kThumb2Vstrs;
- size = kSingle;
- } else {
- DCHECK(DOUBLEREG(rSrc));
- DCHECK((size == kLong) || (size == kDouble));
- DCHECK((rSrc & 0x1) == 0);
- opcode = kThumb2Vstrd;
- size = kDouble;
- }
+ if (FPREG(rSrc)) {
+ if (SINGLEREG(rSrc)) {
+ DCHECK((size == kWord) || (size == kSingle));
+ opcode = kThumb2Vstrs;
+ size = kSingle;
} else {
- if (size == kSingle)
- size = kWord;
+ DCHECK(DOUBLEREG(rSrc));
+ DCHECK((size == kLong) || (size == kDouble));
+ DCHECK((rSrc & 0x1) == 0);
+ opcode = kThumb2Vstrd;
+ size = kDouble;
}
+ } else {
+ if (size == kSingle)
+ size = kWord;
+ }
- switch (size) {
- case kDouble: // fall-through
- case kSingle:
- regPtr = oatAllocTemp(cUnit);
- if (scale) {
- newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
- encodeShift(kArmLsl, scale));
- } else {
- opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
- }
- store = newLIR3(cUnit, opcode, rSrc, regPtr, 0);
- oatFreeTemp(cUnit, regPtr);
- return store;
- case kWord:
- opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
- break;
- case kUnsignedHalf:
- case kSignedHalf:
- opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
- break;
- case kUnsignedByte:
- case kSignedByte:
- opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
- break;
- default:
- LOG(FATAL) << "Bad size: " << (int)size;
- }
- if (thumbForm)
- store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex);
- else
- store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale);
+ switch (size) {
+ case kDouble: // fall-through
+ case kSingle:
+ regPtr = oatAllocTemp(cUnit);
+ if (scale) {
+ newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
+ encodeShift(kArmLsl, scale));
+ } else {
+ opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
+ }
+ store = newLIR3(cUnit, opcode, rSrc, regPtr, 0);
+ oatFreeTemp(cUnit, regPtr);
+ return store;
+ case kWord:
+ opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
+ break;
+ case kUnsignedHalf:
+ case kSignedHalf:
+ opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
+ break;
+ case kUnsignedByte:
+ case kSignedByte:
+ opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
+ break;
+ default:
+ LOG(FATAL) << "Bad size: " << (int)size;
+ }
+ if (thumbForm)
+ store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex);
+ else
+ store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale);
- return store;
+ return store;
}
/*
@@ -782,267 +778,266 @@
int displacement, int rDest, int rDestHi, OpSize size,
int sReg)
{
- LIR* res;
- LIR* load;
- ArmOpcode opcode = kThumbBkpt;
- bool shortForm = false;
- bool thumb2Form = (displacement < 4092 && displacement >= 0);
- bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
- int encodedDisp = displacement;
- bool is64bit = false;
- switch (size) {
- case kDouble:
- case kLong:
- is64bit = true;
- if (FPREG(rDest)) {
- if (SINGLEREG(rDest)) {
- DCHECK(FPREG(rDestHi));
- rDest = S2D(rDest, rDestHi);
- }
- opcode = kThumb2Vldrd;
- if (displacement <= 1020) {
- shortForm = true;
- encodedDisp >>= 2;
- }
- break;
- } else {
- res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest,
- -1, kWord, sReg);
- loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi,
- -1, kWord, INVALID_SREG);
- return res;
- }
- case kSingle:
- case kWord:
- if (FPREG(rDest)) {
- opcode = kThumb2Vldrs;
- if (displacement <= 1020) {
- shortForm = true;
- encodedDisp >>= 2;
- }
- break;
- }
- if (LOWREG(rDest) && (rBase == r15pc) &&
- (displacement <= 1020) && (displacement >= 0)) {
- shortForm = true;
- encodedDisp >>= 2;
- opcode = kThumbLdrPcRel;
- } else if (LOWREG(rDest) && (rBase == r13sp) &&
- (displacement <= 1020) && (displacement >= 0)) {
- shortForm = true;
- encodedDisp >>= 2;
- opcode = kThumbLdrSpRel;
- } else if (allLowRegs && displacement < 128 && displacement >= 0) {
- DCHECK_EQ((displacement & 0x3), 0);
- shortForm = true;
- encodedDisp >>= 2;
- opcode = kThumbLdrRRI5;
- } else if (thumb2Form) {
- shortForm = true;
- opcode = kThumb2LdrRRI12;
- }
- break;
- case kUnsignedHalf:
- if (allLowRegs && displacement < 64 && displacement >= 0) {
- DCHECK_EQ((displacement & 0x1), 0);
- shortForm = true;
- encodedDisp >>= 1;
- opcode = kThumbLdrhRRI5;
- } else if (displacement < 4092 && displacement >= 0) {
- shortForm = true;
- opcode = kThumb2LdrhRRI12;
- }
- break;
- case kSignedHalf:
- if (thumb2Form) {
- shortForm = true;
- opcode = kThumb2LdrshRRI12;
- }
- break;
- case kUnsignedByte:
- if (allLowRegs && displacement < 32 && displacement >= 0) {
- shortForm = true;
- opcode = kThumbLdrbRRI5;
- } else if (thumb2Form) {
- shortForm = true;
- opcode = kThumb2LdrbRRI12;
- }
- break;
- case kSignedByte:
- if (thumb2Form) {
- shortForm = true;
- opcode = kThumb2LdrsbRRI12;
- }
- break;
- default:
- LOG(FATAL) << "Bad size: " << (int)size;
- }
+ LIR* res;
+ LIR* load;
+ ArmOpcode opcode = kThumbBkpt;
+ bool shortForm = false;
+ bool thumb2Form = (displacement < 4092 && displacement >= 0);
+ bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
+ int encodedDisp = displacement;
+ bool is64bit = false;
+ switch (size) {
+ case kDouble:
+ case kLong:
+ is64bit = true;
+ if (FPREG(rDest)) {
+ if (SINGLEREG(rDest)) {
+ DCHECK(FPREG(rDestHi));
+ rDest = S2D(rDest, rDestHi);
+ }
+ opcode = kThumb2Vldrd;
+ if (displacement <= 1020) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ }
+ break;
+ } else {
+ res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest,
+ -1, kWord, sReg);
+ loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi,
+ -1, kWord, INVALID_SREG);
+ return res;
+ }
+ case kSingle:
+ case kWord:
+ if (FPREG(rDest)) {
+ opcode = kThumb2Vldrs;
+ if (displacement <= 1020) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ }
+ break;
+ }
+ if (LOWREG(rDest) && (rBase == r15pc) &&
+ (displacement <= 1020) && (displacement >= 0)) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ opcode = kThumbLdrPcRel;
+ } else if (LOWREG(rDest) && (rBase == r13sp) &&
+ (displacement <= 1020) && (displacement >= 0)) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ opcode = kThumbLdrSpRel;
+ } else if (allLowRegs && displacement < 128 && displacement >= 0) {
+ DCHECK_EQ((displacement & 0x3), 0);
+ shortForm = true;
+ encodedDisp >>= 2;
+ opcode = kThumbLdrRRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opcode = kThumb2LdrRRI12;
+ }
+ break;
+ case kUnsignedHalf:
+ if (allLowRegs && displacement < 64 && displacement >= 0) {
+ DCHECK_EQ((displacement & 0x1), 0);
+ shortForm = true;
+ encodedDisp >>= 1;
+ opcode = kThumbLdrhRRI5;
+ } else if (displacement < 4092 && displacement >= 0) {
+ shortForm = true;
+ opcode = kThumb2LdrhRRI12;
+ }
+ break;
+ case kSignedHalf:
+ if (thumb2Form) {
+ shortForm = true;
+ opcode = kThumb2LdrshRRI12;
+ }
+ break;
+ case kUnsignedByte:
+ if (allLowRegs && displacement < 32 && displacement >= 0) {
+ shortForm = true;
+ opcode = kThumbLdrbRRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opcode = kThumb2LdrbRRI12;
+ }
+ break;
+ case kSignedByte:
+ if (thumb2Form) {
+ shortForm = true;
+ opcode = kThumb2LdrsbRRI12;
+ }
+ break;
+ default:
+ LOG(FATAL) << "Bad size: " << (int)size;
+ }
- if (shortForm) {
- load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp);
- } else {
- int regOffset = oatAllocTemp(cUnit);
- res = loadConstant(cUnit, regOffset, encodedDisp);
- load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
- oatFreeTemp(cUnit, regOffset);
- }
+ if (shortForm) {
+ load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp);
+ } else {
+ int regOffset = oatAllocTemp(cUnit);
+ res = loadConstant(cUnit, regOffset, encodedDisp);
+ load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
+ oatFreeTemp(cUnit, regOffset);
+ }
- // TODO: in future may need to differentiate Dalvik accesses w/ spills
- if (rBase == rSP) {
- annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */, is64bit);
- }
- return load;
+ // TODO: in future may need to differentiate Dalvik accesses w/ spills
+ if (rBase == rSP) {
+ annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */, is64bit);
+ }
+ 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);
+ return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1, 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);
+ return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
+ kLong, sReg);
}
LIR* storeBaseDispBody(CompilationUnit* cUnit, int rBase, int displacement,
int rSrc, int rSrcHi, OpSize size)
{
- LIR* res, *store;
- ArmOpcode opcode = kThumbBkpt;
- bool shortForm = false;
- bool thumb2Form = (displacement < 4092 && displacement >= 0);
- bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
- int encodedDisp = displacement;
- bool is64bit = false;
- switch (size) {
- case kLong:
- case kDouble:
- is64bit = true;
- if (!FPREG(rSrc)) {
- res = storeBaseDispBody(cUnit, rBase, displacement, rSrc,
- -1, kWord);
- storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi,
- -1, kWord);
- return res;
- }
- if (SINGLEREG(rSrc)) {
- DCHECK(FPREG(rSrcHi));
- rSrc = S2D(rSrc, rSrcHi);
- }
- opcode = kThumb2Vstrd;
- if (displacement <= 1020) {
- shortForm = true;
- encodedDisp >>= 2;
- }
- break;
- case kSingle:
- case kWord:
- if (FPREG(rSrc)) {
- DCHECK(SINGLEREG(rSrc));
- opcode = kThumb2Vstrs;
- if (displacement <= 1020) {
- shortForm = true;
- encodedDisp >>= 2;
- }
- break;
- }
- if (allLowRegs && displacement < 128 && displacement >= 0) {
- DCHECK_EQ((displacement & 0x3), 0);
- shortForm = true;
- encodedDisp >>= 2;
- opcode = kThumbStrRRI5;
- } else if (thumb2Form) {
- shortForm = true;
- opcode = kThumb2StrRRI12;
- }
- break;
- case kUnsignedHalf:
- case kSignedHalf:
- if (allLowRegs && displacement < 64 && displacement >= 0) {
- DCHECK_EQ((displacement & 0x1), 0);
- shortForm = true;
- encodedDisp >>= 1;
- opcode = kThumbStrhRRI5;
- } else if (thumb2Form) {
- shortForm = true;
- opcode = kThumb2StrhRRI12;
- }
- break;
- case kUnsignedByte:
- case kSignedByte:
- if (allLowRegs && displacement < 32 && displacement >= 0) {
- shortForm = true;
- opcode = kThumbStrbRRI5;
- } else if (thumb2Form) {
- shortForm = true;
- opcode = kThumb2StrbRRI12;
- }
- break;
- default:
- LOG(FATAL) << "Bad size: " << (int)size;
- }
- if (shortForm) {
- store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp);
- } else {
- int rScratch = oatAllocTemp(cUnit);
- res = loadConstant(cUnit, rScratch, encodedDisp);
- store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
- oatFreeTemp(cUnit, rScratch);
- }
+ LIR* res, *store;
+ ArmOpcode opcode = kThumbBkpt;
+ bool shortForm = false;
+ bool thumb2Form = (displacement < 4092 && displacement >= 0);
+ bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
+ int encodedDisp = displacement;
+ bool is64bit = false;
+ switch (size) {
+ case kLong:
+ case kDouble:
+ is64bit = true;
+ if (!FPREG(rSrc)) {
+ res = storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, kWord);
+ storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi, -1, kWord);
+ return res;
+ }
+ if (SINGLEREG(rSrc)) {
+ DCHECK(FPREG(rSrcHi));
+ rSrc = S2D(rSrc, rSrcHi);
+ }
+ opcode = kThumb2Vstrd;
+ if (displacement <= 1020) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ }
+ break;
+ case kSingle:
+ case kWord:
+ if (FPREG(rSrc)) {
+ DCHECK(SINGLEREG(rSrc));
+ opcode = kThumb2Vstrs;
+ if (displacement <= 1020) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ }
+ break;
+ }
+ if (allLowRegs && displacement < 128 && displacement >= 0) {
+ DCHECK_EQ((displacement & 0x3), 0);
+ shortForm = true;
+ encodedDisp >>= 2;
+ opcode = kThumbStrRRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opcode = kThumb2StrRRI12;
+ }
+ break;
+ case kUnsignedHalf:
+ case kSignedHalf:
+ if (allLowRegs && displacement < 64 && displacement >= 0) {
+ DCHECK_EQ((displacement & 0x1), 0);
+ shortForm = true;
+ encodedDisp >>= 1;
+ opcode = kThumbStrhRRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opcode = kThumb2StrhRRI12;
+ }
+ break;
+ case kUnsignedByte:
+ case kSignedByte:
+ if (allLowRegs && displacement < 32 && displacement >= 0) {
+ shortForm = true;
+ opcode = kThumbStrbRRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opcode = kThumb2StrbRRI12;
+ }
+ break;
+ default:
+ LOG(FATAL) << "Bad size: " << (int)size;
+ }
+ if (shortForm) {
+ store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp);
+ } else {
+ int rScratch = oatAllocTemp(cUnit);
+ res = loadConstant(cUnit, rScratch, encodedDisp);
+ store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
+ oatFreeTemp(cUnit, rScratch);
+ }
- // TODO: In future, may need to differentiate Dalvik & spill accesses
- if (rBase == rSP) {
- annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */, is64bit);
- }
- return res;
+ // TODO: In future, may need to differentiate Dalvik & spill accesses
+ if (rBase == rSP) {
+ annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */,
+ is64bit);
+ }
+ return res;
}
LIR* storeBaseDisp(CompilationUnit* cUnit, int rBase, int displacement,
int rSrc, OpSize size)
{
- return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
+ return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
}
LIR* storeBaseDispWide(CompilationUnit* cUnit, int rBase, int displacement,
int rSrcLo, int rSrcHi)
{
- return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
+ return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
}
void storePair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
{
- storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
+ storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
}
void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
{
- loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
+ loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
}
LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
{
- int opcode;
- DCHECK_EQ(DOUBLEREG(rDest), DOUBLEREG(rSrc));
- if (DOUBLEREG(rDest)) {
- opcode = kThumb2Vmovd;
+ int opcode;
+ DCHECK_EQ(DOUBLEREG(rDest), DOUBLEREG(rSrc));
+ if (DOUBLEREG(rDest)) {
+ opcode = kThumb2Vmovd;
+ } else {
+ if (SINGLEREG(rDest)) {
+ opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
} else {
- if (SINGLEREG(rDest)) {
- opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
- } else {
- DCHECK(SINGLEREG(rSrc));
- opcode = kThumb2Fmrs;
- }
+ DCHECK(SINGLEREG(rSrc));
+ opcode = kThumb2Fmrs;
}
- LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
- if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
- res->flags.isNop = true;
- }
- return res;
+ }
+ LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
+ if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
+ res->flags.isNop = true;
+ }
+ return res;
}
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 5451d57..5252b49 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -31,8 +31,8 @@
/* Return the position of an ssa name within the argument list */
int inPosition(CompilationUnit* cUnit, int sReg)
{
- int vReg = SRegToVReg(cUnit, sReg);
- return vReg - cUnit->numRegs;
+ int vReg = SRegToVReg(cUnit, sReg);
+ return vReg - cUnit->numRegs;
}
/*
@@ -42,27 +42,27 @@
*/
RegLocation argLoc(CompilationUnit* cUnit, RegLocation loc)
{
- int argNum = inPosition(cUnit, loc.sRegLow);
- if (loc.wide) {
- if (argNum == 2) {
- // Bad case - half in register, half in frame. Just punt
- loc.location = kLocInvalid;
- } else if (argNum < 2) {
- loc.lowReg = rARG1 + argNum;
- loc.highReg = loc.lowReg + 1;
- loc.location = kLocPhysReg;
- } else {
- loc.location = kLocDalvikFrame;
- }
+ int argNum = inPosition(cUnit, loc.sRegLow);
+ if (loc.wide) {
+ if (argNum == 2) {
+ // Bad case - half in register, half in frame. Just punt
+ loc.location = kLocInvalid;
+ } else if (argNum < 2) {
+ loc.lowReg = rARG1 + argNum;
+ loc.highReg = loc.lowReg + 1;
+ loc.location = kLocPhysReg;
} else {
- if (argNum < 3) {
- loc.lowReg = rARG1 + argNum;
- loc.location = kLocPhysReg;
- } else {
- loc.location = kLocDalvikFrame;
- }
+ loc.location = kLocDalvikFrame;
}
- return loc;
+ } else {
+ if (argNum < 3) {
+ loc.lowReg = rARG1 + argNum;
+ loc.location = kLocPhysReg;
+ } else {
+ loc.location = kLocDalvikFrame;
+ }
+ }
+ return loc;
}
/*
@@ -72,243 +72,241 @@
*/
RegLocation loadArg(CompilationUnit* cUnit, RegLocation loc)
{
- if (loc.location == kLocDalvikFrame) {
- int start = (inPosition(cUnit, loc.sRegLow) + 1) * sizeof(uint32_t);
- loc.lowReg = oatAllocTemp(cUnit);
- loadWordDisp(cUnit, rSP, start, loc.lowReg);
- if (loc.wide) {
- loc.highReg = oatAllocTemp(cUnit);
- loadWordDisp(cUnit, rSP, start + sizeof(uint32_t), loc.highReg);
- }
- loc.location = kLocPhysReg;
+ if (loc.location == kLocDalvikFrame) {
+ int start = (inPosition(cUnit, loc.sRegLow) + 1) * sizeof(uint32_t);
+ loc.lowReg = oatAllocTemp(cUnit);
+ loadWordDisp(cUnit, rSP, start, loc.lowReg);
+ if (loc.wide) {
+ loc.highReg = oatAllocTemp(cUnit);
+ loadWordDisp(cUnit, rSP, start + sizeof(uint32_t), loc.highReg);
}
- return loc;
+ loc.location = kLocPhysReg;
+ }
+ return loc;
}
/* Lock any referenced arguments that arrive in registers */
void lockLiveArgs(CompilationUnit* cUnit, MIR* mir)
{
- int firstIn = cUnit->numRegs;
- const int numArgRegs = 3; // TODO: generalize & move to RegUtil.cc
- for (int i = 0; i < mir->ssaRep->numUses; i++) {
- int vReg = SRegToVReg(cUnit, mir->ssaRep->uses[i]);
- int inPosition = vReg - firstIn;
- if (inPosition < numArgRegs) {
- oatLockTemp(cUnit, rARG1 + inPosition);
- }
+ int firstIn = cUnit->numRegs;
+ const int numArgRegs = 3; // TODO: generalize & move to RegUtil.cc
+ for (int i = 0; i < mir->ssaRep->numUses; i++) {
+ int vReg = SRegToVReg(cUnit, mir->ssaRep->uses[i]);
+ int inPosition = vReg - firstIn;
+ if (inPosition < numArgRegs) {
+ oatLockTemp(cUnit, rARG1 + inPosition);
}
+ }
}
/* Find the next MIR, which may be in a following basic block */
MIR* getNextMir(CompilationUnit* cUnit, BasicBlock** pBb, MIR* mir)
{
- BasicBlock* bb = *pBb;
- MIR* origMir = mir;
- while (bb != NULL) {
- if (mir != NULL) {
- mir = mir->next;
- }
- if (mir != NULL) {
- return mir;
- } else {
- bb = bb->fallThrough;
- *pBb = bb;
- if (bb) {
- mir = bb->firstMIRInsn;
- if (mir != NULL) {
- return mir;
- }
- }
- }
+ BasicBlock* bb = *pBb;
+ MIR* origMir = mir;
+ while (bb != NULL) {
+ if (mir != NULL) {
+ mir = mir->next;
}
- return origMir;
+ if (mir != NULL) {
+ return mir;
+ } else {
+ bb = bb->fallThrough;
+ *pBb = bb;
+ if (bb) {
+ mir = bb->firstMIRInsn;
+ if (mir != NULL) {
+ return mir;
+ }
+ }
+ }
+ }
+ return origMir;
}
/* Used for the "printMe" listing */
void genPrintLabel(CompilationUnit *cUnit, MIR* mir)
{
- LIR* boundaryLIR;
- /* Mark the beginning of a Dalvik instruction for line tracking */
- char* instStr = cUnit->printMe ?
- oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
- boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
- (intptr_t) instStr);
- cUnit->boundaryMap.Put(mir->offset, boundaryLIR);
- /* Don't generate the SSA annotation unless verbose mode is on */
- if (cUnit->printMe && mir->ssaRep) {
- char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
- newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
- }
+ LIR* boundaryLIR;
+ /* Mark the beginning of a Dalvik instruction for line tracking */
+ char* instStr = cUnit->printMe ?
+ oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
+ boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
+ (intptr_t) instStr);
+ cUnit->boundaryMap.Put(mir->offset, boundaryLIR);
+ /* Don't generate the SSA annotation unless verbose mode is on */
+ if (cUnit->printMe && mir->ssaRep) {
+ char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
+ newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
+ }
}
MIR* specialIGet(CompilationUnit* cUnit, BasicBlock** bb, MIR* mir,
OpSize size, bool longOrDouble, bool isObject)
{
- int fieldOffset;
- bool isVolatile;
- uint32_t fieldIdx = mir->dalvikInsn.vC;
- bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile,
- false);
- if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) {
- return NULL;
- }
- RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
- lockLiveArgs(cUnit, mir);
- rlObj = argLoc(cUnit, rlObj);
- RegLocation rlDest;
- if (longOrDouble) {
- rlDest = oatGetReturnWide(cUnit, false);
- } else {
- rlDest = oatGetReturn(cUnit, false);
- }
- // Point of no return - no aborts after this
- genPrintLabel(cUnit, mir);
- rlObj = loadArg(cUnit, rlObj);
- genIGet(cUnit, mir, size, rlDest, rlObj, longOrDouble, isObject);
- return getNextMir(cUnit, bb, mir);
+ int fieldOffset;
+ bool isVolatile;
+ uint32_t fieldIdx = mir->dalvikInsn.vC;
+ bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile, false);
+ if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) {
+ return NULL;
+ }
+ RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
+ lockLiveArgs(cUnit, mir);
+ rlObj = argLoc(cUnit, rlObj);
+ RegLocation rlDest;
+ if (longOrDouble) {
+ rlDest = oatGetReturnWide(cUnit, false);
+ } else {
+ rlDest = oatGetReturn(cUnit, false);
+ }
+ // Point of no return - no aborts after this
+ genPrintLabel(cUnit, mir);
+ rlObj = loadArg(cUnit, rlObj);
+ genIGet(cUnit, mir, size, rlDest, rlObj, longOrDouble, isObject);
+ return getNextMir(cUnit, bb, mir);
}
MIR* specialIPut(CompilationUnit* cUnit, BasicBlock** bb, MIR* mir,
OpSize size, bool longOrDouble, bool isObject)
{
- int fieldOffset;
- bool isVolatile;
- uint32_t fieldIdx = mir->dalvikInsn.vC;
- bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile,
- false);
- if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) {
- return NULL;
- }
- RegLocation rlSrc;
- RegLocation rlObj;
- lockLiveArgs(cUnit, mir);
- if (longOrDouble) {
- rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- rlObj = oatGetSrc(cUnit, mir, 2);
- } else {
- rlSrc = oatGetSrc(cUnit, mir, 0);
- rlObj = oatGetSrc(cUnit, mir, 1);
- }
- rlSrc = argLoc(cUnit, rlSrc);
- rlObj = argLoc(cUnit, rlObj);
- // Reject if source is split across registers & frame
- if (rlObj.location == kLocInvalid) {
- oatResetRegPool(cUnit);
- return NULL;
- }
- // Point of no return - no aborts after this
- genPrintLabel(cUnit, mir);
- rlObj = loadArg(cUnit, rlObj);
- rlSrc = loadArg(cUnit, rlSrc);
- genIPut(cUnit, mir, size, rlSrc, rlObj, longOrDouble, isObject);
- return getNextMir(cUnit, bb, mir);
+ int fieldOffset;
+ bool isVolatile;
+ uint32_t fieldIdx = mir->dalvikInsn.vC;
+ bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile, false);
+ if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) {
+ return NULL;
+ }
+ RegLocation rlSrc;
+ RegLocation rlObj;
+ lockLiveArgs(cUnit, mir);
+ if (longOrDouble) {
+ rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+ rlObj = oatGetSrc(cUnit, mir, 2);
+ } else {
+ rlSrc = oatGetSrc(cUnit, mir, 0);
+ rlObj = oatGetSrc(cUnit, mir, 1);
+ }
+ rlSrc = argLoc(cUnit, rlSrc);
+ rlObj = argLoc(cUnit, rlObj);
+ // Reject if source is split across registers & frame
+ if (rlObj.location == kLocInvalid) {
+ oatResetRegPool(cUnit);
+ return NULL;
+ }
+ // Point of no return - no aborts after this
+ genPrintLabel(cUnit, mir);
+ rlObj = loadArg(cUnit, rlObj);
+ rlSrc = loadArg(cUnit, rlSrc);
+ genIPut(cUnit, mir, size, rlSrc, rlObj, longOrDouble, isObject);
+ return getNextMir(cUnit, bb, mir);
}
MIR* specialIdentity(CompilationUnit* cUnit, MIR* mir)
{
- RegLocation rlSrc;
- RegLocation rlDest;
- bool wide = (mir->ssaRep->numUses == 2);
- if (wide) {
- rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- rlDest = oatGetReturnWide(cUnit, false);
- } else {
- rlSrc = oatGetSrc(cUnit, mir, 0);
- rlDest = oatGetReturn(cUnit, false);
- }
- lockLiveArgs(cUnit, mir);
- rlSrc = argLoc(cUnit, rlSrc);
- if (rlSrc.location == kLocInvalid) {
- oatResetRegPool(cUnit);
- return NULL;
- }
- // Point of no return - no aborts after this
- genPrintLabel(cUnit, mir);
- rlSrc = loadArg(cUnit, rlSrc);
- if (wide) {
- storeValueWide(cUnit, rlDest, rlSrc);
- } else {
- storeValue(cUnit, rlDest, rlSrc);
- }
- return mir;
+ RegLocation rlSrc;
+ RegLocation rlDest;
+ bool wide = (mir->ssaRep->numUses == 2);
+ if (wide) {
+ rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+ rlDest = oatGetReturnWide(cUnit, false);
+ } else {
+ rlSrc = oatGetSrc(cUnit, mir, 0);
+ rlDest = oatGetReturn(cUnit, false);
+ }
+ lockLiveArgs(cUnit, mir);
+ rlSrc = argLoc(cUnit, rlSrc);
+ if (rlSrc.location == kLocInvalid) {
+ oatResetRegPool(cUnit);
+ return NULL;
+ }
+ // Point of no return - no aborts after this
+ genPrintLabel(cUnit, mir);
+ rlSrc = loadArg(cUnit, rlSrc);
+ if (wide) {
+ storeValueWide(cUnit, rlDest, rlSrc);
+ } else {
+ storeValue(cUnit, rlDest, rlSrc);
+ }
+ return mir;
}
/*
* Special-case code genration for simple non-throwing leaf methods.
*/
void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
- SpecialCaseHandler specialCase)
+ SpecialCaseHandler specialCase)
{
cUnit->currentDalvikOffset = mir->offset;
MIR* nextMir = NULL;
switch (specialCase) {
- case kNullMethod:
- DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID);
- nextMir = mir;
- break;
- case kConstFunction:
- genPrintLabel(cUnit, mir);
- loadConstant(cUnit, rRET0, mir->dalvikInsn.vB);
- nextMir = getNextMir(cUnit, &bb, mir);
- break;
- case kIGet:
- nextMir = specialIGet(cUnit, &bb, mir, kWord, false, false);
- break;
- case kIGetBoolean:
- case kIGetByte:
- nextMir = specialIGet(cUnit, &bb, mir, kUnsignedByte, false, false);
- break;
- case kIGetObject:
- nextMir = specialIGet(cUnit, &bb, mir, kWord, false, true);
- break;
- case kIGetChar:
- nextMir = specialIGet(cUnit, &bb, mir, kUnsignedHalf, false, false);
- break;
- case kIGetShort:
- nextMir = specialIGet(cUnit, &bb, mir, kSignedHalf, false, false);
- break;
- case kIGetWide:
- nextMir = specialIGet(cUnit, &bb, mir, kLong, true, false);
- break;
- case kIPut:
- nextMir = specialIPut(cUnit, &bb, mir, kWord, false, false);
- break;
- case kIPutBoolean:
- case kIPutByte:
- nextMir = specialIPut(cUnit, &bb, mir, kUnsignedByte, false, false);
- break;
- case kIPutObject:
- nextMir = specialIPut(cUnit, &bb, mir, kWord, false, true);
- break;
- case kIPutChar:
- nextMir = specialIPut(cUnit, &bb, mir, kUnsignedHalf, false, false);
- break;
- case kIPutShort:
- nextMir = specialIPut(cUnit, &bb, mir, kSignedHalf, false, false);
- break;
- case kIPutWide:
- nextMir = specialIPut(cUnit, &bb, mir, kLong, true, false);
- break;
- case kIdentity:
- nextMir = specialIdentity(cUnit, mir);
- break;
- default:
- return;
+ case kNullMethod:
+ DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID);
+ nextMir = mir;
+ break;
+ case kConstFunction:
+ genPrintLabel(cUnit, mir);
+ loadConstant(cUnit, rRET0, mir->dalvikInsn.vB);
+ nextMir = getNextMir(cUnit, &bb, mir);
+ break;
+ case kIGet:
+ nextMir = specialIGet(cUnit, &bb, mir, kWord, false, false);
+ break;
+ case kIGetBoolean:
+ case kIGetByte:
+ nextMir = specialIGet(cUnit, &bb, mir, kUnsignedByte, false, false);
+ break;
+ case kIGetObject:
+ nextMir = specialIGet(cUnit, &bb, mir, kWord, false, true);
+ break;
+ case kIGetChar:
+ nextMir = specialIGet(cUnit, &bb, mir, kUnsignedHalf, false, false);
+ break;
+ case kIGetShort:
+ nextMir = specialIGet(cUnit, &bb, mir, kSignedHalf, false, false);
+ break;
+ case kIGetWide:
+ nextMir = specialIGet(cUnit, &bb, mir, kLong, true, false);
+ break;
+ case kIPut:
+ nextMir = specialIPut(cUnit, &bb, mir, kWord, false, false);
+ break;
+ case kIPutBoolean:
+ case kIPutByte:
+ nextMir = specialIPut(cUnit, &bb, mir, kUnsignedByte, false, false);
+ break;
+ case kIPutObject:
+ nextMir = specialIPut(cUnit, &bb, mir, kWord, false, true);
+ break;
+ case kIPutChar:
+ nextMir = specialIPut(cUnit, &bb, mir, kUnsignedHalf, false, false);
+ break;
+ case kIPutShort:
+ nextMir = specialIPut(cUnit, &bb, mir, kSignedHalf, false, false);
+ break;
+ case kIPutWide:
+ nextMir = specialIPut(cUnit, &bb, mir, kLong, true, false);
+ break;
+ case kIdentity:
+ nextMir = specialIdentity(cUnit, mir);
+ break;
+ default:
+ return;
}
if (nextMir != NULL) {
- cUnit->currentDalvikOffset = nextMir->offset;
- if (specialCase != kIdentity) {
- genPrintLabel(cUnit, nextMir);
- }
- newLIR1(cUnit, kThumbBx, rLR);
- cUnit->coreSpillMask = 0;
- cUnit->numCoreSpills = 0;
- cUnit->fpSpillMask = 0;
- cUnit->numFPSpills = 0;
- cUnit->frameSize = 0;
- cUnit->coreVmapTable.clear();
- cUnit->fpVmapTable.clear();
+ cUnit->currentDalvikOffset = nextMir->offset;
+ if (specialCase != kIdentity) {
+ genPrintLabel(cUnit, nextMir);
}
+ newLIR1(cUnit, kThumbBx, rLR);
+ cUnit->coreSpillMask = 0;
+ cUnit->numCoreSpills = 0;
+ cUnit->fpSpillMask = 0;
+ cUnit->numFPSpills = 0;
+ cUnit->frameSize = 0;
+ cUnit->coreVmapTable.clear();
+ cUnit->fpVmapTable.clear();
+ }
}
/*
@@ -323,30 +321,30 @@
*/
LIR* opIT(CompilationUnit* cUnit, ArmConditionCode code, const char* guide)
{
- int mask;
- int condBit = code & 1;
- int altBit = condBit ^ 1;
- int mask3 = 0;
- int mask2 = 0;
- int mask1 = 0;
+ int mask;
+ int condBit = code & 1;
+ int altBit = condBit ^ 1;
+ int mask3 = 0;
+ int mask2 = 0;
+ int mask1 = 0;
- //Note: case fallthroughs intentional
- switch (strlen(guide)) {
- case 3:
- mask1 = (guide[2] == 'T') ? condBit : altBit;
- case 2:
- mask2 = (guide[1] == 'T') ? condBit : altBit;
- case 1:
- mask3 = (guide[0] == 'T') ? condBit : altBit;
- break;
- case 0:
- break;
- default:
- LOG(FATAL) << "OAT: bad case in opIT";
- }
- mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
- (1 << (3 - strlen(guide)));
- return newLIR2(cUnit, kThumb2It, code, mask);
+ //Note: case fallthroughs intentional
+ switch (strlen(guide)) {
+ case 3:
+ mask1 = (guide[2] == 'T') ? condBit : altBit;
+ case 2:
+ mask2 = (guide[1] == 'T') ? condBit : altBit;
+ case 1:
+ mask3 = (guide[0] == 'T') ? condBit : altBit;
+ break;
+ case 0:
+ break;
+ default:
+ LOG(FATAL) << "OAT: bad case in opIT";
+ }
+ mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
+ (1 << (3 - strlen(guide)));
+ return newLIR2(cUnit, kThumb2It, code, mask);
}
/*
@@ -371,97 +369,95 @@
void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
LIR* labelList)
{
- const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
- if (cUnit->printMe) {
- dumpSparseSwitchTable(table);
- }
- // Add the table to the list - we'll process it later
- SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
- true, kAllocData);
- tabRec->table = table;
- tabRec->vaddr = mir->offset;
- int size = table[1];
- tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
- kAllocLIR);
- oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
+ const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
+ if (cUnit->printMe) {
+ dumpSparseSwitchTable(table);
+ }
+ // Add the table to the list - we'll process it later
+ SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
+ true, kAllocData);
+ tabRec->table = table;
+ tabRec->vaddr = mir->offset;
+ int size = table[1];
+ tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, kAllocLIR);
+ oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
- // Get the switch value
- rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- int rBase = oatAllocTemp(cUnit);
- /* Allocate key and disp temps */
- int rKey = oatAllocTemp(cUnit);
- int rDisp = oatAllocTemp(cUnit);
- // Make sure rKey's register number is less than rDisp's number for ldmia
- if (rKey > rDisp) {
- int tmp = rDisp;
- rDisp = rKey;
- rKey = tmp;
- }
- // Materialize a pointer to the switch table
- newLIR3(cUnit, kThumb2Adr, rBase, 0, (intptr_t)tabRec);
- // Set up rIdx
- int rIdx = oatAllocTemp(cUnit);
- loadConstant(cUnit, rIdx, size);
- // Establish loop branch target
- LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
- // Load next key/disp
- newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp));
- opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg);
- // Go if match. NOTE: No instruction set switch here - must stay Thumb2
- opIT(cUnit, kArmCondEq, "");
- LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);
- tabRec->anchor = switchBranch;
- // Needs to use setflags encoding here
- newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
- opCondBranch(cUnit, kCondNe, target);
+ // Get the switch value
+ rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+ int rBase = oatAllocTemp(cUnit);
+ /* Allocate key and disp temps */
+ int rKey = oatAllocTemp(cUnit);
+ int rDisp = oatAllocTemp(cUnit);
+ // Make sure rKey's register number is less than rDisp's number for ldmia
+ if (rKey > rDisp) {
+ int tmp = rDisp;
+ rDisp = rKey;
+ rKey = tmp;
+ }
+ // Materialize a pointer to the switch table
+ newLIR3(cUnit, kThumb2Adr, rBase, 0, (intptr_t)tabRec);
+ // Set up rIdx
+ int rIdx = oatAllocTemp(cUnit);
+ loadConstant(cUnit, rIdx, size);
+ // Establish loop branch target
+ LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+ // Load next key/disp
+ newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp));
+ opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg);
+ // Go if match. NOTE: No instruction set switch here - must stay Thumb2
+ opIT(cUnit, kArmCondEq, "");
+ LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);
+ tabRec->anchor = switchBranch;
+ // Needs to use setflags encoding here
+ newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
+ opCondBranch(cUnit, kCondNe, target);
}
void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
- if (cUnit->printMe) {
- dumpPackedSwitchTable(table);
- }
- // Add the table to the list - we'll process it later
- SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
- true, kAllocData);
- tabRec->table = table;
- tabRec->vaddr = mir->offset;
- int size = table[1];
- tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
- kAllocLIR);
- oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
+ const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
+ if (cUnit->printMe) {
+ dumpPackedSwitchTable(table);
+ }
+ // Add the table to the list - we'll process it later
+ SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
+ true, kAllocData);
+ tabRec->table = table;
+ tabRec->vaddr = mir->offset;
+ int size = table[1];
+ tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, kAllocLIR);
+ oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
- // Get the switch value
- rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- int tableBase = oatAllocTemp(cUnit);
- // Materialize a pointer to the switch table
- newLIR3(cUnit, kThumb2Adr, tableBase, 0, (intptr_t)tabRec);
- int lowKey = s4FromSwitchData(&table[2]);
- int keyReg;
- // Remove the bias, if necessary
- if (lowKey == 0) {
- keyReg = rlSrc.lowReg;
- } else {
- keyReg = oatAllocTemp(cUnit);
- opRegRegImm(cUnit, kOpSub, keyReg, rlSrc.lowReg, lowKey);
- }
- // Bounds check - if < 0 or >= size continue following switch
- opRegImm(cUnit, kOpCmp, keyReg, size-1);
- LIR* branchOver = opCondBranch(cUnit, kCondHi, NULL);
+ // Get the switch value
+ rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+ int tableBase = oatAllocTemp(cUnit);
+ // Materialize a pointer to the switch table
+ newLIR3(cUnit, kThumb2Adr, tableBase, 0, (intptr_t)tabRec);
+ int lowKey = s4FromSwitchData(&table[2]);
+ int keyReg;
+ // Remove the bias, if necessary
+ if (lowKey == 0) {
+ keyReg = rlSrc.lowReg;
+ } else {
+ keyReg = oatAllocTemp(cUnit);
+ opRegRegImm(cUnit, kOpSub, keyReg, rlSrc.lowReg, lowKey);
+ }
+ // Bounds check - if < 0 or >= size continue following switch
+ opRegImm(cUnit, kOpCmp, keyReg, size-1);
+ LIR* branchOver = opCondBranch(cUnit, kCondHi, NULL);
- // Load the displacement from the switch table
- int dispReg = oatAllocTemp(cUnit);
- loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord);
+ // Load the displacement from the switch table
+ int dispReg = oatAllocTemp(cUnit);
+ loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord);
- // ..and go! NOTE: No instruction set switch here - must stay Thumb2
- LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);
- tabRec->anchor = switchBranch;
+ // ..and go! NOTE: No instruction set switch here - must stay Thumb2
+ LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);
+ tabRec->anchor = switchBranch;
- /* branchOver target here */
- LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
- branchOver->target = (LIR*)target;
+ /* branchOver target here */
+ LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+ branchOver->target = (LIR*)target;
}
/*
@@ -476,46 +472,46 @@
*/
void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
- // Add the table to the list - we'll process it later
- FillArrayData *tabRec = (FillArrayData *)
- oatNew(cUnit, sizeof(FillArrayData), true, kAllocData);
- tabRec->table = table;
- tabRec->vaddr = mir->offset;
- u2 width = tabRec->table[1];
- u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16);
- tabRec->size = (size * width) + 8;
+ const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
+ // Add the table to the list - we'll process it later
+ FillArrayData *tabRec = (FillArrayData *)
+ oatNew(cUnit, sizeof(FillArrayData), true, kAllocData);
+ tabRec->table = table;
+ tabRec->vaddr = mir->offset;
+ u2 width = tabRec->table[1];
+ u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16);
+ tabRec->size = (size * width) + 8;
- oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec);
+ oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec);
- // Making a call - use explicit registers
- oatFlushAllRegs(cUnit); /* Everything to home location */
- loadValueDirectFixed(cUnit, rlSrc, r0);
- loadWordDisp(cUnit, rSELF,
- ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rLR);
- // Materialize a pointer to the fill data image
- newLIR3(cUnit, kThumb2Adr, r1, 0, (intptr_t)tabRec);
- oatClobberCalleeSave(cUnit);
- opReg(cUnit, kOpBlx, rLR);
+ // Making a call - use explicit registers
+ oatFlushAllRegs(cUnit); /* Everything to home location */
+ loadValueDirectFixed(cUnit, rlSrc, r0);
+ loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode),
+ rLR);
+ // Materialize a pointer to the fill data image
+ newLIR3(cUnit, kThumb2Adr, r1, 0, (intptr_t)tabRec);
+ oatClobberCalleeSave(cUnit);
+ opReg(cUnit, kOpBlx, rLR);
}
void genNegFloat(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
{
- RegLocation rlResult;
- rlSrc = loadValue(cUnit, rlSrc, kFPReg);
- rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR2(cUnit, kThumb2Vnegs, rlResult.lowReg, rlSrc.lowReg);
- storeValue(cUnit, rlDest, rlResult);
+ RegLocation rlResult;
+ rlSrc = loadValue(cUnit, rlSrc, kFPReg);
+ rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
+ newLIR2(cUnit, kThumb2Vnegs, rlResult.lowReg, rlSrc.lowReg);
+ storeValue(cUnit, rlDest, rlResult);
}
void genNegDouble(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
{
- RegLocation rlResult;
- rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
- rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR2(cUnit, kThumb2Vnegd, S2D(rlResult.lowReg, rlResult.highReg),
- S2D(rlSrc.lowReg, rlSrc.highReg));
- storeValueWide(cUnit, rlDest, rlResult);
+ RegLocation rlResult;
+ rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
+ rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
+ newLIR2(cUnit, kThumb2Vnegd, S2D(rlResult.lowReg, rlResult.highReg),
+ S2D(rlSrc.lowReg, rlSrc.highReg));
+ storeValueWide(cUnit, rlDest, rlResult);
}
/*
@@ -546,31 +542,30 @@
*/
void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- oatFlushAllRegs(cUnit);
- DCHECK_EQ(LW_SHAPE_THIN, 0);
- loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj
- oatLockCallTemps(cUnit); // Prepare for explicit register usage
- genNullCheck(cUnit, rlSrc.sRegLow, r0, mir);
- loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2);
- newLIR3(cUnit, kThumb2Ldrex, r1, r0,
- Object::MonitorOffset().Int32Value() >> 2); // Get object->lock
- // Align owner
- opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT);
- // Is lock unheld on lock or held by us (==threadId) on unlock?
- newLIR4(cUnit, kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1);
- newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
- opRegImm(cUnit, kOpCmp, r1, 0);
- opIT(cUnit, kArmCondEq, "");
- newLIR4(cUnit, kThumb2Strex, r1, r2, r0,
- Object::MonitorOffset().Int32Value() >> 2);
- opRegImm(cUnit, kOpCmp, r1, 0);
- opIT(cUnit, kArmCondNe, "T");
- // Go expensive route - artLockObjectFromCode(self, obj);
- loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pLockObjectFromCode),
- rLR);
- oatClobberCalleeSave(cUnit);
- opReg(cUnit, kOpBlx, rLR);
- oatGenMemBarrier(cUnit, kSY);
+ oatFlushAllRegs(cUnit);
+ DCHECK_EQ(LW_SHAPE_THIN, 0);
+ loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj
+ oatLockCallTemps(cUnit); // Prepare for explicit register usage
+ genNullCheck(cUnit, rlSrc.sRegLow, r0, mir);
+ loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2);
+ newLIR3(cUnit, kThumb2Ldrex, r1, r0,
+ Object::MonitorOffset().Int32Value() >> 2); // Get object->lock
+ // Align owner
+ opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT);
+ // Is lock unheld on lock or held by us (==threadId) on unlock?
+ newLIR4(cUnit, kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1);
+ newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
+ opRegImm(cUnit, kOpCmp, r1, 0);
+ opIT(cUnit, kArmCondEq, "");
+ newLIR4(cUnit, kThumb2Strex, r1, r2, r0,
+ Object::MonitorOffset().Int32Value() >> 2);
+ opRegImm(cUnit, kOpCmp, r1, 0);
+ opIT(cUnit, kArmCondNe, "T");
+ // Go expensive route - artLockObjectFromCode(self, obj);
+ loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), rLR);
+ oatClobberCalleeSave(cUnit);
+ opReg(cUnit, kOpBlx, rLR);
+ oatGenMemBarrier(cUnit, kSY);
}
/*
@@ -581,27 +576,27 @@
*/
void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- DCHECK_EQ(LW_SHAPE_THIN, 0);
- oatFlushAllRegs(cUnit);
- loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj
- oatLockCallTemps(cUnit); // Prepare for explicit register usage
- genNullCheck(cUnit, rlSrc.sRegLow, r0, mir);
- loadWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r1); // Get lock
- loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2);
- // Is lock unheld on lock or held by us (==threadId) on unlock?
- opRegRegImm(cUnit, kOpAnd, r3, r1, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
- // Align owner
- opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT);
- newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
- opRegReg(cUnit, kOpSub, r1, r2);
- opIT(cUnit, kArmCondEq, "EE");
- storeWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r3);
- // Go expensive route - UnlockObjectFromCode(obj);
- loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode),
- rLR);
- oatClobberCalleeSave(cUnit);
- opReg(cUnit, kOpBlx, rLR);
- oatGenMemBarrier(cUnit, kSY);
+ DCHECK_EQ(LW_SHAPE_THIN, 0);
+ oatFlushAllRegs(cUnit);
+ loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj
+ oatLockCallTemps(cUnit); // Prepare for explicit register usage
+ genNullCheck(cUnit, rlSrc.sRegLow, r0, mir);
+ loadWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r1); // Get lock
+ loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2);
+ // Is lock unheld on lock or held by us (==threadId) on unlock?
+ opRegRegImm(cUnit, kOpAnd, r3, r1,
+ (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+ // Align owner
+ opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT);
+ newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
+ opRegReg(cUnit, kOpSub, r1, r2);
+ opIT(cUnit, kArmCondEq, "EE");
+ storeWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r3);
+ // Go expensive route - UnlockObjectFromCode(obj);
+ loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rLR);
+ oatClobberCalleeSave(cUnit);
+ opReg(cUnit, kOpBlx, rLR);
+ oatGenMemBarrier(cUnit, kSY);
}
/*
@@ -620,83 +615,83 @@
* done:
*/
void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
- RegLocation rlSrc1, RegLocation rlSrc2)
+ RegLocation rlSrc1, RegLocation rlSrc2)
{
- LIR* target1;
- LIR* target2;
- rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
- rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
- int tReg = oatAllocTemp(cUnit);
- loadConstant(cUnit, tReg, -1);
- opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
- LIR* branch1 = opCondBranch(cUnit, kCondLt, NULL);
- LIR* branch2 = opCondBranch(cUnit, kCondGt, NULL);
- opRegRegReg(cUnit, kOpSub, tReg, rlSrc1.lowReg, rlSrc2.lowReg);
- LIR* branch3 = opCondBranch(cUnit, kCondEq, NULL);
+ LIR* target1;
+ LIR* target2;
+ rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
+ rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
+ int tReg = oatAllocTemp(cUnit);
+ loadConstant(cUnit, tReg, -1);
+ opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
+ LIR* branch1 = opCondBranch(cUnit, kCondLt, NULL);
+ LIR* branch2 = opCondBranch(cUnit, kCondGt, NULL);
+ opRegRegReg(cUnit, kOpSub, tReg, rlSrc1.lowReg, rlSrc2.lowReg);
+ LIR* branch3 = opCondBranch(cUnit, kCondEq, NULL);
- opIT(cUnit, kArmCondHi, "E");
- newLIR2(cUnit, kThumb2MovImmShift, tReg, modifiedImmediate(-1));
- loadConstant(cUnit, tReg, 1);
- genBarrier(cUnit);
+ opIT(cUnit, kArmCondHi, "E");
+ newLIR2(cUnit, kThumb2MovImmShift, tReg, modifiedImmediate(-1));
+ loadConstant(cUnit, tReg, 1);
+ genBarrier(cUnit);
- target2 = newLIR0(cUnit, kPseudoTargetLabel);
- opRegReg(cUnit, kOpNeg, tReg, tReg);
+ target2 = newLIR0(cUnit, kPseudoTargetLabel);
+ opRegReg(cUnit, kOpNeg, tReg, tReg);
- target1 = newLIR0(cUnit, kPseudoTargetLabel);
+ target1 = newLIR0(cUnit, kPseudoTargetLabel);
- RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change
- rlTemp.lowReg = tReg;
- storeValue(cUnit, rlDest, rlTemp);
- oatFreeTemp(cUnit, tReg);
+ RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change
+ rlTemp.lowReg = tReg;
+ storeValue(cUnit, rlDest, rlTemp);
+ oatFreeTemp(cUnit, tReg);
- branch1->target = (LIR*)target1;
- branch2->target = (LIR*)target2;
- branch3->target = branch1->target;
+ branch1->target = (LIR*)target1;
+ branch2->target = (LIR*)target2;
+ branch3->target = branch1->target;
}
void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
{
- LIR* labelList = (LIR*)cUnit->blockLabelList;
- LIR* taken = &labelList[bb->taken->id];
- LIR* notTaken = &labelList[bb->fallThrough->id];
- RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1);
- RegLocation rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3);
- rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
- rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
- ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
- opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
- switch(ccode) {
- case kCondEq:
- opCondBranch(cUnit, kCondNe, notTaken);
- break;
- case kCondNe:
- opCondBranch(cUnit, kCondNe, taken);
- break;
- case kCondLt:
- opCondBranch(cUnit, kCondLt, taken);
- opCondBranch(cUnit, kCondGt, notTaken);
- ccode = kCondCc;
- break;
- case kCondLe:
- opCondBranch(cUnit, kCondLt, taken);
- opCondBranch(cUnit, kCondGt, notTaken);
- ccode = kCondLs;
- break;
- case kCondGt:
- opCondBranch(cUnit, kCondGt, taken);
- opCondBranch(cUnit, kCondLt, notTaken);
- ccode = kCondHi;
- break;
- case kCondGe:
- opCondBranch(cUnit, kCondGt, taken);
- opCondBranch(cUnit, kCondLt, notTaken);
- ccode = kCondCs;
- break;
- default:
- LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
- }
- opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
- opCondBranch(cUnit, ccode, taken);
+ LIR* labelList = (LIR*)cUnit->blockLabelList;
+ LIR* taken = &labelList[bb->taken->id];
+ LIR* notTaken = &labelList[bb->fallThrough->id];
+ RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1);
+ RegLocation rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3);
+ rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
+ rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
+ ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
+ opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
+ switch(ccode) {
+ case kCondEq:
+ opCondBranch(cUnit, kCondNe, notTaken);
+ break;
+ case kCondNe:
+ opCondBranch(cUnit, kCondNe, taken);
+ break;
+ case kCondLt:
+ opCondBranch(cUnit, kCondLt, taken);
+ opCondBranch(cUnit, kCondGt, notTaken);
+ ccode = kCondCc;
+ break;
+ case kCondLe:
+ opCondBranch(cUnit, kCondLt, taken);
+ opCondBranch(cUnit, kCondGt, notTaken);
+ ccode = kCondLs;
+ break;
+ case kCondGt:
+ opCondBranch(cUnit, kCondGt, taken);
+ opCondBranch(cUnit, kCondLt, notTaken);
+ ccode = kCondHi;
+ break;
+ case kCondGe:
+ opCondBranch(cUnit, kCondGt, taken);
+ opCondBranch(cUnit, kCondLt, notTaken);
+ ccode = kCondCs;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
+ }
+ opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
+ opCondBranch(cUnit, ccode, taken);
}
/*
@@ -704,166 +699,165 @@
* is responsible for setting branch target field.
*/
LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
- int checkValue, LIR* target)
+ int checkValue, LIR* target)
{
- LIR* branch;
- int modImm;
- ArmConditionCode armCond = oatArmConditionEncoding(cond);
- if ((LOWREG(reg)) && (checkValue == 0) &&
- ((armCond == kArmCondEq) || (armCond == kArmCondNe))) {
- branch = newLIR2(cUnit,
- (armCond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
- reg, 0);
+ LIR* branch;
+ int modImm;
+ ArmConditionCode armCond = oatArmConditionEncoding(cond);
+ if ((LOWREG(reg)) && (checkValue == 0) &&
+ ((armCond == kArmCondEq) || (armCond == kArmCondNe))) {
+ branch = newLIR2(cUnit, (armCond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
+ reg, 0);
+ } else {
+ modImm = modifiedImmediate(checkValue);
+ if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
+ newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
+ } else if (modImm >= 0) {
+ newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
} else {
- modImm = modifiedImmediate(checkValue);
- if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
- newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
- } else if (modImm >= 0) {
- newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
- } else {
- int tReg = oatAllocTemp(cUnit);
- loadConstant(cUnit, tReg, checkValue);
- opRegReg(cUnit, kOpCmp, reg, tReg);
- }
- branch = newLIR2(cUnit, kThumbBCond, 0, armCond);
+ int tReg = oatAllocTemp(cUnit);
+ loadConstant(cUnit, tReg, checkValue);
+ opRegReg(cUnit, kOpCmp, reg, tReg);
}
- branch->target = target;
- return branch;
+ branch = newLIR2(cUnit, kThumbBCond, 0, armCond);
+ }
+ branch->target = target;
+ return branch;
}
LIR* opRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
{
- LIR* res;
- ArmOpcode opcode;
- if (FPREG(rDest) || FPREG(rSrc))
- return fpRegCopy(cUnit, rDest, rSrc);
- if (LOWREG(rDest) && LOWREG(rSrc))
- opcode = kThumbMovRR;
- else if (!LOWREG(rDest) && !LOWREG(rSrc))
- opcode = kThumbMovRR_H2H;
- else if (LOWREG(rDest))
- opcode = kThumbMovRR_H2L;
- else
- opcode = kThumbMovRR_L2H;
- res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
- if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
- res->flags.isNop = true;
- }
- return res;
+ LIR* res;
+ ArmOpcode opcode;
+ if (FPREG(rDest) || FPREG(rSrc))
+ return fpRegCopy(cUnit, rDest, rSrc);
+ if (LOWREG(rDest) && LOWREG(rSrc))
+ opcode = kThumbMovRR;
+ else if (!LOWREG(rDest) && !LOWREG(rSrc))
+ opcode = kThumbMovRR_H2H;
+ else if (LOWREG(rDest))
+ opcode = kThumbMovRR_H2L;
+ else
+ opcode = kThumbMovRR_L2H;
+ res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
+ if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
+ res->flags.isNop = true;
+ }
+ return res;
}
LIR* opRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
{
- LIR* res = opRegCopyNoInsert(cUnit, rDest, rSrc);
- oatAppendLIR(cUnit, (LIR*)res);
- return res;
+ LIR* res = opRegCopyNoInsert(cUnit, rDest, rSrc);
+ oatAppendLIR(cUnit, (LIR*)res);
+ return res;
}
void opRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
- int srcLo, int srcHi)
+ int srcLo, int srcHi)
{
- bool destFP = FPREG(destLo) && FPREG(destHi);
- bool srcFP = FPREG(srcLo) && FPREG(srcHi);
- DCHECK_EQ(FPREG(srcLo), FPREG(srcHi));
- DCHECK_EQ(FPREG(destLo), FPREG(destHi));
- if (destFP) {
- if (srcFP) {
- opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
- } else {
- newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi);
- }
+ bool destFP = FPREG(destLo) && FPREG(destHi);
+ bool srcFP = FPREG(srcLo) && FPREG(srcHi);
+ DCHECK_EQ(FPREG(srcLo), FPREG(srcHi));
+ DCHECK_EQ(FPREG(destLo), FPREG(destHi));
+ if (destFP) {
+ if (srcFP) {
+ opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
} else {
- if (srcFP) {
- newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi));
- } else {
- // Handle overlap
- if (srcHi == destLo) {
- opRegCopy(cUnit, destHi, srcHi);
- opRegCopy(cUnit, destLo, srcLo);
- } else {
- opRegCopy(cUnit, destLo, srcLo);
- opRegCopy(cUnit, destHi, srcHi);
- }
- }
+ newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi);
}
+ } else {
+ if (srcFP) {
+ newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi));
+ } else {
+ // Handle overlap
+ if (srcHi == destLo) {
+ opRegCopy(cUnit, destHi, srcHi);
+ opRegCopy(cUnit, destLo, srcLo);
+ } else {
+ opRegCopy(cUnit, destLo, srcLo);
+ opRegCopy(cUnit, destHi, srcHi);
+ }
+ }
+ }
}
// Table of magic divisors
enum DividePattern {
- DivideNone,
- Divide3,
- Divide5,
- Divide7,
+ DivideNone,
+ Divide3,
+ Divide5,
+ Divide7,
};
struct MagicTable {
- uint32_t magic;
- uint32_t shift;
- DividePattern pattern;
+ uint32_t magic;
+ uint32_t shift;
+ DividePattern pattern;
};
static const MagicTable magicTable[] = {
- {0, 0, DivideNone}, // 0
- {0, 0, DivideNone}, // 1
- {0, 0, DivideNone}, // 2
- {0x55555556, 0, Divide3}, // 3
- {0, 0, DivideNone}, // 4
- {0x66666667, 1, Divide5}, // 5
- {0x2AAAAAAB, 0, Divide3}, // 6
- {0x92492493, 2, Divide7}, // 7
- {0, 0, DivideNone}, // 8
- {0x38E38E39, 1, Divide5}, // 9
- {0x66666667, 2, Divide5}, // 10
- {0x2E8BA2E9, 1, Divide5}, // 11
- {0x2AAAAAAB, 1, Divide5}, // 12
- {0x4EC4EC4F, 2, Divide5}, // 13
- {0x92492493, 3, Divide7}, // 14
- {0x88888889, 3, Divide7}, // 15
+ {0, 0, DivideNone}, // 0
+ {0, 0, DivideNone}, // 1
+ {0, 0, DivideNone}, // 2
+ {0x55555556, 0, Divide3}, // 3
+ {0, 0, DivideNone}, // 4
+ {0x66666667, 1, Divide5}, // 5
+ {0x2AAAAAAB, 0, Divide3}, // 6
+ {0x92492493, 2, Divide7}, // 7
+ {0, 0, DivideNone}, // 8
+ {0x38E38E39, 1, Divide5}, // 9
+ {0x66666667, 2, Divide5}, // 10
+ {0x2E8BA2E9, 1, Divide5}, // 11
+ {0x2AAAAAAB, 1, Divide5}, // 12
+ {0x4EC4EC4F, 2, Divide5}, // 13
+ {0x92492493, 3, Divide7}, // 14
+ {0x88888889, 3, Divide7}, // 15
};
// Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4)
bool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode,
RegLocation rlSrc, RegLocation rlDest, int lit)
{
- if ((lit < 0) || (lit >= (int)(sizeof(magicTable)/sizeof(magicTable[0])))) {
- return false;
- }
- DividePattern pattern = magicTable[lit].pattern;
- if (pattern == DivideNone) {
- return false;
- }
- // Tuning: add rem patterns
- if (dalvikOpcode != Instruction::DIV_INT_LIT8) {
- return false;
- }
+ if ((lit < 0) || (lit >= (int)(sizeof(magicTable)/sizeof(magicTable[0])))) {
+ return false;
+ }
+ DividePattern pattern = magicTable[lit].pattern;
+ if (pattern == DivideNone) {
+ return false;
+ }
+ // Tuning: add rem patterns
+ if (dalvikOpcode != Instruction::DIV_INT_LIT8) {
+ return false;
+ }
- int rMagic = oatAllocTemp(cUnit);
- loadConstant(cUnit, rMagic, magicTable[lit].magic);
- rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- int rHi = oatAllocTemp(cUnit);
- int rLo = oatAllocTemp(cUnit);
- newLIR4(cUnit, kThumb2Smull, rLo, rHi, rMagic, rlSrc.lowReg);
- switch(pattern) {
- case Divide3:
- opRegRegRegShift(cUnit, kOpSub, rlResult.lowReg, rHi,
- rlSrc.lowReg, encodeShift(kArmAsr, 31));
- break;
- case Divide5:
- opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31);
- opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi,
- encodeShift(kArmAsr, magicTable[lit].shift));
- break;
- case Divide7:
- opRegReg(cUnit, kOpAdd, rHi, rlSrc.lowReg);
- opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31);
- opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi,
- encodeShift(kArmAsr, magicTable[lit].shift));
- break;
- default:
- LOG(FATAL) << "Unexpected pattern: " << (int)pattern;
- }
- storeValue(cUnit, rlDest, rlResult);
- return true;
+ int rMagic = oatAllocTemp(cUnit);
+ loadConstant(cUnit, rMagic, magicTable[lit].magic);
+ rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ int rHi = oatAllocTemp(cUnit);
+ int rLo = oatAllocTemp(cUnit);
+ newLIR4(cUnit, kThumb2Smull, rLo, rHi, rMagic, rlSrc.lowReg);
+ switch(pattern) {
+ case Divide3:
+ opRegRegRegShift(cUnit, kOpSub, rlResult.lowReg, rHi,
+ rlSrc.lowReg, encodeShift(kArmAsr, 31));
+ break;
+ case Divide5:
+ opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31);
+ opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi,
+ encodeShift(kArmAsr, magicTable[lit].shift));
+ break;
+ case Divide7:
+ opRegReg(cUnit, kOpAdd, rHi, rlSrc.lowReg);
+ opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31);
+ opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi,
+ encodeShift(kArmAsr, magicTable[lit].shift));
+ break;
+ default:
+ LOG(FATAL) << "Unexpected pattern: " << (int)pattern;
+ }
+ storeValue(cUnit, rlDest, rlResult);
+ return true;
}
} // namespace art
diff --git a/src/compiler/codegen/arm/Thumb2/Ralloc.cc b/src/compiler/codegen/arm/Thumb2/Ralloc.cc
index 7858318..98a110c 100644
--- a/src/compiler/codegen/arm/Thumb2/Ralloc.cc
+++ b/src/compiler/codegen/arm/Thumb2/Ralloc.cc
@@ -30,96 +30,96 @@
*/
int oatAllocTypedTempPair(CompilationUnit* cUnit, bool fpHint, int regClass)
{
- int highReg;
- int lowReg;
- int res = 0;
+ int highReg;
+ int lowReg;
+ int res = 0;
- if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
- lowReg = oatAllocTempDouble(cUnit);
- highReg = lowReg + 1;
- } else {
- lowReg = oatAllocTemp(cUnit);
- highReg = oatAllocTemp(cUnit);
- }
- res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
- return res;
+ if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
+ lowReg = oatAllocTempDouble(cUnit);
+ highReg = lowReg + 1;
+ } else {
+ lowReg = oatAllocTemp(cUnit);
+ highReg = oatAllocTemp(cUnit);
+ }
+ res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
+ return res;
}
int oatAllocTypedTemp(CompilationUnit* cUnit, bool fpHint, int regClass)
{
- if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
- return oatAllocTempFloat(cUnit);
- return oatAllocTemp(cUnit);
+ if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
+ return oatAllocTempFloat(cUnit);
+ return oatAllocTemp(cUnit);
}
void oatInitializeRegAlloc(CompilationUnit* cUnit)
{
- int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
- int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
- int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
- int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
- int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
- RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
- kAllocRegAlloc);
- cUnit->regPool = pool;
- pool->numCoreRegs = numRegs;
- pool->coreRegs = (RegisterInfo *)
- oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
- true, kAllocRegAlloc);
- pool->numFPRegs = numFPRegs;
- pool->FPRegs = (RegisterInfo *)
- oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
- kAllocRegAlloc);
- oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
- oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
- // Keep special registers from being allocated
- for (int i = 0; i < numReserved; i++) {
- if (NO_SUSPEND && !cUnit->genDebugger &&
- (reservedRegs[i] == rSUSPEND)) {
- //To measure cost of suspend check
- continue;
- }
- oatMarkInUse(cUnit, reservedRegs[i]);
+ int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
+ int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
+ int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
+ int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
+ int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
+ RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
+ kAllocRegAlloc);
+ cUnit->regPool = pool;
+ pool->numCoreRegs = numRegs;
+ pool->coreRegs = (RegisterInfo *)
+ oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
+ true, kAllocRegAlloc);
+ pool->numFPRegs = numFPRegs;
+ pool->FPRegs = (RegisterInfo *)
+ oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
+ kAllocRegAlloc);
+ oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
+ oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
+ // Keep special registers from being allocated
+ for (int i = 0; i < numReserved; i++) {
+ if (NO_SUSPEND && !cUnit->genDebugger &&
+ (reservedRegs[i] == rSUSPEND)) {
+ //To measure cost of suspend check
+ continue;
}
- // Mark temp regs - all others not in use can be used for promotion
- for (int i = 0; i < numTemps; i++) {
- oatMarkTemp(cUnit, coreTemps[i]);
- }
- for (int i = 0; i < numFPTemps; i++) {
- oatMarkTemp(cUnit, fpTemps[i]);
- }
+ oatMarkInUse(cUnit, reservedRegs[i]);
+ }
+ // Mark temp regs - all others not in use can be used for promotion
+ for (int i = 0; i < numTemps; i++) {
+ oatMarkTemp(cUnit, coreTemps[i]);
+ }
+ for (int i = 0; i < numFPTemps; i++) {
+ oatMarkTemp(cUnit, fpTemps[i]);
+ }
- // Start allocation at r2 in an attempt to avoid clobbering return values
- pool->nextCoreReg = r2;
+ // Start allocation at r2 in an attempt to avoid clobbering return values
+ pool->nextCoreReg = r2;
- // Construct the alias map.
- cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
- sizeof(cUnit->phiAliasMap[0]), false,
- kAllocDFInfo);
- for (int i = 0; i < cUnit->numSSARegs; i++) {
- cUnit->phiAliasMap[i] = i;
+ // Construct the alias map.
+ cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
+ sizeof(cUnit->phiAliasMap[0]), false,
+ kAllocDFInfo);
+ for (int i = 0; i < cUnit->numSSARegs; i++) {
+ cUnit->phiAliasMap[i] = i;
+ }
+ for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
+ int defReg = phi->ssaRep->defs[0];
+ for (int i = 0; i < phi->ssaRep->numUses; i++) {
+ for (int j = 0; j < cUnit->numSSARegs; j++) {
+ if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
+ cUnit->phiAliasMap[j] = defReg;
+ }
+ }
}
- for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
- int defReg = phi->ssaRep->defs[0];
- for (int i = 0; i < phi->ssaRep->numUses; i++) {
- for (int j = 0; j < cUnit->numSSARegs; j++) {
- if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
- cUnit->phiAliasMap[j] = defReg;
- }
- }
- }
- }
+ }
}
void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
RegLocation rlFree)
{
- if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
- (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
- // No overlap, free both
- oatFreeTemp(cUnit, rlFree.lowReg);
- oatFreeTemp(cUnit, rlFree.highReg);
- }
+ if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
+ (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
+ // No overlap, free both
+ oatFreeTemp(cUnit, rlFree.lowReg);
+ oatFreeTemp(cUnit, rlFree.highReg);
+ }
}
diff --git a/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc b/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc
index dcf3a99..0512896 100644
--- a/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc
+++ b/src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc
@@ -22,33 +22,33 @@
*/
InstructionSet oatInstructionSet()
{
- return kThumb2;
+ return kThumb2;
}
/* Architecture-specific initializations and checks go here */
bool oatArchVariantInit(void)
{
- return true;
+ return true;
}
int oatTargetOptHint(int key)
{
- int res = 0;
- switch (key) {
- case kMaxHoistDistance:
- res = 7;
- break;
- default:
- LOG(FATAL) << "Unknown target optimization hint key: " << key;
- }
- return res;
+ int res = 0;
+ switch (key) {
+ case kMaxHoistDistance:
+ res = 7;
+ break;
+ default:
+ LOG(FATAL) << "Unknown target optimization hint key: " << key;
+ }
+ return res;
}
void oatGenMemBarrier(CompilationUnit* cUnit, int barrierKind)
{
#if ANDROID_SMP != 0
- LIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
- dmb->defMask = ENCODE_ALL;
+ LIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
+ dmb->defMask = ENCODE_ALL;
#endif
}
diff --git a/src/compiler/codegen/arm/armv7-a/ArchVariant.cc b/src/compiler/codegen/arm/armv7-a/ArchVariant.cc
index dcf3a99..3977d50 100644
--- a/src/compiler/codegen/arm/armv7-a/ArchVariant.cc
+++ b/src/compiler/codegen/arm/armv7-a/ArchVariant.cc
@@ -22,33 +22,33 @@
*/
InstructionSet oatInstructionSet()
{
- return kThumb2;
+ return kThumb2;
}
/* Architecture-specific initializations and checks go here */
bool oatArchVariantInit(void)
{
- return true;
+ return true;
}
int oatTargetOptHint(int key)
{
- int res = 0;
- switch (key) {
- case kMaxHoistDistance:
- res = 7;
- break;
- default:
- LOG(FATAL) << "Unknown target optimization hint key: " << key;
+ int res = 0;
+ switch (key) {
+ case kMaxHoistDistance:
+ res = 7;
+ break;
+ default:
+ LOG(FATAL) << "Unknown target optimization hint key: " << key;
}
- return res;
+ return res;
}
void oatGenMemBarrier(CompilationUnit* cUnit, int barrierKind)
{
#if ANDROID_SMP != 0
- LIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
- dmb->defMask = ENCODE_ALL;
+ LIR* dmb = newLIR1(cUnit, kThumb2Dmb, barrierKind);
+ dmb->defMask = ENCODE_ALL;
#endif
}