| Index: runtime/vm/simulator_arm.cc
|
| ===================================================================
|
| --- runtime/vm/simulator_arm.cc (revision 40852)
|
| +++ runtime/vm/simulator_arm.cc (working copy)
|
| @@ -17,6 +17,7 @@
|
| #include "vm/constants_arm.h"
|
| #include "vm/cpu.h"
|
| #include "vm/disassembler.h"
|
| +#include "vm/lockers.h"
|
| #include "vm/native_arguments.h"
|
| #include "vm/stack_frame.h"
|
| #include "vm/thread.h"
|
| @@ -675,9 +676,60 @@
|
| }
|
|
|
|
|
| -void Simulator::InitOnce() {}
|
| +// Synchronization primitives support.
|
| +Mutex* Simulator::exclusive_access_lock_ = NULL;
|
| +Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags];
|
| +int Simulator::next_address_tag_;
|
|
|
|
|
| +void Simulator::SetExclusiveAccess(uword addr) {
|
| + Isolate* isolate = Isolate::Current();
|
| + ASSERT(isolate != NULL);
|
| + int i = 0;
|
| + while ((i < kNumAddressTags) &&
|
| + (exclusive_access_state_[i].isolate != isolate)) {
|
| + i++;
|
| + }
|
| + if (i == kNumAddressTags) {
|
| + i = next_address_tag_;
|
| + if (++next_address_tag_ == kNumAddressTags) next_address_tag_ = 0;
|
| + exclusive_access_state_[i].isolate = isolate;
|
| + }
|
| + exclusive_access_state_[i].addr = addr;
|
| +}
|
| +
|
| +
|
| +bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
|
| + Isolate* isolate = Isolate::Current();
|
| + ASSERT(isolate != NULL);
|
| + bool result = false;
|
| + for (int i = 0; i < kNumAddressTags; i++) {
|
| + if (exclusive_access_state_[i].isolate == isolate) {
|
| + if (exclusive_access_state_[i].addr == addr) {
|
| + result = true;
|
| + }
|
| + exclusive_access_state_[i].addr = NULL;
|
| + continue;
|
| + }
|
| + if (exclusive_access_state_[i].addr == addr) {
|
| + exclusive_access_state_[i].addr = NULL;
|
| + }
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +
|
| +void Simulator::InitOnce() {
|
| + // Setup exclusive access state.
|
| + exclusive_access_lock_ = new Mutex();
|
| + for (int i = 0; i < kNumAddressTags; i++) {
|
| + exclusive_access_state_[i].isolate = NULL;
|
| + exclusive_access_state_[i].addr = NULL;
|
| + }
|
| + next_address_tag_ = 0;
|
| +}
|
| +
|
| +
|
| Simulator::Simulator() {
|
| // Setup simulator support first. Some of this information is needed to
|
| // setup the architecture state.
|
| @@ -1059,6 +1111,53 @@
|
| }
|
|
|
|
|
| +// Synchronization primitives support.
|
| +void Simulator::ClearExclusive() {
|
| + // This lock is initialized in Simulator::InitOnce().
|
| + MutexLocker ml(exclusive_access_lock_);
|
| + // Set exclusive access to open state for this isolate.
|
| + HasExclusiveAccessAndOpen(NULL);
|
| +}
|
| +
|
| +
|
| +intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) {
|
| + // This lock is initialized in Simulator::InitOnce().
|
| + MutexLocker ml(exclusive_access_lock_);
|
| + SetExclusiveAccess(addr);
|
| + return ReadW(addr, instr);
|
| +}
|
| +
|
| +
|
| +intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) {
|
| + // This lock is initialized in Simulator::InitOnce().
|
| + MutexLocker ml(exclusive_access_lock_);
|
| + bool write_allowed = HasExclusiveAccessAndOpen(addr);
|
| + if (write_allowed) {
|
| + WriteW(addr, value, instr);
|
| + return 0; // Success.
|
| + }
|
| + return 1; // Failure.
|
| +}
|
| +
|
| +
|
| +uword Simulator::CompareExchange(uword* address,
|
| + uword compare_value,
|
| + uword new_value) {
|
| + // This lock is initialized in Simulator::InitOnce().
|
| + MutexLocker ml(exclusive_access_lock_);
|
| + uword value = *address;
|
| + if (value == compare_value) {
|
| + *address = new_value;
|
| + // Same effect on exclusive access state as a successful STREX.
|
| + HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address));
|
| + } else {
|
| + // Same effect on exclusive access state as an LDREX.
|
| + SetExclusiveAccess(reinterpret_cast<uword>(address));
|
| + }
|
| + return value;
|
| +}
|
| +
|
| +
|
| // Returns the top of the stack area to enable checking for stack pointer
|
| // validity.
|
| uword Simulator::StackTop() const {
|
| @@ -1739,7 +1838,39 @@
|
| }
|
| }
|
| } else {
|
| - UnimplementedInstruction(instr);
|
| + if (TargetCPUFeatures::arm_version() == ARMv5TE) {
|
| + UnimplementedInstruction(instr);
|
| + return;
|
| + }
|
| + // synchronization primitives
|
| + Register rd = instr->RdField();
|
| + Register rn = instr->RnField();
|
| + uword addr = get_register(rn);
|
| + switch (instr->Bits(20, 4)) {
|
| + case 8: {
|
| + // Format(instr, "strex'cond 'rd, 'rm, ['rn]");
|
| + if (IsIllegalAddress(addr)) {
|
| + HandleIllegalAccess(addr, instr);
|
| + } else {
|
| + Register rm = instr->RmField();
|
| + set_register(rd, WriteExclusiveW(addr, get_register(rm), instr));
|
| + }
|
| + break;
|
| + }
|
| + case 9: {
|
| + // Format(instr, "ldrex'cond 'rd, ['rn]");
|
| + if (IsIllegalAddress(addr)) {
|
| + HandleIllegalAccess(addr, instr);
|
| + } else {
|
| + set_register(rd, ReadExclusiveW(addr, instr));
|
| + }
|
| + break;
|
| + }
|
| + default: {
|
| + UnimplementedInstruction(instr);
|
| + break;
|
| + }
|
| + }
|
| }
|
| } else if (instr->Bit(25) == 1) {
|
| // 16-bit immediate loads, msr (immediate), and hints
|
| @@ -3451,7 +3582,7 @@
|
| if (instr->ConditionField() == kSpecialCondition) {
|
| if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
|
| // Format(instr, "clrex");
|
| - UnimplementedInstruction(instr);
|
| + ClearExclusive();
|
| } else {
|
| if (instr->IsSIMDDataProcessing()) {
|
| DecodeSIMDDataProcessing(instr);
|
|
|