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