summaryrefslogtreecommitdiffstats
path: root/vm/compiler/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler/codegen')
-rw-r--r--vm/compiler/codegen/arm/ArmLIR.h6
-rw-r--r--vm/compiler/codegen/arm/Assemble.cpp15
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.cpp48
-rw-r--r--vm/compiler/codegen/arm/Thumb2/Factory.cpp21
4 files changed, 88 insertions, 2 deletions
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index e159aecdb..d6d17575a 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -613,8 +613,14 @@ typedef enum ArmOpcode {
[10110000] imm4l[3-0] */
kThumb2Mla, /* mla [111110110000] rn[19-16] ra[15-12] rd[7-4]
[0000] rm[3-0] */
+ kThumb2MlsRRRR, /* mls [1111101110000] rn[19-16] ra[15-12] rd[11-8]
+ [0001] rm[3-0] */
kThumb2Umull, /* umull [111110111010] rn[19-16], rdlo[15-12]
rdhi[11-8] [0000] rm[3-0] */
+ kThumb2SdivRRR, /* sdiv [1111101111001 rn[19-16] [1111] rd[11-8]
+ [1111] rm[3-0] */
+ kThumb2UdivRRR, /* udiv [1111101111011 rn[19-16] [1111] rd[11-8]
+ [1111] rm[3-0] */
kThumb2Ldrex, /* ldrex [111010000101] rn[19-16] rt[11-8] [1111]
imm8[7-0] */
kThumb2Strex, /* strex [111010000100] rn[19-16] rt[11-8] rd[11-8]
diff --git a/vm/compiler/codegen/arm/Assemble.cpp b/vm/compiler/codegen/arm/Assemble.cpp
index 10572eb5f..d4707867e 100644
--- a/vm/compiler/codegen/arm/Assemble.cpp
+++ b/vm/compiler/codegen/arm/Assemble.cpp
@@ -847,11 +847,26 @@ ArmEncodingMap EncodingMap[kArmLast] = {
kFmtBitBlt, 15, 12,
IS_QUAD_OP | REG_DEF0 | REG_USE1 | REG_USE2 | REG_USE3,
"mla", "r!0d, r!1d, r!2d, r!3d", 2),
+ ENCODING_MAP(kThumb2MlsRRRR, 0xfb000010,
+ kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
+ kFmtBitBlt, 15, 12,
+ IS_QUAD_OP | REG_DEF0 | REG_USE1 | REG_USE2 | REG_USE3,
+ "mls", "r!0d, r!1d, r!2d, r!3d", 2),
ENCODING_MAP(kThumb2Umull, 0xfba00000,
kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16,
kFmtBitBlt, 3, 0,
IS_QUAD_OP | REG_DEF0 | REG_DEF1 | REG_USE2 | REG_USE3,
"umull", "r!0d, r!1d, r!2d, r!3d", 2),
+ ENCODING_MAP(kThumb2SdivRRR, 0xfb90f0f0,
+ kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0,
+ kFmtUnused, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "sdiv", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(kThumb2UdivRRR, 0xfbb0f0f0,
+ kFmtBitBlt, 19, 16, kFmtBitBlt, 11, 8, kFmtBitBlt, 3, 0,
+ kFmtUnused, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0 | REG_USE1 | REG_USE2,
+ "udiv", "r!0d, r!1d, r!2d", 2),
ENCODING_MAP(kThumb2Ldrex, 0xe8500f00,
kFmtBitBlt, 15, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0,
kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD,
diff --git a/vm/compiler/codegen/arm/CodegenDriver.cpp b/vm/compiler/codegen/arm/CodegenDriver.cpp
index c2c112b3b..3f00f4385 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.cpp
+++ b/vm/compiler/codegen/arm/CodegenDriver.cpp
@@ -783,6 +783,7 @@ static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
int (*callTgt)(int, int);
RegLocation rlResult;
bool shiftOp = false;
+ bool remOp = false;
switch (mir->dalvikInsn.opcode) {
case OP_NEG_INT:
@@ -807,18 +808,27 @@ static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
break;
case OP_DIV_INT:
case OP_DIV_INT_2ADDR:
+#ifdef __ARM_ARCH_EXT_IDIV__
+ op = kOpDiv;
+#else
callOut = true;
- checkZero = true;
callTgt = __aeabi_idiv;
retReg = r0;
+#endif
+ checkZero = true;
break;
/* NOTE: returns in r1 */
case OP_REM_INT:
case OP_REM_INT_2ADDR:
+#ifdef __ARM_ARCH_EXT_IDIV__
+ op = kOpRem;
+ remOp = true;
+#else
callOut = true;
- checkZero = true;
callTgt = __aeabi_idivmod;
retReg = r1;
+#endif
+ checkZero = true;
break;
case OP_AND_INT:
case OP_AND_INT_2ADDR:
@@ -860,6 +870,11 @@ static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
rlSrc1.lowReg);
} else {
rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
+#ifdef __ARM_ARCH_EXT_IDIV__
+ if (checkZero) {
+ genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL);
+ }
+#endif
if (shiftOp) {
int tReg = dvmCompilerAllocTemp(cUnit);
opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
@@ -867,6 +882,14 @@ static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
opRegRegReg(cUnit, op, rlResult.lowReg,
rlSrc1.lowReg, tReg);
dvmCompilerFreeTemp(cUnit, tReg);
+ } else if(remOp) {
+ int tReg = dvmCompilerAllocTemp(cUnit);
+ opRegRegReg(cUnit, kOpDiv, tReg,
+ rlSrc1.lowReg, rlSrc2.lowReg);
+ rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
+ opRegRegRegReg(cUnit, op, rlResult.lowReg,
+ rlSrc2.lowReg, tReg, rlSrc1.lowReg);
+ dvmCompilerFreeTemp(cUnit, tReg);
} else {
rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
opRegRegReg(cUnit, op, rlResult.lowReg,
@@ -2273,6 +2296,7 @@ static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
OpKind op = (OpKind)0; /* Make gcc happy */
int shiftOp = false;
bool isDiv = false;
+ bool isRem = false;
switch (dalvikOpcode) {
case OP_RSUB_INT_LIT8:
@@ -2342,6 +2366,17 @@ static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
if (handleEasyDivide(cUnit, dalvikOpcode, rlSrc, rlDest, lit)) {
return false;
}
+#ifdef __ARM_ARCH_EXT_IDIV__
+ if ((dalvikOpcode == OP_DIV_INT_LIT8) ||
+ (dalvikOpcode == OP_DIV_INT_LIT16)) {
+ op = kOpDiv;
+ }
+ else {
+ isRem = true;
+ op = kOpRem;
+ }
+ break;
+#endif
dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
loadValueDirectFixed(cUnit, rlSrc, r0);
dvmCompilerClobber(cUnit, r0);
@@ -2371,6 +2406,15 @@ static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
// Avoid shifts by literal 0 - no support in Thumb. Change to copy
if (shiftOp && (lit == 0)) {
genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
+ } else if(isRem) {
+ int tReg1 = dvmCompilerAllocTemp(cUnit);
+ int tReg2 = dvmCompilerAllocTemp(cUnit);
+
+ loadConstant(cUnit, tReg2, lit);
+ opRegRegReg(cUnit, kOpDiv, tReg1, rlSrc.lowReg, tReg2);
+ opRegRegRegReg(cUnit, op, rlResult.lowReg, tReg2, tReg1, rlSrc.lowReg);
+ dvmCompilerFreeTemp(cUnit, tReg1);
+ dvmCompilerFreeTemp(cUnit, tReg2);
} else {
opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
}
diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.cpp b/vm/compiler/codegen/arm/Thumb2/Factory.cpp
index b9265e823..cc036cb8b 100644
--- a/vm/compiler/codegen/arm/Thumb2/Factory.cpp
+++ b/vm/compiler/codegen/arm/Thumb2/Factory.cpp
@@ -352,6 +352,10 @@ static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
assert(shift == 0);
opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
break;
+ case kOpDiv:
+ assert(shift == 0);
+ opcode = kThumb2SdivRRR;
+ break;
case kOpMvn:
opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
break;
@@ -454,6 +458,13 @@ static ArmLIR *opRegRegRegShift(CompilationUnit *cUnit, OpKind op,
assert(shift == 0);
opcode = kThumb2MulRRR;
break;
+ case kOpDiv:
+ assert(shift == 0);
+ opcode = kThumb2SdivRRR;
+ break;
+ case kOpRem:
+ opcode = kThumb2MlsRRRR;
+ break;
case kOpOr:
opcode = kThumb2OrrRRR;
break;
@@ -495,6 +506,12 @@ static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
}
+static ArmLIR *opRegRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int rSrc2, int rSrc3)
+{
+ return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, rSrc3);
+}
+
static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
int rSrc1, int value)
{
@@ -586,6 +603,10 @@ static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
modImm = -1;
altOpcode = kThumb2MulRRR;
break;
+ case kOpDiv:
+ modImm = -1;
+ altOpcode = kThumb2SdivRRR;
+ break;
case kOpCmp: {
int modImm = modifiedImmediate(value);
ArmLIR *res;