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 3 // found in the LICENSE file. 4 5 // Declares a Simulator for PPC instructions if we are not generating a native 6 // PPC binary. This Simulator allows us to run and debug PPC code generation on 7 // regular desktop machines. 8 // V8 calls into generated code via the GeneratedCode wrapper, 9 // which will start execution in the Simulator or forwards to the real entry 10 // on a PPC HW platform. 11 12 #ifndef V8_PPC_SIMULATOR_PPC_H_ 13 #define V8_PPC_SIMULATOR_PPC_H_ 14 15 #include "src/allocation.h" 16 17 #if defined(USE_SIMULATOR) 18 // Running with a simulator. 19 20 #include "src/assembler.h" 21 #include "src/base/hashmap.h" 22 #include "src/ppc/constants-ppc.h" 23 #include "src/simulator-base.h" 24 25 namespace v8 { 26 namespace internal { 27 28 class CachePage { 29 public: 30 static const int LINE_VALID = 0; 31 static const int LINE_INVALID = 1; 32 33 static const int kPageShift = 12; 34 static const int kPageSize = 1 << kPageShift; 35 static const int kPageMask = kPageSize - 1; 36 static const int kLineShift = 2; // The cache line is only 4 bytes right now. 37 static const int kLineLength = 1 << kLineShift; 38 static const int kLineMask = kLineLength - 1; 39 40 CachePage() { memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); } 41 42 char* ValidityByte(int offset) { 43 return &validity_map_[offset >> kLineShift]; 44 } 45 46 char* CachedData(int offset) { return &data_[offset]; } 47 48 private: 49 char data_[kPageSize]; // The cached data. 50 static const int kValidityMapSize = kPageSize >> kLineShift; 51 char validity_map_[kValidityMapSize]; // One byte per line. 52 }; 53 54 class Simulator : public SimulatorBase { 55 public: 56 friend class PPCDebugger; 57 enum Register { 58 no_reg = -1, 59 r0 = 0, 60 sp, 61 r2, 62 r3, 63 r4, 64 r5, 65 r6, 66 r7, 67 r8, 68 r9, 69 r10, 70 r11, 71 r12, 72 r13, 73 r14, 74 r15, 75 r16, 76 r17, 77 r18, 78 r19, 79 r20, 80 r21, 81 r22, 82 r23, 83 r24, 84 r25, 85 r26, 86 r27, 87 r28, 88 r29, 89 r30, 90 fp, 91 kNumGPRs = 32, 92 d0 = 0, 93 d1, 94 d2, 95 d3, 96 d4, 97 d5, 98 d6, 99 d7, 100 d8, 101 d9, 102 d10, 103 d11, 104 d12, 105 d13, 106 d14, 107 d15, 108 d16, 109 d17, 110 d18, 111 d19, 112 d20, 113 d21, 114 d22, 115 d23, 116 d24, 117 d25, 118 d26, 119 d27, 120 d28, 121 d29, 122 d30, 123 d31, 124 kNumFPRs = 32 125 }; 126 127 explicit Simulator(Isolate* isolate); 128 ~Simulator(); 129 130 // The currently executing Simulator instance. Potentially there can be one 131 // for each native thread. 132 static Simulator* current(v8::internal::Isolate* isolate); 133 134 // Accessors for register state. 135 void set_register(int reg, intptr_t value); 136 intptr_t get_register(int reg) const; 137 double get_double_from_register_pair(int reg); 138 void set_d_register_from_double(int dreg, const double dbl) { 139 DCHECK(dreg >= 0 && dreg < kNumFPRs); 140 *bit_cast<double*>(&fp_registers_[dreg]) = dbl; 141 } 142 double get_double_from_d_register(int dreg) { 143 DCHECK(dreg >= 0 && dreg < kNumFPRs); 144 return *bit_cast<double*>(&fp_registers_[dreg]); 145 } 146 void set_d_register(int dreg, int64_t value) { 147 DCHECK(dreg >= 0 && dreg < kNumFPRs); 148 fp_registers_[dreg] = value; 149 } 150 int64_t get_d_register(int dreg) { 151 DCHECK(dreg >= 0 && dreg < kNumFPRs); 152 return fp_registers_[dreg]; 153 } 154 155 // Special case of set_register and get_register to access the raw PC value. 156 void set_pc(intptr_t value); 157 intptr_t get_pc() const; 158 159 Address get_sp() const { return static_cast<Address>(get_register(sp)); } 160 161 // Accessor to the internal simulator stack area. 162 uintptr_t StackLimit(uintptr_t c_limit) const; 163 164 // Executes PPC instructions until the PC reaches end_sim_pc. 165 void Execute(); 166 167 template <typename Return, typename... Args> 168 Return Call(Address entry, Args... args) { 169 return VariadicCall<Return>(this, &Simulator::CallImpl, entry, args...); 170 } 171 172 // Alternative: call a 2-argument double function. 173 void CallFP(Address entry, double d0, double d1); 174 int32_t CallFPReturnsInt(Address entry, double d0, double d1); 175 double CallFPReturnsDouble(Address entry, double d0, double d1); 176 177 // Push an address onto the JS stack. 178 uintptr_t PushAddress(uintptr_t address); 179 180 // Pop an address from the JS stack. 181 uintptr_t PopAddress(); 182 183 // Debugger input. 184 void set_last_debugger_input(char* input); 185 char* last_debugger_input() { return last_debugger_input_; } 186 187 // Redirection support. 188 static void SetRedirectInstruction(Instruction* instruction); 189 190 // ICache checking. 191 static bool ICacheMatch(void* one, void* two); 192 static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start, 193 size_t size); 194 195 // Returns true if pc register contains one of the 'special_values' defined 196 // below (bad_lr, end_sim_pc). 197 bool has_bad_pc() const; 198 199 private: 200 enum special_values { 201 // Known bad pc value to ensure that the simulator does not execute 202 // without being properly setup. 203 bad_lr = -1, 204 // A pc value used to signal the simulator to stop execution. Generally 205 // the lr is set to this value on transition from native C code to 206 // simulated execution, so that the simulator can "return" to the native 207 // C code. 208 end_sim_pc = -2 209 }; 210 211 intptr_t CallImpl(Address entry, int argument_count, 212 const intptr_t* arguments); 213 214 enum BCType { BC_OFFSET, BC_LINK_REG, BC_CTR_REG }; 215 216 // Unsupported instructions use Format to print an error and stop execution. 217 void Format(Instruction* instr, const char* format); 218 219 // Helper functions to set the conditional flags in the architecture state. 220 bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0); 221 bool BorrowFrom(int32_t left, int32_t right); 222 bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right, 223 bool addition); 224 225 // Helper functions to decode common "addressing" modes 226 int32_t GetShiftRm(Instruction* instr, bool* carry_out); 227 int32_t GetImm(Instruction* instr, bool* carry_out); 228 void ProcessPUW(Instruction* instr, int num_regs, int operand_size, 229 intptr_t* start_address, intptr_t* end_address); 230 void HandleRList(Instruction* instr, bool load); 231 void HandleVList(Instruction* inst); 232 void SoftwareInterrupt(Instruction* instr); 233 234 // Stop helper functions. 235 inline bool isStopInstruction(Instruction* instr); 236 inline bool isWatchedStop(uint32_t bkpt_code); 237 inline bool isEnabledStop(uint32_t bkpt_code); 238 inline void EnableStop(uint32_t bkpt_code); 239 inline void DisableStop(uint32_t bkpt_code); 240 inline void IncreaseStopCounter(uint32_t bkpt_code); 241 void PrintStopInfo(uint32_t code); 242 243 // Read and write memory. 244 inline uint8_t ReadBU(intptr_t addr); 245 inline uint8_t ReadExBU(intptr_t addr); 246 inline int8_t ReadB(intptr_t addr); 247 inline void WriteB(intptr_t addr, uint8_t value); 248 inline int WriteExB(intptr_t addr, uint8_t value); 249 inline void WriteB(intptr_t addr, int8_t value); 250 251 inline uint16_t ReadHU(intptr_t addr, Instruction* instr); 252 inline uint16_t ReadExHU(intptr_t addr, Instruction* instr); 253 inline int16_t ReadH(intptr_t addr, Instruction* instr); 254 // Note: Overloaded on the sign of the value. 255 inline void WriteH(intptr_t addr, uint16_t value, Instruction* instr); 256 inline int WriteExH(intptr_t addr, uint16_t value, Instruction* instr); 257 inline void WriteH(intptr_t addr, int16_t value, Instruction* instr); 258 259 inline uint32_t ReadWU(intptr_t addr, Instruction* instr); 260 inline uint32_t ReadExWU(intptr_t addr, Instruction* instr); 261 inline int32_t ReadW(intptr_t addr, Instruction* instr); 262 inline void WriteW(intptr_t addr, uint32_t value, Instruction* instr); 263 inline int WriteExW(intptr_t addr, uint32_t value, Instruction* instr); 264 inline void WriteW(intptr_t addr, int32_t value, Instruction* instr); 265 266 intptr_t* ReadDW(intptr_t addr); 267 void WriteDW(intptr_t addr, int64_t value); 268 269 void Trace(Instruction* instr); 270 void SetCR0(intptr_t result, bool setSO = false); 271 void ExecuteBranchConditional(Instruction* instr, BCType type); 272 void ExecuteExt1(Instruction* instr); 273 bool ExecuteExt2_10bit_part1(Instruction* instr); 274 bool ExecuteExt2_10bit_part2(Instruction* instr); 275 bool ExecuteExt2_9bit_part1(Instruction* instr); 276 bool ExecuteExt2_9bit_part2(Instruction* instr); 277 void ExecuteExt2_5bit(Instruction* instr); 278 void ExecuteExt2(Instruction* instr); 279 void ExecuteExt3(Instruction* instr); 280 void ExecuteExt4(Instruction* instr); 281 #if V8_TARGET_ARCH_PPC64 282 void ExecuteExt5(Instruction* instr); 283 #endif 284 void ExecuteExt6(Instruction* instr); 285 void ExecuteGeneric(Instruction* instr); 286 287 void SetFPSCR(int bit) { fp_condition_reg_ |= (1 << (31 - bit)); } 288 void ClearFPSCR(int bit) { fp_condition_reg_ &= ~(1 << (31 - bit)); } 289 290 // Executes one instruction. 291 void ExecuteInstruction(Instruction* instr); 292 293 // ICache. 294 static void CheckICache(base::CustomMatcherHashMap* i_cache, 295 Instruction* instr); 296 static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start, 297 int size); 298 static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache, 299 void* page); 300 301 // Handle arguments and return value for runtime FP functions. 302 void GetFpArgs(double* x, double* y, intptr_t* z); 303 void SetFpResult(const double& result); 304 void TrashCallerSaveRegisters(); 305 306 void CallInternal(Address entry); 307 308 // Architecture state. 309 // Saturating instructions require a Q flag to indicate saturation. 310 // There is currently no way to read the CPSR directly, and thus read the Q 311 // flag, so this is left unimplemented. 312 intptr_t registers_[kNumGPRs]; 313 int32_t condition_reg_; 314 int32_t fp_condition_reg_; 315 intptr_t special_reg_lr_; 316 intptr_t special_reg_pc_; 317 intptr_t special_reg_ctr_; 318 int32_t special_reg_xer_; 319 320 int64_t fp_registers_[kNumFPRs]; 321 322 // Simulator support. 323 char* stack_; 324 static const size_t stack_protection_size_ = 256 * kPointerSize; 325 bool pc_modified_; 326 int icount_; 327 328 // Debugger input. 329 char* last_debugger_input_; 330 331 // Registered breakpoints. 332 Instruction* break_pc_; 333 Instr break_instr_; 334 335 v8::internal::Isolate* isolate_; 336 337 // A stop is watched if its code is less than kNumOfWatchedStops. 338 // Only watched stops support enabling/disabling and the counter feature. 339 static const uint32_t kNumOfWatchedStops = 256; 340 341 // Breakpoint is disabled if bit 31 is set. 342 static const uint32_t kStopDisabledBit = 1 << 31; 343 344 // A stop is enabled, meaning the simulator will stop when meeting the 345 // instruction, if bit 31 of watched_stops_[code].count is unset. 346 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 347 // the breakpoint was hit or gone through. 348 struct StopCountAndDesc { 349 uint32_t count; 350 char* desc; 351 }; 352 StopCountAndDesc watched_stops_[kNumOfWatchedStops]; 353 354 // Synchronization primitives. See ARM DDI 0406C.b, A2.9. 355 enum class MonitorAccess { 356 Open, 357 Exclusive, 358 }; 359 360 enum class TransactionSize { 361 None = 0, 362 Byte = 1, 363 HalfWord = 2, 364 Word = 4, 365 }; 366 367 class LocalMonitor { 368 public: 369 LocalMonitor(); 370 371 // These functions manage the state machine for the local monitor, but do 372 // not actually perform loads and stores. NotifyStoreExcl only returns 373 // true if the exclusive store is allowed; the global monitor will still 374 // have to be checked to see whether the memory should be updated. 375 void NotifyLoad(int32_t addr); 376 void NotifyLoadExcl(int32_t addr, TransactionSize size); 377 void NotifyStore(int32_t addr); 378 bool NotifyStoreExcl(int32_t addr, TransactionSize size); 379 380 private: 381 void Clear(); 382 383 MonitorAccess access_state_; 384 int32_t tagged_addr_; 385 TransactionSize size_; 386 }; 387 388 class GlobalMonitor { 389 public: 390 GlobalMonitor(); 391 392 class Processor { 393 public: 394 Processor(); 395 396 private: 397 friend class GlobalMonitor; 398 // These functions manage the state machine for the global monitor, but do 399 // not actually perform loads and stores. 400 void Clear_Locked(); 401 void NotifyLoadExcl_Locked(int32_t addr); 402 void NotifyStore_Locked(int32_t addr, bool is_requesting_processor); 403 bool NotifyStoreExcl_Locked(int32_t addr, bool is_requesting_processor); 404 405 MonitorAccess access_state_; 406 int32_t tagged_addr_; 407 Processor* next_; 408 Processor* prev_; 409 }; 410 411 // Exposed so it can be accessed by Simulator::{Read,Write}Ex*. 412 base::Mutex mutex; 413 414 void NotifyLoadExcl_Locked(int32_t addr, Processor* processor); 415 void NotifyStore_Locked(int32_t addr, Processor* processor); 416 bool NotifyStoreExcl_Locked(int32_t addr, Processor* processor); 417 418 // Called when the simulator is destroyed. 419 void RemoveProcessor(Processor* processor); 420 421 private: 422 bool IsProcessorInLinkedList_Locked(Processor* processor) const; 423 void PrependProcessor_Locked(Processor* processor); 424 425 Processor* head_; 426 }; 427 428 LocalMonitor local_monitor_; 429 GlobalMonitor::Processor global_monitor_processor_; 430 static base::LazyInstance<GlobalMonitor>::type global_monitor_; 431 }; 432 433 } // namespace internal 434 } // namespace v8 435 436 #endif // defined(USE_SIMULATOR) 437 #endif // V8_PPC_SIMULATOR_PPC_H_ 438