Various bugfixes
divide by zero check for longs, off-by-one error on fill-array-data,
register management hygene, mvn encoding, iget/iput <= 32bits are
done as 32-bit (code was using type size for ld/st).
Change-Id: Ia09323e7d92f4ad21890af4c10f2f8c8f05f3b0e
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index ec37876..a68727f 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -51,6 +51,19 @@
#endif
}
+STATIC ArmLIR* genCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
+ MIR* mir, ArmThrowKind kind)
+{
+ ArmLIR* tgt = (ArmLIR*)oatNew(sizeof(ArmLIR), true);
+ tgt->opcode = kArmPseudoThrowTarget;
+ tgt->operands[0] = kind;
+ tgt->operands[1] = mir ? mir->offset : 0;
+ ArmLIR* branch = genConditionalBranch(cUnit, cCode, tgt);
+ // Remember branch target - will process later
+ oatInsertGrowableList(&cUnit->throwLaunchpads, (intptr_t)tgt);
+ return branch;
+}
+
STATIC ArmLIR* genImmedCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
int reg, int immVal, MIR* mir, ArmThrowKind kind)
{
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 8f71571..3b2e986 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -534,7 +534,7 @@
[0000] rm[3..0] */
kThumb2SubRRI12, /* sub rd, rn, #imm12 [11110] i [01010] rn[19..16]
[0] imm3[14..12] rd[11..8] imm8[7..0] */
- kThumb2MvnImmShift, /* mov(T2) rd, #<const> [11110] i [00011011110]
+ kThumb2MvnImm12, /* mov(T2) rd, #<const> [11110] i [00011011110]
imm3 rd[11..8] imm8 */
kThumb2Sel, /* sel rd, rn, rm [111110101010] rn[19-16] rd[11-8]
rm[3-0] */
@@ -691,6 +691,8 @@
kThumb2MovImm16HST, /* Special purpose version for switch table use */
kThumb2LdmiaWB, /* ldmia [111010011001[ rn[19..16] mask[15..0] */
kThumb2SubsRRI12, /* setflags encoding */
+ kThumb2OrrRRRs, /* orrx [111010100101] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
kArmLast,
} ArmOpcode;
diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc
index dff9ddd..c42b4b8 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -571,8 +571,8 @@
kFmtUnused, -1, -1,
IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
"sub", "!0C,!1C,#!2d", 2),
- ENCODING_MAP(kThumb2MvnImmShift, 0xf06f0000, /* no setflags encoding */
- kFmtBitBlt, 11, 8, kFmtModImm, -1, -1, kFmtUnused, -1, -1,
+ ENCODING_MAP(kThumb2MvnImm12, 0xf06f0000, /* no setflags encoding */
+ kFmtBitBlt, 11, 8, kFmtImm12, -1, -1, kFmtUnused, -1, -1,
kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
"mvn", "!0C, #!1n", 2),
ENCODING_MAP(kThumb2Sel, 0xfaa0f080,
@@ -955,6 +955,10 @@
kFmtUnused, -1, -1,
IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
"subs", "!0C,!1C,#!2d", 2),
+ ENCODING_MAP(kThumb2OrrRRRs, 0xea500000,
+ kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
+ kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
+ "orrs", "!0C, !1C, !2C!3H", 2),
};
@@ -1039,7 +1043,7 @@
&iterator);
if (tabRec == NULL) break;
alignBuffer(cUnit->codeBuffer, tabRec->offset);
- for (int i = 0; i < (tabRec->size / 2) ; i++) {
+ for (int i = 0; i < ((tabRec->size + 1) / 2) ; i++) {
cUnit->codeBuffer.push_back( tabRec->table[i]);
}
}
diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc
index c8e428f..3ee23ea 100644
--- a/src/compiler/codegen/arm/Thumb2/Factory.cc
+++ b/src/compiler/codegen/arm/Thumb2/Factory.cc
@@ -163,7 +163,7 @@
}
modImm = modifiedImmediate(~value);
if (modImm >= 0) {
- res = newLIR2(cUnit, kThumb2MvnImmShift, rDest, modImm);
+ res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm);
return res;
}
/* 16-bit immediate? */
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 5ef7687..3f7a7ae 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -460,7 +460,7 @@
rlObj = loadValue(cUnit, rlObj, kCoreReg);
rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
- loadBaseIndexed(cUnit, rlObj.lowReg, r0, rlResult.lowReg, 0, size);
+ loadBaseIndexed(cUnit, rlObj.lowReg, r0, rlResult.lowReg, 0, kWord);
oatGenMemBarrier(cUnit, kSY);
storeValue(cUnit, rlDest, rlResult);
} else {
@@ -474,7 +474,7 @@
rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
- size, rlObj.sRegLow);
+ kWord, rlObj.sRegLow);
if (isVolatile) {
oatGenMemBarrier(cUnit, kSY);
}
@@ -495,7 +495,7 @@
rlSrc = loadValue(cUnit, rlSrc, regClass);
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */
oatGenMemBarrier(cUnit, kSY);
- storeBaseIndexed(cUnit, rlObj.lowReg, r0, rlSrc.lowReg, 0, size);
+ storeBaseIndexed(cUnit, rlObj.lowReg, r0, rlSrc.lowReg, 0, kWord);
} else {
#if ANDROID_SMP != 0
bool isVolatile = fieldPtr->IsVolatile();
@@ -510,7 +510,7 @@
if (isVolatile) {
oatGenMemBarrier(cUnit, kST);
}
- storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
+ storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, kWord);
if (isVolatile) {
oatGenMemBarrier(cUnit, kSY);
}
@@ -1498,6 +1498,7 @@
OpKind firstOp = kOpBkpt;
OpKind secondOp = kOpBkpt;
bool callOut = false;
+ bool checkZero = false;
int funcOffset;
int retReg = r0;
@@ -1538,6 +1539,7 @@
case OP_DIV_LONG:
case OP_DIV_LONG_2ADDR:
callOut = true;
+ checkZero = true;
retReg = r0;
funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
break;
@@ -1545,6 +1547,7 @@
case OP_REM_LONG:
case OP_REM_LONG_2ADDR:
callOut = true;
+ checkZero = true;
funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
retReg = r2;
break;
@@ -1592,12 +1595,22 @@
if (!callOut) {
genLong3Addr(cUnit, mir, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
} else {
- // Adjust return regs in to handle case of rem returning r2/r3
oatFlushAllRegs(cUnit); /* Send everything to home location */
- loadWordDisp(cUnit, rSELF, funcOffset, rLR);
- loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
- loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
+ if (checkZero) {
+ loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
+ loadWordDisp(cUnit, rSELF, funcOffset, rLR);
+ loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
+ int tReg = oatAllocTemp(cUnit);
+ newLIR4(cUnit, kThumb2OrrRRRs, tReg, r2, r3, 0);
+ oatFreeTemp(cUnit, tReg);
+ genCheck(cUnit, kArmCondEq, mir, kArmThrowDivZero);
+ } else {
+ loadWordDisp(cUnit, rSELF, funcOffset, rLR);
+ loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
+ loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
+ }
callRuntimeHelper(cUnit, rLR);
+ // Adjust return regs in to handle case of rem returning r2/r3
if (retReg == r0)
rlResult = oatGetReturnWide(cUnit);
else