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 |