Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Unified Diff: src/arm/simulator-arm.cc

Issue 2006183004: Implement ldrex and strex in ARM simulator (Closed) Base URL: http://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/arm/simulator-arm.h ('K') | « src/arm/simulator-arm.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/simulator-arm.cc
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 1a870c5c05ae56fc2524022a52713b15523a39c9..d7c028ffa2caf742fc9c38bdb922fbd2a1f55b5e 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -22,6 +22,12 @@
namespace v8 {
namespace internal {
+// static
+base::LazyMutex Simulator::DataMonitor::mutex_ =
+ LAZY_STATIC_INSTANCE_INITIALIZER;
+// static
+Simulator::DataMonitor* Simulator::DataMonitor::head_;
+
// This macro provides a platform independent use of sscanf. The reason for
// SScanF not being implemented in a platform independent way through
// ::v8::internal::OS in the same way as SNPrintF is that the
@@ -2203,7 +2209,72 @@ void Simulator::DecodeType01(Instruction* instr) {
}
}
} else {
- UNIMPLEMENTED(); // Not used by V8.
+ if (instr->Bits(24, 23) == 3) {
+ if (instr->Bit(20) == 1) {
+ // ldrex
+ int rt = instr->RtValue();
+ int rn = instr->RnValue();
+ int32_t addr = get_register(rn);
+ switch (instr->Bits(22, 21)) {
+ case 0: {
+ // Format(instr, "ldrex'cond 'rt, ['rn]");
+ int value = data_monitor_.ReadExW(this, addr, instr);
+ set_register(rt, value);
+ break;
+ }
+ case 2: {
+ // Format(instr, "ldrexb'cond 'rt, ['rn]");
+ uint8_t value = data_monitor_.ReadExBU(this, addr);
+ set_register(rt, value);
+ break;
+ }
+ case 3: {
+ // Format(instr, "ldrexh'cond 'rt, ['rn]");
+ uint16_t value = data_monitor_.ReadExHU(this, addr, instr);
+ set_register(rt, value);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ } else {
+ // The instruction is documented as strex rd, rt, [rn], but the
+ // "rt" register is using the rm bits.
+ int rd = instr->RdValue();
+ int rt = instr->RmValue();
+ int rn = instr->RnValue();
+ int32_t addr = get_register(rn);
+ switch (instr->Bits(22, 21)) {
+ case 0: {
+ // Format(instr, "strex'cond 'rd, 'rm, ['rn]");
+ int value = get_register(rt);
+ int status = data_monitor_.WriteExW(this, addr, value, instr);
+ set_register(rd, status);
+ break;
+ }
+ case 2: {
+ // Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
+ uint8_t value = get_register(rt);
+ int status = data_monitor_.WriteExB(this, addr, value);
+ set_register(rd, status);
+ break;
+ }
+ case 3: {
+ // Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
+ uint16_t value = get_register(rt);
+ int status = data_monitor_.WriteExH(this, addr, value, instr);
+ set_register(rd, status);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ } else {
+ UNIMPLEMENTED(); // Not used by V8.
+ }
}
} else {
// extra load/store instructions
@@ -4316,6 +4387,146 @@ uintptr_t Simulator::PopAddress() {
return address;
}
+
+// Syncronization primitives. See ARM DDI 0406C.b, A2.9.
+uint8_t Simulator::DataMonitor::ReadExBU(Simulator* simulator, int32_t addr) {
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ ReadExInternal_Locked(addr);
+ return simulator->ReadBU(addr);
+}
+
+
+int Simulator::DataMonitor::WriteExB(Simulator* simulator,
+ int32_t addr,
+ uint8_t value) {
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ if (WriteExInternal_Locked(addr)) {
+ simulator->WriteB(addr, value);
jbramley 2016/05/31 16:58:47 Also, _any_ unrelated memory operation should _som
binji 2016/06/01 21:06:40 OK, makes sense.
+ return 1;
Rodolph Perfetta (ARM) 2016/05/25 17:38:29 it is 0 on success and 1 for failure.
binji 2016/06/01 21:06:40 Oops! done.
+ }
+ return 0;
+}
+
+
+uint16_t Simulator::DataMonitor::ReadExHU(Simulator* simulator,
+ int32_t addr,
+ Instruction* instr) {
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ ReadExInternal_Locked(addr);
+ return simulator->ReadHU(addr, instr);
+}
+
+
+int Simulator::DataMonitor::WriteExH(Simulator* simulator,
+ int32_t addr,
+ uint16_t value,
+ Instruction* instr) {
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ if (WriteExInternal_Locked(addr)) {
+ simulator->WriteH(addr, value, instr);
+ return 1;
Rodolph Perfetta (ARM) 2016/05/25 17:38:29 0
binji 2016/06/01 21:06:40 Done.
+ }
+ return 0;
+}
+
+
+int Simulator::DataMonitor::ReadExW(Simulator* simulator,
+ int32_t addr,
+ Instruction* instr) {
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ ReadExInternal_Locked(addr);
+ return simulator->ReadW(addr, instr);
+}
+
+
+int Simulator::DataMonitor::WriteExW(Simulator* simulator,
+ int32_t addr,
+ int value,
+ Instruction* instr) {
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ if (WriteExInternal_Locked(addr)) {
+ simulator->WriteW(addr, value, instr);
+ return 1;
Rodolph Perfetta (ARM) 2016/05/25 17:38:29 0
binji 2016/06/01 21:06:40 Done.
+ }
+ return 0;
+}
+
+
+Simulator::DataMonitor::DataMonitor()
+ : access_state_(Access::Open),
+ tagged_addr_(0),
+ next_(nullptr),
+ prev_(nullptr) {}
+
+
+void Simulator::DataMonitor::ReadExInternal_Locked(int32_t addr) {
+ if (access_state_ == Access::Exclusive) {
+ // This DataMonitor is already in the linked list; remove it so can be
+ // added below.
+ RemoveNode_Locked();
+ }
+
+ PrependNode_Locked();
+ access_state_ = Access::Exclusive;
+ tagged_addr_ = addr & kAddrMask;
+}
+
+
+bool Simulator::DataMonitor::WriteExInternal_Locked(int32_t addr) {
+ if (access_state_ == Access::Exclusive) {
jbramley 2016/05/31 16:58:47 This should be more strict, and check that the add
binji 2016/06/01 21:06:40 OK, I'll work on this after these simple fixes.
+ // This DataMonitor is in the linked list, check if there is another
+ // thread that has more recent exclusive access to this address.
+ DataMonitor* node = FirstNodeWithTaggedAddr_Locked(addr);
+ if (node != this) {
+ // This thread does not have exclusive access (either it never called
+ // ldrex or another thread took it away. Either way, this write will
+ // fail.
+ return false;
+ }
+
+ RemoveNode_Locked();
+ access_state_ = Access::Open;
Rodolph Perfetta (ARM) 2016/05/25 17:38:29 You should make sure any other nodes with the same
binji 2016/06/01 21:06:40 OK, I'll work on this after these simple fixes.
+ return true;
+ } else {
+ // Not marked for exclusive access.
+ return false;
+ }
+}
+
+
+void Simulator::DataMonitor::RemoveNode_Locked() {
+ if (prev_) {
+ prev_->next_ = next_;
+ } else {
+ head_ = next_;
+ }
+ if (next_) {
+ next_->prev_ = prev_;
+ }
+ prev_ = nullptr;
+ next_ = nullptr;
+}
+
+
+void Simulator::DataMonitor::PrependNode_Locked() {
+ if (head_) {
+ head_->prev_ = this;
+ }
Rodolph Perfetta (ARM) 2016/05/25 17:38:29 shouldn't next_ point to head_?
binji 2016/06/01 21:06:40 Done.
+ head_ = this;
+}
+
+
+Simulator::DataMonitor* Simulator::DataMonitor::FirstNodeWithTaggedAddr_Locked(
+ int32_t addr) {
+ for (DataMonitor* node = head_; node; node = node->next_) {
+ if ((addr & kAddrMask) == node->tagged_addr_) {
+ return node;
+ }
+ }
+ return nullptr;
+}
+
+
} // namespace internal
} // namespace v8
« src/arm/simulator-arm.h ('K') | « src/arm/simulator-arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698