Index: runtime/vm/assembler_arm.cc |
=================================================================== |
--- runtime/vm/assembler_arm.cc (revision 44777) |
+++ runtime/vm/assembler_arm.cc (working copy) |
@@ -435,7 +435,6 @@ |
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); |
} |
@@ -540,15 +539,27 @@ |
} |
-void Assembler::ldrd(Register rd, Address ad, Condition cond) { |
+void Assembler::ldrd(Register rd, Register rn, int32_t offset, Condition cond) { |
ASSERT((rd % 2) == 0); |
- EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad); |
+ if (TargetCPUFeatures::arm_version() == ARMv5TE) { |
+ const Register rd2 = static_cast<Register>(static_cast<int32_t>(rd) + 1); |
+ ldr(rd, Address(rn, offset), cond); |
+ ldr(rd2, Address(rn, offset + kWordSize), cond); |
+ } else { |
+ EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, Address(rn, offset)); |
+ } |
} |
-void Assembler::strd(Register rd, Address ad, Condition cond) { |
+void Assembler::strd(Register rd, Register rn, int32_t offset, Condition cond) { |
ASSERT((rd % 2) == 0); |
- EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad); |
+ if (TargetCPUFeatures::arm_version() == ARMv5TE) { |
+ const Register rd2 = static_cast<Register>(static_cast<int32_t>(rd) + 1); |
+ str(rd, Address(rn, offset), cond); |
+ str(rd2, Address(rn, offset + kWordSize), cond); |
+ } else { |
+ EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, Address(rn, offset)); |
+ } |
} |
@@ -556,11 +567,6 @@ |
Condition cond) { |
ASSERT(regs != 0); |
EmitMultiMemOp(cond, am, true, base, regs); |
- if (TargetCPUFeatures::arm_version() == ARMv5TE) { |
- // On ARMv5, touching a "banked" register after an ldm gives undefined |
- // behavior, so we just add a nop here to make that case easy to avoid. |
- nop(); |
- } |
} |
@@ -568,11 +574,6 @@ |
Condition cond) { |
ASSERT(regs != 0); |
EmitMultiMemOp(cond, am, false, base, regs); |
- if (TargetCPUFeatures::arm_version() == ARMv5TE) { |
- // On ARMv5, touching a "banked" register after an stm gives undefined |
- // behavior, so we just add a nop here to make that case easy to avoid. |
- nop(); |
- } |
} |
@@ -1676,10 +1677,10 @@ |
ASSERT(base != value_odd); |
Operand shadow(GetVerifiedMemoryShadow()); |
add(base, base, shadow, cond); |
- strd(value_even, Address(base, offset), cond); |
+ strd(value_even, base, offset, cond); |
sub(base, base, shadow, cond); |
} |
- strd(value_even, Address(base, offset), cond); |
+ strd(value_even, base, offset, cond); |
} |
@@ -2794,7 +2795,7 @@ |
ldr(reg, Address(base, offset), cond); |
break; |
case kWordPair: |
- ldrd(reg, Address(base, offset), cond); |
+ ldrd(reg, base, offset, cond); |
break; |
default: |
UNREACHABLE(); |
@@ -2826,7 +2827,7 @@ |
str(reg, Address(base, offset), cond); |
break; |
case kWordPair: |
- strd(reg, Address(base, offset), cond); |
+ strd(reg, base, offset, cond); |
break; |
default: |
UNREACHABLE(); |
@@ -3132,60 +3133,6 @@ |
} |
-// 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, Operand(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, Operand(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, Operand(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, Operand(left)); |
- b(overflow, GT); |
- |
- Bind(&done); |
-} |
- |
- |
static int NumRegsBelowFP(RegList regs) { |
int count = 0; |
for (int i = 0; i < FP; i++) { |
@@ -3323,7 +3270,11 @@ |
// optimized function and there may be extra space for spill slots to |
// allocate. We must also set up the pool pointer for the function. |
void Assembler::EnterOsrFrame(intptr_t extra_size) { |
- const intptr_t offset = CodeSize(); |
+ // The offset for the PC marker is adjusted by the difference in PC offset |
+ // between stores and other instructions. In particular, on some ARMv5's the |
+ // PC offset for stores is 12 and the offset in other instructions is 8. |
+ const intptr_t offset = CodeSize() - |
+ (TargetCPUFeatures::store_pc_read_offset() - Instr::kPCReadOffset); |
Comment("EnterOsrFrame"); |
mov(IP, Operand(PC)); |