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