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

Side by Side Diff: src/ppc/simulator-ppc.cc

Issue 2754263004: PPC: [Atomics] Make Atomics.exchange a builtin using TF (Closed)
Patch Set: rebased Created 3 years, 8 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
« no previous file with comments | « src/ppc/simulator-ppc.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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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_PPC 9 #if V8_TARGET_ARCH_PPC
10 10
11 #include "src/assembler.h" 11 #include "src/assembler.h"
12 #include "src/base/bits.h" 12 #include "src/base/bits.h"
13 #include "src/codegen.h" 13 #include "src/codegen.h"
14 #include "src/disasm.h" 14 #include "src/disasm.h"
15 #include "src/ppc/constants-ppc.h" 15 #include "src/ppc/constants-ppc.h"
16 #include "src/ppc/frames-ppc.h" 16 #include "src/ppc/frames-ppc.h"
17 #include "src/ppc/simulator-ppc.h" 17 #include "src/ppc/simulator-ppc.h"
18 #include "src/runtime/runtime-utils.h" 18 #include "src/runtime/runtime-utils.h"
19 19
20 #if defined(USE_SIMULATOR) 20 #if defined(USE_SIMULATOR)
21 21
22 // Only build the simulator if not compiling for real PPC hardware. 22 // Only build the simulator if not compiling for real PPC hardware.
23 namespace v8 { 23 namespace v8 {
24 namespace internal { 24 namespace internal {
25 25
26 const auto GetRegConfig = RegisterConfiguration::Crankshaft; 26 const auto GetRegConfig = RegisterConfiguration::Crankshaft;
27 27
28 // static
29 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
30 LAZY_INSTANCE_INITIALIZER;
31
28 // This macro provides a platform independent use of sscanf. The reason for 32 // This macro provides a platform independent use of sscanf. The reason for
29 // SScanF not being implemented in a platform independent way through 33 // SScanF not being implemented in a platform independent way through
30 // ::v8::internal::OS in the same way as SNPrintF is that the 34 // ::v8::internal::OS in the same way as SNPrintF is that the
31 // Windows C Run-Time Library does not provide vsscanf. 35 // Windows C Run-Time Library does not provide vsscanf.
32 #define SScanF sscanf // NOLINT 36 #define SScanF sscanf // NOLINT
33 37
34 // The PPCDebugger class is used by the simulator while debugging simulated 38 // The PPCDebugger class is used by the simulator while debugging simulated
35 // PowerPC code. 39 // PowerPC code.
36 class PPCDebugger { 40 class PPCDebugger {
37 public: 41 public:
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 778
775 // The sp is initialized to point to the bottom (high address) of the 779 // The sp is initialized to point to the bottom (high address) of the
776 // allocated stack area. To be safe in potential stack underflows we leave 780 // allocated stack area. To be safe in potential stack underflows we leave
777 // some buffer below. 781 // some buffer below.
778 registers_[sp] = 782 registers_[sp] =
779 reinterpret_cast<intptr_t>(stack_) + stack_size - stack_protection_size_; 783 reinterpret_cast<intptr_t>(stack_) + stack_size - stack_protection_size_;
780 784
781 last_debugger_input_ = NULL; 785 last_debugger_input_ = NULL;
782 } 786 }
783 787
784 788 Simulator::~Simulator() {
785 Simulator::~Simulator() { free(stack_); } 789 global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
786 790 free(stack_);
791 }
787 792
788 // When the generated code calls an external reference we need to catch that in 793 // When the generated code calls an external reference we need to catch that in
789 // the simulator. The external reference will be a function compiled for the 794 // the simulator. The external reference will be a function compiled for the
790 // host architecture. We need to call that function instead of trying to 795 // host architecture. We need to call that function instead of trying to
791 // execute it with the simulator. We do that by redirecting the external 796 // execute it with the simulator. We do that by redirecting the external
792 // reference to a svc (Supervisor Call) instruction that is handled by 797 // reference to a svc (Supervisor Call) instruction that is handled by
793 // the simulator. We write the original destination of the jump just at a known 798 // the simulator. We write the original destination of the jump just at a known
794 // offset from the svc instruction so the simulator knows what to call. 799 // offset from the svc instruction so the simulator knows what to call.
795 class Redirection { 800 class Redirection {
796 public: 801 public:
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 // We don't trash the registers with the return value. 985 // We don't trash the registers with the return value.
981 #if 0 // A good idea to trash volatile registers, needs to be done 986 #if 0 // A good idea to trash volatile registers, needs to be done
982 registers_[2] = 0x50Bad4U; 987 registers_[2] = 0x50Bad4U;
983 registers_[3] = 0x50Bad4U; 988 registers_[3] = 0x50Bad4U;
984 registers_[12] = 0x50Bad4U; 989 registers_[12] = 0x50Bad4U;
985 #endif 990 #endif
986 } 991 }
987 992
988 993
989 uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) { 994 uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) {
995 // All supported PPC targets allow unaligned accesses, so we don't need to
996 // check the alignment here.
997 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
998 local_monitor_.NotifyLoad(addr);
990 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 999 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
991 return *ptr; 1000 return *ptr;
992 } 1001 }
993 1002
1003 uint32_t Simulator::ReadExWU(intptr_t addr, Instruction* instr) {
1004 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1005 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word);
1006 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1007 &global_monitor_processor_);
1008 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1009 return *ptr;
1010 }
994 1011
995 int32_t Simulator::ReadW(intptr_t addr, Instruction* instr) { 1012 int32_t Simulator::ReadW(intptr_t addr, Instruction* instr) {
1013 // All supported PPC targets allow unaligned accesses, so we don't need to
1014 // check the alignment here.
1015 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1016 local_monitor_.NotifyLoad(addr);
996 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1017 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
997 return *ptr; 1018 return *ptr;
998 } 1019 }
999 1020
1000 1021
1001 void Simulator::WriteW(intptr_t addr, uint32_t value, Instruction* instr) { 1022 void Simulator::WriteW(intptr_t addr, uint32_t value, Instruction* instr) {
1023 // All supported PPC targets allow unaligned accesses, so we don't need to
1024 // check the alignment here.
1025 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1026 local_monitor_.NotifyStore(addr);
1027 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1028 &global_monitor_processor_);
1002 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); 1029 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1003 *ptr = value; 1030 *ptr = value;
1004 return; 1031 return;
1005 } 1032 }
1006 1033
1034 int Simulator::WriteExW(intptr_t addr, uint32_t value, Instruction* instr) {
1035 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1036 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) &&
1037 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1038 addr, &global_monitor_processor_)) {
1039 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
1040 *ptr = value;
1041 return 0;
1042 } else {
1043 return 1;
1044 }
1045 }
1007 1046
1008 void Simulator::WriteW(intptr_t addr, int32_t value, Instruction* instr) { 1047 void Simulator::WriteW(intptr_t addr, int32_t value, Instruction* instr) {
1048 // All supported PPC targets allow unaligned accesses, so we don't need to
1049 // check the alignment here.
1050 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1051 local_monitor_.NotifyStore(addr);
1052 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1053 &global_monitor_processor_);
1009 int32_t* ptr = reinterpret_cast<int32_t*>(addr); 1054 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1010 *ptr = value; 1055 *ptr = value;
1011 return; 1056 return;
1012 } 1057 }
1013 1058
1014
1015 uint16_t Simulator::ReadHU(intptr_t addr, Instruction* instr) { 1059 uint16_t Simulator::ReadHU(intptr_t addr, Instruction* instr) {
1060 // All supported PPC targets allow unaligned accesses, so we don't need to
1061 // check the alignment here.
1062 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1063 local_monitor_.NotifyLoad(addr);
1016 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1064 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1017 return *ptr; 1065 return *ptr;
1018 } 1066 }
1019 1067
1068 uint16_t Simulator::ReadExHU(intptr_t addr, Instruction* instr) {
1069 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1070 local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord);
1071 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1072 &global_monitor_processor_);
1073 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1074 return *ptr;
1075 }
1020 1076
1021 int16_t Simulator::ReadH(intptr_t addr, Instruction* instr) { 1077 int16_t Simulator::ReadH(intptr_t addr, Instruction* instr) {
1078 // All supported PPC targets allow unaligned accesses, so we don't need to
1079 // check the alignment here.
1080 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1081 local_monitor_.NotifyLoad(addr);
1022 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1082 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1023 return *ptr; 1083 return *ptr;
1024 } 1084 }
1025 1085
1026 1086
1027 void Simulator::WriteH(intptr_t addr, uint16_t value, Instruction* instr) { 1087 void Simulator::WriteH(intptr_t addr, uint16_t value, Instruction* instr) {
1088 // All supported PPC targets allow unaligned accesses, so we don't need to
1089 // check the alignment here.
1090 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1091 local_monitor_.NotifyStore(addr);
1092 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1093 &global_monitor_processor_);
1028 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1094 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1029 *ptr = value; 1095 *ptr = value;
1030 return; 1096 return;
1031 } 1097 }
1032 1098
1033 1099
1034 void Simulator::WriteH(intptr_t addr, int16_t value, Instruction* instr) { 1100 void Simulator::WriteH(intptr_t addr, int16_t value, Instruction* instr) {
1101 // All supported PPC targets allow unaligned accesses, so we don't need to
1102 // check the alignment here.
1103 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1104 local_monitor_.NotifyStore(addr);
1105 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1106 &global_monitor_processor_);
1035 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1107 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1036 *ptr = value; 1108 *ptr = value;
1037 return; 1109 return;
1038 } 1110 }
1039 1111
1112 int Simulator::WriteExH(intptr_t addr, uint16_t value, Instruction* instr) {
1113 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1114 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) &&
1115 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1116 addr, &global_monitor_processor_)) {
1117 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1118 *ptr = value;
1119 return 0;
1120 } else {
1121 return 1;
1122 }
1123 }
1040 1124
1041 uint8_t Simulator::ReadBU(intptr_t addr) { 1125 uint8_t Simulator::ReadBU(intptr_t addr) {
1126 // All supported PPC targets allow unaligned accesses, so we don't need to
1127 // check the alignment here.
1128 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1129 local_monitor_.NotifyLoad(addr);
1042 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1130 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1043 return *ptr; 1131 return *ptr;
1044 } 1132 }
1045 1133
1046 1134
1047 int8_t Simulator::ReadB(intptr_t addr) { 1135 int8_t Simulator::ReadB(intptr_t addr) {
1136 // All supported PPC targets allow unaligned accesses, so we don't need to
1137 // check the alignment here.
1138 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1139 local_monitor_.NotifyLoad(addr);
1048 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1140 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1049 return *ptr; 1141 return *ptr;
1050 } 1142 }
1051 1143
1144 uint8_t Simulator::ReadExBU(intptr_t addr) {
1145 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1146 local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte);
1147 global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1148 &global_monitor_processor_);
1149 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1150 return *ptr;
1151 }
1052 1152
1053 void Simulator::WriteB(intptr_t addr, uint8_t value) { 1153 void Simulator::WriteB(intptr_t addr, uint8_t value) {
1154 // All supported PPC targets allow unaligned accesses, so we don't need to
1155 // check the alignment here.
1156 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1157 local_monitor_.NotifyStore(addr);
1158 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1159 &global_monitor_processor_);
1054 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1160 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1055 *ptr = value; 1161 *ptr = value;
1056 } 1162 }
1057 1163
1058 1164
1059 void Simulator::WriteB(intptr_t addr, int8_t value) { 1165 void Simulator::WriteB(intptr_t addr, int8_t value) {
1166 // All supported PPC targets allow unaligned accesses, so we don't need to
1167 // check the alignment here.
1168 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1169 local_monitor_.NotifyStore(addr);
1170 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1171 &global_monitor_processor_);
1060 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1172 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1061 *ptr = value; 1173 *ptr = value;
1062 } 1174 }
1063 1175
1176 int Simulator::WriteExB(intptr_t addr, uint8_t value) {
1177 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1178 if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) &&
1179 global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1180 addr, &global_monitor_processor_)) {
1181 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1182 *ptr = value;
1183 return 0;
1184 } else {
1185 return 1;
1186 }
1187 }
1064 1188
1065 intptr_t* Simulator::ReadDW(intptr_t addr) { 1189 intptr_t* Simulator::ReadDW(intptr_t addr) {
1190 // All supported PPC targets allow unaligned accesses, so we don't need to
1191 // check the alignment here.
1192 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1193 local_monitor_.NotifyLoad(addr);
1066 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1194 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1067 return ptr; 1195 return ptr;
1068 } 1196 }
1069 1197
1070 1198
1071 void Simulator::WriteDW(intptr_t addr, int64_t value) { 1199 void Simulator::WriteDW(intptr_t addr, int64_t value) {
1200 // All supported PPC targets allow unaligned accesses, so we don't need to
1201 // check the alignment here.
1202 base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1203 local_monitor_.NotifyStore(addr);
1204 global_monitor_.Pointer()->NotifyStore_Locked(addr,
1205 &global_monitor_processor_);
1072 int64_t* ptr = reinterpret_cast<int64_t*>(addr); 1206 int64_t* ptr = reinterpret_cast<int64_t*>(addr);
1073 *ptr = value; 1207 *ptr = value;
1074 return; 1208 return;
1075 } 1209 }
1076 1210
1077 1211
1078 // Returns the limit of the stack area to enable checking for stack overflows. 1212 // Returns the limit of the stack area to enable checking for stack overflows.
1079 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const { 1213 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
1080 // The simulator uses a separate JS stack. If we have exhausted the C stack, 1214 // The simulator uses a separate JS stack. If we have exhausted the C stack,
1081 // we also drop down the JS limit to reflect the exhaustion on the JS stack. 1215 // we also drop down the JS limit to reflect the exhaustion on the JS stack.
(...skipping 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2255 int rs = instr->RSValue(); 2389 int rs = instr->RSValue();
2256 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5)); 2390 int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
2257 intptr_t rs_val = get_register(rs); 2391 intptr_t rs_val = get_register(rs);
2258 intptr_t result = rs_val >> sh; 2392 intptr_t result = rs_val >> sh;
2259 set_register(ra, result); 2393 set_register(ra, result);
2260 if (instr->Bit(0)) { // RC bit set 2394 if (instr->Bit(0)) { // RC bit set
2261 SetCR0(result); 2395 SetCR0(result);
2262 } 2396 }
2263 break; 2397 break;
2264 } 2398 }
2399 case STBCX: {
2400 int rs = instr->RSValue();
2401 int ra = instr->RAValue();
2402 int rb = instr->RBValue();
2403 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2404 int8_t rs_val = get_register(rs);
2405 intptr_t rb_val = get_register(rb);
2406 SetCR0(WriteExB(ra_val + rb_val, rs_val));
2407 break;
2408 }
2409 case STHCX: {
2410 int rs = instr->RSValue();
2411 int ra = instr->RAValue();
2412 int rb = instr->RBValue();
2413 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2414 int16_t rs_val = get_register(rs);
2415 intptr_t rb_val = get_register(rb);
2416 SetCR0(WriteExH(ra_val + rb_val, rs_val, instr));
2417 break;
2418 }
2419 case STWCX: {
2420 int rs = instr->RSValue();
2421 int ra = instr->RAValue();
2422 int rb = instr->RBValue();
2423 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2424 int32_t rs_val = get_register(rs);
2425 intptr_t rb_val = get_register(rb);
2426 SetCR0(WriteExW(ra_val + rb_val, rs_val, instr));
2427 break;
2428 }
2265 case TW: { 2429 case TW: {
2266 // used for call redirection in simulation mode 2430 // used for call redirection in simulation mode
2267 SoftwareInterrupt(instr); 2431 SoftwareInterrupt(instr);
2268 break; 2432 break;
2269 } 2433 }
2270 case CMP: { 2434 case CMP: {
2271 int ra = instr->RAValue(); 2435 int ra = instr->RAValue();
2272 int rb = instr->RBValue(); 2436 int rb = instr->RBValue();
2273 int cr = instr->Bits(25, 23); 2437 int cr = instr->Bits(25, 23);
2274 uint32_t bf = 0; 2438 uint32_t bf = 0;
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after
2986 int rb = instr->RBValue(); 3150 int rb = instr->RBValue();
2987 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3151 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
2988 intptr_t rb_val = get_register(rb); 3152 intptr_t rb_val = get_register(rb);
2989 set_register(rt, ReadHU(ra_val + rb_val, instr) & 0xFFFF); 3153 set_register(rt, ReadHU(ra_val + rb_val, instr) & 0xFFFF);
2990 if (opcode == LHZUX) { 3154 if (opcode == LHZUX) {
2991 DCHECK(ra != 0 && ra != rt); 3155 DCHECK(ra != 0 && ra != rt);
2992 set_register(ra, ra_val + rb_val); 3156 set_register(ra, ra_val + rb_val);
2993 } 3157 }
2994 break; 3158 break;
2995 } 3159 }
2996 case LHAX: 3160 case LHAX: {
2997 case LHAUX: {
2998 int rt = instr->RTValue(); 3161 int rt = instr->RTValue();
2999 int ra = instr->RAValue(); 3162 int ra = instr->RAValue();
3000 int rb = instr->RBValue(); 3163 int rb = instr->RBValue();
3001 intptr_t ra_val = ra == 0 ? 0 : get_register(ra); 3164 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3002 intptr_t rb_val = get_register(rb); 3165 intptr_t rb_val = get_register(rb);
3003 set_register(rt, ReadH(ra_val + rb_val, instr)); 3166 set_register(rt, ReadH(ra_val + rb_val, instr));
3004 if (opcode == LHAUX) { 3167 break;
3005 DCHECK(ra != 0 && ra != rt); 3168 }
3006 set_register(ra, ra_val + rb_val); 3169 case LBARX: {
3007 } 3170 int rt = instr->RTValue();
3171 int ra = instr->RAValue();
3172 int rb = instr->RBValue();
3173 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3174 intptr_t rb_val = get_register(rb);
3175 set_register(rt, ReadExBU(ra_val + rb_val) & 0xFF);
3176 break;
3177 }
3178 case LHARX: {
3179 int rt = instr->RTValue();
3180 int ra = instr->RAValue();
3181 int rb = instr->RBValue();
3182 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3183 intptr_t rb_val = get_register(rb);
3184 set_register(rt, ReadExHU(ra_val + rb_val, instr));
3185 break;
3186 }
3187 case LWARX: {
3188 int rt = instr->RTValue();
3189 int ra = instr->RAValue();
3190 int rb = instr->RBValue();
3191 intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
3192 intptr_t rb_val = get_register(rb);
3193 set_register(rt, ReadExWU(ra_val + rb_val, instr));
3008 break; 3194 break;
3009 } 3195 }
3010 case DCBF: { 3196 case DCBF: {
3011 // todo - simulate dcbf 3197 // todo - simulate dcbf
3012 break; 3198 break;
3013 } 3199 }
3014 case ISEL: { 3200 case ISEL: {
3015 int rt = instr->RTValue(); 3201 int rt = instr->RTValue();
3016 int ra = instr->RAValue(); 3202 int ra = instr->RAValue();
3017 int rb = instr->RBValue(); 3203 int rb = instr->RBValue();
(...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after
4066 } 4252 }
4067 4253
4068 4254
4069 uintptr_t Simulator::PopAddress() { 4255 uintptr_t Simulator::PopAddress() {
4070 uintptr_t current_sp = get_register(sp); 4256 uintptr_t current_sp = get_register(sp);
4071 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 4257 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
4072 uintptr_t address = *stack_slot; 4258 uintptr_t address = *stack_slot;
4073 set_register(sp, current_sp + sizeof(uintptr_t)); 4259 set_register(sp, current_sp + sizeof(uintptr_t));
4074 return address; 4260 return address;
4075 } 4261 }
4262
4263 Simulator::LocalMonitor::LocalMonitor()
4264 : access_state_(MonitorAccess::Open),
4265 tagged_addr_(0),
4266 size_(TransactionSize::None) {}
4267
4268 void Simulator::LocalMonitor::Clear() {
4269 access_state_ = MonitorAccess::Open;
4270 tagged_addr_ = 0;
4271 size_ = TransactionSize::None;
4272 }
4273
4274 void Simulator::LocalMonitor::NotifyLoad(int32_t addr) {
4275 if (access_state_ == MonitorAccess::Exclusive) {
4276 // A load could cause a cache eviction which will affect the monitor. As a
4277 // result, it's most strict to unconditionally clear the local monitor on
4278 // load.
4279 Clear();
4280 }
4281 }
4282
4283 void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr,
4284 TransactionSize size) {
4285 access_state_ = MonitorAccess::Exclusive;
4286 tagged_addr_ = addr;
4287 size_ = size;
4288 }
4289
4290 void Simulator::LocalMonitor::NotifyStore(int32_t addr) {
4291 if (access_state_ == MonitorAccess::Exclusive) {
4292 // A store could cause a cache eviction which will affect the
4293 // monitor. As a result, it's most strict to unconditionally clear the
4294 // local monitor on store.
4295 Clear();
4296 }
4297 }
4298
4299 bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr,
4300 TransactionSize size) {
4301 if (access_state_ == MonitorAccess::Exclusive) {
4302 if (addr == tagged_addr_ && size_ == size) {
4303 Clear();
4304 return true;
4305 } else {
4306 Clear();
4307 return false;
4308 }
4309 } else {
4310 DCHECK(access_state_ == MonitorAccess::Open);
4311 return false;
4312 }
4313 }
4314
4315 Simulator::GlobalMonitor::Processor::Processor()
4316 : access_state_(MonitorAccess::Open),
4317 tagged_addr_(0),
4318 next_(nullptr),
4319 prev_(nullptr) {}
4320
4321 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
4322 access_state_ = MonitorAccess::Open;
4323 tagged_addr_ = 0;
4324 }
4325 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) {
4326 access_state_ = MonitorAccess::Exclusive;
4327 tagged_addr_ = addr;
4328 }
4329
4330 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
4331 int32_t addr, bool is_requesting_processor) {
4332 if (access_state_ == MonitorAccess::Exclusive) {
4333 // It is possible that a store caused a cache eviction,
4334 // which can affect the montior, so conservatively,
4335 // we always clear the monitor.
4336 Clear_Locked();
4337 }
4338 }
4339
4340 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
4341 int32_t addr, bool is_requesting_processor) {
4342 if (access_state_ == MonitorAccess::Exclusive) {
4343 if (is_requesting_processor) {
4344 if (addr == tagged_addr_) {
4345 Clear_Locked();
4346 return true;
4347 }
4348 } else if (addr == tagged_addr_) {
4349 Clear_Locked();
4350 return false;
4351 }
4352 }
4353 return false;
4354 }
4355
4356 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
4357
4358 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr,
4359 Processor* processor) {
4360 processor->NotifyLoadExcl_Locked(addr);
4361 PrependProcessor_Locked(processor);
4362 }
4363
4364 void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr,
4365 Processor* processor) {
4366 // Notify each processor of the store operation.
4367 for (Processor* iter = head_; iter; iter = iter->next_) {
4368 bool is_requesting_processor = iter == processor;
4369 iter->NotifyStore_Locked(addr, is_requesting_processor);
4370 }
4371 }
4372
4373 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr,
4374 Processor* processor) {
4375 DCHECK(IsProcessorInLinkedList_Locked(processor));
4376 if (processor->NotifyStoreExcl_Locked(addr, true)) {
4377 // Notify the other processors that this StoreExcl succeeded.
4378 for (Processor* iter = head_; iter; iter = iter->next_) {
4379 if (iter != processor) {
4380 iter->NotifyStoreExcl_Locked(addr, false);
4381 }
4382 }
4383 return true;
4384 } else {
4385 return false;
4386 }
4387 }
4388
4389 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
4390 Processor* processor) const {
4391 return head_ == processor || processor->next_ || processor->prev_;
4392 }
4393
4394 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
4395 if (IsProcessorInLinkedList_Locked(processor)) {
4396 return;
4397 }
4398
4399 if (head_) {
4400 head_->prev_ = processor;
4401 }
4402 processor->prev_ = nullptr;
4403 processor->next_ = head_;
4404 head_ = processor;
4405 }
4406
4407 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
4408 base::LockGuard<base::Mutex> lock_guard(&mutex);
4409 if (!IsProcessorInLinkedList_Locked(processor)) {
4410 return;
4411 }
4412
4413 if (processor->prev_) {
4414 processor->prev_->next_ = processor->next_;
4415 } else {
4416 head_ = processor->next_;
4417 }
4418 if (processor->next_) {
4419 processor->next_->prev_ = processor->prev_;
4420 }
4421 processor->prev_ = nullptr;
4422 processor->next_ = nullptr;
4423 }
4424
4076 } // namespace internal 4425 } // namespace internal
4077 } // namespace v8 4426 } // namespace v8
4078 4427
4079 #endif // USE_SIMULATOR 4428 #endif // USE_SIMULATOR
4080 #endif // V8_TARGET_ARCH_PPC 4429 #endif // V8_TARGET_ARCH_PPC
OLDNEW
« no previous file with comments | « src/ppc/simulator-ppc.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698