summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/CompilerIR.h17
-rw-r--r--src/compiler/codegen/CodegenUtil.cc209
-rw-r--r--src/compiler/codegen/CompilerCodegen.h3
-rw-r--r--src/compiler/codegen/GenCommon.cc89
-rw-r--r--src/compiler/codegen/MethodCodegenDriver.cc4
-rw-r--r--src/compiler/codegen/arm/ArchUtility.cc175
-rw-r--r--src/compiler/codegen/arm/ArmLIR.h16
-rw-r--r--src/compiler/codegen/arm/ArmRallocUtil.cc16
-rw-r--r--src/compiler/codegen/arm/Codegen.h2
-rw-r--r--src/compiler/codegen/mips/ArchFactory.cc1291
-rw-r--r--src/compiler/codegen/mips/ArchUtility.cc213
-rw-r--r--src/compiler/codegen/mips/Assemble.cc75
-rw-r--r--src/compiler/codegen/mips/Codegen.h68
-rw-r--r--src/compiler/codegen/mips/CodegenCommon.cc319
-rw-r--r--src/compiler/codegen/mips/FP/MipsFP.cc210
-rw-r--r--src/compiler/codegen/mips/Mips32/Factory.cc195
-rw-r--r--src/compiler/codegen/mips/Mips32/Gen.cc800
-rw-r--r--src/compiler/codegen/mips/Mips32/Ralloc.cc72
-rw-r--r--src/compiler/codegen/mips/MipsLIR.h117
-rw-r--r--src/compiler/codegen/mips/MipsRallocUtil.cc58
-rw-r--r--src/compiler/codegen/mips/mips/Codegen.cc13
21 files changed, 848 insertions, 3114 deletions
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index 34ccfb4235..52b12d8bf6 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -445,6 +445,7 @@ typedef enum OpKind {
kOp2Byte,
kOpCondBr,
kOpUncondBr,
+ kOpBx,
kOpInvalid,
} OpKind;
@@ -477,6 +478,22 @@ typedef enum ThrowKind {
kThrowStackOverflow,
} ThrowKind;
+typedef struct SwitchTable {
+ int offset;
+ const u2* table; // Original dex table
+ int vaddr; // Dalvik offset of switch opcode
+ LIR* bxInst; // Switch indirect branch instruction
+ LIR** targets; // Array of case targets
+} SwitchTable;
+
+typedef struct FillArrayData {
+ int offset;
+ const u2* table; // Original dex table
+ int size;
+ int vaddr; // Dalvik offset of OP_FILL_ARRAY_DATA opcode
+} FillArrayData;
+
+
BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
void oatAppendMIR(BasicBlock* bb, MIR* mir);
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index 4eccf04814..96a9b2176f 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -154,6 +154,7 @@ void setupResourceMasks(LIR* lir)
lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
}
+#if defined(TARGET_ARM)
if (flags & REG_DEF_FPCS_LIST0) {
lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
}
@@ -163,6 +164,7 @@ void setupResourceMasks(LIR* lir)
setupRegMask(&lir->defMask, lir->operands[1] + i);
}
}
+#endif
if (flags & SETS_CCODES) {
lir->defMask |= ENCODE_CCODE;
@@ -201,6 +203,7 @@ void setupResourceMasks(LIR* lir)
lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
}
+#if defined(TARGET_ARM)
if (flags & REG_USE_FPCS_LIST0) {
lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
}
@@ -210,6 +213,7 @@ void setupResourceMasks(LIR* lir)
setupRegMask(&lir->useMask, lir->operands[1] + i);
}
}
+#endif
if (flags & USES_CCODES) {
lir->useMask |= ENCODE_CCODE;
@@ -231,10 +235,186 @@ void setupResourceMasks(LIR* lir)
}
/*
+ * Debugging macros
+ */
+#define DUMP_RESOURCE_MASK(X)
+#define DUMP_SSA_REP(X)
+
+/* Pretty-print a LIR instruction */
+void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
+{
+ LIR* lir = (LIR*) arg;
+ int offset = lir->offset;
+ int dest = lir->operands[0];
+ const bool dumpNop = false;
+
+ /* Handle pseudo-ops individually, and all regular insns as a group */
+ switch(lir->opcode) {
+ case kPseudoMethodEntry:
+ LOG(INFO) << "-------- method entry " <<
+ PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ break;
+ case kPseudoMethodExit:
+ LOG(INFO) << "-------- Method_Exit";
+ break;
+ case kPseudoBarrier:
+ LOG(INFO) << "-------- BARRIER";
+ break;
+ case kPseudoExtended:
+ LOG(INFO) << "-------- " << (char* ) dest;
+ break;
+ case kPseudoSSARep:
+ DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
+ break;
+ case kPseudoEntryBlock:
+ LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
+ break;
+ case kPseudoDalvikByteCodeBoundary:
+ LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
+ lir->dalvikOffset << " @ " << (char* )lir->operands[0];
+ break;
+ case kPseudoExitBlock:
+ LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
+ break;
+ case kPseudoPseudoAlign4:
+ LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
+ offset << "): .align4";
+ break;
+ case kPseudoEHBlockLabel:
+ LOG(INFO) << "Exception_Handling:";
+ break;
+ case kPseudoTargetLabel:
+ case kPseudoNormalBlockLabel:
+ LOG(INFO) << "L" << (intptr_t)lir << ":";
+ break;
+ case kPseudoThrowTarget:
+ LOG(INFO) << "LT" << (intptr_t)lir << ":";
+ break;
+ case kPseudoSuspendTarget:
+ LOG(INFO) << "LS" << (intptr_t)lir << ":";
+ break;
+ case kPseudoCaseLabel:
+ LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
+ std::hex << lir->operands[0] << "|" << std::dec <<
+ lir->operands[0];
+ break;
+ default:
+ if (lir->flags.isNop && !dumpNop) {
+ break;
+ } else {
+ std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr));
+ std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr));
+ LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset,
+ op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : "");
+ }
+ break;
+ }
+
+ if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
+ DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
+ lir->useMask, "use"));
+ }
+ if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
+ DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
+ lir->defMask, "def"));
+ }
+}
+
+void oatDumpPromotionMap(CompilationUnit *cUnit)
+{
+ for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
+ PromotionMap vRegMap = cUnit->promotionMap[i];
+ char buf[100];
+ if (vRegMap.fpLocation == kLocPhysReg) {
+ snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK);
+ } else {
+ buf[0] = 0;
+ }
+ char buf2[100];
+ snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
+ vRegMap.coreLocation == kLocPhysReg ?
+ "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
+ vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
+ LOG(INFO) << buf2;
+ }
+}
+
+void oatDumpFullPromotionMap(CompilationUnit *cUnit)
+{
+ for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
+ PromotionMap vRegMap = cUnit->promotionMap[i];
+ LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation <<
+ ", CR:" << (int)vRegMap.coreReg << ", FL:" <<
+ (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg <<
+ ", - " << (int)vRegMap.firstInPair;
+ }
+}
+
+/* Dump instructions and constant pool contents */
+void oatCodegenDump(CompilationUnit* cUnit)
+{
+ LOG(INFO) << "/*";
+ LOG(INFO) << "Dumping LIR insns for "
+ << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ LIR* lirInsn;
+ LIR* thisLIR;
+ int insnsSize = cUnit->insnsSize;
+
+ LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
+ LOG(INFO) << "Ins : " << cUnit->numIns;
+ LOG(INFO) << "Outs : " << cUnit->numOuts;
+ LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
+ LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
+ LOG(INFO) << "Padding : " << cUnit->numPadding;
+ LOG(INFO) << "Frame size : " << cUnit->frameSize;
+ LOG(INFO) << "Start of ins : " << cUnit->insOffset;
+ LOG(INFO) << "Start of regs : " << cUnit->regsOffset;
+ LOG(INFO) << "code size is " << cUnit->totalSize <<
+ " bytes, Dalvik size is " << insnsSize * 2;
+ LOG(INFO) << "expansion factor: " <<
+ (float)cUnit->totalSize / (float)(insnsSize * 2);
+ oatDumpPromotionMap(cUnit);
+ for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
+ oatDumpLIRInsn(cUnit, lirInsn, 0);
+ }
+ for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
+ thisLIR = (LIR*) lirInsn;
+ LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
+ thisLIR->offset, thisLIR->offset,
+ ((CallsiteInfo *) thisLIR->operands[0])->classDescriptor);
+ }
+ for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
+ thisLIR = (LIR*) lirInsn;
+ LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
+ thisLIR->offset, thisLIR->offset, thisLIR->operands[0]);
+ }
+
+ const DexFile::MethodId& method_id =
+ cUnit->dex_file->GetMethodId(cUnit->method_idx);
+ std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
+ std::string name(cUnit->dex_file->GetMethodName(method_id));
+ std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
+
+ // Dump mapping table
+ if (cUnit->mappingTable.size() > 0) {
+ std::string line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
+ descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size()));
+ std::replace(line.begin(), line.end(), ';', '_');
+ LOG(INFO) << line;
+ for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
+ line = StringPrintf(" {0x%08x, 0x%04x},",
+ cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
+ LOG(INFO) << line;
+ }
+ LOG(INFO) <<" };\n\n";
+ }
+}
+
+/*
* The following are building blocks to construct low-level IRs with 0 - 4
* operands.
*/
-LIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode)
+LIR* newLIR0(CompilationUnit* cUnit, int opcode)
{
LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
@@ -245,7 +425,7 @@ LIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode)
return insn;
}
-LIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode,
+LIR* newLIR1(CompilationUnit* cUnit, int opcode,
int dest)
{
LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
@@ -258,7 +438,7 @@ LIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode,
return insn;
}
-LIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode,
+LIR* newLIR2(CompilationUnit* cUnit, int opcode,
int dest, int src1)
{
LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
@@ -273,7 +453,7 @@ LIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode,
return insn;
}
-LIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode,
+LIR* newLIR3(CompilationUnit* cUnit, int opcode,
int dest, int src1, int src2)
{
LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
@@ -293,7 +473,7 @@ LIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode,
}
#if defined(TARGET_ARM)
-LIR* newLIR4(CompilationUnit* cUnit, ArmOpcode opcode,
+LIR* newLIR4(CompilationUnit* cUnit, int opcode,
int dest, int src1, int src2, int info)
{
LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
@@ -350,7 +530,7 @@ LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
* instruction streams.
*/
-/* Add a 32-bit constant either in the constant pool or mixed with code */
+/* Add a 32-bit constant either in the constant pool */
LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
int value)
{
@@ -362,10 +542,6 @@ LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
newValue->next = *constantListP;
*constantListP = (LIR*) newValue;
return newValue;
- } else {
- /* Add the constant in the middle of code stream */
- newLIR1(cUnit, kArm16BitData, (value & 0xffff));
- newLIR1(cUnit, kArm16BitData, (value >> 16));
}
return NULL;
}
@@ -374,17 +550,10 @@ LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
int valLo, int valHi)
{
- LIR* res;
//FIXME: hard-coded little endian, need BE variant
- if (constantListP == NULL) {
- res = addWordData(cUnit, NULL, valLo);
- addWordData(cUnit, NULL, valHi);
- } else {
- // Insert high word into list first
- addWordData(cUnit, constantListP, valHi);
- res = addWordData(cUnit, constantListP, valLo);
- }
- return res;
+ // Insert high word into list first
+ addWordData(cUnit, constantListP, valHi);
+ return addWordData(cUnit, constantListP, valLo);
}
void pushWord(std::vector<uint16_t>&buf, int data) {
diff --git a/src/compiler/codegen/CompilerCodegen.h b/src/compiler/codegen/CompilerCodegen.h
index ae85bb3d15..26dad8240c 100644
--- a/src/compiler/codegen/CompilerCodegen.h
+++ b/src/compiler/codegen/CompilerCodegen.h
@@ -35,6 +35,9 @@ int oatAssignInsnOffsets(CompilationUnit* cUnit);
void oatCodegenDump(CompilationUnit* cUnit);
void oatDumpPromotionMap(CompilationUnit* cUnit);
void oatDumpFullPromotionMap(CompilationUnit* cUnit);
+std::string buildInsnString(const char* fmt, LIR* lir,
+ unsigned char* baseAddr);
+
/* Implemented in codegen/<target>/Ralloc.c */
void oatSimpleRegAlloc(CompilationUnit* cUnit);
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 7af1aa033c..511c47bdae 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -43,19 +43,23 @@ void genBarrier(CompilationUnit* cUnit)
barrier->defMask = -1;
}
-/* Generate conditional branch instructions */
-LIR* genConditionalBranch(CompilationUnit* cUnit, ConditionCode cond,
- LIR* target)
+
+/* Generate unconditional branch instructions */
+LIR* genUnconditionalBranch(CompilationUnit* cUnit, LIR* target)
{
- LIR* branch = opCondBranch(cUnit, cond);
+ LIR* branch = opNone(cUnit, kOpUncondBr);
branch->target = (LIR*) target;
return branch;
}
-/* Generate unconditional branch instructions */
-LIR* genUnconditionalBranch(CompilationUnit* cUnit, LIR* target)
+// FIXME: need to do some work to split out targets with
+// condition codes and those without
+#if defined(TARGET_ARM) || defined(TARGET_X86)
+/* Generate conditional branch instructions */
+LIR* genConditionalBranch(CompilationUnit* cUnit, ConditionCode cond,
+ LIR* target)
{
- LIR* branch = opNone(cUnit, kOpUncondBr);
+ LIR* branch = opCondBranch(cUnit, cond);
branch->target = (LIR*) target;
return branch;
}
@@ -72,6 +76,7 @@ LIR* genCheck(CompilationUnit* cUnit, ConditionCode cCode, MIR* mir,
oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
return branch;
}
+#endif
LIR* genImmedCheck(CompilationUnit* cUnit, ConditionCode cCode,
int reg, int immVal, MIR* mir, ThrowKind kind)
@@ -112,8 +117,12 @@ LIR* genRegRegCheck(CompilationUnit* cUnit, ConditionCode cCode,
tgt->operands[1] = mir ? mir->offset : 0;
tgt->operands[2] = reg1;
tgt->operands[3] = reg2;
+#if defined(TARGET_MIPS)
+ LIR* branch = genCompareBranch(cUnit, cCode, reg1, reg2);
+#else
opRegReg(cUnit, kOpCmp, reg1, reg2);
LIR* branch = genConditionalBranch(cUnit, cCode, tgt);
+#endif
// Remember branch target - will process later
oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
return branch;
@@ -125,7 +134,6 @@ void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
ConditionCode cond;
rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
- opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
Opcode opcode = mir->dalvikInsn.opcode;
switch(opcode) {
case OP_IF_EQ:
@@ -150,7 +158,13 @@ void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
cond = (ConditionCode)0;
LOG(FATAL) << "Unexpected opcode " << (int)opcode;
}
+#if defined(TARGET_MIPS)
+ LIR* branch = genCompareBranch(cUnit, cond, rlSrc1.lowReg, rlSrc2.lowReg);
+ branch->target = &labelList[bb->taken->id];
+#else
+ opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
+#endif
genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
}
@@ -159,7 +173,6 @@ void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
{
ConditionCode cond;
rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
Opcode opcode = mir->dalvikInsn.opcode;
switch(opcode) {
case OP_IF_EQZ:
@@ -184,7 +197,13 @@ void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
cond = (ConditionCode)0;
LOG(FATAL) << "Unexpected opcode " << (int)opcode;
}
+#if defined(TARGET_MIPS)
+ LIR* branch = genCmpImmBranch(cUnit, cond, rlSrc.lowReg, 0);
+ branch->target = &labelList[bb->taken->id];
+#else
+ opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
+#endif
genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
}
@@ -319,7 +338,11 @@ void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
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
+#else
+ int rVal = oatAllocTemp(cUnit);
+#endif
// Set up source pointer
RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
@@ -340,8 +363,9 @@ void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
LIR* branch = opCondBranch(cUnit, kCondGe);
#else
+ oatFreeTemp(cUnit, rVal);
opRegImm(cUnit, kOpSub, rIdx, 1);
- LIR* branch = opCompareBranchImm(cUnit, kCondGe, rIdx, 0);
+ LIR* branch = genCmpImmBranch(cUnit, kCondGe, rIdx, 0);
#endif
branch->target = (LIR*)target;
} else if (!isRange) {
@@ -637,11 +661,11 @@ void handleThrowLaunchpads(CompilationUnit *cUnit)
funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode);
break;
case kThrowArrayBounds:
- if (v2 != r0) {
+ if (v2 != rARG0) {
genRegCopy(cUnit, rARG0, v1);
genRegCopy(cUnit, rARG1, v2);
} else {
- if (v1 == r1) {
+ if (v1 == rARG1) {
#if defined(TARGET_ARM)
int rTmp = r12;
#else
@@ -860,7 +884,7 @@ void genConstClass(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
// TUNING: move slow path to end & remove unconditional branch
LIR* target1 = newLIR0(cUnit, kPseudoTargetLabel);
target1->defMask = ENCODE_ALL;
- // Call out to helper, which will return resolved type in r0
+ // Call out to helper, which will return resolved type in rARG0
int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
pInitializeTypeFromCode));
genRegCopy(cUnit, rARG1, mReg);
@@ -909,7 +933,7 @@ void genConstString(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
genRegCopy(cUnit, rARG0, rARG2); // .eq
opReg(cUnit, kOpBlx, rTgt); // .eq, helper(Method*, string_idx)
#else
- LIR* branch = genCmpImmBranch(cUnit, kCondNe, 0);
+ LIR* branch = genCmpImmBranch(cUnit, kCondNe, rRET0, 0);
genRegCopy(cUnit, rARG0, rARG2); // .eq
opReg(cUnit, kOpBlx, rTgt);
LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
@@ -961,22 +985,22 @@ void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
// May generate a call - use explicit registers
oatLockCallTemps(cUnit);
uint32_t type_idx = mir->dalvikInsn.vC;
- loadCurrMethodDirect(cUnit, rARG1); // r1 <= current Method*
+ loadCurrMethodDirect(cUnit, rARG1); // rARG1 <= current Method*
int classReg = rARG2; // rARG2 will hold the Class*
if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
cUnit->dex_cache,
*cUnit->dex_file,
type_idx)) {
// Check we have access to type_idx and if not throw IllegalAccessError,
- // returns Class* in r0
+ // returns Class* in rARG0
int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
pInitializeTypeAndVerifyAccessFromCode));
loadConstant(cUnit, rARG0, type_idx);
callRuntimeHelper(cUnit, rTgt); // InitializeTypeAndVerifyAccess(idx, method)
genRegCopy(cUnit, classReg, rRET0); // Align usage with fast path
- loadValueDirectFixed(cUnit, rlSrc, rARG0); // r0 <= ref
+ loadValueDirectFixed(cUnit, rlSrc, rARG0); // rARG0 <= ref
} else {
- // Load dex cache entry into classReg (r2)
+ // Load dex cache entry into classReg (rARG2)
loadValueDirectFixed(cUnit, rlSrc, rARG0); // rARG0 <= ref
loadWordDisp(cUnit, rARG1,
Method::DexCacheResolvedTypesOffset().Int32Value(),
@@ -995,7 +1019,7 @@ void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
pInitializeTypeFromCode));
loadConstant(cUnit, rARG0, type_idx);
callRuntimeHelper(cUnit, rTgt); // InitializeTypeFromCode(idx, method)
- genRegCopy(cUnit, r2, rRET0); // Align usage with fast path
+ genRegCopy(cUnit, rARG2, rRET0); // Align usage with fast path
loadValueDirectFixed(cUnit, rlSrc, rARG0); /* reload Ref */
// Rejoin code paths
LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
@@ -1021,6 +1045,7 @@ void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
genBarrier(cUnit);
oatClobberCalleeSave(cUnit);
#else
+ (void)rTgt;
// Perhaps a general-purpose kOpSelect operator?
UNIMPLEMENTED(FATAL) << "Need non IT implementation";
#endif
@@ -1065,18 +1090,18 @@ void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
// Need to test presence of type in dex cache at runtime
LIR* hopBranch = genCmpImmBranch(cUnit, kCondNe, classReg, 0);
// Not resolved
- // Call out to helper, which will return resolved type in r0
- loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
- loadConstant(cUnit, r0, type_idx);
- callRuntimeHelper(cUnit, rLR); // InitializeTypeFromCode(idx, method)
- genRegCopy(cUnit, classReg, r0); // Align usage with fast path
+ // Call out to helper, which will return resolved type in rARG0
+ int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode));
+ loadConstant(cUnit, rARG0, type_idx);
+ callRuntimeHelper(cUnit, rTgt); // InitializeTypeFromCode(idx, method)
+ genRegCopy(cUnit, classReg, rARG0); // Align usage with fast path
// Rejoin code paths
LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel);
hopTarget->defMask = ENCODE_ALL;
hopBranch->target = (LIR*)hopTarget;
}
}
- // At this point, classReg (r2) has class
+ // At this point, classReg (rARG2) has class
loadValueDirectFixed(cUnit, rlSrc, rARG0); // rARG0 <= ref
/* Null is OK - continue */
LIR* branch1 = genCmpImmBranch(cUnit, kCondEq, rARG0, 0);
@@ -1086,8 +1111,12 @@ void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
/* rARG1 now contains object->clazz */
int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
pCheckCastFromCode));
+#if defined(TARGET_MIPS)
+ LIR* branch2 = genCompareBranch(cUnit, kCondEq, rARG1, classReg);
+#else
opRegReg(cUnit, kOpCmp, rARG1, classReg);
LIR* branch2 = opCondBranch(cUnit, kCondEq); /* If equal, trivial yes */
+#endif
genRegCopy(cUnit, rARG0, rARG1);
genRegCopy(cUnit, rARG1, rARG2);
callRuntimeHelper(cUnit, rTgt);
@@ -1430,7 +1459,7 @@ bool genArithOpInt(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
retReg = rRET0;
break;
- /* NOTE: returns in r1 */
+ /* NOTE: returns in rARG1 */
case OP_REM_INT:
case OP_REM_INT_2ADDR:
callOut = true;
@@ -1598,8 +1627,12 @@ void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc,
RegLocation rlResult, int lit,
int firstBit, int secondBit)
{
+#if defined(TARGET_MIPS)
+ UNIMPLEMENTED(FATAL) << "Need shift & add primative";
+#else
opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,
encodeShift(kArmLsl, secondBit - firstBit));
+#endif
if (firstBit != 0) {
opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
}
@@ -1882,7 +1915,7 @@ bool genArithOpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
genCheck(cUnit, kCondEq, mir, kThrowDivZero);
#else
opRegRegReg(cUnit, kOpOr, tReg, rARG2, rARG3);
- genImmedCheck(cUnit, kCondEq, mir, tReg, 0, mir, kThrowDivZero);
+ genImmedCheck(cUnit, kCondEq, tReg, 0, mir, kThrowDivZero);
oatFreeTemp(cUnit, tReg);
#endif
} else {
@@ -2116,7 +2149,7 @@ void genSuspendTest(CompilationUnit* cUnit, MIR* mir)
branch = opCondBranch(cUnit, kCondEq);
#else
opRegImm(cUnit, kOpSub, rSUSPEND, 1);
- branch = opCompareBranchImm(cUnit, kCondEq, rSUSPEND, 0);
+ branch = genCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0);
#endif
}
LIR* retLab = newLIR0(cUnit, kPseudoTargetLabel);
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index 6de3a9c3d9..38c2117036 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -102,7 +102,11 @@ void genInvoke(CompilationUnit* cUnit, MIR* mir, InvokeType type, bool isRange)
if (DISPLAY_MISSING_TARGETS) {
genShowTarget(cUnit);
}
+#if defined(TARGET_MIPS)
+ UNIMPLEMENTED(FATAL) << "Need to handle common target register";
+#else
opReg(cUnit, kOpBlx, rLR);
+#endif
oatClobberCalleeSave(cUnit);
}
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index e1eba44138..be6b44de71 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -321,180 +321,5 @@ void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
}
}
-/*
- * Debugging macros
- */
-#define DUMP_RESOURCE_MASK(X)
-#define DUMP_SSA_REP(X)
-
-/* Pretty-print a LIR instruction */
-void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
-{
- LIR* lir = (LIR*) arg;
- int offset = lir->offset;
- int dest = lir->operands[0];
- const bool dumpNop = false;
-
- /* Handle pseudo-ops individually, and all regular insns as a group */
- switch(lir->opcode) {
- case kPseudoMethodEntry:
- LOG(INFO) << "-------- method entry " <<
- PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
- break;
- case kPseudoMethodExit:
- LOG(INFO) << "-------- Method_Exit";
- break;
- case kPseudoBarrier:
- LOG(INFO) << "-------- BARRIER";
- break;
- case kPseudoExtended:
- LOG(INFO) << "-------- " << (char* ) dest;
- break;
- case kPseudoSSARep:
- DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
- break;
- case kPseudoEntryBlock:
- LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
- break;
- case kPseudoDalvikByteCodeBoundary:
- LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
- lir->dalvikOffset << " @ " << (char* )lir->operands[0];
- break;
- case kPseudoExitBlock:
- LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
- break;
- case kPseudoPseudoAlign4:
- LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
- offset << "): .align4";
- break;
- case kPseudoEHBlockLabel:
- LOG(INFO) << "Exception_Handling:";
- break;
- case kPseudoTargetLabel:
- case kPseudoNormalBlockLabel:
- LOG(INFO) << "L" << (intptr_t)lir << ":";
- break;
- case kPseudoThrowTarget:
- LOG(INFO) << "LT" << (intptr_t)lir << ":";
- break;
- case kPseudoSuspendTarget:
- LOG(INFO) << "LS" << (intptr_t)lir << ":";
- break;
- case kPseudoCaseLabel:
- LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
- std::hex << lir->operands[0] << "|" << std::dec <<
- lir->operands[0];
- break;
- default:
- if (lir->flags.isNop && !dumpNop) {
- break;
- } else {
- std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr));
- std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr));
- LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset,
- op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : "");
- }
- break;
- }
-
- if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
- DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
- lir->useMask, "use"));
- }
- if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
- DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
- lir->defMask, "def"));
- }
-}
-
-void oatDumpPromotionMap(CompilationUnit *cUnit)
-{
- for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
- PromotionMap vRegMap = cUnit->promotionMap[i];
- char buf[100];
- if (vRegMap.fpLocation == kLocPhysReg) {
- snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK);
- } else {
- buf[0] = 0;
- }
- char buf2[100];
- snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
- vRegMap.coreLocation == kLocPhysReg ?
- "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
- vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
- LOG(INFO) << buf2;
- }
-}
-
-void oatDumpFullPromotionMap(CompilationUnit *cUnit)
-{
- for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
- PromotionMap vRegMap = cUnit->promotionMap[i];
- LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation <<
- ", CR:" << (int)vRegMap.coreReg << ", FL:" <<
- (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg <<
- ", - " << (int)vRegMap.firstInPair;
- }
-}
-
-/* Dump instructions and constant pool contents */
-void oatCodegenDump(CompilationUnit* cUnit)
-{
- LOG(INFO) << "/*";
- LOG(INFO) << "Dumping LIR insns for "
- << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
- LIR* lirInsn;
- LIR* armLIR;
- int insnsSize = cUnit->insnsSize;
-
- LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
- LOG(INFO) << "Ins : " << cUnit->numIns;
- LOG(INFO) << "Outs : " << cUnit->numOuts;
- LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
- LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
- LOG(INFO) << "Padding : " << cUnit->numPadding;
- LOG(INFO) << "Frame size : " << cUnit->frameSize;
- LOG(INFO) << "Start of ins : " << cUnit->insOffset;
- LOG(INFO) << "Start of regs : " << cUnit->regsOffset;
- LOG(INFO) << "code size is " << cUnit->totalSize <<
- " bytes, Dalvik size is " << insnsSize * 2;
- LOG(INFO) << "expansion factor: " <<
- (float)cUnit->totalSize / (float)(insnsSize * 2);
- oatDumpPromotionMap(cUnit);
- for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
- oatDumpLIRInsn(cUnit, lirInsn, 0);
- }
- for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
- armLIR = (LIR*) lirInsn;
- LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
- armLIR->offset, armLIR->offset,
- ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
- }
- for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
- armLIR = (LIR*) lirInsn;
- LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
- armLIR->offset, armLIR->offset, armLIR->operands[0]);
- }
-
- const DexFile::MethodId& method_id =
- cUnit->dex_file->GetMethodId(cUnit->method_idx);
- std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
- std::string name(cUnit->dex_file->GetMethodName(method_id));
- std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
-
- // Dump mapping table
- if (cUnit->mappingTable.size() > 0) {
- std::string line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
- descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size()));
- std::replace(line.begin(), line.end(), ';', '_');
- LOG(INFO) << line;
- for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
- line = StringPrintf(" {0x%08x, 0x%04x},",
- cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
- LOG(INFO) << line;
- }
- LOG(INFO) <<" };\n\n";
- }
-}
} // namespace art
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 196bddb37f..e4e9eb83b1 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -745,22 +745,6 @@ typedef enum ArmTargetOptHints {
extern const ArmEncodingMap EncodingMap[kArmLast];
-typedef struct SwitchTable {
- int offset;
- const u2* table; // Original dex table
- int vaddr; // Dalvik offset of switch opcode
- LIR* bxInst; // Switch indirect branch instruction
- LIR** targets; // Array of case targets
-} SwitchTable;
-
-typedef struct FillArrayData {
- int offset;
- const u2* table; // Original dex table
- int size;
- int vaddr; // Dalvik offset of OP_FILL_ARRAY_DATA opcode
-} FillArrayData;
-
-
} // namespace art
#endif // ART_SRC_COMPILER_CODEGEN_ARM_ARMLIR_H_
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index a020687210..d44d7cf970 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -116,6 +116,22 @@ void oatClobberCalleeSave(CompilationUnit *cUnit)
oatClobber(cUnit, r3);
oatClobber(cUnit, r12);
oatClobber(cUnit, r14lr);
+ oatClobber(cUnit, fr0);
+ oatClobber(cUnit, fr1);
+ oatClobber(cUnit, fr2);
+ oatClobber(cUnit, fr3);
+ oatClobber(cUnit, fr4);
+ oatClobber(cUnit, fr5);
+ oatClobber(cUnit, fr6);
+ oatClobber(cUnit, fr7);
+ oatClobber(cUnit, fr8);
+ oatClobber(cUnit, fr9);
+ oatClobber(cUnit, fr10);
+ oatClobber(cUnit, fr11);
+ oatClobber(cUnit, fr12);
+ oatClobber(cUnit, fr13);
+ oatClobber(cUnit, fr14);
+ oatClobber(cUnit, fr15);
}
extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)
diff --git a/src/compiler/codegen/arm/Codegen.h b/src/compiler/codegen/arm/Codegen.h
index a565cb1f37..49e39db837 100644
--- a/src/compiler/codegen/arm/Codegen.h
+++ b/src/compiler/codegen/arm/Codegen.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc
index cb9645de56..2cb0731e0c 100644
--- a/src/compiler/codegen/mips/ArchFactory.cc
+++ b/src/compiler/codegen/mips/ArchFactory.cc
@@ -22,1096 +22,68 @@
*
*/
-#define SLOW_FIELD_PATH (cUnit->enableDebug & (1 << kDebugSlowFieldPath))
-#define SLOW_INVOKE_PATH (cUnit->enableDebug & (1 << kDebugSlowInvokePath))
-#define SLOW_STRING_PATH (cUnit->enableDebug & (1 << kDebugSlowStringPath))
-#define SLOW_TYPE_PATH (cUnit->enableDebug & (1 << kDebugSlowTypePath))
-#define EXERCISE_SLOWEST_FIELD_PATH (cUnit->enableDebug & \
- (1 << kDebugSlowestFieldPath))
-#define EXERCISE_SLOWEST_STRING_PATH (cUnit->enableDebug & \
- (1 << kDebugSlowestStringPath))
-#define EXERCISE_RESOLVE_METHOD (cUnit->enableDebug & \
- (1 << kDebugExerciseResolveMethod))
-
-// FIXME - this is the Mips version, change to MIPS
-
namespace art {
-STATIC void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
-
-/* Generate unconditional branch instructions */
-STATIC MipsLIR* genUnconditionalBranch(CompilationUnit* cUnit, MipsLIR* target)
-{
- MipsLIR* branch = opNone(cUnit, kOpUncondBr);
- branch->generic.target = (LIR*) target;
- return branch;
-}
-
-STATIC MipsLIR* callRuntimeHelper(CompilationUnit* cUnit, int reg)
-{
- oatClobberCalleeSave(cUnit);
- return opReg(cUnit, kOpBlx, reg);
-}
-
-/*
- * Mark garbage collection card. Skip if the value we're storing is null.
- */
-STATIC void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
-{
- int regCardBase = oatAllocTemp(cUnit);
- int regCardNo = oatAllocTemp(cUnit);
- MipsLIR* branchOver = opCompareBranchCC(cUnit, kMipsCondEq, valReg, r_ZERO);
- loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(),
- regCardBase);
- opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
- storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
- kUnsignedByte);
- MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
- target->defMask = ENCODE_ALL;
- branchOver->generic.target = (LIR*)target;
- oatFreeTemp(cUnit, regCardBase);
- oatFreeTemp(cUnit, regCardNo);
-}
-
-/*
- * Utiltiy to load the current Method*. Broken out
- * to allow easy change between placing the current Method* in a
- * dedicated register or its home location in the frame.
- */
-STATIC void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
-{
-#if defined(METHOD_IN_REG)
- genRegCopy(cUnit, rTgt, rMETHOD);
-#else
- loadWordDisp(cUnit, rSP, 0, rTgt);
-#endif
-}
-
-STATIC int loadCurrMethod(CompilationUnit *cUnit)
-{
-#if defined(METHOD_IN_REG)
- return rMETHOD;
-#else
- int mReg = oatAllocTemp(cUnit);
- loadCurrMethodDirect(cUnit, mReg);
- return mReg;
-#endif
-}
-
-STATIC MipsLIR* genImmedCheck(CompilationUnit* cUnit, MipsConditionCode cCode,
- int reg, int immVal, MIR* mir, MipsThrowKind kind)
-{
- MipsLIR* tgt = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- tgt->opcode = kPseudoThrowTarget;
- tgt->operands[0] = kind;
- tgt->operands[1] = mir->offset;
- MipsLIR* branch;
- if (cCode == kMipsCondAl) {
- branch = genUnconditionalBranch(cUnit, tgt);
- } else {
- int tReg;
- if (immVal == 0) {
- tReg = r_ZERO;
- } else {
- tReg = oatAllocTemp(cUnit);
- loadConstant(cUnit, tReg, immVal);
- }
- branch = opCompareBranchCC(cUnit, cCode, reg, tReg);
- branch->generic.target = (LIR*)tgt;
- }
- // Remember branch target - will process later
- oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
- return branch;
-}
-
-/* Perform null-check on a register. */
-STATIC MipsLIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg,
- MIR* mir)
-{
- if (!(cUnit->disableOpt & (1 << kNullCheckElimination)) &&
- mir->optimizationFlags & MIR_IGNORE_NULL_CHECK) {
- return NULL;
- }
- return genImmedCheck(cUnit, kMipsCondEq, mReg, 0, mir, kMipsThrowNullPointer);
-}
-
-/* Perform check on two registers */
-STATIC TGT_LIR* genRegRegCheck(CompilationUnit* cUnit, MipsConditionCode cCode,
- int reg1, int reg2, MIR* mir, MipsThrowKind kind)
-{
- MipsLIR* tgt = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- tgt->opcode = kPseudoThrowTarget;
- tgt->operands[0] = kind;
- tgt->operands[1] = mir ? mir->offset : 0;
- tgt->operands[2] = reg1;
- tgt->operands[3] = reg2;
- opRegReg(cUnit, kOpCmp, reg1, reg2);
- MipsLIR* branch = genConditionalBranch(cUnit, cCode, tgt);
- // Remember branch target - will process later
- oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
- return branch;
-}
-
-/*
- * Let helper function take care of everything. Will call
- * Array::AllocFromCode(type_idx, method, count);
- * Note: AllocFromCode will handle checks for errNegativeArraySize.
- */
-STATIC void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
- RegLocation rlSrc)
-{
- oatFlushAllRegs(cUnit); /* Everything to home location */
- oatLockCallTemps(cUnit);
- int addrReg = oatAllocTemp(cUnit);
- uint32_t type_idx = mir->dalvikInsn.vC;
- if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
- cUnit->dex_cache,
- *cUnit->dex_file,
- type_idx)) {
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), addrReg);
- } else {
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pAllocArrayFromCodeWithAccessCheck), addrReg);
- }
- loadCurrMethodDirect(cUnit, r_ARG1); // arg1 <- Method*
- loadConstant(cUnit, r_ARG0, type_idx); // arg0 <- type_id
- loadValueDirectFixed(cUnit, rlSrc, r_ARG2); // arg2 <- count
- callRuntimeHelper(cUnit, addrReg);
- RegLocation rlResult = oatGetReturn(cUnit);
- storeValue(cUnit, rlDest, rlResult);
-}
-
-/*
- * Similar to genNewArray, but with post-allocation initialization.
- * Verifier guarantees we're dealing with an array class. Current
- * code throws runtime exception "bad Filled array req" for 'D' and 'J'.
- * Current code also throws internal unimp if not 'L', '[' or 'I'.
- */
-STATIC void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
-{
- DecodedInstruction* dInsn = &mir->dalvikInsn;
- int elems = dInsn->vA;
- int typeId = dInsn->vB;
- oatFlushAllRegs(cUnit); /* Everything to home location */
- oatLockCallTemps(cUnit);
- int addrReg = oatAllocTemp(cUnit);
- if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,
- cUnit->dex_cache,
- *cUnit->dex_file,
- typeId)) {
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode),
- addrReg);
- } else {
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread,
- pCheckAndAllocArrayFromCodeWithAccessCheck), addrReg);
- }
- loadCurrMethodDirect(cUnit, r_ARG1); // arg1 <- Method*
- loadConstant(cUnit, r_ARG0, typeId); // arg0 <- type_id
- loadConstant(cUnit, r_ARG2, elems); // arg2 <- count
- callRuntimeHelper(cUnit, addrReg);
- /*
- * NOTE: the implicit target for OP_FILLED_NEW_ARRAY is the
- * return region. Because AllocFromCode placed the new array
- * in r_V0, we'll just lock it into place. When debugger support is
- * added, it may be necessary to additionally copy all return
- * values to a home location in thread-local storage
- */
- oatLockTemp(cUnit, r_V0);
-
- // Having a range of 0 is legal
- if (isRange && (dInsn->vA > 0)) {
- /*
- * Bit of ugliness here. We're going generate a mem copy loop
- * on the register range, but it is possible that some regs
- * in the range have been promoted. This is unlikely, but
- * before generating the copy, we'll just force a flush
- * of any regs in the source range that have been promoted to
- * home location.
- */
- for (unsigned int i = 0; i < dInsn->vA; i++) {
- RegLocation loc = oatUpdateLoc(cUnit,
- oatGetSrc(cUnit, mir, i));
- if (loc.location == kLocPhysReg) {
- storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
- loc.lowReg, kWord);
- }
- }
- /*
- * TUNING note: generated code here could be much improved, but
- * this is an uncommon operation and isn't especially performance
- * critical.
- */
- int rSrc = oatAllocTemp(cUnit);
- int rDst = oatAllocTemp(cUnit);
- int rIdx = oatAllocTemp(cUnit);
- int rVal = oatAllocTemp(cUnit);
- // Set up source pointer
- RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
- opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
- oatSRegOffset(cUnit, rlFirst.sRegLow));
- // Set up the target pointer
- opRegRegImm(cUnit, kOpAdd, rDst, r_V0,
- Array::DataOffset().Int32Value());
- // Set up the loop counter (known to be > 0)
- loadConstant(cUnit, rIdx, dInsn->vA - 1);
- // Generate the copy loop. Going backwards for convenience
- MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
- target->defMask = ENCODE_ALL;
- // Copy next element
- loadBaseIndexed(cUnit, rSrc, rIdx, rVal, 2, kWord);
- storeBaseIndexed(cUnit, rDst, rIdx, rVal, 2, kWord);
- opRegImm(cUnit, kOpSub, rIdx, 1);
- MipsLIR* branch = opCompareBranchCC(cUnit, kMipsCondGe, rIdx, r_ZERO);
- branch->generic.target = (LIR*)target;
- } else if (!isRange) {
- // TUNING: interleave
- for (unsigned int i = 0; i < dInsn->vA; i++) {
- RegLocation rlArg = loadValue(cUnit,
- oatGetSrc(cUnit, mir, i), kCoreReg);
- storeBaseDisp(cUnit, r_V0,
- Array::DataOffset().Int32Value() +
- i * 4, rlArg.lowReg, kWord);
- // If the loadValue caused a temp to be allocated, free it
- if (oatIsTemp(cUnit, rlArg.lowReg)) {
- oatFreeTemp(cUnit, rlArg.lowReg);
- }
- }
- }
-}
-
-STATIC void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
- bool isLongOrDouble, bool isObject)
-{
- int fieldOffset;
- int ssbIndex;
- bool isVolatile;
- bool isReferrersClass;
- uint32_t fieldIdx = mir->dalvikInsn.vB;
- bool fastPath =
- cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, cUnit,
- fieldOffset, ssbIndex,
- isReferrersClass, isVolatile, true);
- if (fastPath && !SLOW_FIELD_PATH) {
- DCHECK_GE(fieldOffset, 0);
- int rBase;
- int rMethod;
- if (isReferrersClass) {
- // Fast path, static storage base is this method's class
- rMethod = loadCurrMethod(cUnit);
- rBase = oatAllocTemp(cUnit);
- loadWordDisp(cUnit, rMethod,
- Method::DeclaringClassOffset().Int32Value(), rBase);
- } else {
- // Medium path, static storage base in a different class which
- // requires checks that the other class is initialized.
- DCHECK_GE(ssbIndex, 0);
- // May do runtime call so everything to home locations.
- oatFlushAllRegs(cUnit);
- // Using fixed register to sync with possible call to runtime
- // support.
- oatLockCallTemps(cUnit);
- rMethod = r1;
- oatLockTemp(cUnit, rMethod);
- loadCurrMethodDirect(cUnit, rMethod);
- rBase = r0;
- oatLockTemp(cUnit, rBase);
- loadWordDisp(cUnit, rMethod,
- Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
- rBase);
- loadWordDisp(cUnit, rBase,
- Array::DataOffset().Int32Value() + sizeof(int32_t*) *
- ssbIndex, rBase);
- // rBase now points at appropriate static storage base (Class*)
- // or NULL if not initialized. Check for NULL and call helper if NULL.
- // TUNING: fast path should fall through
- MipsLIR* branchOver = opCmpImmBranchCC(cUnit, kMipsCondNe,
- rBase, 0);
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR);
- loadConstant(cUnit, r0, ssbIndex);
- callRuntimeHelper(cUnit, rLR);
- MipsLIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel);
- skipTarget->defMask = ENCODE_ALL;
- branchOver->generic.target = (LIR*)skipTarget;
- }
- // rBase now holds static storage base
- oatFreeTemp(cUnit, rMethod);
- if (isLongOrDouble) {
- rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
- } else {
- rlSrc = oatGetSrc(cUnit, mir, 0);
- rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
- }
- if (isVolatile) {
- oatGenMemBarrier(cUnit, kST);
- }
- if (isLongOrDouble) {
- storeBaseDispWide(cUnit, rBase, fieldOffset, rlSrc.lowReg,
- rlSrc.highReg);
- } else {
- storeWordDisp(cUnit, rBase, fieldOffset, rlSrc.lowReg);
- }
- if (isVolatile) {
- oatGenMemBarrier(cUnit, kSY);
- }
- if (isObject) {
- markGCCard(cUnit, rlSrc.lowReg, rBase);
- }
- oatFreeTemp(cUnit, rBase);
- } else {
- oatFlushAllRegs(cUnit); // Everything to home locations
- int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Static) :
- (isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic)
- : OFFSETOF_MEMBER(Thread, pSet32Static));
- loadWordDisp(cUnit, rSELF, setterOffset, rLR);
- loadConstant(cUnit, r0, fieldIdx);
- if (isLongOrDouble) {
- loadValueDirectWideFixed(cUnit, rlSrc, r2, r3);
- } else {
- loadValueDirect(cUnit, rlSrc, r1);
- }
- callRuntimeHelper(cUnit, rLR);
- }
-}
-
-STATIC void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
- bool isLongOrDouble, bool isObject)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- int fieldOffset;
- int ssbIndex;
- bool isVolatile;
- bool isReferrersClass;
- uint32_t fieldIdx = mir->dalvikInsn.vB;
- bool fastPath =
- cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, cUnit,
- fieldOffset, ssbIndex,
- isReferrersClass, isVolatile, false);
- if (fastPath && !SLOW_FIELD_PATH) {
- DCHECK_GE(fieldOffset, 0);
- int rBase;
- int rMethod;
- if (isReferrersClass) {
- // Fast path, static storage base is this method's class
- rMethod = loadCurrMethod(cUnit);
- rBase = oatAllocTemp(cUnit);
- loadWordDisp(cUnit, rMethod,
- Method::DeclaringClassOffset().Int32Value(), rBase);
- } else {
- // Medium path, static storage base in a different class which
- // requires checks that the other class is initialized
- DCHECK_GE(ssbIndex, 0);
- // May do runtime call so everything to home locations.
- oatFlushAllRegs(cUnit);
- // Using fixed register to sync with possible call to runtime
- // support
- rMethod = r1;
- oatLockTemp(cUnit, rMethod);
- loadCurrMethodDirect(cUnit, rMethod);
- rBase = r0;
- oatLockTemp(cUnit, rBase);
- loadWordDisp(cUnit, rMethod,
- Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
- rBase);
- loadWordDisp(cUnit, rBase,
- Array::DataOffset().Int32Value() + sizeof(int32_t*) * ssbIndex,
- rBase);
- // rBase now points at appropriate static storage base (Class*)
- // or NULL if not initialized. Check for NULL and call helper if NULL.
- // TUNING: fast path should fall through
- MipsLIR* branchOver = opCmpImmBranchCC(cUnit, kMipsCondNe, rBase, 0);
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR);
- loadConstant(cUnit, r0, ssbIndex);
- callRuntimeHelper(cUnit, rLR);
- MipsLIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel);
- skipTarget->defMask = ENCODE_ALL;
- branchOver->generic.target = (LIR*)skipTarget;
- }
- // rBase now holds static storage base
- oatFreeTemp(cUnit, rMethod);
- rlDest = isLongOrDouble ? oatGetDestWide(cUnit, mir, 0, 1)
- : oatGetDest(cUnit, mir, 0);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
- if (isVolatile) {
- oatGenMemBarrier(cUnit, kSY);
- }
- if (isLongOrDouble) {
- loadBaseDispWide(cUnit, NULL, rBase, fieldOffset, rlResult.lowReg,
- rlResult.highReg, INVALID_SREG);
- } else {
- loadWordDisp(cUnit, rBase, fieldOffset, rlResult.lowReg);
- }
- oatFreeTemp(cUnit, rBase);
- if (isLongOrDouble) {
- storeValueWide(cUnit, rlDest, rlResult);
- } else {
- storeValue(cUnit, rlDest, rlResult);
- }
- } else {
- oatFlushAllRegs(cUnit); // Everything to home locations
- int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Static) :
- (isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic)
- : OFFSETOF_MEMBER(Thread, pGet32Static));
- loadWordDisp(cUnit, rSELF, getterOffset, rLR);
- loadConstant(cUnit, r0, fieldIdx);
- callRuntimeHelper(cUnit, rLR);
- if (isLongOrDouble) {
- RegLocation rlResult = oatGetReturnWide(cUnit);
- storeValueWide(cUnit, rlDest, rlResult);
- } else {
- RegLocation rlResult = oatGetReturn(cUnit);
- storeValue(cUnit, rlDest, rlResult);
- }
- }
-#endif
-}
-
-typedef int (*NextCallInsn)(CompilationUnit*, MIR*, int, uint32_t dexIdx,
- uint32_t methodIdx);
-
-/*
- * Bit of a hack here - in leiu of a real scheduling pass,
- * emit the next instruction in static & direct invoke sequences.
- */
-STATIC int nextSDCallInsn(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t unused)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- switch(state) {
- case 0: // Get the current Method* [sets r0]
- loadCurrMethodDirect(cUnit, r0);
- break;
- case 1: // Get method->code_and_direct_methods_
- loadWordDisp(cUnit, r0,
- Method::GetDexCacheCodeAndDirectMethodsOffset().Int32Value(),
- r0);
- break;
- case 2: // Grab target method* and target code_
- loadWordDisp(cUnit, r0,
- CodeAndDirectMethods::CodeOffsetInBytes(dexIdx), rLR);
- loadWordDisp(cUnit, r0,
- CodeAndDirectMethods::MethodOffsetInBytes(dexIdx), r0);
- break;
- default:
- return -1;
- }
-#endif
- return state + 1;
-}
-
-/*
- * Bit of a hack here - in leiu of a real scheduling pass,
- * emit the next instruction in a virtual invoke sequence.
- * We can use rLR as a temp prior to target address loading
- * Note also that we'll load the first argument ("this") into
- * r1 here rather than the standard loadArgRegs.
- */
-STATIC int nextVCallInsn(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t methodIdx)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- RegLocation rlArg;
- /*
- * This is the fast path in which the target virtual method is
- * fully resolved at compile time.
- */
- switch(state) {
- case 0: // Get "this" [set r1]
- rlArg = oatGetSrc(cUnit, mir, 0);
- loadValueDirectFixed(cUnit, rlArg, r1);
- break;
- case 1: // Is "this" null? [use r1]
- genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
- // get this->klass_ [use r1, set rLR]
- loadWordDisp(cUnit, r1, Object::ClassOffset().Int32Value(), rLR);
- break;
- case 2: // Get this->klass_->vtable [usr rLR, set rLR]
- loadWordDisp(cUnit, rLR, Class::VTableOffset().Int32Value(), rLR);
- break;
- case 3: // Get target method [use rLR, set r0]
- loadWordDisp(cUnit, rLR, (methodIdx * 4) +
- Array::DataOffset().Int32Value(), r0);
- break;
- case 4: // Get the target compiled code address [uses r0, sets rLR]
- loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
- break;
- default:
- return -1;
- }
-#endif
- return state + 1;
-}
+void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
/*
- * Interleave launch code for INVOKE_SUPER. See comments
- * for nextVCallIns.
+ * In the Arm code a it is typical to use the link register
+ * to hold the target address. However, for Mips we must
+ * ensure that all branch instructions can be restarted if
+ * there is a trap in the shadow. Allocate a temp register.
*/
-STATIC int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t methodIdx)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- /*
- * This is the fast path in which the target virtual method is
- * fully resolved at compile time. Note also that this path assumes
- * that the check to verify that the target method index falls
- * within the size of the super's vtable has been done at compile-time.
- */
- RegLocation rlArg;
- switch(state) {
- case 0: // Get current Method* [set r0]
- loadCurrMethodDirect(cUnit, r0);
- // Load "this" [set r1]
- rlArg = oatGetSrc(cUnit, mir, 0);
- loadValueDirectFixed(cUnit, rlArg, r1);
- // Get method->declaring_class_ [use r0, set rLR]
- loadWordDisp(cUnit, r0, Method::DeclaringClassOffset().Int32Value(),
- rLR);
- // Is "this" null? [use r1]
- genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
- break;
- case 1: // Get method->declaring_class_->super_class [usr rLR, set rLR]
- loadWordDisp(cUnit, rLR, Class::SuperClassOffset().Int32Value(),
- rLR);
- break;
- case 2: // Get ...->super_class_->vtable [u/s rLR]
- loadWordDisp(cUnit, rLR, Class::VTableOffset().Int32Value(), rLR);
- break;
- case 3: // Get target method [use rLR, set r0]
- loadWordDisp(cUnit, rLR, (methodIdx * 4) +
- Array::DataOffset().Int32Value(), r0);
- break;
- case 4: // Get the target compiled code address [uses r0, sets rLR]
- loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
- break;
- default:
- return -1;
- }
-#endif
- return state + 1;
-}
-
-STATIC int nextInvokeInsnSP(CompilationUnit* cUnit, MIR* mir, int trampoline,
- int state, uint32_t dexIdx, uint32_t methodIdx)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- /*
- * This handles the case in which the base method is not fully
- * resolved at compile time, we bail to a runtime helper.
- */
- if (state == 0) {
- // Load trampoline target
- loadWordDisp(cUnit, rSELF, trampoline, rLR);
- // Load r0 with method index
- loadConstant(cUnit, r0, dexIdx);
- return 1;
- }
-#endif
- return -1;
-}
-
-STATIC int nextStaticCallInsnSP(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t methodIdx)
-{
- int trampoline = OFFSETOF_MEMBER(Thread, pInvokeStaticTrampolineWithAccessCheck);
- return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int nextDirectCallInsnSP(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t methodIdx)
+int loadHelper(CompilationUnit* cUnit, int offset)
{
- int trampoline = OFFSETOF_MEMBER(Thread, pInvokeDirectTrampolineWithAccessCheck);
- return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
+ int tReg = oatAllocTemp(cUnit);
+ loadWordDisp(cUnit, rSELF, offset, tReg);
+ return tReg;
}
-STATIC int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t methodIdx)
+void spillCoreRegs(CompilationUnit* cUnit)
{
- int trampoline = OFFSETOF_MEMBER(Thread, pInvokeSuperTrampolineWithAccessCheck);
- return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t methodIdx)
-{
- int trampoline = OFFSETOF_MEMBER(Thread, pInvokeVirtualTrampolineWithAccessCheck);
- return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-/*
- * All invoke-interface calls bounce off of art_invoke_interface_trampoline,
- * which will locate the target and continue on via a tail call.
- */
-STATIC int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir,
- int state, uint32_t dexIdx, uint32_t unused)
-{
- int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampoline);
- return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int nextInterfaceCallInsnWithAccessCheck(CompilationUnit* cUnit,
- MIR* mir, int state,
- uint32_t dexIdx,
- uint32_t unused)
-{
- int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampolineWithAccessCheck);
- return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
-}
-
-STATIC int loadArgRegs(CompilationUnit* cUnit, MIR* mir,
- DecodedInstruction* dInsn, int callState,
- NextCallInsn nextCallInsn, uint32_t dexIdx,
- uint32_t methodIdx, bool skipThis)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- int nextReg = r1;
- int nextArg = 0;
- if (skipThis) {
- nextReg++;
- nextArg++;
- }
- for (; (nextReg <= r3) && (nextArg < mir->ssaRep->numUses); nextReg++) {
- RegLocation rlArg = oatGetRawSrc(cUnit, mir, nextArg++);
- rlArg = oatUpdateRawLoc(cUnit, rlArg);
- if (rlArg.wide && (nextReg <= r2)) {
- loadValueDirectWideFixed(cUnit, rlArg, nextReg, nextReg + 1);
- nextReg++;
- nextArg++;
- } else {
- rlArg.wide = false;
- loadValueDirectFixed(cUnit, rlArg, nextReg);
- }
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+ if (cUnit->numCoreSpills == 0) {
+ return;
}
-#endif
- return callState;
-}
-
-/*
- * Load up to 5 arguments, the first three of which will be in
- * r1 .. r3. On entry r0 contains the current method pointer,
- * and as part of the load sequence, it must be replaced with
- * the target method pointer. Note, this may also be called
- * for "range" variants if the number of arguments is 5 or fewer.
- */
-STATIC int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir,
- DecodedInstruction* dInsn, int callState,
- MipsLIR** pcrLabel, NextCallInsn nextCallInsn,
- uint32_t dexIdx, uint32_t methodIdx,
- bool skipThis)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- RegLocation rlArg;
-
- /* If no arguments, just return */
- if (dInsn->vA == 0)
- return callState;
-
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
-
- DCHECK_LE(dInsn->vA, 5U);
- if (dInsn->vA > 3) {
- uint32_t nextUse = 3;
- //Detect special case of wide arg spanning arg3/arg4
- RegLocation rlUse0 = oatGetRawSrc(cUnit, mir, 0);
- RegLocation rlUse1 = oatGetRawSrc(cUnit, mir, 1);
- RegLocation rlUse2 = oatGetRawSrc(cUnit, mir, 2);
- if (((!rlUse0.wide && !rlUse1.wide) || rlUse0.wide) &&
- rlUse2.wide) {
- int reg;
- // Wide spans, we need the 2nd half of uses[2].
- rlArg = oatUpdateLocWide(cUnit, rlUse2);
- if (rlArg.location == kLocPhysReg) {
- reg = rlArg.highReg;
- } else {
- // r2 & r3 can safely be used here
- reg = r3;
- loadWordDisp(cUnit, rSP,
- oatSRegOffset(cUnit, rlArg.sRegLow) + 4, reg);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx,
- methodIdx);
- }
- storeBaseDisp(cUnit, rSP, (nextUse + 1) * 4, reg, kWord);
- storeBaseDisp(cUnit, rSP, 16 /* (3+1)*4 */, reg, kWord);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
- nextUse++;
- }
- // Loop through the rest
- while (nextUse < dInsn->vA) {
- int lowReg;
- int highReg;
- rlArg = oatGetRawSrc(cUnit, mir, nextUse);
- rlArg = oatUpdateRawLoc(cUnit, rlArg);
- if (rlArg.location == kLocPhysReg) {
- lowReg = rlArg.lowReg;
- highReg = rlArg.highReg;
- } else {
- lowReg = r2;
- highReg = r3;
- if (rlArg.wide) {
- loadValueDirectWideFixed(cUnit, rlArg, lowReg, highReg);
- } else {
- loadValueDirectFixed(cUnit, rlArg, lowReg);
- }
- callState = nextCallInsn(cUnit, mir, callState, dexIdx,
- methodIdx);
- }
- int outsOffset = (nextUse + 1) * 4;
- if (rlArg.wide) {
- storeBaseDispWide(cUnit, rSP, outsOffset, lowReg, highReg);
- nextUse += 2;
- } else {
- storeWordDisp(cUnit, rSP, outsOffset, lowReg);
- nextUse++;
- }
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
+ uint32_t mask = cUnit->coreSpillMask;
+ int offset = cUnit->numCoreSpills * 4;
+ opRegImm(cUnit, kOpSub, rSP, offset);
+ for (int reg = 0; mask; mask >>= 1, reg++) {
+ if (mask & 0x1) {
+ offset -= 4;
+ storeWordDisp(cUnit, rSP, offset, reg);
}
}
-
- callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
- dexIdx, methodIdx, skipThis);
-
- if (pcrLabel) {
- *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
- }
-#endif
- return callState;
}
-/*
- * May have 0+ arguments (also used for jumbo). Note that
- * source virtual registers may be in physical registers, so may
- * need to be flushed to home location before copying. This
- * applies to arg3 and above (see below).
- *
- * Two general strategies:
- * If < 20 arguments
- * Pass args 3-18 using vldm/vstm block copy
- * Pass arg0, arg1 & arg2 in r1-r3
- * If 20+ arguments
- * Pass args arg19+ using memcpy block copy
- * Pass arg0, arg1 & arg2 in r1-r3
- *
- */
-STATIC int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir,
- DecodedInstruction* dInsn, int callState,
- MipsLIR** pcrLabel, NextCallInsn nextCallInsn,
- uint32_t dexIdx, uint32_t methodIdx,
- bool skipThis)
+void unSpillCoreRegs(CompilationUnit* cUnit)
{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- int firstArg = dInsn->vC;
- int numArgs = dInsn->vA;
-
- // If we can treat it as non-range (Jumbo ops will use range form)
- if (numArgs <= 5)
- return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
- nextCallInsn, dexIdx, methodIdx,
- skipThis);
- /*
- * Make sure range list doesn't span the break between in normal
- * Dalvik vRegs and the ins.
- */
- int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
- int boundaryReg = cUnit->numDalvikRegisters - cUnit->numIns;
- if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) {
- LOG(FATAL) << "Argument list spanned locals & args";
- }
-
- /*
- * First load the non-register arguments. Both forms expect all
- * of the source arguments to be in their home frame location, so
- * scan the sReg names and flush any that have been promoted to
- * frame backing storage.
- */
- // Scan the rest of the args - if in physReg flush to memory
- for (int nextArg = 0; nextArg < numArgs;) {
- RegLocation loc = oatGetRawSrc(cUnit, mir, nextArg);
- if (loc.wide) {
- loc = oatUpdateLocWide(cUnit, loc);
- if ((nextArg >= 2) && (loc.location == kLocPhysReg)) {
- storeBaseDispWide(cUnit, rSP,
- oatSRegOffset(cUnit, loc.sRegLow),
- loc.lowReg, loc.highReg);
- }
- nextArg += 2;
- } else {
- loc = oatUpdateLoc(cUnit, loc);
- if ((nextArg >= 3) && (loc.location == kLocPhysReg)) {
- storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
- loc.lowReg, kWord);
- }
- nextArg++;
- }
- }
-
- int startOffset = oatSRegOffset(cUnit,
- cUnit->regLocation[mir->ssaRep->uses[3]].sRegLow);
- int outsOffset = 4 /* Method* */ + (3 * 4);
- if (numArgs >= 20) {
- // Generate memcpy
- opRegRegImm(cUnit, kOpAdd, r0, rSP, outsOffset);
- opRegRegImm(cUnit, kOpAdd, r1, rSP, startOffset);
- loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pMemcpy), rLR);
- loadConstant(cUnit, r2, (numArgs - 3) * 4);
- callRuntimeHelper(cUnit, rLR);
- // Restore Method*
- loadCurrMethodDirect(cUnit, r0);
- } else {
- // Use vldm/vstm pair using r3 as a temp
- int regsLeft = std::min(numArgs - 3, 16);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
- opRegRegImm(cUnit, kOpAdd, r3, rSP, startOffset);
- MipsLIR* ld = newLIR3(cUnit, kThumb2Vldms, r3, fr0, regsLeft);
- //TUNING: loosen barrier
- ld->defMask = ENCODE_ALL;
- setMemRefType(ld, true /* isLoad */, kDalvikReg);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
- opRegRegImm(cUnit, kOpAdd, r3, rSP, 4 /* Method* */ + (3 * 4));
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
- MipsLIR* st = newLIR3(cUnit, kThumb2Vstms, r3, fr0, regsLeft);
- setMemRefType(st, false /* isLoad */, kDalvikReg);
- st->defMask = ENCODE_ALL;
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
- }
-
- callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
- dexIdx, methodIdx, skipThis);
-
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx);
- if (pcrLabel) {
- *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir);
- }
-#endif
- return callState;
-}
-
-// Debugging routine - if null target, branch to DebugMe
-STATIC void genShowTarget(CompilationUnit* cUnit)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- MipsLIR* branchOver = opCmpImmBranch(cUnit, kMipsCondNe, rLR, 0);
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pDebugMe), rLR);
- MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
- target->defMask = -1;
- branchOver->generic.target = (LIR*)target;
-#endif
-}
-
-STATIC void genThrowVerificationError(CompilationUnit* cUnit, MIR* mir)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode), rLR);
- loadConstant(cUnit, r0, mir->dalvikInsn.vA);
- loadConstant(cUnit, r1, mir->dalvikInsn.vB);
- callRuntimeHelper(cUnit, rLR);
-#endif
-}
-
-STATIC void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb,
- MIR* mir, RegLocation rlSrc1,
- RegLocation rlSrc2, MipsLIR* labelList)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- MipsConditionCode cond;
- rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
- rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
- opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
- Opcode opcode = mir->dalvikInsn.opcode;
- switch(opcode) {
- case OP_IF_EQ:
- cond = kMipsCondEq;
- break;
- case OP_IF_NE:
- cond = kMipsCondNe;
- break;
- case OP_IF_LT:
- cond = kMipsCondLt;
- break;
- case OP_IF_GE:
- cond = kMipsCondGe;
- break;
- case OP_IF_GT:
- cond = kMipsCondGt;
- break;
- case OP_IF_LE:
- cond = kMipsCondLe;
- break;
- default:
- cond = (MipsConditionCode)0;
- LOG(FATAL) << "Unexpected opcode " << (int)opcode;
- }
- genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
- genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
-#endif
-}
-
-STATIC void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb,
- MIR* mir, RegLocation rlSrc,
- MipsLIR* labelList)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- MipsConditionCode cond;
- rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
- Opcode opcode = mir->dalvikInsn.opcode;
- switch(opcode) {
- case OP_IF_EQZ:
- cond = kMipsCondEq;
- break;
- case OP_IF_NEZ:
- cond = kMipsCondNe;
- break;
- case OP_IF_LTZ:
- cond = kMipsCondLt;
- break;
- case OP_IF_GEZ:
- cond = kMipsCondGe;
- break;
- case OP_IF_GTZ:
- cond = kMipsCondGt;
- break;
- case OP_IF_LEZ:
- cond = kMipsCondLe;
- break;
- default:
- cond = (MipsConditionCode)0;
- LOG(FATAL) << "Unexpected opcode " << (int)opcode;
- }
- genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
- genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
-#endif
-}
-
-STATIC void genIntToLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
- RegLocation rlSrc)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- if (rlSrc.location == kLocPhysReg) {
- genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
- } else {
- loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
- }
- opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
- rlResult.lowReg, 31);
- storeValueWide(cUnit, rlDest, rlResult);
-#endif
-}
-
-STATIC void genIntNarrowing(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- OpKind op = kOpInvalid;
- switch(mir->dalvikInsn.opcode) {
- case OP_INT_TO_BYTE:
- op = kOp2Byte;
- break;
- case OP_INT_TO_SHORT:
- op = kOp2Short;
- break;
- case OP_INT_TO_CHAR:
- op = kOp2Char;
- break;
- default:
- LOG(ERROR) << "Bad int conversion type";
- }
- opRegReg(cUnit, op, rlResult.lowReg, rlSrc.lowReg);
- storeValue(cUnit, rlDest, rlResult);
-#endif
-}
-
-/*
- * If there are any ins passed in registers that have not been promoted
- * to a callee-save register, flush them to the frame. Perform intial
- * assignment of promoted arguments.
- */
-STATIC void flushIns(CompilationUnit* cUnit)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- if (cUnit->numIns == 0)
+ if (cUnit->numCoreSpills == 0) {
return;
- int firstArgReg = r1;
- int lastArgReg = r3;
- int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
- /*
- * Arguments passed in registers should be flushed
- * to their backing locations in the frame for now.
- * Also, we need to do initial assignment for promoted
- * arguments. NOTE: an older version of dx had an issue
- * in which it would reuse static method argument registers.
- * This could result in the same Dalvik virtual register
- * being promoted to both core and fp regs. In those
- * cases, copy argument to both. This will be uncommon
- * enough that it isn't worth attempting to optimize.
- */
- for (int i = 0; i < cUnit->numIns; i++) {
- PromotionMap vMap = cUnit->promotionMap[startVReg + i];
- if (i <= (lastArgReg - firstArgReg)) {
- // If arriving in register
- if (vMap.coreLocation == kLocPhysReg) {
- genRegCopy(cUnit, vMap.coreReg, firstArgReg + i);
- }
- if (vMap.fpLocation == kLocPhysReg) {
- genRegCopy(cUnit, vMap.fpReg, firstArgReg + i);
- }
- // Also put a copy in memory in case we're partially promoted
- storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- firstArgReg + i, kWord);
- } else {
- // If arriving in frame & promoted
- if (vMap.coreLocation == kLocPhysReg) {
- loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- vMap.coreReg);
- }
- if (vMap.fpLocation == kLocPhysReg) {
- loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- vMap.fpReg);
- }
+ }
+ uint32_t mask = cUnit->coreSpillMask;
+ int offset = cUnit->frameSize;
+ for (int reg = 0; mask; mask >>= 1, reg++) {
+ if (mask & 0x1) {
+ offset -= 4;
+ loadWordDisp(cUnit, rSP, offset, reg);
}
}
-#endif
+ opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize);
}
-STATIC void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
+void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
/*
- * On entry, r0, r1, r2 & r3 are live. Let the register allocation
- * mechanism know so it doesn't try to use any of them when
+ * On entry, rARG0, rARG1, rARG2 & rARG3 are live. Let the register
+ * allocation mechanism know so it doesn't try to use any of them when
* expanding the frame or flushing. This leaves the utility
* code with a single temp: r12. This should be enough.
*/
- oatLockTemp(cUnit, r0);
- oatLockTemp(cUnit, r1);
- oatLockTemp(cUnit, r2);
- oatLockTemp(cUnit, r3);
+ oatLockTemp(cUnit, rARG0);
+ oatLockTemp(cUnit, rARG1);
+ oatLockTemp(cUnit, rARG2);
+ oatLockTemp(cUnit, rARG3);
/*
* We can safely skip the stack overflow check if we're
@@ -1121,33 +93,28 @@ STATIC void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
((size_t)cUnit->frameSize <
Thread::kStackOverflowReservedBytes));
newLIR0(cUnit, kPseudoMethodEntry);
+ int checkReg = oatAllocTemp(cUnit);
+ int newSP = oatAllocTemp(cUnit);
if (!skipOverflowCheck) {
/* Load stack limit */
loadWordDisp(cUnit, rSELF,
- Thread::StackEndOffset().Int32Value(), r12);
+ Thread::StackEndOffset().Int32Value(), checkReg);
}
/* Spill core callee saves */
- newLIR1(cUnit, kThumb2Push, cUnit->coreSpillMask);
- /* Need to spill any FP regs? */
- if (cUnit->numFPSpills) {
- /*
- * NOTE: fp spills are a little different from core spills in that
- * they are pushed as a contiguous block. When promoting from
- * the fp set, we must allocate all singles from s16..highest-promoted
- */
- newLIR1(cUnit, kThumb2VPushCS, cUnit->numFPSpills);
- }
+ spillCoreRegs(cUnit);
+ /* NOTE: promotion of FP regs currently unsupported, thus no FP spill */
+ DCHECK_EQ(cUnit->numFPSpills, 0);
if (!skipOverflowCheck) {
- opRegRegImm(cUnit, kOpSub, rLR, rSP,
+ opRegRegImm(cUnit, kOpSub, newSP, rSP,
cUnit->frameSize - (spillCount * 4));
- genRegRegCheck(cUnit, kMipsCondCc, rLR, r12, NULL,
- kMipsThrowStackOverflow);
- genRegCopy(cUnit, rSP, rLR); // Establish stack
+ genRegRegCheck(cUnit, kCondCc, newSP, checkReg, NULL,
+ kThrowStackOverflow);
+ genRegCopy(cUnit, rSP, newSP); // Establish stack
} else {
opRegImm(cUnit, kOpSub, rSP,
cUnit->frameSize - (spillCount * 4));
}
- storeBaseDisp(cUnit, rSP, 0, r0, kWord);
+ storeBaseDisp(cUnit, rSP, 0, rARG0, kWord);
flushIns(cUnit);
if (cUnit->genDebugger) {
@@ -1157,46 +124,28 @@ STATIC void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY);
}
- oatFreeTemp(cUnit, r0);
- oatFreeTemp(cUnit, r1);
- oatFreeTemp(cUnit, r2);
- oatFreeTemp(cUnit, r3);
-#endif
+ oatFreeTemp(cUnit, rARG0);
+ oatFreeTemp(cUnit, rARG1);
+ oatFreeTemp(cUnit, rARG2);
+ oatFreeTemp(cUnit, rARG3);
}
-STATIC void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)
+void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)
{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
/*
- * In the exit path, r0/r1 are live - make sure they aren't
+ * In the exit path, rRET0/rRET1 are live - make sure they aren't
* allocated by the register utilities as temps.
*/
- oatLockTemp(cUnit, r0);
- oatLockTemp(cUnit, r1);
+ oatLockTemp(cUnit, rRET0);
+ 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);
}
- opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize - (spillCount * 4));
- /* Need to restore any FP callee saves? */
- if (cUnit->numFPSpills) {
- newLIR1(cUnit, kThumb2VPopCS, cUnit->numFPSpills);
- }
- if (cUnit->coreSpillMask & (1 << rLR)) {
- /* Unspill rLR to rPC */
- cUnit->coreSpillMask &= ~(1 << rLR);
- cUnit->coreSpillMask |= (1 << rPC);
- }
- newLIR1(cUnit, kThumb2Pop, cUnit->coreSpillMask);
- if (!(cUnit->coreSpillMask & (1 << rPC))) {
- /* We didn't pop to rPC, so must do a bv rLR */
- newLIR1(cUnit, kThumbBx, rLR);
- }
-#endif
+ unSpillCoreRegs(cUnit);
+ opReg(cUnit, kOpBx, rLINK);
}
/*
@@ -1206,18 +155,15 @@ STATIC void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)
*/
void removeRedundantBranches(CompilationUnit* cUnit)
{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- MipsLIR* thisLIR;
+ LIR* thisLIR;
- for (thisLIR = (MipsLIR*) cUnit->firstLIRInsn;
- thisLIR != (MipsLIR*) cUnit->lastLIRInsn;
+ for (thisLIR = (LIR*) cUnit->firstLIRInsn;
+ thisLIR != (LIR*) cUnit->lastLIRInsn;
thisLIR = NEXT_LIR(thisLIR)) {
/* Branch to the next instruction */
- if ((thisLIR->opcode == kThumbBUncond) ||
- (thisLIR->opcode == kThumb2BUncond)) {
- MipsLIR* nextLIR = thisLIR;
+ if (thisLIR->opcode == kMipsB) {
+ LIR* nextLIR = thisLIR;
while (true) {
nextLIR = NEXT_LIR(nextLIR);
@@ -1225,7 +171,7 @@ void removeRedundantBranches(CompilationUnit* cUnit)
/*
* Is the branch target the next instruction?
*/
- if (nextLIR == (MipsLIR*) thisLIR->generic.target) {
+ if (nextLIR == (LIR*) thisLIR->target) {
thisLIR->flags.isNop = true;
break;
}
@@ -1236,116 +182,13 @@ void removeRedundantBranches(CompilationUnit* cUnit)
* might be the last real instruction.
*/
if (!isPseudoOpcode(nextLIR->opcode) ||
- (nextLIR = (MipsLIR*) cUnit->lastLIRInsn))
+ (nextLIR = (LIR*) cUnit->lastLIRInsn))
break;
}
}
}
-#endif
}
-STATIC void handleSuspendLaunchpads(CompilationUnit *cUnit)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- MipsLIR** suspendLabel =
- (MipsLIR **) cUnit->suspendLaunchpads.elemList;
- int numElems = cUnit->suspendLaunchpads.numUsed;
-
- for (int i = 0; i < numElems; i++) {
- /* TUNING: move suspend count load into helper */
- MipsLIR* lab = suspendLabel[i];
- MipsLIR* resumeLab = (MipsLIR*)lab->operands[0];
- cUnit->currentDalvikOffset = lab->operands[1];
- oatAppendLIR(cUnit, (LIR *)lab);
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pTestSuspendFromCode), rLR);
- if (!cUnit->genDebugger) {
- // use rSUSPEND for suspend count
- loadWordDisp(cUnit, rSELF,
- Thread::SuspendCountOffset().Int32Value(), rSUSPEND);
- }
- opReg(cUnit, kOpBlx, rLR);
- if ( cUnit->genDebugger) {
- // use rSUSPEND for update debugger
- loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode), rSUSPEND);
- }
- genUnconditionalBranch(cUnit, resumeLab);
- }
-#endif
-}
-
-STATIC void handleThrowLaunchpads(CompilationUnit *cUnit)
-{
- UNIMPLEMENTED(FATAL) << "Needs mips version";
-#if 0
- MipsLIR** throwLabel =
- (MipsLIR **) cUnit->throwLaunchpads.elemList;
- int numElems = cUnit->throwLaunchpads.numUsed;
- int i;
-
- for (i = 0; i < numElems; i++) {
- MipsLIR* lab = throwLabel[i];
- cUnit->currentDalvikOffset = lab->operands[1];
- oatAppendLIR(cUnit, (LIR *)lab);
- int funcOffset = 0;
- int v1 = lab->operands[2];
- int v2 = lab->operands[3];
- switch(lab->operands[0]) {
- case kMipsThrowNullPointer:
- funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode);
- break;
- case kMipsThrowArrayBounds:
- if (v2 != r0) {
- genRegCopy(cUnit, r0, v1);
- genRegCopy(cUnit, r1, v2);
- } else {
- if (v1 == r1) {
- genRegCopy(cUnit, r12, v1);
- genRegCopy(cUnit, r1, v2);
- genRegCopy(cUnit, r0, r12);
- } else {
- genRegCopy(cUnit, r1, v2);
- genRegCopy(cUnit, r0, v1);
- }
- }
- funcOffset = OFFSETOF_MEMBER(Thread, pThrowArrayBoundsFromCode);
- break;
- case kMipsThrowDivZero:
- funcOffset = OFFSETOF_MEMBER(Thread, pThrowDivZeroFromCode);
- break;
- case kMipsThrowVerificationError:
- loadConstant(cUnit, r0, v1);
- loadConstant(cUnit, r1, v2);
- funcOffset =
- OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode);
- break;
- case kMipsThrowNegArraySize:
- genRegCopy(cUnit, r0, v1);
- funcOffset =
- OFFSETOF_MEMBER(Thread, pThrowNegArraySizeFromCode);
- break;
- case kMipsThrowNoSuchMethod:
- genRegCopy(cUnit, r0, v1);
- funcOffset =
- OFFSETOF_MEMBER(Thread, pThrowNoSuchMethodFromCode);
- break;
- case kMipsThrowStackOverflow:
- funcOffset =
- OFFSETOF_MEMBER(Thread, pThrowStackOverflowFromCode);
- // Restore stack alignment
- opRegImm(cUnit, kOpAdd, rSP,
- (cUnit->numCoreSpills + cUnit->numFPSpills) * 4);
- break;
- default:
- LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0];
- }
- loadWordDisp(cUnit, rSELF, funcOffset, rLR);
- callRuntimeHelper(cUnit, rLR);
- }
-#endif
-}
/* Common initialization routine for an architecture family */
bool oatArchInit()
@@ -1363,10 +206,4 @@ bool oatArchInit()
return oatArchVariantInit();
}
-/* Needed by the Assembler */
-void oatSetupResourceMasks(MipsLIR* lir)
-{
- setupResourceMasks(lir);
-}
-
} // namespace art
diff --git a/src/compiler/codegen/mips/ArchUtility.cc b/src/compiler/codegen/mips/ArchUtility.cc
index 2e8d4170d5..7f7aeb3b90 100644
--- a/src/compiler/codegen/mips/ArchUtility.cc
+++ b/src/compiler/codegen/mips/ArchUtility.cc
@@ -22,6 +22,33 @@
namespace art {
+MipsConditionCode oatMipsConditionEncoding(ConditionCode code)
+{
+ MipsConditionCode res;
+ switch(code) {
+ case kCondEq: res = kMipsCondEq; break;
+ case kCondNe: res = kMipsCondNe; break;
+ case kCondCs: res = kMipsCondCs; break;
+ case kCondCc: res = kMipsCondCc; break;
+ case kCondMi: res = kMipsCondMi; break;
+ case kCondPl: res = kMipsCondPl; break;
+ case kCondVs: res = kMipsCondVs; break;
+ case kCondVc: res = kMipsCondVc; break;
+ case kCondHi: res = kMipsCondHi; break;
+ case kCondLs: res = kMipsCondLs; break;
+ case kCondGe: res = kMipsCondGe; break;
+ case kCondLt: res = kMipsCondLt; break;
+ case kCondGt: res = kMipsCondGt; break;
+ case kCondLe: res = kMipsCondLe; break;
+ case kCondAl: res = kMipsCondAl; break;
+ case kCondNv: res = kMipsCondNv; break;
+ default:
+ LOG(FATAL) << "Bad condition code" << (int)code;
+ res = (MipsConditionCode)0; // Quiet gcc
+ }
+ return res;
+}
+
/* For dumping instructions */
#define MIPS_REG_COUNT 32
static const char *mipsRegName[MIPS_REG_COUNT] = {
@@ -35,7 +62,7 @@ static const char *mipsRegName[MIPS_REG_COUNT] = {
* Interpret a format string and build a string no longer than size
* See format key in Assemble.c.
*/
-STATIC std::string buildInsnString(const char *fmt, MipsLIR *lir, unsigned char* baseAddr)
+std::string buildInsnString(const char *fmt, LIR *lir, unsigned char* baseAddr)
{
std::string buf;
int i;
@@ -118,9 +145,9 @@ STATIC std::string buildInsnString(const char *fmt, MipsLIR *lir, unsigned char*
break;
case 't':
sprintf(tbuf,"0x%08x (L%p)",
- (int) baseAddr + lir->generic.offset + 4 +
+ (int) baseAddr + lir->offset + 4 +
(operand << 2),
- lir->generic.target);
+ lir->target);
break;
case 'T':
sprintf(tbuf,"0x%08x",
@@ -130,7 +157,7 @@ STATIC std::string buildInsnString(const char *fmt, MipsLIR *lir, unsigned char*
int offset_1 = lir->operands[0];
int offset_2 = NEXT_LIR(lir)->operands[0];
intptr_t target =
- ((((intptr_t) baseAddr + lir->generic.offset + 4) &
+ ((((intptr_t) baseAddr + lir->offset + 4) &
~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
0xfffffffc;
sprintf(tbuf, "%p", (void *) target);
@@ -163,7 +190,7 @@ void oatDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
{
char buf[256];
buf[0] = 0;
- MipsLIR *mipsLIR = (MipsLIR *) lir;
+ LIR *mipsLIR = (LIR *) lir;
if (mask == ENCODE_ALL) {
strcpy(buf, "all");
@@ -205,180 +232,4 @@ void oatDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
}
}
-/*
- * Debugging macros
- */
-#define DUMP_RESOURCE_MASK(X)
-#define DUMP_SSA_REP(X)
-
-/* Pretty-print a LIR instruction */
-void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
-{
- MipsLIR* lir = (MipsLIR*) arg;
- int offset = lir->generic.offset;
- int dest = lir->operands[0];
- const bool dumpNop = false;
-
- /* Handle pseudo-ops individually, and all regular insns as a group */
- switch(lir->opcode) {
- case kPseudoMethodEntry:
- LOG(INFO) << "-------- method entry " <<
- PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
- break;
- case kPseudoMethodExit:
- LOG(INFO) << "-------- Method_Exit";
- break;
- case kPseudoBarrier:
- LOG(INFO) << "-------- BARRIER";
- break;
- case kPseudoExtended:
- LOG(INFO) << "-------- " << (char* ) dest;
- break;
- case kPseudoSSARep:
- DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
- break;
- case kPseudoEntryBlock:
- LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
- break;
- case kPseudoDalvikByteCodeBoundary:
- LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
- lir->generic.dalvikOffset << " @ " << (char* )lir->operands[0];
- break;
- case kPseudoExitBlock:
- LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
- break;
- case kPseudoPseudoAlign4:
- LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
- offset << "): .align4";
- break;
- case kPseudoEHBlockLabel:
- LOG(INFO) << "Exception_Handling:";
- break;
- case kPseudoTargetLabel:
- case kPseudoNormalBlockLabel:
- LOG(INFO) << "L" << (intptr_t)lir << ":";
- break;
- case kPseudoThrowTarget:
- LOG(INFO) << "LT" << (intptr_t)lir << ":";
- break;
- case kPseudoSuspendTarget:
- LOG(INFO) << "LS" << (intptr_t)lir << ":";
- break;
- case kPseudoCaseLabel:
- LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
- std::hex << lir->operands[0] << "|" << std::dec <<
- lir->operands[0];
- break;
- default:
- if (lir->flags.isNop && !dumpNop) {
- break;
- } else {
- std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr));
- std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr));
- LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset,
- op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : "");
- }
- break;
- }
-
- if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
- DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
- lir->useMask, "use"));
- }
- if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
- DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
- lir->defMask, "def"));
- }
-}
-
-void oatDumpPromotionMap(CompilationUnit *cUnit)
-{
- for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
- PromotionMap vRegMap = cUnit->promotionMap[i];
- char buf[100];
- if (vRegMap.fpLocation == kLocPhysReg) {
- snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK);
- } else {
- buf[0] = 0;
- }
- char buf2[100];
- snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
- vRegMap.coreLocation == kLocPhysReg ?
- "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
- vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
- LOG(INFO) << buf2;
- }
-}
-
-void oatDumpFullPromotionMap(CompilationUnit *cUnit)
-{
- for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
- PromotionMap vRegMap = cUnit->promotionMap[i];
- LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation <<
- ", CR:" << (int)vRegMap.coreReg << ", FL:" <<
- (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg <<
- ", - " << (int)vRegMap.firstInPair;
- }
-}
-
-/* Dump instructions and constant pool contents */
-void oatCodegenDump(CompilationUnit* cUnit)
-{
- LOG(INFO) << "/*";
- LOG(INFO) << "Dumping LIR insns for "
- << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
- LIR* lirInsn;
- MipsLIR* mipsLIR;
- int insnsSize = cUnit->insnsSize;
-
- LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
- LOG(INFO) << "Ins : " << cUnit->numIns;
- LOG(INFO) << "Outs : " << cUnit->numOuts;
- LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
- LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
- LOG(INFO) << "Padding : " << cUnit->numPadding;
- LOG(INFO) << "Frame size : " << cUnit->frameSize;
- LOG(INFO) << "Start of ins : " << cUnit->insOffset;
- LOG(INFO) << "Start of regs : " << cUnit->regsOffset;
- LOG(INFO) << "code size is " << cUnit->totalSize <<
- " bytes, Dalvik size is " << insnsSize * 2;
- LOG(INFO) << "expansion factor: " <<
- (float)cUnit->totalSize / (float)(insnsSize * 2);
- oatDumpPromotionMap(cUnit);
- for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
- oatDumpLIRInsn(cUnit, lirInsn, 0);
- }
- for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
- mipsLIR = (MipsLIR*) lirInsn;
- LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
- mipsLIR->generic.offset, mipsLIR->generic.offset,
- ((CallsiteInfo *) mipsLIR->operands[0])->classDescriptor);
- }
- for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
- mipsLIR = (MipsLIR*) lirInsn;
- LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
- mipsLIR->generic.offset, mipsLIR->generic.offset, mipsLIR->operands[0]);
- }
-
- const DexFile::MethodId& method_id =
- cUnit->dex_file->GetMethodId(cUnit->method_idx);
- std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
- std::string name(cUnit->dex_file->GetMethodName(method_id));
- std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
-
- // Dump mapping table
- if (cUnit->mappingTable.size() > 0) {
- std::string line(StringPrintf("\n MappingTable %s%s_%s_mappingTable[%zu] = {",
- descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size()));
- std::replace(line.begin(), line.end(), ';', '_');
- LOG(INFO) << line;
- for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
- line = StringPrintf(" {0x%08x, 0x%04x},",
- cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
- LOG(INFO) << line;
- }
- LOG(INFO) <<" };\n\n";
- }
-}
-
} // namespace art
diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc
index 5b6e6ed771..cb355c0b31 100644
--- a/src/compiler/codegen/mips/Assemble.cc
+++ b/src/compiler/codegen/mips/Assemble.cc
@@ -75,7 +75,7 @@ namespace art {
*
* [!] escape. To insert "!", use "!!"
*/
-/* NOTE: must be kept in sync with enum MipsOpcode from MipsLIR.h */
+/* NOTE: must be kept in sync with enum MipsOpcode from LIR.h */
MipsEncodingMap EncodingMap[kMipsLast] = {
ENCODING_MAP(kMips32BitData, 0x00000000,
kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
@@ -406,12 +406,10 @@ MipsEncodingMap EncodingMap[kMipsLast] = {
AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
intptr_t startAddr)
{
- UNIMPLEMENTED(FATAL) << "Rework for art code buffer";
-#if 0
- int *bufferAddr = (int *) cUnit->codeBuffer;
- MipsLIR *lir;
+ LIR *lir;
+ AssemblerStatus res = kSuccess; // Assume success
- for (lir = (MipsLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
+ for (lir = (LIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
if (lir->opcode < 0) {
continue;
}
@@ -422,43 +420,43 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
}
if (lir->opcode == kMipsB || lir->opcode == kMipsBal) {
- MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
- intptr_t pc = lir->generic.offset + 4;
- intptr_t target = targetLIR->generic.offset;
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
int delta = target - pc;
if (delta & 0x3) {
LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
}
if (delta > 131068 || delta < -131069) {
- LOG(FATAL) << "Unconditional branch out of range: " << delta;
+ UNIMPLEMENTED(FATAL) << "B out of range, need long sequence: " << delta;
}
lir->operands[0] = delta >> 2;
} else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) {
- MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
- intptr_t pc = lir->generic.offset + 4;
- intptr_t target = targetLIR->generic.offset;
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
int delta = target - pc;
if (delta & 0x3) {
LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
}
if (delta > 131068 || delta < -131069) {
- LOG(FATAL) << "Conditional branch out of range: " << delta;
+ UNIMPLEMENTED(FATAL) << "B[eq|ne]z needs long sequence: " << delta;
}
lir->operands[1] = delta >> 2;
} else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) {
- MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
- intptr_t pc = lir->generic.offset + 4;
- intptr_t target = targetLIR->generic.offset;
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
int delta = target - pc;
if (delta & 0x3) {
LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
}
if (delta > 131068 || delta < -131069) {
- LOG(FATAL) << "Conditional branch out of range: " << delta;
+ UNIMPLEMENTED(FATAL) << "B[eq|ne] needs long sequence: " << delta;
}
lir->operands[2] = delta >> 2;
} else if (lir->opcode == kMipsJal) {
- intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3;
+ intptr_t curPC = (startAddr + lir->offset + 4) & ~3;
intptr_t target = lir->operands[0];
/* ensure PC-region branch can be used */
DCHECK_EQ((curPC & 0xF0000000), (target & 0xF0000000));
@@ -467,16 +465,24 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
}
lir->operands[0] = target >> 2;
} else if (lir->opcode == kMipsLahi) { /* load address hi (via lui) */
- MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
- intptr_t target = startAddr + targetLIR->generic.offset;
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t target = startAddr + targetLIR->offset;
lir->operands[1] = target >> 16;
} else if (lir->opcode == kMipsLalo) { /* load address lo (via ori) */
- MipsLIR *targetLIR = (MipsLIR *) lir->generic.target;
- intptr_t target = startAddr + targetLIR->generic.offset;
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t target = startAddr + targetLIR->offset;
lir->operands[2] = lir->operands[2] + target;
}
- MipsEncodingMap *encoder = &EncodingMap[lir->opcode];
+ /*
+ * If one of the pc-relative instructions expanded we'll have
+ * to make another pass. Don't bother to fully assemble the
+ * instruction.
+ */
+ if (res != kSuccess) {
+ continue;
+ }
+ const MipsEncodingMap *encoder = &EncodingMap[lir->opcode];
u4 bits = encoder->skeleton;
int i;
for (i = 0; i < 4; i++) {
@@ -497,7 +503,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
break;
case kFmtDfp: {
DCHECK(DOUBLEREG(operand));
- DCHECK_EQ((operand & 0x1), 0);
+ DCHECK((operand & 0x1) == 0);
value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &
((1 << (encoder->fieldLoc[i].end + 1)) - 1);
bits |= value;
@@ -511,14 +517,15 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
break;
default:
LOG(FATAL) << "Bad encoder format: "
- << encoder->fieldLoc[i].kind;
+ << (int)encoder->fieldLoc[i].kind;
}
}
DCHECK_EQ(encoder->size, 2);
- *bufferAddr++ = bits;
+ // FIXME: need multi-endian handling here
+ cUnit->codeBuffer.push_back((bits >> 16) & 0xffff);
+ cUnit->codeBuffer.push_back(bits & 0xffff);
}
-#endif
- return kSuccess;
+ return res;
}
/*
@@ -528,13 +535,13 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
*/
int oatAssignInsnOffsets(CompilationUnit* cUnit)
{
- MipsLIR* mipsLIR;
+ LIR* mipsLIR;
int offset = 0;
- for (mipsLIR = (MipsLIR *) cUnit->firstLIRInsn;
- mipsLIR;
- mipsLIR = NEXT_LIR(mipsLIR)) {
- mipsLIR->generic.offset = offset;
+ for (mipsLIR = (LIR *) cUnit->firstLIRInsn;
+ mipsLIR;
+ mipsLIR = NEXT_LIR(mipsLIR)) {
+ mipsLIR->offset = offset;
if (mipsLIR->opcode >= 0) {
if (!mipsLIR->flags.isNop) {
mipsLIR->flags.size = EncodingMap[mipsLIR->opcode].size * 2;
diff --git a/src/compiler/codegen/mips/Codegen.h b/src/compiler/codegen/mips/Codegen.h
index b350dae035..355693c678 100644
--- a/src/compiler/codegen/mips/Codegen.h
+++ b/src/compiler/codegen/mips/Codegen.h
@@ -27,30 +27,72 @@
namespace art {
#if defined(_CODEGEN_C)
-/*
- * loadConstant() sometimes needs to add a small imm to a pre-existing constant
- */
-STATIC MipsLIR *opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
- int value);
-STATIC MipsLIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
- int rSrc2);
+LIR *opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value);
+LIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2);
-/* Forward decalraton the portable versions due to circular dependency */
-STATIC bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
+/* Forward declaraton the portable versions due to circular dependency */
+bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest, RegLocation rlSrc1,
RegLocation rlSrc2);
-STATIC bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
+bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest, RegLocation rlSrc1,
RegLocation rlSrc2);
-STATIC bool genConversionPortable(CompilationUnit* cUnit, MIR* mir);
+bool genConversionPortable(CompilationUnit* cUnit, MIR* mir);
+
+MipsConditionCode oatMipsConditionEncoding(ConditionCode code);
+
+int loadHelper(CompilationUnit* cUnit, int offset);
+LIR* callRuntimeHelper(CompilationUnit* cUnit, int reg);
+RegLocation getRetLoc(CompilationUnit* cUnit);
+LIR* loadConstant(CompilationUnit* cUnit, int reg, int immVal);
+void genRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
+ int srcLo, int srcHi);
+LIR* genRegCopy(CompilationUnit* cUnit, int rDest, int rSrc);
+LIR* genCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
+ int checkValue);
+void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
+ RegLocation rlFree);
+
+
+/*
+ * Return most flexible allowed register class based on size.
+ * Bug: 2813841
+ * Must use a core register for data types narrower than word (due
+ * to possible unaligned load/store.
+ */
+inline RegisterClass oatRegClassBySize(OpSize size)
+{
+ return (size == kUnsignedHalf ||
+ size == kSignedHalf ||
+ size == kUnsignedByte ||
+ size == kSignedByte ) ? kCoreReg : kAnyReg;
+}
+
+/*
+ * Construct an s4 from two consecutive half-words of switch data.
+ * This needs to check endianness because the DEX optimizer only swaps
+ * half-words in instruction stream.
+ *
+ * "switchData" must be 32-bit aligned.
+ */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+inline s4 s4FromSwitchData(const void* switchData) {
+ return *(s4*) switchData;
+}
+#else
+inline s4 s4FromSwitchData(const void* switchData) {
+ u2* data = switchData;
+ return data[0] | (((s4) data[1]) << 16);
+}
+#endif
#endif
-extern void oatSetupResourceMasks(MipsLIR* lir);
+extern void oatSetupResourceMasks(LIR* lir);
-extern MipsLIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest,
+extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest,
int rSrc);
} // namespace art
diff --git a/src/compiler/codegen/mips/CodegenCommon.cc b/src/compiler/codegen/mips/CodegenCommon.cc
deleted file mode 100644
index 8dbb9a3506..0000000000
--- a/src/compiler/codegen/mips/CodegenCommon.cc
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace art {
-
-/*
- * This file contains codegen and support common to all supported
- * Mips variants. It is included by:
- *
- * Codegen-$(TARGET_ARCH_VARIANT).c
- *
- * which combines this common code with specific support found in the
- * applicable directory below this one.
- */
-
-static void setMemRefType(MipsLIR *lir, bool isLoad, int memType)
-{
- /* MIPSTODO simplify setMemRefType() */
- u8 *maskPtr;
- u8 mask = ENCODE_MEM;;
- DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
-
- if (isLoad) {
- maskPtr = &lir->useMask;
- } else {
- maskPtr = &lir->defMask;
- }
- /* Clear out the memref flags */
- *maskPtr &= ~mask;
- /* ..and then add back the one we need */
- switch(memType) {
- case kLiteral:
- DCHECK(isLoad);
- *maskPtr |= ENCODE_LITERAL;
- break;
- case kDalvikReg:
- *maskPtr |= ENCODE_DALVIK_REG;
- break;
- case kHeapRef:
- *maskPtr |= ENCODE_HEAP_REF;
- break;
- case kMustNotAlias:
- /* Currently only loads can be marked as kMustNotAlias */
- DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
- *maskPtr |= ENCODE_MUST_NOT_ALIAS;
- break;
- default:
- LOG(FATAL) << "Oat: invalid memref kind - " << memType;
- }
-}
-
-/*
- * Mark load/store instructions that access Dalvik registers through rFP +
- * offset.
- */
-STATIC void annotateDalvikRegAccess(MipsLIR *lir, int regId, bool isLoad)
-{
- /* MIPSTODO simplify annotateDalvikRegAccess() */
- setMemRefType(lir, isLoad, kDalvikReg);
-
- /*
- * Store the Dalvik register id in aliasInfo. Mark he MSB if it is a 64-bit
- * access.
- */
- lir->aliasInfo = regId;
- if (DOUBLEREG(lir->operands[0])) {
- lir->aliasInfo |= 0x80000000;
- }
-}
-
-/*
- * Decode the register id
- */
-STATIC inline u8 getRegMaskCommon(int reg)
-{
- u8 seed;
- int shift;
- int regId = reg & 0x1f;
-
- /*
- * Each double register is equal to a pair of single-precision FP registers
- */
- if (!DOUBLEREG(reg)) {
- seed = 1;
- } else {
- DCHECK_EQ((regId & 1), 0); /* double registers must be even */
- seed = 3;
- }
-
- if (FPREG(reg)) {
- DCHECK_LT(regId, 16); /* only 16 fp regs */
- shift = kFPReg0;
- } else if (EXTRAREG(reg)) {
- DCHECK_LT(regId, 3); /* only 3 extra regs */
- shift = kFPRegEnd;
- } else {
- shift = 0;
- }
-
- /* Expand the double register id into single offset */
- shift += regId;
- return (seed << shift);
-}
-
-/*
- * Mark the corresponding bit(s).
- */
-STATIC inline void setupRegMask(u8 *mask, int reg)
-{
- *mask |= getRegMaskCommon(reg);
-}
-
-/*
- * Set up the proper fields in the resource mask
- */
-STATIC void setupResourceMasks(MipsLIR *lir)
-{
- /* MIPSTODO simplify setupResourceMasks() */
- int opcode = lir->opcode;
- int flags;
-
- if (opcode <= 0) {
- lir->useMask = lir->defMask = 0;
- return;
- }
-
- flags = EncodingMap[lir->opcode].flags;
-
- // TODO: do we need this for MIPS? if so, add to inst table defs
-#if 0
- if (flags & NEEDS_FIXUP) {
- lir->flags.pcRelFixup = true;
- }
-#endif
-
- /* Set up the mask for resources that are updated */
- if (flags & (IS_LOAD | IS_STORE)) {
- /* Default to heap - will catch specialized classes later */
- setMemRefType(lir, flags & IS_LOAD, kHeapRef);
- }
-
- /*
- * Conservatively assume the branch here will call out a function that in
- * turn will trash everything.
- */
- if (flags & IS_BRANCH) {
- lir->defMask = lir->useMask = ENCODE_ALL;
- return;
- }
-
- if (flags & REG_DEF0) {
- setupRegMask(&lir->defMask, lir->operands[0]);
- }
-
- if (flags & REG_DEF1) {
- setupRegMask(&lir->defMask, lir->operands[1]);
- }
-
- if (flags & REG_DEF_SP) {
- lir->defMask |= ENCODE_REG_SP;
- }
-
- if (flags & REG_DEF_LR) {
- lir->defMask |= ENCODE_REG_LR;
- }
-
- 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 & SETS_CCODES) {
- lir->defMask |= ENCODE_CCODE;
- }
-
- // TODO: needed for MIPS?
- /* Conservatively treat the IT block */
- if (flags & IS_IT) {
- lir->defMask = ENCODE_ALL;
- }
-
- 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]);
- }
- }
- }
-
- if (flags & REG_USE_PC) {
- lir->useMask |= ENCODE_REG_PC;
- }
-
- if (flags & REG_USE_SP) {
- lir->useMask |= ENCODE_REG_SP;
- }
-
- 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 & USES_CCODES) {
- lir->useMask |= ENCODE_CCODE;
- }
-}
-
-/*
- * The following are building blocks to construct low-level IRs with 0 - 4
- * operands.
- */
-MipsLIR *newLIR0(CompilationUnit *cUnit, MipsOpCode opcode)
-{
- MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
- insn->opcode = opcode;
- setupResourceMasks(insn);
- insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
- oatAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-MipsLIR *newLIR1(CompilationUnit *cUnit, MipsOpCode opcode,
- int dest)
-{
- MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- setupResourceMasks(insn);
- insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
- oatAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-MipsLIR *newLIR2(CompilationUnit *cUnit, MipsOpCode opcode,
- int dest, int src1)
-{
- MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- DCHECK(isPseudoOpcode(opcode) ||
- (EncodingMap[opcode].flags & IS_BINARY_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- insn->operands[1] = src1;
- setupResourceMasks(insn);
- insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
- oatAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-MipsLIR *newLIR3(CompilationUnit *cUnit, MipsOpCode opcode,
- int dest, int src1, int src2)
-{
- MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- if (!(EncodingMap[opcode].flags & IS_TERTIARY_OP)) {
- LOG(FATAL) << "Bad LIR3: " << EncodingMap[opcode].name;
- }
- DCHECK(isPseudoOpcode(opcode) ||
- (EncodingMap[opcode].flags & IS_TERTIARY_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- insn->operands[1] = src1;
- insn->operands[2] = src2;
- setupResourceMasks(insn);
- insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
- oatAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-MipsLIR *newLIR4(CompilationUnit *cUnit, MipsOpCode opcode,
- int dest, int src1, int src2, int info)
-{
- MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- DCHECK(isPseudoOpcode(opcode) ||
- (EncodingMap[opcode].flags & IS_QUAD_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- insn->operands[1] = src1;
- insn->operands[2] = src2;
- insn->operands[3] = info;
- setupResourceMasks(insn);
- insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
- oatAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-/*
- * Generate an kPseudoBarrier marker to indicate the boundary of special
- * blocks.
- */
-static void genBarrier(CompilationUnit *cUnit)
-{
- MipsLIR *barrier = newLIR0(cUnit, kPseudoBarrier);
- /* Mark all resources as being clobbered */
- barrier->defMask = -1;
-}
-
-} // namespace art
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index 7eb2a1ae68..acbac7f6d9 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -16,42 +16,8 @@
namespace art {
-extern void oatFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
- int reg1, int reg2);
-extern void oatFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg);
-
-/* First, flush any registers associated with this value */
-void loadValueAddress(CompilationUnit *cUnit, RegLocation rlSrc,
- int rDest)
-{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
-#if 0
- rlSrc = rlSrc.wide ? oatUpdateLocWide(cUnit, rlSrc) :
- oatUpdateLoc(cUnit, rlSrc);
- if (rlSrc.location == kLocPhysReg) {
- if (rlSrc.wide) {
- oatFlushRegWideForV5TEVFP(cUnit, rlSrc.lowReg,
- rlSrc.highReg);
- } else {
- oatFlushRegForV5TEVFP(cUnit, rlSrc.lowReg);
- }
- }
- opRegRegImm(cUnit, kOpAdd, rDest, rFP,
- oatS2VReg(cUnit, rlSrc.sRegLow) << 2);
-#endif
-}
-
-/*
- * TUNING: On some implementations, it is quicker to pass addresses
- * to the handlers rather than load the operands into core registers
- * and then move the values to FP regs in the handlers. Other implementations
- * may prefer passing data in registers (and the latter approach would
- * yeild cleaner register handling - avoiding the requirement that operands
- * be flushed to memory prior to the call).
- */
-static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2)
+bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
+ RegLocation rlSrc1, RegLocation rlSrc2)
{
#ifdef __mips_hard_float
int op = kMipsNop;
@@ -89,60 +55,14 @@ static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,
rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
- newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
+ newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg,
+ rlSrc2.lowReg);
storeValue(cUnit, rlDest, rlResult);
return false;
#else
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+ UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation";
return false;
-#if 0
- TemplateOpcode opcode;
-
- /*
- * Don't attempt to optimize register usage since these opcodes call out to
- * the handlers.
- */
- switch (mir->dalvikInsn.opcode) {
- case OP_ADD_FLOAT_2ADDR:
- case OP_ADD_FLOAT:
- opcode = TEMPLATE_ADD_FLOAT_VFP;
- break;
- case OP_SUB_FLOAT_2ADDR:
- case OP_SUB_FLOAT:
- opcode = TEMPLATE_SUB_FLOAT_VFP;
- break;
- case OP_DIV_FLOAT_2ADDR:
- case OP_DIV_FLOAT:
- opcode = TEMPLATE_DIV_FLOAT_VFP;
- break;
- case OP_MUL_FLOAT_2ADDR:
- case OP_MUL_FLOAT:
- opcode = TEMPLATE_MUL_FLOAT_VFP;
- break;
- case OP_REM_FLOAT_2ADDR:
- case OP_REM_FLOAT:
- case OP_NEG_FLOAT: {
- return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2);
- }
- default:
- return true;
- }
- loadValueAddress(cUnit, rlDest, r_A0);
- oatClobber(cUnit, r_A0);
- loadValueAddress(cUnit, rlSrc1, r_A1);
- oatClobber(cUnit, r_A1);
- loadValueAddress(cUnit, rlSrc2, r_A2);
- UNIMP(FATAL) << "Need callout to handler";
-#if 0
- genDispatchToHandler(cUnit, opcode);
-#endif
- rlDest = oatUpdateLoc(cUnit, rlDest);
- if (rlDest.location == kLocPhysReg) {
- oatClobber(cUnit, rlDest.lowReg);
- }
- return false;
-#endif
#endif
}
@@ -192,64 +112,19 @@ static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,
storeValueWide(cUnit, rlDest, rlResult);
return false;
#else
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
- return false;
-#if 0
- TemplateOpcode opcode;
-
- switch (mir->dalvikInsn.opcode) {
- case OP_ADD_DOUBLE_2ADDR:
- case OP_ADD_DOUBLE:
- opcode = TEMPLATE_ADD_DOUBLE_VFP;
- break;
- case OP_SUB_DOUBLE_2ADDR:
- case OP_SUB_DOUBLE:
- opcode = TEMPLATE_SUB_DOUBLE_VFP;
- break;
- case OP_DIV_DOUBLE_2ADDR:
- case OP_DIV_DOUBLE:
- opcode = TEMPLATE_DIV_DOUBLE_VFP;
- break;
- case OP_MUL_DOUBLE_2ADDR:
- case OP_MUL_DOUBLE:
- opcode = TEMPLATE_MUL_DOUBLE_VFP;
- break;
- case OP_REM_DOUBLE_2ADDR:
- case OP_REM_DOUBLE:
- case OP_NEG_DOUBLE: {
- return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1,
- rlSrc2);
- }
- default:
- return true;
- }
- loadValueAddress(cUnit, rlDest, r_A0);
- oatClobber(cUnit, r_A0);
- loadValueAddress(cUnit, rlSrc1, r_A1);
- oatClobber(cUnit, r_A1);
- loadValueAddress(cUnit, rlSrc2, r_A2);
- UNIMP(FATAL) << "Need callout to handler";
-#if 0
- genDispatchToHandler(cUnit, opcode);
-#endif
- rlDest = oatUpdateLocWide(cUnit, rlDest);
- if (rlDest.location == kLocPhysReg) {
- oatClobber(cUnit, rlDest.lowReg);
- oatClobber(cUnit, rlDest.highReg);
- }
+ UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation";
return false;
#endif
-#endif
}
static bool genConversion(CompilationUnit *cUnit, MIR *mir)
{
+#ifdef __mips_hard_float
Opcode opcode = mir->dalvikInsn.opcode;
bool longSrc = false;
bool longDest = false;
RegLocation rlSrc;
RegLocation rlDest;
-#ifdef __mips_hard_float
int op = kMipsNop;
int srcReg;
RegLocation rlResult;
@@ -306,77 +181,8 @@ static bool genConversion(CompilationUnit *cUnit, MIR *mir)
}
return false;
#else
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+ UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation";
return false;
-#if 0
- TemplateOpcode templateOpcode;
- switch (opcode) {
- case OP_INT_TO_FLOAT:
- longSrc = false;
- longDest = false;
- templateOpcode = TEMPLATE_INT_TO_FLOAT_VFP;
- break;
- case OP_FLOAT_TO_INT:
- longSrc = false;
- longDest = false;
- templateOpcode = TEMPLATE_FLOAT_TO_INT_VFP;
- break;
- case OP_DOUBLE_TO_FLOAT:
- longSrc = true;
- longDest = false;
- templateOpcode = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
- break;
- case OP_FLOAT_TO_DOUBLE:
- longSrc = false;
- longDest = true;
- templateOpcode = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
- break;
- case OP_INT_TO_DOUBLE:
- longSrc = false;
- longDest = true;
- templateOpcode = TEMPLATE_INT_TO_DOUBLE_VFP;
- break;
- case OP_DOUBLE_TO_INT:
- longSrc = true;
- longDest = false;
- templateOpcode = TEMPLATE_DOUBLE_TO_INT_VFP;
- break;
- case OP_LONG_TO_DOUBLE:
- case OP_FLOAT_TO_LONG:
- case OP_LONG_TO_FLOAT:
- case OP_DOUBLE_TO_LONG:
- return genConversionPortable(cUnit, mir);
- default:
- return true;
- }
-
- if (longSrc) {
- rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- } else {
- rlSrc = oatGetSrc(cUnit, mir, 0);
- }
-
- if (longDest) {
- rlDest = oatGetDestWide(cUnit, mir, 0, 1);
- } else {
- rlDest = oatGetDest(cUnit, mir, 0);
- }
- loadValueAddress(cUnit, rlDest, r_A0);
- oatClobber(cUnit, r_A0);
- loadValueAddress(cUnit, rlSrc, r_A1);
- UNIMP(FATAL) << "Need callout to handler";
-#if 0
- genDispatchToHandler(cUnit, templateOpcode);
-#endif
- if (rlDest.wide) {
- rlDest = oatUpdateLocWide(cUnit, rlDest);
- oatClobber(cUnit, rlDest.highReg);
- } else {
- rlDest = oatUpdateLoc(cUnit, rlDest);
- }
- oatClobber(cUnit, rlDest.lowReg);
- return false;
-#endif
#endif
}
diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc
index f76adff3bd..71220c0be7 100644
--- a/src/compiler/codegen/mips/Mips32/Factory.cc
+++ b/src/compiler/codegen/mips/Mips32/Factory.cc
@@ -38,19 +38,24 @@ static int fpTemps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
#endif
+void genBarrier(CompilationUnit *cUnit);
+LIR* genCompareBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
+ int src2);
+LIR* opCompareBranch(CompilationUnit* cUnit, MipsOpCode opc, int src1,
+ int src2);
void storePair(CompilationUnit *cUnit, int base, int lowReg,
int highReg);
void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
-MipsLIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
+LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
int rDest);
-MipsLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
int displacement, int rSrc);
-MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
+LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
#ifdef __mips_hard_float
-MipsLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
{
- MipsLIR* res = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
+ LIR* res = (LIR *) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
res->operands[0] = rDest;
res->operands[1] = rSrc;
if (rDest == rSrc) {
@@ -90,10 +95,10 @@ MipsLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
* 1) rDest is freshly returned from oatAllocTemp or
* 2) The codegen is under fixed register usage
*/
-MipsLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
+LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
int value)
{
- MipsLIR *res;
+ LIR *res;
#ifdef __mips_hard_float
int rDestSave = rDest;
@@ -127,22 +132,9 @@ MipsLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
return res;
}
-/*
- * Load an immediate value into a fixed or temp register. Target
- * register is clobbered, and marked inUse.
- */
-MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
-{
- if (oatIsTemp(cUnit, rDest)) {
- oatClobber(cUnit, rDest);
- oatMarkInUse(cUnit, rDest);
- }
- return loadConstantNoClobber(cUnit, rDest, value);
-}
-
-MipsLIR *opNone(CompilationUnit *cUnit, OpKind op)
+LIR *opNone(CompilationUnit *cUnit, OpKind op)
{
- MipsLIR *res;
+ LIR *res;
MipsOpCode opcode = kMipsNop;
switch (op) {
case kOpUncondBr:
@@ -156,28 +148,28 @@ MipsLIR *opNone(CompilationUnit *cUnit, OpKind op)
}
-MipsLIR *opCmpBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
+LIR *opCmpBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
int rs, int rt)
{
UNIMPLEMENTED(FATAL);
return 0;
}
-MipsLIR *opCmpImmBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
+LIR *opCmpImmBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,
int rs, int immVal)
{
UNIMPLEMENTED(FATAL);
return 0;
}
-MipsLIR *opCmpImmBranch(CompilationUnit *cUnit, MipsOpCode cc,
+LIR *opCmpImmBranch(CompilationUnit *cUnit, MipsOpCode cc,
int rs, int immVal)
{
UNIMPLEMENTED(FATAL);
return 0;
}
-MipsLIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)
+LIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)
{
- MipsLIR *res;
+ LIR *res;
if (rt < 0) {
DCHECK(opc >= kMipsBeqz && opc <= kMipsBnez);
res = newLIR1(cUnit, opc, rs);
@@ -188,9 +180,9 @@ MipsLIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)
return res;
}
-MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
+LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
-MipsLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
+LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
{
MipsOpCode opcode = kMipsNop;
switch (op) {
@@ -203,12 +195,12 @@ MipsLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
return newLIR2(cUnit, opcode, r_RA, rDestSrc);
}
-MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
int rSrc1, int value);
-MipsLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
int value)
{
- MipsLIR *res;
+ LIR *res;
bool neg = (value < 0);
int absValue = (neg) ? -value : value;
bool shortForm = (absValue & 0xff) == absValue;
@@ -237,7 +229,7 @@ MipsLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
return res;
}
-MipsLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+LIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
int rSrc1, int rSrc2)
{
MipsOpCode opcode = kMipsNop;
@@ -276,10 +268,10 @@ MipsLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
}
-MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
int rSrc1, int value)
{
- MipsLIR *res;
+ LIR *res;
MipsOpCode opcode = kMipsNop;
bool shortForm = true;
@@ -366,11 +358,11 @@ MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
return res;
}
-MipsLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
int rSrc2)
{
MipsOpCode opcode = kMipsNop;
- MipsLIR *res;
+ LIR *res;
switch (op) {
case kOpMov:
opcode = kMipsMove;
@@ -411,21 +403,21 @@ MipsLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
}
-MipsLIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
+LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
int rDestHi, int valLo, int valHi)
{
- MipsLIR *res;
+ LIR *res;
res = loadConstantNoClobber(cUnit, rDestLo, valLo);
loadConstantNoClobber(cUnit, rDestHi, valHi);
return res;
}
/* Load value from base + scaled index. */
-MipsLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
int rIndex, int rDest, int scale, OpSize size)
{
- MipsLIR *first = NULL;
- MipsLIR *res;
+ LIR *first = NULL;
+ LIR *res;
MipsOpCode opcode = kMipsNop;
int tReg = oatAllocTemp(cUnit);
@@ -478,11 +470,11 @@ MipsLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
}
/* store value base base + scaled index. */
-MipsLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
+LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
int rIndex, int rSrc, int scale, OpSize size)
{
- MipsLIR *first = NULL;
- MipsLIR *res;
+ LIR *first = NULL;
+ LIR *res;
MipsOpCode opcode = kMipsNop;
int rNewIndex = rIndex;
int tReg = oatAllocTemp(cUnit);
@@ -530,11 +522,11 @@ MipsLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
return first;
}
-MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
{
int i;
int loadCnt = 0;
- MipsLIR *res = NULL ;
+ LIR *res = NULL ;
genBarrier(cUnit);
for (i = 0; i < 8; i++, rMask >>= 1) {
@@ -552,11 +544,11 @@ MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
return res; /* NULL always returned which should be ok since no callers use it */
}
-MipsLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
{
int i;
int storeCnt = 0;
- MipsLIR *res = NULL ;
+ LIR *res = NULL ;
genBarrier(cUnit);
for (i = 0; i < 8; i++, rMask >>= 1) {
@@ -574,7 +566,7 @@ MipsLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
return res; /* NULL always returned which should be ok since no callers use it */
}
-MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
+LIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
int displacement, int rDest, int rDestHi,
OpSize size, int sReg)
/*
@@ -586,9 +578,9 @@ MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
* rlp and then restore.
*/
{
- MipsLIR *res;
- MipsLIR *load = NULL;
- MipsLIR *load2 = NULL;
+ LIR *res;
+ LIR *load = NULL;
+ LIR *load2 = NULL;
MipsOpCode opcode = kMipsNop;
bool shortForm = IS_SIMM16(displacement);
bool pair = false;
@@ -680,7 +672,7 @@ MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,
return load;
}
-MipsLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+LIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
int displacement, int rDest, OpSize size,
int sReg)
{
@@ -688,7 +680,7 @@ MipsLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
size, sReg);
}
-MipsLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
+LIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
int displacement, int rDestLo, int rDestHi,
int sReg)
{
@@ -696,13 +688,13 @@ MipsLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,
kLong, sReg);
}
-MipsLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
+LIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
int displacement, int rSrc, int rSrcHi,
OpSize size)
{
- MipsLIR *res;
- MipsLIR *store = NULL;
- MipsLIR *store2 = NULL;
+ LIR *res;
+ LIR *store = NULL;
+ LIR *store2 = NULL;
MipsOpCode opcode = kMipsNop;
bool shortForm = IS_SIMM16(displacement);
bool pair = false;
@@ -785,13 +777,13 @@ MipsLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,
return res;
}
-MipsLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
int displacement, int rSrc, OpSize size)
{
return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
}
-MipsLIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
+LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,
int displacement, int rSrcLo, int rSrcHi)
{
return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
@@ -803,83 +795,12 @@ void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
loadWordDisp(cUnit, base, HIWORD_OFFSET , highReg);
}
-MipsLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
-{
- MipsLIR* res;
- MipsOpCode opcode;
-#ifdef __mips_hard_float
- if (FPREG(rDest) || FPREG(rSrc))
- return fpRegCopy(cUnit, rDest, rSrc);
-#endif
- res = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- opcode = kMipsMove;
- DCHECK(LOWREG(rDest) && LOWREG(rSrc));
- res->operands[0] = rDest;
- res->operands[1] = rSrc;
- res->opcode = opcode;
- setupResourceMasks(res);
- if (rDest == rSrc) {
- res->flags.isNop = true;
- }
- return res;
-}
-
-MipsLIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
-{
- MipsLIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc);
- oatAppendLIR(cUnit, (LIR*)res);
- return res;
-}
-
-void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
- int srcLo, int srcHi)
-{
-#ifdef __mips_hard_float
- bool destFP = FPREG(destLo) && FPREG(destHi);
- bool srcFP = FPREG(srcLo) && FPREG(srcHi);
- DCHECK_EQ(FPREG(srcLo), FPREG(srcHi));
- DCHECK_EQ(FPREG(destLo), FPREG(destHi));
- if (destFP) {
- if (srcFP) {
- genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
- } else {
- /* note the operands are swapped for the mtc1 instr */
- newLIR2(cUnit, kMipsMtc1, srcLo, destLo);
- newLIR2(cUnit, kMipsMtc1, srcHi, destHi);
- }
- } else {
- if (srcFP) {
- newLIR2(cUnit, kMipsMfc1, destLo, srcLo);
- newLIR2(cUnit, kMipsMfc1, destHi, srcHi);
- } else {
- // Handle overlap
- if (srcHi == destLo) {
- genRegCopy(cUnit, destHi, srcHi);
- genRegCopy(cUnit, destLo, srcLo);
- } else {
- genRegCopy(cUnit, destLo, srcLo);
- genRegCopy(cUnit, destHi, srcHi);
- }
- }
- }
-#else
- // Handle overlap
- if (srcHi == destLo) {
- genRegCopy(cUnit, destHi, srcHi);
- genRegCopy(cUnit, destLo, srcLo);
- } else {
- genRegCopy(cUnit, destLo, srcLo);
- genRegCopy(cUnit, destHi, srcHi);
- }
-#endif
-}
-
-inline MipsLIR *genRegImmCheck(CompilationUnit *cUnit,
+LIR *genRegImmCheck(CompilationUnit *cUnit,
MipsConditionCode cond, int reg,
int checkValue, int dOffset,
- MipsLIR *pcrLabel)
+ LIR *pcrLabel)
{
- MipsLIR *branch = NULL;
+ LIR *branch = NULL;
if (checkValue == 0) {
MipsOpCode opc = kMipsNop;
@@ -918,9 +839,9 @@ inline MipsLIR *genRegImmCheck(CompilationUnit *cUnit,
if (cUnit->jitMode == kJitMethod) {
BasicBlock *bb = cUnit->curBlock;
if (bb->taken) {
- MipsLIR *exceptionLabel = (MipsLIR *) cUnit->blockLabelList;
+ LIR *exceptionLabel = (LIR *) cUnit->blockLabelList;
exceptionLabel += bb->taken->id;
- branch->generic.target = (LIR *) exceptionLabel;
+ branch->target = (LIR *) exceptionLabel;
return exceptionLabel;
} else {
LOG(FATAL) << "Catch blocks not handled yet";
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index 880169272e..0b2b15ac45 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -24,377 +24,6 @@
namespace art {
-// FIXME: need the following:
-void genSuspendTest(CompilationUnit* cUnit, MIR* mir) {}
-void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {}
-void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {}
-void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {}
-void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
- RegLocation rlSrc) {}
-void genNewInstance(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest) {}
-void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {}
-void genConstString(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc) {}
-void genConstClass(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc) {}
-void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size,
- RegLocation rlArray, RegLocation rlIndex,
- RegLocation rlDest, int scale) {}
-void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size,
- RegLocation rlArray, RegLocation rlIndex,
- RegLocation rlSrc, int scale) {}
-void genArrayObjPut(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlArray, RegLocation rlIndex,
- RegLocation rlSrc, int scale) {}
-void genIPut(CompilationUnit* cUnit, MIR* mir, OpSize size,
- RegLocation rlSrc, RegLocation rlObj,
- bool isLongOrDouble, bool isObject) {}
-bool genArithOpInt(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2) { return 0; }
-bool genArithOpLong(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2) { return 0; }
-bool genShiftOpLong(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlShift) { return 0; }
-bool genArithOpIntLit(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc,
- int lit) { return 0; }
-void oatArchDump(void) {};
-void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset) {};
-
-
-
-
-STATIC bool genConversionCall(CompilationUnit* cUnit, MIR* mir, int funcOffset,
- int srcSize, int tgtSize)
-{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
- return 0;
-#if 0
- /*
- * Don't optimize the register usage since it calls out to support
- * functions
- */
- RegLocation rlSrc;
- RegLocation rlDest;
- oatFlushAllRegs(cUnit); /* Send everything to home location */
- loadWordDisp(cUnit, rSELF, funcOffset, rLR);
- if (srcSize == 1) {
- rlSrc = oatGetSrc(cUnit, mir, 0);
- loadValueDirectFixed(cUnit, rlSrc, r0);
- } else {
- rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- loadValueDirectWideFixed(cUnit, rlSrc, r0, r1);
- }
- callRuntimeHelper(cUnit, rLR);
- if (tgtSize == 1) {
- RegLocation rlResult;
- rlDest = oatGetDest(cUnit, mir, 0);
- rlResult = oatGetReturn(cUnit);
- storeValue(cUnit, rlDest, rlResult);
- } else {
- RegLocation rlResult;
- rlDest = oatGetDestWide(cUnit, mir, 0, 1);
- rlResult = oatGetReturnWide(cUnit);
- storeValueWide(cUnit, rlDest, rlResult);
- }
- return false;
-#endif
-}
-
-bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2)
-{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
- return 0;
-#if 0
- RegLocation rlResult;
- int funcOffset;
-
- switch (mir->dalvikInsn.opcode) {
- case OP_ADD_FLOAT_2ADDR:
- case OP_ADD_FLOAT:
- funcOffset = OFFSETOF_MEMBER(Thread, pFadd);
- break;
- case OP_SUB_FLOAT_2ADDR:
- case OP_SUB_FLOAT:
- funcOffset = OFFSETOF_MEMBER(Thread, pFsub);
- break;
- case OP_DIV_FLOAT_2ADDR:
- case OP_DIV_FLOAT:
- funcOffset = OFFSETOF_MEMBER(Thread, pFdiv);
- break;
- case OP_MUL_FLOAT_2ADDR:
- case OP_MUL_FLOAT:
- funcOffset = OFFSETOF_MEMBER(Thread, pFmul);
- break;
- case OP_REM_FLOAT_2ADDR:
- case OP_REM_FLOAT:
- funcOffset = OFFSETOF_MEMBER(Thread, pFmodf);
- break;
- case OP_NEG_FLOAT: {
- genNegFloat(cUnit, rlDest, rlSrc1);
- return false;
- }
- default:
- return true;
- }
- oatFlushAllRegs(cUnit); /* Send everything to home location */
- loadWordDisp(cUnit, rSELF, funcOffset, rLR);
- loadValueDirectFixed(cUnit, rlSrc1, r0);
- loadValueDirectFixed(cUnit, rlSrc2, r1);
- callRuntimeHelper(cUnit, rLR);
- rlResult = oatGetReturn(cUnit);
- storeValue(cUnit, rlDest, rlResult);
- return false;
-#endif
-}
-
-bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2)
-{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
- return 0;
-#if 0
- RegLocation rlResult;
- int funcOffset;
-
- switch (mir->dalvikInsn.opcode) {
- case OP_ADD_DOUBLE_2ADDR:
- case OP_ADD_DOUBLE:
- funcOffset = OFFSETOF_MEMBER(Thread, pDadd);
- break;
- case OP_SUB_DOUBLE_2ADDR:
- case OP_SUB_DOUBLE:
- funcOffset = OFFSETOF_MEMBER(Thread, pDsub);
- break;
- case OP_DIV_DOUBLE_2ADDR:
- case OP_DIV_DOUBLE:
- funcOffset = OFFSETOF_MEMBER(Thread, pDdiv);
- break;
- case OP_MUL_DOUBLE_2ADDR:
- case OP_MUL_DOUBLE:
- funcOffset = OFFSETOF_MEMBER(Thread, pDmul);
- break;
- case OP_REM_DOUBLE_2ADDR:
- case OP_REM_DOUBLE:
- funcOffset = OFFSETOF_MEMBER(Thread, pFmod);
- break;
- case OP_NEG_DOUBLE: {
- genNegDouble(cUnit, rlDest, rlSrc1);
- return false;
- }
- default:
- return true;
- }
- oatFlushAllRegs(cUnit); /* Send everything to home location */
- loadWordDisp(cUnit, rSELF, funcOffset, rLR);
- loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
- loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
- callRuntimeHelper(cUnit, rLR);
- rlResult = oatGetReturnWide(cUnit);
- storeValueWide(cUnit, rlDest, rlResult);
- return false;
-#endif
-}
-
-bool genConversionPortable(CompilationUnit* cUnit, MIR* mir)
-{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
- return 0;
-#if 0
- Opcode opcode = mir->dalvikInsn.opcode;
-
- switch (opcode) {
- case OP_INT_TO_FLOAT:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2f),
- 1, 1);
- case OP_FLOAT_TO_INT:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2iz),
- 1, 1);
- case OP_DOUBLE_TO_FLOAT:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2f),
- 2, 1);
- case OP_FLOAT_TO_DOUBLE:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2d),
- 1, 2);
- case OP_INT_TO_DOUBLE:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2d),
- 1, 2);
- case OP_DOUBLE_TO_INT:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2iz),
- 2, 1);
- case OP_FLOAT_TO_LONG:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
- pF2l), 1, 2);
- case OP_LONG_TO_FLOAT:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2f),
- 2, 1);
- case OP_DOUBLE_TO_LONG:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
- pD2l), 2, 2);
- case OP_LONG_TO_DOUBLE:
- return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2d),
- 2, 2);
- default:
- return true;
- }
- return false;
-#endif
-}
-
-
-
-
-
-STATIC RegLocation getRetLoc(CompilationUnit* cUnit);
-
-void warnIfUnresolved(CompilationUnit* cUnit, int fieldIdx, Field* field) {
- if (field == NULL) {
- const DexFile::FieldId& field_id = cUnit->dex_file->GetFieldId(fieldIdx);
- std::string class_name(cUnit->dex_file->GetFieldDeclaringClassDescriptor(field_id));
- std::string field_name(cUnit->dex_file->GetFieldName(field_id));
- LOG(INFO) << "Field " << PrettyDescriptor(class_name) << "." << field_name
- << " unresolved at compile time";
- } else {
- // We also use the slow path for wide volatile fields.
- }
-}
-
-/*
- * Construct an s4 from two consecutive half-words of switch data.
- * This needs to check endianness because the DEX optimizer only swaps
- * half-words in instruction stream.
- *
- * "switchData" must be 32-bit aligned.
- */
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-STATIC inline s4 s4FromSwitchData(const void* switchData) {
- return *(s4*) switchData;
-}
-#else
-STATIC inline s4 s4FromSwitchData(const void* switchData) {
- u2* data = switchData;
- return data[0] | (((s4) data[1]) << 16);
-}
-#endif
-/*
- * Insert a kPseudoCaseLabel at the beginning of the Dalvik
- * offset vaddr. This label will be used to fix up the case
- * branch table during the assembly phase. Be sure to set
- * all resource flags on this to prevent code motion across
- * target boundaries. KeyVal is just there for debugging.
- */
-STATIC MipsLIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
-{
- std::map<unsigned int, LIR*>::iterator it;
- it = cUnit->boundaryMap.find(vaddr);
- if (it == cUnit->boundaryMap.end()) {
- LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
- }
- MipsLIR* newLabel = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR);
- newLabel->generic.dalvikOffset = vaddr;
- newLabel->opcode = kPseudoCaseLabel;
- newLabel->operands[0] = keyVal;
- oatInsertLIRAfter(it->second, (LIR*)newLabel);
- return newLabel;
-}
-
-STATIC void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
-{
- const u2* table = tabRec->table;
- int baseVaddr = tabRec->vaddr;
- int *targets = (int*)&table[4];
- int entries = table[1];
- int lowKey = s4FromSwitchData(&table[2]);
- for (int i = 0; i < entries; i++) {
- tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
- i + lowKey);
- }
-}
-
-STATIC void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
-{
- const u2* table = tabRec->table;
- int baseVaddr = tabRec->vaddr;
- int entries = table[1];
- int* keys = (int*)&table[2];
- int* targets = &keys[entries];
- for (int i = 0; i < entries; i++) {
- tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
- keys[i]);
- }
-}
-
-void oatProcessSwitchTables(CompilationUnit* cUnit)
-{
- GrowableListIterator iterator;
- oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
- while (true) {
- SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
- &iterator);
- if (tabRec == NULL) break;
- if (tabRec->table[0] == kPackedSwitchSignature)
- markPackedCaseLabels(cUnit, tabRec);
- else if (tabRec->table[0] == kSparseSwitchSignature)
- markSparseCaseLabels(cUnit, tabRec);
- else {
- LOG(FATAL) << "Invalid switch table";
- }
- }
-}
-
-STATIC void dumpSparseSwitchTable(const u2* table)
- /*
- * Sparse switch data format:
- * ushort ident = 0x0200 magic value
- * ushort size number of entries in the table; > 0
- * int keys[size] keys, sorted low-to-high; 32-bit aligned
- * int targets[size] branch targets, relative to switch opcode
- *
- * Total size is (2+size*4) 16-bit code units.
- */
-{
- u2 ident = table[0];
- int entries = table[1];
- int* keys = (int*)&table[2];
- int* targets = &keys[entries];
- LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident <<
- ", entries: " << std::dec << entries;
- for (int i = 0; i < entries; i++) {
- LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex <<
- targets[i];
- }
-}
-
-STATIC void dumpPackedSwitchTable(const u2* table)
- /*
- * Packed switch data format:
- * ushort ident = 0x0100 magic value
- * ushort size number of entries in the table
- * int first_key first (and lowest) switch case value
- * int targets[size] branch targets, relative to switch opcode
- *
- * Total size is (4+size*2) 16-bit code units.
- */
-{
- u2 ident = table[0];
- int* targets = (int*)&table[4];
- int entries = table[1];
- int lowKey = s4FromSwitchData(&table[2]);
- LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident <<
- ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
- for (int i = 0; i < entries; i++) {
- LOG(INFO) << " Key[" << (i + lowKey) << "] -> 0x" << std::hex <<
- targets[i];
- }
-}
-
/*
* The sparse table in the literal pool is an array of <key,displacement>
* pairs. For each set, we'll load them as a pair using ldmia.
@@ -414,10 +43,9 @@ STATIC void dumpPackedSwitchTable(const u2* table)
* add rPC, rDisp ; This is the branch from which we compute displacement
* cbnz rIdx, lp
*/
-STATIC void genSparseSwitch(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlSrc)
+void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+ UNIMPLEMENTED(FATAL) << "Needs Mips sparse switch";
#if 0
const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
if (cUnit->printMe) {
@@ -429,8 +57,8 @@ STATIC void genSparseSwitch(CompilationUnit* cUnit, MIR* mir,
tabRec->table = table;
tabRec->vaddr = mir->offset;
int size = table[1];
- tabRec->targets = (MipsLIR* *)oatNew(cUnit, size * sizeof(MipsLIR*), true,
- kAllocLIR);
+ tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
+ kAllocLIR);
oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
// Get the switch value
@@ -451,26 +79,26 @@ STATIC void genSparseSwitch(CompilationUnit* cUnit, MIR* mir,
int rIdx = oatAllocTemp(cUnit);
loadConstant(cUnit, rIdx, size);
// Establish loop branch target
- MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+ LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
target->defMask = ENCODE_ALL;
// Load next key/disp
newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp));
opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg);
// Go if match. NOTE: No instruction set switch here - must stay Thumb2
- genIT(cUnit, kMipsCondEq, "");
- MipsLIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);
+ genIT(cUnit, kArmCondEq, "");
+ LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);
tabRec->bxInst = switchBranch;
// Needs to use setflags encoding here
newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);
- MipsLIR* branch = opCondBranch(cUnit, kMipsCondNe);
- branch->generic.target = (LIR*)target;
+ LIR* branch = opCondBranch(cUnit, kCondNe);
+ branch->target = (LIR*)target;
#endif
}
-STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlSrc)
+
+void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+ UNIMPLEMENTED(FATAL) << "Need Mips packed switch";
#if 0
const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
if (cUnit->printMe) {
@@ -482,7 +110,7 @@ STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,
tabRec->table = table;
tabRec->vaddr = mir->offset;
int size = table[1];
- tabRec->targets = (MipsLIR* *)oatNew(cUnit, size * sizeof(MipsLIR*), true,
+ tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,
kAllocLIR);
oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
@@ -502,20 +130,20 @@ STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,
}
// Bounds check - if < 0 or >= size continue following switch
opRegImm(cUnit, kOpCmp, keyReg, size-1);
- MipsLIR* branchOver = opCondBranch(cUnit, kMipsCondHi);
+ LIR* branchOver = opCondBranch(cUnit, kCondHi);
// Load the displacement from the switch table
int dispReg = oatAllocTemp(cUnit);
loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord);
// ..and go! NOTE: No instruction set switch here - must stay Thumb2
- MipsLIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);
+ LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);
tabRec->bxInst = switchBranch;
/* branchOver target here */
- MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+ LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
target->defMask = ENCODE_ALL;
- branchOver->generic.target = (LIR*)target;
+ branchOver->target = (LIR*)target;
#endif
}
@@ -529,10 +157,9 @@ STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,
*
* Total size is 4+(width * size + 1)/2 16-bit code units.
*/
-STATIC void genFillArrayData(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlSrc)
+void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
+ UNIMPLEMENTED(FATAL) << "Needs Mips FillArrayData";
#if 0
const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
// Add the table to the list - we'll process it later
@@ -548,7 +175,7 @@ STATIC void genFillArrayData(CompilationUnit* cUnit, MIR* mir,
// Making a call - use explicit registers
oatFlushAllRegs(cUnit); /* Everything to home location */
- loadValueDirectFixed(cUnit, rlSrc, r0);
+ loadValueDirectFixed(cUnit, rlSrc, rARG0);
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pHandleFillArrayDataFromCode), rLR);
// Materialize a pointer to the fill data image
@@ -557,275 +184,186 @@ STATIC void genFillArrayData(CompilationUnit* cUnit, MIR* mir,
#endif
}
-STATIC void genIGet(CompilationUnit* cUnit, MIR* mir, OpSize size,
- RegLocation rlDest, RegLocation rlObj,
- bool isLongOrDouble, bool isObject)
+/*
+ * TODO: implement fast path to short-circuit thin-lock case
+ */
+void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
-#if 0
- int fieldOffset;
- bool isVolatile;
- uint32_t fieldIdx = mir->dalvikInsn.vC;
- bool fastPath =
- cUnit->compiler->ComputeInstanceFieldInfo(fieldIdx, cUnit,
- fieldOffset, isVolatile, false);
- if (fastPath && !SLOW_FIELD_PATH) {
- RegLocation rlResult;
- RegisterClass regClass = oatRegClassBySize(size);
- DCHECK_GE(fieldOffset, 0);
- rlObj = loadValue(cUnit, rlObj, kCoreReg);
- if (isLongOrDouble) {
- DCHECK(rlDest.wide);
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */
- 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);
- storeValueWide(cUnit, rlDest, rlResult);
- } else {
- rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
- loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
- kWord, rlObj.sRegLow);
- if (isVolatile) {
- oatGenMemBarrier(cUnit, kSY);
- }
- storeValue(cUnit, rlDest, rlResult);
- }
- } else {
- int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Instance) :
- (isObject ? OFFSETOF_MEMBER(Thread, pGetObjInstance)
- : OFFSETOF_MEMBER(Thread, pGet32Instance));
- loadWordDisp(cUnit, rSELF, getterOffset, rLR);
- loadValueDirect(cUnit, rlObj, r1);
- loadConstant(cUnit, r0, fieldIdx);
- callRuntimeHelper(cUnit, rLR);
- if (isLongOrDouble) {
- RegLocation rlResult = oatGetReturnWide(cUnit);
- storeValueWide(cUnit, rlDest, rlResult);
- } else {
- RegLocation rlResult = oatGetReturn(cUnit);
- storeValue(cUnit, rlDest, rlResult);
- }
- }
-#endif
+ oatFlushAllRegs(cUnit);
+ loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
+ oatLockCallTemps(cUnit); // Prepare for explicit register usage
+ genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
+ // Go expensive route - artLockObjectFromCode(self, obj);
+ int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pLockObjectFromCode));
+ callRuntimeHelper(cUnit, rTgt);
}
/*
- * Perform a "reg cmp imm" operation and jump to the PCR region if condition
- * satisfies.
+ * TODO: implement fast path to short-circuit thin-lock case
*/
-STATIC void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest,
- RegLocation rlSrc)
+void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
- RegLocation rlResult;
- rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- opRegRegImm(cUnit, kOpAdd, rlResult.lowReg,
- rlSrc.lowReg, 0x80000000);
- storeValue(cUnit, rlDest, rlResult);
+ oatFlushAllRegs(cUnit);
+ loadValueDirectFixed(cUnit, rlSrc, rARG0); // Get obj
+ oatLockCallTemps(cUnit); // Prepare for explicit register usage
+ genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
+ // Go expensive route - UnlockObjectFromCode(obj);
+ int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode));
+ callRuntimeHelper(cUnit, rTgt);
}
-STATIC void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest,
- RegLocation rlSrc)
+/*
+ * Compare two 64-bit values
+ * x = y return 0
+ * x < y return -1
+ * x > y return 1
+ *
+ * slt t0, x.hi, y.hi; # (x.hi < y.hi) ? 1:0
+ * sgt t1, x.hi, y.hi; # (y.hi > x.hi) ? 1:0
+ * subu res, t0, t1 # res = -1:1:0 for [ < > = ]
+ * bnez res, finish
+ * sltu t0, x.lo, y.lo
+ * sgtu r1, x.lo, y.lo
+ * subu res, t0, t1
+ * finish:
+ *
+ */
+void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
+ RegLocation rlSrc1, RegLocation rlSrc2)
{
- RegLocation rlResult;
- rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
- rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg,
- 0x80000000);
- genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
- storeValueWide(cUnit, rlDest, rlResult);
+ rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
+ rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
+ int t0 = oatAllocTemp(cUnit);
+ int t1 = oatAllocTemp(cUnit);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ newLIR3(cUnit, kMipsSlt, t0, rlSrc1.highReg, rlSrc2.highReg);
+ newLIR3(cUnit, kMipsSlt, t1, rlSrc2.highReg, rlSrc1.highReg);
+ newLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0);
+ LIR* branch = genCmpImmBranch(cUnit, kCondNe, rlResult.lowReg, 0);
+ newLIR3(cUnit, kMipsSltu, t0, rlSrc1.lowReg, rlSrc2.lowReg);
+ newLIR3(cUnit, kMipsSltu, t1, rlSrc2.lowReg, rlSrc1.lowReg);
+ newLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0);
+ oatFreeTemp(cUnit, t0);
+ oatFreeTemp(cUnit, t1);
+ LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
+ target->defMask = ENCODE_ALL;
+ branch->target = (LIR*)target;
+ storeValue(cUnit, rlDest, rlResult);
}
-STATIC void genMulLong(CompilationUnit *cUnit, RegLocation rlDest,
- RegLocation rlSrc1, RegLocation rlSrc2)
+LIR* genCompareBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
+ int src2)
{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
-#if 0
- RegLocation rlResult;
- loadValueDirectWideFixed(cUnit, rlSrc1, r_ARG0, r_ARG1);
- loadValueDirectWideFixed(cUnit, rlSrc2, r_ARG2, r_ARG3);
- genDispatchToHandler(cUnit, TEMPLATE_MUL_LONG);
- rlResult = oatGetReturnWide(cUnit);
- storeValueWide(cUnit, rlDest, rlResult);
-#endif
+ if (cond == kCondEq) {
+ return newLIR2(cUnit, kMipsBeq, src1, src2);
+ } else if (cond == kCondNe) {
+ return newLIR2(cUnit, kMipsBne, src1, src2);
+ }
+ //int rRes = oatAllocTemp(cUnit);
+ switch(cond) {
+ case kCondEq: return newLIR2(cUnit, kMipsBeq, src1, src2);
+ case kCondNe: return newLIR2(cUnit, kMipsBne, src1, src2);
+ default:
+ UNIMPLEMENTED(FATAL) << "Need to flesh out genCompareBranch";
+ return NULL;
+ }
}
-STATIC bool partialOverlap(int sreg1, int sreg2)
+LIR* genCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
+ int checkValue)
{
- return abs(sreg1 - sreg2) == 1;
+ if (checkValue != 0) {
+ // TUNING: handle s16 & kCondLt/Mi case using slti
+ int tReg = oatAllocTemp(cUnit);
+ loadConstant(cUnit, tReg, checkValue);
+ return genCompareBranch(cUnit, cond, reg, tReg);
+ }
+ MipsOpCode opc;
+ switch(cond) {
+ case kCondEq: opc = kMipsBeqz; break;
+ case kCondGe: opc = kMipsBgez; break;
+ case kCondGt: opc = kMipsBgtz; break;
+ case kCondLe: opc = kMipsBlez; break;
+ //case KCondMi:
+ case kCondLt: opc = kMipsBltz; break;
+ case kCondNe: opc = kMipsBnez; break;
+ default:
+ int tReg = oatAllocTemp(cUnit);
+ loadConstant(cUnit, tReg, checkValue);
+ return genCompareBranch(cUnit, cond, reg, tReg);
+ }
+ return newLIR1(cUnit, opc, reg);
}
-STATIC void withCarryHelper(CompilationUnit *cUnit, MipsOpCode opc,
- RegLocation rlDest, RegLocation rlSrc1,
- RegLocation rlSrc2, int sltuSrc1, int sltuSrc2)
+LIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
{
- int tReg = oatAllocTemp(cUnit);
- newLIR3(cUnit, opc, rlDest.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
- newLIR3(cUnit, kMipsSltu, tReg, sltuSrc1, sltuSrc2);
- newLIR3(cUnit, opc, rlDest.highReg, rlSrc1.highReg, rlSrc2.highReg);
- newLIR3(cUnit, opc, rlDest.highReg, rlDest.highReg, tReg);
- oatFreeTemp(cUnit, tReg);
+ LIR* res;
+ MipsOpCode opcode;
+#ifdef __mips_hard_float
+ if (FPREG(rDest) || FPREG(rSrc))
+ return fpRegCopy(cUnit, rDest, rSrc);
+#endif
+ res = (LIR *) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
+ opcode = kMipsMove;
+ assert(LOWREG(rDest) && LOWREG(rSrc));
+ res->operands[0] = rDest;
+ res->operands[1] = rSrc;
+ res->opcode = opcode;
+ setupResourceMasks(res);
+ if (rDest == rSrc) {
+ res->flags.isNop = true;
+ }
+ return res;
}
-STATIC void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp,
- OpKind secondOp, RegLocation rlDest,
- RegLocation rlSrc1, RegLocation rlSrc2)
+LIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
-#if 0
- RegLocation rlResult;
- int carryOp = (secondOp == kOpAdc || secondOp == kOpSbc);
+ LIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc);
+ oatAppendLIR(cUnit, (LIR*)res);
+ return res;
+}
- if (partialOverlap(rlSrc1.sRegLow,rlSrc2.sRegLow) ||
- partialOverlap(rlSrc1.sRegLow,rlDest.sRegLow) ||
- partialOverlap(rlSrc2.sRegLow,rlDest.sRegLow)) {
- // Rare case - not enough registers to properly handle
- genInterpSingleStep(cUnit, mir);
- } else if (rlDest.sRegLow == rlSrc1.sRegLow) {
- rlResult = loadValueWide(cUnit, rlDest, kCoreReg);
- rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
- if (!carryOp) {
- opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlResult.lowReg, rlSrc2.lowReg);
- opRegRegReg(cUnit, secondOp, rlResult.highReg, rlResult.highReg, rlSrc2.highReg);
- } else if (secondOp == kOpAdc) {
- withCarryHelper(cUnit, kMipsAddu, rlResult, rlResult, rlSrc2,
- rlResult.lowReg, rlSrc2.lowReg);
- } else {
- int tReg = oatAllocTemp(cUnit);
- newLIR2(cUnit, kMipsMove, tReg, rlResult.lowReg);
- withCarryHelper(cUnit, kMipsSubu, rlResult, rlResult, rlSrc2,
- tReg, rlResult.lowReg);
- oatFreeTemp(cUnit, tReg);
- }
- storeValueWide(cUnit, rlDest, rlResult);
- } else if (rlDest.sRegLow == rlSrc2.sRegLow) {
- rlResult = loadValueWide(cUnit, rlDest, kCoreReg);
- rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
- if (!carryOp) {
- opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg, rlResult.lowReg);
- opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg, rlResult.highReg);
- } else if (secondOp == kOpAdc) {
- withCarryHelper(cUnit, kMipsAddu, rlResult, rlSrc1, rlResult,
- rlResult.lowReg, rlSrc1.lowReg);
+void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
+ int srcLo, int srcHi)
+{
+#ifdef __mips_hard_float
+ bool destFP = FPREG(destLo) && FPREG(destHi);
+ bool srcFP = FPREG(srcLo) && FPREG(srcHi);
+ assert(FPREG(srcLo) == FPREG(srcHi));
+ assert(FPREG(destLo) == FPREG(destHi));
+ if (destFP) {
+ if (srcFP) {
+ genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));
} else {
- withCarryHelper(cUnit, kMipsSubu, rlResult, rlSrc1, rlResult,
- rlSrc1.lowReg, rlResult.lowReg);
+ /* note the operands are swapped for the mtc1 instr */
+ newLIR2(cUnit, kMipsMtc1, srcLo, destLo);
+ newLIR2(cUnit, kMipsMtc1, srcHi, destHi);
}
- storeValueWide(cUnit, rlDest, rlResult);
} else {
- rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
- rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
- rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- if (!carryOp) {
- opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
- opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg);
- } else if (secondOp == kOpAdc) {
- withCarryHelper(cUnit, kMipsAddu, rlResult, rlSrc1, rlSrc2,
- rlResult.lowReg, rlSrc1.lowReg);
+ if (srcFP) {
+ newLIR2(cUnit, kMipsMfc1, destLo, srcLo);
+ newLIR2(cUnit, kMipsMfc1, destHi, srcHi);
} else {
- withCarryHelper(cUnit, kMipsSubu, rlResult, rlSrc1, rlSrc2,
- rlSrc1.lowReg, rlResult.lowReg);
+ // Handle overlap
+ if (srcHi == destLo) {
+ genRegCopy(cUnit, destHi, srcHi);
+ genRegCopy(cUnit, destLo, srcLo);
+ } else {
+ genRegCopy(cUnit, destLo, srcLo);
+ genRegCopy(cUnit, destHi, srcHi);
+ }
}
- storeValueWide(cUnit, rlDest, rlResult);
}
-#endif
-}
-
-void oatInitializeRegAlloc(CompilationUnit* cUnit)
-{
- int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
- int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
- int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
-#ifdef __mips_hard_float
- int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
- int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
#else
- int numFPRegs = 0;
- int numFPTemps = 0;
-#endif
- RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
- kAllocRegAlloc);
- cUnit->regPool = pool;
- pool->numCoreRegs = numRegs;
- pool->coreRegs = (RegisterInfo *)
- oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
- true, kAllocRegAlloc);
- pool->numFPRegs = numFPRegs;
- pool->FPRegs = numFPRegs == 0 ? NULL : (RegisterInfo *)
- oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
- kAllocRegAlloc);
- oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
- oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
- // Keep special registers from being allocated
- for (int i = 0; i < numReserved; i++) {
- if (NO_SUSPEND && !cUnit->genDebugger &&
- (reservedRegs[i] == rSUSPEND)) {
- //To measure cost of suspend check
- continue;
- }
- oatMarkInUse(cUnit, reservedRegs[i]);
- }
- // Mark temp regs - all others not in use can be used for promotion
- for (int i = 0; i < numTemps; i++) {
- oatMarkTemp(cUnit, coreTemps[i]);
- }
- for (int i = 0; i < numFPTemps; i++) {
- oatMarkTemp(cUnit, fpTemps[i]);
- }
- // Construct the alias map.
- cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
- sizeof(cUnit->phiAliasMap[0]), false,
- kAllocDFInfo);
- for (int i = 0; i < cUnit->numSSARegs; i++) {
- cUnit->phiAliasMap[i] = i;
- }
- for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
- int defReg = phi->ssaRep->defs[0];
- for (int i = 0; i < phi->ssaRep->numUses; i++) {
- for (int j = 0; j < cUnit->numSSARegs; j++) {
- if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
- cUnit->phiAliasMap[j] = defReg;
- }
- }
- }
+ // Handle overlap
+ if (srcHi == destLo) {
+ genRegCopy(cUnit, destHi, srcHi);
+ genRegCopy(cUnit, destLo, srcLo);
+ } else {
+ genRegCopy(cUnit, destLo, srcLo);
+ genRegCopy(cUnit, destHi, srcHi);
}
-}
-
-STATIC void genMonitor(CompilationUnit *cUnit, MIR *mir)
-{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
-#if 0
- genMonitorPortable(cUnit, mir);
#endif
}
-STATIC void genCmpLong(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
- RegLocation rlSrc1, RegLocation rlSrc2)
-{
- UNIMPLEMENTED(FATAL) << "Need Mips implementation";
-#if 0
- RegLocation rlResult;
- loadValueDirectWideFixed(cUnit, rlSrc1, r_ARG0, r_ARG1);
- loadValueDirectWideFixed(cUnit, rlSrc2, r_ARG2, r_ARG3);
- genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG);
- rlResult = oatGetReturn(cUnit);
- storeValue(cUnit, rlDest, rlResult);
-#endif
-}
-
-STATIC void genMultiplyByTwoBitMultiplier(CompilationUnit *cUnit,
- RegLocation rlSrc, RegLocation rlResult, int lit,
- int firstBit, int secondBit)
-{
- // We can't implement "add src, src, src, lsl#shift" on Thumb, so we have
- // to do a regular multiply.
- opRegRegImm(cUnit, kOpMul, rlResult.lowReg, rlSrc.lowReg, lit);
-}
-
} // namespace art
diff --git a/src/compiler/codegen/mips/Mips32/Ralloc.cc b/src/compiler/codegen/mips/Mips32/Ralloc.cc
index e0912d77b8..f8440a45da 100644
--- a/src/compiler/codegen/mips/Mips32/Ralloc.cc
+++ b/src/compiler/codegen/mips/Mips32/Ralloc.cc
@@ -61,4 +61,76 @@ int oatAllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass)
return oatAllocTemp(cUnit);
}
+void oatInitializeRegAlloc(CompilationUnit* cUnit)
+{
+ int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
+ int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
+ int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
+#ifdef __mips_hard_float
+ int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
+ int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
+#else
+ int numFPRegs = 0;
+ int numFPTemps = 0;
+#endif
+ RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
+ kAllocRegAlloc);
+ cUnit->regPool = pool;
+ pool->numCoreRegs = numRegs;
+ pool->coreRegs = (RegisterInfo *)
+ oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
+ true, kAllocRegAlloc);
+ pool->numFPRegs = numFPRegs;
+ pool->FPRegs = (RegisterInfo *)
+ oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
+ kAllocRegAlloc);
+ oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
+ oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
+ // Keep special registers from being allocated
+ for (int i = 0; i < numReserved; i++) {
+ if (NO_SUSPEND && !cUnit->genDebugger &&
+ (reservedRegs[i] == rSUSPEND)) {
+ //To measure cost of suspend check
+ continue;
+ }
+ oatMarkInUse(cUnit, reservedRegs[i]);
+ }
+ // Mark temp regs - all others not in use can be used for promotion
+ for (int i = 0; i < numTemps; i++) {
+ oatMarkTemp(cUnit, coreTemps[i]);
+ }
+ for (int i = 0; i < numFPTemps; i++) {
+ oatMarkTemp(cUnit, fpTemps[i]);
+ }
+ // Construct the alias map.
+ cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
+ sizeof(cUnit->phiAliasMap[0]), false,
+ kAllocDFInfo);
+ for (int i = 0; i < cUnit->numSSARegs; i++) {
+ cUnit->phiAliasMap[i] = i;
+ }
+ for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
+ int defReg = phi->ssaRep->defs[0];
+ for (int i = 0; i < phi->ssaRep->numUses; i++) {
+ for (int j = 0; j < cUnit->numSSARegs; j++) {
+ if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
+ cUnit->phiAliasMap[j] = defReg;
+ }
+ }
+ }
+ }
+}
+
+void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
+ RegLocation rlFree)
+{
+ if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
+ (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
+ // No overlap, free both
+ oatFreeTemp(cUnit, rlFree.lowReg);
+ oatFreeTemp(cUnit, rlFree.highReg);
+ }
+}
+
+
} // namespace art
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 44f0c5a2b9..93956d5d5f 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -149,10 +149,10 @@ namespace art {
INVALID_SREG}
#define LOC_C_RETURN_ALT {kLocPhysReg, 0, 0, 0, 0, 0, 1, r_F0, INVALID_REG, \
INVALID_SREG}
-#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_V0, r_V1,\
- INVALID_SREG}
-#define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_F0, r_F1,\
+#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_RESULT0, r_RESULT1,\
INVALID_SREG}
+#define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_FRESULT0,\
+ r_FRESULT1, INVALID_SREG}
typedef enum ResourceEncodingPos {
kGPReg0 = 0,
@@ -194,25 +194,6 @@ typedef enum ResourceEncodingPos {
#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
/*
- * FIXME:
- * Originally had r4PC as r_S0, rFP as r_S1, rSELF as r_S2, rINST as r_S4
- * Remap - don't need r4PC, rFP or rINST. Might make sense to keep
- * Method* in one of these since we have so many registers to play with.
- */
-
-#define rSUSPEND r_S0
-#define rSELF r_S1
-#define rSP r_SP
-
-#define rARG0 r_ARG0
-#define rARG1 r_ARG1
-#define rARG2 r_ARG2
-#define rARG3 r_ARG3
-
-#define rRET0 r_V0
-#define rRET1 r_V1
-
-/*
* Annotate special-purpose core registers:
*/
@@ -307,6 +288,21 @@ typedef enum NativeRegisterPool {
r_PC,
} NativeRegisterPool;
+/*
+ * Target-independent aliases
+ */
+
+#define rSUSPEND r_S0
+#define rSELF r_S1
+#define rSP r_SP
+#define rARG0 r_ARG0
+#define rARG1 r_ARG1
+#define rARG2 r_ARG2
+#define rARG3 r_ARG3
+#define rRET0 r_RESULT0
+#define rRET1 r_RESULT1
+#define rLINK r_RA
+
/* Shift encodings */
typedef enum MipsShiftEncodings {
kMipsLsl = 0x0,
@@ -335,15 +331,9 @@ typedef enum MipsConditionCode {
kMipsCondNv = 0xf, /* 1111 */
} MipsConditionCode;
-typedef enum MipsThrowKind {
- kMipsThrowNullPointer,
- kMipsThrowDivZero,
- kMipsThrowArrayBounds,
- kMipsThrowVerificationError,
- kMipsThrowNegArraySize,
- kMipsThrowNoSuchMethod,
- kMipsThrowStackOverflow,
-} MipsThrowKind;
+// FIXME: Need support for barriers. Adding these defines to allow compile
+#define kST 0
+#define kSY 1
#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
@@ -487,6 +477,8 @@ typedef enum MipsOpFeatureFlags {
kUsesCCodes,
kMemLoad,
kMemStore,
+ kPCRelFixup,
+// FIXME: add NEEDS_FIXUP to instruction attributes
} MipsOpFeatureFlags;
#define IS_LOAD (1 << kMemLoad)
@@ -514,6 +506,12 @@ typedef enum MipsOpFeatureFlags {
#define IS_IT (1 << kIsIT)
#define SETS_CCODES (1 << kSetsCCodes)
#define USES_CCODES (1 << kUsesCCodes)
+#define NEEDS_FIXUP (1 << kPCRelFixup)
+
+/* attributes, included for compatibility */
+#define REG_DEF_FPCS_LIST0 (0)
+#define REG_DEF_FPCS_LIST2 (0)
+
/* Common combo register usage patterns */
#define REG_USE01 (REG_USE0 | REG_USE1)
@@ -559,63 +557,6 @@ typedef enum MipsTargetOptHints {
extern MipsEncodingMap EncodingMap[kMipsLast];
-/*
- * Each instance of this struct holds a pseudo or real LIR instruction:
- * - pseudo ones (eg labels and marks) and will be discarded by the assembler.
- * - real ones will be assembled
- *
- * FIXME: notes below are Arm-specific. We have 32 core registers instead
- * of 16, and no IT blocks. Must widen this or overload in order to
- * support all 32 FP regs. Perhaps use r0 for ccodes, eliminate IT block
- * and overload gp with fp status word? (or just use a single bit for
- * both core and fp condition code/status word?
- *
- * Machine resources are encoded into a 64-bit vector, where the encodings are
- * as following:
- * - [ 0..15]: general purpose registers including PC, SP, and LR
- * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
- * starts at bit 16
- * - [48]: IT block
- * - [49]: integer condition code
- * - [50]: floatint-point status word
- */
-typedef struct MipsLIR {
- LIR generic;
- MipsOpCode opcode;
- int operands[4]; // [0..3] = [dest, src1, src2, extra]
- struct {
- bool isNop:1; // LIR is optimized away
- bool pcRelFixup:1; // May need pc-relative fixup
- unsigned int age:4; // default is 0, set lazily by the optimizer
- unsigned int size:3; // in bytes
- unsigned int unused:23;
- } flags;
- int aliasInfo; // For Dalvik register access & litpool disambiguation
- u8 useMask; // Resource mask for use
- u8 defMask; // Resource mask for def
-} MipsLIR;
-
-typedef struct SwitchTable {
- int offset;
- const u2* table; // Original dex table
- int vaddr; // Dalvik offset of switch opcode
- MipsLIR* bxInst; // Switch indirect branch instruction
- MipsLIR** targets; // Array of case targets
-} SwitchTable;
-
-typedef struct FillArrayData {
- int offset;
- const u2* table; // Original dex table
- int size;
- int vaddr; // Dalvik offset of OP_FILL_ARRAY_DATA opcode
-} FillArrayData;
-
-/* Utility macros to traverse the LIR/MipsLIR list */
-#define NEXT_LIR(lir) ((MipsLIR *) lir->generic.next)
-#define PREV_LIR(lir) ((MipsLIR *) lir->generic.prev)
-
-#define NEXT_LIR_LVALUE(lir) (lir)->generic.next
-#define PREV_LIR_LVALUE(lir) (lir)->generic.prev
#define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535))
#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766))
diff --git a/src/compiler/codegen/mips/MipsRallocUtil.cc b/src/compiler/codegen/mips/MipsRallocUtil.cc
index 0dfbfa5065..504375b572 100644
--- a/src/compiler/codegen/mips/MipsRallocUtil.cc
+++ b/src/compiler/codegen/mips/MipsRallocUtil.cc
@@ -48,20 +48,6 @@ void oatAdjustSpillMask(CompilationUnit* cUnit)
void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
{
UNIMPLEMENTED(FATAL) << "No support yet for promoted FP regs";
-#if 0
- DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
- reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
- // Ensure fpVmapTable is large enough
- int tableSize = cUnit->fpVmapTable.size();
- for (int i = tableSize; i < (reg + 1); i++) {
- cUnit->fpVmapTable.push_back(INVALID_VREG);
- }
- // Add the current mapping
- cUnit->fpVmapTable[reg] = sReg;
- // Size of fpVmapTable is high-water mark, use to set mask
- cUnit->numFPSpills = cUnit->fpVmapTable.size();
- cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
-#endif
}
void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
@@ -159,10 +145,10 @@ extern void oatClobberCalleeSave(CompilationUnit *cUnit)
extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)
{
RegLocation res = LOC_C_RETURN_WIDE;
- oatClobber(cUnit, r_V0);
- oatClobber(cUnit, r_V1);
- oatMarkInUse(cUnit, r_V0);
- oatMarkInUse(cUnit, r_V1);
+ oatClobber(cUnit, res.lowReg);
+ oatClobber(cUnit, res.highReg);
+ oatMarkInUse(cUnit, res.lowReg);
+ oatMarkInUse(cUnit, res.highReg);
oatMarkPair(cUnit, res.lowReg, res.highReg);
return res;
}
@@ -170,10 +156,10 @@ extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)
extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
{
RegLocation res = LOC_C_RETURN_WIDE_ALT;
- oatClobber(cUnit, r_F0);
- oatClobber(cUnit, r_F1);
- oatMarkInUse(cUnit, r_F0);
- oatMarkInUse(cUnit, r_F1);
+ oatClobber(cUnit, res.lowReg);
+ oatClobber(cUnit, res.highReg);
+ oatMarkInUse(cUnit, res.lowReg);
+ oatMarkInUse(cUnit, res.highReg);
oatMarkPair(cUnit, res.lowReg, res.highReg);
return res;
}
@@ -181,16 +167,16 @@ extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
extern RegLocation oatGetReturn(CompilationUnit* cUnit)
{
RegLocation res = LOC_C_RETURN;
- oatClobber(cUnit, r_V0);
- oatMarkInUse(cUnit, r_V0);
+ oatClobber(cUnit, res.lowReg);
+ oatMarkInUse(cUnit, res.lowReg);
return res;
}
extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
{
RegLocation res = LOC_C_RETURN_ALT;
- oatClobber(cUnit, r_F0);
- oatMarkInUse(cUnit, r_F0);
+ oatClobber(cUnit, res.lowReg);
+ oatMarkInUse(cUnit, res.lowReg);
return res;
}
@@ -203,25 +189,25 @@ extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
/* To be used when explicitly managing register use */
extern void oatLockCallTemps(CompilationUnit* cUnit)
{
- oatLockTemp(cUnit, r_A0);
- oatLockTemp(cUnit, r_A1);
- oatLockTemp(cUnit, r_A2);
- oatLockTemp(cUnit, r_A3);
+ oatLockTemp(cUnit, rARG0);
+ oatLockTemp(cUnit, rARG1);
+ oatLockTemp(cUnit, rARG2);
+ oatLockTemp(cUnit, rARG3);
}
/* To be used when explicitly managing register use */
extern void oatFreeCallTemps(CompilationUnit* cUnit)
{
- oatFreeTemp(cUnit, r_A0);
- oatFreeTemp(cUnit, r_A1);
- oatFreeTemp(cUnit, r_A2);
- oatFreeTemp(cUnit, r_A3);
+ oatFreeTemp(cUnit, rARG0);
+ oatFreeTemp(cUnit, rARG1);
+ oatFreeTemp(cUnit, rARG2);
+ oatFreeTemp(cUnit, rARG3);
}
/* Convert an instruction to a NOP */
-STATIC void oatNopLIR( LIR* lir)
+void oatNopLIR( LIR* lir)
{
- ((MipsLIR*)lir)->flags.isNop = true;
+ ((LIR*)lir)->flags.isNop = true;
}
} // namespace art
diff --git a/src/compiler/codegen/mips/mips/Codegen.cc b/src/compiler/codegen/mips/mips/Codegen.cc
index 22a7c94209..71f43e55fd 100644
--- a/src/compiler/codegen/mips/mips/Codegen.cc
+++ b/src/compiler/codegen/mips/mips/Codegen.cc
@@ -15,7 +15,7 @@
*/
#define _CODEGEN_C
-#define TGT_LIR MipsLIR
+#define TARGET_MIPS
#include "../../../Dalvik.h"
#include "../../../CompilerInternals.h"
@@ -24,12 +24,16 @@
#include "../Codegen.h"
/* Mips codegen building blocks */
-#include "../CodegenCommon.cc"
+#include "../../CodegenUtil.cc"
/* Mips-specific factory utilities */
#include "../Mips32/Factory.cc"
-/* Target indepedent factory utilities */
+/* Target independent factory utilities */
#include "../../CodegenFactory.cc"
+/* Target independent gen routines */
+#include "../../GenCommon.cc"
+/* Shared invoke gen routines */
+#include "../../GenInvoke.cc"
/* Mips-specific factory utilities */
#include "../ArchFactory.cc"
@@ -47,8 +51,5 @@
/* Target-independent local optimizations */
#include "../../LocalOptimizations.cc"
-/* Common codegen utility code */
-#include "../../CodegenUtil.cc"
-
/* Architecture manifest */
#include "ArchVariant.cc"