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 |