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 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <cmath> | 6 #include <cmath> |
7 #include <cstdarg> | 7 #include <cstdarg> |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #if V8_TARGET_ARCH_ARM64 | 10 #if V8_TARGET_ARCH_ARM64 |
(...skipping 12 matching lines...) Expand all Loading... |
23 | 23 |
24 | 24 |
25 // This macro provides a platform independent use of sscanf. The reason for | 25 // This macro provides a platform independent use of sscanf. The reason for |
26 // SScanF not being implemented in a platform independent way through | 26 // SScanF not being implemented in a platform independent way through |
27 // ::v8::internal::OS in the same way as SNPrintF is that the | 27 // ::v8::internal::OS in the same way as SNPrintF is that the |
28 // Windows C Run-Time Library does not provide vsscanf. | 28 // Windows C Run-Time Library does not provide vsscanf. |
29 #define SScanF sscanf // NOLINT | 29 #define SScanF sscanf // NOLINT |
30 | 30 |
31 | 31 |
32 // Helpers for colors. | 32 // Helpers for colors. |
33 // Depending on your terminal configuration, the colour names may not match the | 33 #define COLOUR(colour_code) "\033[0;" colour_code "m" |
34 // observed colours. | 34 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m" |
35 #define COLOUR(colour_code) "\033[" colour_code "m" | 35 #define NORMAL "" |
36 #define BOLD(colour_code) "1;" colour_code | 36 #define GREY "30" |
37 #define NORMAL "" | 37 #define RED "31" |
38 #define GREY "30" | 38 #define GREEN "32" |
39 #define GREEN "32" | 39 #define YELLOW "33" |
40 #define ORANGE "33" | 40 #define BLUE "34" |
41 #define BLUE "34" | 41 #define MAGENTA "35" |
42 #define PURPLE "35" | 42 #define CYAN "36" |
43 #define INDIGO "36" | 43 #define WHITE "37" |
44 #define WHITE "37" | |
45 typedef char const * const TEXT_COLOUR; | 44 typedef char const * const TEXT_COLOUR; |
46 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : ""; | 45 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : ""; |
47 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR(BOLD(GREY)) : ""; | 46 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR_BOLD(WHITE) : ""; |
48 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(BOLD(WHITE)) : ""; | 47 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) : ""; |
49 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR(BOLD(BLUE)) : ""; | 48 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) : ""; |
50 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(BOLD(INDIGO)) : ""; | 49 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) : ""; |
51 TEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : ""; | 50 TEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) : ""; |
52 TEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(BOLD(PURPLE)) : ""; | 51 TEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(MAGENTA) : ""; |
53 TEXT_COLOUR clr_memory_value = FLAG_log_colour ? COLOUR(BOLD(GREEN)) : ""; | 52 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) : ""; |
54 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR(GREEN) : ""; | 53 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) : ""; |
55 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : ""; | 54 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : ""; |
56 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(ORANGE) : ""; | |
57 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : ""; | 55 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : ""; |
58 | 56 |
59 | 57 |
60 // This is basically the same as PrintF, with a guard for FLAG_trace_sim. | 58 // This is basically the same as PrintF, with a guard for FLAG_trace_sim. |
61 void Simulator::TraceSim(const char* format, ...) { | 59 void Simulator::TraceSim(const char* format, ...) { |
62 if (FLAG_trace_sim) { | 60 if (FLAG_trace_sim) { |
63 va_list arguments; | 61 va_list arguments; |
64 va_start(arguments, format); | 62 va_start(arguments, format); |
65 base::OS::VFPrint(stream_, format, arguments); | 63 base::OS::VFPrint(stream_, format, arguments); |
66 va_end(arguments); | 64 va_end(arguments); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize); | 328 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize); |
331 set_sp(current_sp + 2 * kXRegSize); | 329 set_sp(current_sp + 2 * kXRegSize); |
332 return address; | 330 return address; |
333 } | 331 } |
334 | 332 |
335 | 333 |
336 // Returns the limit of the stack area to enable checking for stack overflows. | 334 // Returns the limit of the stack area to enable checking for stack overflows. |
337 uintptr_t Simulator::StackLimit() const { | 335 uintptr_t Simulator::StackLimit() const { |
338 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when | 336 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when |
339 // pushing values. | 337 // pushing values. |
340 return reinterpret_cast<uintptr_t>(stack_limit_) + 1024; | 338 return stack_limit_ + 1024; |
341 } | 339 } |
342 | 340 |
343 | 341 |
344 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder, | 342 Simulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder, |
345 Isolate* isolate, FILE* stream) | 343 Isolate* isolate, FILE* stream) |
346 : decoder_(decoder), | 344 : decoder_(decoder), |
347 last_debugger_input_(NULL), | 345 last_debugger_input_(NULL), |
348 log_parameters_(NO_PARAM), | 346 log_parameters_(NO_PARAM), |
349 isolate_(isolate) { | 347 isolate_(isolate) { |
350 // Setup the decoder. | 348 // Setup the decoder. |
(...skipping 22 matching lines...) Expand all Loading... |
373 Init(stdout); | 371 Init(stdout); |
374 CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats); | 372 CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats); |
375 } | 373 } |
376 | 374 |
377 | 375 |
378 void Simulator::Init(FILE* stream) { | 376 void Simulator::Init(FILE* stream) { |
379 ResetState(); | 377 ResetState(); |
380 | 378 |
381 // Allocate and setup the simulator stack. | 379 // Allocate and setup the simulator stack. |
382 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_); | 380 stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_); |
383 stack_ = new byte[stack_size_]; | 381 stack_ = reinterpret_cast<uintptr_t>(new byte[stack_size_]); |
384 stack_limit_ = stack_ + stack_protection_size_; | 382 stack_limit_ = stack_ + stack_protection_size_; |
385 byte* tos = stack_ + stack_size_ - stack_protection_size_; | 383 uintptr_t tos = stack_ + stack_size_ - stack_protection_size_; |
386 // The stack pointer must be 16 bytes aligned. | 384 // The stack pointer must be 16-byte aligned. |
387 set_sp(reinterpret_cast<int64_t>(tos) & ~0xfUL); | 385 set_sp(tos & ~0xfUL); |
388 | 386 |
389 stream_ = stream; | 387 stream_ = stream; |
390 print_disasm_ = new PrintDisassembler(stream_); | 388 print_disasm_ = new PrintDisassembler(stream_); |
391 | 389 |
392 // The debugger needs to disassemble code without the simulator executing an | 390 // The debugger needs to disassemble code without the simulator executing an |
393 // instruction, so we create a dedicated decoder. | 391 // instruction, so we create a dedicated decoder. |
394 disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>(); | 392 disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>(); |
395 disassembler_decoder_->AppendVisitor(print_disasm_); | 393 disassembler_decoder_->AppendVisitor(print_disasm_); |
396 } | 394 } |
397 | 395 |
(...skipping 15 matching lines...) Expand all Loading... |
413 // Returning to address 0 exits the Simulator. | 411 // Returning to address 0 exits the Simulator. |
414 set_lr(kEndOfSimAddress); | 412 set_lr(kEndOfSimAddress); |
415 | 413 |
416 // Reset debug helpers. | 414 // Reset debug helpers. |
417 breakpoints_.empty(); | 415 breakpoints_.empty(); |
418 break_on_next_= false; | 416 break_on_next_= false; |
419 } | 417 } |
420 | 418 |
421 | 419 |
422 Simulator::~Simulator() { | 420 Simulator::~Simulator() { |
423 delete[] stack_; | 421 delete[] reinterpret_cast<byte*>(stack_); |
424 if (FLAG_log_instruction_stats) { | 422 if (FLAG_log_instruction_stats) { |
425 delete instrument_; | 423 delete instrument_; |
426 } | 424 } |
427 delete disassembler_decoder_; | 425 delete disassembler_decoder_; |
428 delete print_disasm_; | 426 delete print_disasm_; |
429 DeleteArray(last_debugger_input_); | 427 DeleteArray(last_debugger_input_); |
430 delete decoder_; | 428 delete decoder_; |
431 } | 429 } |
432 | 430 |
433 | 431 |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 | 725 |
728 | 726 |
729 void* Simulator::RedirectExternalReference(void* external_function, | 727 void* Simulator::RedirectExternalReference(void* external_function, |
730 ExternalReference::Type type) { | 728 ExternalReference::Type type) { |
731 Redirection* redirection = Redirection::Get(external_function, type); | 729 Redirection* redirection = Redirection::Get(external_function, type); |
732 return redirection->address_of_redirect_call(); | 730 return redirection->address_of_redirect_call(); |
733 } | 731 } |
734 | 732 |
735 | 733 |
736 const char* Simulator::xreg_names[] = { | 734 const char* Simulator::xreg_names[] = { |
737 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", | 735 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", |
738 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", | 736 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", |
739 "ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23", | 737 "ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23", |
740 "x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"}; | 738 "x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"}; |
741 | 739 |
742 const char* Simulator::wreg_names[] = { | 740 const char* Simulator::wreg_names[] = { |
743 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", | 741 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", |
744 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", | 742 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", |
745 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", | 743 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", |
746 "w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"}; | 744 "w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"}; |
747 | 745 |
748 const char* Simulator::sreg_names[] = { | 746 const char* Simulator::sreg_names[] = { |
749 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", | 747 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
750 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", | 748 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", |
751 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", | 749 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", |
752 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"}; | 750 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"}; |
753 | 751 |
754 const char* Simulator::dreg_names[] = { | 752 const char* Simulator::dreg_names[] = { |
755 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", | 753 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
756 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", | 754 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", |
757 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", | 755 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", |
758 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"}; | 756 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"}; |
759 | 757 |
760 const char* Simulator::vreg_names[] = { | 758 const char* Simulator::vreg_names[] = { |
761 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", | 759 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", |
762 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", | 760 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", |
763 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", | 761 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", |
764 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"}; | 762 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"}; |
765 | 763 |
766 | 764 |
767 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) { | 765 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) { |
| 766 STATIC_ASSERT(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1)); |
768 DCHECK(code < kNumberOfRegisters); | 767 DCHECK(code < kNumberOfRegisters); |
| 768 // The modulo operator has no effect here, but it silences a broken GCC |
| 769 // warning about out-of-bounds array accesses. |
| 770 code %= kNumberOfRegisters; |
| 771 |
769 // If the code represents the stack pointer, index the name after zr. | 772 // If the code represents the stack pointer, index the name after zr. |
770 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { | 773 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { |
771 code = kZeroRegCode + 1; | 774 code = kZeroRegCode + 1; |
772 } | 775 } |
773 return wreg_names[code]; | 776 return wreg_names[code]; |
774 } | 777 } |
775 | 778 |
776 | 779 |
777 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { | 780 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { |
| 781 STATIC_ASSERT(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1)); |
778 DCHECK(code < kNumberOfRegisters); | 782 DCHECK(code < kNumberOfRegisters); |
| 783 code %= kNumberOfRegisters; |
| 784 |
779 // If the code represents the stack pointer, index the name after zr. | 785 // If the code represents the stack pointer, index the name after zr. |
780 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { | 786 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { |
781 code = kZeroRegCode + 1; | 787 code = kZeroRegCode + 1; |
782 } | 788 } |
783 return xreg_names[code]; | 789 return xreg_names[code]; |
784 } | 790 } |
785 | 791 |
786 | 792 |
787 const char* Simulator::SRegNameForCode(unsigned code) { | 793 const char* Simulator::SRegNameForCode(unsigned code) { |
| 794 STATIC_ASSERT(arraysize(Simulator::sreg_names) == kNumberOfFPRegisters); |
788 DCHECK(code < kNumberOfFPRegisters); | 795 DCHECK(code < kNumberOfFPRegisters); |
789 return sreg_names[code]; | 796 return sreg_names[code % kNumberOfFPRegisters]; |
790 } | 797 } |
791 | 798 |
792 | 799 |
793 const char* Simulator::DRegNameForCode(unsigned code) { | 800 const char* Simulator::DRegNameForCode(unsigned code) { |
| 801 STATIC_ASSERT(arraysize(Simulator::dreg_names) == kNumberOfFPRegisters); |
794 DCHECK(code < kNumberOfFPRegisters); | 802 DCHECK(code < kNumberOfFPRegisters); |
795 return dreg_names[code]; | 803 return dreg_names[code % kNumberOfFPRegisters]; |
796 } | 804 } |
797 | 805 |
798 | 806 |
799 const char* Simulator::VRegNameForCode(unsigned code) { | 807 const char* Simulator::VRegNameForCode(unsigned code) { |
| 808 STATIC_ASSERT(arraysize(Simulator::vreg_names) == kNumberOfFPRegisters); |
800 DCHECK(code < kNumberOfFPRegisters); | 809 DCHECK(code < kNumberOfFPRegisters); |
801 return vreg_names[code]; | 810 return vreg_names[code % kNumberOfFPRegisters]; |
802 } | 811 } |
803 | 812 |
804 | 813 |
805 int Simulator::CodeFromName(const char* name) { | 814 int Simulator::CodeFromName(const char* name) { |
806 for (unsigned i = 0; i < kNumberOfRegisters; i++) { | 815 for (unsigned i = 0; i < kNumberOfRegisters; i++) { |
807 if ((strcmp(xreg_names[i], name) == 0) || | 816 if ((strcmp(xreg_names[i], name) == 0) || |
808 (strcmp(wreg_names[i], name) == 0)) { | 817 (strcmp(wreg_names[i], name) == 0)) { |
809 return i; | 818 return i; |
810 } | 819 } |
811 } | 820 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); | 857 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); |
849 | 858 |
850 N = CalcNFlag(result); | 859 N = CalcNFlag(result); |
851 Z = CalcZFlag(result); | 860 Z = CalcZFlag(result); |
852 | 861 |
853 if (set_flags) { | 862 if (set_flags) { |
854 nzcv().SetN(N); | 863 nzcv().SetN(N); |
855 nzcv().SetZ(Z); | 864 nzcv().SetZ(Z); |
856 nzcv().SetC(C); | 865 nzcv().SetC(C); |
857 nzcv().SetV(V); | 866 nzcv().SetV(V); |
| 867 LogSystemRegister(NZCV); |
858 } | 868 } |
859 return result; | 869 return result; |
860 } | 870 } |
861 | 871 |
862 | 872 |
863 template<typename T> | 873 template<typename T> |
864 void Simulator::AddSubWithCarry(Instruction* instr) { | 874 void Simulator::AddSubWithCarry(Instruction* instr) { |
865 T op2 = reg<T>(instr->Rm()); | 875 T op2 = reg<T>(instr->Rm()); |
866 T new_val; | 876 T new_val; |
867 | 877 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 nzcv().SetRawValue(FPUnorderedFlag); | 981 nzcv().SetRawValue(FPUnorderedFlag); |
972 } else if (val0 < val1) { | 982 } else if (val0 < val1) { |
973 nzcv().SetRawValue(FPLessThanFlag); | 983 nzcv().SetRawValue(FPLessThanFlag); |
974 } else if (val0 > val1) { | 984 } else if (val0 > val1) { |
975 nzcv().SetRawValue(FPGreaterThanFlag); | 985 nzcv().SetRawValue(FPGreaterThanFlag); |
976 } else if (val0 == val1) { | 986 } else if (val0 == val1) { |
977 nzcv().SetRawValue(FPEqualFlag); | 987 nzcv().SetRawValue(FPEqualFlag); |
978 } else { | 988 } else { |
979 UNREACHABLE(); | 989 UNREACHABLE(); |
980 } | 990 } |
| 991 LogSystemRegister(NZCV); |
981 } | 992 } |
982 | 993 |
983 | 994 |
984 void Simulator::SetBreakpoint(Instruction* location) { | 995 void Simulator::SetBreakpoint(Instruction* location) { |
985 for (unsigned i = 0; i < breakpoints_.size(); i++) { | 996 for (unsigned i = 0; i < breakpoints_.size(); i++) { |
986 if (breakpoints_.at(i).location == location) { | 997 if (breakpoints_.at(i).location == location) { |
987 PrintF(stream_, | 998 PrintF(stream_, |
988 "Existing breakpoint at %p was %s\n", | 999 "Existing breakpoint at %p was %s\n", |
989 reinterpret_cast<void*>(location), | 1000 reinterpret_cast<void*>(location), |
990 breakpoints_.at(i).enabled ? "disabled" : "enabled"); | 1001 breakpoints_.at(i).enabled ? "disabled" : "enabled"); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 | 1048 |
1038 | 1049 |
1039 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { | 1050 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { |
1040 Instruction* end = start->InstructionAtOffset(count * kInstructionSize); | 1051 Instruction* end = start->InstructionAtOffset(count * kInstructionSize); |
1041 for (Instruction* pc = start; pc < end; pc = pc->following()) { | 1052 for (Instruction* pc = start; pc < end; pc = pc->following()) { |
1042 disassembler_decoder_->Decode(pc); | 1053 disassembler_decoder_->Decode(pc); |
1043 } | 1054 } |
1044 } | 1055 } |
1045 | 1056 |
1046 | 1057 |
1047 void Simulator::PrintSystemRegisters(bool print_all) { | 1058 void Simulator::PrintSystemRegisters() { |
1048 static bool first_run = true; | 1059 PrintSystemRegister(NZCV); |
1049 | 1060 PrintSystemRegister(FPCR); |
1050 static SimSystemRegister last_nzcv; | 1061 } |
1051 if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) { | 1062 |
1052 fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n", | 1063 |
1053 clr_flag_name, | 1064 void Simulator::PrintRegisters() { |
1054 clr_flag_value, | |
1055 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(), | |
1056 clr_normal); | |
1057 } | |
1058 last_nzcv = nzcv(); | |
1059 | |
1060 static SimSystemRegister last_fpcr; | |
1061 if (print_all || first_run || (last_fpcr.RawValue() != fpcr().RawValue())) { | |
1062 static const char * rmode[] = { | |
1063 "0b00 (Round to Nearest)", | |
1064 "0b01 (Round towards Plus Infinity)", | |
1065 "0b10 (Round towards Minus Infinity)", | |
1066 "0b11 (Round towards Zero)" | |
1067 }; | |
1068 DCHECK(fpcr().RMode() < arraysize(rmode)); | |
1069 fprintf(stream_, "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n", | |
1070 clr_flag_name, | |
1071 clr_flag_value, | |
1072 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()], | |
1073 clr_normal); | |
1074 } | |
1075 last_fpcr = fpcr(); | |
1076 | |
1077 first_run = false; | |
1078 } | |
1079 | |
1080 | |
1081 void Simulator::PrintRegisters(bool print_all_regs) { | |
1082 static bool first_run = true; | |
1083 static int64_t last_regs[kNumberOfRegisters]; | |
1084 | |
1085 for (unsigned i = 0; i < kNumberOfRegisters; i++) { | 1065 for (unsigned i = 0; i < kNumberOfRegisters; i++) { |
1086 if (print_all_regs || first_run || | 1066 PrintRegister(i); |
1087 (last_regs[i] != xreg(i, Reg31IsStackPointer))) { | 1067 } |
| 1068 } |
| 1069 |
| 1070 |
| 1071 void Simulator::PrintFPRegisters() { |
| 1072 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { |
| 1073 PrintFPRegister(i); |
| 1074 } |
| 1075 } |
| 1076 |
| 1077 |
| 1078 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) { |
| 1079 // Don't print writes into xzr. |
| 1080 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) { |
| 1081 return; |
| 1082 } |
| 1083 |
| 1084 // The template is "# x<code>:value". |
| 1085 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s\n", |
| 1086 clr_reg_name, XRegNameForCode(code, r31mode), |
| 1087 clr_reg_value, reg<uint64_t>(code, r31mode), clr_normal); |
| 1088 } |
| 1089 |
| 1090 |
| 1091 void Simulator::PrintFPRegister(unsigned code, PrintFPRegisterSizes sizes) { |
| 1092 // The template is "# v<code>:bits (d<code>:value, ...)". |
| 1093 |
| 1094 DCHECK(sizes != 0); |
| 1095 DCHECK((sizes & kPrintAllFPRegValues) == sizes); |
| 1096 |
| 1097 // Print the raw bits. |
| 1098 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (", |
| 1099 clr_fpreg_name, VRegNameForCode(code), |
| 1100 clr_fpreg_value, fpreg<uint64_t>(code), clr_normal); |
| 1101 |
| 1102 // Print all requested value interpretations. |
| 1103 bool need_separator = false; |
| 1104 if (sizes & kPrintDRegValue) { |
| 1105 fprintf(stream_, "%s%s%s: %s%g%s", |
| 1106 need_separator ? ", " : "", |
| 1107 clr_fpreg_name, DRegNameForCode(code), |
| 1108 clr_fpreg_value, fpreg<double>(code), clr_normal); |
| 1109 need_separator = true; |
| 1110 } |
| 1111 |
| 1112 if (sizes & kPrintSRegValue) { |
| 1113 fprintf(stream_, "%s%s%s: %s%g%s", |
| 1114 need_separator ? ", " : "", |
| 1115 clr_fpreg_name, SRegNameForCode(code), |
| 1116 clr_fpreg_value, fpreg<float>(code), clr_normal); |
| 1117 need_separator = true; |
| 1118 } |
| 1119 |
| 1120 // End the value list. |
| 1121 fprintf(stream_, ")\n"); |
| 1122 } |
| 1123 |
| 1124 |
| 1125 void Simulator::PrintSystemRegister(SystemRegister id) { |
| 1126 switch (id) { |
| 1127 case NZCV: |
| 1128 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n", |
| 1129 clr_flag_name, clr_flag_value, |
| 1130 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(), |
| 1131 clr_normal); |
| 1132 break; |
| 1133 case FPCR: { |
| 1134 static const char * rmode[] = { |
| 1135 "0b00 (Round to Nearest)", |
| 1136 "0b01 (Round towards Plus Infinity)", |
| 1137 "0b10 (Round towards Minus Infinity)", |
| 1138 "0b11 (Round towards Zero)" |
| 1139 }; |
| 1140 DCHECK(fpcr().RMode() < arraysize(rmode)); |
1088 fprintf(stream_, | 1141 fprintf(stream_, |
1089 "# %s%4s:%s 0x%016" PRIx64 "%s\n", | 1142 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n", |
1090 clr_reg_name, | 1143 clr_flag_name, clr_flag_value, |
1091 XRegNameForCode(i, Reg31IsStackPointer), | 1144 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()], |
1092 clr_reg_value, | |
1093 xreg(i, Reg31IsStackPointer), | |
1094 clr_normal); | 1145 clr_normal); |
| 1146 break; |
1095 } | 1147 } |
1096 // Cache the new register value so the next run can detect any changes. | 1148 default: |
1097 last_regs[i] = xreg(i, Reg31IsStackPointer); | 1149 UNREACHABLE(); |
1098 } | 1150 } |
1099 first_run = false; | 1151 } |
1100 } | 1152 |
1101 | 1153 |
1102 | 1154 void Simulator::PrintRead(uintptr_t address, |
1103 void Simulator::PrintFPRegisters(bool print_all_regs) { | 1155 size_t size, |
1104 static bool first_run = true; | 1156 unsigned reg_code) { |
1105 static uint64_t last_regs[kNumberOfFPRegisters]; | 1157 USE(size); // Size is unused here. |
1106 | 1158 |
1107 // Print as many rows of registers as necessary, keeping each individual | 1159 // The template is "# x<code>:value <- address". |
1108 // register in the same column each time (to make it easy to visually scan | 1160 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s", |
1109 // for changes). | 1161 clr_reg_name, XRegNameForCode(reg_code), |
1110 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { | 1162 clr_reg_value, reg<uint64_t>(reg_code), clr_normal); |
1111 if (print_all_regs || first_run || (last_regs[i] != dreg_bits(i))) { | 1163 |
1112 fprintf(stream_, | 1164 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n", |
1113 "# %s %4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n", | 1165 clr_memory_address, address, clr_normal); |
1114 clr_fpreg_name, | 1166 } |
1115 VRegNameForCode(i), | 1167 |
1116 clr_fpreg_value, | 1168 |
1117 dreg_bits(i), | 1169 void Simulator::PrintReadFP(uintptr_t address, |
1118 clr_normal, | 1170 size_t size, |
1119 clr_fpreg_name, | 1171 unsigned reg_code) { |
1120 DRegNameForCode(i), | 1172 // The template is "# reg:bits (reg:value) <- address". |
1121 clr_fpreg_value, | 1173 switch (size) { |
1122 dreg(i), | 1174 case kSRegSize: |
1123 clr_fpreg_name, | 1175 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%gf%s)", |
1124 SRegNameForCode(i), | 1176 clr_fpreg_name, VRegNameForCode(reg_code), |
1125 clr_fpreg_value, | 1177 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, |
1126 sreg(i), | 1178 clr_fpreg_name, SRegNameForCode(reg_code), |
1127 clr_normal); | 1179 clr_fpreg_value, fpreg<float>(reg_code), clr_normal); |
1128 } | 1180 break; |
1129 // Cache the new register value so the next run can detect any changes. | 1181 case kDRegSize: |
1130 last_regs[i] = dreg_bits(i); | 1182 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)", |
1131 } | 1183 clr_fpreg_name, VRegNameForCode(reg_code), |
1132 first_run = false; | 1184 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, |
1133 } | 1185 clr_fpreg_name, DRegNameForCode(reg_code), |
1134 | 1186 clr_fpreg_value, fpreg<double>(reg_code), clr_normal); |
1135 | 1187 break; |
1136 void Simulator::PrintProcessorState() { | 1188 default: |
1137 PrintSystemRegisters(); | 1189 UNREACHABLE(); |
1138 PrintRegisters(); | 1190 } |
1139 PrintFPRegisters(); | 1191 |
1140 } | 1192 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n", |
1141 | 1193 clr_memory_address, address, clr_normal); |
1142 | 1194 } |
1143 void Simulator::PrintWrite(uintptr_t address, uint64_t value, | 1195 |
1144 unsigned num_bytes) { | 1196 |
1145 // The template is "# value -> address". The format string is not used | 1197 void Simulator::PrintWrite(uintptr_t address, |
1146 // directly in the printf because some compilers struggle with the | 1198 size_t size, |
1147 // parametrized width field (%0*). | 1199 unsigned reg_code) { |
1148 const char* format = "# %s0x%0*" PRIx64 "%s -> %s0x%016" PRIxPTR "%s\n"; | 1200 // The template is "# reg:value -> address". To keep the trace tidy and |
1149 fprintf(stream_, | 1201 // readable, the value is aligned with the values in the register trace. |
1150 format, | 1202 switch (size) { |
1151 clr_memory_value, | 1203 case kByteSizeInBytes: |
1152 num_bytes * 2, // The width in hexadecimal characters. | 1204 fprintf(stream_, "# %s%5s<7:0>: %s0x%02" PRIx8 "%s", |
1153 value, | 1205 clr_reg_name, WRegNameForCode(reg_code), |
1154 clr_normal, | 1206 clr_reg_value, reg<uint8_t>(reg_code), clr_normal); |
1155 clr_memory_address, | 1207 break; |
1156 address, | 1208 case kHalfWordSizeInBytes: |
1157 clr_normal); | 1209 fprintf(stream_, "# %s%5s<15:0>: %s0x%04" PRIx16 "%s", |
1158 } | 1210 clr_reg_name, WRegNameForCode(reg_code), |
1159 | 1211 clr_reg_value, reg<uint16_t>(reg_code), clr_normal); |
1160 | 1212 break; |
| 1213 case kWRegSize: |
| 1214 fprintf(stream_, "# %s%5s: %s0x%08" PRIx32 "%s", |
| 1215 clr_reg_name, WRegNameForCode(reg_code), |
| 1216 clr_reg_value, reg<uint32_t>(reg_code), clr_normal); |
| 1217 break; |
| 1218 case kXRegSize: |
| 1219 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s", |
| 1220 clr_reg_name, XRegNameForCode(reg_code), |
| 1221 clr_reg_value, reg<uint64_t>(reg_code), clr_normal); |
| 1222 break; |
| 1223 default: |
| 1224 UNREACHABLE(); |
| 1225 } |
| 1226 |
| 1227 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", |
| 1228 clr_memory_address, address, clr_normal); |
| 1229 } |
| 1230 |
| 1231 |
| 1232 void Simulator::PrintWriteFP(uintptr_t address, |
| 1233 size_t size, |
| 1234 unsigned reg_code) { |
| 1235 // The template is "# reg:bits (reg:value) -> address". To keep the trace tidy |
| 1236 // and readable, the value is aligned with the values in the register trace. |
| 1237 switch (size) { |
| 1238 case kSRegSize: |
| 1239 fprintf(stream_, "# %s%5s<31:0>: %s0x%08" PRIx32 "%s (%s%s: %s%gf%s)", |
| 1240 clr_fpreg_name, VRegNameForCode(reg_code), |
| 1241 clr_fpreg_value, fpreg<uint32_t>(reg_code), clr_normal, |
| 1242 clr_fpreg_name, SRegNameForCode(reg_code), |
| 1243 clr_fpreg_value, fpreg<float>(reg_code), clr_normal); |
| 1244 break; |
| 1245 case kDRegSize: |
| 1246 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)", |
| 1247 clr_fpreg_name, VRegNameForCode(reg_code), |
| 1248 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, |
| 1249 clr_fpreg_name, DRegNameForCode(reg_code), |
| 1250 clr_fpreg_value, fpreg<double>(reg_code), clr_normal); |
| 1251 break; |
| 1252 default: |
| 1253 UNREACHABLE(); |
| 1254 } |
| 1255 |
| 1256 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", |
| 1257 clr_memory_address, address, clr_normal); |
| 1258 } |
| 1259 |
| 1260 |
1161 // Visitors--------------------------------------------------------------------- | 1261 // Visitors--------------------------------------------------------------------- |
1162 | 1262 |
1163 void Simulator::VisitUnimplemented(Instruction* instr) { | 1263 void Simulator::VisitUnimplemented(Instruction* instr) { |
1164 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n", | 1264 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n", |
1165 reinterpret_cast<void*>(instr), instr->InstructionBits()); | 1265 reinterpret_cast<void*>(instr), instr->InstructionBits()); |
1166 UNIMPLEMENTED(); | 1266 UNIMPLEMENTED(); |
1167 } | 1267 } |
1168 | 1268 |
1169 | 1269 |
1170 void Simulator::VisitUnallocated(Instruction* instr) { | 1270 void Simulator::VisitUnallocated(Instruction* instr) { |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1376 case EOR: result = op1 ^ op2; break; | 1476 case EOR: result = op1 ^ op2; break; |
1377 default: | 1477 default: |
1378 UNIMPLEMENTED(); | 1478 UNIMPLEMENTED(); |
1379 } | 1479 } |
1380 | 1480 |
1381 if (update_flags) { | 1481 if (update_flags) { |
1382 nzcv().SetN(CalcNFlag(result)); | 1482 nzcv().SetN(CalcNFlag(result)); |
1383 nzcv().SetZ(CalcZFlag(result)); | 1483 nzcv().SetZ(CalcZFlag(result)); |
1384 nzcv().SetC(0); | 1484 nzcv().SetC(0); |
1385 nzcv().SetV(0); | 1485 nzcv().SetV(0); |
| 1486 LogSystemRegister(NZCV); |
1386 } | 1487 } |
1387 | 1488 |
1388 set_reg<T>(instr->Rd(), result, instr->RdMode()); | 1489 set_reg<T>(instr->Rd(), result, instr->RdMode()); |
1389 } | 1490 } |
1390 | 1491 |
1391 | 1492 |
1392 void Simulator::VisitConditionalCompareRegister(Instruction* instr) { | 1493 void Simulator::VisitConditionalCompareRegister(Instruction* instr) { |
1393 if (instr->SixtyFourBits()) { | 1494 if (instr->SixtyFourBits()) { |
1394 ConditionalCompareHelper(instr, xreg(instr->Rm())); | 1495 ConditionalCompareHelper(instr, xreg(instr->Rm())); |
1395 } else { | 1496 } else { |
(...skipping 20 matching lines...) Expand all Loading... |
1416 // the operands. | 1517 // the operands. |
1417 if (instr->Mask(ConditionalCompareMask) == CCMP) { | 1518 if (instr->Mask(ConditionalCompareMask) == CCMP) { |
1418 AddWithCarry<T>(true, op1, ~op2, 1); | 1519 AddWithCarry<T>(true, op1, ~op2, 1); |
1419 } else { | 1520 } else { |
1420 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN); | 1521 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN); |
1421 AddWithCarry<T>(true, op1, op2, 0); | 1522 AddWithCarry<T>(true, op1, op2, 0); |
1422 } | 1523 } |
1423 } else { | 1524 } else { |
1424 // If the condition fails, set the status flags to the nzcv immediate. | 1525 // If the condition fails, set the status flags to the nzcv immediate. |
1425 nzcv().SetFlags(instr->Nzcv()); | 1526 nzcv().SetFlags(instr->Nzcv()); |
| 1527 LogSystemRegister(NZCV); |
1426 } | 1528 } |
1427 } | 1529 } |
1428 | 1530 |
1429 | 1531 |
1430 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { | 1532 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { |
1431 int offset = instr->ImmLSUnsigned() << instr->SizeLS(); | 1533 int offset = instr->ImmLSUnsigned() << instr->SizeLS(); |
1432 LoadStoreHelper(instr, offset, Offset); | 1534 LoadStoreHelper(instr, offset, Offset); |
1433 } | 1535 } |
1434 | 1536 |
1435 | 1537 |
(...skipping 20 matching lines...) Expand all Loading... |
1456 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount); | 1558 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount); |
1457 LoadStoreHelper(instr, offset, Offset); | 1559 LoadStoreHelper(instr, offset, Offset); |
1458 } | 1560 } |
1459 | 1561 |
1460 | 1562 |
1461 void Simulator::LoadStoreHelper(Instruction* instr, | 1563 void Simulator::LoadStoreHelper(Instruction* instr, |
1462 int64_t offset, | 1564 int64_t offset, |
1463 AddrMode addrmode) { | 1565 AddrMode addrmode) { |
1464 unsigned srcdst = instr->Rt(); | 1566 unsigned srcdst = instr->Rt(); |
1465 unsigned addr_reg = instr->Rn(); | 1567 unsigned addr_reg = instr->Rn(); |
1466 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); | 1568 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode); |
1467 uint8_t* stack = NULL; | 1569 uintptr_t stack = 0; |
1468 | 1570 |
1469 // Handle the writeback for stores before the store. On a CPU the writeback | 1571 // Handle the writeback for stores before the store. On a CPU the writeback |
1470 // and the store are atomic, but when running on the simulator it is possible | 1572 // and the store are atomic, but when running on the simulator it is possible |
1471 // to be interrupted in between. The simulator is not thread safe and V8 does | 1573 // to be interrupted in between. The simulator is not thread safe and V8 does |
1472 // not require it to be to run JavaScript therefore the profiler may sample | 1574 // not require it to be to run JavaScript therefore the profiler may sample |
1473 // the "simulated" CPU in the middle of load/store with writeback. The code | 1575 // the "simulated" CPU in the middle of load/store with writeback. The code |
1474 // below ensures that push operations are safe even when interrupted: the | 1576 // below ensures that push operations are safe even when interrupted: the |
1475 // stack pointer will be decremented before adding an element to the stack. | 1577 // stack pointer will be decremented before adding an element to the stack. |
1476 if (instr->IsStore()) { | 1578 if (instr->IsStore()) { |
1477 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1579 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1478 | 1580 |
1479 // For store the address post writeback is used to check access below the | 1581 // For store the address post writeback is used to check access below the |
1480 // stack. | 1582 // stack. |
1481 stack = reinterpret_cast<uint8_t*>(sp()); | 1583 stack = sp(); |
1482 } | 1584 } |
1483 | 1585 |
1484 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); | 1586 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); |
1485 switch (op) { | 1587 switch (op) { |
1486 case LDRB_w: set_wreg(srcdst, MemoryRead<uint8_t>(address)); break; | 1588 // Use _no_log variants to suppress the register trace (LOG_REGS, |
1487 case LDRH_w: set_wreg(srcdst, MemoryRead<uint16_t>(address)); break; | 1589 // LOG_FP_REGS). We will print a more detailed log. |
1488 case LDR_w: set_wreg(srcdst, MemoryRead<uint32_t>(address)); break; | 1590 case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break; |
1489 case LDR_x: set_xreg(srcdst, MemoryRead<uint64_t>(address)); break; | 1591 case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break; |
1490 case LDRSB_w: set_wreg(srcdst, MemoryRead<int8_t>(address)); break; | 1592 case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break; |
1491 case LDRSH_w: set_wreg(srcdst, MemoryRead<int16_t>(address)); break; | 1593 case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break; |
1492 case LDRSB_x: set_xreg(srcdst, MemoryRead<int8_t>(address)); break; | 1594 case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break; |
1493 case LDRSH_x: set_xreg(srcdst, MemoryRead<int16_t>(address)); break; | 1595 case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break; |
1494 case LDRSW_x: set_xreg(srcdst, MemoryRead<int32_t>(address)); break; | 1596 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break; |
1495 case LDR_s: set_sreg(srcdst, MemoryRead<float>(address)); break; | 1597 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break; |
1496 case LDR_d: set_dreg(srcdst, MemoryRead<double>(address)); break; | 1598 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break; |
| 1599 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break; |
| 1600 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break; |
1497 | 1601 |
1498 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break; | 1602 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break; |
1499 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break; | 1603 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break; |
1500 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break; | 1604 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break; |
1501 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break; | 1605 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break; |
1502 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break; | 1606 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break; |
1503 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break; | 1607 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break; |
1504 | 1608 |
1505 default: UNIMPLEMENTED(); | 1609 default: UNIMPLEMENTED(); |
1506 } | 1610 } |
1507 | 1611 |
| 1612 // Print a detailed trace (including the memory address) instead of the basic |
| 1613 // register:value trace generated by set_*reg(). |
| 1614 size_t access_size = 1 << instr->SizeLS(); |
| 1615 if (instr->IsLoad()) { |
| 1616 if ((op == LDR_s) || (op == LDR_d)) { |
| 1617 LogReadFP(address, access_size, srcdst); |
| 1618 } else { |
| 1619 LogRead(address, access_size, srcdst); |
| 1620 } |
| 1621 } else { |
| 1622 if ((op == STR_s) || (op == STR_d)) { |
| 1623 LogWriteFP(address, access_size, srcdst); |
| 1624 } else { |
| 1625 LogWrite(address, access_size, srcdst); |
| 1626 } |
| 1627 } |
| 1628 |
1508 // Handle the writeback for loads after the load to ensure safe pop | 1629 // Handle the writeback for loads after the load to ensure safe pop |
1509 // operation even when interrupted in the middle of it. The stack pointer | 1630 // operation even when interrupted in the middle of it. The stack pointer |
1510 // is only updated after the load so pop(fp) will never break the invariant | 1631 // is only updated after the load so pop(fp) will never break the invariant |
1511 // sp <= fp expected while walking the stack in the sampler. | 1632 // sp <= fp expected while walking the stack in the sampler. |
1512 if (instr->IsLoad()) { | 1633 if (instr->IsLoad()) { |
1513 // For loads the address pre writeback is used to check access below the | 1634 // For loads the address pre writeback is used to check access below the |
1514 // stack. | 1635 // stack. |
1515 stack = reinterpret_cast<uint8_t*>(sp()); | 1636 stack = sp(); |
1516 | 1637 |
1517 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1638 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1518 } | 1639 } |
1519 | 1640 |
1520 // Accesses below the stack pointer (but above the platform stack limit) are | 1641 // Accesses below the stack pointer (but above the platform stack limit) are |
1521 // not allowed in the ABI. | 1642 // not allowed in the ABI. |
1522 CheckMemoryAccess(address, stack); | 1643 CheckMemoryAccess(address, stack); |
1523 } | 1644 } |
1524 | 1645 |
1525 | 1646 |
(...skipping 15 matching lines...) Expand all Loading... |
1541 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) { | 1662 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) { |
1542 LoadStorePairHelper(instr, Offset); | 1663 LoadStorePairHelper(instr, Offset); |
1543 } | 1664 } |
1544 | 1665 |
1545 | 1666 |
1546 void Simulator::LoadStorePairHelper(Instruction* instr, | 1667 void Simulator::LoadStorePairHelper(Instruction* instr, |
1547 AddrMode addrmode) { | 1668 AddrMode addrmode) { |
1548 unsigned rt = instr->Rt(); | 1669 unsigned rt = instr->Rt(); |
1549 unsigned rt2 = instr->Rt2(); | 1670 unsigned rt2 = instr->Rt2(); |
1550 unsigned addr_reg = instr->Rn(); | 1671 unsigned addr_reg = instr->Rn(); |
1551 int offset = instr->ImmLSPair() << instr->SizeLSPair(); | 1672 size_t access_size = 1 << instr->SizeLSPair(); |
1552 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); | 1673 int64_t offset = instr->ImmLSPair() * access_size; |
1553 uint8_t* stack = NULL; | 1674 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode); |
| 1675 uintptr_t address2 = address + access_size; |
| 1676 uintptr_t stack = 0; |
1554 | 1677 |
1555 // Handle the writeback for stores before the store. On a CPU the writeback | 1678 // Handle the writeback for stores before the store. On a CPU the writeback |
1556 // and the store are atomic, but when running on the simulator it is possible | 1679 // and the store are atomic, but when running on the simulator it is possible |
1557 // to be interrupted in between. The simulator is not thread safe and V8 does | 1680 // to be interrupted in between. The simulator is not thread safe and V8 does |
1558 // not require it to be to run JavaScript therefore the profiler may sample | 1681 // not require it to be to run JavaScript therefore the profiler may sample |
1559 // the "simulated" CPU in the middle of load/store with writeback. The code | 1682 // the "simulated" CPU in the middle of load/store with writeback. The code |
1560 // below ensures that push operations are safe even when interrupted: the | 1683 // below ensures that push operations are safe even when interrupted: the |
1561 // stack pointer will be decremented before adding an element to the stack. | 1684 // stack pointer will be decremented before adding an element to the stack. |
1562 if (instr->IsStore()) { | 1685 if (instr->IsStore()) { |
1563 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1686 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1564 | 1687 |
1565 // For store the address post writeback is used to check access below the | 1688 // For store the address post writeback is used to check access below the |
1566 // stack. | 1689 // stack. |
1567 stack = reinterpret_cast<uint8_t*>(sp()); | 1690 stack = sp(); |
1568 } | 1691 } |
1569 | 1692 |
1570 LoadStorePairOp op = | 1693 LoadStorePairOp op = |
1571 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); | 1694 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); |
1572 | 1695 |
1573 // 'rt' and 'rt2' can only be aliased for stores. | 1696 // 'rt' and 'rt2' can only be aliased for stores. |
1574 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); | 1697 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); |
1575 | 1698 |
1576 switch (op) { | 1699 switch (op) { |
| 1700 // Use _no_log variants to suppress the register trace (LOG_REGS, |
| 1701 // LOG_FP_REGS). We will print a more detailed log. |
1577 case LDP_w: { | 1702 case LDP_w: { |
1578 set_wreg(rt, MemoryRead<uint32_t>(address)); | 1703 DCHECK(access_size == kWRegSize); |
1579 set_wreg(rt2, MemoryRead<uint32_t>(address + kWRegSize)); | 1704 set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); |
| 1705 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2)); |
1580 break; | 1706 break; |
1581 } | 1707 } |
1582 case LDP_s: { | 1708 case LDP_s: { |
1583 set_sreg(rt, MemoryRead<float>(address)); | 1709 DCHECK(access_size == kSRegSize); |
1584 set_sreg(rt2, MemoryRead<float>(address + kSRegSize)); | 1710 set_sreg_no_log(rt, MemoryRead<float>(address)); |
| 1711 set_sreg_no_log(rt2, MemoryRead<float>(address2)); |
1585 break; | 1712 break; |
1586 } | 1713 } |
1587 case LDP_x: { | 1714 case LDP_x: { |
1588 set_xreg(rt, MemoryRead<uint64_t>(address)); | 1715 DCHECK(access_size == kXRegSize); |
1589 set_xreg(rt2, MemoryRead<uint64_t>(address + kXRegSize)); | 1716 set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); |
| 1717 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2)); |
1590 break; | 1718 break; |
1591 } | 1719 } |
1592 case LDP_d: { | 1720 case LDP_d: { |
1593 set_dreg(rt, MemoryRead<double>(address)); | 1721 DCHECK(access_size == kDRegSize); |
1594 set_dreg(rt2, MemoryRead<double>(address + kDRegSize)); | 1722 set_dreg_no_log(rt, MemoryRead<double>(address)); |
| 1723 set_dreg_no_log(rt2, MemoryRead<double>(address2)); |
1595 break; | 1724 break; |
1596 } | 1725 } |
1597 case LDPSW_x: { | 1726 case LDPSW_x: { |
1598 set_xreg(rt, MemoryRead<int32_t>(address)); | 1727 DCHECK(access_size == kWRegSize); |
1599 set_xreg(rt2, MemoryRead<int32_t>(address + kWRegSize)); | 1728 set_xreg_no_log(rt, MemoryRead<int32_t>(address)); |
| 1729 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2)); |
1600 break; | 1730 break; |
1601 } | 1731 } |
1602 case STP_w: { | 1732 case STP_w: { |
| 1733 DCHECK(access_size == kWRegSize); |
1603 MemoryWrite<uint32_t>(address, wreg(rt)); | 1734 MemoryWrite<uint32_t>(address, wreg(rt)); |
1604 MemoryWrite<uint32_t>(address + kWRegSize, wreg(rt2)); | 1735 MemoryWrite<uint32_t>(address2, wreg(rt2)); |
1605 break; | 1736 break; |
1606 } | 1737 } |
1607 case STP_s: { | 1738 case STP_s: { |
| 1739 DCHECK(access_size == kSRegSize); |
1608 MemoryWrite<float>(address, sreg(rt)); | 1740 MemoryWrite<float>(address, sreg(rt)); |
1609 MemoryWrite<float>(address + kSRegSize, sreg(rt2)); | 1741 MemoryWrite<float>(address2, sreg(rt2)); |
1610 break; | 1742 break; |
1611 } | 1743 } |
1612 case STP_x: { | 1744 case STP_x: { |
| 1745 DCHECK(access_size == kXRegSize); |
1613 MemoryWrite<uint64_t>(address, xreg(rt)); | 1746 MemoryWrite<uint64_t>(address, xreg(rt)); |
1614 MemoryWrite<uint64_t>(address + kXRegSize, xreg(rt2)); | 1747 MemoryWrite<uint64_t>(address2, xreg(rt2)); |
1615 break; | 1748 break; |
1616 } | 1749 } |
1617 case STP_d: { | 1750 case STP_d: { |
| 1751 DCHECK(access_size == kDRegSize); |
1618 MemoryWrite<double>(address, dreg(rt)); | 1752 MemoryWrite<double>(address, dreg(rt)); |
1619 MemoryWrite<double>(address + kDRegSize, dreg(rt2)); | 1753 MemoryWrite<double>(address2, dreg(rt2)); |
1620 break; | 1754 break; |
1621 } | 1755 } |
1622 default: UNREACHABLE(); | 1756 default: UNREACHABLE(); |
1623 } | 1757 } |
1624 | 1758 |
| 1759 // Print a detailed trace (including the memory address) instead of the basic |
| 1760 // register:value trace generated by set_*reg(). |
| 1761 if (instr->IsLoad()) { |
| 1762 if ((op == LDP_s) || (op == LDP_d)) { |
| 1763 LogReadFP(address, access_size, rt); |
| 1764 LogReadFP(address2, access_size, rt2); |
| 1765 } else { |
| 1766 LogRead(address, access_size, rt); |
| 1767 LogRead(address2, access_size, rt2); |
| 1768 } |
| 1769 } else { |
| 1770 if ((op == STP_s) || (op == STP_d)) { |
| 1771 LogWriteFP(address, access_size, rt); |
| 1772 LogWriteFP(address2, access_size, rt2); |
| 1773 } else { |
| 1774 LogWrite(address, access_size, rt); |
| 1775 LogWrite(address2, access_size, rt2); |
| 1776 } |
| 1777 } |
| 1778 |
1625 // Handle the writeback for loads after the load to ensure safe pop | 1779 // Handle the writeback for loads after the load to ensure safe pop |
1626 // operation even when interrupted in the middle of it. The stack pointer | 1780 // operation even when interrupted in the middle of it. The stack pointer |
1627 // is only updated after the load so pop(fp) will never break the invariant | 1781 // is only updated after the load so pop(fp) will never break the invariant |
1628 // sp <= fp expected while walking the stack in the sampler. | 1782 // sp <= fp expected while walking the stack in the sampler. |
1629 if (instr->IsLoad()) { | 1783 if (instr->IsLoad()) { |
1630 // For loads the address pre writeback is used to check access below the | 1784 // For loads the address pre writeback is used to check access below the |
1631 // stack. | 1785 // stack. |
1632 stack = reinterpret_cast<uint8_t*>(sp()); | 1786 stack = sp(); |
1633 | 1787 |
1634 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1788 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1635 } | 1789 } |
1636 | 1790 |
1637 // Accesses below the stack pointer (but above the platform stack limit) are | 1791 // Accesses below the stack pointer (but above the platform stack limit) are |
1638 // not allowed in the ABI. | 1792 // not allowed in the ABI. |
1639 CheckMemoryAccess(address, stack); | 1793 CheckMemoryAccess(address, stack); |
1640 } | 1794 } |
1641 | 1795 |
1642 | 1796 |
1643 void Simulator::VisitLoadLiteral(Instruction* instr) { | 1797 void Simulator::VisitLoadLiteral(Instruction* instr) { |
1644 uint8_t* address = instr->LiteralAddress(); | 1798 uintptr_t address = instr->LiteralAddress(); |
1645 unsigned rt = instr->Rt(); | 1799 unsigned rt = instr->Rt(); |
1646 | 1800 |
1647 switch (instr->Mask(LoadLiteralMask)) { | 1801 switch (instr->Mask(LoadLiteralMask)) { |
1648 case LDR_w_lit: set_wreg(rt, MemoryRead<uint32_t>(address)); break; | 1802 // Use _no_log variants to suppress the register trace (LOG_REGS, |
1649 case LDR_x_lit: set_xreg(rt, MemoryRead<uint64_t>(address)); break; | 1803 // LOG_FP_REGS), then print a more detailed log. |
1650 case LDR_s_lit: set_sreg(rt, MemoryRead<float>(address)); break; | 1804 case LDR_w_lit: |
1651 case LDR_d_lit: set_dreg(rt, MemoryRead<double>(address)); break; | 1805 set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); |
| 1806 LogRead(address, kWRegSize, rt); |
| 1807 break; |
| 1808 case LDR_x_lit: |
| 1809 set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); |
| 1810 LogRead(address, kXRegSize, rt); |
| 1811 break; |
| 1812 case LDR_s_lit: |
| 1813 set_sreg_no_log(rt, MemoryRead<float>(address)); |
| 1814 LogReadFP(address, kSRegSize, rt); |
| 1815 break; |
| 1816 case LDR_d_lit: |
| 1817 set_dreg_no_log(rt, MemoryRead<double>(address)); |
| 1818 LogReadFP(address, kDRegSize, rt); |
| 1819 break; |
1652 default: UNREACHABLE(); | 1820 default: UNREACHABLE(); |
1653 } | 1821 } |
1654 } | 1822 } |
1655 | 1823 |
1656 | 1824 |
1657 uint8_t* Simulator::LoadStoreAddress(unsigned addr_reg, | 1825 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset, |
1658 int64_t offset, | 1826 AddrMode addrmode) { |
1659 AddrMode addrmode) { | |
1660 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; | 1827 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; |
1661 int64_t address = xreg(addr_reg, Reg31IsStackPointer); | 1828 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); |
1662 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) { | 1829 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) { |
1663 // When the base register is SP the stack pointer is required to be | 1830 // When the base register is SP the stack pointer is required to be |
1664 // quadword aligned prior to the address calculation and write-backs. | 1831 // quadword aligned prior to the address calculation and write-backs. |
1665 // Misalignment will cause a stack alignment fault. | 1832 // Misalignment will cause a stack alignment fault. |
1666 FATAL("ALIGNMENT EXCEPTION"); | 1833 FATAL("ALIGNMENT EXCEPTION"); |
1667 } | 1834 } |
1668 | 1835 |
1669 if ((addrmode == Offset) || (addrmode == PreIndex)) { | 1836 if ((addrmode == Offset) || (addrmode == PreIndex)) { |
1670 address += offset; | 1837 address += offset; |
1671 } | 1838 } |
1672 | 1839 |
1673 return reinterpret_cast<uint8_t*>(address); | 1840 return address; |
1674 } | 1841 } |
1675 | 1842 |
1676 | 1843 |
1677 void Simulator::LoadStoreWriteBack(unsigned addr_reg, | 1844 void Simulator::LoadStoreWriteBack(unsigned addr_reg, |
1678 int64_t offset, | 1845 int64_t offset, |
1679 AddrMode addrmode) { | 1846 AddrMode addrmode) { |
1680 if ((addrmode == PreIndex) || (addrmode == PostIndex)) { | 1847 if ((addrmode == PreIndex) || (addrmode == PostIndex)) { |
1681 DCHECK(offset != 0); | 1848 DCHECK(offset != 0); |
1682 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); | 1849 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); |
1683 set_reg(addr_reg, address + offset, Reg31IsStackPointer); | 1850 set_reg(addr_reg, address + offset, Reg31IsStackPointer); |
1684 } | 1851 } |
1685 } | 1852 } |
1686 | 1853 |
1687 | 1854 |
1688 void Simulator::CheckMemoryAccess(uint8_t* address, uint8_t* stack) { | 1855 void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) { |
1689 if ((address >= stack_limit_) && (address < stack)) { | 1856 if ((address >= stack_limit_) && (address < stack)) { |
1690 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); | 1857 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); |
1691 fprintf(stream_, " sp is here: 0x%16p\n", stack); | 1858 fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n", stack); |
1692 fprintf(stream_, " access was here: 0x%16p\n", address); | 1859 fprintf(stream_, " access was here: 0x%016" PRIx64 "\n", address); |
1693 fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_); | 1860 fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n", stack_limit_); |
1694 fprintf(stream_, "\n"); | 1861 fprintf(stream_, "\n"); |
1695 FATAL("ACCESS BELOW STACK POINTER"); | 1862 FATAL("ACCESS BELOW STACK POINTER"); |
1696 } | 1863 } |
1697 } | 1864 } |
1698 | 1865 |
1699 | 1866 |
1700 void Simulator::VisitMoveWideImmediate(Instruction* instr) { | 1867 void Simulator::VisitMoveWideImmediate(Instruction* instr) { |
1701 MoveWideImmediateOp mov_op = | 1868 MoveWideImmediateOp mov_op = |
1702 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); | 1869 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); |
1703 int64_t new_xn_val = 0; | 1870 int64_t new_xn_val = 0; |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2238 case FCCMP_d: { | 2405 case FCCMP_d: { |
2239 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { | 2406 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { |
2240 // If the condition passes, set the status flags to the result of | 2407 // If the condition passes, set the status flags to the result of |
2241 // comparing the operands. | 2408 // comparing the operands. |
2242 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits | 2409 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits |
2243 : kSRegSizeInBits; | 2410 : kSRegSizeInBits; |
2244 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); | 2411 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); |
2245 } else { | 2412 } else { |
2246 // If the condition fails, set the status flags to the nzcv immediate. | 2413 // If the condition fails, set the status flags to the nzcv immediate. |
2247 nzcv().SetFlags(instr->Nzcv()); | 2414 nzcv().SetFlags(instr->Nzcv()); |
| 2415 LogSystemRegister(NZCV); |
2248 } | 2416 } |
2249 break; | 2417 break; |
2250 } | 2418 } |
2251 default: UNIMPLEMENTED(); | 2419 default: UNIMPLEMENTED(); |
2252 } | 2420 } |
2253 } | 2421 } |
2254 | 2422 |
2255 | 2423 |
2256 void Simulator::VisitFPConditionalSelect(Instruction* instr) { | 2424 void Simulator::VisitFPConditionalSelect(Instruction* instr) { |
2257 AssertSupportedFPCR(); | 2425 AssertSupportedFPCR(); |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3020 case MRS: { | 3188 case MRS: { |
3021 switch (instr->ImmSystemRegister()) { | 3189 switch (instr->ImmSystemRegister()) { |
3022 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; | 3190 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; |
3023 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; | 3191 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; |
3024 default: UNIMPLEMENTED(); | 3192 default: UNIMPLEMENTED(); |
3025 } | 3193 } |
3026 break; | 3194 break; |
3027 } | 3195 } |
3028 case MSR: { | 3196 case MSR: { |
3029 switch (instr->ImmSystemRegister()) { | 3197 switch (instr->ImmSystemRegister()) { |
3030 case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break; | 3198 case NZCV: |
3031 case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break; | 3199 nzcv().SetRawValue(xreg(instr->Rt())); |
| 3200 LogSystemRegister(NZCV); |
| 3201 break; |
| 3202 case FPCR: |
| 3203 fpcr().SetRawValue(xreg(instr->Rt())); |
| 3204 LogSystemRegister(FPCR); |
| 3205 break; |
3032 default: UNIMPLEMENTED(); | 3206 default: UNIMPLEMENTED(); |
3033 } | 3207 } |
3034 break; | 3208 break; |
3035 } | 3209 } |
3036 } | 3210 } |
3037 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { | 3211 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { |
3038 DCHECK(instr->Mask(SystemHintMask) == HINT); | 3212 DCHECK(instr->Mask(SystemHintMask) == HINT); |
3039 switch (instr->ImmHint()) { | 3213 switch (instr->ImmHint()) { |
3040 case NOP: break; | 3214 case NOP: break; |
3041 default: UNIMPLEMENTED(); | 3215 default: UNIMPLEMENTED(); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3232 | 3406 |
3233 // Disassemble. | 3407 // Disassemble. |
3234 PrintInstructionsAt(reinterpret_cast<Instruction*>(address), | 3408 PrintInstructionsAt(reinterpret_cast<Instruction*>(address), |
3235 n_of_instrs_to_disasm); | 3409 n_of_instrs_to_disasm); |
3236 PrintF("\n"); | 3410 PrintF("\n"); |
3237 | 3411 |
3238 // print / p ------------------------------------------------------------- | 3412 // print / p ------------------------------------------------------------- |
3239 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) { | 3413 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) { |
3240 if (argc == 2) { | 3414 if (argc == 2) { |
3241 if (strcmp(arg1, "all") == 0) { | 3415 if (strcmp(arg1, "all") == 0) { |
3242 PrintRegisters(true); | 3416 PrintRegisters(); |
3243 PrintFPRegisters(true); | 3417 PrintFPRegisters(); |
3244 } else { | 3418 } else { |
3245 if (!PrintValue(arg1)) { | 3419 if (!PrintValue(arg1)) { |
3246 PrintF("%s unrecognized\n", arg1); | 3420 PrintF("%s unrecognized\n", arg1); |
3247 } | 3421 } |
3248 } | 3422 } |
3249 } else { | 3423 } else { |
3250 PrintF( | 3424 PrintF( |
3251 "print <register>\n" | 3425 "print <register>\n" |
3252 " Print the content of a register. (alias 'p')\n" | 3426 " Print the content of a register. (alias 'p')\n" |
3253 " 'print all' will print all registers.\n" | 3427 " 'print all' will print all registers.\n" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3437 char const *message = | 3611 char const *message = |
3438 reinterpret_cast<char const*>( | 3612 reinterpret_cast<char const*>( |
3439 pc_->InstructionAtOffset(kDebugMessageOffset)); | 3613 pc_->InstructionAtOffset(kDebugMessageOffset)); |
3440 | 3614 |
3441 // Always print something when we hit a debug point that breaks. | 3615 // Always print something when we hit a debug point that breaks. |
3442 // We are going to break, so printing something is not an issue in | 3616 // We are going to break, so printing something is not an issue in |
3443 // terms of speed. | 3617 // terms of speed. |
3444 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) { | 3618 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) { |
3445 if (message != NULL) { | 3619 if (message != NULL) { |
3446 PrintF(stream_, | 3620 PrintF(stream_, |
3447 "%sDebugger hit %d: %s%s%s\n", | 3621 "# %sDebugger hit %d: %s%s%s\n", |
3448 clr_debug_number, | 3622 clr_debug_number, |
3449 code, | 3623 code, |
3450 clr_debug_message, | 3624 clr_debug_message, |
3451 message, | 3625 message, |
3452 clr_normal); | 3626 clr_normal); |
3453 } else { | 3627 } else { |
3454 PrintF(stream_, | 3628 PrintF(stream_, |
3455 "%sDebugger hit %d.%s\n", | 3629 "# %sDebugger hit %d.%s\n", |
3456 clr_debug_number, | 3630 clr_debug_number, |
3457 code, | 3631 code, |
3458 clr_normal); | 3632 clr_normal); |
3459 } | 3633 } |
3460 } | 3634 } |
3461 | 3635 |
3462 // Other options. | 3636 // Other options. |
3463 switch (parameters & kDebuggerTracingDirectivesMask) { | 3637 switch (parameters & kDebuggerTracingDirectivesMask) { |
3464 case TRACE_ENABLE: | 3638 case TRACE_ENABLE: |
3465 set_log_parameters(log_parameters() | parameters); | 3639 set_log_parameters(log_parameters() | parameters); |
3466 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); } | 3640 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); } |
3467 if (parameters & LOG_REGS) { PrintRegisters(); } | 3641 if (parameters & LOG_REGS) { PrintRegisters(); } |
3468 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); } | 3642 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); } |
3469 break; | 3643 break; |
3470 case TRACE_DISABLE: | 3644 case TRACE_DISABLE: |
3471 set_log_parameters(log_parameters() & ~parameters); | 3645 set_log_parameters(log_parameters() & ~parameters); |
3472 break; | 3646 break; |
3473 case TRACE_OVERRIDE: | 3647 case TRACE_OVERRIDE: |
3474 set_log_parameters(parameters); | 3648 set_log_parameters(parameters); |
3475 break; | 3649 break; |
3476 default: | 3650 default: |
3477 // We don't support a one-shot LOG_DISASM. | 3651 // We don't support a one-shot LOG_DISASM. |
3478 DCHECK((parameters & LOG_DISASM) == 0); | 3652 DCHECK((parameters & LOG_DISASM) == 0); |
3479 // Don't print information that is already being traced. | 3653 // Don't print information that is already being traced. |
3480 parameters &= ~log_parameters(); | 3654 parameters &= ~log_parameters(); |
3481 // Print the requested information. | 3655 // Print the requested information. |
3482 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true); | 3656 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(); |
3483 if (parameters & LOG_REGS) PrintRegisters(true); | 3657 if (parameters & LOG_REGS) PrintRegisters(); |
3484 if (parameters & LOG_FP_REGS) PrintFPRegisters(true); | 3658 if (parameters & LOG_FP_REGS) PrintFPRegisters(); |
3485 } | 3659 } |
3486 | 3660 |
3487 // The stop parameters are inlined in the code. Skip them: | 3661 // The stop parameters are inlined in the code. Skip them: |
3488 // - Skip to the end of the message string. | 3662 // - Skip to the end of the message string. |
3489 size_t size = kDebugMessageOffset + strlen(message) + 1; | 3663 size_t size = kDebugMessageOffset + strlen(message) + 1; |
3490 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize)); | 3664 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize)); |
3491 // - Verify that the unreachable marker is present. | 3665 // - Verify that the unreachable marker is present. |
3492 DCHECK(pc_->Mask(ExceptionMask) == HLT); | 3666 DCHECK(pc_->Mask(ExceptionMask) == HLT); |
3493 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable); | 3667 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable); |
3494 // - Skip past the unreachable marker. | 3668 // - Skip past the unreachable marker. |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3643 | 3817 |
3644 delete[] format; | 3818 delete[] format; |
3645 } | 3819 } |
3646 | 3820 |
3647 | 3821 |
3648 #endif // USE_SIMULATOR | 3822 #endif // USE_SIMULATOR |
3649 | 3823 |
3650 } } // namespace v8::internal | 3824 } } // namespace v8::internal |
3651 | 3825 |
3652 #endif // V8_TARGET_ARCH_ARM64 | 3826 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |