1 // Copyright 2011 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 MIPS instructions if we are not generating a native 7 // MIPS binary. This Simulator allows us to run and debug MIPS code generation 8 // on 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 MIPS HW platform. 12 13 #ifndef V8_MIPS_SIMULATOR_MIPS_H_ 14 #define V8_MIPS_SIMULATOR_MIPS_H_ 15 16 #include "src/allocation.h" 17 #include "src/mips/constants-mips.h" 18 19 #if !defined(USE_SIMULATOR) 20 // Running without a simulator on a native mips platform. 21 22 namespace v8 { 23 namespace internal { 24 25 // When running without a simulator we call the entry directly. 26 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 27 entry(p0, p1, p2, p3, p4) 28 29 typedef int (*mips_regexp_matcher)(String*, int, const byte*, const byte*, 30 void*, int*, int, Address, int, Isolate*); 31 32 33 // Call the generated regexp code directly. The code at the entry address 34 // should act as a function matching the type arm_regexp_matcher. 35 // The fifth argument is a dummy that reserves the space used for 36 // the return address added by the ExitFrame in native calls. 37 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 38 p7, p8) \ 39 (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6, \ 40 p7, p8)) 41 42 // The stack limit beyond which we will throw stack overflow errors in 43 // generated code. Because generated code on mips uses the C stack, we 44 // just use the C stack limit. 45 class SimulatorStack : public v8::internal::AllStatic { 46 public: 47 static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 48 uintptr_t c_limit) { 49 return c_limit; 50 } 51 52 static inline uintptr_t RegisterCTryCatch(Isolate* isolate, 53 uintptr_t try_catch_address) { 54 USE(isolate); 55 return try_catch_address; 56 } 57 58 static inline void UnregisterCTryCatch(Isolate* isolate) { USE(isolate); } 59 }; 60 61 } // namespace internal 62 } // namespace v8 63 64 // Calculated the stack limit beyond which we will throw stack overflow errors. 65 // This macro must be called from a C++ method. It relies on being able to take 66 // the address of "this" to get a value on the current execution stack and then 67 // calculates the stack limit based on that value. 68 // NOTE: The check for overflow is not safe as there is no guarantee that the 69 // running thread has its stack in all memory up to address 0x00000000. 70 #define GENERATED_CODE_STACK_LIMIT(limit) \ 71 (reinterpret_cast<uintptr_t>(this) >= limit ? \ 72 reinterpret_cast<uintptr_t>(this) - limit : 0) 73 74 #else // !defined(USE_SIMULATOR) 75 // Running with a simulator. 76 77 #include "src/assembler.h" 78 #include "src/hashmap.h" 79 80 namespace v8 { 81 namespace internal { 82 83 // ----------------------------------------------------------------------------- 84 // Utility functions 85 86 class CachePage { 87 public: 88 static const int LINE_VALID = 0; 89 static const int LINE_INVALID = 1; 90 91 static const int kPageShift = 12; 92 static const int kPageSize = 1 << kPageShift; 93 static const int kPageMask = kPageSize - 1; 94 static const int kLineShift = 2; // The cache line is only 4 bytes right now. 95 static const int kLineLength = 1 << kLineShift; 96 static const int kLineMask = kLineLength - 1; 97 98 CachePage() { 99 memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); 100 } 101 102 char* ValidityByte(int offset) { 103 return &validity_map_[offset >> kLineShift]; 104 } 105 106 char* CachedData(int offset) { 107 return &data_[offset]; 108 } 109 110 private: 111 char data_[kPageSize]; // The cached data. 112 static const int kValidityMapSize = kPageSize >> kLineShift; 113 char validity_map_[kValidityMapSize]; // One byte per line. 114 }; 115 116 class Simulator { 117 public: 118 friend class MipsDebugger; 119 120 // Registers are declared in order. See SMRL chapter 2. 121 enum Register { 122 no_reg = -1, 123 zero_reg = 0, 124 at, 125 v0, v1, 126 a0, a1, a2, a3, 127 t0, t1, t2, t3, t4, t5, t6, t7, 128 s0, s1, s2, s3, s4, s5, s6, s7, 129 t8, t9, 130 k0, k1, 131 gp, 132 sp, 133 s8, 134 ra, 135 // LO, HI, and pc. 136 LO, 137 HI, 138 pc, // pc must be the last register. 139 kNumSimuRegisters, 140 // aliases 141 fp = s8 142 }; 143 144 // Coprocessor registers. 145 // Generated code will always use doubles. So we will only use even registers. 146 enum FPURegister { 147 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, 148 f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters. 149 f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, 150 f26, f27, f28, f29, f30, f31, 151 kNumFPURegisters 152 }; 153 154 explicit Simulator(Isolate* isolate); 155 ~Simulator(); 156 157 // The currently executing Simulator instance. Potentially there can be one 158 // for each native thread. 159 static Simulator* current(v8::internal::Isolate* isolate); 160 161 // Accessors for register state. Reading the pc value adheres to the MIPS 162 // architecture specification and is off by a 8 from the currently executing 163 // instruction. 164 void set_register(int reg, int32_t value); 165 void set_dw_register(int dreg, const int* dbl); 166 int32_t get_register(int reg) const; 167 double get_double_from_register_pair(int reg); 168 // Same for FPURegisters. 169 void set_fpu_register(int fpureg, int64_t value); 170 void set_fpu_register_word(int fpureg, int32_t value); 171 void set_fpu_register_hi_word(int fpureg, int32_t value); 172 void set_fpu_register_float(int fpureg, float value); 173 void set_fpu_register_double(int fpureg, double value); 174 void set_fpu_register_invalid_result64(float original, float rounded); 175 void set_fpu_register_invalid_result(float original, float rounded); 176 void set_fpu_register_word_invalid_result(float original, float rounded); 177 void set_fpu_register_invalid_result64(double original, double rounded); 178 void set_fpu_register_invalid_result(double original, double rounded); 179 void set_fpu_register_word_invalid_result(double original, double rounded); 180 int64_t get_fpu_register(int fpureg) const; 181 int32_t get_fpu_register_word(int fpureg) const; 182 int32_t get_fpu_register_signed_word(int fpureg) const; 183 int32_t get_fpu_register_hi_word(int fpureg) const; 184 float get_fpu_register_float(int fpureg) const; 185 double get_fpu_register_double(int fpureg) const; 186 void set_fcsr_bit(uint32_t cc, bool value); 187 bool test_fcsr_bit(uint32_t cc); 188 void set_fcsr_rounding_mode(FPURoundingMode mode); 189 unsigned int get_fcsr_rounding_mode(); 190 bool set_fcsr_round_error(double original, double rounded); 191 bool set_fcsr_round_error(float original, float rounded); 192 bool set_fcsr_round64_error(double original, double rounded); 193 bool set_fcsr_round64_error(float original, float rounded); 194 void round_according_to_fcsr(double toRound, double& rounded, 195 int32_t& rounded_int, double fs); 196 void round_according_to_fcsr(float toRound, float& rounded, 197 int32_t& rounded_int, float fs); 198 void round64_according_to_fcsr(double toRound, double& rounded, 199 int64_t& rounded_int, double fs); 200 void round64_according_to_fcsr(float toRound, float& rounded, 201 int64_t& rounded_int, float fs); 202 // Special case of set_register and get_register to access the raw PC value. 203 void set_pc(int32_t value); 204 int32_t get_pc() const; 205 206 Address get_sp() const { 207 return reinterpret_cast<Address>(static_cast<intptr_t>(get_register(sp))); 208 } 209 210 // Accessor to the internal simulator stack area. 211 uintptr_t StackLimit(uintptr_t c_limit) const; 212 213 // Executes MIPS instructions until the PC reaches end_sim_pc. 214 void Execute(); 215 216 // Call on program start. 217 static void Initialize(Isolate* isolate); 218 219 static void TearDown(HashMap* i_cache, Redirection* first); 220 221 // V8 generally calls into generated JS code with 5 parameters and into 222 // generated RegExp code with 7 parameters. This is a convenience function, 223 // which sets up the simulator state and grabs the result on return. 224 int32_t Call(byte* entry, int argument_count, ...); 225 // Alternative: call a 2-argument double function. 226 double CallFP(byte* entry, double d0, double d1); 227 228 // Push an address onto the JS stack. 229 uintptr_t PushAddress(uintptr_t address); 230 231 // Pop an address from the JS stack. 232 uintptr_t PopAddress(); 233 234 // Debugger input. 235 void set_last_debugger_input(char* input); 236 char* last_debugger_input() { return last_debugger_input_; } 237 238 // ICache checking. 239 static void FlushICache(v8::internal::HashMap* i_cache, void* start, 240 size_t size); 241 242 // Returns true if pc register contains one of the 'special_values' defined 243 // below (bad_ra, end_sim_pc). 244 bool has_bad_pc() const; 245 246 private: 247 enum special_values { 248 // Known bad pc value to ensure that the simulator does not execute 249 // without being properly setup. 250 bad_ra = -1, 251 // A pc value used to signal the simulator to stop execution. Generally 252 // the ra is set to this value on transition from native C code to 253 // simulated execution, so that the simulator can "return" to the native 254 // C code. 255 end_sim_pc = -2, 256 // Unpredictable value. 257 Unpredictable = 0xbadbeaf 258 }; 259 260 // Unsupported instructions use Format to print an error and stop execution. 261 void Format(Instruction* instr, const char* format); 262 263 // Read and write memory. 264 inline uint32_t ReadBU(int32_t addr); 265 inline int32_t ReadB(int32_t addr); 266 inline void WriteB(int32_t addr, uint8_t value); 267 inline void WriteB(int32_t addr, int8_t value); 268 269 inline uint16_t ReadHU(int32_t addr, Instruction* instr); 270 inline int16_t ReadH(int32_t addr, Instruction* instr); 271 // Note: Overloaded on the sign of the value. 272 inline void WriteH(int32_t addr, uint16_t value, Instruction* instr); 273 inline void WriteH(int32_t addr, int16_t value, Instruction* instr); 274 275 inline int ReadW(int32_t addr, Instruction* instr); 276 inline void WriteW(int32_t addr, int value, Instruction* instr); 277 278 inline double ReadD(int32_t addr, Instruction* instr); 279 inline void WriteD(int32_t addr, double value, Instruction* instr); 280 281 // Helpers for data value tracing. 282 enum TraceType { 283 BYTE, 284 HALF, 285 WORD 286 // DWORD, 287 // DFLOAT - Floats may have printing issues due to paired lwc1's 288 }; 289 290 void TraceRegWr(int32_t value); 291 void TraceMemWr(int32_t addr, int32_t value, TraceType t); 292 void TraceMemRd(int32_t addr, int32_t value); 293 EmbeddedVector<char, 128> trace_buf_; 294 295 // Operations depending on endianness. 296 // Get Double Higher / Lower word. 297 inline int32_t GetDoubleHIW(double* addr); 298 inline int32_t GetDoubleLOW(double* addr); 299 // Set Double Higher / Lower word. 300 inline int32_t SetDoubleHIW(double* addr); 301 inline int32_t SetDoubleLOW(double* addr); 302 303 // Executing is handled based on the instruction type. 304 void DecodeTypeRegister(Instruction* instr); 305 306 // Functions called from DecodeTypeRegister. 307 void DecodeTypeRegisterCOP1(); 308 309 void DecodeTypeRegisterCOP1X(); 310 311 void DecodeTypeRegisterSPECIAL(); 312 313 void DecodeTypeRegisterSPECIAL2(); 314 315 void DecodeTypeRegisterSPECIAL3(); 316 317 // Called from DecodeTypeRegisterCOP1. 318 void DecodeTypeRegisterSRsType(); 319 320 void DecodeTypeRegisterDRsType(); 321 322 void DecodeTypeRegisterWRsType(); 323 324 void DecodeTypeRegisterLRsType(); 325 326 Instruction* currentInstr_; 327 328 inline Instruction* get_instr() const { return currentInstr_; } 329 inline void set_instr(Instruction* instr) { currentInstr_ = instr; } 330 331 inline int32_t rs_reg() const { return currentInstr_->RsValue(); } 332 inline int32_t rs() const { return get_register(rs_reg()); } 333 inline uint32_t rs_u() const { 334 return static_cast<uint32_t>(get_register(rs_reg())); 335 } 336 inline int32_t rt_reg() const { return currentInstr_->RtValue(); } 337 inline int32_t rt() const { return get_register(rt_reg()); } 338 inline uint32_t rt_u() const { 339 return static_cast<uint32_t>(get_register(rt_reg())); 340 } 341 inline int32_t rd_reg() const { return currentInstr_->RdValue(); } 342 inline int32_t fr_reg() const { return currentInstr_->FrValue(); } 343 inline int32_t fs_reg() const { return currentInstr_->FsValue(); } 344 inline int32_t ft_reg() const { return currentInstr_->FtValue(); } 345 inline int32_t fd_reg() const { return currentInstr_->FdValue(); } 346 inline int32_t sa() const { return currentInstr_->SaValue(); } 347 inline int32_t lsa_sa() const { return currentInstr_->LsaSaValue(); } 348 349 inline void SetResult(int32_t rd_reg, int32_t alu_out) { 350 set_register(rd_reg, alu_out); 351 TraceRegWr(alu_out); 352 } 353 354 void DecodeTypeImmediate(Instruction* instr); 355 void DecodeTypeJump(Instruction* instr); 356 357 // Used for breakpoints and traps. 358 void SoftwareInterrupt(Instruction* instr); 359 360 // Compact branch guard. 361 void CheckForbiddenSlot(int32_t current_pc) { 362 Instruction* instr_aftter_compact_branch = 363 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); 364 if (instr_aftter_compact_branch->IsForbiddenInBranchDelay()) { 365 V8_Fatal(__FILE__, __LINE__, 366 "Error: Unexpected instruction 0x%08x immediately after a " 367 "compact branch instruction.", 368 *reinterpret_cast<uint32_t*>(instr_aftter_compact_branch)); 369 } 370 } 371 372 // Stop helper functions. 373 bool IsWatchpoint(uint32_t code); 374 void PrintWatchpoint(uint32_t code); 375 void HandleStop(uint32_t code, Instruction* instr); 376 bool IsStopInstruction(Instruction* instr); 377 bool IsEnabledStop(uint32_t code); 378 void EnableStop(uint32_t code); 379 void DisableStop(uint32_t code); 380 void IncreaseStopCounter(uint32_t code); 381 void PrintStopInfo(uint32_t code); 382 383 384 // Executes one instruction. 385 void InstructionDecode(Instruction* instr); 386 // Execute one instruction placed in a branch delay slot. 387 void BranchDelayInstructionDecode(Instruction* instr) { 388 if (instr->InstructionBits() == nopInstr) { 389 // Short-cut generic nop instructions. They are always valid and they 390 // never change the simulator state. 391 return; 392 } 393 394 if (instr->IsForbiddenInBranchDelay()) { 395 V8_Fatal(__FILE__, __LINE__, 396 "Eror:Unexpected %i opcode in a branch delay slot.", 397 instr->OpcodeValue()); 398 } 399 InstructionDecode(instr); 400 SNPrintF(trace_buf_, " "); 401 } 402 403 // ICache. 404 static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr); 405 static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start, 406 int size); 407 static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page); 408 409 enum Exception { 410 none, 411 kIntegerOverflow, 412 kIntegerUnderflow, 413 kDivideByZero, 414 kNumExceptions 415 }; 416 417 // Exceptions. 418 void SignalException(Exception e); 419 420 // Runtime call support. 421 static void* RedirectExternalReference(Isolate* isolate, 422 void* external_function, 423 ExternalReference::Type type); 424 425 // Handle arguments and return value for runtime FP functions. 426 void GetFpArgs(double* x, double* y, int32_t* z); 427 void SetFpResult(const double& result); 428 429 void CallInternal(byte* entry); 430 431 // Architecture state. 432 // Registers. 433 int32_t registers_[kNumSimuRegisters]; 434 // Coprocessor Registers. 435 // Note: FP32 mode uses only the lower 32-bit part of each element, 436 // the upper 32-bit is unpredictable. 437 int64_t FPUregisters_[kNumFPURegisters]; 438 // FPU control register. 439 uint32_t FCSR_; 440 441 // Simulator support. 442 // Allocate 1MB for stack. 443 static const size_t stack_size_ = 1 * 1024*1024; 444 char* stack_; 445 bool pc_modified_; 446 uint64_t icount_; 447 int break_count_; 448 449 // Debugger input. 450 char* last_debugger_input_; 451 452 // Icache simulation. 453 v8::internal::HashMap* i_cache_; 454 455 v8::internal::Isolate* isolate_; 456 457 // Registered breakpoints. 458 Instruction* break_pc_; 459 Instr break_instr_; 460 461 // Stop is disabled if bit 31 is set. 462 static const uint32_t kStopDisabledBit = 1 << 31; 463 464 // A stop is enabled, meaning the simulator will stop when meeting the 465 // instruction, if bit 31 of watched_stops_[code].count is unset. 466 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times 467 // the breakpoint was hit or gone through. 468 struct StopCountAndDesc { 469 uint32_t count; 470 char* desc; 471 }; 472 StopCountAndDesc watched_stops_[kMaxStopCode + 1]; 473 }; 474 475 476 // When running with the simulator transition into simulated execution at this 477 // point. 478 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 479 reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \ 480 FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) 481 482 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 483 p7, p8) \ 484 Simulator::current(isolate) \ 485 ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8) 486 487 488 // The simulator has its own stack. Thus it has a different stack limit from 489 // the C-based native code. The JS-based limit normally points near the end of 490 // the simulator stack. When the C-based limit is exhausted we reflect that by 491 // lowering the JS-based limit as well, to make stack checks trigger. 492 class SimulatorStack : public v8::internal::AllStatic { 493 public: 494 static inline uintptr_t JsLimitFromCLimit(Isolate* isolate, 495 uintptr_t c_limit) { 496 return Simulator::current(isolate)->StackLimit(c_limit); 497 } 498 499 static inline uintptr_t RegisterCTryCatch(Isolate* isolate, 500 uintptr_t try_catch_address) { 501 Simulator* sim = Simulator::current(isolate); 502 return sim->PushAddress(try_catch_address); 503 } 504 505 static inline void UnregisterCTryCatch(Isolate* isolate) { 506 Simulator::current(isolate)->PopAddress(); 507 } 508 }; 509 510 } // namespace internal 511 } // namespace v8 512 513 #endif // !defined(USE_SIMULATOR) 514 #endif // V8_MIPS_SIMULATOR_MIPS_H_ 515