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

Side by Side 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: merge master Created 4 years, 5 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 unified diff | Download patch
« src/arm/simulator-arm.h ('K') | « src/arm/simulator-arm.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdarg.h> 5 #include <stdarg.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <cmath> 7 #include <cmath>
8 8
9 #if V8_TARGET_ARCH_ARM 9 #if V8_TARGET_ARCH_ARM
10 10
11 #include "src/arm/constants-arm.h" 11 #include "src/arm/constants-arm.h"
12 #include "src/arm/simulator-arm.h" 12 #include "src/arm/simulator-arm.h"
13 #include "src/assembler.h" 13 #include "src/assembler.h"
14 #include "src/base/bits.h" 14 #include "src/base/bits.h"
15 #include "src/codegen.h" 15 #include "src/codegen.h"
16 #include "src/disasm.h" 16 #include "src/disasm.h"
17 #include "src/runtime/runtime-utils.h" 17 #include "src/runtime/runtime-utils.h"
18 18
19 #if defined(USE_SIMULATOR) 19 #if defined(USE_SIMULATOR)
20 20
21 // Only build the simulator if not compiling for real ARM hardware. 21 // Only build the simulator if not compiling for real ARM hardware.
22 namespace v8 { 22 namespace v8 {
23 namespace internal { 23 namespace internal {
24 24
25 // static
26 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
27 LAZY_INSTANCE_INITIALIZER;
28
25 // This macro provides a platform independent use of sscanf. The reason for 29 // This macro provides a platform independent use of sscanf. The reason for
26 // SScanF not being implemented in a platform independent way through 30 // SScanF not being implemented in a platform independent way through
27 // ::v8::internal::OS in the same way as SNPrintF is that the 31 // ::v8::internal::OS in the same way as SNPrintF is that the
28 // Windows C Run-Time Library does not provide vsscanf. 32 // Windows C Run-Time Library does not provide vsscanf.
29 #define SScanF sscanf // NOLINT 33 #define SScanF sscanf // NOLINT
30 34
31 // The ArmDebugger class is used by the simulator while debugging simulated ARM 35 // The ArmDebugger class is used by the simulator while debugging simulated ARM
32 // code. 36 // code.
33 class ArmDebugger { 37 class ArmDebugger {
34 public: 38 public:
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; 766 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
763 // The lr and pc are initialized to a known bad value that will cause an 767 // The lr and pc are initialized to a known bad value that will cause an
764 // access violation if the simulator ever tries to execute it. 768 // access violation if the simulator ever tries to execute it.
765 registers_[pc] = bad_lr; 769 registers_[pc] = bad_lr;
766 registers_[lr] = bad_lr; 770 registers_[lr] = bad_lr;
767 InitializeCoverage(); 771 InitializeCoverage();
768 772
769 last_debugger_input_ = NULL; 773 last_debugger_input_ = NULL;
770 } 774 }
771 775
772 776 Simulator::~Simulator() {
773 Simulator::~Simulator() { free(stack_); } 777 global_monitor_.Pointer()->RemoveNode(&global_monitor_node_);
774 778 free(stack_);
779 }
775 780
776 // When the generated code calls an external reference we need to catch that in 781 // When the generated code calls an external reference we need to catch that in
777 // the simulator. The external reference will be a function compiled for the 782 // the simulator. The external reference will be a function compiled for the
778 // host architecture. We need to call that function instead of trying to 783 // host architecture. We need to call that function instead of trying to
779 // execute it with the simulator. We do that by redirecting the external 784 // execute it with the simulator. We do that by redirecting the external
780 // reference to a svc (Supervisor Call) instruction that is handled by 785 // reference to a svc (Supervisor Call) instruction that is handled by
781 // the simulator. We write the original destination of the jump just at a known 786 // the simulator. We write the original destination of the jump just at a known
782 // offset from the svc instruction so the simulator knows what to call. 787 // offset from the svc instruction so the simulator knows what to call.
783 class Redirection { 788 class Redirection {
784 public: 789 public:
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 return *ptr; 1132 return *ptr;
1128 } else { 1133 } else {
1129 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1134 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1130 addr, 1135 addr,
1131 reinterpret_cast<intptr_t>(instr)); 1136 reinterpret_cast<intptr_t>(instr));
1132 UNIMPLEMENTED(); 1137 UNIMPLEMENTED();
1133 return 0; 1138 return 0;
1134 } 1139 }
1135 } 1140 }
1136 1141
1137 1142 void Simulator::WriteW_Internal(int32_t addr, int value, Instruction* instr) {
1138 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1139 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) { 1143 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1140 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1144 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1141 *ptr = value; 1145 *ptr = value;
1142 } else { 1146 } else {
1143 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1147 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1144 addr, 1148 addr,
1145 reinterpret_cast<intptr_t>(instr)); 1149 reinterpret_cast<intptr_t>(instr));
1146 UNIMPLEMENTED(); 1150 UNIMPLEMENTED();
1147 } 1151 }
1148 } 1152 }
(...skipping 18 matching lines...) Expand all
1167 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) { 1171 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1168 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1172 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1169 return *ptr; 1173 return *ptr;
1170 } else { 1174 } else {
1171 PrintF("Unaligned signed halfword read at 0x%08x\n", addr); 1175 PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
1172 UNIMPLEMENTED(); 1176 UNIMPLEMENTED();
1173 return 0; 1177 return 0;
1174 } 1178 }
1175 } 1179 }
1176 1180
1177 1181 void Simulator::WriteH_Internal(int32_t addr, uint16_t value,
1178 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { 1182 Instruction* instr) {
1179 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) { 1183 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1180 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1184 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1181 *ptr = value; 1185 *ptr = value;
1182 } else { 1186 } else {
1183 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" 1187 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1184 V8PRIxPTR "\n", 1188 V8PRIxPTR "\n",
1185 addr, 1189 addr,
1186 reinterpret_cast<intptr_t>(instr)); 1190 reinterpret_cast<intptr_t>(instr));
1187 UNIMPLEMENTED(); 1191 UNIMPLEMENTED();
1188 } 1192 }
1189 } 1193 }
1190 1194
1191 1195 void Simulator::WriteH_Internal(int32_t addr, int16_t value,
1192 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { 1196 Instruction* instr) {
1193 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) { 1197 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1194 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1198 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1195 *ptr = value; 1199 *ptr = value;
1196 } else { 1200 } else {
1197 PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", 1201 PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1198 addr, 1202 addr,
1199 reinterpret_cast<intptr_t>(instr)); 1203 reinterpret_cast<intptr_t>(instr));
1200 UNIMPLEMENTED(); 1204 UNIMPLEMENTED();
1201 } 1205 }
1202 } 1206 }
1203 1207
1204 1208
1205 uint8_t Simulator::ReadBU(int32_t addr) { 1209 uint8_t Simulator::ReadBU(int32_t addr) {
1206 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1210 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1207 return *ptr; 1211 return *ptr;
1208 } 1212 }
1209 1213
1210 1214
1211 int8_t Simulator::ReadB(int32_t addr) { 1215 int8_t Simulator::ReadB(int32_t addr) {
1212 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1216 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1213 return *ptr; 1217 return *ptr;
1214 } 1218 }
1215 1219
1216 1220 void Simulator::WriteB_Internal(int32_t addr, uint8_t value) {
1217 void Simulator::WriteB(int32_t addr, uint8_t value) {
1218 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1221 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1219 *ptr = value; 1222 *ptr = value;
1220 } 1223 }
1221 1224
1222 1225 void Simulator::WriteB_Internal(int32_t addr, int8_t value) {
1223 void Simulator::WriteB(int32_t addr, int8_t value) {
1224 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1226 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1225 *ptr = value; 1227 *ptr = value;
1226 } 1228 }
1227 1229
1228 1230
1229 int32_t* Simulator::ReadDW(int32_t addr) { 1231 int32_t* Simulator::ReadDW(int32_t addr) {
1230 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) { 1232 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1231 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1233 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1232 return ptr; 1234 return ptr;
1233 } else { 1235 } else {
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after
2190 hi_res = static_cast<int32_t>(result >> 32); 2192 hi_res = static_cast<int32_t>(result >> 32);
2191 lo_res = static_cast<int32_t>(result & 0xffffffff); 2193 lo_res = static_cast<int32_t>(result & 0xffffffff);
2192 } 2194 }
2193 set_register(rd_lo, lo_res); 2195 set_register(rd_lo, lo_res);
2194 set_register(rd_hi, hi_res); 2196 set_register(rd_hi, hi_res);
2195 if (instr->HasS()) { 2197 if (instr->HasS()) {
2196 UNIMPLEMENTED(); 2198 UNIMPLEMENTED();
2197 } 2199 }
2198 } 2200 }
2199 } else { 2201 } else {
2200 UNIMPLEMENTED(); // Not used by V8. 2202 if (instr->Bits(24, 23) == 3) {
2203 if (instr->Bit(20) == 1) {
2204 // ldrex
2205 int rt = instr->RtValue();
2206 int rn = instr->RnValue();
2207 int32_t addr = get_register(rn);
2208 switch (instr->Bits(22, 21)) {
2209 case 0: {
2210 // Format(instr, "ldrex'cond 'rt, ['rn]");
2211 int value = ReadExW(addr, instr);
2212 set_register(rt, value);
2213 break;
2214 }
2215 case 2: {
2216 // Format(instr, "ldrexb'cond 'rt, ['rn]");
2217 uint8_t value = ReadExBU(addr);
2218 set_register(rt, value);
2219 break;
2220 }
2221 case 3: {
2222 // Format(instr, "ldrexh'cond 'rt, ['rn]");
2223 uint16_t value = ReadExHU(addr, instr);
2224 set_register(rt, value);
2225 break;
2226 }
2227 default:
2228 UNREACHABLE();
2229 break;
2230 }
2231 } else {
2232 // The instruction is documented as strex rd, rt, [rn], but the
2233 // "rt" register is using the rm bits.
2234 int rd = instr->RdValue();
2235 int rt = instr->RmValue();
2236 int rn = instr->RnValue();
2237 int32_t addr = get_register(rn);
2238 switch (instr->Bits(22, 21)) {
2239 case 0: {
2240 // Format(instr, "strex'cond 'rd, 'rm, ['rn]");
2241 int value = get_register(rt);
2242 int status = WriteExW(addr, value, instr);
2243 set_register(rd, status);
2244 break;
2245 }
2246 case 2: {
2247 // Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
2248 uint8_t value = get_register(rt);
2249 int status = WriteExB(addr, value);
2250 set_register(rd, status);
2251 break;
2252 }
2253 case 3: {
2254 // Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
2255 uint16_t value = get_register(rt);
2256 int status = WriteExH(addr, value, instr);
2257 set_register(rd, status);
2258 break;
2259 }
2260 default:
2261 UNREACHABLE();
2262 break;
2263 }
2264 }
2265 } else {
2266 UNIMPLEMENTED(); // Not used by V8.
2267 }
2201 } 2268 }
2202 } else { 2269 } else {
2203 // extra load/store instructions 2270 // extra load/store instructions
2204 int rd = instr->RdValue(); 2271 int rd = instr->RdValue();
2205 int rn = instr->RnValue(); 2272 int rn = instr->RnValue();
2206 int32_t rn_val = get_register(rn); 2273 int32_t rn_val = get_register(rn);
2207 int32_t addr = 0; 2274 int32_t addr = 0;
2208 if (instr->Bit(22) == 0) { 2275 if (instr->Bit(22) == 0) {
2209 int rm = instr->RmValue(); 2276 int rm = instr->RmValue();
2210 int32_t rm_val = get_register(rm); 2277 int32_t rm_val = get_register(rm);
(...skipping 2092 matching lines...) Expand 10 before | Expand all | Expand 10 after
4303 4370
4304 4371
4305 uintptr_t Simulator::PopAddress() { 4372 uintptr_t Simulator::PopAddress() {
4306 int current_sp = get_register(sp); 4373 int current_sp = get_register(sp);
4307 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 4374 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
4308 uintptr_t address = *stack_slot; 4375 uintptr_t address = *stack_slot;
4309 set_register(sp, current_sp + sizeof(uintptr_t)); 4376 set_register(sp, current_sp + sizeof(uintptr_t));
4310 return address; 4377 return address;
4311 } 4378 }
4312 4379
4380 void Simulator::WriteB(int32_t addr, uint8_t value) {
4381 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4382 local_monitor_.Store(addr, TransactionSize::Byte);
4383 global_monitor_.Pointer()->Store_Locked(addr, &global_monitor_node_);
4384 WriteB_Internal(addr, value);
4385 }
4386
4387 void Simulator::WriteB(int32_t addr, int8_t value) {
4388 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4389 local_monitor_.Store(addr, TransactionSize::Byte);
4390 global_monitor_.Pointer()->Store_Locked(addr, &global_monitor_node_);
4391 WriteB_Internal(addr, value);
4392 }
4393
4394 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
4395 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4396 local_monitor_.Store(addr, TransactionSize::HalfWord);
4397 global_monitor_.Pointer()->Store_Locked(addr, &global_monitor_node_);
4398 WriteH_Internal(addr, value, instr);
4399 }
4400
4401 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
4402 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4403 local_monitor_.Store(addr, TransactionSize::HalfWord);
4404 global_monitor_.Pointer()->Store_Locked(addr, &global_monitor_node_);
4405 WriteH_Internal(addr, value, instr);
4406 }
4407
4408 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
4409 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4410 local_monitor_.Store(addr, TransactionSize::Word);
4411 global_monitor_.Pointer()->Store_Locked(addr, &global_monitor_node_);
4412 WriteW_Internal(addr, value, instr);
4413 }
4414
4415 uint8_t Simulator::ReadExBU(int32_t addr) {
4416 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4417 local_monitor_.LoadExcl(addr, TransactionSize::Byte);
4418 global_monitor_.Pointer()->LoadExcl_Locked(addr, &global_monitor_node_);
4419 return ReadBU(addr);
4420 }
4421
4422 int Simulator::WriteExB(int32_t addr, uint8_t value) {
4423 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4424 if (local_monitor_.CheckStoreExcl(addr, TransactionSize::Byte) &&
4425 global_monitor_.Pointer()->CheckStoreExcl_Locked(addr,
4426 &global_monitor_node_)) {
4427 WriteB_Internal(addr, value);
4428 return 0;
4429 } else {
4430 return 1;
4431 }
4432 }
4433
4434 uint16_t Simulator::ReadExHU(int32_t addr, Instruction* instr) {
4435 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4436 local_monitor_.LoadExcl(addr, TransactionSize::HalfWord);
4437 global_monitor_.Pointer()->LoadExcl_Locked(addr, &global_monitor_node_);
4438 return ReadHU(addr, instr);
4439 }
4440
4441 int Simulator::WriteExH(int32_t addr, uint16_t value, Instruction* instr) {
4442 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4443 if (local_monitor_.CheckStoreExcl(addr, TransactionSize::HalfWord) &&
4444 global_monitor_.Pointer()->CheckStoreExcl_Locked(addr,
4445 &global_monitor_node_)) {
4446 WriteH_Internal(addr, value, instr);
4447 return 0;
4448 } else {
4449 return 1;
4450 }
4451 }
4452
4453 int Simulator::ReadExW(int32_t addr, Instruction* instr) {
4454 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4455 local_monitor_.LoadExcl(addr, TransactionSize::Word);
4456 global_monitor_.Pointer()->LoadExcl_Locked(addr, &global_monitor_node_);
4457 return ReadW(addr, instr);
4458 }
4459
4460 int Simulator::WriteExW(int32_t addr, int value, Instruction* instr) {
4461 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
4462 if (local_monitor_.CheckStoreExcl(addr, TransactionSize::Word) &&
4463 global_monitor_.Pointer()->CheckStoreExcl_Locked(addr,
4464 &global_monitor_node_)) {
4465 WriteW_Internal(addr, value, instr);
4466 return 0;
4467 } else {
4468 return 1;
4469 }
4470 }
4471
4472 Simulator::LocalMonitor::LocalMonitor()
4473 : access_state_(MonitorAccess::Open),
4474 tagged_addr_(0),
4475 size_(TransactionSize::None) {}
4476
4477 void Simulator::LocalMonitor::LoadExcl(int32_t addr, TransactionSize size) {
4478 access_state_ = MonitorAccess::Exclusive;
4479 tagged_addr_ = addr & kTaggedAddrMask;
4480 size_ = size;
4481 }
4482
4483 void Simulator::LocalMonitor::Store(int32_t addr, TransactionSize size) {
4484 if (access_state_ == MonitorAccess::Exclusive) {
4485 // It is implementation-defined whether a non-exclusive store to an address
4486 // covered by the local monitor during exclusive access transitions to open
4487 // or exclusive access. See ARM DDI 0406C.b, A3.4.1.
jbramley 2016/07/20 16:09:24 That's true, but also note that software should av
binji 2016/07/29 21:46:29 Done.
4488 if ((addr & kTaggedAddrMask) == tagged_addr_) {
4489 access_state_ = MonitorAccess::Open;
4490 tagged_addr_ = 0;
4491 size_ = TransactionSize::None;
4492 }
4493 }
4494 }
4495
4496 bool Simulator::LocalMonitor::CheckStoreExcl(int32_t addr,
4497 TransactionSize size) {
4498 if (access_state_ == MonitorAccess::Exclusive) {
4499 if ((addr & kTaggedAddrMask) == tagged_addr_ && size_ == size) {
jbramley 2016/07/20 16:09:24 I'd drop the mask here. The ARM ARM allows a proce
binji 2016/07/29 21:46:29 Done.
4500 access_state_ = MonitorAccess::Open;
4501 tagged_addr_ = 0;
4502 size_ = TransactionSize::None;
4503 return true;
jbramley 2016/07/20 16:09:24 This should fail randomly from time to time. The A
binji 2016/07/29 21:46:29 Done, though I'm not sure this is the best way to
jbramley 2016/11/10 11:19:01 Some randomness would be useful but this is probab
4504 } else {
4505 // It is implementation-defined whether an exclusive store to a
4506 // non-tagged address will update memory. Behavior is unpredictable if
4507 // the transaction size of the exclusive store differs from that of the
4508 // exclusive load. See ARM DDI 0406C.b, A3.4.5.
4509 access_state_ = MonitorAccess::Open;
4510 tagged_addr_ = 0;
4511 size_ = TransactionSize::None;
4512 return false;
4513 }
4514 } else {
4515 DCHECK(access_state_ == MonitorAccess::Open);
4516 return false;
4517 }
4518 }
4519
4520 Simulator::GlobalMonitor::Node::Node()
4521 : access_state_(MonitorAccess::Open),
4522 tagged_addr_(0),
4523 next_(nullptr),
4524 prev_(nullptr) {}
4525
4526 void Simulator::GlobalMonitor::Node::LoadExcl_Locked(int32_t addr) {
4527 access_state_ = MonitorAccess::Exclusive;
4528 tagged_addr_ = addr & kTaggedAddrMask;
4529 }
4530
4531 void Simulator::GlobalMonitor::Node::Store_Locked(
4532 int32_t addr, bool is_requesting_processor) {
4533 if (access_state_ == MonitorAccess::Exclusive) {
4534 if ((addr & kTaggedAddrMask) == tagged_addr_) {
4535 // It is implementation-defined whether a non-exclusive store by the
4536 // requesting processor to an address covered by the global monitor
4537 // during exclusive access transitions to open or exclusive access.
4538 //
4539 // For any other processor, the access state always transitions to open
4540 // access.
4541 //
4542 // See ARM DDI 0406C.b, A3.4.2.
4543 access_state_ = MonitorAccess::Open;
4544 tagged_addr_ = 0;
4545 }
4546 }
4547 }
4548
4549 bool Simulator::GlobalMonitor::Node::CheckStoreExcl_Locked(
4550 int32_t addr, bool is_requesting_processor) {
4551 if (access_state_ == MonitorAccess::Exclusive) {
4552 if ((addr & kTaggedAddrMask) == tagged_addr_) {
4553 if (is_requesting_processor) {
4554 // The access state for the requesting processor after a successful
4555 // exclusive store is implementation-defined, but according to the ARM
4556 // DDI, this has no effect on the subsequent operation of the global
4557 // monitor.
4558 access_state_ = MonitorAccess::Open;
4559 tagged_addr_ = 0;
4560 return true;
4561 } else {
4562 access_state_ = MonitorAccess::Open;
4563 tagged_addr_ = 0;
4564 return false;
4565 }
4566 }
4567 }
4568 return false;
4569 }
4570
4571 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
4572
4573 void Simulator::GlobalMonitor::LoadExcl_Locked(int32_t addr, Node* node) {
4574 node->LoadExcl_Locked(addr);
4575 PrependNode_Locked(node);
4576 }
4577
4578 void Simulator::GlobalMonitor::Store_Locked(int32_t addr, Node* node) {
4579 // Notify each processor of the store operation.
4580 for (Node* iter = head_; iter; iter = iter->next_) {
4581 bool is_requesting_processor = iter == node;
4582 iter->Store_Locked(addr, is_requesting_processor);
4583 }
4584 }
4585
4586 bool Simulator::GlobalMonitor::CheckStoreExcl_Locked(int32_t addr, Node* node) {
4587 DCHECK(IsNodeInLinkedList_Locked(node));
4588 if (node->CheckStoreExcl_Locked(addr, true)) {
4589 // Notify the other processors that this StoreExcl succeeded.
4590 for (Node* iter = head_; iter; iter = iter->next_) {
4591 if (iter != node) {
4592 iter->CheckStoreExcl_Locked(addr, false);
4593 }
4594 }
4595 return true;
4596 } else {
4597 return false;
4598 }
4599 }
4600
4601 bool Simulator::GlobalMonitor::IsNodeInLinkedList_Locked(Node* node) const {
4602 return head_ == node || node->next_ || node->prev_;
4603 }
4604
4605 void Simulator::GlobalMonitor::PrependNode_Locked(Node* node) {
4606 if (IsNodeInLinkedList_Locked(node)) {
4607 return;
4608 }
4609
4610 if (head_) {
4611 head_->prev_ = node;
4612 }
4613 node->prev_ = nullptr;
4614 node->next_ = head_;
4615 head_ = node;
4616 }
4617
4618 void Simulator::GlobalMonitor::RemoveNode(Node* node) {
4619 base::LockGuard<base::Mutex> lock_guard(&mutex);
4620 if (!IsNodeInLinkedList_Locked(node)) {
4621 return;
4622 }
4623
4624 if (node->prev_) {
4625 node->prev_->next_ = node->next_;
4626 } else {
4627 head_ = node->next_;
4628 }
4629 if (node->next_) {
4630 node->next_->prev_ = node->prev_;
4631 }
4632 node->prev_ = nullptr;
4633 node->next_ = nullptr;
4634 }
4635
4313 } // namespace internal 4636 } // namespace internal
4314 } // namespace v8 4637 } // namespace v8
4315 4638
4316 #endif // USE_SIMULATOR 4639 #endif // USE_SIMULATOR
4317 4640
4318 #endif // V8_TARGET_ARCH_ARM 4641 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« 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