Index: runtime/vm/assembler_arm.cc |
=================================================================== |
--- runtime/vm/assembler_arm.cc (revision 35547) |
+++ runtime/vm/assembler_arm.cc (working copy) |
@@ -416,20 +416,33 @@ |
void Assembler::mla(Register rd, Register rn, |
Register rm, Register ra, Condition cond) { |
- // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
- EmitMulOp(cond, B21, ra, rd, rn, rm); |
+ // rd <- ra + rn * rm. |
+ if (TargetCPUFeatures::arm_version() == ARMv7) { |
+ // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
+ EmitMulOp(cond, B21, ra, rd, rn, rm); |
+ } else { |
+ mul(IP, rn, rm, cond); |
+ add(rd, ra, ShifterOperand(IP), cond); |
+ } |
} |
void Assembler::mls(Register rd, Register rn, |
Register rm, Register ra, Condition cond) { |
- // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
- EmitMulOp(cond, B22 | B21, ra, rd, rn, rm); |
+ // rd <- ra - rn * rm. |
+ if (TargetCPUFeatures::arm_version() == ARMv7) { |
+ // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. |
+ EmitMulOp(cond, B22 | B21, ra, rd, rn, rm); |
+ } else { |
+ mul(IP, rn, rm, cond); |
+ sub(rd, ra, ShifterOperand(IP), cond); |
+ } |
} |
void Assembler::smull(Register rd_lo, Register rd_hi, |
Register rn, Register rm, Condition cond) { |
+ ASSERT(TargetCPUFeatures::arm_version() == ARMv7); |
// Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm); |
} |
@@ -437,6 +450,7 @@ |
void Assembler::umull(Register rd_lo, Register rd_hi, |
Register rn, Register rm, Condition cond) { |
+ ASSERT(TargetCPUFeatures::arm_version() == ARMv7); |
// Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm); |
} |
@@ -444,6 +458,7 @@ |
void Assembler::smlal(Register rd_lo, Register rd_hi, |
Register rn, Register rm, Condition cond) { |
+ ASSERT(TargetCPUFeatures::arm_version() == ARMv7); |
// Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
EmitMulOp(cond, B23 | B22 | B21, rd_lo, rd_hi, rn, rm); |
} |
@@ -451,6 +466,7 @@ |
void Assembler::umlal(Register rd_lo, Register rd_hi, |
Register rn, Register rm, Condition cond) { |
+ ASSERT(TargetCPUFeatures::arm_version() == ARMv7); |
// Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. |
EmitMulOp(cond, B23 | B21, rd_lo, rd_hi, rn, rm); |
} |
@@ -2581,6 +2597,60 @@ |
} |
+// If we aren't on ARMv7, there is no smull, and we have to check for overflow |
+// manually. |
+void Assembler::CheckMultSignedOverflow(Register left, |
+ Register right, |
+ Register tmp, |
+ DRegister dtmp0, DRegister dtmp1, |
+ Label* overflow) { |
+ Label done, left_neg, left_pos_right_neg, left_neg_right_pos; |
+ |
+ CompareImmediate(left, 0); |
+ b(&left_neg, LT); |
+ b(&done, EQ); |
+ CompareImmediate(right, 0); |
+ b(&left_pos_right_neg, LT); |
+ b(&done, EQ); |
+ |
+ // Both positive. |
+ LoadImmediate(tmp, INT_MAX); |
+ IntegerDivide(tmp, tmp, left, dtmp0, dtmp1); |
+ cmp(tmp, ShifterOperand(right)); |
+ b(overflow, LT); |
+ b(&done); |
+ |
+ // left positive, right non-positive. |
+ Bind(&left_pos_right_neg); |
+ LoadImmediate(tmp, INT_MIN); |
+ IntegerDivide(tmp, tmp, left, dtmp0, dtmp1); |
+ cmp(tmp, ShifterOperand(right)); |
+ b(overflow, GT); |
+ b(&done); |
+ |
+ Bind(&left_neg); |
+ CompareImmediate(right, 0); |
+ b(&left_neg_right_pos, GT); |
+ b(&done, EQ); |
+ |
+ // both negative. |
+ LoadImmediate(tmp, INT_MAX); |
+ IntegerDivide(tmp, tmp, left, dtmp0, dtmp1); |
+ cmp(tmp, ShifterOperand(right)); |
+ b(overflow, GT); |
+ b(&done); |
+ |
+ // left non-positive, right positive. |
+ Bind(&left_neg_right_pos); |
+ LoadImmediate(tmp, INT_MIN); |
+ IntegerDivide(tmp, tmp, right, dtmp0, dtmp1); |
+ cmp(tmp, ShifterOperand(left)); |
+ b(overflow, GT); |
+ |
+ Bind(&done); |
+} |
+ |
+ |
static int NumRegsBelowFP(RegList regs) { |
int count = 0; |
for (int i = 0; i < FP; i++) { |