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
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index d08af07..4327fb6 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -128,6 +128,7 @@
#define INVALID_SREG (-1)
#define INVALID_VREG (0xFFFFU)
#define INVALID_REG (0xFF)
+#define INVALID_OFFSET (0xDEADF00FU)
/* SSA encodings for special registers */
#define SSA_METHOD_BASEREG (-2)
@@ -176,6 +177,28 @@
u8 defMask; // Resource mask for def
};
+/* Shared pseudo opcodes - must be < 0 */
+enum LIRPseudoOpcode {
+ 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,
+};
+
enum ExtendedMIROpcode {
kMirOpFirst = kNumPackedOpcodes,
kMirOpPhi = kMirOpFirst,
@@ -326,7 +349,6 @@
totalSize(0),
assemblerStatus(kSuccess),
assemblerRetries(0),
- genDebugger(false),
printMe(false),
hasLoop(false),
hasInvoke(false),
@@ -435,7 +457,6 @@
std::vector<uint32_t> coreVmapTable;
std::vector<uint32_t> fpVmapTable;
std::vector<uint8_t> nativeGcMap;
- bool genDebugger; // Generate code for debugger
bool printMe;
bool hasLoop; // Contains a loop
bool hasInvoke; // Contains an invoke instruction
@@ -643,6 +664,73 @@
kCondNv, // never
};
+// Target specific 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 */
+};
+
+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
+};
+
+
enum ThrowKind {
kThrowNullPointer,
kThrowDivZero,
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index c5d5c21..e05c32f 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -884,19 +884,6 @@
(1 << kMatch) |
(1 << kPromoteCompilerTemps));
}
- /* Are we generating code for the debugger? */
- if (compiler.IsDebuggingSupported()) {
- cUnit->genDebugger = true;
- // Yes, disable most optimizations
- cUnit->disableOpt |= (
- (1 << kLoadStoreElimination) |
- (1 << kLoadHoisting) |
- (1 << kSuppressLoads) |
- (1 << kPromoteRegs) |
- (1 << kBBOpt) |
- (1 << kMatch) |
- (1 << kTrackLiveTemps));
- }
/* Gathering opcode stats? */
if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc
index ce25aad..b0dc30c 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 @@
}
}
-/*
- * 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 cf06c80..7ad2647 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -74,24 +74,22 @@
/*
* 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 @@
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(reg);
+ *mask |= getRegMaskCommon(cUnit, reg);
+}
+
+/* Exported version of setupRegMask */
+void oatSetupRegMask(CompilationUnit* cUnit, u8* mask, int 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 @@
return;
}
- flags = EncodingMap[lir->opcode].flags;
+ flags = EncodingMap[opcode].flags;
if (flags & NEEDS_FIXUP) {
lir->flags.pcRelFixup = true;
@@ -145,135 +154,42 @@
}
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 @@
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 @@
* 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 61ea6b6..d349412 100644
--- a/src/compiler/codegen/CompilerCodegen.h
+++ b/src/compiler/codegen/CompilerCodegen.h
@@ -79,6 +79,42 @@
/* 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 7305271..035617e 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -24,11 +24,8 @@
* 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 @@
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 @@
}
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 @@
}
}
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 @@
}
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 @@
// 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 @@
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* 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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);
+ 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);
}
-#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);
-#endif
storeValueWide(cUnit, rlDest, rlResult);
} else {
rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
@@ -1207,33 +1055,32 @@
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 @@
{
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 @@
}
/* 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 @@
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 @@
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);
+ 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);
}
- 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);
-#endif
oatFreeTemp(cUnit, rIndex);
markGCCard(cUnit, rValue, rArray);
}
@@ -1535,80 +1382,79 @@
/* 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);
-
- 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);
+ 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 {
- opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
- }
- oatFreeTemp(cUnit, rlIndex.lowReg);
- rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+ 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);
+ loadBaseIndexedDisp(cUnit, rlArray.lowReg, rlIndex.lowReg, scale,
+ dataOffset, rlResult.lowReg, INVALID_REG, size,
+ INVALID_SREG);
- oatFreeTemp(cUnit, regPtr);
- storeValueWide(cUnit, rlDest, rlResult);
+ storeValue(cUnit, rlDest, rlResult);
+ }
} else {
- rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
-
+ 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);
}
- loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
- scale, size);
+ /* 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);
- 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);
+ }
+ loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
+
+ 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);
+ }
+ loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg, scale, size);
+
+ oatFreeTemp(cUnit, regPtr);
+ storeValue(cUnit, rlDest, rlResult);
+ }
}
-#endif
}
/*
@@ -1631,85 +1477,82 @@
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 (needsRangeCheck) {
- genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, kThrowArrayBounds);
- oatFreeTemp(cUnit, regLen);
+ // 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);
}
-
- storeBaseDispWide(cUnit, regPtr, 0, rlSrc.lowReg, rlSrc.highReg);
-
- oatFreeTemp(cUnit, regPtr);
} else {
- rlSrc = loadValue(cUnit, rlSrc, regClass);
+ 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);
}
- storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
- scale, size);
+ /* 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);
+
+ 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);
+ }
}
-#endif
}
void genLong3Addr(CompilationUnit* cUnit, OpKind firstOp,
@@ -1717,18 +1560,18 @@
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 @@
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 @@
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 @@
}
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);
+ 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);
}
-#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);
- }
- // 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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 0208a4a..2da6242 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -140,10 +140,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
* 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 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 @@
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 @@
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);
+ 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);
}
- 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 = 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 @@
// 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 @@
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 @@
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 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 @@
} 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 @@
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 @@
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 @@
(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 @@
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 1dca491..c0e6036 100644
--- a/src/compiler/codegen/LocalOptimizations.cc
+++ b/src/compiler/codegen/LocalOptimizations.cc
@@ -91,11 +91,14 @@
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 @@
*/
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 @@
}
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 @@
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 7920883..f3ebf09 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -1722,23 +1722,22 @@
}
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 @@
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 @@
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 @@
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 3321c33..8fd6045 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 @@
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 @@
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 db8fc7d..55e62b1 100644
--- a/src/compiler/codegen/Ralloc.h
+++ b/src/compiler/codegen/Ralloc.h
@@ -202,10 +202,7 @@
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 8fa110a..4848a59 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 ba49277..f85bd2f 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 @@
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 @@
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 @@
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 cdb8486..820f64e 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 1da567e..407ad79 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -258,6 +258,7 @@
#define rRET0 r0
#define rRET1 r1
#define rINVOKE_TGT rLR
+#define rCOUNT INVALID_REG
/* Shift encodings */
enum ArmShiftEncodings {
@@ -267,26 +268,6 @@
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 @@
* 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 ede3f61..759ffd3 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -1070,7 +1070,7 @@
// 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 @@
/* 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 @@
}
}
lir->operands[0] = reg;
- oatSetupResourceMasks(lir);
+ oatSetupResourceMasks(cUnit, lir);
res = kRetryAll;
}
} else if (lir->opcode == kThumbBCond || lir->opcode == kThumb2BCond) {
@@ -1138,7 +1138,7 @@
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 @@
// 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 @@
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 22f6157..0890c15 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 @@
#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 c6cb220..c373e35 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 @@
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 3584a52..cbe6b14 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 @@
}
}
+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* 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 @@
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 98a110c..894488a 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 @@
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 ba1e7ab..c398b8e 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 e2d9e91..e5dc98f 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 @@
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 @@
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 @@
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 @@
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 ead9ff5..f837c39 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 106c030..03efe03 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 @@
#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 63c92eb..2f0d460 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 @@
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 b0cad0f..22c8b84 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 @@
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 9f39212..e7ad60c 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 @@
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 4b7da55..a175706 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -146,6 +146,9 @@
#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 @@
#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 @@
* 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 60a7646..0c726d3 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 001a93d..1fc1034 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 @@
return false;
}
-void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
-
void spillCoreRegs(CompilationUnit* cUnit) {
if (cUnit->numCoreSpills == 0) {
return;
@@ -202,16 +194,6 @@
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 @@
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 @@
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 4e75ef2..4c28b35 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 2522283..c47711c 100644
--- a/src/compiler/codegen/x86/Assemble.cc
+++ b/src/compiler/codegen/x86/Assemble.cc
@@ -1225,7 +1225,7 @@
<< " delta: " << delta << " old delta: " << lir->operands[0];
}
lir->opcode = kX86Jcc32;
- oatSetupResourceMasks(lir);
+ oatSetupResourceMasks(cUnit, lir);
res = kRetryAll;
}
if (kVerbosePcFixup) {
@@ -1278,7 +1278,7 @@
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 568a388..3755e50 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 @@
#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 291b761..3da7672 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 28c6914..b57acac 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 @@
}
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 2886b8f..ef72e52 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 8ad014a..9a5d630 100644
--- a/src/compiler/codegen/x86/X86LIR.h
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -175,6 +175,8 @@
#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 @@
#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 0552ce3..744a7d2 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"