diff options
| author | 2012-05-03 15:00:40 -0700 | |
|---|---|---|
| committer | 2012-05-03 18:57:47 -0700 | |
| commit | a114add0300b95eeaae7465493f39144e07324e8 (patch) | |
| tree | 19b119195c00bd4688bb085eadbe142851f75e0e /src/compiler/codegen/arm | |
| parent | 1ecce9487a1b3aac6b656f5704cf86a961ab0481 (diff) | |
[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
Diffstat (limited to 'src/compiler/codegen/arm')
| -rw-r--r-- | src/compiler/codegen/arm/ArchFactory.cc | 288 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArchUtility.cc | 502 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArmLIR.h | 996 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArmRallocUtil.cc | 179 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Assemble.cc | 763 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Codegen.h | 25 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/FP/Thumb2VFP.cc | 487 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Factory.cc | 1625 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Gen.cc | 1196 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Ralloc.cc | 144 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/armv7-a-neon/ArchVariant.cc | 26 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/armv7-a/ArchVariant.cc | 24 |
12 files changed, 3108 insertions, 3147 deletions
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc index 9326faf08f..c20151e533 100644 --- a/src/compiler/codegen/arm/ArchFactory.cc +++ b/src/compiler/codegen/arm/ArchFactory.cc @@ -31,129 +31,121 @@ void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset); 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; - /* - * 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); - + 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) { /* - * We can safely skip the stack overflow check if we're - * a leaf *and* our frame size < fudge factor. + * 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 */ - 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); - - 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); + 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); + + 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); } 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); - - 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); - } + 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); + } } /* @@ -163,55 +155,55 @@ void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb) */ void removeRedundantBranches(CompilationUnit* cUnit) { - 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; - - 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; - } + 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; + + 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; + } } + } } /* 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 4346bda058..725200a6f6 100644 --- a/src/compiler/codegen/arm/ArchUtility.cc +++ b/src/compiler/codegen/arm/ArchUtility.cc @@ -24,109 +24,109 @@ namespace art { 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 @@ const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc", * 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); - } - } + 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 "); - } + 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 "); - } + /* 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 (mask & ENCODE_HEAP_REF) { + strcat(buf, "heap "); } - if (buf[0]) { - LOG(INFO) << prefix << ": " << buf; + 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 484892a03c..fc5aa40178 100644 --- a/src/compiler/codegen/arm/ArmLIR.h +++ b/src/compiler/codegen/arm/ArmLIR.h @@ -132,20 +132,20 @@ namespace art { #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 @@ enum ResourceEncodingPos { #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 @@ enum ResourceEncodingPos { * 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 @@ enum NativeRegisterPool { /* 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 @@ enum ArmConditionCode { * 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 @@ enum ArmOpFeatureFlags { /* 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 89bff5ee9b..bf7c1c759a 100644 --- a/src/compiler/codegen/arm/ArmRallocUtil.cc +++ b/src/compiler/codegen/arm/ArmRallocUtil.cc @@ -35,8 +35,8 @@ namespace art { void oatAdjustSpillMask(CompilationUnit* cUnit) { - cUnit->coreSpillMask |= (1 << rLR); - cUnit->numCoreSpills++; + cUnit->coreSpillMask |= (1 << rLR); + cUnit->numCoreSpills++; } /* @@ -47,143 +47,140 @@ void oatAdjustSpillMask(CompilationUnit* cUnit) */ 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 1d1442a313..aca146e309 100644 --- a/src/compiler/codegen/arm/Assemble.cc +++ b/src/compiler/codegen/arm/Assemble.cc @@ -991,393 +991,382 @@ const ArmEncodingMap EncodingMap[kArmLast] = { * 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->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; + } - if (lir->flags.isNop) { - 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))) { /* - * 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. + * 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. */ - 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; + 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); + // 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]; + // 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))); + /* 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]; + 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))); + 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; - } + 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; } - if (encoder->size == 4) { - cUnit->codeBuffer.push_back((bits >> 16) & 0xff); - cUnit->codeBuffer.push_back((bits >> 24) & 0xff); + } 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; } - cUnit->codeBuffer.push_back(bits & 0xff); - cUnit->codeBuffer.push_back((bits >> 8) & 0xff); + 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; + } } - return res; + 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 oatGetInsnSize(LIR* lir) */ 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 f467d4ffd3..10f5e384ad 100644 --- a/src/compiler/codegen/arm/Codegen.h +++ b/src/compiler/codegen/arm/Codegen.h @@ -36,12 +36,12 @@ bool genNegLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, /* 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 @@ void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep, */ 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 @@ inline RegisterClass oatRegClassBySize(OpSize size) */ #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 @@ inline s4 s4FromSwitchData(const void* switchData) { 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 380c014b6d..fbce1f5b0b 100644 --- a/src/compiler/codegen/arm/FP/Thumb2VFP.cc +++ b/src/compiler/codegen/arm/FP/Thumb2VFP.cc @@ -19,280 +19,277 @@ namespace art { 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 0fe937ad98..533f8b4bcf 100644 --- a/src/compiler/codegen/arm/Thumb2/Factory.cc +++ b/src/compiler/codegen/arm/Thumb2/Factory.cc @@ -37,62 +37,62 @@ static int fpTemps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, 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 @@ int modifiedImmediate(u4 value) /* 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 @@ int modifiedImmediate(u4 value) */ 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 @@ LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value) */ 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 @@ LIR* loadBaseDispBody(CompilationUnit* cUnit, MIR* mir, int rBase, 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 5451d57e02..5252b495c1 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -31,8 +31,8 @@ namespace art { /* 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 @@ int inPosition(CompilationUnit* cUnit, int sReg) */ 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 { + loc.location = kLocDalvikFrame; + } + } else { + if (argNum < 3) { + loc.lowReg = rARG1 + argNum; + loc.location = kLocPhysReg; } else { - if (argNum < 3) { - loc.lowReg = rARG1 + argNum; - loc.location = kLocPhysReg; - } else { - loc.location = kLocDalvikFrame; - } + loc.location = kLocDalvikFrame; } - return loc; + } + return loc; } /* @@ -72,243 +72,241 @@ RegLocation argLoc(CompilationUnit* cUnit, RegLocation loc) */ 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; + } + if (mir != NULL) { + return mir; + } else { + bb = bb->fallThrough; + *pBb = bb; + if (bb) { + mir = bb->firstMIRInsn; + if (mir != NULL) { + return mir; + } + } } - return origMir; + } + 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 @@ void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, */ 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; - - //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); + 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); } /* @@ -371,97 +369,95 @@ LIR* opIT(CompilationUnit* cUnit, ArmConditionCode code, const char* guide) 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); - - // 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); + 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); } 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); - - // 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); - - // ..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; + 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); + + // 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; + + /* branchOver target here */ + LIR* target = newLIR0(cUnit, kPseudoTargetLabel); + branchOver->target = (LIR*)target; } /* @@ -476,46 +472,46 @@ void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) */ 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; - - 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); + 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); + + // 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 genNegDouble(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc) */ 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 genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) */ 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 @@ void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) * 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); - - 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); - - 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); - - branch1->target = (LIR*)target1; - branch2->target = (LIR*)target2; - branch3->target = branch1->target; + 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); + + target2 = newLIR0(cUnit, kPseudoTargetLabel); + opRegReg(cUnit, kOpNeg, tReg, tReg); + + 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); + + 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 @@ void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) * 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; - } - - 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; + 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; } } // namespace art diff --git a/src/compiler/codegen/arm/Thumb2/Ralloc.cc b/src/compiler/codegen/arm/Thumb2/Ralloc.cc index 7858318001..98a110cb2b 100644 --- a/src/compiler/codegen/arm/Thumb2/Ralloc.cc +++ b/src/compiler/codegen/arm/Thumb2/Ralloc.cc @@ -30,96 +30,96 @@ namespace art { */ 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]); - } - // 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]); + 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]); + } + // 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; - } - 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; - } - } - } + // 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; + } + } } + } } 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 dcf3a995f3..0512896340 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 @@ namespace art { */ 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 dcf3a995f3..3977d502ca 100644 --- a/src/compiler/codegen/arm/armv7-a/ArchVariant.cc +++ b/src/compiler/codegen/arm/armv7-a/ArchVariant.cc @@ -22,33 +22,33 @@ namespace art { */ 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 } |