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 3 // found in the LICENSE file. 4 5 // Declares a Simulator for ARM instructions if we are not generating a native 6 // ARM binary. This Simulator allows us to run and debug ARM code generation on 7 // regular desktop machines. 8 // V8 calls into generated code by using the GeneratedCode class, 9 // which will start execution in the Simulator or forwards to the real entry 10 // on a ARM HW platform. 11 12 #ifndef V8_ARM_SIMULATOR_ARM_H_ 13 #define V8_ARM_SIMULATOR_ARM_H_ 14 15 #include "src/allocation.h" 16 #include "src/base/lazy-instance.h" 17 #include "src/base/platform/mutex.h" 18 #include "src/boxed-float.h" 19 20 #if defined(USE_SIMULATOR) 21 // Running with a simulator. 22 23 #include "src/arm/constants-arm.h" 24 #include "src/assembler.h" 25 #include "src/base/hashmap.h" 26 #include "src/simulator-base.h" 27 28 namespace v8 { 29 namespace internal { 30 31 class CachePage { 32 public: 33 static const int LINE_VALID = 0; 34 static const int LINE_INVALID = 1; 35 36 static const int kPageShift = 12; 37 static const int kPageSize = 1 << kPageShift; 38 static const int kPageMask = kPageSize - 1; 39 static const int kLineShift = 2; // The cache line is only 4 bytes right now. 40 static const int kLineLength = 1 << kLineShift; 41 static const int kLineMask = kLineLength - 1; 42 43 CachePage() { 44 memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); 45 } 46 47 char* ValidityByte(int offset) { 48 return &validity_map_[offset >> kLineShift]; 49 } 50 51 char* CachedData(int offset) { 52 return &data_[offset]; 53 } 54 55 private: 56 char data_[kPageSize]; // The cached data. 57 static const int kValidityMapSize = kPageSize >> kLineShift; 58 char validity_map_[kValidityMapSize]; // One byte per line. 59 }; 60 61 class Simulator : public SimulatorBase { 62 public: 63 friend class ArmDebugger; 64 enum Register { 65 no_reg = -1, 66 r0 = 0, r1, r2, r3, r4, r5, r6, r7, 67 r8, r9, r10, r11, r12, r13, r14, r15, 68 num_registers, 69 sp = 13, 70 lr = 14, 71 pc = 15, 72 s0 = 0, s1, s2, s3, s4, s5, s6, s7, 73 s8, s9, s10, s11, s12, s13, s14, s15, 74 s16, s17, s18, s19, s20, s21, s22, s23, 75 s24, s25, s26, s27, s28, s29, s30, s31, 76 num_s_registers = 32, 77 d0 = 0, d1, d2, d3, d4, d5, d6, d7, 78 d8, d9, d10, d11, d12, d13, d14, d15, 79 d16, d17, d18, d19, d20, d21, d22, d23, 80 d24, d25, d26, d27, d28, d29, d30, d31, 81 num_d_registers = 32, 82 q0 = 0, q1, q2, q3, q4, q5, q6, q7, 83 q8, q9, q10, q11, q12, q13, q14, q15, 84 num_q_registers = 16 85 }; 86 87 explicit Simulator(Isolate* isolate); 88 ~Simulator(); 89 90 // The currently executing Simulator instance. Potentially there can be one 91 // for each native thread. 92 V8_EXPORT_PRIVATE static Simulator* current(v8::internal::Isolate* isolate); 93 94 // Accessors for register state. Reading the pc value adheres to the ARM 95 // architecture specification and is off by a 8 from the currently executing 96 // instruction. 97 void set_register(int reg, int32_t value); 98 int32_t get_register(int reg) const; 99 double get_double_from_register_pair(int reg); 100 void set_register_pair_from_double(int reg, double* value); 101 void set_dw_register(int dreg, const int* dbl); 102 103 // Support for VFP. 104 void get_d_register(int dreg, uint64_t* value); 105 void set_d_register(int dreg, const uint64_t* value); 106 void get_d_register(int dreg, uint32_t* value); 107 void set_d_register(int dreg, const uint32_t* value); 108 // Support for NEON. 109 template <typename T, int SIZE = kSimd128Size> 110 void get_neon_register(int reg, T (&value)[SIZE / sizeof(T)]); 111 template <typename T, int SIZE = kSimd128Size> 112 void set_neon_register(int reg, const T (&value)[SIZE / sizeof(T)]); 113 114 void set_s_register(int reg, unsigned int value); 115 unsigned int get_s_register(int reg) const; 116 117 void set_d_register_from_double(int dreg, const Float64 dbl) { 118 SetVFPRegister<Float64, 2>(dreg, dbl); 119 } 120 void set_d_register_from_double(int dreg, const double dbl) { 121 SetVFPRegister<double, 2>(dreg, dbl); 122 } 123 124 Float64 get_double_from_d_register(int dreg) { 125 return GetFromVFPRegister<Float64, 2>(dreg); 126 } 127 128 void set_s_register_from_float(int sreg, const Float32 flt) { 129 SetVFPRegister<Float32, 1>(sreg, flt); 130 } 131 void set_s_register_from_float(int sreg, const float flt) { 132 SetVFPRegister<float, 1>(sreg, flt); 133 } 134 135 Float32 get_float_from_s_register(int sreg) { 136 return GetFromVFPRegister<Float32, 1>(sreg); 137 } 138 139 void set_s_register_from_sinteger(int sreg, const int sint) { 140 SetVFPRegister<int, 1>(sreg, sint); 141 } 142 143 int get_sinteger_from_s_register(int sreg) { 144 return GetFromVFPRegister<int, 1>(sreg); 145 } 146 147 // Special case of set_register and get_register to access the raw PC value. 148 void set_pc(int32_t value); 149 int32_t get_pc() const; 150 151 Address get_sp() const { return static_cast<Address>(get_register(sp)); } 152 153 // Accessor to the internal simulator stack area. 154 uintptr_t StackLimit(uintptr_t c_limit) const; 155 156 // Executes ARM instructions until the PC reaches end_sim_pc. 157 void Execute(); 158 159 template <typename Return, typename... Args> 160 Return Call(Address entry, Args... args) { 161 return VariadicCall<Return>(this, &Simulator::CallImpl, entry, args...); 162 } 163 164 // Alternative: call a 2-argument double function. 165 template <typename Return> 166 Return CallFP(Address entry, double d0, double d1) { 167 return ConvertReturn<Return>(CallFPImpl(entry, d0, d1)); 168 } 169 170 // Push an address onto the JS stack. 171 uintptr_t PushAddress(uintptr_t address); 172 173 // Pop an address from the JS stack. 174 uintptr_t PopAddress(); 175 176 // Debugger input. 177 void set_last_debugger_input(char* input); 178 char* last_debugger_input() { return last_debugger_input_; } 179 180 // Redirection support. 181 static void SetRedirectInstruction(Instruction* instruction); 182 183 // ICache checking. 184 static bool ICacheMatch(void* one, void* two); 185 static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start, 186 size_t size); 187 188 // Returns true if pc register contains one of the 'special_values' defined 189 // below (bad_lr, end_sim_pc). 190 bool has_bad_pc() const; 191 192 // EABI variant for double arguments in use. 193 bool use_eabi_hardfloat() { 194 #if USE_EABI_HARDFLOAT 195 return true; 196 #else 197 return false; 198 #endif 199 } 200 201 private: 202 enum special_values { 203 // Known bad pc value to ensure that the simulator does not execute 204 // without being properly setup. 205 bad_lr = -1, 206 // A pc value used to signal the simulator to stop execution. Generally 207 // the lr is set to this value on transition from native C code to 208 // simulated execution, so that the simulator can "return" to the native 209 // C code. 210 end_sim_pc = -2 211 }; 212 213 V8_EXPORT_PRIVATE intptr_t CallImpl(Address entry, int argument_count, 214 const intptr_t* arguments); 215 intptr_t CallFPImpl(Address entry, double d0, double d1); 216 217 // Unsupported instructions use Format to print an error and stop execution. 218 void Format(Instruction* instr, const char* format); 219 220 // Checks if the current instruction should be executed based on its 221 // condition bits. 222 inline bool ConditionallyExecute(Instruction* instr); 223 224 // Helper functions to set the conditional flags in the architecture state. 225 void SetNZFlags(int32_t val); 226 void SetCFlag(bool val); 227 void SetVFlag(bool val); 228 bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0); 229 bool BorrowFrom(int32_t left, int32_t right, int32_t carry = 1); 230 bool OverflowFrom(int32_t alu_out, 231 int32_t left, 232 int32_t right, 233 bool addition); 234 235 inline int GetCarry() { 236 return c_flag_ ? 1 : 0; 237 } 238 239 // Support for VFP. 240 void Compute_FPSCR_Flags(float val1, float val2); 241 void Compute_FPSCR_Flags(double val1, double val2); 242 void Copy_FPSCR_to_APSR(); 243 inline float canonicalizeNaN(float value); 244 inline double canonicalizeNaN(double value); 245 inline Float32 canonicalizeNaN(Float32 value); 246 inline Float64 canonicalizeNaN(Float64 value); 247 248 // Helper functions to decode common "addressing" modes 249 int32_t GetShiftRm(Instruction* instr, bool* carry_out); 250 int32_t GetImm(Instruction* instr, bool* carry_out); 251 int32_t ProcessPU(Instruction* instr, 252 int num_regs, 253 int operand_size, 254 intptr_t* start_address, 255 intptr_t* end_address); 256 void HandleRList(Instruction* instr, bool load); 257 void HandleVList(Instruction* inst); 258 void SoftwareInterrupt(Instruction* instr); 259 260 // Stop helper functions. 261 inline bool isStopInstruction(Instruction* instr); 262 inline bool isWatchedStop(uint32_t bkpt_code); 263 inline bool isEnabledStop(uint32_t bkpt_code); 264 inline void EnableStop(uint32_t bkpt_code); 265 inline void DisableStop(uint32_t bkpt_code); 266 inline void IncreaseStopCounter(uint32_t bkpt_code); 267 void PrintStopInfo(uint32_t code); 268 269 // Read and write memory. 270 // The *Ex functions are exclusive access. The writes return the strex status: 271 // 0 if the write succeeds, and 1 if the write fails. 272 inline uint8_t ReadBU(int32_t addr); 273 inline int8_t ReadB(int32_t addr); 274 uint8_t ReadExBU(int32_t addr); 275 inline void WriteB(int32_t addr, uint8_t value); 276 inline void WriteB(int32_t addr, int8_t value); 277 int WriteExB(int32_t addr, uint8_t value); 278 279 inline uint16_t ReadHU(int32_t addr); 280 inline int16_t ReadH(int32_t addr); 281 uint16_t ReadExHU(int32_t addr); 282 // Note: Overloaded on the sign of the value. 283 inline void WriteH(int32_t addr, uint16_t value); 284 inline void WriteH(int32_t addr, int16_t value); 285 int WriteExH(int32_t addr, uint16_t value); 286 287 inline int ReadW(int32_t addr); 288 int ReadExW(int32_t addr); 289 inline void WriteW(int32_t addr, int value); 290 int WriteExW(int32_t addr, int value); 291 292 int32_t* ReadDW(int32_t addr); 293 void WriteDW(int32_t addr, int32_t value1, int32_t value2); 294 int32_t* ReadExDW(int32_t addr); 295 int WriteExDW(int32_t addr, int32_t value1, int32_t value2); 296 297 // Executing is handled based on the instruction type. 298 // Both type 0 and type 1 rolled into one. 299 void DecodeType01(Instruction* instr); 300 void DecodeType2(Instruction* instr); 301 void DecodeType3(Instruction* instr); 302 void DecodeType4(Instruction* instr); 303 void DecodeType5(Instruction* instr); 304 void DecodeType6(Instruction* instr); 305 void DecodeType7(Instruction* instr); 306 307 // CP15 coprocessor instructions. 308 void DecodeTypeCP15(Instruction* instr); 309 310 // Support for VFP. 311 void DecodeTypeVFP(Instruction* instr); 312 void DecodeType6CoprocessorIns(Instruction* instr); 313 void DecodeSpecialCondition(Instruction* instr); 314 315 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); 316 void DecodeVCMP(Instruction* instr); 317 void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); 318 int32_t ConvertDoubleToInt(double val, bool unsigned_integer, 319 VFPRoundingMode mode); 320 void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr); 321 322 // Executes one instruction. 323 void InstructionDecode(Instruction* instr); 324 325 // ICache. 326 static void CheckICache(base::CustomMatcherHashMap* i_cache, 327 Instruction* instr); 328 static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start, 329 int size); 330 static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache, 331 void* page); 332 333 // Handle arguments and return value for runtime FP functions. 334 void GetFpArgs(double* x, double* y, int32_t* z); 335 void SetFpResult(const double& result); 336 void TrashCallerSaveRegisters(); 337 338 template<class ReturnType, int register_size> 339 ReturnType GetFromVFPRegister(int reg_index); 340 341 template<class InputType, int register_size> 342 void SetVFPRegister(int reg_index, const InputType& value); 343 344 void SetSpecialRegister(SRegisterFieldMask reg_and_mask, uint32_t value); 345 uint32_t GetFromSpecialRegister(SRegister reg); 346 347 void CallInternal(Address entry); 348 349 // Architecture state. 350 // Saturating instructions require a Q flag to indicate saturation. 351 // There is currently no way to read the CPSR directly, and thus read the Q 352 // flag, so this is left unimplemented. 353 int32_t registers_[16]; 354 bool n_flag_; 355 bool z_flag_; 356 bool c_flag_; 357 bool v_flag_; 358 359 // VFP architecture state. 360 unsigned int vfp_registers_[num_d_registers * 2]; 361 bool n_flag_FPSCR_; 362 bool z_flag_FPSCR_; 363 bool c_flag_FPSCR_; 364 bool v_flag_FPSCR_; 365 366 // VFP rounding mode. See ARM DDI 0406B Page A2-29. 367 VFPRoundingMode FPSCR_rounding_mode_; 368 bool FPSCR_default_NaN_mode_; 369 370 // VFP FP exception flags architecture state. 371 bool inv_op_vfp_flag_; 372 bool div_zero_vfp_flag_; 373 bool overflow_vfp_flag_; 374 bool underflow_vfp_flag_; 375 bool inexact_vfp_flag_; 376 377 // Simulator support. 378 char* stack_; 379 bool pc_modified_; 380 int icount_; 381 382 // Debugger input. 383 char* last_debugger_input_; 384 385 // Registered breakpoints. 386 Instruction* break_pc_; 387 Instr break_instr_; 388 389 v8::internal::Isolate* isolate_; 390 391 // A stop is watched if its code is less than kNumOfWatchedStops. 392 // Only watched stops support enabling/disabling and the counter feature. 393 static const uint32_t kNumOfWatchedStops = 256; 394 395 // Breakpoint is disabled if bit 31 is set. 396 static const uint32_t kStopDisabledBit = 1 << 31; 397 398 // A stop is enabled, meaning the simulator will stop when meeting the 399 // instruction, if bit 31 of watched_stops_[code].count is unset. 400 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 401 // the breakpoint was hit or gone through. 402 struct StopCountAndDesc { 403 uint32_t count; 404 char* desc; 405 }; 406 StopCountAndDesc watched_stops_[kNumOfWatchedStops]; 407 408 // Synchronization primitives. See ARM DDI 0406C.b, A2.9. 409 enum class MonitorAccess { 410 Open, 411 Exclusive, 412 }; 413 414 enum class TransactionSize { 415 None = 0, 416 Byte = 1, 417 HalfWord = 2, 418 Word = 4, 419 DoubleWord = 8, 420 }; 421 422 // The least-significant bits of the address are ignored. The number of bits 423 // is implementation-defined, between 3 and 11. See ARM DDI 0406C.b, A3.4.3. 424 static const int32_t kExclusiveTaggedAddrMask = ~((1 << 11) - 1); 425 426 class LocalMonitor { 427 public: 428 LocalMonitor(); 429 430 // These functions manage the state machine for the local monitor, but do 431 // not actually perform loads and stores. NotifyStoreExcl only returns 432 // true if the exclusive store is allowed; the global monitor will still 433 // have to be checked to see whether the memory should be updated. 434 void NotifyLoad(int32_t addr); 435 void NotifyLoadExcl(int32_t addr, TransactionSize size); 436 void NotifyStore(int32_t addr); 437 bool NotifyStoreExcl(int32_t addr, TransactionSize size); 438 439 private: 440 void Clear(); 441 442 MonitorAccess access_state_; 443 int32_t tagged_addr_; 444 TransactionSize size_; 445 }; 446 447 class GlobalMonitor { 448 public: 449 GlobalMonitor(); 450 451 class Processor { 452 public: 453 Processor(); 454 455 private: 456 friend class GlobalMonitor; 457 // These functions manage the state machine for the global monitor, but do 458 // not actually perform loads and stores. 459 void Clear_Locked(); 460 void NotifyLoadExcl_Locked(int32_t addr); 461 void NotifyStore_Locked(int32_t addr, bool is_requesting_processor); 462 bool NotifyStoreExcl_Locked(int32_t addr, bool is_requesting_processor); 463 464 MonitorAccess access_state_; 465 int32_t tagged_addr_; 466 Processor* next_; 467 Processor* prev_; 468 // A strex can fail due to background cache evictions. Rather than 469 // simulating this, we'll just occasionally introduce cases where an 470 // exclusive store fails. This will happen once after every 471 // kMaxFailureCounter exclusive stores. 472 static const int kMaxFailureCounter = 5; 473 int failure_counter_; 474 }; 475 476 // Exposed so it can be accessed by Simulator::{Read,Write}Ex*. 477 base::Mutex mutex; 478 479 void NotifyLoadExcl_Locked(int32_t addr, Processor* processor); 480 void NotifyStore_Locked(int32_t addr, Processor* processor); 481 bool NotifyStoreExcl_Locked(int32_t addr, Processor* processor); 482 483 // Called when the simulator is destroyed. 484 void RemoveProcessor(Processor* processor); 485 486 private: 487 bool IsProcessorInLinkedList_Locked(Processor* processor) const; 488 void PrependProcessor_Locked(Processor* processor); 489 490 Processor* head_; 491 }; 492 493 LocalMonitor local_monitor_; 494 GlobalMonitor::Processor global_monitor_processor_; 495 static base::LazyInstance<GlobalMonitor>::type global_monitor_; 496 }; 497 498 } // namespace internal 499 } // namespace v8 500 501 #endif // defined(USE_SIMULATOR) 502 #endif // V8_ARM_SIMULATOR_ARM_H_ 503