1// Copyright 2013 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#ifndef V8_ARM64_SIMULATOR_ARM64_H_ 6#define V8_ARM64_SIMULATOR_ARM64_H_ 7 8#include <stdarg.h> 9#include <vector> 10 11#include "src/v8.h" 12 13#include "src/globals.h" 14#include "src/utils.h" 15#include "src/allocation.h" 16#include "src/assembler.h" 17#include "src/arm64/assembler-arm64.h" 18#include "src/arm64/decoder-arm64.h" 19#include "src/arm64/disasm-arm64.h" 20#include "src/arm64/instrument-arm64.h" 21 22#define REGISTER_CODE_LIST(R) \ 23R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 24R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 25R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 26R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) 27 28namespace v8 { 29namespace internal { 30 31#if !defined(USE_SIMULATOR) 32 33// Running without a simulator on a native ARM64 platform. 34// When running without a simulator we call the entry directly. 35#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ 36 (entry(p0, p1, p2, p3, p4)) 37 38typedef int (*arm64_regexp_matcher)(String* input, 39 int64_t start_offset, 40 const byte* input_start, 41 const byte* input_end, 42 int* output, 43 int64_t output_size, 44 Address stack_base, 45 int64_t direct_call, 46 void* return_address, 47 Isolate* isolate); 48 49// Call the generated regexp code directly. The code at the entry address 50// should act as a function matching the type arm64_regexp_matcher. 51// The ninth argument is a dummy that reserves the space used for 52// the return address added by the ExitFrame in native calls. 53#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ 54 (FUNCTION_CAST<arm64_regexp_matcher>(entry)( \ 55 p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)) 56 57// Running without a simulator there is nothing to do. 58class SimulatorStack : public v8::internal::AllStatic { 59 public: 60 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 61 uintptr_t c_limit) { 62 USE(isolate); 63 return c_limit; 64 } 65 66 static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 67 return try_catch_address; 68 } 69 70 static void UnregisterCTryCatch() { } 71}; 72 73#else // !defined(USE_SIMULATOR) 74 75enum ReverseByteMode { 76 Reverse16 = 0, 77 Reverse32 = 1, 78 Reverse64 = 2 79}; 80 81 82// The proper way to initialize a simulated system register (such as NZCV) is as 83// follows: 84// SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV); 85class SimSystemRegister { 86 public: 87 // The default constructor represents a register which has no writable bits. 88 // It is not possible to set its value to anything other than 0. 89 SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { } 90 91 uint32_t RawValue() const { 92 return value_; 93 } 94 95 void SetRawValue(uint32_t new_value) { 96 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_); 97 } 98 99 uint32_t Bits(int msb, int lsb) const { 100 return unsigned_bitextract_32(msb, lsb, value_); 101 } 102 103 int32_t SignedBits(int msb, int lsb) const { 104 return signed_bitextract_32(msb, lsb, value_); 105 } 106 107 void SetBits(int msb, int lsb, uint32_t bits); 108 109 // Default system register values. 110 static SimSystemRegister DefaultValueFor(SystemRegister id); 111 112#define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type) \ 113 Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); } \ 114 void Set##Name(Type bits) { \ 115 SetBits(HighBit, LowBit, static_cast<Type>(bits)); \ 116 } 117#define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \ 118 static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask); 119 SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK) 120#undef DEFINE_ZERO_BITS 121#undef DEFINE_GETTER 122 123 protected: 124 // Most system registers only implement a few of the bits in the word. Other 125 // bits are "read-as-zero, write-ignored". The write_ignore_mask argument 126 // describes the bits which are not modifiable. 127 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask) 128 : value_(value), write_ignore_mask_(write_ignore_mask) { } 129 130 uint32_t value_; 131 uint32_t write_ignore_mask_; 132}; 133 134 135// Represent a register (r0-r31, v0-v31). 136class SimRegisterBase { 137 public: 138 template<typename T> 139 void Set(T new_value) { 140 value_ = 0; 141 memcpy(&value_, &new_value, sizeof(T)); 142 } 143 144 template<typename T> 145 T Get() const { 146 T result; 147 memcpy(&result, &value_, sizeof(T)); 148 return result; 149 } 150 151 protected: 152 int64_t value_; 153}; 154 155 156typedef SimRegisterBase SimRegister; // r0-r31 157typedef SimRegisterBase SimFPRegister; // v0-v31 158 159 160class Simulator : public DecoderVisitor { 161 public: 162 explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder, 163 Isolate* isolate = NULL, 164 FILE* stream = stderr); 165 Simulator(); 166 ~Simulator(); 167 168 // System functions. 169 170 static void Initialize(Isolate* isolate); 171 172 static Simulator* current(v8::internal::Isolate* isolate); 173 174 class CallArgument; 175 176 // Call an arbitrary function taking an arbitrary number of arguments. The 177 // varargs list must be a set of arguments with type CallArgument, and 178 // terminated by CallArgument::End(). 179 void CallVoid(byte* entry, CallArgument* args); 180 181 // Like CallVoid, but expect a return value. 182 int64_t CallInt64(byte* entry, CallArgument* args); 183 double CallDouble(byte* entry, CallArgument* args); 184 185 // V8 calls into generated JS code with 5 parameters and into 186 // generated RegExp code with 10 parameters. These are convenience functions, 187 // which set up the simulator state and grab the result on return. 188 int64_t CallJS(byte* entry, 189 byte* function_entry, 190 JSFunction* func, 191 Object* revc, 192 int64_t argc, 193 Object*** argv); 194 int64_t CallRegExp(byte* entry, 195 String* input, 196 int64_t start_offset, 197 const byte* input_start, 198 const byte* input_end, 199 int* output, 200 int64_t output_size, 201 Address stack_base, 202 int64_t direct_call, 203 void* return_address, 204 Isolate* isolate); 205 206 // A wrapper class that stores an argument for one of the above Call 207 // functions. 208 // 209 // Only arguments up to 64 bits in size are supported. 210 class CallArgument { 211 public: 212 template<typename T> 213 explicit CallArgument(T argument) { 214 ASSERT(sizeof(argument) <= sizeof(bits_)); 215 memcpy(&bits_, &argument, sizeof(argument)); 216 type_ = X_ARG; 217 } 218 219 explicit CallArgument(double argument) { 220 ASSERT(sizeof(argument) == sizeof(bits_)); 221 memcpy(&bits_, &argument, sizeof(argument)); 222 type_ = D_ARG; 223 } 224 225 explicit CallArgument(float argument) { 226 // TODO(all): CallArgument(float) is untested, remove this check once 227 // tested. 228 UNIMPLEMENTED(); 229 // Make the D register a NaN to try to trap errors if the callee expects a 230 // double. If it expects a float, the callee should ignore the top word. 231 ASSERT(sizeof(kFP64SignallingNaN) == sizeof(bits_)); 232 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN)); 233 // Write the float payload to the S register. 234 ASSERT(sizeof(argument) <= sizeof(bits_)); 235 memcpy(&bits_, &argument, sizeof(argument)); 236 type_ = D_ARG; 237 } 238 239 // This indicates the end of the arguments list, so that CallArgument 240 // objects can be passed into varargs functions. 241 static CallArgument End() { return CallArgument(); } 242 243 int64_t bits() const { return bits_; } 244 bool IsEnd() const { return type_ == NO_ARG; } 245 bool IsX() const { return type_ == X_ARG; } 246 bool IsD() const { return type_ == D_ARG; } 247 248 private: 249 enum CallArgumentType { X_ARG, D_ARG, NO_ARG }; 250 251 // All arguments are aligned to at least 64 bits and we don't support 252 // passing bigger arguments, so the payload size can be fixed at 64 bits. 253 int64_t bits_; 254 CallArgumentType type_; 255 256 CallArgument() { type_ = NO_ARG; } 257 }; 258 259 260 // Start the debugging command line. 261 void Debug(); 262 263 bool GetValue(const char* desc, int64_t* value); 264 265 bool PrintValue(const char* desc); 266 267 // Push an address onto the JS stack. 268 uintptr_t PushAddress(uintptr_t address); 269 270 // Pop an address from the JS stack. 271 uintptr_t PopAddress(); 272 273 // Accessor to the internal simulator stack area. 274 uintptr_t StackLimit() const; 275 276 void ResetState(); 277 278 // Runtime call support. 279 static void* RedirectExternalReference(void* external_function, 280 ExternalReference::Type type); 281 void DoRuntimeCall(Instruction* instr); 282 283 // Run the simulator. 284 static const Instruction* kEndOfSimAddress; 285 void DecodeInstruction(); 286 void Run(); 287 void RunFrom(Instruction* start); 288 289 // Simulation helpers. 290 template <typename T> 291 void set_pc(T new_pc) { 292 ASSERT(sizeof(T) == sizeof(pc_)); 293 memcpy(&pc_, &new_pc, sizeof(T)); 294 pc_modified_ = true; 295 } 296 Instruction* pc() { return pc_; } 297 298 void increment_pc() { 299 if (!pc_modified_) { 300 pc_ = pc_->following(); 301 } 302 303 pc_modified_ = false; 304 } 305 306 virtual void Decode(Instruction* instr) { 307 decoder_->Decode(instr); 308 } 309 310 void ExecuteInstruction() { 311 ASSERT(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize)); 312 CheckBreakNext(); 313 Decode(pc_); 314 LogProcessorState(); 315 increment_pc(); 316 CheckBreakpoints(); 317 } 318 319 // Declare all Visitor functions. 320 #define DECLARE(A) void Visit##A(Instruction* instr); 321 VISITOR_LIST(DECLARE) 322 #undef DECLARE 323 324 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const { 325 return ((code == 31) && (r31mode == Reg31IsZeroRegister)); 326 } 327 328 // Register accessors. 329 // Return 'size' bits of the value of an integer register, as the specified 330 // type. The value is zero-extended to fill the result. 331 // 332 template<typename T> 333 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { 334 ASSERT(code < kNumberOfRegisters); 335 if (IsZeroRegister(code, r31mode)) { 336 return 0; 337 } 338 return registers_[code].Get<T>(); 339 } 340 341 // Common specialized accessors for the reg() template. 342 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { 343 return reg<int32_t>(code, r31mode); 344 } 345 346 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { 347 return reg<int64_t>(code, r31mode); 348 } 349 350 // Write 'size' bits of 'value' into an integer register. The value is 351 // zero-extended. This behaviour matches AArch64 register writes. 352 353 // Like set_reg(), but infer the access size from the template type. 354 template<typename T> 355 void set_reg(unsigned code, T value, 356 Reg31Mode r31mode = Reg31IsZeroRegister) { 357 ASSERT(code < kNumberOfRegisters); 358 if (!IsZeroRegister(code, r31mode)) 359 registers_[code].Set(value); 360 } 361 362 // Common specialized accessors for the set_reg() template. 363 void set_wreg(unsigned code, int32_t value, 364 Reg31Mode r31mode = Reg31IsZeroRegister) { 365 set_reg(code, value, r31mode); 366 } 367 368 void set_xreg(unsigned code, int64_t value, 369 Reg31Mode r31mode = Reg31IsZeroRegister) { 370 set_reg(code, value, r31mode); 371 } 372 373 // Commonly-used special cases. 374 template<typename T> 375 void set_lr(T value) { 376 ASSERT(sizeof(T) == kPointerSize); 377 set_reg(kLinkRegCode, value); 378 } 379 380 template<typename T> 381 void set_sp(T value) { 382 ASSERT(sizeof(T) == kPointerSize); 383 set_reg(31, value, Reg31IsStackPointer); 384 } 385 386 int64_t sp() { return xreg(31, Reg31IsStackPointer); } 387 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); } 388 int64_t fp() { 389 return xreg(kFramePointerRegCode, Reg31IsStackPointer); 390 } 391 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); } 392 393 Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); } 394 395 template<typename T> 396 T fpreg(unsigned code) const { 397 ASSERT(code < kNumberOfRegisters); 398 return fpregisters_[code].Get<T>(); 399 } 400 401 // Common specialized accessors for the fpreg() template. 402 float sreg(unsigned code) const { 403 return fpreg<float>(code); 404 } 405 406 uint32_t sreg_bits(unsigned code) const { 407 return fpreg<uint32_t>(code); 408 } 409 410 double dreg(unsigned code) const { 411 return fpreg<double>(code); 412 } 413 414 uint64_t dreg_bits(unsigned code) const { 415 return fpreg<uint64_t>(code); 416 } 417 418 double fpreg(unsigned size, unsigned code) const { 419 switch (size) { 420 case kSRegSizeInBits: return sreg(code); 421 case kDRegSizeInBits: return dreg(code); 422 default: 423 UNREACHABLE(); 424 return 0.0; 425 } 426 } 427 428 // Write 'value' into a floating-point register. The value is zero-extended. 429 // This behaviour matches AArch64 register writes. 430 template<typename T> 431 void set_fpreg(unsigned code, T value) { 432 ASSERT((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); 433 ASSERT(code < kNumberOfFPRegisters); 434 fpregisters_[code].Set(value); 435 } 436 437 // Common specialized accessors for the set_fpreg() template. 438 void set_sreg(unsigned code, float value) { 439 set_fpreg(code, value); 440 } 441 442 void set_sreg_bits(unsigned code, uint32_t value) { 443 set_fpreg(code, value); 444 } 445 446 void set_dreg(unsigned code, double value) { 447 set_fpreg(code, value); 448 } 449 450 void set_dreg_bits(unsigned code, uint64_t value) { 451 set_fpreg(code, value); 452 } 453 454 SimSystemRegister& nzcv() { return nzcv_; } 455 SimSystemRegister& fpcr() { return fpcr_; } 456 457 // Debug helpers 458 459 // Simulator breakpoints. 460 struct Breakpoint { 461 Instruction* location; 462 bool enabled; 463 }; 464 std::vector<Breakpoint> breakpoints_; 465 void SetBreakpoint(Instruction* breakpoint); 466 void ListBreakpoints(); 467 void CheckBreakpoints(); 468 469 // Helpers for the 'next' command. 470 // When this is set, the Simulator will insert a breakpoint after the next BL 471 // instruction it meets. 472 bool break_on_next_; 473 // Check if the Simulator should insert a break after the current instruction 474 // for the 'next' command. 475 void CheckBreakNext(); 476 477 // Disassemble instruction at the given address. 478 void PrintInstructionsAt(Instruction* pc, uint64_t count); 479 480 void PrintSystemRegisters(bool print_all = false); 481 void PrintRegisters(bool print_all_regs = false); 482 void PrintFPRegisters(bool print_all_regs = false); 483 void PrintProcessorState(); 484 void PrintWrite(uint8_t* address, uint64_t value, unsigned num_bytes); 485 void LogSystemRegisters() { 486 if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters(); 487 } 488 void LogRegisters() { 489 if (log_parameters_ & LOG_REGS) PrintRegisters(); 490 } 491 void LogFPRegisters() { 492 if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters(); 493 } 494 void LogProcessorState() { 495 LogSystemRegisters(); 496 LogRegisters(); 497 LogFPRegisters(); 498 } 499 void LogWrite(uint8_t* address, uint64_t value, unsigned num_bytes) { 500 if (log_parameters_ & LOG_WRITE) PrintWrite(address, value, num_bytes); 501 } 502 503 int log_parameters() { return log_parameters_; } 504 void set_log_parameters(int new_parameters) { 505 log_parameters_ = new_parameters; 506 if (!decoder_) { 507 if (new_parameters & LOG_DISASM) { 508 PrintF("Run --debug-sim to dynamically turn on disassembler\n"); 509 } 510 return; 511 } 512 if (new_parameters & LOG_DISASM) { 513 decoder_->InsertVisitorBefore(print_disasm_, this); 514 } else { 515 decoder_->RemoveVisitor(print_disasm_); 516 } 517 } 518 519 static inline const char* WRegNameForCode(unsigned code, 520 Reg31Mode mode = Reg31IsZeroRegister); 521 static inline const char* XRegNameForCode(unsigned code, 522 Reg31Mode mode = Reg31IsZeroRegister); 523 static inline const char* SRegNameForCode(unsigned code); 524 static inline const char* DRegNameForCode(unsigned code); 525 static inline const char* VRegNameForCode(unsigned code); 526 static inline int CodeFromName(const char* name); 527 528 protected: 529 // Simulation helpers ------------------------------------ 530 bool ConditionPassed(Condition cond) { 531 SimSystemRegister& flags = nzcv(); 532 switch (cond) { 533 case eq: 534 return flags.Z(); 535 case ne: 536 return !flags.Z(); 537 case hs: 538 return flags.C(); 539 case lo: 540 return !flags.C(); 541 case mi: 542 return flags.N(); 543 case pl: 544 return !flags.N(); 545 case vs: 546 return flags.V(); 547 case vc: 548 return !flags.V(); 549 case hi: 550 return flags.C() && !flags.Z(); 551 case ls: 552 return !(flags.C() && !flags.Z()); 553 case ge: 554 return flags.N() == flags.V(); 555 case lt: 556 return flags.N() != flags.V(); 557 case gt: 558 return !flags.Z() && (flags.N() == flags.V()); 559 case le: 560 return !(!flags.Z() && (flags.N() == flags.V())); 561 case nv: // Fall through. 562 case al: 563 return true; 564 default: 565 UNREACHABLE(); 566 return false; 567 } 568 } 569 570 bool ConditionFailed(Condition cond) { 571 return !ConditionPassed(cond); 572 } 573 574 template<typename T> 575 void AddSubHelper(Instruction* instr, T op2); 576 template<typename T> 577 T AddWithCarry(bool set_flags, 578 T src1, 579 T src2, 580 T carry_in = 0); 581 template<typename T> 582 void AddSubWithCarry(Instruction* instr); 583 template<typename T> 584 void LogicalHelper(Instruction* instr, T op2); 585 template<typename T> 586 void ConditionalCompareHelper(Instruction* instr, T op2); 587 void LoadStoreHelper(Instruction* instr, 588 int64_t offset, 589 AddrMode addrmode); 590 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode); 591 uint8_t* LoadStoreAddress(unsigned addr_reg, 592 int64_t offset, 593 AddrMode addrmode); 594 void LoadStoreWriteBack(unsigned addr_reg, 595 int64_t offset, 596 AddrMode addrmode); 597 void CheckMemoryAccess(uint8_t* address, uint8_t* stack); 598 599 uint64_t MemoryRead(uint8_t* address, unsigned num_bytes); 600 uint8_t MemoryRead8(uint8_t* address); 601 uint16_t MemoryRead16(uint8_t* address); 602 uint32_t MemoryRead32(uint8_t* address); 603 float MemoryReadFP32(uint8_t* address); 604 uint64_t MemoryRead64(uint8_t* address); 605 double MemoryReadFP64(uint8_t* address); 606 607 void MemoryWrite(uint8_t* address, uint64_t value, unsigned num_bytes); 608 void MemoryWrite32(uint8_t* address, uint32_t value); 609 void MemoryWriteFP32(uint8_t* address, float value); 610 void MemoryWrite64(uint8_t* address, uint64_t value); 611 void MemoryWriteFP64(uint8_t* address, double value); 612 613 614 template <typename T> 615 T ShiftOperand(T value, 616 Shift shift_type, 617 unsigned amount); 618 template <typename T> 619 T ExtendValue(T value, 620 Extend extend_type, 621 unsigned left_shift = 0); 622 template <typename T> 623 void Extract(Instruction* instr); 624 template <typename T> 625 void DataProcessing2Source(Instruction* instr); 626 template <typename T> 627 void BitfieldHelper(Instruction* instr); 628 629 uint64_t ReverseBits(uint64_t value, unsigned num_bits); 630 uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode); 631 632 template <typename T> 633 T FPDefaultNaN() const; 634 635 void FPCompare(double val0, double val1); 636 double FPRoundInt(double value, FPRounding round_mode); 637 double FPToDouble(float value); 638 float FPToFloat(double value, FPRounding round_mode); 639 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode); 640 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode); 641 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode); 642 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode); 643 int32_t FPToInt32(double value, FPRounding rmode); 644 int64_t FPToInt64(double value, FPRounding rmode); 645 uint32_t FPToUInt32(double value, FPRounding rmode); 646 uint64_t FPToUInt64(double value, FPRounding rmode); 647 648 template <typename T> 649 T FPAdd(T op1, T op2); 650 651 template <typename T> 652 T FPDiv(T op1, T op2); 653 654 template <typename T> 655 T FPMax(T a, T b); 656 657 template <typename T> 658 T FPMaxNM(T a, T b); 659 660 template <typename T> 661 T FPMin(T a, T b); 662 663 template <typename T> 664 T FPMinNM(T a, T b); 665 666 template <typename T> 667 T FPMul(T op1, T op2); 668 669 template <typename T> 670 T FPMulAdd(T a, T op1, T op2); 671 672 template <typename T> 673 T FPSqrt(T op); 674 675 template <typename T> 676 T FPSub(T op1, T op2); 677 678 // Standard NaN processing. 679 template <typename T> 680 T FPProcessNaN(T op); 681 682 bool FPProcessNaNs(Instruction* instr); 683 684 template <typename T> 685 T FPProcessNaNs(T op1, T op2); 686 687 template <typename T> 688 T FPProcessNaNs3(T op1, T op2, T op3); 689 690 void CheckStackAlignment(); 691 692 inline void CheckPCSComplianceAndRun(); 693 694#ifdef DEBUG 695 // Corruption values should have their least significant byte cleared to 696 // allow the code of the register being corrupted to be inserted. 697 static const uint64_t kCallerSavedRegisterCorruptionValue = 698 0xca11edc0de000000UL; 699 // This value is a NaN in both 32-bit and 64-bit FP. 700 static const uint64_t kCallerSavedFPRegisterCorruptionValue = 701 0x7ff000007f801000UL; 702 // This value is a mix of 32/64-bits NaN and "verbose" immediate. 703 static const uint64_t kDefaultCPURegisterCorruptionValue = 704 0x7ffbad007f8bad00UL; 705 706 void CorruptRegisters(CPURegList* list, 707 uint64_t value = kDefaultCPURegisterCorruptionValue); 708 void CorruptAllCallerSavedCPURegisters(); 709#endif 710 711 // Pseudo Printf instruction 712 void DoPrintf(Instruction* instr); 713 714 // Processor state --------------------------------------- 715 716 // Output stream. 717 FILE* stream_; 718 PrintDisassembler* print_disasm_; 719 void PRINTF_METHOD_CHECKING TraceSim(const char* format, ...); 720 721 // Instrumentation. 722 Instrument* instrument_; 723 724 // General purpose registers. Register 31 is the stack pointer. 725 SimRegister registers_[kNumberOfRegisters]; 726 727 // Floating point registers 728 SimFPRegister fpregisters_[kNumberOfFPRegisters]; 729 730 // Processor state 731 // bits[31, 27]: Condition flags N, Z, C, and V. 732 // (Negative, Zero, Carry, Overflow) 733 SimSystemRegister nzcv_; 734 735 // Floating-Point Control Register 736 SimSystemRegister fpcr_; 737 738 // Only a subset of FPCR features are supported by the simulator. This helper 739 // checks that the FPCR settings are supported. 740 // 741 // This is checked when floating-point instructions are executed, not when 742 // FPCR is set. This allows generated code to modify FPCR for external 743 // functions, or to save and restore it when entering and leaving generated 744 // code. 745 void AssertSupportedFPCR() { 746 ASSERT(fpcr().FZ() == 0); // No flush-to-zero support. 747 ASSERT(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only. 748 749 // The simulator does not support half-precision operations so fpcr().AHP() 750 // is irrelevant, and is not checked here. 751 } 752 753 template <typename T> 754 static int CalcNFlag(T result) { 755 return (result >> (sizeof(T) * 8 - 1)) & 1; 756 } 757 758 static int CalcZFlag(uint64_t result) { 759 return result == 0; 760 } 761 762 static const uint32_t kConditionFlagsMask = 0xf0000000; 763 764 // Stack 765 byte* stack_; 766 static const intptr_t stack_protection_size_ = KB; 767 intptr_t stack_size_; 768 byte* stack_limit_; 769 770 Decoder<DispatchingDecoderVisitor>* decoder_; 771 Decoder<DispatchingDecoderVisitor>* disassembler_decoder_; 772 773 // Indicates if the pc has been modified by the instruction and should not be 774 // automatically incremented. 775 bool pc_modified_; 776 Instruction* pc_; 777 778 static const char* xreg_names[]; 779 static const char* wreg_names[]; 780 static const char* sreg_names[]; 781 static const char* dreg_names[]; 782 static const char* vreg_names[]; 783 784 // Debugger input. 785 void set_last_debugger_input(char* input) { 786 DeleteArray(last_debugger_input_); 787 last_debugger_input_ = input; 788 } 789 char* last_debugger_input() { return last_debugger_input_; } 790 char* last_debugger_input_; 791 792 private: 793 void Init(FILE* stream); 794 795 int log_parameters_; 796 Isolate* isolate_; 797}; 798 799 800// When running with the simulator transition into simulated execution at this 801// point. 802#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ 803 reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS( \ 804 FUNCTION_ADDR(entry), \ 805 p0, p1, p2, p3, p4)) 806 807#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ 808 Simulator::current(Isolate::Current())->CallRegExp( \ 809 entry, \ 810 p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8) 811 812 813// The simulator has its own stack. Thus it has a different stack limit from 814// the C-based native code. 815// See also 'class SimulatorStack' in arm/simulator-arm.h. 816class SimulatorStack : public v8::internal::AllStatic { 817 public: 818 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 819 uintptr_t c_limit) { 820 return Simulator::current(isolate)->StackLimit(); 821 } 822 823 static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 824 Simulator* sim = Simulator::current(Isolate::Current()); 825 return sim->PushAddress(try_catch_address); 826 } 827 828 static void UnregisterCTryCatch() { 829 Simulator::current(Isolate::Current())->PopAddress(); 830 } 831}; 832 833#endif // !defined(USE_SIMULATOR) 834 835} } // namespace v8::internal 836 837#endif // V8_ARM64_SIMULATOR_ARM64_H_ 838