diff options
| author | 2012-10-30 15:48:42 -0700 | |
|---|---|---|
| committer | 2012-11-01 12:05:35 -0700 | |
| commit | b046e16d8b8da318d6055f9308950131f1255e08 (patch) | |
| tree | d4472622967d02fcc87bb422bddea9a9140c75f9 /src/compiler/codegen | |
| parent | 6e30145f1ed992be8d4e5a9973410c19f3de59f9 (diff) | |
Remove all TARGET_[ARM|X86|MIPS] #ifdefs
Two steps forward, one step back towards elimination of the
"#include" build model for target-specific compilers. This CL
does some restructuring to eliminate all of the TARGET_xxx #ifdefs
and convert them to run-time tests.
Considerable work is still required to fully eliminate the multiple
builds. In particular, much of the "common" codegen code relies on
macros defined by the target-specific [Arm|X86|Mips]Lir.h include file.
Next step is more restructuring to better isolate target-independent
code generation code.
Change-Id: If6efbde65c48031a48423344d8dc3e2ff2c4ad9d
Diffstat (limited to 'src/compiler/codegen')
36 files changed, 1621 insertions, 1653 deletions
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc index ce25aad223..b0dc30c67a 100644 --- a/src/compiler/codegen/CodegenFactory.cc +++ b/src/compiler/codegen/CodegenFactory.cc @@ -16,16 +16,7 @@ namespace art { -/* - * This file contains target-independent codegen and support, and is - * included by: - * - * $(TARGET_ARCH)/Codegen-$(TARGET_ARCH_VARIANT).c - * - * which combines this common code with specific support found in the - * applicable directories below this one. - * - */ +/* This file contains target-independent codegen and support. */ /* * Load an immediate value into a fixed or temp register. Target @@ -265,30 +256,6 @@ void storeValueWide(CompilationUnit* cUnit, RegLocation rlDest, } } -/* - * Mark garbage collection card. Skip if the value we're storing is null. - */ -void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) -{ - int regCardBase = oatAllocTemp(cUnit); - int regCardNo = oatAllocTemp(cUnit); - LIR* branchOver = opCmpImmBranch(cUnit, kCondEq, valReg, 0, NULL); -#if !defined(TARGET_X86) - loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(), - regCardBase); -#else - newLIR2(cUnit, kX86Mov32RT, regCardBase, - Thread::CardTableOffset().Int32Value()); -#endif - opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, CardTable::kCardShift); - storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0, - kUnsignedByte); - LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - branchOver->target = (LIR*)target; - oatFreeTemp(cUnit, regCardBase); - oatFreeTemp(cUnit, regCardNo); -} - /* Utilities to load the current Method* */ void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt) { diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc index cf06c80643..7ad2647f18 100644 --- a/src/compiler/codegen/CodegenUtil.cc +++ b/src/compiler/codegen/CodegenUtil.cc @@ -74,24 +74,22 @@ void annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit) /* * Decode the register id. */ -inline u8 getRegMaskCommon(int reg) +inline u8 getRegMaskCommon(CompilationUnit* cUnit, int reg) { u8 seed; int shift; + int regId; -#if defined(TARGET_X86) - int regId = reg & 0xf; - /* - * Double registers in x86 are just a single FP register - */ - seed = 1; -#else - int regId = reg & 0x1f; - /* - * Each double register is equal to a pair of single-precision FP registers - */ - seed = DOUBLEREG(reg) ? 3 : 1; -#endif + + if (cUnit->instructionSet == kX86) { + regId = reg & 0xf; + /* Double registers in x86 are just a single FP register */ + seed = 1; + } else { + regId = reg & 0x1f; + /* Each double register is equal to a pair of single-precision FP registers */ + seed = DOUBLEREG(reg) ? 3 : 1; + } /* FP register starts at bit position 16 */ shift = FPREG(reg) ? kFPReg0 : 0; /* Expand the double register id into single offset */ @@ -99,18 +97,29 @@ inline u8 getRegMaskCommon(int reg) return (seed << shift); } +u8 oatGetRegMaskCommon(CompilationUnit* cUnit, int reg) +{ + return getRegMaskCommon(cUnit, reg); +} + /* * Mark the corresponding bit(s). */ -inline void setupRegMask(u8* mask, int reg) +inline void setupRegMask(CompilationUnit* cUnit, u8* mask, int reg) +{ + *mask |= getRegMaskCommon(cUnit, reg); +} + +/* Exported version of setupRegMask */ +void oatSetupRegMask(CompilationUnit* cUnit, u8* mask, int reg) { - *mask |= getRegMaskCommon(reg); + setupRegMask(cUnit, mask, reg); } /* * Set up the proper fields in the resource mask */ -void setupResourceMasks(LIR* lir) +void setupResourceMasks(CompilationUnit* cUnit, LIR* lir) { int opcode = lir->opcode; int flags; @@ -120,7 +129,7 @@ void setupResourceMasks(LIR* lir) return; } - flags = EncodingMap[lir->opcode].flags; + flags = EncodingMap[opcode].flags; if (flags & NEEDS_FIXUP) { lir->flags.pcRelFixup = true; @@ -145,135 +154,42 @@ void setupResourceMasks(LIR* lir) } if (flags & REG_DEF0) { - setupRegMask(&lir->defMask, lir->operands[0]); + setupRegMask(cUnit, &lir->defMask, lir->operands[0]); } if (flags & REG_DEF1) { - setupRegMask(&lir->defMask, lir->operands[1]); + setupRegMask(cUnit, &lir->defMask, lir->operands[1]); } -#if defined(TARGET_X86) - if (flags & REG_DEFA) { - setupRegMask(&lir->defMask, rAX); - } - - if (flags & REG_DEFD) { - setupRegMask(&lir->defMask, rDX); - } -#endif - if (flags & REG_DEF_SP) { lir->defMask |= ENCODE_REG_SP; } -#if !defined(TARGET_X86) - if (flags & REG_DEF_LR) { - lir->defMask |= ENCODE_REG_LR; - } -#endif - -#if defined(TARGET_ARM) - if (flags & REG_DEF_LIST0) { - lir->defMask |= ENCODE_REG_LIST(lir->operands[0]); - } - - if (flags & REG_DEF_LIST1) { - lir->defMask |= ENCODE_REG_LIST(lir->operands[1]); - } - - if (flags & REG_DEF_FPCS_LIST0) { - lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]); - } - - if (flags & REG_DEF_FPCS_LIST2) { - for (int i = 0; i < lir->operands[2]; i++) { - setupRegMask(&lir->defMask, lir->operands[1] + i); - } - } -#endif if (flags & SETS_CCODES) { lir->defMask |= ENCODE_CCODE; } -#if defined(TARGET_ARM) - /* Conservatively treat the IT block */ - if (flags & IS_IT) { - lir->defMask = ENCODE_ALL; - } -#endif - if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) { int i; for (i = 0; i < 4; i++) { if (flags & (1 << (kRegUse0 + i))) { - setupRegMask(&lir->useMask, lir->operands[i]); + setupRegMask(cUnit, &lir->useMask, lir->operands[i]); } } } -#if defined(TARGET_X86) - if (flags & REG_USEA) { - setupRegMask(&lir->useMask, rAX); - } - - if (flags & REG_USEC) { - setupRegMask(&lir->useMask, rCX); - } - - if (flags & REG_USED) { - setupRegMask(&lir->useMask, rDX); - } -#endif - -#if defined(TARGET_ARM) - if (flags & REG_USE_PC) { - lir->useMask |= ENCODE_REG_PC; - } -#endif - if (flags & REG_USE_SP) { lir->useMask |= ENCODE_REG_SP; } -#if defined(TARGET_ARM) - if (flags & REG_USE_LIST0) { - lir->useMask |= ENCODE_REG_LIST(lir->operands[0]); - } - - if (flags & REG_USE_LIST1) { - lir->useMask |= ENCODE_REG_LIST(lir->operands[1]); - } - - if (flags & REG_USE_FPCS_LIST0) { - lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]); - } - - if (flags & REG_USE_FPCS_LIST2) { - for (int i = 0; i < lir->operands[2]; i++) { - setupRegMask(&lir->useMask, lir->operands[1] + i); - } - } -#endif - if (flags & USES_CCODES) { lir->useMask |= ENCODE_CCODE; } -#if defined(TARGET_ARM) - /* Fixup for kThumbPush/lr and kThumbPop/pc */ - if (opcode == kThumbPush || opcode == kThumbPop) { - u8 r8Mask = getRegMaskCommon(r8); - if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) { - lir->useMask &= ~r8Mask; - lir->useMask |= ENCODE_REG_LR; - } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) { - lir->defMask &= ~r8Mask; - lir->defMask |= ENCODE_REG_PC; - } - } -#endif + // Handle target-specific actions + setupTargetResourceMasks(cUnit, lir); } /* @@ -472,7 +388,7 @@ LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0, insn->operands[3] = op3; insn->operands[4] = op4; insn->target = target; - oatSetupResourceMasks(insn); + oatSetupResourceMasks(cUnit, insn); if ((opcode == kPseudoTargetLabel) || (opcode == kPseudoSafepointPC) || (opcode == kPseudoExportedPC)) { // Always make labels scheduling barriers @@ -697,13 +613,19 @@ void installSwitchTables(CompilationUnit* cUnit) * the auto pc-advance. For other targets the reference point * is a label, so we can use the offset as-is. */ -#if defined(TARGET_ARM) - int bxOffset = tabRec->anchor->offset + 4; -#elif defined(TARGET_X86) - int bxOffset = 0; -#else - int bxOffset = tabRec->anchor->offset; -#endif + int bxOffset = INVALID_OFFSET; + switch (cUnit->instructionSet) { + case kThumb2: + bxOffset = tabRec->anchor->offset + 4; + break; + case kX86: + bxOffset = 0; + break; + case kMips: + bxOffset = tabRec->anchor->offset; + break; + default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet; + } if (cUnit->printMe) { LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset; } diff --git a/src/compiler/codegen/CompilerCodegen.h b/src/compiler/codegen/CompilerCodegen.h index 61ea6b6cef..d349412950 100644 --- a/src/compiler/codegen/CompilerCodegen.h +++ b/src/compiler/codegen/CompilerCodegen.h @@ -79,6 +79,42 @@ int oatTargetOptHint(int key); /* Implemented in codegen/<target>/<target_variant>/ArchVariant.c */ void oatGenMemBarrier(CompilationUnit* cUnit, int barrierKind); +LIR* genRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode, + int reg1, int base, int offset, ThrowKind kind); +LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset); +LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp); +LIR* storeBaseIndexedDisp(CompilationUnit *cUnit, + int rBase, int rIndex, int scale, int displacement, + int rSrc, int rSrcHi, OpSize size, int sReg); +LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase, int offset); +LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, + int src2, LIR* target); +void oatSetupRegMask(CompilationUnit* cUnit, u8* mask, int reg); +u8 oatGetRegMaskCommon(CompilationUnit* cUnit, int reg); +void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir); +RegLocation genDivRem(CompilationUnit* cUnit, RegLocation rlDest, int regLo, int regHi, bool isDiv); +RegLocation genDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int regLo, int lit, bool isDiv); +void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg); +bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin); +void opLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset); +void opTlsCmp(CompilationUnit* cUnit, int offset, int val); +bool genInlinedSqrt(CompilationUnit* cUnit, CallInfo* info); +bool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier); +LIR* opPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target); +LIR* opVldm(CompilationUnit* cUnit, int rBase, int count); +LIR* opVstm(CompilationUnit* cUnit, int rBase, int count); +void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc, + RegLocation rlResult, int lit, + int firstBit, int secondBit); +RegLocation inlineTarget(CompilationUnit* cUnit, CallInfo* info); +RegLocation inlineTargetWide(CompilationUnit* cUnit, CallInfo* info); +void genDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi); +LIR* genImmedCheck(CompilationUnit* cUnit, ConditionCode cCode, + int reg, int immVal, ThrowKind kind); +LIR* opTestSuspend(CompilationUnit* cUnit, LIR* target); +LIR* opDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target); +LIR* opIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide); + } // namespace art #endif // ART_SRC_COMPILER_COMPILERCODEGEN_H_ diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc index 730527115e..035617e8f3 100644 --- a/src/compiler/codegen/GenCommon.cc +++ b/src/compiler/codegen/GenCommon.cc @@ -24,11 +24,8 @@ namespace art { * and "op" calls may be used here. */ void genInvoke(CompilationUnit* cUnit, CallInfo* info); -#if defined(TARGET_ARM) -LIR* opIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide); bool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, RegLocation rlSrc, RegLocation rlDest, int lit); -#endif void markSafepointPC(CompilationUnit* cUnit, LIR* inst) { @@ -37,86 +34,71 @@ void markSafepointPC(CompilationUnit* cUnit, LIR* inst) DCHECK_EQ(safepointPC->defMask, ENCODE_ALL); } -void callRuntimeHelperImm(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif - loadConstant(cUnit, rARG0, arg0); - oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif +/* + * To save scheduling time, helper calls are broken into two parts: generation of + * the helper target address, and the actuall call to the helper. Because x86 + * has a memory call operation, part 1 is a NOP for x86. For other targets, + * load arguments between the two parts. + */ +int callHelperSetup(CompilationUnit* cUnit, int helperOffset) +{ + return (cUnit->instructionSet == kX86) ? 0 : loadHelper(cUnit, helperOffset); +} + +/* NOTE: if rTgt is a temp, it will be freed following use */ +LIR* callHelper(CompilationUnit* cUnit, int rTgt, int helperOffset, bool safepointPC) +{ + LIR* callInst; + if (cUnit->instructionSet == kX86) { + callInst = opThreadMem(cUnit, kOpBlx, helperOffset); + } else { + callInst = opReg(cUnit, kOpBlx, rTgt); + oatFreeTemp(cUnit, rTgt); + } if (safepointPC) { markSafepointPC(cUnit, callInst); } + return callInst; +} + +void callRuntimeHelperImm(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC) { + int rTgt = callHelperSetup(cUnit, helperOffset); + loadConstant(cUnit, rARG0, arg0); + oatClobberCalleeSave(cUnit); + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperReg(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); opRegCopy(cUnit, rARG0, arg0); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperRegLocation(CompilationUnit* cUnit, int helperOffset, RegLocation arg0, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); if (arg0.wide == 0) { loadValueDirectFixed(cUnit, arg0, rARG0); } else { loadValueDirectWideFixed(cUnit, arg0, rARG0, rARG1); } oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperImmImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); loadConstant(cUnit, rARG0, arg0); loadConstant(cUnit, rARG1, arg1); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperImmRegLocation(CompilationUnit* cUnit, int helperOffset, int arg0, RegLocation arg1, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); if (arg1.wide == 0) { loadValueDirectFixed(cUnit, arg1, rARG1); } else { @@ -124,111 +106,61 @@ void callRuntimeHelperImmRegLocation(CompilationUnit* cUnit, int helperOffset, i } loadConstant(cUnit, rARG0, arg0); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperRegLocationImm(CompilationUnit* cUnit, int helperOffset, RegLocation arg0, int arg1, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); loadValueDirectFixed(cUnit, arg0, rARG0); loadConstant(cUnit, rARG1, arg1); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperImmReg(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); opRegCopy(cUnit, rARG1, arg1); loadConstant(cUnit, rARG0, arg0); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperRegImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); opRegCopy(cUnit, rARG0, arg0); loadConstant(cUnit, rARG1, arg1); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperImmMethod(CompilationUnit* cUnit, int helperOffset, int arg0, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); loadCurrMethodDirect(cUnit, rARG1); loadConstant(cUnit, rARG0, arg0); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperRegLocationRegLocation(CompilationUnit* cUnit, int helperOffset, RegLocation arg0, RegLocation arg1, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); if (arg0.wide == 0) { loadValueDirectFixed(cUnit, arg0, arg0.fp ? rFARG0 : rARG0); if (arg1.wide == 0) { -#if defined(TARGET_MIPS) - loadValueDirectFixed(cUnit, arg1, arg1.fp ? rFARG2 : rARG1); -#else - loadValueDirectFixed(cUnit, arg1, rARG1); -#endif + if (cUnit->instructionSet == kMips) { + loadValueDirectFixed(cUnit, arg1, arg1.fp ? rFARG2 : rARG1); + } else { + loadValueDirectFixed(cUnit, arg1, rARG1); + } } else { -#if defined(TARGET_MIPS) - loadValueDirectWideFixed(cUnit, arg1, arg1.fp ? rFARG2 : rARG1, arg1.fp ? rFARG3 : rARG2); -#else - loadValueDirectWideFixed(cUnit, arg1, rARG1, rARG2); -#endif + if (cUnit->instructionSet == kMips) { + loadValueDirectWideFixed(cUnit, arg1, arg1.fp ? rFARG2 : rARG1, arg1.fp ? rFARG3 : rARG2); + } else { + loadValueDirectWideFixed(cUnit, arg1, rARG1, rARG2); + } } } else { loadValueDirectWideFixed(cUnit, arg0, arg0.fp ? rFARG0 : rARG0, arg0.fp ? rFARG1 : rARG1); @@ -239,104 +171,54 @@ void callRuntimeHelperRegLocationRegLocation(CompilationUnit* cUnit, int helperO } } oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperRegReg(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); DCHECK_NE((int)rARG0, arg1); // check copy into arg0 won't clobber arg1 opRegCopy(cUnit, rARG0, arg0); opRegCopy(cUnit, rARG1, arg1); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperRegRegImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg1, int arg2, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); DCHECK_NE((int)rARG0, arg1); // check copy into arg0 won't clobber arg1 opRegCopy(cUnit, rARG0, arg0); opRegCopy(cUnit, rARG1, arg1); loadConstant(cUnit, rARG2, arg2); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperImmMethodRegLocation(CompilationUnit* cUnit, int helperOffset, int arg0, RegLocation arg2, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); loadValueDirectFixed(cUnit, arg2, rARG2); loadCurrMethodDirect(cUnit, rARG1); loadConstant(cUnit, rARG0, arg0); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperImmMethodImm(CompilationUnit* cUnit, int helperOffset, int arg0, int arg2, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); loadCurrMethodDirect(cUnit, rARG1); loadConstant(cUnit, rARG2, arg2); loadConstant(cUnit, rARG0, arg0); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } void callRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cUnit, int helperOffset, int arg0, RegLocation arg1, RegLocation arg2, bool safepointPC) { -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, helperOffset); -#endif + int rTgt = callHelperSetup(cUnit, helperOffset); loadValueDirectFixed(cUnit, arg1, rARG1); if (arg2.wide == 0) { loadValueDirectFixed(cUnit, arg2, rARG2); @@ -345,15 +227,7 @@ void callRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cUnit, int help } loadConstant(cUnit, rARG0, arg0); oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, helperOffset); -#endif - if (safepointPC) { - markSafepointPC(cUnit, callInst); - } + callHelper(cUnit, rTgt, helperOffset, safepointPC); } /* @@ -378,10 +252,10 @@ LIR* opUnconditionalBranch(CompilationUnit* cUnit, LIR* target) // FIXME: need to do some work to split out targets with // condition codes and those without -#if defined(TARGET_ARM) || defined(TARGET_X86) LIR* genCheck(CompilationUnit* cUnit, ConditionCode cCode, ThrowKind kind) { + DCHECK_NE(cUnit->instructionSet, kMips); LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind, cUnit->currentDalvikOffset); LIR* branch = opCondBranch(cUnit, cCode, tgt); @@ -389,7 +263,6 @@ LIR* genCheck(CompilationUnit* cUnit, ConditionCode cCode, oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt); return branch; } -#endif LIR* genImmedCheck(CompilationUnit* cUnit, ConditionCode cCode, int reg, int immVal, ThrowKind kind) @@ -423,12 +296,7 @@ LIR* genRegRegCheck(CompilationUnit* cUnit, ConditionCode cCode, { LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind, cUnit->currentDalvikOffset, reg1, reg2); -#if defined(TARGET_MIPS) LIR* branch = opCmpBranch(cUnit, cCode, reg1, reg2, tgt); -#else - opRegReg(cUnit, kOpCmp, reg1, reg2); - LIR* branch = opCondBranch(cUnit, cCode, tgt); -#endif // Remember branch target - will process later oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt); return branch; @@ -464,12 +332,7 @@ void genCompareAndBranch(CompilationUnit* cUnit, Instruction::Code opcode, cond = (ConditionCode)0; LOG(FATAL) << "Unexpected opcode " << (int)opcode; } -#if defined(TARGET_MIPS) opCmpBranch(cUnit, cond, rlSrc1.lowReg, rlSrc2.lowReg, taken); -#else - opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); - opCondBranch(cUnit, cond, taken); -#endif opUnconditionalBranch(cUnit, fallThrough); } @@ -501,12 +364,12 @@ void genCompareZeroAndBranch(CompilationUnit* cUnit, Instruction::Code opcode, cond = (ConditionCode)0; LOG(FATAL) << "Unexpected opcode " << (int)opcode; } -#if defined(TARGET_MIPS) || defined(TARGET_X86) - opCmpImmBranch(cUnit, cond, rlSrc.lowReg, 0, taken); -#else - opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); - opCondBranch(cUnit, cond, taken); -#endif + if (cUnit->instructionSet == kThumb2) { + opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); + opCondBranch(cUnit, cond, taken); + } else { + opCmpImmBranch(cUnit, cond, rlSrc.lowReg, 0, taken); + } opUnconditionalBranch(cUnit, fallThrough); } @@ -628,14 +491,20 @@ void genFilledNewArray(CompilationUnit* cUnit, CallInfo* info) int rSrc = oatAllocTemp(cUnit); int rDst = oatAllocTemp(cUnit); int rIdx = oatAllocTemp(cUnit); -#if defined(TARGET_ARM) - int rVal = rLR; // Using a lot of temps, rLR is known free here -#elif defined(TARGET_X86) - oatFreeTemp(cUnit, rRET0); - int rVal = oatAllocTemp(cUnit); -#else - int rVal = oatAllocTemp(cUnit); -#endif + int rVal = INVALID_REG; + switch(cUnit->instructionSet) { + case kThumb2: + rVal = rLR; + break; + case kX86: + oatFreeTemp(cUnit, rRET0); + rVal = oatAllocTemp(cUnit); + break; + case kMips: + rVal = oatAllocTemp(cUnit); + break; + default: LOG(FATAL) << "Unexpected instruction set: " << cUnit->instructionSet; + } // Set up source pointer RegLocation rlFirst = info->args[0]; opRegRegImm(cUnit, kOpAdd, rSrc, rSP, @@ -650,20 +519,12 @@ void genFilledNewArray(CompilationUnit* cUnit, CallInfo* info) // Copy next element loadBaseIndexed(cUnit, rSrc, rIdx, rVal, 2, kWord); storeBaseIndexed(cUnit, rDst, rIdx, rVal, 2, kWord); -#if defined(TARGET_ARM) - // Combine sub & test using sub setflags encoding here - newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1); - opCondBranch(cUnit, kCondGe, target); -#else oatFreeTemp(cUnit, rVal); - opRegImm(cUnit, kOpSub, rIdx, 1); - opCmpImmBranch(cUnit, kCondGe, rIdx, 0, target); -#endif -#if defined(TARGET_X86) - // Restore the target pointer - opRegRegImm(cUnit, kOpAdd, rRET0, rDst, - -Array::DataOffset(component_size).Int32Value()); -#endif + opDecAndBranch(cUnit, kCondGe, rIdx, target); + if (cUnit->instructionSet == kX86) { + // Restore the target pointer + opRegRegImm(cUnit, kOpAdd, rRET0, rDst, -Array::DataOffset(component_size).Int32Value()); + } } else if (!info->isRange) { // TUNING: interleave for (int i = 0; i < elems; i++) { @@ -735,10 +596,10 @@ void genSput(CompilationUnit* cUnit, uint32_t fieldIdx, RegLocation rlSrc, LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL); loadConstant(cUnit, rARG0, ssbIndex); callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssbIndex, true); -#if defined(TARGET_MIPS) - // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy - opRegCopy(cUnit, rBase, rRET0); -#endif + if (cUnit->instructionSet == kMips) { + // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy + opRegCopy(cUnit, rBase, rRET0); + } LIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel); branchOver->target = (LIR*)skipTarget; oatFreeTemp(cUnit, rMethod); @@ -826,10 +687,10 @@ void genSget(CompilationUnit* cUnit, uint32_t fieldIdx, RegLocation rlDest, // TUNING: fast path should fall through LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL); callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssbIndex, true); -#if defined(TARGET_MIPS) - // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy - opRegCopy(cUnit, rBase, rRET0); -#endif + if (cUnit->instructionSet == kMips) { + // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy + opRegCopy(cUnit, rBase, rRET0); + } LIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel); branchOver->target = (LIR*)skipTarget; oatFreeTemp(cUnit, rMethod); @@ -871,20 +732,18 @@ void genSget(CompilationUnit* cUnit, uint32_t fieldIdx, RegLocation rlDest, // Debugging routine - if null target, branch to DebugMe void genShowTarget(CompilationUnit* cUnit) { -#if defined(TARGET_X86) - UNIMPLEMENTED(WARNING) << "genShowTarget"; -#else + DCHECK_NE(cUnit->instructionSet, kX86) << "unimplemented genShowTarget"; LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rINVOKE_TGT, 0, NULL); loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pDebugMe), rINVOKE_TGT); LIR* target = newLIR0(cUnit, kPseudoTargetLabel); branchOver->target = (LIR*)target; -#endif } void handleSuspendLaunchpads(CompilationUnit *cUnit) { LIR** suspendLabel = (LIR **)cUnit->suspendLaunchpads.elemList; int numElems = cUnit->suspendLaunchpads.numUsed; + int helperOffset = ENTRYPOINT_OFFSET(pTestSuspendFromCode); for (int i = 0; i < numElems; i++) { oatResetRegPool(cUnit); oatResetDefTracking(cUnit); @@ -892,13 +751,8 @@ void handleSuspendLaunchpads(CompilationUnit *cUnit) LIR* resumeLab = (LIR*)lab->operands[0]; cUnit->currentDalvikOffset = lab->operands[1]; oatAppendLIR(cUnit, lab); -#if defined(TARGET_X86) - LIR* callInst = opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pTestSuspendFromCode)); -#else - int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pTestSuspendFromCode)); - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); -#endif - markSafepointPC(cUnit, callInst); + int rTgt = callHelperSetup(cUnit, helperOffset); + callHelper(cUnit, rTgt, helperOffset, true /* markSafepointPC */); opUnconditionalBranch(cUnit, resumeLab); } } @@ -936,6 +790,7 @@ void handleThrowLaunchpads(CompilationUnit *cUnit) int funcOffset = 0; int v1 = lab->operands[2]; int v2 = lab->operands[3]; + bool targetX86 = (cUnit->instructionSet == kX86); switch (lab->operands[0]) { case kThrowNullPointer: funcOffset = ENTRYPOINT_OFFSET(pThrowNullPointerFromCode); @@ -944,30 +799,30 @@ void handleThrowLaunchpads(CompilationUnit *cUnit) // Move v1 (array index) to rARG0 and v2 (array length) to rARG1 if (v2 != rARG0) { opRegCopy(cUnit, rARG0, v1); -#if defined (TARGET_X86) - // x86 leaves the array pointer in v2, so load the array length that the handler expects - opRegMem(cUnit, kOpMov, rARG1, v2, Array::LengthOffset().Int32Value()); -#else - opRegCopy(cUnit, rARG1, v2); -#endif + if (targetX86) { + // x86 leaves the array pointer in v2, so load the array length that the handler expects + opRegMem(cUnit, kOpMov, rARG1, v2, Array::LengthOffset().Int32Value()); + } else { + opRegCopy(cUnit, rARG1, v2); + } } else { if (v1 == rARG1) { // Swap v1 and v2, using rARG2 as a temp opRegCopy(cUnit, rARG2, v1); -#if defined (TARGET_X86) - // x86 leaves the array pointer in v2, so load the array length that the handler expects - opRegMem(cUnit, kOpMov, rARG1, v2, Array::LengthOffset().Int32Value()); -#else - opRegCopy(cUnit, rARG1, v2); -#endif + if (targetX86) { + // x86 leaves the array pointer in v2; load the array length that the handler expects + opRegMem(cUnit, kOpMov, rARG1, v2, Array::LengthOffset().Int32Value()); + } else { + opRegCopy(cUnit, rARG1, v2); + } opRegCopy(cUnit, rARG0, rARG2); } else { -#if defined (TARGET_X86) - // x86 leaves the array pointer in v2, so load the array length that the handler expects - opRegMem(cUnit, kOpMov, rARG1, v2, Array::LengthOffset().Int32Value()); -#else - opRegCopy(cUnit, rARG1, v2); -#endif + if (targetX86) { + // x86 leaves the array pointer in v2; load the array length that the handler expects + opRegMem(cUnit, kOpMov, rARG1, v2, Array::LengthOffset().Int32Value()); + } else { + opRegCopy(cUnit, rARG1, v2); + } opRegCopy(cUnit, rARG0, v1); } } @@ -984,32 +839,25 @@ void handleThrowLaunchpads(CompilationUnit *cUnit) case kThrowStackOverflow: funcOffset = ENTRYPOINT_OFFSET(pThrowStackOverflowFromCode); // Restore stack alignment -#if !defined(TARGET_X86) - opRegImm(cUnit, kOpAdd, rSP, - (cUnit->numCoreSpills + cUnit->numFPSpills) * 4); -#else - opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize); -#endif + if (targetX86) { + opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize); + } else { + opRegImm(cUnit, kOpAdd, rSP, (cUnit->numCoreSpills + cUnit->numFPSpills) * 4); + } break; default: LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0]; } oatClobberCalleeSave(cUnit); -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, funcOffset); - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - LIR* callInst = opThreadMem(cUnit, kOpBlx, funcOffset); -#endif - markSafepointPC(cUnit, callInst); + int rTgt = callHelperSetup(cUnit, funcOffset); + callHelper(cUnit, rTgt, funcOffset, true /* markSafepointPC */); } } /* Needed by the Assembler */ -void oatSetupResourceMasks(LIR* lir) +void oatSetupResourceMasks(CompilationUnit* cUnit, LIR* lir) { - setupResourceMasks(lir); + setupResourceMasks(cUnit, lir); } bool fastInstance(CompilationUnit* cUnit, uint32_t fieldIdx, @@ -1040,24 +888,24 @@ void genIGet(CompilationUnit* cUnit, uint32_t fieldIdx, int optFlags, OpSize siz if (isLongOrDouble) { DCHECK(rlDest.wide); genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, optFlags); -#if defined(TARGET_X86) - rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, optFlags); - loadBaseDispWide(cUnit, rlObj.lowReg, fieldOffset, rlResult.lowReg, - rlResult.highReg, rlObj.sRegLow); - if (isVolatile) { - oatGenMemBarrier(cUnit, kSY); - } -#else - int regPtr = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset); - rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg); - if (isVolatile) { - oatGenMemBarrier(cUnit, kSY); + if (cUnit->instructionSet == kX86) { + rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, optFlags); + loadBaseDispWide(cUnit, rlObj.lowReg, fieldOffset, rlResult.lowReg, + rlResult.highReg, rlObj.sRegLow); + if (isVolatile) { + oatGenMemBarrier(cUnit, kSY); + } + } else { + int regPtr = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset); + rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); + loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg); + if (isVolatile) { + oatGenMemBarrier(cUnit, kSY); + } + oatFreeTemp(cUnit, regPtr); } - oatFreeTemp(cUnit, regPtr); -#endif storeValueWide(cUnit, rlDest, rlResult); } else { rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); @@ -1207,33 +1055,32 @@ void genConstString(CompilationUnit* cUnit, uint32_t string_idx, loadWordDisp(cUnit, rARG2, AbstractMethod::DexCacheStringsOffset().Int32Value(), rARG0); // Might call out to helper, which will return resolved string in rRET0 -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode)); -#endif + int rTgt = callHelperSetup(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode)); loadWordDisp(cUnit, rARG0, offset_of_string, rRET0); loadConstant(cUnit, rARG1, string_idx); -#if defined(TARGET_ARM) - opRegImm(cUnit, kOpCmp, rRET0, 0); // Is resolved? - genBarrier(cUnit); - // For testing, always force through helper - if (!EXERCISE_SLOWEST_STRING_PATH) { - opIT(cUnit, kArmCondEq, "T"); + if (cUnit->instructionSet == kThumb2) { + opRegImm(cUnit, kOpCmp, rRET0, 0); // Is resolved? + genBarrier(cUnit); + // For testing, always force through helper + if (!EXERCISE_SLOWEST_STRING_PATH) { + opIT(cUnit, kArmCondEq, "T"); + } + opRegCopy(cUnit, rARG0, rARG2); // .eq + LIR* callInst = opReg(cUnit, kOpBlx, rTgt); // .eq, helper(Method*, string_idx) + markSafepointPC(cUnit, callInst); + oatFreeTemp(cUnit, rTgt); + } else if (cUnit->instructionSet == kMips) { + LIR* branch = opCmpImmBranch(cUnit, kCondNe, rRET0, 0, NULL); + opRegCopy(cUnit, rARG0, rARG2); // .eq + LIR* callInst = opReg(cUnit, kOpBlx, rTgt); + markSafepointPC(cUnit, callInst); + oatFreeTemp(cUnit, rTgt); + LIR* target = newLIR0(cUnit, kPseudoTargetLabel); + branch->target = target; + } else { + DCHECK_EQ(cUnit->instructionSet, kX86); + callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode), rARG2, rARG1, true); } - opRegCopy(cUnit, rARG0, rARG2); // .eq - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); // .eq, helper(Method*, string_idx) - markSafepointPC(cUnit, callInst); - oatFreeTemp(cUnit, rTgt); -#elif defined(TARGET_MIPS) - LIR* branch = opCmpImmBranch(cUnit, kCondNe, rRET0, 0, NULL); - opRegCopy(cUnit, rARG0, rARG2); // .eq - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - markSafepointPC(cUnit, callInst); - oatFreeTemp(cUnit, rTgt); - LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - branch->target = target; -#else - callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode), rARG2, rARG1, true); -#endif genBarrier(cUnit); storeValue(cUnit, rlDest, oatGetReturn(cUnit, false)); } else { @@ -1272,12 +1119,12 @@ void genMoveException(CompilationUnit* cUnit, RegLocation rlDest) { oatFlushAllRegs(cUnit); /* Everything to home location */ int funcOffset = ENTRYPOINT_OFFSET(pGetAndClearException); -#if defined(TARGET_X86) - // Runtime helper will load argument for x86. - callRuntimeHelperReg(cUnit, funcOffset, rARG0, false); -#else - callRuntimeHelperReg(cUnit, funcOffset, rSELF, false); -#endif + if (cUnit->instructionSet == kX86) { + // Runtime helper will load argument for x86. + callRuntimeHelperReg(cUnit, funcOffset, rARG0, false); + } else { + callRuntimeHelperReg(cUnit, funcOffset, rSELF, false); + } RegLocation rlResult = oatGetReturn(cUnit, false); storeValue(cUnit, rlDest, rlResult); } @@ -1330,49 +1177,48 @@ void genInstanceof(CompilationUnit* cUnit, uint32_t type_idx, RegLocation rlDest } /* rARG0 is ref, rARG2 is class. If ref==null, use directly as bool result */ RegLocation rlResult = oatGetReturn(cUnit, false); -#if defined(TARGET_MIPS) - opRegCopy(cUnit, rlResult.lowReg, r_ZERO); // store false result for if branch is taken -#endif + if (cUnit->instructionSet == kMips) { + loadConstant(cUnit, rlResult.lowReg, 0); // store false result for if branch is taken + } LIR* branch1 = opCmpImmBranch(cUnit, kCondEq, rARG0, 0, NULL); /* load object->klass_ */ DCHECK_EQ(Object::ClassOffset().Int32Value(), 0); loadWordDisp(cUnit, rARG0, Object::ClassOffset().Int32Value(), rARG1); /* rARG0 is ref, rARG1 is ref->klass_, rARG2 is class */ LIR* callInst; -#if defined(TARGET_ARM) - /* Uses conditional nullification */ - int rTgt = loadHelper(cUnit, - ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); - opRegReg(cUnit, kOpCmp, rARG1, rARG2); // Same? - opIT(cUnit, kArmCondEq, "EE"); // if-convert the test - loadConstant(cUnit, rARG0, 1); // .eq case - load true - opRegCopy(cUnit, rARG0, rARG2); // .ne case - arg0 <= class - callInst = opReg(cUnit, kOpBlx, rTgt); // .ne case: helper(class, ref->class) - oatFreeTemp(cUnit, rTgt); -#else - /* Uses branchovers */ - loadConstant(cUnit, rlResult.lowReg, 1); // assume true - LIR* branchover = opCmpBranch(cUnit, kCondEq, rARG1, rARG2, NULL); -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, - ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); - opRegCopy(cUnit, rARG0, rARG2); // .ne case - arg0 <= class - callInst = opReg(cUnit, kOpBlx, rTgt); // .ne case: helper(class, ref->class) - oatFreeTemp(cUnit, rTgt); -#else - opRegCopy(cUnit, rARG0, rARG2); - callInst = opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); -#endif -#endif + LIR* branchover = NULL; + if (cUnit->instructionSet == kThumb2) { + /* Uses conditional nullification */ + int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); + opRegReg(cUnit, kOpCmp, rARG1, rARG2); // Same? + opIT(cUnit, kArmCondEq, "EE"); // if-convert the test + loadConstant(cUnit, rARG0, 1); // .eq case - load true + opRegCopy(cUnit, rARG0, rARG2); // .ne case - arg0 <= class + callInst = opReg(cUnit, kOpBlx, rTgt); // .ne case: helper(class, ref->class) + oatFreeTemp(cUnit, rTgt); + } else { + /* Uses branchovers */ + loadConstant(cUnit, rlResult.lowReg, 1); // assume true + branchover = opCmpBranch(cUnit, kCondEq, rARG1, rARG2, NULL); + if (cUnit->instructionSet != kX86) { + int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); + opRegCopy(cUnit, rARG0, rARG2); // .ne case - arg0 <= class + callInst = opReg(cUnit, kOpBlx, rTgt); // .ne case: helper(class, ref->class) + oatFreeTemp(cUnit, rTgt); + } else { + opRegCopy(cUnit, rARG0, rARG2); + callInst = opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode)); + } + } markSafepointPC(cUnit, callInst); oatClobberCalleeSave(cUnit); /* branch targets here */ LIR* target = newLIR0(cUnit, kPseudoTargetLabel); storeValue(cUnit, rlDest, rlResult); branch1->target = target; -#if !defined(TARGET_ARM) - branchover->target = target; -#endif + if (cUnit->instructionSet != kThumb2) { + branchover->target = target; + } } void genCheckCast(CompilationUnit* cUnit, uint32_t type_idx, RegLocation rlSrc) @@ -1422,20 +1268,21 @@ void genCheckCast(CompilationUnit* cUnit, uint32_t type_idx, RegLocation rlSrc) DCHECK_EQ(Object::ClassOffset().Int32Value(), 0); loadWordDisp(cUnit, rARG0, Object::ClassOffset().Int32Value(), rARG1); /* rARG1 now contains object->klass_ */ -#if defined(TARGET_MIPS) || defined(TARGET_X86) - LIR* branch2 = opCmpBranch(cUnit, kCondEq, rARG1, classReg, NULL); - callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode), rARG1, rARG2, true); -#else // defined(TARGET_ARM) - int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode)); - opRegReg(cUnit, kOpCmp, rARG1, classReg); - LIR* branch2 = opCondBranch(cUnit, kCondEq, NULL); /* If eq, trivial yes */ - opRegCopy(cUnit, rARG0, rARG1); - opRegCopy(cUnit, rARG1, rARG2); - oatClobberCalleeSave(cUnit); - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - markSafepointPC(cUnit, callInst); - oatFreeTemp(cUnit, rTgt); -#endif + LIR* branch2; + if (cUnit->instructionSet == kThumb2) { + int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode)); + opRegReg(cUnit, kOpCmp, rARG1, classReg); + branch2 = opCondBranch(cUnit, kCondEq, NULL); /* If eq, trivial yes */ + opRegCopy(cUnit, rARG0, rARG1); + opRegCopy(cUnit, rARG1, rARG2); + oatClobberCalleeSave(cUnit); + LIR* callInst = opReg(cUnit, kOpBlx, rTgt); + markSafepointPC(cUnit, callInst); + oatFreeTemp(cUnit, rTgt); + } else { + branch2 = opCmpBranch(cUnit, kCondEq, rARG1, classReg, NULL); + callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode), rARG1, rARG2, true); + } /* branch target here */ LIR* target = newLIR0(cUnit, kPseudoTargetLabel); branch1->target = target; @@ -1483,31 +1330,31 @@ void genArrayObjPut(CompilationUnit* cUnit, int optFlags, RegLocation rlArray, LIR* target = newLIR0(cUnit, kPseudoTargetLabel); null_value_check->target = target; -#if defined(TARGET_X86) - // make an extra temp available for card mark below - oatFreeTemp(cUnit, rARG1); - if (!(optFlags & MIR_IGNORE_RANGE_CHECK)) { - /* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */ - genRegMemCheck(cUnit, kCondUge, rIndex, rArray, lenOffset, kThrowArrayBounds); - } - storeBaseIndexedDisp(cUnit, rArray, rIndex, scale, - dataOffset, rValue, INVALID_REG, kWord, INVALID_SREG); -#else - bool needsRangeCheck = (!(optFlags & MIR_IGNORE_RANGE_CHECK)); - int regLen = INVALID_REG; - if (needsRangeCheck) { - regLen = rARG1; - loadWordDisp(cUnit, rArray, lenOffset, regLen); // Get len - } - /* rPtr -> array data */ - int rPtr = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpAdd, rPtr, rArray, dataOffset); - if (needsRangeCheck) { - genRegRegCheck(cUnit, kCondCs, rIndex, regLen, kThrowArrayBounds); + if (cUnit->instructionSet == kX86) { + // make an extra temp available for card mark below + oatFreeTemp(cUnit, rARG1); + if (!(optFlags & MIR_IGNORE_RANGE_CHECK)) { + /* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */ + genRegMemCheck(cUnit, kCondUge, rIndex, rArray, lenOffset, kThrowArrayBounds); + } + storeBaseIndexedDisp(cUnit, rArray, rIndex, scale, + dataOffset, rValue, INVALID_REG, kWord, INVALID_SREG); + } else { + bool needsRangeCheck = (!(optFlags & MIR_IGNORE_RANGE_CHECK)); + int regLen = INVALID_REG; + if (needsRangeCheck) { + regLen = rARG1; + loadWordDisp(cUnit, rArray, lenOffset, regLen); // Get len + } + /* rPtr -> array data */ + int rPtr = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpAdd, rPtr, rArray, dataOffset); + if (needsRangeCheck) { + genRegRegCheck(cUnit, kCondCs, rIndex, regLen, kThrowArrayBounds); + } + storeBaseIndexed(cUnit, rPtr, rIndex, rValue, scale, kWord); + oatFreeTemp(cUnit, rPtr); } - storeBaseIndexed(cUnit, rPtr, rIndex, rValue, scale, kWord); - oatFreeTemp(cUnit, rPtr); -#endif oatFreeTemp(cUnit, rIndex); markGCCard(cUnit, rValue, rArray); } @@ -1535,80 +1382,79 @@ void genArrayGet(CompilationUnit* cUnit, int optFlags, OpSize size, /* null object? */ genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, optFlags); -#if defined(TARGET_X86) - if (!(optFlags & MIR_IGNORE_RANGE_CHECK)) { - /* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */ - genRegMemCheck(cUnit, kCondUge, rlIndex.lowReg, rlArray.lowReg, - lenOffset, kThrowArrayBounds); - } - if ((size == kLong) || (size == kDouble)) { - int regAddr = oatAllocTemp(cUnit); - newLIR5(cUnit, kX86Lea32RA, regAddr, rlArray.lowReg, rlIndex.lowReg, scale, dataOffset); - oatFreeTemp(cUnit, rlArray.lowReg); - oatFreeTemp(cUnit, rlIndex.lowReg); - rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - loadBaseIndexedDisp(cUnit, regAddr, INVALID_REG, 0, 0, rlResult.lowReg, - rlResult.highReg, size, INVALID_SREG); - storeValueWide(cUnit, rlDest, rlResult); - } else { - rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); + if (cUnit->instructionSet == kX86) { + if (!(optFlags & MIR_IGNORE_RANGE_CHECK)) { + /* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */ + genRegMemCheck(cUnit, kCondUge, rlIndex.lowReg, rlArray.lowReg, + lenOffset, kThrowArrayBounds); + } + if ((size == kLong) || (size == kDouble)) { + int regAddr = oatAllocTemp(cUnit); + opLea(cUnit, regAddr, rlArray.lowReg, rlIndex.lowReg, scale, dataOffset); + oatFreeTemp(cUnit, rlArray.lowReg); + oatFreeTemp(cUnit, rlIndex.lowReg); + rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); + loadBaseIndexedDisp(cUnit, regAddr, INVALID_REG, 0, 0, rlResult.lowReg, + rlResult.highReg, size, INVALID_SREG); + storeValueWide(cUnit, rlDest, rlResult); + } else { + rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - loadBaseIndexedDisp(cUnit, rlArray.lowReg, rlIndex.lowReg, scale, - dataOffset, rlResult.lowReg, INVALID_REG, size, - INVALID_SREG); + loadBaseIndexedDisp(cUnit, rlArray.lowReg, rlIndex.lowReg, scale, + dataOffset, rlResult.lowReg, INVALID_REG, size, + INVALID_SREG); - storeValue(cUnit, rlDest, rlResult); - } -#else - int regPtr = oatAllocTemp(cUnit); - bool needsRangeCheck = (!(optFlags & MIR_IGNORE_RANGE_CHECK)); - int regLen = INVALID_REG; - if (needsRangeCheck) { - regLen = oatAllocTemp(cUnit); - /* Get len */ - loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); - } - /* regPtr -> array data */ - opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset); - oatFreeTemp(cUnit, rlArray.lowReg); - if ((size == kLong) || (size == kDouble)) { - if (scale) { - int rNewIndex = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale); - opRegReg(cUnit, kOpAdd, regPtr, rNewIndex); - oatFreeTemp(cUnit, rNewIndex); - } else { - opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg); + storeValue(cUnit, rlDest, rlResult); } - oatFreeTemp(cUnit, rlIndex.lowReg); - rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - + } else { + int regPtr = oatAllocTemp(cUnit); + bool needsRangeCheck = (!(optFlags & MIR_IGNORE_RANGE_CHECK)); + int regLen = INVALID_REG; if (needsRangeCheck) { - // TODO: change kCondCS to a more meaningful name, is the sense of - // carry-set/clear flipped? - genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); - oatFreeTemp(cUnit, regLen); + regLen = oatAllocTemp(cUnit); + /* Get len */ + loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); } - loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg); + /* regPtr -> array data */ + opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset); + oatFreeTemp(cUnit, rlArray.lowReg); + if ((size == kLong) || (size == kDouble)) { + if (scale) { + int rNewIndex = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale); + opRegReg(cUnit, kOpAdd, regPtr, rNewIndex); + oatFreeTemp(cUnit, rNewIndex); + } else { + opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg); + } + oatFreeTemp(cUnit, rlIndex.lowReg); + rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - oatFreeTemp(cUnit, regPtr); - storeValueWide(cUnit, rlDest, rlResult); - } else { - rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); + if (needsRangeCheck) { + // TODO: change kCondCS to a more meaningful name, is the sense of + // carry-set/clear flipped? + genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); + oatFreeTemp(cUnit, regLen); + } + loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg); - if (needsRangeCheck) { - // TODO: change kCondCS to a more meaningful name, is the sense of - // carry-set/clear flipped? - genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); - oatFreeTemp(cUnit, regLen); - } - loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg, - scale, size); + oatFreeTemp(cUnit, regPtr); + storeValueWide(cUnit, rlDest, rlResult); + } else { + rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - oatFreeTemp(cUnit, regPtr); - storeValue(cUnit, rlDest, rlResult); + if (needsRangeCheck) { + // TODO: change kCondCS to a more meaningful name, is the sense of + // carry-set/clear flipped? + genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); + oatFreeTemp(cUnit, regLen); + } + loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg, scale, size); + + oatFreeTemp(cUnit, regPtr); + storeValue(cUnit, rlDest, rlResult); + } } -#endif } /* @@ -1631,85 +1477,82 @@ void genArrayPut(CompilationUnit* cUnit, int optFlags, OpSize size, rlArray = loadValue(cUnit, rlArray, kCoreReg); rlIndex = loadValue(cUnit, rlIndex, kCoreReg); -#if !defined(TARGET_X86) - int regPtr; - if (oatIsTemp(cUnit, rlArray.lowReg)) { - oatClobber(cUnit, rlArray.lowReg); - regPtr = rlArray.lowReg; - } else { - regPtr = oatAllocTemp(cUnit); - opRegCopy(cUnit, regPtr, rlArray.lowReg); + int regPtr = INVALID_REG; + if (cUnit->instructionSet != kX86) { + if (oatIsTemp(cUnit, rlArray.lowReg)) { + oatClobber(cUnit, rlArray.lowReg); + regPtr = rlArray.lowReg; + } else { + regPtr = oatAllocTemp(cUnit); + opRegCopy(cUnit, regPtr, rlArray.lowReg); + } } -#endif /* null object? */ genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, optFlags); -#if defined(TARGET_X86) - if (!(optFlags & MIR_IGNORE_RANGE_CHECK)) { - /* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */ - genRegMemCheck(cUnit, kCondUge, rlIndex.lowReg, rlArray.lowReg, - lenOffset, kThrowArrayBounds); - } - if ((size == kLong) || (size == kDouble)) { - rlSrc = loadValueWide(cUnit, rlSrc, regClass); - } else { - rlSrc = loadValue(cUnit, rlSrc, regClass); - } - // If the src reg can't be byte accessed, move it to a temp first. - if ((size == kSignedByte || size == kUnsignedByte) && rlSrc.lowReg >= 4) { - int temp = oatAllocTemp(cUnit); - opRegCopy(cUnit, temp, rlSrc.lowReg); - storeBaseIndexedDisp(cUnit, rlArray.lowReg, rlIndex.lowReg, scale, - dataOffset, temp, INVALID_REG, size, - INVALID_SREG); - } else { - storeBaseIndexedDisp(cUnit, rlArray.lowReg, rlIndex.lowReg, scale, - dataOffset, rlSrc.lowReg, rlSrc.highReg, size, - INVALID_SREG); - } -#else - bool needsRangeCheck = (!(optFlags & MIR_IGNORE_RANGE_CHECK)); - int regLen = INVALID_REG; - if (needsRangeCheck) { - regLen = oatAllocTemp(cUnit); - //NOTE: max live temps(4) here. - /* Get len */ - loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); - } - /* regPtr -> array data */ - opRegImm(cUnit, kOpAdd, regPtr, dataOffset); - /* at this point, regPtr points to array, 2 live temps */ - if ((size == kLong) || (size == kDouble)) { - //TUNING: specific wide routine that can handle fp regs - if (scale) { - int rNewIndex = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale); - opRegReg(cUnit, kOpAdd, regPtr, rNewIndex); - oatFreeTemp(cUnit, rNewIndex); + if (cUnit->instructionSet == kX86) { + if (!(optFlags & MIR_IGNORE_RANGE_CHECK)) { + /* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */ + genRegMemCheck(cUnit, kCondUge, rlIndex.lowReg, rlArray.lowReg, lenOffset, kThrowArrayBounds); + } + if ((size == kLong) || (size == kDouble)) { + rlSrc = loadValueWide(cUnit, rlSrc, regClass); } else { - opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg); + rlSrc = loadValue(cUnit, rlSrc, regClass); } - rlSrc = loadValueWide(cUnit, rlSrc, regClass); - + // If the src reg can't be byte accessed, move it to a temp first. + if ((size == kSignedByte || size == kUnsignedByte) && rlSrc.lowReg >= 4) { + int temp = oatAllocTemp(cUnit); + opRegCopy(cUnit, temp, rlSrc.lowReg); + storeBaseIndexedDisp(cUnit, rlArray.lowReg, rlIndex.lowReg, scale, dataOffset, temp, + INVALID_REG, size, INVALID_SREG); + } else { + storeBaseIndexedDisp(cUnit, rlArray.lowReg, rlIndex.lowReg, scale, dataOffset, rlSrc.lowReg, + rlSrc.highReg, size, INVALID_SREG); + } + } else { + bool needsRangeCheck = (!(optFlags & MIR_IGNORE_RANGE_CHECK)); + int regLen = INVALID_REG; if (needsRangeCheck) { - genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); - oatFreeTemp(cUnit, regLen); + regLen = oatAllocTemp(cUnit); + //NOTE: max live temps(4) here. + /* Get len */ + loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); } + /* regPtr -> array data */ + opRegImm(cUnit, kOpAdd, regPtr, dataOffset); + /* at this point, regPtr points to array, 2 live temps */ + if ((size == kLong) || (size == kDouble)) { + //TUNING: specific wide routine that can handle fp regs + if (scale) { + int rNewIndex = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale); + opRegReg(cUnit, kOpAdd, regPtr, rNewIndex); + oatFreeTemp(cUnit, rNewIndex); + } else { + opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg); + } + rlSrc = loadValueWide(cUnit, rlSrc, regClass); - storeBaseDispWide(cUnit, regPtr, 0, rlSrc.lowReg, rlSrc.highReg); + if (needsRangeCheck) { + genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); + oatFreeTemp(cUnit, regLen); + } - oatFreeTemp(cUnit, regPtr); - } else { - rlSrc = loadValue(cUnit, rlSrc, regClass); - if (needsRangeCheck) { - genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); - oatFreeTemp(cUnit, regLen); + storeBaseDispWide(cUnit, regPtr, 0, rlSrc.lowReg, rlSrc.highReg); + + oatFreeTemp(cUnit, regPtr); + } else { + rlSrc = loadValue(cUnit, rlSrc, regClass); + if (needsRangeCheck) { + genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds); + oatFreeTemp(cUnit, regLen); + } + storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg, + scale, size); } - storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg, - scale, size); } -#endif } void genLong3Addr(CompilationUnit* cUnit, OpKind firstOp, @@ -1717,18 +1560,18 @@ void genLong3Addr(CompilationUnit* cUnit, OpKind firstOp, RegLocation rlSrc1, RegLocation rlSrc2) { RegLocation rlResult; -#if defined(TARGET_ARM) - /* - * NOTE: This is the one place in the code in which we might have - * as many as six live temporary registers. There are 5 in the normal - * set for Arm. Until we have spill capabilities, temporarily add - * lr to the temp set. It is safe to do this locally, but note that - * lr is used explicitly elsewhere in the code generator and cannot - * normally be used as a general temp register. - */ - oatMarkTemp(cUnit, rLR); // Add lr to the temp pool - oatFreeTemp(cUnit, rLR); // and make it available -#endif + if (cUnit->instructionSet == kThumb2) { + /* + * NOTE: This is the one place in the code in which we might have + * as many as six live temporary registers. There are 5 in the normal + * set for Arm. Until we have spill capabilities, temporarily add + * lr to the temp set. It is safe to do this locally, but note that + * lr is used explicitly elsewhere in the code generator and cannot + * normally be used as a general temp register. + */ + oatMarkTemp(cUnit, rLR); // Add lr to the temp pool + oatFreeTemp(cUnit, rLR); // and make it available + } rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); @@ -1754,10 +1597,10 @@ void genLong3Addr(CompilationUnit* cUnit, OpKind firstOp, freeRegLocTemps(cUnit, rlResult, rlSrc1); freeRegLocTemps(cUnit, rlResult, rlSrc2); storeValueWide(cUnit, rlDest, rlResult); -#if defined(TARGET_ARM) - oatClobber(cUnit, rLR); - oatUnmarkTemp(cUnit, rLR); // Remove lr from the temp pool -#endif + if (cUnit->instructionSet == kThumb2) { + oatClobber(cUnit, rLR); + oatUnmarkTemp(cUnit, rLR); // Remove lr from the temp pool + } } @@ -1872,15 +1715,16 @@ bool genArithOpInt(CompilationUnit* cUnit, Instruction::Code opcode, RegLocation opRegReg(cUnit, op, rlResult.lowReg, rlSrc1.lowReg); } else { if (shiftOp) { -#if !defined(TARGET_X86) - rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); - int tReg = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31); -#else - // X86 doesn't require masking and must use ECX - loadValueDirectFixed(cUnit, rlSrc2, rCX); - int tReg = rCX; -#endif + int tReg = INVALID_REG; + if (cUnit->instructionSet == kX86) { + // X86 doesn't require masking and must use ECX + tReg = rCOUNT; // rCX + loadValueDirectFixed(cUnit, rlSrc2, tReg); + } else { + rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); + tReg = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31); + } rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); opRegRegReg(cUnit, op, rlResult.lowReg, rlSrc1.lowReg, tReg); @@ -1894,43 +1738,29 @@ bool genArithOpInt(CompilationUnit* cUnit, Instruction::Code opcode, RegLocation } storeValue(cUnit, rlDest, rlResult); } else { -#if defined(TARGET_MIPS) - rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); - rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); - if (checkZero) { - genImmedCheck(cUnit, kCondEq, rlSrc2.lowReg, 0, kThrowDivZero); - } - newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc1.lowReg, rlSrc2.lowReg); - rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); - if (op == kOpDiv) { - newLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO); + if (cUnit->instructionSet == kMips) { + rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); + rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); + if (checkZero) { + genImmedCheck(cUnit, kCondEq, rlSrc2.lowReg, 0, kThrowDivZero); + } + rlResult = genDivRem(cUnit, rlDest, rlSrc1.lowReg, rlSrc2.lowReg, op == kOpDiv); } else { - newLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI); - } -#else - int funcOffset = ENTRYPOINT_OFFSET(pIdivmod); - RegLocation rlResult; - oatFlushAllRegs(cUnit); /* Send everything to home location */ - loadValueDirectFixed(cUnit, rlSrc2, rARG1); -#if defined(TARGET_ARM) - int rTgt = loadHelper(cUnit, funcOffset); -#endif - loadValueDirectFixed(cUnit, rlSrc1, rARG0); - if (checkZero) { - genImmedCheck(cUnit, kCondEq, rARG1, 0, kThrowDivZero); + int funcOffset = ENTRYPOINT_OFFSET(pIdivmod); + oatFlushAllRegs(cUnit); /* Send everything to home location */ + loadValueDirectFixed(cUnit, rlSrc2, rARG1); + int rTgt = callHelperSetup(cUnit, funcOffset); + loadValueDirectFixed(cUnit, rlSrc1, rARG0); + if (checkZero) { + genImmedCheck(cUnit, kCondEq, rARG1, 0, kThrowDivZero); + } + // NOTE: callout here is not a safepoint + callHelper(cUnit, rTgt, funcOffset, false /* not a safepoint */ ); + if (op == kOpDiv) + rlResult = oatGetReturn(cUnit, false); + else + rlResult = oatGetReturnAlt(cUnit); } - // NOTE: callout here is not a safepoint -#if defined(TARGET_ARM) - opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - opThreadMem(cUnit, kOpBlx, funcOffset); -#endif - if (op == kOpDiv) - rlResult = oatGetReturn(cUnit, false); - else - rlResult = oatGetReturnAlt(cUnit); -#endif storeValue(cUnit, rlDest, rlResult); } return false; @@ -1973,19 +1803,12 @@ int lowestSetBit(unsigned int x) { bool handleEasyDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, RegLocation rlSrc, RegLocation rlDest, int lit) { -#if defined(TARGET_ARM) - // No divide instruction for Arm, so check for more special cases - if (lit < 2) { + if (lit < 2) return false; - } - if (!isPowerOfTwo(lit)) { + // No divide instruction for Arm, so check for more special cases + if ((cUnit->instructionSet == kThumb2) && !isPowerOfTwo(lit)) { return smallLiteralDivide(cUnit, dalvikOpcode, rlSrc, rlDest, lit); } -#else - if (lit < 2 || !isPowerOfTwo(lit)) { - return false; - } -#endif int k = lowestSetBit(lit); if (k >= 30) { // Avoid special cases. @@ -2028,24 +1851,6 @@ bool handleEasyDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, return true; } -void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc, - RegLocation rlResult, int lit, - int firstBit, int secondBit) -{ -#if defined(TARGET_ARM) - opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg, - encodeShift(kArmLsl, secondBit - firstBit)); -#else - int tReg = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, secondBit - firstBit); - opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, tReg); - oatFreeTemp(cUnit, tReg); -#endif - if (firstBit != 0) { - opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit); - } -} - // Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit' // and store the result in 'rlDest'. bool handleEasyMultiply(CompilationUnit* cUnit, RegLocation rlSrc, @@ -2174,29 +1979,20 @@ bool genArithOpIntLit(CompilationUnit* cUnit, Instruction::Code opcode, } else { isDiv = false; } -#if defined(TARGET_MIPS) - rlSrc = loadValue(cUnit, rlSrc, kCoreReg); - int tReg = oatAllocTemp(cUnit); - newLIR3(cUnit, kMipsAddiu, tReg, r_ZERO, lit); - newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc.lowReg, tReg); - rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); - if (isDiv) { - newLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO); + if (cUnit->instructionSet == kMips) { + rlSrc = loadValue(cUnit, rlSrc, kCoreReg); + rlResult = genDivRemLit(cUnit, rlDest, rlSrc.lowReg, lit, isDiv); } else { - newLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI); + oatFlushAllRegs(cUnit); /* Everything to home location */ + loadValueDirectFixed(cUnit, rlSrc, rARG0); + oatClobber(cUnit, rARG0); + int funcOffset = ENTRYPOINT_OFFSET(pIdivmod); + callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit, false); + if (isDiv) + rlResult = oatGetReturn(cUnit, false); + else + rlResult = oatGetReturnAlt(cUnit); } - oatFreeTemp(cUnit, tReg); -#else - oatFlushAllRegs(cUnit); /* Everything to home location */ - loadValueDirectFixed(cUnit, rlSrc, rARG0); - oatClobber(cUnit, rARG0); - int funcOffset = ENTRYPOINT_OFFSET(pIdivmod); - callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit, false); - if (isDiv) - rlResult = oatGetReturn(cUnit, false); - else - rlResult = oatGetReturnAlt(cUnit); -#endif storeValue(cUnit, rlDest, rlResult); return false; break; @@ -2247,22 +2043,20 @@ bool genArithOpLong(CompilationUnit* cUnit, Instruction::Code opcode, RegLocatio break; case Instruction::ADD_LONG: case Instruction::ADD_LONG_2ADDR: -#if defined(TARGET_MIPS) || defined(TARGET_X86) - return genAddLong(cUnit, rlDest, rlSrc1, rlSrc2); -#else + if (cUnit->instructionSet != kThumb2) { + return genAddLong(cUnit, rlDest, rlSrc1, rlSrc2); + } firstOp = kOpAdd; secondOp = kOpAdc; break; -#endif case Instruction::SUB_LONG: case Instruction::SUB_LONG_2ADDR: -#if defined(TARGET_MIPS) || defined(TARGET_X86) - return genSubLong(cUnit, rlDest, rlSrc1, rlSrc2); -#else + if (cUnit->instructionSet != kThumb2) { + return genSubLong(cUnit, rlDest, rlSrc1, rlSrc2); + } firstOp = kOpSub; secondOp = kOpSbc; break; -#endif case Instruction::MUL_LONG: case Instruction::MUL_LONG_2ADDR: callOut = true; @@ -2281,40 +2075,33 @@ bool genArithOpLong(CompilationUnit* cUnit, Instruction::Code opcode, RegLocatio callOut = true; checkZero = true; funcOffset = ENTRYPOINT_OFFSET(pLdivmod); -#if defined(TARGET_ARM) - /* NOTE - result is in rARG2/rARG3 instead of rRET0/rRET1 */ - retReg = rARG2; -#else - retReg = rRET0; -#endif + /* NOTE - for Arm, result is in rARG2/rARG3 instead of rRET0/rRET1 */ + retReg = (cUnit->instructionSet == kThumb2) ? rARG2 : rRET0; break; case Instruction::AND_LONG_2ADDR: case Instruction::AND_LONG: -#if defined(TARGET_X86) - return genAndLong(cUnit, rlDest, rlSrc1, rlSrc2); -#else + if (cUnit->instructionSet == kX86) { + return genAndLong(cUnit, rlDest, rlSrc1, rlSrc2); + } firstOp = kOpAnd; secondOp = kOpAnd; break; -#endif case Instruction::OR_LONG: case Instruction::OR_LONG_2ADDR: -#if defined(TARGET_X86) - return genOrLong(cUnit, rlDest, rlSrc1, rlSrc2); -#else + if (cUnit->instructionSet == kX86) { + return genOrLong(cUnit, rlDest, rlSrc1, rlSrc2); + } firstOp = kOpOr; secondOp = kOpOr; break; -#endif case Instruction::XOR_LONG: case Instruction::XOR_LONG_2ADDR: -#if defined(TARGET_X86) - return genXorLong(cUnit, rlDest, rlSrc1, rlSrc2); -#else + if (cUnit->instructionSet == kX86) { + return genXorLong(cUnit, rlDest, rlSrc1, rlSrc2); + } firstOp = kOpXor; secondOp = kOpXor; break; -#endif case Instruction::NEG_LONG: { return genNegLong(cUnit, rlDest, rlSrc2); } @@ -2327,27 +2114,11 @@ bool genArithOpLong(CompilationUnit* cUnit, Instruction::Code opcode, RegLocatio oatFlushAllRegs(cUnit); /* Send everything to home location */ if (checkZero) { loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3); -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, funcOffset); -#endif - int tReg = oatAllocTemp(cUnit); -#if defined(TARGET_ARM) - newLIR4(cUnit, kThumb2OrrRRRs, tReg, rARG2, rARG3, 0); - oatFreeTemp(cUnit, tReg); - genCheck(cUnit, kCondEq, kThrowDivZero); -#else - opRegRegReg(cUnit, kOpOr, tReg, rARG2, rARG3); -#endif - genImmedCheck(cUnit, kCondEq, tReg, 0, kThrowDivZero); - oatFreeTemp(cUnit, tReg); + int rTgt = callHelperSetup(cUnit, funcOffset); + genDivZeroCheck(cUnit, rARG2, rARG3); loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1); // NOTE: callout here is not a safepoint -#if !defined(TARGET_X86) - opReg(cUnit, kOpBlx, rTgt); - oatFreeTemp(cUnit, rTgt); -#else - opThreadMem(cUnit, kOpBlx, funcOffset); -#endif + callHelper(cUnit, rTgt, funcOffset, false /* not safepoint */); } else { callRuntimeHelperRegLocationRegLocation(cUnit, funcOffset, rlSrc1, rlSrc2, false); @@ -2515,40 +2286,6 @@ bool genConversionPortable(CompilationUnit* cUnit, Instruction::Code opcode, return false; } -/* - * Generate callout to updateDebugger. Note that we're overloading - * the use of rSUSPEND here. When the debugger is active, this - * register holds the address of the update function. So, if it's - * non-null, we call out to it. - * - * Note also that rRET0 and rRET1 must be preserved across this - * code. This must be handled by the stub. - */ -void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset) -{ - // Following DCHECK verifies that dPC is in range of single load immediate - DCHECK((offset == DEBUGGER_METHOD_ENTRY) || - (offset == DEBUGGER_METHOD_EXIT) || ((offset & 0xffff) == offset)); - oatClobberCalleeSave(cUnit); -#if defined(TARGET_ARM) - opRegImm(cUnit, kOpCmp, rSUSPEND, 0); - opIT(cUnit, kArmCondNe, "T"); - loadConstant(cUnit, rARG2, offset); // arg2 <- Entry code - LIR* callInst = opReg(cUnit, kOpBlx, rSUSPEND); - markSafepointPC(cUnit, callInst); -#elif defined(TARGET_X86) - UNIMPLEMENTED(FATAL); -#else - LIR* branch = opCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0, NULL); - loadConstant(cUnit, rARG2, offset); - LIR* callInst = opReg(cUnit, kOpBlx, rSUSPEND); - markSafepointPC(cUnit, callInst); - LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - branch->target = (LIR*)target; -#endif - oatFreeTemp(cUnit, rARG2); -} - /* Check if we need to check for pending suspend request */ void genSuspendTest(CompilationUnit* cUnit, int optFlags) { @@ -2556,38 +2293,12 @@ void genSuspendTest(CompilationUnit* cUnit, int optFlags) return; } oatFlushAllRegs(cUnit); - if (cUnit->genDebugger) { - // If generating code for the debugger, always check for suspension -#if defined(TARGET_X86) - UNIMPLEMENTED(FATAL); -#else - int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pTestSuspendFromCode)); - LIR* callInst = opReg(cUnit, kOpBlx, rTgt); - markSafepointPC(cUnit, callInst); - // Refresh rSUSPEND - loadWordDisp(cUnit, rSELF, - ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode), - rSUSPEND); -#endif - } else { - LIR* branch = NULL; -#if defined(TARGET_ARM) - // In non-debug case, only check periodically - newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1); - branch = opCondBranch(cUnit, kCondEq, NULL); -#elif defined(TARGET_X86) - newLIR2(cUnit, kX86Cmp16TI8, Thread::ThreadFlagsOffset().Int32Value(), 0); - branch = opCondBranch(cUnit, kCondNe, NULL); -#else - opRegImm(cUnit, kOpSub, rSUSPEND, 1); - branch = opCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0, NULL); -#endif - LIR* retLab = newLIR0(cUnit, kPseudoTargetLabel); - LIR* target = rawLIR(cUnit, cUnit->currentDalvikOffset, - kPseudoSuspendTarget, (intptr_t)retLab, cUnit->currentDalvikOffset); - branch->target = (LIR*)target; - oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)target); - } + LIR* branch = opTestSuspend(cUnit, NULL); + LIR* retLab = newLIR0(cUnit, kPseudoTargetLabel); + LIR* target = rawLIR(cUnit, cUnit->currentDalvikOffset, kPseudoSuspendTarget, + (intptr_t)retLab, cUnit->currentDalvikOffset); + branch->target = (LIR*)target; + oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)target); } /* Check if we need to check for pending suspend request */ @@ -2597,28 +2308,12 @@ void genSuspendTestAndBranch(CompilationUnit* cUnit, int optFlags, LIR* target) opUnconditionalBranch(cUnit, target); return; } - if (cUnit->genDebugger) { - genSuspendTest(cUnit, optFlags); - opUnconditionalBranch(cUnit, target); - } else { -#if defined(TARGET_ARM) - // In non-debug case, only check periodically - newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1); - opCondBranch(cUnit, kCondNe, target); -#elif defined(TARGET_X86) - newLIR2(cUnit, kX86Cmp16TI8, Thread::ThreadFlagsOffset().Int32Value(), 0); - opCondBranch(cUnit, kCondEq, target); -#else - opRegImm(cUnit, kOpSub, rSUSPEND, 1); - opCmpImmBranch(cUnit, kCondNe, rSUSPEND, 0, target); -#endif - LIR* launchPad = rawLIR(cUnit, cUnit->currentDalvikOffset, - kPseudoSuspendTarget, (intptr_t)target, cUnit->currentDalvikOffset); - oatFlushAllRegs(cUnit); - opUnconditionalBranch(cUnit, launchPad); - oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, - (intptr_t)launchPad); - } + opTestSuspend(cUnit, target); + LIR* launchPad = rawLIR(cUnit, cUnit->currentDalvikOffset, kPseudoSuspendTarget, (intptr_t)target, + cUnit->currentDalvikOffset); + oatFlushAllRegs(cUnit); + opUnconditionalBranch(cUnit, launchPad); + oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)launchPad); } } // namespace art diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc index 0208a4afc5..2da6242ab6 100644 --- a/src/compiler/codegen/GenInvoke.cc +++ b/src/compiler/codegen/GenInvoke.cc @@ -140,10 +140,11 @@ int nextSDCallInsn(CompilationUnit* cUnit, CallInfo* info, uintptr_t directCode, uintptr_t directMethod, InvokeType type) { -#if !defined(TARGET_ARM) - directCode = 0; - directMethod = 0; -#endif + if (cUnit->instructionSet != kThumb2) { + // Disable sharpening + directCode = 0; + directMethod = 0; + } if (directCode != 0 && directMethod != 0) { switch (state) { case 0: // Get the current Method* [sets rARG0] @@ -155,14 +156,9 @@ int nextSDCallInsn(CompilationUnit* cUnit, CallInfo* info, dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx); dataTarget->operands[1] = type; } -#if defined(TARGET_ARM) - LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, - kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0, - dataTarget); + LIR* loadPcRel = opPcRelLoad(cUnit, rINVOKE_TGT, dataTarget); oatAppendLIR(cUnit, loadPcRel); -#else - UNIMPLEMENTED(FATAL) << (void*)dataTarget; -#endif + DCHECK_EQ(cUnit->instructionSet, kThumb2) << (void*)dataTarget; } if (directMethod != (uintptr_t)-1) { loadConstant(cUnit, rARG0, directMethod); @@ -172,14 +168,9 @@ int nextSDCallInsn(CompilationUnit* cUnit, CallInfo* info, dataTarget = addWordData(cUnit, &cUnit->methodLiteralList, dexIdx); dataTarget->operands[1] = type; } -#if defined(TARGET_ARM) - LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, - kThumb2LdrPcRel12, rARG0, 0, 0, 0, 0, - dataTarget); + LIR* loadPcRel = opPcRelLoad(cUnit, rARG0, dataTarget); oatAppendLIR(cUnit, loadPcRel); -#else - UNIMPLEMENTED(FATAL) << (void*)dataTarget; -#endif + DCHECK_EQ(cUnit->instructionSet, kThumb2) << (void*)dataTarget; } break; default: @@ -205,14 +196,9 @@ int nextSDCallInsn(CompilationUnit* cUnit, CallInfo* info, dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx); dataTarget->operands[1] = type; } -#if defined(TARGET_ARM) - LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, - kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0, - dataTarget); + LIR* loadPcRel = opPcRelLoad(cUnit, rINVOKE_TGT, dataTarget); oatAppendLIR(cUnit, loadPcRel); -#else - UNIMPLEMENTED(FATAL) << (void*)dataTarget; -#endif + DCHECK_EQ(cUnit->instructionSet, kThumb2) << (void*)dataTarget; } } break; @@ -221,14 +207,15 @@ int nextSDCallInsn(CompilationUnit* cUnit, CallInfo* info, Array::DataOffset(sizeof(Object*)).Int32Value() + dexIdx * 4, rARG0); break; -#if !defined(TARGET_X86) case 3: // Grab the code from the method* - if (directCode == 0) { - loadWordDisp(cUnit, rARG0, AbstractMethod::GetCodeOffset().Int32Value(), - rINVOKE_TGT); + if (cUnit->instructionSet != kX86) { + if (directCode == 0) { + loadWordDisp(cUnit, rARG0, AbstractMethod::GetCodeOffset().Int32Value(), + rINVOKE_TGT); + } + break; } - break; -#endif + // Intentional fallthrough for x86 default: return -1; } @@ -271,12 +258,12 @@ int nextVCallInsn(CompilationUnit* cUnit, CallInfo* info, loadWordDisp(cUnit, rINVOKE_TGT, (methodIdx * 4) + Array::DataOffset(sizeof(Object*)).Int32Value(), rARG0); break; -#if !defined(TARGET_X86) case 4: // Get the compiled code address [uses rARG0, sets rINVOKE_TGT] - loadWordDisp(cUnit, rARG0, AbstractMethod::GetCodeOffset().Int32Value(), - rINVOKE_TGT); - break; -#endif + if (cUnit->instructionSet != kX86) { + loadWordDisp(cUnit, rARG0, AbstractMethod::GetCodeOffset().Int32Value(), rINVOKE_TGT); + break; + } + // Intentional fallthrough for X86 default: return -1; } @@ -291,19 +278,19 @@ int nextInterfaceCallInsn(CompilationUnit* cUnit, CallInfo* info, int state, uint32_t dexIdx, uint32_t unused, uintptr_t unused2, uintptr_t directMethod, InvokeType unused4) { -#if !defined(TARGET_ARM) - directMethod = 0; -#endif -#if !defined(TARGET_X86) - int trampoline = ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline); -#endif + if (cUnit->instructionSet != kThumb2) { + // Disable sharpening + directMethod = 0; + } + int trampoline = (cUnit->instructionSet == kX86) ? 0 + : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline); if (directMethod != 0) { switch (state) { case 0: // Load the trampoline target [sets rINVOKE_TGT]. -#if !defined(TARGET_X86) - loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT); -#endif + if (cUnit->instructionSet != kX86) { + loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT); + } // Get the interface Method* [sets rARG0] if (directMethod != (uintptr_t)-1) { loadConstant(cUnit, rARG0, directMethod); @@ -313,14 +300,9 @@ int nextInterfaceCallInsn(CompilationUnit* cUnit, CallInfo* info, int state, dataTarget = addWordData(cUnit, &cUnit->methodLiteralList, dexIdx); dataTarget->operands[1] = kInterface; } -#if defined(TARGET_ARM) - LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, - kThumb2LdrPcRel12, rARG0, 0, 0, 0, 0, - dataTarget); + LIR* loadPcRel = opPcRelLoad(cUnit, rARG0, dataTarget); oatAppendLIR(cUnit, loadPcRel); -#else - UNIMPLEMENTED(FATAL) << (void*)dataTarget; -#endif + DCHECK_EQ(cUnit->instructionSet, kThumb2) << (void*)dataTarget; } break; default: @@ -332,9 +314,9 @@ int nextInterfaceCallInsn(CompilationUnit* cUnit, CallInfo* info, int state, // Get the current Method* [sets rARG0] - TUNING: remove copy of method if it is promoted. loadCurrMethodDirect(cUnit, rARG0); // Load the trampoline target [sets rINVOKE_TGT]. -#if !defined(TARGET_X86) - loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT); -#endif + if (cUnit->instructionSet != kX86) { + loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT); + } break; case 1: // Get method->dex_cache_resolved_methods_ [set/use rARG0] loadWordDisp(cUnit, rARG0, @@ -361,10 +343,10 @@ int nextInvokeInsnSP(CompilationUnit* cUnit, CallInfo* info, int trampoline, * resolved at compile time, we bail to a runtime helper. */ if (state == 0) { -#if !defined(TARGET_X86) - // Load trampoline target - loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT); -#endif + if (cUnit->instructionSet != kX86) { + // Load trampoline target + loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT); + } // Load rARG0 with method index loadConstant(cUnit, rARG0, dexIdx); return 1; @@ -593,42 +575,41 @@ int genDalvikArgsRange(CompilationUnit* cUnit, CallInfo* info, int callState, int startOffset = oatSRegOffset(cUnit, info->args[3].sRegLow); int outsOffset = 4 /* Method* */ + (3 * 4); -#if defined(TARGET_MIPS) || defined(TARGET_X86) - // Generate memcpy - opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset); - opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset); - callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy), - rARG0, rARG1, (info->numArgWords - 3) * 4, false); -#else - if (info->numArgWords >= 20) { + if (cUnit->instructionSet != kThumb2) { // Generate memcpy opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset); opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset); callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy), rARG0, rARG1, (info->numArgWords - 3) * 4, false); } else { - // Use vldm/vstm pair using rARG3 as a temp - int regsLeft = std::min(info->numArgWords - 3, 16); - callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, - directCode, directMethod, type); - opRegRegImm(cUnit, kOpAdd, rARG3, rSP, startOffset); - LIR* ld = newLIR3(cUnit, kThumb2Vldms, rARG3, fr0, regsLeft); - //TUNING: loosen barrier - ld->defMask = ENCODE_ALL; - setMemRefType(ld, true /* isLoad */, kDalvikReg); - callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, - directCode, directMethod, type); - opRegRegImm(cUnit, kOpAdd, rARG3, rSP, 4 /* Method* */ + (3 * 4)); - callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, - directCode, directMethod, type); - LIR* st = newLIR3(cUnit, kThumb2Vstms, rARG3, fr0, regsLeft); - setMemRefType(st, false /* isLoad */, kDalvikReg); - st->defMask = ENCODE_ALL; - callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, - directCode, directMethod, type); - + if (info->numArgWords >= 20) { + // Generate memcpy + opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset); + opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset); + callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy), + rARG0, rARG1, (info->numArgWords - 3) * 4, false); + } else { + // Use vldm/vstm pair using rARG3 as a temp + int regsLeft = std::min(info->numArgWords - 3, 16); + callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, + directCode, directMethod, type); + opRegRegImm(cUnit, kOpAdd, rARG3, rSP, startOffset); + LIR* ld = opVldm(cUnit, rARG3, regsLeft); + //TUNING: loosen barrier + ld->defMask = ENCODE_ALL; + setMemRefType(ld, true /* isLoad */, kDalvikReg); + callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, + directCode, directMethod, type); + opRegRegImm(cUnit, kOpAdd, rARG3, rSP, 4 /* Method* */ + (3 * 4)); + callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, + directCode, directMethod, type); + LIR* st = opVstm(cUnit, rARG3, regsLeft); + setMemRefType(st, false /* isLoad */, kDalvikReg); + st->defMask = ENCODE_ALL; + callState = nextCallInsn(cUnit, info, callState, dexIdx, methodIdx, + directCode, directMethod, type); + } } -#endif callState = loadArgRegs(cUnit, info, callState, nextCallInsn, dexIdx, methodIdx, directCode, directMethod, @@ -667,7 +648,10 @@ RegLocation inlineTargetWide(CompilationUnit* cUnit, CallInfo* info) bool genInlinedCharAt(CompilationUnit* cUnit, CallInfo* info) { -#if defined(TARGET_ARM) || defined(TARGET_X86) + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } // Location of reference to data array int valueOffset = String::ValueOffset().Int32Value(); // Location of count @@ -685,41 +669,43 @@ bool genInlinedCharAt(CompilationUnit* cUnit, CallInfo* info) genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, info->optFlags); bool rangeCheck = (!(info->optFlags & MIR_IGNORE_RANGE_CHECK)); LIR* launchPad = NULL; -#if !defined(TARGET_X86) - int regOff = oatAllocTemp(cUnit); - int regPtr = oatAllocTemp(cUnit); - if (rangeCheck) { - regMax = oatAllocTemp(cUnit); - loadWordDisp(cUnit, rlObj.lowReg, countOffset, regMax); - } - loadWordDisp(cUnit, rlObj.lowReg, offsetOffset, regOff); - loadWordDisp(cUnit, rlObj.lowReg, valueOffset, regPtr); - if (rangeCheck) { - // Set up a launch pad to allow retry in case of bounds violation */ - launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); - oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads, - (intptr_t)launchPad); - opRegReg(cUnit, kOpCmp, rlIdx.lowReg, regMax); - oatFreeTemp(cUnit, regMax); - opCondBranch(cUnit, kCondCs, launchPad); - } -#else - if (rangeCheck) { - regMax = oatAllocTemp(cUnit); - loadWordDisp(cUnit, rlObj.lowReg, countOffset, regMax); - // Set up a launch pad to allow retry in case of bounds violation */ - launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); - oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads, - (intptr_t)launchPad); - opRegReg(cUnit, kOpCmp, rlIdx.lowReg, regMax); - oatFreeTemp(cUnit, regMax); - opCondBranch(cUnit, kCondCc, launchPad); + int regOff = INVALID_REG; + int regPtr = INVALID_REG; + if (cUnit->instructionSet != kX86) { + regOff = oatAllocTemp(cUnit); + regPtr = oatAllocTemp(cUnit); + if (rangeCheck) { + regMax = oatAllocTemp(cUnit); + loadWordDisp(cUnit, rlObj.lowReg, countOffset, regMax); + } + loadWordDisp(cUnit, rlObj.lowReg, offsetOffset, regOff); + loadWordDisp(cUnit, rlObj.lowReg, valueOffset, regPtr); + if (rangeCheck) { + // Set up a launch pad to allow retry in case of bounds violation */ + launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); + oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads, + (intptr_t)launchPad); + opRegReg(cUnit, kOpCmp, rlIdx.lowReg, regMax); + oatFreeTemp(cUnit, regMax); + opCondBranch(cUnit, kCondCs, launchPad); + } + } else { + if (rangeCheck) { + regMax = oatAllocTemp(cUnit); + loadWordDisp(cUnit, rlObj.lowReg, countOffset, regMax); + // Set up a launch pad to allow retry in case of bounds violation */ + launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); + oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads, + (intptr_t)launchPad); + opRegReg(cUnit, kOpCmp, rlIdx.lowReg, regMax); + oatFreeTemp(cUnit, regMax); + opCondBranch(cUnit, kCondCc, launchPad); + } + regOff = oatAllocTemp(cUnit); + regPtr = oatAllocTemp(cUnit); + loadWordDisp(cUnit, rlObj.lowReg, offsetOffset, regOff); + loadWordDisp(cUnit, rlObj.lowReg, valueOffset, regPtr); } - int regOff = oatAllocTemp(cUnit); - int regPtr = oatAllocTemp(cUnit); - loadWordDisp(cUnit, rlObj.lowReg, offsetOffset, regOff); - loadWordDisp(cUnit, rlObj.lowReg, valueOffset, regPtr); -#endif opRegImm(cUnit, kOpAdd, regPtr, dataOffset); opRegReg(cUnit, kOpAdd, regOff, rlIdx.lowReg); oatFreeTemp(cUnit, rlObj.lowReg); @@ -736,46 +722,16 @@ bool genInlinedCharAt(CompilationUnit* cUnit, CallInfo* info) // Record that we've already inlined & null checked info->optFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK); return true; -#else - return false; -#endif -} - -bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin) -{ -#if defined(TARGET_ARM) || defined(TARGET_X86) - RegLocation rlSrc1 = info->args[0]; - RegLocation rlSrc2 = info->args[1]; - rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); - rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); - RegLocation rlDest = inlineTarget(cUnit, info); - RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); - opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); -#if defined(TARGET_ARM) - opIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E"); - opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg); - opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg); - genBarrier(cUnit); -#elif defined(TARGET_X86) - LIR* branch = newLIR2(cUnit, kX86Jcc8, 0, isMin ? kX86CondG : kX86CondL); - opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg); - LIR* branch2 = newLIR1(cUnit, kX86Jmp8, 0); - branch->target = newLIR0(cUnit, kPseudoTargetLabel); - opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg); - branch2->target = newLIR0(cUnit, kPseudoTargetLabel); -#endif - storeValue(cUnit, rlDest, rlResult); - return true; -#else - return false; -#endif } // Generates an inlined String.isEmpty or String.length. bool genInlinedStringIsEmptyOrLength(CompilationUnit* cUnit, CallInfo* info, bool isEmpty) { -#if defined(TARGET_ARM) || defined(TARGET_X86) + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } // dst = src.length(); RegLocation rlObj = info->args[0]; rlObj = loadValue(cUnit, rlObj, kCoreReg); @@ -786,25 +742,26 @@ bool genInlinedStringIsEmptyOrLength(CompilationUnit* cUnit, CallInfo* info, rlResult.lowReg); if (isEmpty) { // dst = (dst == 0); -#if defined(TARGET_ARM) - int tReg = oatAllocTemp(cUnit); - opRegReg(cUnit, kOpNeg, tReg, rlResult.lowReg); - opRegRegReg(cUnit, kOpAdc, rlResult.lowReg, rlResult.lowReg, tReg); -#elif defined(TARGET_X86) - opRegImm(cUnit, kOpSub, rlResult.lowReg, 1); - opRegImm(cUnit, kOpLsr, rlResult.lowReg, 31); -#endif + if (cUnit->instructionSet == kThumb2) { + int tReg = oatAllocTemp(cUnit); + opRegReg(cUnit, kOpNeg, tReg, rlResult.lowReg); + opRegRegReg(cUnit, kOpAdc, rlResult.lowReg, rlResult.lowReg, tReg); + } else { + DCHECK_EQ(cUnit->instructionSet, kX86); + opRegImm(cUnit, kOpSub, rlResult.lowReg, 1); + opRegImm(cUnit, kOpLsr, rlResult.lowReg, 31); + } } storeValue(cUnit, rlDest, rlResult); return true; -#else - return false; -#endif } bool genInlinedAbsInt(CompilationUnit *cUnit, CallInfo* info) { -#if defined(TARGET_ARM) || defined(TARGET_X86) + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } RegLocation rlSrc = info->args[0]; rlSrc = loadValue(cUnit, rlSrc, kCoreReg); RegLocation rlDest = inlineTarget(cUnit, info); @@ -816,72 +773,72 @@ bool genInlinedAbsInt(CompilationUnit *cUnit, CallInfo* info) opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg); storeValue(cUnit, rlDest, rlResult); return true; -#else - return false; -#endif } bool genInlinedAbsLong(CompilationUnit *cUnit, CallInfo* info) { -#if defined(TARGET_ARM) - RegLocation rlSrc = info->args[0]; - rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); - RegLocation rlDest = inlineTargetWide(cUnit, info); - RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); - int signReg = oatAllocTemp(cUnit); - // abs(x) = y<=x>>31, (x+y)^y. - opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31); - opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg); - opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc.highReg, signReg); - opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg); - opRegReg(cUnit, kOpXor, rlResult.highReg, signReg); - storeValueWide(cUnit, rlDest, rlResult); - return true; -#elif defined(TARGET_X86) - // Reuse source registers to avoid running out of temps - RegLocation rlSrc = info->args[0]; - rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); - RegLocation rlDest = inlineTargetWide(cUnit, info); - RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); - opRegCopyWide(cUnit, rlResult.lowReg, rlResult.highReg, rlSrc.lowReg, rlSrc.highReg); - oatFreeTemp(cUnit, rlSrc.lowReg); - oatFreeTemp(cUnit, rlSrc.highReg); - int signReg = oatAllocTemp(cUnit); - // abs(x) = y<=x>>31, (x+y)^y. - opRegRegImm(cUnit, kOpAsr, signReg, rlResult.highReg, 31); - opRegReg(cUnit, kOpAdd, rlResult.lowReg, signReg); - opRegReg(cUnit, kOpAdc, rlResult.highReg, signReg); - opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg); - opRegReg(cUnit, kOpXor, rlResult.highReg, signReg); - storeValueWide(cUnit, rlDest, rlResult); - return true; -#else - return false; -#endif + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } + if (cUnit->instructionSet == kThumb2) { + RegLocation rlSrc = info->args[0]; + rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); + RegLocation rlDest = inlineTargetWide(cUnit, info); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + int signReg = oatAllocTemp(cUnit); + // abs(x) = y<=x>>31, (x+y)^y. + opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31); + opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg); + opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc.highReg, signReg); + opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg); + opRegReg(cUnit, kOpXor, rlResult.highReg, signReg); + storeValueWide(cUnit, rlDest, rlResult); + return true; + } else { + DCHECK_EQ(cUnit->instructionSet, kX86); + // Reuse source registers to avoid running out of temps + RegLocation rlSrc = info->args[0]; + rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); + RegLocation rlDest = inlineTargetWide(cUnit, info); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + opRegCopyWide(cUnit, rlResult.lowReg, rlResult.highReg, rlSrc.lowReg, rlSrc.highReg); + oatFreeTemp(cUnit, rlSrc.lowReg); + oatFreeTemp(cUnit, rlSrc.highReg); + int signReg = oatAllocTemp(cUnit); + // abs(x) = y<=x>>31, (x+y)^y. + opRegRegImm(cUnit, kOpAsr, signReg, rlResult.highReg, 31); + opRegReg(cUnit, kOpAdd, rlResult.lowReg, signReg); + opRegReg(cUnit, kOpAdc, rlResult.highReg, signReg); + opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg); + opRegReg(cUnit, kOpXor, rlResult.highReg, signReg); + storeValueWide(cUnit, rlDest, rlResult); + return true; + } } bool genInlinedFloatCvt(CompilationUnit *cUnit, CallInfo* info) { -#if defined(TARGET_ARM) || defined(TARGET_X86) + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } RegLocation rlSrc = info->args[0]; RegLocation rlDest = inlineTarget(cUnit, info); storeValue(cUnit, rlDest, rlSrc); return true; -#else - return false; -#endif } bool genInlinedDoubleCvt(CompilationUnit *cUnit, CallInfo* info) { -#if defined(TARGET_ARM) || defined(TARGET_X86) + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } RegLocation rlSrc = info->args[0]; RegLocation rlDest = inlineTargetWide(cUnit, info); storeValueWide(cUnit, rlDest, rlSrc); return true; -#else - return false; -#endif } /* @@ -891,7 +848,10 @@ bool genInlinedDoubleCvt(CompilationUnit *cUnit, CallInfo* info) bool genInlinedIndexOf(CompilationUnit* cUnit, CallInfo* info, bool zeroBased) { -#if defined(TARGET_ARM) || defined(TARGET_X86) + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } oatClobberCalleeSave(cUnit); oatLockCallTemps(cUnit); // Using fixed registers int regPtr = rARG0; @@ -908,20 +868,18 @@ bool genInlinedIndexOf(CompilationUnit* cUnit, CallInfo* info, } else { loadValueDirectFixed(cUnit, rlStart, regStart); } -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pIndexOf)); -#endif + int rTgt = (cUnit->instructionSet != kX86) ? loadHelper(cUnit, ENTRYPOINT_OFFSET(pIndexOf)) : 0; genNullCheck(cUnit, rlObj.sRegLow, regPtr, info->optFlags); LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads, (intptr_t)launchPad); opCmpImmBranch(cUnit, kCondGt, regChar, 0xFFFF, launchPad); // NOTE: not a safepoint -#if !defined(TARGET_X86) - opReg(cUnit, kOpBlx, rTgt); -#else - opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pIndexOf)); -#endif + if (cUnit->instructionSet != kX86) { + opReg(cUnit, kOpBlx, rTgt); + } else { + opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pIndexOf)); + } LIR* resumeTgt = newLIR0(cUnit, kPseudoTargetLabel); launchPad->operands[2] = (uintptr_t)resumeTgt; // Record that we've already inlined & null checked @@ -930,15 +888,15 @@ bool genInlinedIndexOf(CompilationUnit* cUnit, CallInfo* info, RegLocation rlDest = inlineTarget(cUnit, info); storeValue(cUnit, rlDest, rlReturn); return true; -#else - return false; -#endif } /* Fast string.compareTo(Ljava/lang/string;)I. */ bool genInlinedStringCompareTo(CompilationUnit* cUnit, CallInfo* info) { -#if defined(TARGET_ARM) || defined(TARGET_X86) + if (cUnit->instructionSet == kMips) { + // TODO - add Mips implementation + return false; + } oatClobberCalleeSave(cUnit); oatLockCallTemps(cUnit); // Using fixed registers int regThis = rARG0; @@ -948,9 +906,8 @@ bool genInlinedStringCompareTo(CompilationUnit* cUnit, CallInfo* info) RegLocation rlCmp = info->args[1]; loadValueDirectFixed(cUnit, rlThis, regThis); loadValueDirectFixed(cUnit, rlCmp, regCmp); -#if !defined(TARGET_X86) - int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pStringCompareTo)); -#endif + int rTgt = (cUnit->instructionSet != kX86) ? + loadHelper(cUnit, ENTRYPOINT_OFFSET(pStringCompareTo)) : 0; genNullCheck(cUnit, rlThis.sRegLow, regThis, info->optFlags); //TUNING: check if rlCmp.sRegLow is already null checked LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (uintptr_t)info); @@ -958,11 +915,11 @@ bool genInlinedStringCompareTo(CompilationUnit* cUnit, CallInfo* info) (intptr_t)launchPad); opCmpImmBranch(cUnit, kCondEq, regCmp, 0, launchPad); // NOTE: not a safepoint -#if !defined(TARGET_X86) - opReg(cUnit, kOpBlx, rTgt); -#else - opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pStringCompareTo)); -#endif + if (cUnit->instructionSet != kX86) { + opReg(cUnit, kOpBlx, rTgt); + } else { + opThreadMem(cUnit, kOpBlx, ENTRYPOINT_OFFSET(pStringCompareTo)); + } launchPad->operands[2] = 0; // No return possible // Record that we've already inlined & null checked info->optFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK); @@ -970,97 +927,6 @@ bool genInlinedStringCompareTo(CompilationUnit* cUnit, CallInfo* info) RegLocation rlDest = inlineTarget(cUnit, info); storeValue(cUnit, rlDest, rlReturn); return true; -#else - return false; -#endif -} - -bool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) { -#if defined(TARGET_ARM) - // Unused - RegLocation rlSrcUnsafe = info->args[0]; - RegLocation rlSrcObj= info->args[1]; // Object - known non-null - RegLocation rlSrcOffset= info->args[2]; // long low - rlSrcOffset.wide = 0; // ignore high half in info->args[3] - RegLocation rlSrcExpected= info->args[4]; // int or Object - RegLocation rlSrcNewValue= info->args[5]; // int or Object - RegLocation rlDest = inlineTarget(cUnit, info); // boolean place for result - - - // Release store semantics, get the barrier out of the way. - oatGenMemBarrier(cUnit, kSY); - - RegLocation rlObject = loadValue(cUnit, rlSrcObj, kCoreReg); - RegLocation rlNewValue = loadValue(cUnit, rlSrcNewValue, kCoreReg); - - if (need_write_barrier) { - // Mark card for object assuming new value is stored. - markGCCard(cUnit, rlNewValue.lowReg, rlObject.lowReg); - } - - RegLocation rlOffset = loadValue(cUnit, rlSrcOffset, kCoreReg); - - int rPtr = oatAllocTemp(cUnit); - opRegRegReg(cUnit, kOpAdd, rPtr, rlObject.lowReg, rlOffset.lowReg); - - // Free now unneeded rlObject and rlOffset to give more temps. - oatClobberSReg(cUnit, rlObject.sRegLow); - oatFreeTemp(cUnit, rlObject.lowReg); - oatClobberSReg(cUnit, rlOffset.sRegLow); - oatFreeTemp(cUnit, rlOffset.lowReg); - - int rOldValue = oatAllocTemp(cUnit); - newLIR3(cUnit, kThumb2Ldrex, rOldValue, rPtr, 0); // rOldValue := [rPtr] - - RegLocation rlExpected = loadValue(cUnit, rlSrcExpected, kCoreReg); - - // if (rOldValue == rExpected) { - // [rPtr] <- rNewValue && rResult := success ? 0 : 1 - // rResult ^= 1 - // } else { - // rResult := 0 - // } - opRegReg(cUnit, kOpCmp, rOldValue, rlExpected.lowReg); - oatFreeTemp(cUnit, rOldValue); // Now unneeded. - RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); - opIT(cUnit, kArmCondEq, "TE"); - newLIR4(cUnit, kThumb2Strex, rlResult.lowReg, rlNewValue.lowReg, rPtr, 0); - oatFreeTemp(cUnit, rPtr); // Now unneeded. - opRegImm(cUnit, kOpXor, rlResult.lowReg, 1); - opRegReg(cUnit, kOpXor, rlResult.lowReg, rlResult.lowReg); - - storeValue(cUnit, rlDest, rlResult); - - return true; -#else - return false; -#endif -} - -bool genInlinedSqrt(CompilationUnit* cUnit, CallInfo* info) { -#if defined(TARGET_ARM) - LIR *branch; - RegLocation rlSrc = info->args[0]; - RegLocation rlDest = inlineTargetWide(cUnit, info); // double place for result - rlSrc = loadValueWide(cUnit, rlSrc, kFPReg); - RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true); - newLIR2(cUnit, kThumb2Vsqrtd, S2D(rlResult.lowReg, rlResult.highReg), - S2D(rlSrc.lowReg, rlSrc.highReg)); - newLIR2(cUnit, kThumb2Vcmpd, S2D(rlResult.lowReg, rlResult.highReg), - S2D(rlResult.lowReg, rlResult.highReg)); - newLIR0(cUnit, kThumb2Fmstat); - branch = newLIR2(cUnit, kThumbBCond, 0, kArmCondEq); - oatClobberCalleeSave(cUnit); - oatLockCallTemps(cUnit); // Using fixed registers - int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pSqrt)); - newLIR3(cUnit, kThumb2Fmrrd, r0, r1, S2D(rlSrc.lowReg, rlSrc.highReg)); - newLIR1(cUnit, kThumbBlxR, rTgt); - newLIR3(cUnit, kThumb2Fmdrr, S2D(rlResult.lowReg, rlResult.highReg), r0, r1); - branch->target = newLIR0(cUnit, kPseudoTargetLabel); - storeValueWide(cUnit, rlDest, rlResult); - return true; -#else - return false; -#endif } bool genIntrinsic(CompilationUnit* cUnit, CallInfo* info) diff --git a/src/compiler/codegen/LocalOptimizations.cc b/src/compiler/codegen/LocalOptimizations.cc index 1dca49193a..c0e6036b7f 100644 --- a/src/compiler/codegen/LocalOptimizations.cc +++ b/src/compiler/codegen/LocalOptimizations.cc @@ -91,11 +91,14 @@ void applyLoadStoreElimination(CompilationUnit* cUnit, LIR* headLIR, continue; } -#if defined(TARGET_X86) - int nativeRegId = (EncodingMap[thisLIR->opcode].flags & IS_STORE) ? thisLIR->operands[2] : thisLIR->operands[0]; -#else - int nativeRegId = thisLIR->operands[0]; -#endif + int nativeRegId; + if (cUnit->instructionSet == kX86) { + // If x86, location differs depending on whether memory/reg operation. + nativeRegId = (EncodingMap[thisLIR->opcode].flags & IS_STORE) ? thisLIR->operands[2] + : thisLIR->operands[0]; + } else { + nativeRegId = thisLIR->operands[0]; + } bool isThisLIRLoad = EncodingMap[thisLIR->opcode].flags & IS_LOAD; LIR* checkLIR; /* Use the mem mask to determine the rough memory location */ @@ -107,19 +110,19 @@ void applyLoadStoreElimination(CompilationUnit* cUnit, LIR* headLIR, */ if (!(thisMemMask & (ENCODE_LITERAL | ENCODE_DALVIK_REG))) continue; -#if defined(TARGET_X86) - u8 stopUseRegMask = (IS_BRANCH | thisLIR->useMask) & ~ENCODE_MEM; -#else - /* - * Add r15 (pc) to the resource mask to prevent this instruction - * from sinking past branch instructions. Also take out the memory - * region bits since stopMask is used to check data/control - * dependencies. - */ - u8 stopUseRegMask = (ENCODE_REG_PC | thisLIR->useMask) & - ~ENCODE_MEM; -#endif u8 stopDefRegMask = thisLIR->defMask & ~ENCODE_MEM; + u8 stopUseRegMask; + if (cUnit->instructionSet == kX86) { + stopUseRegMask = (IS_BRANCH | thisLIR->useMask) & ~ENCODE_MEM; + } else { + /* + * Add pc to the resource mask to prevent this instruction + * from sinking past branch instructions. Also take out the memory + * region bits since stopMask is used to check data/control + * dependencies. + */ + stopUseRegMask = (ENCODE_REG_PC | thisLIR->useMask) & ~ENCODE_MEM; + } for (checkLIR = NEXT_LIR(thisLIR); checkLIR != tailLIR; @@ -226,15 +229,15 @@ void applyLoadStoreElimination(CompilationUnit* cUnit, LIR* headLIR, } if (stopHere == true) { -#if defined(TARGET_X86) - // Prevent stores from being sunk between ops that generate ccodes and - // ops that use them. - int flags = EncodingMap[checkLIR->opcode].flags; - if (sinkDistance > 0 && (flags & IS_BRANCH) && (flags & USES_CCODES)) { - checkLIR = PREV_LIR(checkLIR); - sinkDistance--; + if (cUnit->instructionSet == kX86) { + // Prevent stores from being sunk between ops that generate ccodes and + // ops that use them. + int flags = EncodingMap[checkLIR->opcode].flags; + if (sinkDistance > 0 && (flags & IS_BRANCH) && (flags & USES_CCODES)) { + checkLIR = PREV_LIR(checkLIR); + sinkDistance--; + } } -#endif DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR, "REG CLOBBERED")); /* Only sink store instructions */ if (sinkDistance && !isThisLIRLoad) { @@ -287,17 +290,17 @@ void applyLoadHoisting(CompilationUnit* cUnit, LIR* headLIR, LIR* tailLIR) u8 stopUseAllMask = thisLIR->useMask; -#if !defined(TARGET_X86) - /* - * Branches for null/range checks are marked with the true resource - * bits, and loads to Dalvik registers, constant pools, and non-alias - * locations are safe to be hoisted. So only mark the heap references - * conservatively here. - */ - if (stopUseAllMask & ENCODE_HEAP_REF) { - stopUseAllMask |= ENCODE_REG_PC; + if (cUnit->instructionSet != kX86) { + /* + * Branches for null/range checks are marked with the true resource + * bits, and loads to Dalvik registers, constant pools, and non-alias + * locations are safe to be hoisted. So only mark the heap references + * conservatively here. + */ + if (stopUseAllMask & ENCODE_HEAP_REF) { + stopUseAllMask |= ENCODE_REG_PC; + } } -#endif /* Similar as above, but just check for pure register dependency */ u8 stopUseRegMask = stopUseAllMask & ~ENCODE_MEM; diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc index 79208833f1..f3ebf09ab1 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -1722,23 +1722,22 @@ void convertExtendedMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, } break; -#if defined(TARGET_ARM) + // TODO: need GBC intrinsic to take advantage of fused operations case kMirOpFusedCmplFloat: - UNIMPLEMENTED(WARNING) << "unimp kMirOpFusedCmpFloat"; + UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpFloat unsupported"; break; case kMirOpFusedCmpgFloat: - UNIMPLEMENTED(WARNING) << "unimp kMirOpFusedCmgFloat"; + UNIMPLEMENTED(FATAL) << "kMirOpFusedCmgFloat unsupported"; break; case kMirOpFusedCmplDouble: - UNIMPLEMENTED(WARNING) << "unimp kMirOpFusedCmplDouble"; + UNIMPLEMENTED(FATAL) << "kMirOpFusedCmplDouble unsupported"; break; case kMirOpFusedCmpgDouble: - UNIMPLEMENTED(WARNING) << "unimp kMirOpFusedCmpgDouble"; + UNIMPLEMENTED(FATAL) << "kMirOpFusedCmpgDouble unsupported"; break; case kMirOpFusedCmpLong: - UNIMPLEMENTED(WARNING) << "unimp kMirOpLongCmpBranch"; + UNIMPLEMENTED(FATAL) << "kMirOpLongCmpBranch unsupported"; break; -#endif default: break; } @@ -1863,12 +1862,6 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) Instruction::Format dalvikFormat = Instruction::FormatOf(mir->dalvikInsn.opcode); - /* If we're compiling for the debugger, generate an update callout */ - if (cUnit->genDebugger) { - UNIMPLEMENTED(FATAL) << "Need debug codegen"; - //genDebuggerUpdate(cUnit, mir->offset); - } - if (opcode == kMirOpCheck) { // Combine check and work halves of throwing instruction. MIR* workHalf = mir->meta.throwInsn; @@ -2521,13 +2514,10 @@ void cvtICmpBr(CompilationUnit* cUnit, llvm::Instruction* inst, RegLocation rlSrc1 = getLoc(cUnit, inst->getOperand(0)); rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); llvm::Value* rhs = inst->getOperand(1); -#if defined(TARGET_MIPS) - // Compare and branch in one shot - (void)taken; - (void)cond; - (void)rhs; - UNIMPLEMENTED(FATAL); -#else + if (cUnit->instructionSet == kMips) { + // Compare and branch in one shot + UNIMPLEMENTED(FATAL); + } //Compare, then branch // TODO: handle fused CMP_LONG/IF_xxZ case if (llvm::ConstantInt* src2 = llvm::dyn_cast<llvm::ConstantInt>(rhs)) { @@ -2540,7 +2530,6 @@ void cvtICmpBr(CompilationUnit* cUnit, llvm::Instruction* inst, opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); } opCondBranch(cUnit, cond, taken); -#endif // Fallthrough opUnconditionalBranch(cUnit, fallThrough); } diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc index 3321c33cf6..8fd6045a8d 100644 --- a/src/compiler/codegen/MethodCodegenDriver.cc +++ b/src/compiler/codegen/MethodCodegenDriver.cc @@ -18,9 +18,6 @@ namespace art { -#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \ - (1 << kDebugDisplayMissingTargets)) - const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, INVALID_REG, INVALID_REG, INVALID_SREG, INVALID_SREG}; @@ -124,40 +121,40 @@ void genInvoke(CompilationUnit* cUnit, CallInfo* info) vtableIdx, directCode, directMethod, originalType); } - if (DISPLAY_MISSING_TARGETS) { + if (cUnit->enableDebug & (1 << kDebugDisplayMissingTargets)) { genShowTarget(cUnit); } LIR* callInst; -#if !defined(TARGET_X86) - callInst = opReg(cUnit, kOpBlx, rINVOKE_TGT); -#else - if (fastPath && info->type != kInterface) { - callInst = opMem(cUnit, kOpBlx, rARG0, AbstractMethod::GetCodeOffset().Int32Value()); + if (cUnit->instructionSet != kX86) { + callInst = opReg(cUnit, kOpBlx, rINVOKE_TGT); } else { - int trampoline = 0; - switch (info->type) { - case kInterface: - trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline) - : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck); - break; - case kDirect: - trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck); - break; - case kStatic: - trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck); - break; - case kSuper: - trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck); - break; - case kVirtual: - trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck); - break; - default: - LOG(FATAL) << "Unexpected invoke type"; + if (fastPath && info->type != kInterface) { + callInst = opMem(cUnit, kOpBlx, rARG0, AbstractMethod::GetCodeOffset().Int32Value()); + } else { + int trampoline = 0; + switch (info->type) { + case kInterface: + trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline) + : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck); + break; + case kDirect: + trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck); + break; + case kStatic: + trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck); + break; + case kSuper: + trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck); + break; + case kVirtual: + trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck); + break; + default: + LOG(FATAL) << "Unexpected invoke type"; + } + callInst = opThreadMem(cUnit, kOpBlx, trampoline); } - callInst = opThreadMem(cUnit, kOpBlx, trampoline); } -#endif markSafepointPC(cUnit, callInst); oatClobberCalleeSave(cUnit); @@ -923,11 +920,6 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) headLIR->defMask = ENCODE_ALL; } - /* If we're compiling for the debugger, generate an update callout */ - if (cUnit->genDebugger) { - genDebuggerUpdate(cUnit, mir->offset); - } - /* Don't generate the SSA annotation unless verbose mode is on */ if (cUnit->printMe && mir->ssaRep) { char* ssaString = oatGetSSAString(cUnit, mir->ssaRep); diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h index db8fc7dd47..55e62b1a73 100644 --- a/src/compiler/codegen/Ralloc.h +++ b/src/compiler/codegen/Ralloc.h @@ -202,10 +202,7 @@ extern void oatRecordCorePromotion(CompilationUnit* cUnit, int reg, int sReg); extern void oatRecordFpPromotion(CompilationUnit* cUnit, int reg, int sReg); -/* - * Architecture-dependent register allocation routines implemented in - * ${TARGET_ARCH}/${TARGET_ARCH_VARIANT}/Ralloc.c - */ +/* Architecture-dependent register allocation routines. */ extern int oatAllocTypedTempPair(CompilationUnit* cUnit, bool fpHint, int regClass); diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc index 8fa110a90d..4848a59fc6 100644 --- a/src/compiler/codegen/RallocUtil.cc +++ b/src/compiler/codegen/RallocUtil.cc @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains register alloction support and is intended to be - * included by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains register alloction support. */ #include "../CompilerUtility.h" #include "../CompilerIR.h" diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc index ba49277a3f..f85bd2fff5 100644 --- a/src/compiler/codegen/arm/ArchFactory.cc +++ b/src/compiler/codegen/arm/ArchFactory.cc @@ -14,20 +14,12 @@ * limitations under the License. */ -/* - * This file contains arm-specific codegen factory support. - * It is included by - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains arm-specific codegen factory support. */ #include "oat/runtime/oat_support_entrypoints.h" namespace art { -void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset); - bool genNegLong(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc) { @@ -104,13 +96,6 @@ void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, flushIns(cUnit, argLocs, rlMethod); - 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); @@ -128,10 +113,6 @@ void genExitSequence(CompilationUnit* cUnit) 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) { @@ -207,4 +188,40 @@ bool oatArchInit() return oatArchVariantInit(); } + +bool genAddLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genAddLong for Arm"; + return false; +} + +bool genSubLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genSubLong for Arm"; + return false; +} + +bool genAndLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genAndLong for Arm"; + return false; +} + +bool genOrLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genOrLong for Arm"; + return false; +} + +bool genXorLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genXoLong for Arm"; + return false; +} + } // namespace art diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc index cdb8486f50..820f64e643 100644 --- a/src/compiler/codegen/arm/ArchUtility.cc +++ b/src/compiler/codegen/arm/ArchUtility.cc @@ -22,6 +22,74 @@ namespace art { +void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir) +{ + DCHECK_EQ(cUnit->instructionSet, kThumb2); + + // Thumb2 specific setup + int flags = EncodingMap[lir->opcode].flags; + int opcode = lir->opcode; + + if (flags & REG_DEF_LIST0) { + lir->defMask |= ENCODE_REG_LIST(lir->operands[0]); + } + + if (flags & REG_DEF_LIST1) { + lir->defMask |= ENCODE_REG_LIST(lir->operands[1]); + } + + if (flags & REG_DEF_FPCS_LIST0) { + lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]); + } + + if (flags & REG_DEF_FPCS_LIST2) { + for (int i = 0; i < lir->operands[2]; i++) { + oatSetupRegMask(cUnit, &lir->defMask, lir->operands[1] + i); + } + } + + if (flags & REG_USE_PC) { + lir->useMask |= ENCODE_REG_PC; + } + + /* Conservatively treat the IT block */ + if (flags & IS_IT) { + lir->defMask = ENCODE_ALL; + } + + if (flags & REG_USE_LIST0) { + lir->useMask |= ENCODE_REG_LIST(lir->operands[0]); + } + + if (flags & REG_USE_LIST1) { + lir->useMask |= ENCODE_REG_LIST(lir->operands[1]); + } + + if (flags & REG_USE_FPCS_LIST0) { + lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]); + } + + if (flags & REG_USE_FPCS_LIST2) { + for (int i = 0; i < lir->operands[2]; i++) { + oatSetupRegMask(cUnit, &lir->useMask, lir->operands[1] + i); + } + } + /* Fixup for kThumbPush/lr and kThumbPop/pc */ + if (opcode == kThumbPush || opcode == kThumbPop) { + u8 r8Mask = oatGetRegMaskCommon(cUnit, r8); + if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) { + lir->useMask &= ~r8Mask; + lir->useMask |= ENCODE_REG_LR; + } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) { + lir->defMask &= ~r8Mask; + lir->defMask |= ENCODE_REG_PC; + } + } + if (flags & REG_DEF_LR) { + lir->defMask |= ENCODE_REG_LR; + } +} + ArmConditionCode oatArmConditionEncoding(ConditionCode code) { ArmConditionCode res; diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h index 1da567e177..407ad793c0 100644 --- a/src/compiler/codegen/arm/ArmLIR.h +++ b/src/compiler/codegen/arm/ArmLIR.h @@ -258,6 +258,7 @@ enum NativeRegisterPool { #define rRET0 r0 #define rRET1 r1 #define rINVOKE_TGT rLR +#define rCOUNT INVALID_REG /* Shift encodings */ enum ArmShiftEncodings { @@ -267,26 +268,6 @@ enum ArmShiftEncodings { 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 */ -}; - #define isPseudoOpcode(opcode) ((int)(opcode) < 0) /* @@ -295,26 +276,9 @@ enum ArmConditionCode { * Assemble.cc. */ enum ArmOpcode { - kPseudoExportedPC = -18, - kPseudoSafepointPC = -17, - 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] */ + kArmFirst = 0, + kArm16BitData = kArmFirst, /* 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] */ diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc index ede3f6152c..759ffd3bd2 100644 --- a/src/compiler/codegen/arm/Assemble.cc +++ b/src/compiler/codegen/arm/Assemble.cc @@ -1070,7 +1070,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, // Change the load to be relative to the new Adr base lir->operands[1] = baseReg; lir->operands[2] = 0; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } else { if ((lir->opcode == kThumb2Vldrs) || @@ -1101,7 +1101,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, /* operand[0] is src1 in both cb[n]z & CmpRI8 */ lir->operands[1] = 0; lir->target = 0; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } else { lir->operands[1] = delta >> 1; @@ -1126,7 +1126,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, } } lir->operands[0] = reg; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } } else if (lir->opcode == kThumbBCond || lir->opcode == kThumb2BCond) { @@ -1138,7 +1138,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, delta = target - pc; if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) { lir->opcode = kThumb2BCond; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } lir->operands[0] = delta >> 1; @@ -1162,7 +1162,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, // Convert to Thumb2BCond w/ kArmCondAl lir->opcode = kThumb2BUncond; lir->operands[0] = 0; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } else { lir->operands[0] = delta >> 1; @@ -1221,7 +1221,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, lir->opcode = kThumb2AddRRR; lir->operands[1] = rPC; lir->operands[2] = lir->operands[0]; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } } else if (lir->opcode == kThumb2MovImm16LST) { diff --git a/src/compiler/codegen/arm/Codegen.h b/src/compiler/codegen/arm/Codegen.h index 22f6157228..0890c15bab 100644 --- a/src/compiler/codegen/arm/Codegen.h +++ b/src/compiler/codegen/arm/Codegen.h @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains register alloction support and is intended to be - * included by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains register alloction support. */ #include "../../CompilerIR.h" @@ -91,8 +85,19 @@ inline s4 s4FromSwitchData(const void* switchData) { #endif -extern void oatSetupResourceMasks(LIR* lir); +extern void oatSetupResourceMasks(CompilationUnit* cUnit, LIR* lir); extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc); +bool genAddLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genSubLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genAndLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genOrLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genXorLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); + } // namespace art diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc index c6cb220107..c373e35286 100644 --- a/src/compiler/codegen/arm/Thumb2/Factory.cc +++ b/src/compiler/codegen/arm/Thumb2/Factory.cc @@ -16,13 +16,7 @@ namespace art { -/* - * This file contains codegen for the Thumb ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the Thumb ISA. */ static int coreRegs[] = {r0, r1, r2, r3, rSUSPEND, r5, r6, r7, r8, rSELF, r10, r11, r12, rSP, rLR, rPC}; @@ -1035,6 +1029,41 @@ LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc) return res; } +LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset) +{ + LOG(FATAL) << "Unexpected use of opThreadMem for Arm"; + return NULL; +} + +LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp) +{ + LOG(FATAL) << "Unexpected use of opMem for Arm"; + return NULL; +} +LIR* storeBaseIndexedDisp(CompilationUnit *cUnit, + int rBase, int rIndex, int scale, int displacement, + int rSrc, int rSrcHi, + OpSize size, int sReg) +{ + LOG(FATAL) << "Unexpected use of storeBaseIndexedDisp for Arm"; + return NULL; +} + +LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase, + int offset) +{ + LOG(FATAL) << "Unexpected use of opRegMem for Arm"; + return NULL; +} + +LIR* loadBaseIndexedDisp(CompilationUnit *cUnit, + int rBase, int rIndex, int scale, int displacement, + int rDest, int rDestHi, + OpSize size, int sReg) +{ + LOG(FATAL) << "Unexpected use of loadBaseIndexedDisp for Arm"; + return NULL; +} } // namespace art diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index 3584a52e36..cbe6b14b0e 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains codegen for the Thumb2 ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the Thumb2 ISA. */ #include "oat_compilation_unit.h" #include "oat/runtime/oat_support_entrypoints.h" @@ -308,6 +302,13 @@ void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, } } +LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, + int src2, LIR* target) +{ + opRegReg(cUnit, kOpCmp, src1, src2); + return opCondBranch(cUnit, cond, target); +} + /* * Generate a Thumb2 IT instruction, which can nullify up to * four subsequent instructions based on a condition and its @@ -730,7 +731,7 @@ LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg, LIR* opRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc) { LIR* res; - ArmOpcode opcode; + int opcode; if (FPREG(rDest) || FPREG(rSrc)) return fpRegCopy(cUnit, rDest, rSrc); if (LOWREG(rDest) && LOWREG(rSrc)) @@ -863,4 +864,200 @@ bool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, return true; } +/* + * Mark garbage collection card. Skip if the value we're storing is null. + */ +void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) +{ + int regCardBase = oatAllocTemp(cUnit); + int regCardNo = oatAllocTemp(cUnit); + LIR* branchOver = opCmpImmBranch(cUnit, kCondEq, valReg, 0, NULL); + loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(), regCardBase); + opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, CardTable::kCardShift); + storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0, + kUnsignedByte); + LIR* target = newLIR0(cUnit, kPseudoTargetLabel); + branchOver->target = (LIR*)target; + oatFreeTemp(cUnit, regCardBase); + oatFreeTemp(cUnit, regCardNo); +} + +LIR* genRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode, + int reg1, int base, int offset, ThrowKind kind) +{ + LOG(FATAL) << "Unexpected use of genRegMemCheck for Arm"; + return NULL; +} + +RegLocation genDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int lit, bool isDiv) +{ + LOG(FATAL) << "Unexpected use of genDivRemLit for Arm"; + return rlDest; +} + +RegLocation genDivRem(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int reg2, bool isDiv) +{ + LOG(FATAL) << "Unexpected use of genDivRem for Arm"; + return rlDest; +} + +bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin) +{ + DCHECK_EQ(cUnit->instructionSet, kThumb2); + RegLocation rlSrc1 = info->args[0]; + RegLocation rlSrc2 = info->args[1]; + rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); + rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); + RegLocation rlDest = inlineTarget(cUnit, info); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); + opIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E"); + opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg); + opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg); + genBarrier(cUnit); + storeValue(cUnit, rlDest, rlResult); + return true; +} + +void opLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset) +{ + LOG(FATAL) << "Unexpected use of opLea for Arm"; +} + +void opTlsCmp(CompilationUnit* cUnit, int offset, int val) +{ + LOG(FATAL) << "Unexpected use of opTlsCmp for Arm"; +} + +bool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) { + DCHECK_EQ(cUnit->instructionSet, kThumb2); + // Unused - RegLocation rlSrcUnsafe = info->args[0]; + RegLocation rlSrcObj= info->args[1]; // Object - known non-null + RegLocation rlSrcOffset= info->args[2]; // long low + rlSrcOffset.wide = 0; // ignore high half in info->args[3] + RegLocation rlSrcExpected= info->args[4]; // int or Object + RegLocation rlSrcNewValue= info->args[5]; // int or Object + RegLocation rlDest = inlineTarget(cUnit, info); // boolean place for result + + + // Release store semantics, get the barrier out of the way. + oatGenMemBarrier(cUnit, kSY); + + RegLocation rlObject = loadValue(cUnit, rlSrcObj, kCoreReg); + RegLocation rlNewValue = loadValue(cUnit, rlSrcNewValue, kCoreReg); + + if (need_write_barrier) { + // Mark card for object assuming new value is stored. + markGCCard(cUnit, rlNewValue.lowReg, rlObject.lowReg); + } + + RegLocation rlOffset = loadValue(cUnit, rlSrcOffset, kCoreReg); + + int rPtr = oatAllocTemp(cUnit); + opRegRegReg(cUnit, kOpAdd, rPtr, rlObject.lowReg, rlOffset.lowReg); + + // Free now unneeded rlObject and rlOffset to give more temps. + oatClobberSReg(cUnit, rlObject.sRegLow); + oatFreeTemp(cUnit, rlObject.lowReg); + oatClobberSReg(cUnit, rlOffset.sRegLow); + oatFreeTemp(cUnit, rlOffset.lowReg); + + int rOldValue = oatAllocTemp(cUnit); + newLIR3(cUnit, kThumb2Ldrex, rOldValue, rPtr, 0); // rOldValue := [rPtr] + + RegLocation rlExpected = loadValue(cUnit, rlSrcExpected, kCoreReg); + + // if (rOldValue == rExpected) { + // [rPtr] <- rNewValue && rResult := success ? 0 : 1 + // rResult ^= 1 + // } else { + // rResult := 0 + // } + opRegReg(cUnit, kOpCmp, rOldValue, rlExpected.lowReg); + oatFreeTemp(cUnit, rOldValue); // Now unneeded. + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + opIT(cUnit, kArmCondEq, "TE"); + newLIR4(cUnit, kThumb2Strex, rlResult.lowReg, rlNewValue.lowReg, rPtr, 0); + oatFreeTemp(cUnit, rPtr); // Now unneeded. + opRegImm(cUnit, kOpXor, rlResult.lowReg, 1); + opRegReg(cUnit, kOpXor, rlResult.lowReg, rlResult.lowReg); + + storeValue(cUnit, rlDest, rlResult); + + return true; +} + +bool genInlinedSqrt(CompilationUnit* cUnit, CallInfo* info) { + DCHECK_EQ(cUnit->instructionSet, kThumb2); + LIR *branch; + RegLocation rlSrc = info->args[0]; + RegLocation rlDest = inlineTargetWide(cUnit, info); // double place for result + rlSrc = loadValueWide(cUnit, rlSrc, kFPReg); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true); + newLIR2(cUnit, kThumb2Vsqrtd, S2D(rlResult.lowReg, rlResult.highReg), + S2D(rlSrc.lowReg, rlSrc.highReg)); + newLIR2(cUnit, kThumb2Vcmpd, S2D(rlResult.lowReg, rlResult.highReg), + S2D(rlResult.lowReg, rlResult.highReg)); + newLIR0(cUnit, kThumb2Fmstat); + branch = newLIR2(cUnit, kThumbBCond, 0, kArmCondEq); + oatClobberCalleeSave(cUnit); + oatLockCallTemps(cUnit); // Using fixed registers + int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pSqrt)); + newLIR3(cUnit, kThumb2Fmrrd, r0, r1, S2D(rlSrc.lowReg, rlSrc.highReg)); + newLIR1(cUnit, kThumbBlxR, rTgt); + newLIR3(cUnit, kThumb2Fmdrr, S2D(rlResult.lowReg, rlResult.highReg), r0, r1); + branch->target = newLIR0(cUnit, kPseudoTargetLabel); + storeValueWide(cUnit, rlDest, rlResult); + return true; +} + +LIR* opPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target) +{ + return rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target); +} + +LIR* opVldm(CompilationUnit* cUnit, int rBase, int count) +{ + return newLIR3(cUnit, kThumb2Vldms, rBase, fr0, count); +} + +LIR* opVstm(CompilationUnit* cUnit, int rBase, int count) +{ + return newLIR3(cUnit, kThumb2Vstms, rBase, fr0, count); +} + +void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc, + RegLocation rlResult, int lit, + int firstBit, int secondBit) +{ + opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg, + encodeShift(kArmLsl, secondBit - firstBit)); + if (firstBit != 0) { + opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit); + } +} + +void genDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi) +{ + int tReg = oatAllocTemp(cUnit); + newLIR4(cUnit, kThumb2OrrRRRs, tReg, regLo, regHi, 0); + oatFreeTemp(cUnit, tReg); + genCheck(cUnit, kCondEq, kThrowDivZero); +} + +// Test suspend flag, return target of taken suspend branch +LIR* opTestSuspend(CompilationUnit* cUnit, LIR* target) +{ + newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1); + return opCondBranch(cUnit, (target == NULL) ? kCondEq : kCondNe, target); +} + +// Decrement register and branch on condition +LIR* opDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target) +{ + // Combine sub & test using sub setflags encoding here + newLIR3(cUnit, kThumb2SubsRRI12, reg, reg, 1); + return opCondBranch(cUnit, cCode, target); +} + } // namespace art diff --git a/src/compiler/codegen/arm/Thumb2/Ralloc.cc b/src/compiler/codegen/arm/Thumb2/Ralloc.cc index 98a110cb2b..894488a073 100644 --- a/src/compiler/codegen/arm/Thumb2/Ralloc.cc +++ b/src/compiler/codegen/arm/Thumb2/Ralloc.cc @@ -16,13 +16,7 @@ namespace art { -/* - * This file contains codegen for the Thumb ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the Thumb ISA. */ /* * Alloc a pair of core registers, or a double. Low reg in low byte, @@ -74,8 +68,7 @@ void oatInitializeRegAlloc(CompilationUnit* cUnit) 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)) { + if (NO_SUSPEND && (reservedRegs[i] == rSUSPEND)) { //To measure cost of suspend check continue; } diff --git a/src/compiler/codegen/arm/armv7-a/Codegen.cc b/src/compiler/codegen/arm/armv7-a/Codegen.cc index ba1e7ab121..c398b8ebfc 100644 --- a/src/compiler/codegen/arm/armv7-a/Codegen.cc +++ b/src/compiler/codegen/arm/armv7-a/Codegen.cc @@ -15,7 +15,6 @@ */ #define _CODEGEN_C #define _ARMV7_A -#define TARGET_ARM #include "../../../Dalvik.h" #include "../../../CompilerInternals.h" diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc index e2d9e91cf2..e5dc98f0be 100644 --- a/src/compiler/codegen/mips/ArchFactory.cc +++ b/src/compiler/codegen/mips/ArchFactory.cc @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains mips-specific codegen factory support. - * It is included by - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains mips-specific codegen factory support. */ #include "oat/runtime/oat_support_entrypoints.h" @@ -97,8 +91,6 @@ bool genNegLong(CompilationUnit* cUnit, RegLocation rlDest, return false; } -void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset); - /* * In the Arm code a it is typical to use the link register * to hold the target address. However, for Mips we must @@ -185,13 +177,6 @@ void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, flushIns(cUnit, argLocs, rlMethod); - if (cUnit->genDebugger) { - // Refresh update debugger callout - loadWordDisp(cUnit, rSELF, - ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode), rSUSPEND); - genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY); - } - oatFreeTemp(cUnit, rARG0); oatFreeTemp(cUnit, rARG1); oatFreeTemp(cUnit, rARG2); @@ -208,10 +193,6 @@ void genExitSequence(CompilationUnit* cUnit) oatLockTemp(cUnit, rRET1); newLIR0(cUnit, kPseudoMethodExit); - /* If we're compiling for the debugger, generate an update callout */ - if (cUnit->genDebugger) { - genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT); - } unSpillCoreRegs(cUnit); opReg(cUnit, kOpBx, r_RA); } @@ -274,4 +255,27 @@ bool oatArchInit() return oatArchVariantInit(); } +bool genAndLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genAndLong for Mips"; + return false; +} + +bool genOrLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genOrLong for Mips"; + return false; +} + +bool genXorLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + LOG(FATAL) << "Unexpected use of genXorLong for Mips"; + return false; +} + + + } // namespace art diff --git a/src/compiler/codegen/mips/ArchUtility.cc b/src/compiler/codegen/mips/ArchUtility.cc index ead9ff5cd8..f837c399ae 100644 --- a/src/compiler/codegen/mips/ArchUtility.cc +++ b/src/compiler/codegen/mips/ArchUtility.cc @@ -22,6 +22,17 @@ namespace art { +void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir) +{ + DCHECK_EQ(cUnit->instructionSet, kMips); + + // Mips-specific resource map setup here. + int flags = EncodingMap[lir->opcode].flags; + if (flags & REG_DEF_LR) { + lir->defMask |= ENCODE_REG_LR; + } +} + /* For dumping instructions */ #define MIPS_REG_COUNT 32 static const char *mipsRegName[MIPS_REG_COUNT] = { diff --git a/src/compiler/codegen/mips/Codegen.h b/src/compiler/codegen/mips/Codegen.h index 106c030b70..03efe03c6a 100644 --- a/src/compiler/codegen/mips/Codegen.h +++ b/src/compiler/codegen/mips/Codegen.h @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains register alloction support and is intended to be - * included by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains register alloction support */ #include "../../CompilerIR.h" @@ -94,8 +88,19 @@ inline s4 s4FromSwitchData(const void* switchData) { #endif -extern void oatSetupResourceMasks(LIR* lir); +extern void oatSetupResourceMasks(CompilationUnit* cUnit, LIR* lir); extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc); +bool genAddLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genSubLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genAndLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genOrLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genXorLong(CompilationUnit* cUnit, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); + } // namespace art diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc index 63c92ebcec..2f0d46024b 100644 --- a/src/compiler/codegen/mips/Mips32/Factory.cc +++ b/src/compiler/codegen/mips/Mips32/Factory.cc @@ -16,13 +16,7 @@ namespace art { -/* - * This file contains codegen for the MIPS32 ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the MIPS32 ISA. */ static int coreRegs[] = {r_ZERO, r_AT, r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2, r_T3, r_T4, r_T5, r_T6, r_T7, @@ -745,4 +739,47 @@ void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg) loadWordDisp(cUnit, base, HIWORD_OFFSET , highReg); } +LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset) +{ + LOG(FATAL) << "Unexpected use of opThreadMem for MIPS"; + return NULL; +} + +LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp) +{ + LOG(FATAL) << "Unexpected use of opMem for MIPS"; + return NULL; +} + +LIR* storeBaseIndexedDisp(CompilationUnit *cUnit, + int rBase, int rIndex, int scale, int displacement, + int rSrc, int rSrcHi, + OpSize size, int sReg) +{ + LOG(FATAL) << "Unexpected use of storeBaseIndexedDisp for MIPS"; + return NULL; +} + +LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase, + int offset) +{ + LOG(FATAL) << "Unexpected use of opRegMem for MIPS"; + return NULL; +} + +LIR* loadBaseIndexedDisp(CompilationUnit *cUnit, + int rBase, int rIndex, int scale, int displacement, + int rDest, int rDestHi, + OpSize size, int sReg) +{ + LOG(FATAL) << "Unexpected use of loadBaseIndexedDisp for MIPS"; + return NULL; +} + +LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target) +{ + LOG(FATAL) << "Unexpected use of opCondBranch for MIPS"; + return NULL; +} + } // namespace art diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc index b0cad0f750..22c8b84e5b 100644 --- a/src/compiler/codegen/mips/Mips32/Gen.cc +++ b/src/compiler/codegen/mips/Mips32/Gen.cc @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains codegen for the Mips ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the Mips ISA */ #include "oat/runtime/oat_support_entrypoints.h" @@ -525,4 +519,147 @@ void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch"; } +LIR* genRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode, + int reg1, int base, int offset, ThrowKind kind) +{ + LOG(FATAL) << "Unexpected use of genRegMemCheck for Arm"; + return NULL; +} + +RegLocation genDivRem(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int reg2, bool isDiv) +{ + newLIR4(cUnit, kMipsDiv, r_HI, r_LO, reg1, reg2); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + if (isDiv) { + newLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO); + } else { + newLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI); + } + return rlResult; +} + +RegLocation genDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int lit, bool isDiv) +{ + int tReg = oatAllocTemp(cUnit); + newLIR3(cUnit, kMipsAddiu, tReg, r_ZERO, lit); + newLIR4(cUnit, kMipsDiv, r_HI, r_LO, reg1, tReg); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + if (isDiv) { + newLIR2(cUnit, kMipsMflo, rlResult.lowReg, r_LO); + } else { + newLIR2(cUnit, kMipsMfhi, rlResult.lowReg, r_HI); + } + oatFreeTemp(cUnit, tReg); + return rlResult; +} + +/* + * Mark garbage collection card. Skip if the value we're storing is null. + */ +void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) +{ + int regCardBase = oatAllocTemp(cUnit); + int regCardNo = oatAllocTemp(cUnit); + LIR* branchOver = opCmpImmBranch(cUnit, kCondEq, valReg, 0, NULL); + loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(), regCardBase); + opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, CardTable::kCardShift); + storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0, + kUnsignedByte); + LIR* target = newLIR0(cUnit, kPseudoTargetLabel); + branchOver->target = (LIR*)target; + oatFreeTemp(cUnit, regCardBase); + oatFreeTemp(cUnit, regCardNo); +} + +bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin) +{ + // TODO: need Mips implementation + return false; +} + +void opLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset) +{ + LOG(FATAL) << "Unexpected use of opLea for Arm"; +} + +void opTlsCmp(CompilationUnit* cUnit, int offset, int val) +{ + LOG(FATAL) << "Unexpected use of opTlsCmp for Arm"; +} + +bool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) { + DCHECK_NE(cUnit->instructionSet, kThumb2); + return false; +} + +bool genInlinedSqrt(CompilationUnit* cUnit, CallInfo* info) { + DCHECK_NE(cUnit->instructionSet, kThumb2); + return false; +} + +LIR* opPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target) { + LOG(FATAL) << "Unexpected use of opPcRelLoad for Mips"; + return NULL; +} + +LIR* opVldm(CompilationUnit* cUnit, int rBase, int count) +{ + LOG(FATAL) << "Unexpected use of opVldm for Mips"; + return NULL; +} + +LIR* opVstm(CompilationUnit* cUnit, int rBase, int count) +{ + LOG(FATAL) << "Unexpected use of opVstm for Mips"; + return NULL; +} + +void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc, + RegLocation rlResult, int lit, + int firstBit, int secondBit) +{ + int tReg = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, secondBit - firstBit); + opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, tReg); + oatFreeTemp(cUnit, tReg); + if (firstBit != 0) { + opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit); + } +} + +void genDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi) +{ + int tReg = oatAllocTemp(cUnit); + opRegRegReg(cUnit, kOpOr, tReg, regLo, regHi); + genImmedCheck(cUnit, kCondEq, tReg, 0, kThrowDivZero); + oatFreeTemp(cUnit, tReg); +} + +// Test suspend flag, return target of taken suspend branch +LIR* opTestSuspend(CompilationUnit* cUnit, LIR* target) +{ + opRegImm(cUnit, kOpSub, rSUSPEND, 1); + return opCmpImmBranch(cUnit, (target == NULL) ? kCondEq : kCondNe, rSUSPEND, 0, target); +} + +// Decrement register and branch on condition +LIR* opDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target) +{ + opRegImm(cUnit, kOpSub, reg, 1); + return opCmpImmBranch(cUnit, cCode, reg, 0, target); +} + +bool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, + RegLocation rlSrc, RegLocation rlDest, int lit) +{ + LOG(FATAL) << "Unexpected use of smallLiteralDive in Mips"; + return false; +} + +LIR* opIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide) +{ + LOG(FATAL) << "Unexpected use of opIT in Mips"; + return NULL; +} + } // namespace art diff --git a/src/compiler/codegen/mips/Mips32/Ralloc.cc b/src/compiler/codegen/mips/Mips32/Ralloc.cc index 9f392124ee..e7ad60c838 100644 --- a/src/compiler/codegen/mips/Mips32/Ralloc.cc +++ b/src/compiler/codegen/mips/Mips32/Ralloc.cc @@ -16,13 +16,7 @@ namespace art { -/* - * This file contains codegen for the Mips ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the Mips ISA */ /* * Alloc a pair of core registers, or a double. Low reg in low byte, @@ -88,8 +82,7 @@ void oatInitializeRegAlloc(CompilationUnit* cUnit) 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)) { + if (NO_SUSPEND && (reservedRegs[i] == rSUSPEND)) { //To measure cost of suspend check continue; } diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h index 4b7da557b3..a175706d2b 100644 --- a/src/compiler/codegen/mips/MipsLIR.h +++ b/src/compiler/codegen/mips/MipsLIR.h @@ -146,6 +146,9 @@ namespace art { #define r_FRESULT0 r_F0 #define r_FRESULT1 r_F1 +/* Regs not used for Mips */ +#define rLR INVALID_REG + /* RegisterLocation templates return values (r_V0, or r_V0/r_V1) */ #define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, r_V0, INVALID_REG, \ INVALID_SREG, INVALID_SREG} @@ -308,6 +311,7 @@ enum NativeRegisterPool { #define rRET0 r_RESULT0 #define rRET1 r_RESULT1 #define rINVOKE_TGT r_T9 +#define rCOUNT INVALID_REG /* Shift encodings */ enum MipsShiftEncodings { @@ -337,26 +341,7 @@ enum MipsShiftEncodings { * Assemble.cc. */ enum MipsOpCode { - kPseudoExportedPC = -18, - kPseudoSafepointPC = -17, - 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, - - kMipsFirst, + kMipsFirst = 0, kMips32BitData = kMipsFirst, /* data [31..0] */ kMipsAddiu, /* addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] */ kMipsAddu, /* add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001] */ diff --git a/src/compiler/codegen/mips/mips/Codegen.cc b/src/compiler/codegen/mips/mips/Codegen.cc index 60a76460e6..0c726d349a 100644 --- a/src/compiler/codegen/mips/mips/Codegen.cc +++ b/src/compiler/codegen/mips/mips/Codegen.cc @@ -15,7 +15,6 @@ */ #define _CODEGEN_C -#define TARGET_MIPS #include "../../../Dalvik.h" #include "../../../CompilerInternals.h" diff --git a/src/compiler/codegen/x86/ArchFactory.cc b/src/compiler/codegen/x86/ArchFactory.cc index 001a93d199..1fc10340bd 100644 --- a/src/compiler/codegen/x86/ArchFactory.cc +++ b/src/compiler/codegen/x86/ArchFactory.cc @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains x86-specific codegen factory support. - * It is included by - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains x86-specific codegen factory support. */ namespace art { @@ -120,8 +114,6 @@ bool genNegLong(CompilationUnit* cUnit, RegLocation rlDest, return false; } -void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset); - void spillCoreRegs(CompilationUnit* cUnit) { if (cUnit->numCoreSpills == 0) { return; @@ -202,16 +194,6 @@ void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs, flushIns(cUnit, argLocs, rlMethod); - if (cUnit->genDebugger) { - // Refresh update debugger callout - UNIMPLEMENTED(WARNING) << "genDebugger"; -#if 0 - loadWordDisp(cUnit, rSELF, - OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode), rSUSPEND); - genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY); -#endif - } - oatFreeTemp(cUnit, rARG0); oatFreeTemp(cUnit, rARG1); oatFreeTemp(cUnit, rARG2); @@ -226,10 +208,6 @@ void genExitSequence(CompilationUnit* cUnit) { oatLockTemp(cUnit, rRET1); newLIR0(cUnit, kPseudoMethodExit); - /* If we're compiling for the debugger, generate an update callout */ - if (cUnit->genDebugger) { - genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT); - } unSpillCoreRegs(cUnit); /* Remove frame except for return address */ opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize - 4); @@ -292,4 +270,13 @@ bool oatArchInit() { return oatArchVariantInit(); } +// Not used in x86 +int loadHelper(CompilationUnit* cUnit, int offset) +{ + LOG(FATAL) << "Unexpected use of loadHelper in x86"; + return INVALID_REG; +} + + + } // namespace art diff --git a/src/compiler/codegen/x86/ArchUtility.cc b/src/compiler/codegen/x86/ArchUtility.cc index 4e75ef2a70..4c28b35e03 100644 --- a/src/compiler/codegen/x86/ArchUtility.cc +++ b/src/compiler/codegen/x86/ArchUtility.cc @@ -22,6 +22,32 @@ namespace art { +void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir) +{ + DCHECK_EQ(cUnit->instructionSet, kX86); + + // X86-specific resource map setup here. + int flags = EncodingMap[lir->opcode].flags; + if (flags & REG_DEFA) { + oatSetupRegMask(cUnit, &lir->defMask, rAX); + } + + if (flags & REG_DEFD) { + oatSetupRegMask(cUnit, &lir->defMask, rDX); + } + if (flags & REG_USEA) { + oatSetupRegMask(cUnit, &lir->useMask, rAX); + } + + if (flags & REG_USEC) { + oatSetupRegMask(cUnit, &lir->useMask, rCX); + } + + if (flags & REG_USED) { + oatSetupRegMask(cUnit, &lir->useMask, rDX); + } +} + /* For dumping instructions */ static const char* x86RegName[] = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc index 252228344f..c47711cab3 100644 --- a/src/compiler/codegen/x86/Assemble.cc +++ b/src/compiler/codegen/x86/Assemble.cc @@ -1225,7 +1225,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit, intptr_t startAd << " delta: " << delta << " old delta: " << lir->operands[0]; } lir->opcode = kX86Jcc32; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } if (kVerbosePcFixup) { @@ -1278,7 +1278,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit, intptr_t startAd LOG(INFO) << "Retry for JMP growth at " << lir->offset; } lir->opcode = kX86Jmp32; - oatSetupResourceMasks(lir); + oatSetupResourceMasks(cUnit, lir); res = kRetryAll; } lir->operands[0] = delta; diff --git a/src/compiler/codegen/x86/Codegen.h b/src/compiler/codegen/x86/Codegen.h index 568a3888b5..3755e500aa 100644 --- a/src/compiler/codegen/x86/Codegen.h +++ b/src/compiler/codegen/x86/Codegen.h @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains register alloction support and is intended to be - * included by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains register alloction support */ #include "../../CompilerIR.h" @@ -101,7 +95,7 @@ inline s4 s4FromSwitchData(const void* switchData) { #endif -extern void oatSetupResourceMasks(LIR* lir); +extern void oatSetupResourceMasks(CompilationUnit* cUnit, LIR* lir); extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc); diff --git a/src/compiler/codegen/x86/X86/Factory.cc b/src/compiler/codegen/x86/X86/Factory.cc index 291b761d85..3da7672408 100644 --- a/src/compiler/codegen/x86/X86/Factory.cc +++ b/src/compiler/codegen/x86/X86/Factory.cc @@ -16,13 +16,7 @@ namespace art { -/* - * This file contains codegen for the X86 ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the X86 ISA */ //FIXME: restore "static" when usage uncovered /*static*/ int coreRegs[] = { diff --git a/src/compiler/codegen/x86/X86/Gen.cc b/src/compiler/codegen/x86/X86/Gen.cc index 28c691403f..b57acac271 100644 --- a/src/compiler/codegen/x86/X86/Gen.cc +++ b/src/compiler/codegen/x86/X86/Gen.cc @@ -14,13 +14,7 @@ * limitations under the License. */ -/* - * This file contains codegen for the X86 ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the X86 ISA */ namespace art { @@ -418,5 +412,140 @@ void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) { } opCondBranch(cUnit, ccode, taken); } +RegLocation genDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int regLo, int lit, bool isDiv) +{ + LOG(FATAL) << "Unexpected use of genDivRemLit for x86"; + return rlDest; +} + +RegLocation genDivRem(CompilationUnit* cUnit, RegLocation rlDest, int regLo, int regHi, bool isDiv) +{ + LOG(FATAL) << "Unexpected use of genDivRem for x86"; + return rlDest; +} + +/* + * Mark garbage collection card. Skip if the value we're storing is null. + */ +void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) +{ + int regCardBase = oatAllocTemp(cUnit); + int regCardNo = oatAllocTemp(cUnit); + LIR* branchOver = opCmpImmBranch(cUnit, kCondEq, valReg, 0, NULL); + newLIR2(cUnit, kX86Mov32RT, regCardBase, Thread::CardTableOffset().Int32Value()); + opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, CardTable::kCardShift); + storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0, + kUnsignedByte); + LIR* target = newLIR0(cUnit, kPseudoTargetLabel); + branchOver->target = (LIR*)target; + oatFreeTemp(cUnit, regCardBase); + oatFreeTemp(cUnit, regCardNo); +} + +bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin) +{ + DCHECK_EQ(cUnit->instructionSet, kX86); + RegLocation rlSrc1 = info->args[0]; + RegLocation rlSrc2 = info->args[1]; + rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); + rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); + RegLocation rlDest = inlineTarget(cUnit, info); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); + DCHECK_EQ(cUnit->instructionSet, kX86); + LIR* branch = newLIR2(cUnit, kX86Jcc8, 0, isMin ? kX86CondG : kX86CondL); + opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg); + LIR* branch2 = newLIR1(cUnit, kX86Jmp8, 0); + branch->target = newLIR0(cUnit, kPseudoTargetLabel); + opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg); + branch2->target = newLIR0(cUnit, kPseudoTargetLabel); + storeValue(cUnit, rlDest, rlResult); + return true; +} + +void opLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset) +{ + newLIR5(cUnit, kX86Lea32RA, rBase, reg1, reg2, scale, offset); +} + +void opTlsCmp(CompilationUnit* cUnit, int offset, int val) +{ + newLIR2(cUnit, kX86Cmp16TI8, offset, val); +} + +bool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) { + DCHECK_NE(cUnit->instructionSet, kThumb2); + return false; +} + +bool genInlinedSqrt(CompilationUnit* cUnit, CallInfo* info) { + DCHECK_NE(cUnit->instructionSet, kThumb2); + return false; +} + +LIR* opPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target) { + LOG(FATAL) << "Unexpected use of opPcRelLoad for x86"; + return NULL; +} + +LIR* opVldm(CompilationUnit* cUnit, int rBase, int count) +{ + LOG(FATAL) << "Unexpected use of opVldm for x86"; + return NULL; +} + +LIR* opVstm(CompilationUnit* cUnit, int rBase, int count) +{ + LOG(FATAL) << "Unexpected use of opVstm for x86"; + return NULL; +} + +void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc, + RegLocation rlResult, int lit, + int firstBit, int secondBit) +{ + int tReg = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, secondBit - firstBit); + opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, tReg); + oatFreeTemp(cUnit, tReg); + if (firstBit != 0) { + opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit); + } +} + +void genDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi) +{ + int tReg = oatAllocTemp(cUnit); + opRegRegReg(cUnit, kOpOr, tReg, regLo, regHi); + genImmedCheck(cUnit, kCondEq, tReg, 0, kThrowDivZero); + oatFreeTemp(cUnit, tReg); +} + +// Test suspend flag, return target of taken suspend branch +LIR* opTestSuspend(CompilationUnit* cUnit, LIR* target) +{ + opTlsCmp(cUnit, Thread::ThreadFlagsOffset().Int32Value(), 0); + return opCondBranch(cUnit, (target == NULL) ? kCondNe : kCondEq, target); +} + +// Decrement register and branch on condition +LIR* opDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target) +{ + opRegImm(cUnit, kOpSub, reg, 1); + return opCmpImmBranch(cUnit, cCode, reg, 0, target); +} + +bool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, + RegLocation rlSrc, RegLocation rlDest, int lit) +{ + LOG(FATAL) << "Unexpected use of smallLiteralDive in x86"; + return false; +} + +LIR* opIT(CompilationUnit* cUnit, ArmConditionCode cond, const char* guide) +{ + LOG(FATAL) << "Unexpected use of opIT in x86"; + return NULL; +} } // namespace art diff --git a/src/compiler/codegen/x86/X86/Ralloc.cc b/src/compiler/codegen/x86/X86/Ralloc.cc index 2886b8f057..ef72e52515 100644 --- a/src/compiler/codegen/x86/X86/Ralloc.cc +++ b/src/compiler/codegen/x86/X86/Ralloc.cc @@ -16,13 +16,7 @@ namespace art { -/* - * This file contains codegen for the X86 ISA and is intended to be - * includes by: - * - * Codegen-$(TARGET_ARCH_VARIANT).c - * - */ +/* This file contains codegen for the X86 ISA */ /* * Alloc a pair of core registers, or a double. Low reg in low byte, diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h index 8ad014ac85..9a5d63058a 100644 --- a/src/compiler/codegen/x86/X86LIR.h +++ b/src/compiler/codegen/x86/X86LIR.h @@ -175,6 +175,8 @@ enum ResourceEncodingPos { #define DECODE_ALIAS_INFO_REG(X) (X & 0xffff) #define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0) +/* Not used for x86 */ +#define ENCODE_REG_PC (ENCODE_ALL) /* * Annotate special-purpose core registers: @@ -245,81 +247,20 @@ enum NativeRegisterPool { #define rRET0 rAX #define rRET1 rDX #define rINVOKE_TGT rAX +#define rLR INVALID_REG +#define rSUSPEND INVALID_REG +#define rSELF INVALID_REG +#define rCOUNT rCX #define isPseudoOpcode(opCode) ((int)(opCode) < 0) -/* X86 condition encodings */ -enum X86ConditionCode { - kX86CondO = 0x0, // overflow - kX86CondNo = 0x1, // not overflow - - kX86CondB = 0x2, // below - kX86CondNae = kX86CondB, // not-above-equal - kX86CondC = kX86CondB, // carry - - kX86CondNb = 0x3, // not-below - kX86CondAe = kX86CondNb, // above-equal - kX86CondNc = kX86CondNb, // not-carry - - kX86CondZ = 0x4, // zero - kX86CondEq = kX86CondZ, // equal - - kX86CondNz = 0x5, // not-zero - kX86CondNe = kX86CondNz, // not-equal - - kX86CondBe = 0x6, // below-equal - kX86CondNa = kX86CondBe, // not-above - - kX86CondNbe = 0x7, // not-below-equal - kX86CondA = kX86CondNbe,// above - - kX86CondS = 0x8, // sign - kX86CondNs = 0x9, // not-sign - - kX86CondP = 0xA, // 8-bit parity even - kX86CondPE = kX86CondP, - - kX86CondNp = 0xB, // 8-bit parity odd - kX86CondPo = kX86CondNp, - - kX86CondL = 0xC, // less-than - kX86CondNge = kX86CondL, // not-greater-equal - - kX86CondNl = 0xD, // not-less-than - kX86CondGe = kX86CondNl, // not-greater-equal - - kX86CondLe = 0xE, // less-than-equal - kX86CondNg = kX86CondLe, // not-greater - - kX86CondNle = 0xF, // not-less-than - kX86CondG = kX86CondNle,// greater -}; - /* * The following enum defines the list of supported X86 instructions by the * assembler. Their corresponding EncodingMap positions will be defined in * Assemble.cc. */ enum X86OpCode { - kPseudoExportedPC = -18, - kPseudoSafepointPC = -17, - 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, - kX86First, + kX86First = 0, kX8632BitData = kX86First, /* data [31..0] */ kX86Bkpt, kX86Nop, diff --git a/src/compiler/codegen/x86/x86/Codegen.cc b/src/compiler/codegen/x86/x86/Codegen.cc index 0552ce3416..744a7d2246 100644 --- a/src/compiler/codegen/x86/x86/Codegen.cc +++ b/src/compiler/codegen/x86/x86/Codegen.cc @@ -15,7 +15,6 @@ */ #define _CODEGEN_C -#define TARGET_X86 #include "../../../Dalvik.h" #include "../../../CompilerInternals.h" |