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/allocation.h" 12 #include "src/arm64/assembler-arm64.h" 13 #include "src/arm64/decoder-arm64.h" 14 #include "src/arm64/disasm-arm64.h" 15 #include "src/arm64/instrument-arm64.h" 16 #include "src/assembler.h" 17 #include "src/globals.h" 18 #include "src/utils.h" 19 20 namespace v8 { 21 namespace internal { 22 23 #if !defined(USE_SIMULATOR) 24 25 // Running without a simulator on a native ARM64 platform. 26 // When running without a simulator we call the entry directly. 27 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 28 (entry(p0, p1, p2, p3, p4)) 29 30 typedef int (*arm64_regexp_matcher)(String* input, 31 int64_t start_offset, 32 const byte* input_start, 33 const byte* input_end, 34 int* output, 35 int64_t output_size, 36 Address stack_base, 37 int64_t direct_call, 38 void* return_address, 39 Isolate* isolate); 40 41 // Call the generated regexp code directly. The code at the entry address 42 // should act as a function matching the type arm64_regexp_matcher. 43 // The ninth argument is a dummy that reserves the space used for 44 // the return address added by the ExitFrame in native calls. 45 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 46 p7, p8) \ 47 (FUNCTION_CAST<arm64_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, \ 48 NULL, p8)) 49 50 // Running without a simulator there is nothing to do. 51 class SimulatorStack : public v8::internal::AllStatic { 52 public: 53 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 54 uintptr_t c_limit) { 55 USE(isolate); 56 return c_limit; 57 } 58 59 static uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, 60 uintptr_t try_catch_address) { 61 USE(isolate); 62 return try_catch_address; 63 } 64 65 static void UnregisterCTryCatch(v8::internal::Isolate* isolate) { 66 USE(isolate); 67 } 68 }; 69 70 #else // !defined(USE_SIMULATOR) 71 72 73 // The proper way to initialize a simulated system register (such as NZCV) is as 74 // follows: 75 // SimSystemRegister nzcv = SimSystemRegister::DefaultValueFor(NZCV); 76 class SimSystemRegister { 77 public: 78 // The default constructor represents a register which has no writable bits. 79 // It is not possible to set its value to anything other than 0. 80 SimSystemRegister() : value_(0), write_ignore_mask_(0xffffffff) { } 81 82 uint32_t RawValue() const { 83 return value_; 84 } 85 86 void SetRawValue(uint32_t new_value) { 87 value_ = (value_ & write_ignore_mask_) | (new_value & ~write_ignore_mask_); 88 } 89 90 uint32_t Bits(int msb, int lsb) const { 91 return unsigned_bitextract_32(msb, lsb, value_); 92 } 93 94 int32_t SignedBits(int msb, int lsb) const { 95 return signed_bitextract_32(msb, lsb, value_); 96 } 97 98 void SetBits(int msb, int lsb, uint32_t bits); 99 100 // Default system register values. 101 static SimSystemRegister DefaultValueFor(SystemRegister id); 102 103 #define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type) \ 104 Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); } \ 105 void Set##Name(Type bits) { \ 106 SetBits(HighBit, LowBit, static_cast<Type>(bits)); \ 107 } 108 #define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \ 109 static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask); 110 SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK) 111 #undef DEFINE_ZERO_BITS 112 #undef DEFINE_GETTER 113 114 protected: 115 // Most system registers only implement a few of the bits in the word. Other 116 // bits are "read-as-zero, write-ignored". The write_ignore_mask argument 117 // describes the bits which are not modifiable. 118 SimSystemRegister(uint32_t value, uint32_t write_ignore_mask) 119 : value_(value), write_ignore_mask_(write_ignore_mask) { } 120 121 uint32_t value_; 122 uint32_t write_ignore_mask_; 123 }; 124 125 126 // Represent a register (r0-r31, v0-v31). 127 class SimRegisterBase { 128 public: 129 template<typename T> 130 void Set(T new_value) { 131 value_ = 0; 132 memcpy(&value_, &new_value, sizeof(T)); 133 } 134 135 template<typename T> 136 T Get() const { 137 T result; 138 memcpy(&result, &value_, sizeof(T)); 139 return result; 140 } 141 142 protected: 143 int64_t value_; 144 }; 145 146 147 typedef SimRegisterBase SimRegister; // r0-r31 148 typedef SimRegisterBase SimFPRegister; // v0-v31 149 150 151 class Simulator : public DecoderVisitor { 152 public: 153 static void FlushICache(v8::internal::HashMap* i_cache, void* start, 154 size_t size) { 155 USE(i_cache); 156 USE(start); 157 USE(size); 158 } 159 160 explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder, 161 Isolate* isolate = NULL, 162 FILE* stream = stderr); 163 Simulator(); 164 ~Simulator(); 165 166 // System functions. 167 168 static void Initialize(Isolate* isolate); 169 170 static void TearDown(HashMap* i_cache, Redirection* first); 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 Object* new_target, 190 Object* target, 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(uintptr_t c_limit) const; 276 277 void ResetState(); 278 279 // Runtime call support. 280 static void* RedirectExternalReference(Isolate* isolate, 281 void* external_function, 282 ExternalReference::Type type); 283 void DoRuntimeCall(Instruction* instr); 284 285 // Run the simulator. 286 static const Instruction* kEndOfSimAddress; 287 void DecodeInstruction(); 288 void Run(); 289 void RunFrom(Instruction* start); 290 291 // Simulation helpers. 292 template <typename T> 293 void set_pc(T new_pc) { 294 DCHECK(sizeof(T) == sizeof(pc_)); 295 memcpy(&pc_, &new_pc, sizeof(T)); 296 pc_modified_ = true; 297 } 298 Instruction* pc() { return pc_; } 299 300 void increment_pc() { 301 if (!pc_modified_) { 302 pc_ = pc_->following(); 303 } 304 305 pc_modified_ = false; 306 } 307 308 virtual void Decode(Instruction* instr) { 309 decoder_->Decode(instr); 310 } 311 312 void ExecuteInstruction() { 313 DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize)); 314 CheckBreakNext(); 315 Decode(pc_); 316 increment_pc(); 317 CheckBreakpoints(); 318 } 319 320 // Declare all Visitor functions. 321 #define DECLARE(A) void Visit##A(Instruction* instr); 322 VISITOR_LIST(DECLARE) 323 #undef DECLARE 324 325 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const { 326 return ((code == 31) && (r31mode == Reg31IsZeroRegister)); 327 } 328 329 // Register accessors. 330 // Return 'size' bits of the value of an integer register, as the specified 331 // type. The value is zero-extended to fill the result. 332 // 333 template<typename T> 334 T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { 335 DCHECK(code < kNumberOfRegisters); 336 if (IsZeroRegister(code, r31mode)) { 337 return 0; 338 } 339 return registers_[code].Get<T>(); 340 } 341 342 // Common specialized accessors for the reg() template. 343 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { 344 return reg<int32_t>(code, r31mode); 345 } 346 347 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { 348 return reg<int64_t>(code, r31mode); 349 } 350 351 // Write 'value' into an integer register. The value is zero-extended. This 352 // behaviour matches AArch64 register writes. 353 template<typename T> 354 void set_reg(unsigned code, T value, 355 Reg31Mode r31mode = Reg31IsZeroRegister) { 356 set_reg_no_log(code, value, r31mode); 357 LogRegister(code, r31mode); 358 } 359 360 // Common specialized accessors for the set_reg() template. 361 void set_wreg(unsigned code, int32_t value, 362 Reg31Mode r31mode = Reg31IsZeroRegister) { 363 set_reg(code, value, r31mode); 364 } 365 366 void set_xreg(unsigned code, int64_t value, 367 Reg31Mode r31mode = Reg31IsZeroRegister) { 368 set_reg(code, value, r31mode); 369 } 370 371 // As above, but don't automatically log the register update. 372 template <typename T> 373 void set_reg_no_log(unsigned code, T value, 374 Reg31Mode r31mode = Reg31IsZeroRegister) { 375 DCHECK(code < kNumberOfRegisters); 376 if (!IsZeroRegister(code, r31mode)) { 377 registers_[code].Set(value); 378 } 379 } 380 381 void set_wreg_no_log(unsigned code, int32_t value, 382 Reg31Mode r31mode = Reg31IsZeroRegister) { 383 set_reg_no_log(code, value, r31mode); 384 } 385 386 void set_xreg_no_log(unsigned code, int64_t value, 387 Reg31Mode r31mode = Reg31IsZeroRegister) { 388 set_reg_no_log(code, value, r31mode); 389 } 390 391 // Commonly-used special cases. 392 template<typename T> 393 void set_lr(T value) { 394 DCHECK(sizeof(T) == kPointerSize); 395 set_reg(kLinkRegCode, value); 396 } 397 398 template<typename T> 399 void set_sp(T value) { 400 DCHECK(sizeof(T) == kPointerSize); 401 set_reg(31, value, Reg31IsStackPointer); 402 } 403 404 int64_t sp() { return xreg(31, Reg31IsStackPointer); } 405 int64_t jssp() { return xreg(kJSSPCode, Reg31IsStackPointer); } 406 int64_t fp() { 407 return xreg(kFramePointerRegCode, Reg31IsStackPointer); 408 } 409 Instruction* lr() { return reg<Instruction*>(kLinkRegCode); } 410 411 Address get_sp() const { return reg<Address>(31, Reg31IsStackPointer); } 412 413 template<typename T> 414 T fpreg(unsigned code) const { 415 DCHECK(code < kNumberOfRegisters); 416 return fpregisters_[code].Get<T>(); 417 } 418 419 // Common specialized accessors for the fpreg() template. 420 float sreg(unsigned code) const { 421 return fpreg<float>(code); 422 } 423 424 uint32_t sreg_bits(unsigned code) const { 425 return fpreg<uint32_t>(code); 426 } 427 428 double dreg(unsigned code) const { 429 return fpreg<double>(code); 430 } 431 432 uint64_t dreg_bits(unsigned code) const { 433 return fpreg<uint64_t>(code); 434 } 435 436 double fpreg(unsigned size, unsigned code) const { 437 switch (size) { 438 case kSRegSizeInBits: return sreg(code); 439 case kDRegSizeInBits: return dreg(code); 440 default: 441 UNREACHABLE(); 442 return 0.0; 443 } 444 } 445 446 // Write 'value' into a floating-point register. The value is zero-extended. 447 // This behaviour matches AArch64 register writes. 448 template<typename T> 449 void set_fpreg(unsigned code, T value) { 450 set_fpreg_no_log(code, value); 451 452 if (sizeof(value) <= kSRegSize) { 453 LogFPRegister(code, kPrintSRegValue); 454 } else { 455 LogFPRegister(code, kPrintDRegValue); 456 } 457 } 458 459 // Common specialized accessors for the set_fpreg() template. 460 void set_sreg(unsigned code, float value) { 461 set_fpreg(code, value); 462 } 463 464 void set_sreg_bits(unsigned code, uint32_t value) { 465 set_fpreg(code, value); 466 } 467 468 void set_dreg(unsigned code, double value) { 469 set_fpreg(code, value); 470 } 471 472 void set_dreg_bits(unsigned code, uint64_t value) { 473 set_fpreg(code, value); 474 } 475 476 // As above, but don't automatically log the register update. 477 template <typename T> 478 void set_fpreg_no_log(unsigned code, T value) { 479 DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); 480 DCHECK(code < kNumberOfFPRegisters); 481 fpregisters_[code].Set(value); 482 } 483 484 void set_sreg_no_log(unsigned code, float value) { 485 set_fpreg_no_log(code, value); 486 } 487 488 void set_dreg_no_log(unsigned code, double value) { 489 set_fpreg_no_log(code, value); 490 } 491 492 SimSystemRegister& nzcv() { return nzcv_; } 493 SimSystemRegister& fpcr() { return fpcr_; } 494 495 // Debug helpers 496 497 // Simulator breakpoints. 498 struct Breakpoint { 499 Instruction* location; 500 bool enabled; 501 }; 502 std::vector<Breakpoint> breakpoints_; 503 void SetBreakpoint(Instruction* breakpoint); 504 void ListBreakpoints(); 505 void CheckBreakpoints(); 506 507 // Helpers for the 'next' command. 508 // When this is set, the Simulator will insert a breakpoint after the next BL 509 // instruction it meets. 510 bool break_on_next_; 511 // Check if the Simulator should insert a break after the current instruction 512 // for the 'next' command. 513 void CheckBreakNext(); 514 515 // Disassemble instruction at the given address. 516 void PrintInstructionsAt(Instruction* pc, uint64_t count); 517 518 // Print all registers of the specified types. 519 void PrintRegisters(); 520 void PrintFPRegisters(); 521 void PrintSystemRegisters(); 522 523 // Like Print* (above), but respect log_parameters(). 524 void LogSystemRegisters() { 525 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters(); 526 } 527 void LogRegisters() { 528 if (log_parameters() & LOG_REGS) PrintRegisters(); 529 } 530 void LogFPRegisters() { 531 if (log_parameters() & LOG_FP_REGS) PrintFPRegisters(); 532 } 533 534 // Specify relevant register sizes, for PrintFPRegister. 535 // 536 // These values are bit masks; they can be combined in case multiple views of 537 // a machine register are interesting. 538 enum PrintFPRegisterSizes { 539 kPrintDRegValue = 1 << kDRegSize, 540 kPrintSRegValue = 1 << kSRegSize, 541 kPrintAllFPRegValues = kPrintDRegValue | kPrintSRegValue 542 }; 543 544 // Print individual register values (after update). 545 void PrintRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer); 546 void PrintFPRegister(unsigned code, 547 PrintFPRegisterSizes sizes = kPrintAllFPRegValues); 548 void PrintSystemRegister(SystemRegister id); 549 550 // Like Print* (above), but respect log_parameters(). 551 void LogRegister(unsigned code, Reg31Mode r31mode = Reg31IsStackPointer) { 552 if (log_parameters() & LOG_REGS) PrintRegister(code, r31mode); 553 } 554 void LogFPRegister(unsigned code, 555 PrintFPRegisterSizes sizes = kPrintAllFPRegValues) { 556 if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes); 557 } 558 void LogSystemRegister(SystemRegister id) { 559 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id); 560 } 561 562 // Print memory accesses. 563 void PrintRead(uintptr_t address, size_t size, unsigned reg_code); 564 void PrintReadFP(uintptr_t address, size_t size, unsigned reg_code); 565 void PrintWrite(uintptr_t address, size_t size, unsigned reg_code); 566 void PrintWriteFP(uintptr_t address, size_t size, unsigned reg_code); 567 568 // Like Print* (above), but respect log_parameters(). 569 void LogRead(uintptr_t address, size_t size, unsigned reg_code) { 570 if (log_parameters() & LOG_REGS) PrintRead(address, size, reg_code); 571 } 572 void LogReadFP(uintptr_t address, size_t size, unsigned reg_code) { 573 if (log_parameters() & LOG_FP_REGS) PrintReadFP(address, size, reg_code); 574 } 575 void LogWrite(uintptr_t address, size_t size, unsigned reg_code) { 576 if (log_parameters() & LOG_WRITE) PrintWrite(address, size, reg_code); 577 } 578 void LogWriteFP(uintptr_t address, size_t size, unsigned reg_code) { 579 if (log_parameters() & LOG_WRITE) PrintWriteFP(address, size, reg_code); 580 } 581 582 int log_parameters() { return log_parameters_; } 583 void set_log_parameters(int new_parameters) { 584 log_parameters_ = new_parameters; 585 if (!decoder_) { 586 if (new_parameters & LOG_DISASM) { 587 PrintF("Run --debug-sim to dynamically turn on disassembler\n"); 588 } 589 return; 590 } 591 if (new_parameters & LOG_DISASM) { 592 decoder_->InsertVisitorBefore(print_disasm_, this); 593 } else { 594 decoder_->RemoveVisitor(print_disasm_); 595 } 596 } 597 598 static inline const char* WRegNameForCode(unsigned code, 599 Reg31Mode mode = Reg31IsZeroRegister); 600 static inline const char* XRegNameForCode(unsigned code, 601 Reg31Mode mode = Reg31IsZeroRegister); 602 static inline const char* SRegNameForCode(unsigned code); 603 static inline const char* DRegNameForCode(unsigned code); 604 static inline const char* VRegNameForCode(unsigned code); 605 static inline int CodeFromName(const char* name); 606 607 protected: 608 // Simulation helpers ------------------------------------ 609 bool ConditionPassed(Condition cond) { 610 SimSystemRegister& flags = nzcv(); 611 switch (cond) { 612 case eq: 613 return flags.Z(); 614 case ne: 615 return !flags.Z(); 616 case hs: 617 return flags.C(); 618 case lo: 619 return !flags.C(); 620 case mi: 621 return flags.N(); 622 case pl: 623 return !flags.N(); 624 case vs: 625 return flags.V(); 626 case vc: 627 return !flags.V(); 628 case hi: 629 return flags.C() && !flags.Z(); 630 case ls: 631 return !(flags.C() && !flags.Z()); 632 case ge: 633 return flags.N() == flags.V(); 634 case lt: 635 return flags.N() != flags.V(); 636 case gt: 637 return !flags.Z() && (flags.N() == flags.V()); 638 case le: 639 return !(!flags.Z() && (flags.N() == flags.V())); 640 case nv: // Fall through. 641 case al: 642 return true; 643 default: 644 UNREACHABLE(); 645 return false; 646 } 647 } 648 649 bool ConditionFailed(Condition cond) { 650 return !ConditionPassed(cond); 651 } 652 653 template<typename T> 654 void AddSubHelper(Instruction* instr, T op2); 655 template<typename T> 656 T AddWithCarry(bool set_flags, 657 T src1, 658 T src2, 659 T carry_in = 0); 660 template<typename T> 661 void AddSubWithCarry(Instruction* instr); 662 template<typename T> 663 void LogicalHelper(Instruction* instr, T op2); 664 template<typename T> 665 void ConditionalCompareHelper(Instruction* instr, T op2); 666 void LoadStoreHelper(Instruction* instr, 667 int64_t offset, 668 AddrMode addrmode); 669 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode); 670 uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset, 671 AddrMode addrmode); 672 void LoadStoreWriteBack(unsigned addr_reg, 673 int64_t offset, 674 AddrMode addrmode); 675 void CheckMemoryAccess(uintptr_t address, uintptr_t stack); 676 677 // Memory read helpers. 678 template <typename T, typename A> 679 T MemoryRead(A address) { 680 T value; 681 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 682 (sizeof(value) == 4) || (sizeof(value) == 8)); 683 memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value)); 684 return value; 685 } 686 687 // Memory write helpers. 688 template <typename T, typename A> 689 void MemoryWrite(A address, T value) { 690 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 691 (sizeof(value) == 4) || (sizeof(value) == 8)); 692 memcpy(reinterpret_cast<void*>(address), &value, sizeof(value)); 693 } 694 695 template <typename T> 696 T ShiftOperand(T value, 697 Shift shift_type, 698 unsigned amount); 699 template <typename T> 700 T ExtendValue(T value, 701 Extend extend_type, 702 unsigned left_shift = 0); 703 template <typename T> 704 void Extract(Instruction* instr); 705 template <typename T> 706 void DataProcessing2Source(Instruction* instr); 707 template <typename T> 708 void BitfieldHelper(Instruction* instr); 709 710 template <typename T> 711 T FPDefaultNaN() const; 712 713 void FPCompare(double val0, double val1); 714 double FPRoundInt(double value, FPRounding round_mode); 715 double FPToDouble(float value); 716 float FPToFloat(double value, FPRounding round_mode); 717 double FixedToDouble(int64_t src, int fbits, FPRounding round_mode); 718 double UFixedToDouble(uint64_t src, int fbits, FPRounding round_mode); 719 float FixedToFloat(int64_t src, int fbits, FPRounding round_mode); 720 float UFixedToFloat(uint64_t src, int fbits, FPRounding round_mode); 721 int32_t FPToInt32(double value, FPRounding rmode); 722 int64_t FPToInt64(double value, FPRounding rmode); 723 uint32_t FPToUInt32(double value, FPRounding rmode); 724 uint64_t FPToUInt64(double value, FPRounding rmode); 725 726 template <typename T> 727 T FPAdd(T op1, T op2); 728 729 template <typename T> 730 T FPDiv(T op1, T op2); 731 732 template <typename T> 733 T FPMax(T a, T b); 734 735 template <typename T> 736 T FPMaxNM(T a, T b); 737 738 template <typename T> 739 T FPMin(T a, T b); 740 741 template <typename T> 742 T FPMinNM(T a, T b); 743 744 template <typename T> 745 T FPMul(T op1, T op2); 746 747 template <typename T> 748 T FPMulAdd(T a, T op1, T op2); 749 750 template <typename T> 751 T FPSqrt(T op); 752 753 template <typename T> 754 T FPSub(T op1, T op2); 755 756 // Standard NaN processing. 757 template <typename T> 758 T FPProcessNaN(T op); 759 760 bool FPProcessNaNs(Instruction* instr); 761 762 template <typename T> 763 T FPProcessNaNs(T op1, T op2); 764 765 template <typename T> 766 T FPProcessNaNs3(T op1, T op2, T op3); 767 768 void CheckStackAlignment(); 769 770 inline void CheckPCSComplianceAndRun(); 771 772 #ifdef DEBUG 773 // Corruption values should have their least significant byte cleared to 774 // allow the code of the register being corrupted to be inserted. 775 static const uint64_t kCallerSavedRegisterCorruptionValue = 776 0xca11edc0de000000UL; 777 // This value is a NaN in both 32-bit and 64-bit FP. 778 static const uint64_t kCallerSavedFPRegisterCorruptionValue = 779 0x7ff000007f801000UL; 780 // This value is a mix of 32/64-bits NaN and "verbose" immediate. 781 static const uint64_t kDefaultCPURegisterCorruptionValue = 782 0x7ffbad007f8bad00UL; 783 784 void CorruptRegisters(CPURegList* list, 785 uint64_t value = kDefaultCPURegisterCorruptionValue); 786 void CorruptAllCallerSavedCPURegisters(); 787 #endif 788 789 // Pseudo Printf instruction 790 void DoPrintf(Instruction* instr); 791 792 // Processor state --------------------------------------- 793 794 // Output stream. 795 FILE* stream_; 796 PrintDisassembler* print_disasm_; 797 void PRINTF_METHOD_CHECKING TraceSim(const char* format, ...); 798 799 // Instrumentation. 800 Instrument* instrument_; 801 802 // General purpose registers. Register 31 is the stack pointer. 803 SimRegister registers_[kNumberOfRegisters]; 804 805 // Floating point registers 806 SimFPRegister fpregisters_[kNumberOfFPRegisters]; 807 808 // Processor state 809 // bits[31, 27]: Condition flags N, Z, C, and V. 810 // (Negative, Zero, Carry, Overflow) 811 SimSystemRegister nzcv_; 812 813 // Floating-Point Control Register 814 SimSystemRegister fpcr_; 815 816 // Only a subset of FPCR features are supported by the simulator. This helper 817 // checks that the FPCR settings are supported. 818 // 819 // This is checked when floating-point instructions are executed, not when 820 // FPCR is set. This allows generated code to modify FPCR for external 821 // functions, or to save and restore it when entering and leaving generated 822 // code. 823 void AssertSupportedFPCR() { 824 DCHECK(fpcr().FZ() == 0); // No flush-to-zero support. 825 DCHECK(fpcr().RMode() == FPTieEven); // Ties-to-even rounding only. 826 827 // The simulator does not support half-precision operations so fpcr().AHP() 828 // is irrelevant, and is not checked here. 829 } 830 831 template <typename T> 832 static int CalcNFlag(T result) { 833 return (result >> (sizeof(T) * 8 - 1)) & 1; 834 } 835 836 static int CalcZFlag(uint64_t result) { 837 return result == 0; 838 } 839 840 static const uint32_t kConditionFlagsMask = 0xf0000000; 841 842 // Stack 843 uintptr_t stack_; 844 static const size_t stack_protection_size_ = KB; 845 size_t stack_size_; 846 uintptr_t stack_limit_; 847 848 Decoder<DispatchingDecoderVisitor>* decoder_; 849 Decoder<DispatchingDecoderVisitor>* disassembler_decoder_; 850 851 // Indicates if the pc has been modified by the instruction and should not be 852 // automatically incremented. 853 bool pc_modified_; 854 Instruction* pc_; 855 856 static const char* xreg_names[]; 857 static const char* wreg_names[]; 858 static const char* sreg_names[]; 859 static const char* dreg_names[]; 860 static const char* vreg_names[]; 861 862 // Debugger input. 863 void set_last_debugger_input(char* input) { 864 DeleteArray(last_debugger_input_); 865 last_debugger_input_ = input; 866 } 867 char* last_debugger_input() { return last_debugger_input_; } 868 char* last_debugger_input_; 869 870 private: 871 void Init(FILE* stream); 872 873 int log_parameters_; 874 Isolate* isolate_; 875 }; 876 877 878 // When running with the simulator transition into simulated execution at this 879 // point. 880 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ 881 reinterpret_cast<Object*>(Simulator::current(isolate)->CallJS( \ 882 FUNCTION_ADDR(entry), p0, p1, p2, p3, p4)) 883 884 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \ 885 p7, p8) \ 886 static_cast<int>(Simulator::current(isolate)->CallRegExp( \ 887 entry, p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)) 888 889 890 // The simulator has its own stack. Thus it has a different stack limit from 891 // the C-based native code. The JS-based limit normally points near the end of 892 // the simulator stack. When the C-based limit is exhausted we reflect that by 893 // lowering the JS-based limit as well, to make stack checks trigger. 894 class SimulatorStack : public v8::internal::AllStatic { 895 public: 896 static uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate, 897 uintptr_t c_limit) { 898 return Simulator::current(isolate)->StackLimit(c_limit); 899 } 900 901 static uintptr_t RegisterCTryCatch(v8::internal::Isolate* isolate, 902 uintptr_t try_catch_address) { 903 Simulator* sim = Simulator::current(isolate); 904 return sim->PushAddress(try_catch_address); 905 } 906 907 static void UnregisterCTryCatch(v8::internal::Isolate* isolate) { 908 Simulator::current(isolate)->PopAddress(); 909 } 910 }; 911 912 #endif // !defined(USE_SIMULATOR) 913 914 } // namespace internal 915 } // namespace v8 916 917 #endif // V8_ARM64_SIMULATOR_ARM64_H_ 918