| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_ARM64_SIMULATOR_ARM64_H_ | 5 #ifndef V8_ARM64_SIMULATOR_ARM64_H_ |
| 6 #define V8_ARM64_SIMULATOR_ARM64_H_ | 6 #define V8_ARM64_SIMULATOR_ARM64_H_ |
| 7 | 7 |
| 8 #include <stdarg.h> | 8 #include <stdarg.h> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 } | 305 } |
| 306 | 306 |
| 307 virtual void Decode(Instruction* instr) { | 307 virtual void Decode(Instruction* instr) { |
| 308 decoder_->Decode(instr); | 308 decoder_->Decode(instr); |
| 309 } | 309 } |
| 310 | 310 |
| 311 void ExecuteInstruction() { | 311 void ExecuteInstruction() { |
| 312 DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize)); | 312 DCHECK(IsAligned(reinterpret_cast<uintptr_t>(pc_), kInstructionSize)); |
| 313 CheckBreakNext(); | 313 CheckBreakNext(); |
| 314 Decode(pc_); | 314 Decode(pc_); |
| 315 LogProcessorState(); |
| 315 increment_pc(); | 316 increment_pc(); |
| 316 CheckBreakpoints(); | 317 CheckBreakpoints(); |
| 317 } | 318 } |
| 318 | 319 |
| 319 // Declare all Visitor functions. | 320 // Declare all Visitor functions. |
| 320 #define DECLARE(A) void Visit##A(Instruction* instr); | 321 #define DECLARE(A) void Visit##A(Instruction* instr); |
| 321 VISITOR_LIST(DECLARE) | 322 VISITOR_LIST(DECLARE) |
| 322 #undef DECLARE | 323 #undef DECLARE |
| 323 | 324 |
| 324 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const { | 325 bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 340 | 341 |
| 341 // Common specialized accessors for the reg() template. | 342 // Common specialized accessors for the reg() template. |
| 342 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 343 int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { |
| 343 return reg<int32_t>(code, r31mode); | 344 return reg<int32_t>(code, r31mode); |
| 344 } | 345 } |
| 345 | 346 |
| 346 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { | 347 int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const { |
| 347 return reg<int64_t>(code, r31mode); | 348 return reg<int64_t>(code, r31mode); |
| 348 } | 349 } |
| 349 | 350 |
| 350 // Write 'value' into an integer register. The value is zero-extended. This | 351 // Write 'size' bits of 'value' into an integer register. The value is |
| 351 // behaviour matches AArch64 register writes. | 352 // zero-extended. This behaviour matches AArch64 register writes. |
| 353 |
| 354 // Like set_reg(), but infer the access size from the template type. |
| 352 template<typename T> | 355 template<typename T> |
| 353 void set_reg(unsigned code, T value, | 356 void set_reg(unsigned code, T value, |
| 354 Reg31Mode r31mode = Reg31IsZeroRegister) { | 357 Reg31Mode r31mode = Reg31IsZeroRegister) { |
| 355 set_reg_no_log(code, value, r31mode); | 358 DCHECK(code < kNumberOfRegisters); |
| 356 LogRegister(code, r31mode); | 359 if (!IsZeroRegister(code, r31mode)) |
| 360 registers_[code].Set(value); |
| 357 } | 361 } |
| 358 | 362 |
| 359 // Common specialized accessors for the set_reg() template. | 363 // Common specialized accessors for the set_reg() template. |
| 360 void set_wreg(unsigned code, int32_t value, | 364 void set_wreg(unsigned code, int32_t value, |
| 361 Reg31Mode r31mode = Reg31IsZeroRegister) { | 365 Reg31Mode r31mode = Reg31IsZeroRegister) { |
| 362 set_reg(code, value, r31mode); | 366 set_reg(code, value, r31mode); |
| 363 } | 367 } |
| 364 | 368 |
| 365 void set_xreg(unsigned code, int64_t value, | 369 void set_xreg(unsigned code, int64_t value, |
| 366 Reg31Mode r31mode = Reg31IsZeroRegister) { | 370 Reg31Mode r31mode = Reg31IsZeroRegister) { |
| 367 set_reg(code, value, r31mode); | 371 set_reg(code, value, r31mode); |
| 368 } | 372 } |
| 369 | 373 |
| 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. | 374 // Commonly-used special cases. |
| 391 template<typename T> | 375 template<typename T> |
| 392 void set_lr(T value) { | 376 void set_lr(T value) { |
| 393 DCHECK(sizeof(T) == kPointerSize); | 377 DCHECK(sizeof(T) == kPointerSize); |
| 394 set_reg(kLinkRegCode, value); | 378 set_reg(kLinkRegCode, value); |
| 395 } | 379 } |
| 396 | 380 |
| 397 template<typename T> | 381 template<typename T> |
| 398 void set_sp(T value) { | 382 void set_sp(T value) { |
| 399 DCHECK(sizeof(T) == kPointerSize); | 383 DCHECK(sizeof(T) == kPointerSize); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 default: | 423 default: |
| 440 UNREACHABLE(); | 424 UNREACHABLE(); |
| 441 return 0.0; | 425 return 0.0; |
| 442 } | 426 } |
| 443 } | 427 } |
| 444 | 428 |
| 445 // Write 'value' into a floating-point register. The value is zero-extended. | 429 // Write 'value' into a floating-point register. The value is zero-extended. |
| 446 // This behaviour matches AArch64 register writes. | 430 // This behaviour matches AArch64 register writes. |
| 447 template<typename T> | 431 template<typename T> |
| 448 void set_fpreg(unsigned code, T value) { | 432 void set_fpreg(unsigned code, T value) { |
| 449 set_fpreg_no_log(code, value); | 433 DCHECK((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize)); |
| 450 | 434 DCHECK(code < kNumberOfFPRegisters); |
| 451 if (sizeof(value) <= kSRegSize) { | 435 fpregisters_[code].Set(value); |
| 452 LogFPRegister(code, kPrintSRegValue); | |
| 453 } else { | |
| 454 LogFPRegister(code, kPrintDRegValue); | |
| 455 } | |
| 456 } | 436 } |
| 457 | 437 |
| 458 // Common specialized accessors for the set_fpreg() template. | 438 // Common specialized accessors for the set_fpreg() template. |
| 459 void set_sreg(unsigned code, float value) { | 439 void set_sreg(unsigned code, float value) { |
| 460 set_fpreg(code, value); | 440 set_fpreg(code, value); |
| 461 } | 441 } |
| 462 | 442 |
| 463 void set_sreg_bits(unsigned code, uint32_t value) { | 443 void set_sreg_bits(unsigned code, uint32_t value) { |
| 464 set_fpreg(code, value); | 444 set_fpreg(code, value); |
| 465 } | 445 } |
| 466 | 446 |
| 467 void set_dreg(unsigned code, double value) { | 447 void set_dreg(unsigned code, double value) { |
| 468 set_fpreg(code, value); | 448 set_fpreg(code, value); |
| 469 } | 449 } |
| 470 | 450 |
| 471 void set_dreg_bits(unsigned code, uint64_t value) { | 451 void set_dreg_bits(unsigned code, uint64_t value) { |
| 472 set_fpreg(code, value); | 452 set_fpreg(code, value); |
| 473 } | 453 } |
| 474 | 454 |
| 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_; } | 455 SimSystemRegister& nzcv() { return nzcv_; } |
| 492 SimSystemRegister& fpcr() { return fpcr_; } | 456 SimSystemRegister& fpcr() { return fpcr_; } |
| 493 | 457 |
| 494 // Debug helpers | 458 // Debug helpers |
| 495 | 459 |
| 496 // Simulator breakpoints. | 460 // Simulator breakpoints. |
| 497 struct Breakpoint { | 461 struct Breakpoint { |
| 498 Instruction* location; | 462 Instruction* location; |
| 499 bool enabled; | 463 bool enabled; |
| 500 }; | 464 }; |
| 501 std::vector<Breakpoint> breakpoints_; | 465 std::vector<Breakpoint> breakpoints_; |
| 502 void SetBreakpoint(Instruction* breakpoint); | 466 void SetBreakpoint(Instruction* breakpoint); |
| 503 void ListBreakpoints(); | 467 void ListBreakpoints(); |
| 504 void CheckBreakpoints(); | 468 void CheckBreakpoints(); |
| 505 | 469 |
| 506 // Helpers for the 'next' command. | 470 // Helpers for the 'next' command. |
| 507 // When this is set, the Simulator will insert a breakpoint after the next BL | 471 // When this is set, the Simulator will insert a breakpoint after the next BL |
| 508 // instruction it meets. | 472 // instruction it meets. |
| 509 bool break_on_next_; | 473 bool break_on_next_; |
| 510 // Check if the Simulator should insert a break after the current instruction | 474 // Check if the Simulator should insert a break after the current instruction |
| 511 // for the 'next' command. | 475 // for the 'next' command. |
| 512 void CheckBreakNext(); | 476 void CheckBreakNext(); |
| 513 | 477 |
| 514 // Disassemble instruction at the given address. | 478 // Disassemble instruction at the given address. |
| 515 void PrintInstructionsAt(Instruction* pc, uint64_t count); | 479 void PrintInstructionsAt(Instruction* pc, uint64_t count); |
| 516 | 480 |
| 517 // Print all registers of the specified types. | 481 void PrintSystemRegisters(bool print_all = false); |
| 518 void PrintRegisters(); | 482 void PrintRegisters(bool print_all_regs = false); |
| 519 void PrintFPRegisters(); | 483 void PrintFPRegisters(bool print_all_regs = false); |
| 520 void PrintSystemRegisters(); | 484 void PrintProcessorState(); |
| 521 | 485 void PrintWrite(uintptr_t address, uint64_t value, unsigned num_bytes); |
| 522 // Like Print* (above), but respect log_parameters(). | |
| 523 void LogSystemRegisters() { | 486 void LogSystemRegisters() { |
| 524 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegisters(); | 487 if (log_parameters_ & LOG_SYS_REGS) PrintSystemRegisters(); |
| 525 } | 488 } |
| 526 void LogRegisters() { | 489 void LogRegisters() { |
| 527 if (log_parameters() & LOG_REGS) PrintRegisters(); | 490 if (log_parameters_ & LOG_REGS) PrintRegisters(); |
| 528 } | 491 } |
| 529 void LogFPRegisters() { | 492 void LogFPRegisters() { |
| 530 if (log_parameters() & LOG_FP_REGS) PrintFPRegisters(); | 493 if (log_parameters_ & LOG_FP_REGS) PrintFPRegisters(); |
| 531 } | 494 } |
| 532 | 495 void LogProcessorState() { |
| 533 // Specify relevant register sizes, for PrintFPRegister. | 496 LogSystemRegisters(); |
| 534 // | 497 LogRegisters(); |
| 535 // These values are bit masks; they can be combined in case multiple views of | 498 LogFPRegisters(); |
| 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 } | 499 } |
| 553 void LogFPRegister(unsigned code, | 500 template <typename T> |
| 554 PrintFPRegisterSizes sizes = kPrintAllFPRegValues) { | 501 void LogWrite(uintptr_t address, T value) { |
| 555 if (log_parameters() & LOG_FP_REGS) PrintFPRegister(code, sizes); | 502 uint64_t raw_value = 0; |
| 556 } | 503 DCHECK(sizeof(value) <= sizeof(raw_value)); |
| 557 void LogSystemRegister(SystemRegister id) { | 504 if (log_parameters_ & LOG_WRITE) { |
| 558 if (log_parameters() & LOG_SYS_REGS) PrintSystemRegister(id); | 505 memcpy(&raw_value, &value, sizeof(value)); |
| 559 } | 506 PrintWrite(address, raw_value, sizeof(value)); |
| 560 | 507 } |
| 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 } | 508 } |
| 580 | 509 |
| 581 int log_parameters() { return log_parameters_; } | 510 int log_parameters() { return log_parameters_; } |
| 582 void set_log_parameters(int new_parameters) { | 511 void set_log_parameters(int new_parameters) { |
| 583 log_parameters_ = new_parameters; | 512 log_parameters_ = new_parameters; |
| 584 if (!decoder_) { | 513 if (!decoder_) { |
| 585 if (new_parameters & LOG_DISASM) { | 514 if (new_parameters & LOG_DISASM) { |
| 586 PrintF("Run --debug-sim to dynamically turn on disassembler\n"); | 515 PrintF("Run --debug-sim to dynamically turn on disassembler\n"); |
| 587 } | 516 } |
| 588 return; | 517 return; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 template<typename T> | 588 template<typename T> |
| 660 void AddSubWithCarry(Instruction* instr); | 589 void AddSubWithCarry(Instruction* instr); |
| 661 template<typename T> | 590 template<typename T> |
| 662 void LogicalHelper(Instruction* instr, T op2); | 591 void LogicalHelper(Instruction* instr, T op2); |
| 663 template<typename T> | 592 template<typename T> |
| 664 void ConditionalCompareHelper(Instruction* instr, T op2); | 593 void ConditionalCompareHelper(Instruction* instr, T op2); |
| 665 void LoadStoreHelper(Instruction* instr, | 594 void LoadStoreHelper(Instruction* instr, |
| 666 int64_t offset, | 595 int64_t offset, |
| 667 AddrMode addrmode); | 596 AddrMode addrmode); |
| 668 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode); | 597 void LoadStorePairHelper(Instruction* instr, AddrMode addrmode); |
| 669 uintptr_t LoadStoreAddress(unsigned addr_reg, int64_t offset, | 598 uint8_t* LoadStoreAddress(unsigned addr_reg, |
| 670 AddrMode addrmode); | 599 int64_t offset, |
| 600 AddrMode addrmode); |
| 671 void LoadStoreWriteBack(unsigned addr_reg, | 601 void LoadStoreWriteBack(unsigned addr_reg, |
| 672 int64_t offset, | 602 int64_t offset, |
| 673 AddrMode addrmode); | 603 AddrMode addrmode); |
| 674 void CheckMemoryAccess(uintptr_t address, uintptr_t stack); | 604 void CheckMemoryAccess(uint8_t* address, uint8_t* stack); |
| 675 | 605 |
| 676 // Memory read helpers. | |
| 677 template <typename T, typename A> | 606 template <typename T, typename A> |
| 678 T MemoryRead(A address) { | 607 T MemoryRead(A address) { |
| 679 T value; | 608 T value; |
| 680 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || | 609 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || |
| 681 (sizeof(value) == 4) || (sizeof(value) == 8)); | 610 (sizeof(value) == 4) || (sizeof(value) == 8)); |
| 682 memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value)); | 611 memcpy(&value, reinterpret_cast<const void*>(address), sizeof(value)); |
| 683 return value; | 612 return value; |
| 684 } | 613 } |
| 685 | 614 |
| 686 // Memory write helpers. | |
| 687 template <typename T, typename A> | 615 template <typename T, typename A> |
| 688 void MemoryWrite(A address, T value) { | 616 void MemoryWrite(A address, T value) { |
| 689 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || | 617 STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || |
| 690 (sizeof(value) == 4) || (sizeof(value) == 8)); | 618 (sizeof(value) == 4) || (sizeof(value) == 8)); |
| 619 LogWrite(reinterpret_cast<uintptr_t>(address), value); |
| 691 memcpy(reinterpret_cast<void*>(address), &value, sizeof(value)); | 620 memcpy(reinterpret_cast<void*>(address), &value, sizeof(value)); |
| 692 } | 621 } |
| 693 | 622 |
| 694 template <typename T> | 623 template <typename T> |
| 695 T ShiftOperand(T value, | 624 T ShiftOperand(T value, |
| 696 Shift shift_type, | 625 Shift shift_type, |
| 697 unsigned amount); | 626 unsigned amount); |
| 698 template <typename T> | 627 template <typename T> |
| 699 T ExtendValue(T value, | 628 T ExtendValue(T value, |
| 700 Extend extend_type, | 629 Extend extend_type, |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 return (result >> (sizeof(T) * 8 - 1)) & 1; | 764 return (result >> (sizeof(T) * 8 - 1)) & 1; |
| 836 } | 765 } |
| 837 | 766 |
| 838 static int CalcZFlag(uint64_t result) { | 767 static int CalcZFlag(uint64_t result) { |
| 839 return result == 0; | 768 return result == 0; |
| 840 } | 769 } |
| 841 | 770 |
| 842 static const uint32_t kConditionFlagsMask = 0xf0000000; | 771 static const uint32_t kConditionFlagsMask = 0xf0000000; |
| 843 | 772 |
| 844 // Stack | 773 // Stack |
| 845 uintptr_t stack_; | 774 byte* stack_; |
| 846 static const size_t stack_protection_size_ = KB; | 775 static const intptr_t stack_protection_size_ = KB; |
| 847 size_t stack_size_; | 776 intptr_t stack_size_; |
| 848 uintptr_t stack_limit_; | 777 byte* stack_limit_; |
| 849 | 778 |
| 850 Decoder<DispatchingDecoderVisitor>* decoder_; | 779 Decoder<DispatchingDecoderVisitor>* decoder_; |
| 851 Decoder<DispatchingDecoderVisitor>* disassembler_decoder_; | 780 Decoder<DispatchingDecoderVisitor>* disassembler_decoder_; |
| 852 | 781 |
| 853 // Indicates if the pc has been modified by the instruction and should not be | 782 // Indicates if the pc has been modified by the instruction and should not be |
| 854 // automatically incremented. | 783 // automatically incremented. |
| 855 bool pc_modified_; | 784 bool pc_modified_; |
| 856 Instruction* pc_; | 785 Instruction* pc_; |
| 857 | 786 |
| 858 static const char* xreg_names[]; | 787 static const char* xreg_names[]; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 static void UnregisterCTryCatch() { | 837 static void UnregisterCTryCatch() { |
| 909 Simulator::current(Isolate::Current())->PopAddress(); | 838 Simulator::current(Isolate::Current())->PopAddress(); |
| 910 } | 839 } |
| 911 }; | 840 }; |
| 912 | 841 |
| 913 #endif // !defined(USE_SIMULATOR) | 842 #endif // !defined(USE_SIMULATOR) |
| 914 | 843 |
| 915 } } // namespace v8::internal | 844 } } // namespace v8::internal |
| 916 | 845 |
| 917 #endif // V8_ARM64_SIMULATOR_ARM64_H_ | 846 #endif // V8_ARM64_SIMULATOR_ARM64_H_ |
| OLD | NEW |