Method prologue and epilogues, add missing x86 functionality.
Enables compiling and running a number of JNI internal managed code
methods on the host.
Change-Id: I56fceb813d0cb24637bc784ba57f2d1d16911d48
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index c43d8ff..e2c306d 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -94,7 +94,7 @@
/* Perform check on two registers */
LIR* genRegRegCheck(CompilationUnit* cUnit, ConditionCode cCode,
- int reg1, int reg2, MIR* mir, ThrowKind kind)
+ int reg1, int reg2, MIR* mir, ThrowKind kind)
{
LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind,
mir ? mir->offset : 0, reg1, reg2);
@@ -325,11 +325,15 @@
#endif
// Set up source pointer
RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
opRegRegImm(cUnit, kOpAdd, rSrc, rSP,
oatSRegOffset(cUnit, rlFirst.sRegLow));
// Set up the target pointer
opRegRegImm(cUnit, kOpAdd, rDst, rRET0,
Array::DataOffset(component_size).Int32Value());
+#endif
// Set up the loop counter (known to be > 0)
loadConstant(cUnit, rIdx, dInsn->vA - 1);
// Generate the copy loop. Going backwards for convenience
@@ -365,9 +369,6 @@
void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
bool isLongOrDouble, bool isObject)
{
-#if defined(TARGET_X86)
- UNIMPLEMENTED(WARNING) << "genSput";
-#else
int fieldOffset;
int ssbIndex;
bool isVolatile;
@@ -461,13 +462,16 @@
int rTgt = loadHelper(cUnit, setterOffset);
loadConstant(cUnit, rARG0, fieldIdx);
if (isLongOrDouble) {
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
loadValueDirectWideFixed(cUnit, rlSrc, rARG2, rARG3);
+#endif
} else {
loadValueDirect(cUnit, rlSrc, rARG1);
}
callRuntimeHelper(cUnit, rTgt);
}
-#endif
}
void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
@@ -598,9 +602,6 @@
void handleSuspendLaunchpads(CompilationUnit *cUnit)
{
-#if defined(TARGET_X86)
- UNIMPLEMENTED(WARNING);
-#else
LIR** suspendLabel =
(LIR **) cUnit->suspendLaunchpads.elemList;
int numElems = cUnit->suspendLaunchpads.numUsed;
@@ -616,7 +617,6 @@
opReg(cUnit, kOpBlx, rTgt);
opUnconditionalBranch(cUnit, resumeLab);
}
-#endif
}
void handleThrowLaunchpads(CompilationUnit *cUnit)
@@ -723,6 +723,15 @@
if (isLongOrDouble) {
DCHECK(rlDest.wide);
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null? */
+#if defined(TARGET_X86)
+ rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null? */
+ loadBaseDispWide(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
+ rlResult.highReg, rlObj.sRegLow);
+ if (isVolatile) {
+ oatGenMemBarrier(cUnit, kSY);
+ }
+#else
int regPtr = oatAllocTemp(cUnit);
opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
@@ -731,6 +740,7 @@
oatGenMemBarrier(cUnit, kSY);
}
oatFreeTemp(cUnit, regPtr);
+#endif
storeValueWide(cUnit, rlDest, rlResult);
} else {
rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
@@ -763,9 +773,6 @@
void genIPut(CompilationUnit* cUnit, MIR* mir, OpSize size, RegLocation rlSrc,
RegLocation rlObj, bool isLongOrDouble, bool isObject)
{
-#if defined(TARGET_X86)
- UNIMPLEMENTED(WARNING);
-#else
int fieldOffset;
bool isVolatile;
uint32_t fieldIdx = mir->dalvikInsn.vC;
@@ -813,14 +820,17 @@
int rTgt = loadHelper(cUnit, setterOffset);
loadValueDirect(cUnit, rlObj, rARG1);
if (isLongOrDouble) {
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
loadValueDirectWide(cUnit, rlSrc, rARG2, rARG3);
+#endif
} else {
loadValueDirect(cUnit, rlSrc, rARG2);
}
loadConstant(cUnit, rARG0, fieldIdx);
callRuntimeHelper(cUnit, rTgt);
}
-#endif
}
void genConstClass(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
@@ -1091,7 +1101,7 @@
/* rARG1 now contains object->clazz */
int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
pCheckCastFromCode));
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_X86)
LIR* branch2 = opCmpBranch(cUnit, kCondEq, rARG1, classReg, NULL);
#else
opRegReg(cUnit, kOpCmp, rARG1, classReg);
@@ -1188,7 +1198,6 @@
RegLocation rlResult;
rlArray = loadValue(cUnit, rlArray, kCoreReg);
rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
- int regPtr;
if (size == kLong || size == kDouble) {
dataOffset = Array::DataOffset(sizeof(int64_t)).Int32Value();
@@ -1199,14 +1208,36 @@
/* null object? */
genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
- regPtr = oatAllocTemp(cUnit);
+#if defined(TARGET_X86)
+ if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+ /* if (rlIndex >= [rlArray + lenOffset]) goto kThrowArrayBounds */
+ genRegMemCheck(cUnit, kCondUge, rlIndex.lowReg, rlArray.lowReg,
+ lenOffset, mir, kThrowArrayBounds);
+ }
+ if ((size == kLong) || (size == kDouble)) {
+ rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+ loadBaseIndexedDisp(cUnit, NULL, rlArray.lowReg, rlIndex.lowReg, scale, dataOffset,
+ rlResult.lowReg, rlResult.highReg, size, INVALID_SREG);
+ storeValueWide(cUnit, rlDest, rlResult);
+ } else {
+ rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+
+ loadBaseIndexedDisp(cUnit, NULL, rlArray.lowReg, rlIndex.lowReg, scale, dataOffset,
+ rlResult.lowReg, INVALID_REG, size, INVALID_SREG);
+
+ storeValue(cUnit, rlDest, rlResult);
+ }
+#else
+ int regPtr = oatAllocTemp(cUnit);
if (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
int regLen = oatAllocTemp(cUnit);
/* Get len */
loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
/* regPtr -> array data */
opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
+ // TODO: change kCondCS to a more meaningful name, is the sense of
+ // carry-set/clear flipped?
genRegRegCheck(cUnit, kCondCs, rlIndex.lowReg, regLen, mir,
kThrowArrayBounds);
oatFreeTemp(cUnit, regLen);
@@ -1240,6 +1271,7 @@
oatFreeTemp(cUnit, regPtr);
storeValue(cUnit, rlDest, rlResult);
}
+#endif
}
/*
@@ -1405,11 +1437,10 @@
bool callOut = false;
bool checkZero = false;
bool unary = false;
- int retReg = rRET0;
- int funcOffset;
RegLocation rlResult;
bool shiftOp = false;
-
+ int funcOffset;
+ int retReg = rRET0;
switch (mir->dalvikInsn.opcode) {
case Instruction::NEG_INT:
op = kOpNeg;
@@ -1433,16 +1464,18 @@
break;
case Instruction::DIV_INT:
case Instruction::DIV_INT_2ADDR:
- callOut = true;
checkZero = true;
+ op = kOpDiv;
+ callOut = true;
funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
retReg = rRET0;
break;
/* NOTE: returns in rARG1 */
case Instruction::REM_INT:
case Instruction::REM_INT_2ADDR:
- callOut = true;
checkZero = true;
+ op = kOpRem;
+ callOut = true;
funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
retReg = rRET1;
break;
@@ -1485,6 +1518,11 @@
rlSrc1.lowReg);
} else {
rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
+#if defined(TARGET_X86)
+ rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ opRegRegReg(cUnit, op, rlResult.lowReg,
+ rlSrc1.lowReg, rlSrc2.lowReg);
+#else
if (shiftOp) {
int tReg = oatAllocTemp(cUnit);
opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
@@ -1497,6 +1535,7 @@
opRegRegReg(cUnit, op, rlResult.lowReg,
rlSrc1.lowReg, rlSrc2.lowReg);
}
+#endif
}
storeValue(cUnit, rlDest, rlResult);
} else {
@@ -1782,10 +1821,6 @@
bool genArithOpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
RegLocation rlSrc1, RegLocation rlSrc2)
{
-#if defined(TARGET_X86)
- UNIMPLEMENTED(WARNING) << "genArithOpLong";
- return false;
-#else
RegLocation rlResult;
OpKind firstOp = kOpBkpt;
OpKind secondOp = kOpBkpt;
@@ -1879,7 +1914,11 @@
int rTgt;
oatFlushAllRegs(cUnit); /* Send everything to home location */
if (checkZero) {
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+#endif
rTgt = loadHelper(cUnit, funcOffset);
loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
int tReg = oatAllocTemp(cUnit);
@@ -1888,14 +1927,22 @@
oatFreeTemp(cUnit, tReg);
genCheck(cUnit, kCondEq, mir, kThrowDivZero);
#else
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
opRegRegReg(cUnit, kOpOr, tReg, rARG2, rARG3);
+#endif
genImmedCheck(cUnit, kCondEq, tReg, 0, mir, kThrowDivZero);
oatFreeTemp(cUnit, tReg);
#endif
} else {
rTgt = loadHelper(cUnit, funcOffset);
loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+#endif
}
callRuntimeHelper(cUnit, rTgt);
// Adjust return regs in to handle case of rem returning rARG2/rARG3
@@ -1906,7 +1953,6 @@
storeValueWide(cUnit, rlDest, rlResult);
}
return false;
-#endif
}
bool genConversionCall(CompilationUnit* cUnit, MIR* mir, int funcOffset,
@@ -1993,11 +2039,6 @@
RegLocation rlDest, RegLocation rlSrc1,
RegLocation rlSrc2)
{
-#if defined(TARGET_X86)
-//NOTE: probably don't need the portable versions for x86
- UNIMPLEMENTED(WARNING) << "genArithOpDoublePortable";
- return false;
-#else
RegLocation rlResult;
int funcOffset;
@@ -2032,12 +2073,15 @@
oatFlushAllRegs(cUnit); /* Send everything to home location */
int rTgt = loadHelper(cUnit, funcOffset);
loadValueDirectWideFixed(cUnit, rlSrc1, rARG0, rARG1);
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
loadValueDirectWideFixed(cUnit, rlSrc2, rARG2, rARG3);
+#endif
callRuntimeHelper(cUnit, rTgt);
rlResult = oatGetReturnWide(cUnit);
storeValueWide(cUnit, rlDest, rlResult);
return false;
-#endif
}
bool genConversionPortable(CompilationUnit* cUnit, MIR* mir)
@@ -2092,9 +2136,6 @@
*/
void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset)
{
-#if defined(TARGET_X86)
- UNIMPLEMENTED(WARNING);
-#else
// Following DCHECK verifies that dPC is in range of single load immediate
DCHECK((offset == DEBUGGER_METHOD_ENTRY) ||
(offset == DEBUGGER_METHOD_EXIT) || ((offset & 0xffff) == offset));
@@ -2104,6 +2145,8 @@
opIT(cUnit, kArmCondNe, "T");
loadConstant(cUnit, rARG2, offset); // arg2 <- Entry code
opReg(cUnit, kOpBlx, rSUSPEND);
+#elif defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
#else
LIR* branch = opCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0, NULL);
loadConstant(cUnit, rARG2, offset);
@@ -2112,15 +2155,11 @@
branch->target = (LIR*)target;
#endif
oatFreeTemp(cUnit, rARG2);
-#endif
}
/* Check if we need to check for pending suspend request */
void genSuspendTest(CompilationUnit* cUnit, MIR* mir)
{
-#if defined(TARGET_X86)
- UNIMPLEMENTED(WARNING) << "genSuspendTest";
-#else
if (NO_SUSPEND || (mir->optimizationFlags & MIR_IGNORE_SUSPEND_CHECK)) {
return;
}
@@ -2131,15 +2170,23 @@
pTestSuspendFromCode));
opReg(cUnit, kOpBlx, rTgt);
// Refresh rSUSPEND
+#if defined(TARGET_X86)
+ UNIMPLEMENTED(FATAL);
+#else
+
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode),
rSUSPEND);
+#endif
} else {
- LIR* branch;
+ LIR* branch = NULL;
#if defined(TARGET_ARM)
// In non-debug case, only check periodically
newLIR2(cUnit, kThumbSubRI8, rSUSPEND, 1);
branch = opCondBranch(cUnit, kCondEq, NULL);
+#elif defined(TARGET_X86)
+ newLIR2(cUnit, kX86Cmp32TI, Thread::SuspendCountOffset().Int32Value(), 0);
+ branch = opCondBranch(cUnit, kCondNe, NULL);
#else
opRegImm(cUnit, kOpSub, rSUSPEND, 1);
branch = opCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0, NULL);
@@ -2150,7 +2197,6 @@
branch->target = (LIR*)target;
oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)target);
}
-#endif
}
} // namespace art