diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc index c86b2e9043d8..c32632d51157 100644 --- a/runtime/vm/assembler_arm.cc +++ b/runtime/vm/assembler_arm.cc @@ -105,6 +105,8 @@ void Assembler::EmitMemOp(Condition cond, Address ad) { ASSERT(rd != kNoRegister); ASSERT(cond != kNoCondition); + ASSERT(!ad.has_writeback() || (ad.rn() != rd)); // Unpredictable. + int32_t encoding = (static_cast(cond) << kConditionShift) | B26 | (ad.kind() == Address::Immediate ? 0 : B25) | (load ? L : 0) | diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h index 349a50e67295..80b888bc62e2 100644 --- a/runtime/vm/assembler_arm.h +++ b/runtime/vm/assembler_arm.h @@ -321,6 +321,11 @@ class Address : public ValueObject { Mode mode() const { return static_cast(encoding() & kModeMask); } + bool has_writeback() const { + return (mode() == PreIndex) || (mode() == PostIndex) || + (mode() == NegPreIndex) || (mode() == NegPostIndex); + } + uint32_t encoding() const { return encoding_; } // Encoding for addressing mode 3. diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc index f3664d7e74fd..74464c85688c 100644 --- a/runtime/vm/simulator_arm.cc +++ b/runtime/vm/simulator_arm.cc @@ -1996,6 +1996,7 @@ void Simulator::DecodeType01(Instr* instr) { HandleIllegalAccess(addr, instr); } else { if (write_back) { + ASSERT(rd != rn); // Unpredictable. set_register(rn, rn_val); } if (!instr->HasSign()) { @@ -2312,6 +2313,7 @@ void Simulator::DecodeType2(Instr* instr) { HandleIllegalAccess(addr, instr); } else { if (write_back) { + ASSERT(rd != rn); // Unpredictable. set_register(rn, rn_val); } if (instr->HasB()) { @@ -2424,6 +2426,7 @@ void Simulator::DecodeType3(Instr* instr) { HandleIllegalAccess(addr, instr); } else { if (write_back) { + ASSERT(rd != rn); // Unpredictable. set_register(rn, rn_val); } if (instr->HasB()) { diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc index 94cf00b33d08..711c901cab2c 100644 --- a/runtime/vm/stub_code_arm.cc +++ b/runtime/vm/stub_code_arm.cc @@ -419,6 +419,9 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ eor(IP, IP, Operand(LR)); // Set up the frame manually with return address now stored in IP. + COMPILE_ASSERT(PP < CODE_REG); + COMPILE_ASSERT(CODE_REG < FP); + COMPILE_ASSERT(FP < IP); __ EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << IP), 0); __ LoadPoolPointer(); @@ -434,9 +437,12 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, if (i == CODE_REG) { // Save the original value of CODE_REG pushed before invoking this stub // instead of the value used to call this stub. - COMPILE_ASSERT(IP > CODE_REG); // Assert IP is pushed first. __ ldr(IP, Address(FP, kCallerSpSlotFromFp * kWordSize)); __ Push(IP); + } else if (i == SP) { + // Push(SP) has unpredictable behavior. + __ mov(IP, Operand(SP)); + __ Push(IP); } else { __ Push(static_cast(i)); }