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/allocation.h" 14 #include "src/arm64/assembler-arm64.h" 15 #include "src/arm64/decoder-arm64.h" 16 #include "src/arm64/disasm-arm64.h" 17 #include "src/arm64/instrument-arm64.h" 18 #include "src/assembler.h" 19 #include "src/globals.h" 20 #include "src/utils.h" 21 22 #define REGISTER_CODE_LIST(R) \ 23 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 24 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 25 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 26 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) 27 28 namespace v8 { 29 namespace 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 38 typedef 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. 58 class SimulatorStack : public v8::internal::AllStatic { 59 public: JsLimitFromCLimit(v8::internal::Isolate * isolate,uintptr_t c_limit)60 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 61 uintptr_t c_limit) { 62 USE(isolate); 63 return c_limit; 64 } 65 RegisterCTryCatch(uintptr_t try_catch_address)66 static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 67 return try_catch_address; 68 } 69 UnregisterCTryCatch()70 static void UnregisterCTryCatch() { } 71 }; 72 73 #else // !defined(USE_SIMULATOR) 74 75 enum 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); 85 class 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). 136 class 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 156 typedef SimRegisterBase SimRegister; // r0-r31 157 typedef SimRegisterBase SimFPRegister; // v0-v31 158 159 160 class 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 bits_ = 0; 215 DCHECK(sizeof(argument) <= sizeof(bits_)); 216 memcpy(&bits_, &argument, sizeof(argument)); 217 type_ = X_ARG; 218 } 219 220 explicit CallArgument(double argument) { 221 DCHECK(sizeof(argument) == sizeof(bits_)); 222 memcpy(&bits_, &argument, sizeof(argument)); 223 type_ = D_ARG; 224 } 225 226 explicit CallArgument(float argument) { 227 // TODO(all): CallArgument(float) is untested, remove this check once 228 // tested. 229 UNIMPLEMENTED(); 230 // Make the D register a NaN to try to trap errors if the callee expects a 231 // double. If it expects a float, the callee should ignore the top word. 232 DCHECK(sizeof(kFP64SignallingNaN) == sizeof(bits_)); 233 memcpy(&bits_, &kFP64SignallingNaN, sizeof(kFP64SignallingNaN)); 234 // Write the float payload to the S register. 235 DCHECK(sizeof(argument) <= sizeof(bits_)); 236 memcpy(&bits_, &argument, sizeof(argument)); 237 type_ = D_ARG; 238 } 239 240 // This indicates the end of the arguments list, so that CallArgument 241 // objects can be passed into varargs functions. 242 static CallArgument End() { return CallArgument(); } 243 244 int64_t bits() const { return bits_; } 245 bool IsEnd() const { return type_ == NO_ARG; } 246 bool IsX() const { return type_ == X_ARG; } 247 bool IsD() const { return type_ == D_ARG; } 248 249 private: 250 enum CallArgumentType { X_ARG, D_ARG, NO_ARG }; 251 252 // All arguments are aligned to at least 64 bits and we don't support 253 // passing bigger arguments, so the payload size can be fixed at 64 bits. 254 int64_t bits_; 255 CallArgumentType type_; 256 257 CallArgument() { type_ = NO_ARG; } 258 }; 259 260 261 // Start the debugging command line. 262 void Debug(); 263 264 bool GetValue(const char* desc, int64_t* value); 265 266 bool PrintValue(const char* desc); 267 268 // Push an address onto the JS stack. 269 uintptr_t PushAddress(uintptr_t address); 270 271 // Pop an address from the JS stack. 272 uintptr_t PopAddress(); 273 274 // Accessor to the internal simulator stack area. 275 uintptr_t StackLimit() const; 276 277 void ResetState(); 278 279 // Runtime call support. 280 static void* RedirectExternalReference(void* external_function, 281 ExternalReference::Type type); 282 void DoRuntimeCall(Instruction* instr); 283 284 // Run the simulator. 285 static const Instruction* kEndOfSimAddress; 286 void DecodeInstruction(); 287 void Run(); 288 void RunFrom(Instruction* start); 289 290 // Simulation helpers. 291 template <typename T> 292 void set_pc(T new_pc) { 293 DCHECK(sizeof(T) == sizeof(pc_)); 294 memcpy(&pc_, &new_pc, sizeof(T)); 295 pc_modified_ = true; 296 } 297 Instruction* pc() { return pc_; } 298 299 void increment_pc() { 300 if (!pc_modified_) { 301 pc_ = pc_->following(); 302 } 303 304 pc_modified_ = false; 305 } 306 307 virtual void Decode(Instruction* instr) { 308 decoder_->Decode(instr); 309 } 310 311 void ExecuteInstruction() { 312 DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize)); 313 CheckBreakNext(); 314 Decode(pc_); 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 DCHECK(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 'value' into an integer register. The value is zero-extended. This 351 // behaviour matches AArch64 register writes. 352 template<typename T> 353 void set_reg(unsigned code, T value, 354 Reg31Mode r31mode = Reg31IsZeroRegister) { 355 set_reg_no_log(code, value, r31mode); 356 LogRegister(code, r31mode); 357 } 358 359 // Common specialized accessors for the set_reg() template. 360 void set_wreg(unsigned code, int32_t value, 361 Reg31Mode r31mode = Reg31IsZeroRegister) { 362 set_reg(code, value, r31mode); 363 } 364 365 void set_xreg(unsigned code, int64_t value, 366 Reg31Mode r31mode = Reg31IsZeroRegister) { 367 set_reg(code, value, r31mode); 368 } 369 370 // As above, but don't automatically log the register update. 371 template <typename T> 372 void set_reg_no_log(unsigned code, T value, 373 Reg31Mode r31mode = Reg31IsZeroRegister) { 374 DCHECK(code < kNumberOfRegisters); 375 if (!IsZeroRegister(code, r31mode)) { 376 registers_[code].Set(value); 377 } 378 } 379 380 void set_wreg_no_log(unsigned code, int32_t value, 381 Reg31Mode r31mode = Reg31IsZeroRegister) { 382 set_reg_no_log(code, value, r31mode); 383 } 384 385 void set_xreg_no_log(unsigned code, int64_t value, 386 Reg31Mode r31mode = Reg31IsZeroRegister) { 387 set_reg_no_log(code, value, r31mode); 388 } 389 390 // Commonly-used special cases. 391 template<typename T> 392 void set_lr(T value) { 393 DCHECK(sizeof(T) == kPointerSize); 394 set_reg(kLinkRegCode, value); 395 } 396 397 template<typename T> 398 void set_sp(T value) { 399 DCHECK(sizeof(T) == kPointerSize); 400 set_reg(31, value, Reg31IsStackPointer); 401 } 402 403 int64_t sp() { return xreg(31, Reg31IsStackPointer); } 404 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); } 405 int64_t fp() { 406 return xreg(kFramePointerRegCode, Reg31IsStackPointer); 407 } 408 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); } 409 410 Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); } 411 412 template<typename T> 413 T fpreg(unsigned code) const { 414 DCHECK(code < kNumberOfRegisters); 415 return fpregisters_[code].Get<T>(); 416 } 417 418 // Common specialized accessors for the fpreg() template. 419 float sreg(unsigned code) const { 420 return fpreg<float>(code); 421 } 422 423 uint32_t sreg_bits(unsigned code) const { 424 return fpreg<uint32_t>(code); 425 } 426 427 double dreg(unsigned code) const { 428 return fpreg<double>(code); 429 } 430 431 uint64_t dreg_bits(unsigned code) const { 432 return fpreg<uint64_t>(code); 433 } 434 435 double fpreg(unsigned size, unsigned code) const { 436 switch (size) { 437 case kSRegSizeInBits: return sreg(code); 438 case kDRegSizeInBits: return dreg(code); 439 default: 440 UNREACHABLE(); 441 return 0.0; 442 } 443 } 444 445 // Write 'value' into a floating-point register. The value is zero-extended. 446 // This behaviour matches AArch64 register writes. 447 template<typename T> 448 void set_fpreg(unsigned code, T value) { 449 set_fpreg_no_log(code, value); 450 451 if (sizeof(value) <= kSRegSize) { 452 LogFPRegister(code, kPrintSRegValue); 453 } else { 454 LogFPRegister(code, kPrintDRegValue); 455 } 456 } 457 458 // Common specialized accessors for the set_fpreg() template. 459 void set_sreg(unsigned code, float value) { 460 set_fpreg(code, value); 461 } 462 463 void set_sreg_bits(unsigned code, uint32_t value) { 464 set_fpreg(code, value); 465 } 466 467 void set_dreg(unsigned code, double value) { 468 set_fpreg(code, value); 469 } 470 471 void set_dreg_bits(unsigned code, uint64_t value) { 472 set_fpreg(code, value); 473 } 474 475 // As above, but don't automatically log the register update. 476 template <typename T> 477 void set_fpreg_no_log(unsigned code, T value) { 478 DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); 479 DCHECK(code < kNumberOfFPRegisters); 480 fpregisters_[code].Set(value); 481 } 482 483 void set_sreg_no_log(unsigned code, float value) { 484 set_fpreg_no_log(code, value); 485 } 486 487 void set_dreg_no_log(unsigned code, double value) { 488 set_fpreg_no_log(code, value); 489 } 490 491 SimSystemRegister& nzcv() { return nzcv_; } 492 SimSystemRegister& fpcr() { return fpcr_; } 493 494 // Debug helpers 495 496 // Simulator breakpoints. 497 struct Breakpoint { 498 Instruction* location; 499 bool enabled; 500 }; 501 std::vector<Breakpoint> breakpoints_; 502 void SetBreakpoint(Instruction* breakpoint); 503 void ListBreakpoints(); 504 void CheckBreakpoints(); 505 506 // Helpers for the 'next' command. 507 // When this is set, the Simulator will insert a breakpoint after the next BL 508 // instruction it meets. 509 bool break_on_next_; 510 // Check if the Simulator should insert a break after the current instruction 511 // for the 'next' command. 512 void CheckBreakNext(); 513 514 // Disassemble instruction at the given address. 515 void PrintInstructionsAt(Instruction* pc, uint64_t count); 516 517 // Print all registers of the specified types. 518 void PrintRegisters(); 519 void PrintFPRegisters(); 520 void PrintSystemRegisters(); 521 522 // Like Print* (above), but respect log_parameters(). 523 void LogSystemRegisters() { 524 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters(); 525 } 526 void LogRegisters() { 527 if (log_parameters() & LOG_REGS) PrintRegisters(); 528 } 529 void LogFPRegisters() { 530 if (log_parameters() & LOG_FP_REGS) PrintFPRegisters(); 531 } 532 533 // Specify relevant register sizes, for PrintFPRegister. 534 // 535 // These values are bit masks; they can be combined in case multiple views of 536 // a machine register are interesting. 537 enum PrintFPRegisterSizes { 538 kPrintDRegValue = 1 << kDRegSize, 539 kPrintSRegValue = 1 << kSRegSize, 540 kPrintAllFPRegValues = kPrintDRegValue | kPrintSRegValue 541 }; 542 543 // Print individual register values (after update). 544 void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer); 545 void PrintFPRegister(unsigned code, 546 PrintFPRegisterSizes sizes = kPrintAllFPRegValues); 547 void PrintSystemRegister(SystemRegister id); 548 549 // Like Print* (above), but respect log_parameters(). 550 void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) { 551 if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode); 552 } 553 void LogFPRegister(unsigned code, 554 PrintFPRegisterSizes sizes = kPrintAllFPRegValues) { 555 if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes); 556 } 557 void LogSystemRegister(SystemRegister id) { 558 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id); 559 } 560 561 // Print memory accesses. 562 void PrintRead(uintptr_t address, size_t size, unsigned reg_code); 563 void PrintReadFP(uintptr_t address, size_t size, unsigned reg_code); 564 void PrintWrite(uintptr_t address, size_t size, unsigned reg_code); 565 void PrintWriteFP(uintptr_t address, size_t size, unsigned reg_code); 566 567 // Like Print* (above), but respect log_parameters(). 568 void LogRead(uintptr_t address, size_t size, unsigned reg_code) { 569 if (log_parameters() & LOG_REGS) PrintRead(address, size, reg_code); 570 } 571 void LogReadFP(uintptr_t address, size_t size, unsigned reg_code) { 572 if (log_parameters() & LOG_FP_REGS) PrintReadFP(address, size, reg_code); 573 } 574 void LogWrite(uintptr_t address, size_t size, unsigned reg_code) { 575 if (log_parameters() & LOG_WRITE) PrintWrite(address, size, reg_code); 576 } 577 void LogWriteFP(uintptr_t address, size_t size, unsigned reg_code) { 578 if (log_parameters() & LOG_WRITE) PrintWriteFP(address, size, reg_code); 579 } 580 581 int log_parameters() { return log_parameters_; } 582 void set_log_parameters(int new_parameters) { 583 log_parameters_ = new_parameters; 584 if (!decoder_) { 585 if (new_parameters & LOG_DISASM) { 586 PrintF("Run --debug-sim to dynamically turn on disassembler\n"); 587 } 588 return; 589 } 590 if (new_parameters & LOG_DISASM) { 591 decoder_->InsertVisitorBefore(print_disasm_, this); 592 } else { 593 decoder_->RemoveVisitor(print_disasm_); 594 } 595 } 596 597 static inline const char* WRegNameForCode(unsigned code, 598 Reg31Mode mode = Reg31IsZeroRegister); 599 static inline const char* XRegNameForCode(unsigned code, 600 Reg31Mode mode = Reg31IsZeroRegister); 601 static inline const char* SRegNameForCode(unsigned code); 602 static inline const char* DRegNameForCode(unsigned code); 603 static inline const char* VRegNameForCode(unsigned code); 604 static inline int CodeFromName(const char* name); 605 606 protected: 607 // Simulation helpers ------------------------------------ 608 bool ConditionPassed(Condition cond) { 609 SimSystemRegister& flags = nzcv(); 610 switch (cond) { 611 case eq: 612 return flags.Z(); 613 case ne: 614 return !flags.Z(); 615 case hs: 616 return flags.C(); 617 case lo: 618 return !flags.C(); 619 case mi: 620 return flags.N(); 621 case pl: 622 return !flags.N(); 623 case vs: 624 return flags.V(); 625 case vc: 626 return !flags.V(); 627 case hi: 628 return flags.C() && !flags.Z(); 629 case ls: 630 return !(flags.C() && !flags.Z()); 631 case ge: 632 return flags.N() == flags.V(); 633 case lt: 634 return flags.N() != flags.V(); 635 case gt: 636 return !flags.Z() && (flags.N() == flags.V()); 637 case le: 638 return !(!flags.Z() && (flags.N() == flags.V())); 639 case nv: // Fall through. 640 case al: 641 return true; 642 default: 643 UNREACHABLE(); 644 return false; 645 } 646 } 647 648 bool ConditionFailed(Condition cond) { 649 return !ConditionPassed(cond); 650 } 651 652 template<typename T> 653 void AddSubHelper(Instruction* instr, T op2); 654 template<typename T> 655 T AddWithCarry(bool set_flags, 656 T src1, 657 T src2, 658 T carry_in = 0); 659 template<typename T> 660 void AddSubWithCarry(Instruction* instr); 661 template<typename T> 662 void LogicalHelper(Instruction* instr, T op2); 663 template<typename T> 664 void ConditionalCompareHelper(Instruction* instr, T op2); 665 void LoadStoreHelper(Instruction* instr, 666 int64_t offset, 667 AddrMode addrmode); 668 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode); 669 uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset, 670 AddrMode addrmode); 671 void LoadStoreWriteBack(unsigned addr_reg, 672 int64_t offset, 673 AddrMode addrmode); 674 void CheckMemoryAccess(uintptr_t address, uintptr_t stack); 675 676 // Memory read helpers. 677 template <typename T, typename A> 678 T MemoryRead(A address) { 679 T value; 680 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 681 (sizeof(value) == 4) || (sizeof(value) == 8)); 682 memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value)); 683 return value; 684 } 685 686 // Memory write helpers. 687 template <typename T, typename A> 688 void MemoryWrite(A address, T value) { 689 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 690 (sizeof(value) == 4) || (sizeof(value) == 8)); 691 memcpy(reinterpret_cast<void*>(address), &value, sizeof(value)); 692 } 693 694 template <typename T> 695 T ShiftOperand(T value, 696 Shift shift_type, 697 unsigned amount); 698 template <typename T> 699 T ExtendValue(T value, 700 Extend extend_type, 701 unsigned left_shift = 0); 702 template <typename T> 703 void Extract(Instruction* instr); 704 template <typename T> 705 void DataProcessing2Source(Instruction* instr); 706 template <typename T> 707 void BitfieldHelper(Instruction* instr); 708 709 uint64_t ReverseBits(uint64_t value, unsigned num_bits); 710 uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode); 711 712 template <typename T> 713 T FPDefaultNaN() const; 714 715 void FPCompare(double val0, double val1); 716 double FPRoundInt(double value, FPRounding round_mode); 717 double FPToDouble(float value); 718 float FPToFloat(double value, FPRounding round_mode); 719 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode); 720 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode); 721 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode); 722 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode); 723 int32_t FPToInt32(double value, FPRounding rmode); 724 int64_t FPToInt64(double value, FPRounding rmode); 725 uint32_t FPToUInt32(double value, FPRounding rmode); 726 uint64_t FPToUInt64(double value, FPRounding rmode); 727 728 template <typename T> 729 T FPAdd(T op1, T op2); 730 731 template <typename T> 732 T FPDiv(T op1, T op2); 733 734 template <typename T> 735 T FPMax(T a, T b); 736 737 template <typename T> 738 T FPMaxNM(T a, T b); 739 740 template <typename T> 741 T FPMin(T a, T b); 742 743 template <typename T> 744 T FPMinNM(T a, T b); 745 746 template <typename T> 747 T FPMul(T op1, T op2); 748 749 template <typename T> 750 T FPMulAdd(T a, T op1, T op2); 751 752 template <typename T> 753 T FPSqrt(T op); 754 755 template <typename T> 756 T FPSub(T op1, T op2); 757 758 // Standard NaN processing. 759 template <typename T> 760 T FPProcessNaN(T op); 761 762 bool FPProcessNaNs(Instruction* instr); 763 764 template <typename T> 765 T FPProcessNaNs(T op1, T op2); 766 767 template <typename T> 768 T FPProcessNaNs3(T op1, T op2, T op3); 769 770 void CheckStackAlignment(); 771 772 inline void CheckPCSComplianceAndRun(); 773 774 #ifdef DEBUG 775 // Corruption values should have their least significant byte cleared to 776 // allow the code of the register being corrupted to be inserted. 777 static const uint64_t kCallerSavedRegisterCorruptionValue = 778 0xca11edc0de000000UL; 779 // This value is a NaN in both 32-bit and 64-bit FP. 780 static const uint64_t kCallerSavedFPRegisterCorruptionValue = 781 0x7ff000007f801000UL; 782 // This value is a mix of 32/64-bits NaN and "verbose" immediate. 783 static const uint64_t kDefaultCPURegisterCorruptionValue = 784 0x7ffbad007f8bad00UL; 785 786 void CorruptRegisters(CPURegList* list, 787 uint64_t value = kDefaultCPURegisterCorruptionValue); 788 void CorruptAllCallerSavedCPURegisters(); 789 #endif 790 791 // Pseudo Printf instruction 792 void DoPrintf(Instruction* instr); 793 794 // Processor state --------------------------------------- 795 796 // Output stream. 797 FILE* stream_; 798 PrintDisassembler* print_disasm_; 799 void PRINTF_METHOD_CHECKING TraceSim(const char* format, ...); 800 801 // Instrumentation. 802 Instrument* instrument_; 803 804 // General purpose registers. Register 31 is the stack pointer. 805 SimRegister registers_[kNumberOfRegisters]; 806 807 // Floating point registers 808 SimFPRegister fpregisters_[kNumberOfFPRegisters]; 809 810 // Processor state 811 // bits[31, 27]: Condition flags N, Z, C, and V. 812 // (Negative, Zero, Carry, Overflow) 813 SimSystemRegister nzcv_; 814 815 // Floating-Point Control Register 816 SimSystemRegister fpcr_; 817 818 // Only a subset of FPCR features are supported by the simulator. This helper 819 // checks that the FPCR settings are supported. 820 // 821 // This is checked when floating-point instructions are executed, not when 822 // FPCR is set. This allows generated code to modify FPCR for external 823 // functions, or to save and restore it when entering and leaving generated 824 // code. 825 void AssertSupportedFPCR() { 826 DCHECK(fpcr().FZ() == 0); // No flush-to-zero support. 827 DCHECK(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only. 828 829 // The simulator does not support half-precision operations so fpcr().AHP() 830 // is irrelevant, and is not checked here. 831 } 832 833 template <typename T> 834 static int CalcNFlag(T result) { 835 return (result >> (sizeof(T) * 8 - 1)) & 1; 836 } 837 838 static int CalcZFlag(uint64_t result) { 839 return result == 0; 840 } 841 842 static const uint32_t kConditionFlagsMask = 0xf0000000; 843 844 // Stack 845 uintptr_t stack_; 846 static const size_t stack_protection_size_ = KB; 847 size_t stack_size_; 848 uintptr_t stack_limit_; 849 850 Decoder<DispatchingDecoderVisitor>* decoder_; 851 Decoder<DispatchingDecoderVisitor>* disassembler_decoder_; 852 853 // Indicates if the pc has been modified by the instruction and should not be 854 // automatically incremented. 855 bool pc_modified_; 856 Instruction* pc_; 857 858 static const char* xreg_names[]; 859 static const char* wreg_names[]; 860 static const char* sreg_names[]; 861 static const char* dreg_names[]; 862 static const char* vreg_names[]; 863 864 // Debugger input. 865 void set_last_debugger_input(char* input) { 866 DeleteArray(last_debugger_input_); 867 last_debugger_input_ = input; 868 } 869 char* last_debugger_input() { return last_debugger_input_; } 870 char* last_debugger_input_; 871 872 private: 873 void Init(FILE* stream); 874 875 int log_parameters_; 876 Isolate* isolate_; 877 }; 878 879 880 // When running with the simulator transition into simulated execution at this 881 // point. 882 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ 883 reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->CallJS( \ 884 FUNCTION_ADDR(entry), \ 885 p0, p1, p2, p3, p4)) 886 887 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ 888 Simulator::current(Isolate::Current())->CallRegExp( \ 889 entry, \ 890 p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8) 891 892 893 // The simulator has its own stack. Thus it has a different stack limit from 894 // the C-based native code. 895 // See also 'class SimulatorStack' in arm/simulator-arm.h. 896 class SimulatorStack : public v8::internal::AllStatic { 897 public: 898 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 899 uintptr_t c_limit) { 900 return Simulator::current(isolate)->StackLimit(); 901 } 902 903 static uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) { 904 Simulator* sim = Simulator::current(Isolate::Current()); 905 return sim->PushAddress(try_catch_address); 906 } 907 908 static void UnregisterCTryCatch() { 909 Simulator::current(Isolate::Current())->PopAddress(); 910 } 911 }; 912 913 #endif // !defined(USE_SIMULATOR) 914 915 } } // namespace v8::internal 916 917 #endif // V8_ARM64_SIMULATOR_ARM64_H_ 918