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); |
769 // If the code represents the stack pointer, index the name after zr. | 768 // If the code represents the stack pointer, index the name after zr. |
770 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { | 769 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { |
771 code = kZeroRegCode + 1; | 770 code = kZeroRegCode + 1; |
772 } | 771 } |
773 return wreg_names[code]; | 772 // Using basic pointer arithmetic (instead of an array index) avoids an |
| 773 // erroneous GCC warning about an out-of-bounds array index. |
| 774 return *(wreg_names + code); |
774 } | 775 } |
775 | 776 |
776 | 777 |
777 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { | 778 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { |
| 779 STATIC_ASSERT(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1)); |
778 DCHECK(code < kNumberOfRegisters); | 780 DCHECK(code < kNumberOfRegisters); |
779 // If the code represents the stack pointer, index the name after zr. | 781 // If the code represents the stack pointer, index the name after zr. |
780 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { | 782 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { |
781 code = kZeroRegCode + 1; | 783 code = kZeroRegCode + 1; |
782 } | 784 } |
783 return xreg_names[code]; | 785 return *(xreg_names + code); |
784 } | 786 } |
785 | 787 |
786 | 788 |
787 const char* Simulator::SRegNameForCode(unsigned code) { | 789 const char* Simulator::SRegNameForCode(unsigned code) { |
| 790 STATIC_ASSERT(arraysize(Simulator::sreg_names) == kNumberOfFPRegisters); |
788 DCHECK(code < kNumberOfFPRegisters); | 791 DCHECK(code < kNumberOfFPRegisters); |
789 return sreg_names[code]; | 792 return *(sreg_names + code); |
790 } | 793 } |
791 | 794 |
792 | 795 |
793 const char* Simulator::DRegNameForCode(unsigned code) { | 796 const char* Simulator::DRegNameForCode(unsigned code) { |
| 797 STATIC_ASSERT(arraysize(Simulator::dreg_names) == kNumberOfFPRegisters); |
794 DCHECK(code < kNumberOfFPRegisters); | 798 DCHECK(code < kNumberOfFPRegisters); |
795 return dreg_names[code]; | 799 return *(dreg_names + code); |
796 } | 800 } |
797 | 801 |
798 | 802 |
799 const char* Simulator::VRegNameForCode(unsigned code) { | 803 const char* Simulator::VRegNameForCode(unsigned code) { |
| 804 STATIC_ASSERT(arraysize(Simulator::vreg_names) == kNumberOfFPRegisters); |
800 DCHECK(code < kNumberOfFPRegisters); | 805 DCHECK(code < kNumberOfFPRegisters); |
801 return vreg_names[code]; | 806 return *(vreg_names + code); |
802 } | 807 } |
803 | 808 |
804 | 809 |
805 int Simulator::CodeFromName(const char* name) { | 810 int Simulator::CodeFromName(const char* name) { |
806 for (unsigned i = 0; i < kNumberOfRegisters; i++) { | 811 for (unsigned i = 0; i < kNumberOfRegisters; i++) { |
807 if ((strcmp(xreg_names[i], name) == 0) || | 812 if ((strcmp(xreg_names[i], name) == 0) || |
808 (strcmp(wreg_names[i], name) == 0)) { | 813 (strcmp(wreg_names[i], name) == 0)) { |
809 return i; | 814 return i; |
810 } | 815 } |
811 } | 816 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); | 853 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); |
849 | 854 |
850 N = CalcNFlag(result); | 855 N = CalcNFlag(result); |
851 Z = CalcZFlag(result); | 856 Z = CalcZFlag(result); |
852 | 857 |
853 if (set_flags) { | 858 if (set_flags) { |
854 nzcv().SetN(N); | 859 nzcv().SetN(N); |
855 nzcv().SetZ(Z); | 860 nzcv().SetZ(Z); |
856 nzcv().SetC(C); | 861 nzcv().SetC(C); |
857 nzcv().SetV(V); | 862 nzcv().SetV(V); |
| 863 LogSystemRegister(NZCV); |
858 } | 864 } |
859 return result; | 865 return result; |
860 } | 866 } |
861 | 867 |
862 | 868 |
863 template<typename T> | 869 template<typename T> |
864 void Simulator::AddSubWithCarry(Instruction* instr) { | 870 void Simulator::AddSubWithCarry(Instruction* instr) { |
865 T op2 = reg<T>(instr->Rm()); | 871 T op2 = reg<T>(instr->Rm()); |
866 T new_val; | 872 T new_val; |
867 | 873 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 nzcv().SetRawValue(FPUnorderedFlag); | 977 nzcv().SetRawValue(FPUnorderedFlag); |
972 } else if (val0 < val1) { | 978 } else if (val0 < val1) { |
973 nzcv().SetRawValue(FPLessThanFlag); | 979 nzcv().SetRawValue(FPLessThanFlag); |
974 } else if (val0 > val1) { | 980 } else if (val0 > val1) { |
975 nzcv().SetRawValue(FPGreaterThanFlag); | 981 nzcv().SetRawValue(FPGreaterThanFlag); |
976 } else if (val0 == val1) { | 982 } else if (val0 == val1) { |
977 nzcv().SetRawValue(FPEqualFlag); | 983 nzcv().SetRawValue(FPEqualFlag); |
978 } else { | 984 } else { |
979 UNREACHABLE(); | 985 UNREACHABLE(); |
980 } | 986 } |
| 987 LogSystemRegister(NZCV); |
981 } | 988 } |
982 | 989 |
983 | 990 |
984 void Simulator::SetBreakpoint(Instruction* location) { | 991 void Simulator::SetBreakpoint(Instruction* location) { |
985 for (unsigned i = 0; i < breakpoints_.size(); i++) { | 992 for (unsigned i = 0; i < breakpoints_.size(); i++) { |
986 if (breakpoints_.at(i).location == location) { | 993 if (breakpoints_.at(i).location == location) { |
987 PrintF(stream_, | 994 PrintF(stream_, |
988 "Existing breakpoint at %p was %s\n", | 995 "Existing breakpoint at %p was %s\n", |
989 reinterpret_cast<void*>(location), | 996 reinterpret_cast<void*>(location), |
990 breakpoints_.at(i).enabled ? "disabled" : "enabled"); | 997 breakpoints_.at(i).enabled ? "disabled" : "enabled"); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 | 1044 |
1038 | 1045 |
1039 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { | 1046 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { |
1040 Instruction* end = start->InstructionAtOffset(count * kInstructionSize); | 1047 Instruction* end = start->InstructionAtOffset(count * kInstructionSize); |
1041 for (Instruction* pc = start; pc < end; pc = pc->following()) { | 1048 for (Instruction* pc = start; pc < end; pc = pc->following()) { |
1042 disassembler_decoder_->Decode(pc); | 1049 disassembler_decoder_->Decode(pc); |
1043 } | 1050 } |
1044 } | 1051 } |
1045 | 1052 |
1046 | 1053 |
1047 void Simulator::PrintSystemRegisters(bool print_all) { | 1054 void Simulator::PrintSystemRegisters() { |
1048 static bool first_run = true; | 1055 PrintSystemRegister(NZCV); |
1049 | 1056 PrintSystemRegister(FPCR); |
1050 static SimSystemRegister last_nzcv; | 1057 } |
1051 if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) { | 1058 |
1052 fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n", | 1059 |
1053 clr_flag_name, | 1060 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++) { | 1061 for (unsigned i = 0; i < kNumberOfRegisters; i++) { |
1086 if (print_all_regs || first_run || | 1062 PrintRegister(i); |
1087 (last_regs[i] != xreg(i, Reg31IsStackPointer))) { | 1063 } |
| 1064 } |
| 1065 |
| 1066 |
| 1067 void Simulator::PrintFPRegisters() { |
| 1068 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { |
| 1069 PrintFPRegister(i); |
| 1070 } |
| 1071 } |
| 1072 |
| 1073 |
| 1074 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) { |
| 1075 // Don't print writes into xzr. |
| 1076 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) { |
| 1077 return; |
| 1078 } |
| 1079 |
| 1080 // The template is "# x<code>:value". |
| 1081 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s\n", |
| 1082 clr_reg_name, XRegNameForCode(code, r31mode), |
| 1083 clr_reg_value, reg<uint64_t>(code, r31mode), clr_normal); |
| 1084 } |
| 1085 |
| 1086 |
| 1087 void Simulator::PrintFPRegister(unsigned code, PrintFPRegisterSizes sizes) { |
| 1088 // The template is "# v<code>:bits (d<code>:value, ...)". |
| 1089 |
| 1090 DCHECK(sizes != 0); |
| 1091 DCHECK((sizes & kPrintAllFPRegValues) == sizes); |
| 1092 |
| 1093 // Print the raw bits. |
| 1094 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (", |
| 1095 clr_fpreg_name, VRegNameForCode(code), |
| 1096 clr_fpreg_value, fpreg<uint64_t>(code), clr_normal); |
| 1097 |
| 1098 // Print all requested value interpretations. |
| 1099 bool need_separator = false; |
| 1100 if (sizes & kPrintDRegValue) { |
| 1101 fprintf(stream_, "%s%s%s: %s%g%s", |
| 1102 need_separator ? ", " : "", |
| 1103 clr_fpreg_name, DRegNameForCode(code), |
| 1104 clr_fpreg_value, fpreg<double>(code), clr_normal); |
| 1105 need_separator = true; |
| 1106 } |
| 1107 |
| 1108 if (sizes & kPrintSRegValue) { |
| 1109 fprintf(stream_, "%s%s%s: %s%g%s", |
| 1110 need_separator ? ", " : "", |
| 1111 clr_fpreg_name, SRegNameForCode(code), |
| 1112 clr_fpreg_value, fpreg<float>(code), clr_normal); |
| 1113 need_separator = true; |
| 1114 } |
| 1115 |
| 1116 // End the value list. |
| 1117 fprintf(stream_, ")\n"); |
| 1118 } |
| 1119 |
| 1120 |
| 1121 void Simulator::PrintSystemRegister(SystemRegister id) { |
| 1122 switch (id) { |
| 1123 case NZCV: |
| 1124 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n", |
| 1125 clr_flag_name, clr_flag_value, |
| 1126 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(), |
| 1127 clr_normal); |
| 1128 break; |
| 1129 case FPCR: { |
| 1130 static const char * rmode[] = { |
| 1131 "0b00 (Round to Nearest)", |
| 1132 "0b01 (Round towards Plus Infinity)", |
| 1133 "0b10 (Round towards Minus Infinity)", |
| 1134 "0b11 (Round towards Zero)" |
| 1135 }; |
| 1136 DCHECK(fpcr().RMode() < arraysize(rmode)); |
1088 fprintf(stream_, | 1137 fprintf(stream_, |
1089 "# %s%4s:%s 0x%016" PRIx64 "%s\n", | 1138 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n", |
1090 clr_reg_name, | 1139 clr_flag_name, clr_flag_value, |
1091 XRegNameForCode(i, Reg31IsStackPointer), | 1140 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()], |
1092 clr_reg_value, | |
1093 xreg(i, Reg31IsStackPointer), | |
1094 clr_normal); | 1141 clr_normal); |
| 1142 break; |
1095 } | 1143 } |
1096 // Cache the new register value so the next run can detect any changes. | 1144 default: |
1097 last_regs[i] = xreg(i, Reg31IsStackPointer); | 1145 UNREACHABLE(); |
1098 } | 1146 } |
1099 first_run = false; | 1147 } |
1100 } | 1148 |
1101 | 1149 |
1102 | 1150 void Simulator::PrintRead(uintptr_t address, |
1103 void Simulator::PrintFPRegisters(bool print_all_regs) { | 1151 size_t size, |
1104 static bool first_run = true; | 1152 unsigned reg_code) { |
1105 static uint64_t last_regs[kNumberOfFPRegisters]; | 1153 USE(size); // Size is unused here. |
1106 | 1154 |
1107 // Print as many rows of registers as necessary, keeping each individual | 1155 // The template is "# x<code>:value <- address". |
1108 // register in the same column each time (to make it easy to visually scan | 1156 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s", |
1109 // for changes). | 1157 clr_reg_name, XRegNameForCode(reg_code), |
1110 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { | 1158 clr_reg_value, reg<uint64_t>(reg_code), clr_normal); |
1111 if (print_all_regs || first_run || (last_regs[i] != dreg_bits(i))) { | 1159 |
1112 fprintf(stream_, | 1160 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", | 1161 clr_memory_address, address, clr_normal); |
1114 clr_fpreg_name, | 1162 } |
1115 VRegNameForCode(i), | 1163 |
1116 clr_fpreg_value, | 1164 |
1117 dreg_bits(i), | 1165 void Simulator::PrintReadFP(uintptr_t address, |
1118 clr_normal, | 1166 size_t size, |
1119 clr_fpreg_name, | 1167 unsigned reg_code) { |
1120 DRegNameForCode(i), | 1168 // The template is "# reg:bits (reg:value) <- address". |
1121 clr_fpreg_value, | 1169 switch (size) { |
1122 dreg(i), | 1170 case kSRegSize: |
1123 clr_fpreg_name, | 1171 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%gf%s)", |
1124 SRegNameForCode(i), | 1172 clr_fpreg_name, VRegNameForCode(reg_code), |
1125 clr_fpreg_value, | 1173 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, |
1126 sreg(i), | 1174 clr_fpreg_name, SRegNameForCode(reg_code), |
1127 clr_normal); | 1175 clr_fpreg_value, fpreg<float>(reg_code), clr_normal); |
1128 } | 1176 break; |
1129 // Cache the new register value so the next run can detect any changes. | 1177 case kDRegSize: |
1130 last_regs[i] = dreg_bits(i); | 1178 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)", |
1131 } | 1179 clr_fpreg_name, VRegNameForCode(reg_code), |
1132 first_run = false; | 1180 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, |
1133 } | 1181 clr_fpreg_name, DRegNameForCode(reg_code), |
1134 | 1182 clr_fpreg_value, fpreg<double>(reg_code), clr_normal); |
1135 | 1183 break; |
1136 void Simulator::PrintProcessorState() { | 1184 default: |
1137 PrintSystemRegisters(); | 1185 UNREACHABLE(); |
1138 PrintRegisters(); | 1186 } |
1139 PrintFPRegisters(); | 1187 |
1140 } | 1188 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n", |
1141 | 1189 clr_memory_address, address, clr_normal); |
1142 | 1190 } |
1143 void Simulator::PrintWrite(uintptr_t address, uint64_t value, | 1191 |
1144 unsigned num_bytes) { | 1192 |
1145 // The template is "# value -> address". The format string is not used | 1193 void Simulator::PrintWrite(uintptr_t address, |
1146 // directly in the printf because some compilers struggle with the | 1194 size_t size, |
1147 // parametrized width field (%0*). | 1195 unsigned reg_code) { |
1148 const char* format = "# %s0x%0*" PRIx64 "%s -> %s0x%016" PRIxPTR "%s\n"; | 1196 // The template is "# reg:value -> address". To keep the trace tidy and |
1149 fprintf(stream_, | 1197 // readable, the value is aligned with the values in the register trace. |
1150 format, | 1198 switch (size) { |
1151 clr_memory_value, | 1199 case kByteSizeInBytes: |
1152 num_bytes * 2, // The width in hexadecimal characters. | 1200 fprintf(stream_, "# %s%5s<7:0>: %s0x%02" PRIx8 "%s", |
1153 value, | 1201 clr_reg_name, WRegNameForCode(reg_code), |
1154 clr_normal, | 1202 clr_reg_value, reg<uint8_t>(reg_code), clr_normal); |
1155 clr_memory_address, | 1203 break; |
1156 address, | 1204 case kHalfWordSizeInBytes: |
1157 clr_normal); | 1205 fprintf(stream_, "# %s%5s<15:0>: %s0x%04" PRIx16 "%s", |
1158 } | 1206 clr_reg_name, WRegNameForCode(reg_code), |
1159 | 1207 clr_reg_value, reg<uint16_t>(reg_code), clr_normal); |
1160 | 1208 break; |
| 1209 case kWRegSize: |
| 1210 fprintf(stream_, "# %s%5s: %s0x%08" PRIx32 "%s", |
| 1211 clr_reg_name, WRegNameForCode(reg_code), |
| 1212 clr_reg_value, reg<uint32_t>(reg_code), clr_normal); |
| 1213 break; |
| 1214 case kXRegSize: |
| 1215 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s", |
| 1216 clr_reg_name, XRegNameForCode(reg_code), |
| 1217 clr_reg_value, reg<uint64_t>(reg_code), clr_normal); |
| 1218 break; |
| 1219 default: |
| 1220 UNREACHABLE(); |
| 1221 } |
| 1222 |
| 1223 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", |
| 1224 clr_memory_address, address, clr_normal); |
| 1225 } |
| 1226 |
| 1227 |
| 1228 void Simulator::PrintWriteFP(uintptr_t address, |
| 1229 size_t size, |
| 1230 unsigned reg_code) { |
| 1231 // The template is "# reg:bits (reg:value) -> address". To keep the trace tidy |
| 1232 // and readable, the value is aligned with the values in the register trace. |
| 1233 switch (size) { |
| 1234 case kSRegSize: |
| 1235 fprintf(stream_, "# %s%5s<31:0>: %s0x%08" PRIx32 "%s (%s%s: %s%gf%s)", |
| 1236 clr_fpreg_name, VRegNameForCode(reg_code), |
| 1237 clr_fpreg_value, fpreg<uint32_t>(reg_code), clr_normal, |
| 1238 clr_fpreg_name, SRegNameForCode(reg_code), |
| 1239 clr_fpreg_value, fpreg<float>(reg_code), clr_normal); |
| 1240 break; |
| 1241 case kDRegSize: |
| 1242 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)", |
| 1243 clr_fpreg_name, VRegNameForCode(reg_code), |
| 1244 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, |
| 1245 clr_fpreg_name, DRegNameForCode(reg_code), |
| 1246 clr_fpreg_value, fpreg<double>(reg_code), clr_normal); |
| 1247 break; |
| 1248 default: |
| 1249 UNREACHABLE(); |
| 1250 } |
| 1251 |
| 1252 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", |
| 1253 clr_memory_address, address, clr_normal); |
| 1254 } |
| 1255 |
| 1256 |
1161 // Visitors--------------------------------------------------------------------- | 1257 // Visitors--------------------------------------------------------------------- |
1162 | 1258 |
1163 void Simulator::VisitUnimplemented(Instruction* instr) { | 1259 void Simulator::VisitUnimplemented(Instruction* instr) { |
1164 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n", | 1260 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n", |
1165 reinterpret_cast<void*>(instr), instr->InstructionBits()); | 1261 reinterpret_cast<void*>(instr), instr->InstructionBits()); |
1166 UNIMPLEMENTED(); | 1262 UNIMPLEMENTED(); |
1167 } | 1263 } |
1168 | 1264 |
1169 | 1265 |
1170 void Simulator::VisitUnallocated(Instruction* instr) { | 1266 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; | 1472 case EOR: result = op1 ^ op2; break; |
1377 default: | 1473 default: |
1378 UNIMPLEMENTED(); | 1474 UNIMPLEMENTED(); |
1379 } | 1475 } |
1380 | 1476 |
1381 if (update_flags) { | 1477 if (update_flags) { |
1382 nzcv().SetN(CalcNFlag(result)); | 1478 nzcv().SetN(CalcNFlag(result)); |
1383 nzcv().SetZ(CalcZFlag(result)); | 1479 nzcv().SetZ(CalcZFlag(result)); |
1384 nzcv().SetC(0); | 1480 nzcv().SetC(0); |
1385 nzcv().SetV(0); | 1481 nzcv().SetV(0); |
| 1482 LogSystemRegister(NZCV); |
1386 } | 1483 } |
1387 | 1484 |
1388 set_reg<T>(instr->Rd(), result, instr->RdMode()); | 1485 set_reg<T>(instr->Rd(), result, instr->RdMode()); |
1389 } | 1486 } |
1390 | 1487 |
1391 | 1488 |
1392 void Simulator::VisitConditionalCompareRegister(Instruction* instr) { | 1489 void Simulator::VisitConditionalCompareRegister(Instruction* instr) { |
1393 if (instr->SixtyFourBits()) { | 1490 if (instr->SixtyFourBits()) { |
1394 ConditionalCompareHelper(instr, xreg(instr->Rm())); | 1491 ConditionalCompareHelper(instr, xreg(instr->Rm())); |
1395 } else { | 1492 } else { |
(...skipping 20 matching lines...) Expand all Loading... |
1416 // the operands. | 1513 // the operands. |
1417 if (instr->Mask(ConditionalCompareMask) == CCMP) { | 1514 if (instr->Mask(ConditionalCompareMask) == CCMP) { |
1418 AddWithCarry<T>(true, op1, ~op2, 1); | 1515 AddWithCarry<T>(true, op1, ~op2, 1); |
1419 } else { | 1516 } else { |
1420 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN); | 1517 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN); |
1421 AddWithCarry<T>(true, op1, op2, 0); | 1518 AddWithCarry<T>(true, op1, op2, 0); |
1422 } | 1519 } |
1423 } else { | 1520 } else { |
1424 // If the condition fails, set the status flags to the nzcv immediate. | 1521 // If the condition fails, set the status flags to the nzcv immediate. |
1425 nzcv().SetFlags(instr->Nzcv()); | 1522 nzcv().SetFlags(instr->Nzcv()); |
| 1523 LogSystemRegister(NZCV); |
1426 } | 1524 } |
1427 } | 1525 } |
1428 | 1526 |
1429 | 1527 |
1430 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { | 1528 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { |
1431 int offset = instr->ImmLSUnsigned() << instr->SizeLS(); | 1529 int offset = instr->ImmLSUnsigned() << instr->SizeLS(); |
1432 LoadStoreHelper(instr, offset, Offset); | 1530 LoadStoreHelper(instr, offset, Offset); |
1433 } | 1531 } |
1434 | 1532 |
1435 | 1533 |
(...skipping 20 matching lines...) Expand all Loading... |
1456 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount); | 1554 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount); |
1457 LoadStoreHelper(instr, offset, Offset); | 1555 LoadStoreHelper(instr, offset, Offset); |
1458 } | 1556 } |
1459 | 1557 |
1460 | 1558 |
1461 void Simulator::LoadStoreHelper(Instruction* instr, | 1559 void Simulator::LoadStoreHelper(Instruction* instr, |
1462 int64_t offset, | 1560 int64_t offset, |
1463 AddrMode addrmode) { | 1561 AddrMode addrmode) { |
1464 unsigned srcdst = instr->Rt(); | 1562 unsigned srcdst = instr->Rt(); |
1465 unsigned addr_reg = instr->Rn(); | 1563 unsigned addr_reg = instr->Rn(); |
1466 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); | 1564 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode); |
1467 uint8_t* stack = NULL; | 1565 uintptr_t stack = 0; |
1468 | 1566 |
1469 // Handle the writeback for stores before the store. On a CPU the writeback | 1567 // 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 | 1568 // 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 | 1569 // 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 | 1570 // 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 | 1571 // 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 | 1572 // below ensures that push operations are safe even when interrupted: the |
1475 // stack pointer will be decremented before adding an element to the stack. | 1573 // stack pointer will be decremented before adding an element to the stack. |
1476 if (instr->IsStore()) { | 1574 if (instr->IsStore()) { |
1477 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1575 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1478 | 1576 |
1479 // For store the address post writeback is used to check access below the | 1577 // For store the address post writeback is used to check access below the |
1480 // stack. | 1578 // stack. |
1481 stack = reinterpret_cast<uint8_t*>(sp()); | 1579 stack = sp(); |
1482 } | 1580 } |
1483 | 1581 |
1484 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); | 1582 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); |
1485 switch (op) { | 1583 switch (op) { |
1486 case LDRB_w: set_wreg(srcdst, MemoryRead<uint8_t>(address)); break; | 1584 // Use _no_log variants to suppress the register trace (LOG_REGS, |
1487 case LDRH_w: set_wreg(srcdst, MemoryRead<uint16_t>(address)); break; | 1585 // LOG_FP_REGS). We will print a more detailed log. |
1488 case LDR_w: set_wreg(srcdst, MemoryRead<uint32_t>(address)); break; | 1586 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; | 1587 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; | 1588 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; | 1589 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; | 1590 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; | 1591 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; | 1592 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break; |
1495 case LDR_s: set_sreg(srcdst, MemoryRead<float>(address)); break; | 1593 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break; |
1496 case LDR_d: set_dreg(srcdst, MemoryRead<double>(address)); break; | 1594 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break; |
| 1595 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break; |
| 1596 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break; |
1497 | 1597 |
1498 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break; | 1598 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break; |
1499 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break; | 1599 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break; |
1500 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break; | 1600 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break; |
1501 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break; | 1601 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break; |
1502 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break; | 1602 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break; |
1503 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break; | 1603 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break; |
1504 | 1604 |
1505 default: UNIMPLEMENTED(); | 1605 default: UNIMPLEMENTED(); |
1506 } | 1606 } |
1507 | 1607 |
| 1608 // Print a detailed trace (including the memory address) instead of the basic |
| 1609 // register:value trace generated by set_*reg(). |
| 1610 size_t access_size = 1 << instr->SizeLS(); |
| 1611 if (instr->IsLoad()) { |
| 1612 if ((op == LDR_s) || (op == LDR_d)) { |
| 1613 LogReadFP(address, access_size, srcdst); |
| 1614 } else { |
| 1615 LogRead(address, access_size, srcdst); |
| 1616 } |
| 1617 } else { |
| 1618 if ((op == STR_s) || (op == STR_d)) { |
| 1619 LogWriteFP(address, access_size, srcdst); |
| 1620 } else { |
| 1621 LogWrite(address, access_size, srcdst); |
| 1622 } |
| 1623 } |
| 1624 |
1508 // Handle the writeback for loads after the load to ensure safe pop | 1625 // 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 | 1626 // 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 | 1627 // 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. | 1628 // sp <= fp expected while walking the stack in the sampler. |
1512 if (instr->IsLoad()) { | 1629 if (instr->IsLoad()) { |
1513 // For loads the address pre writeback is used to check access below the | 1630 // For loads the address pre writeback is used to check access below the |
1514 // stack. | 1631 // stack. |
1515 stack = reinterpret_cast<uint8_t*>(sp()); | 1632 stack = sp(); |
1516 | 1633 |
1517 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1634 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1518 } | 1635 } |
1519 | 1636 |
1520 // Accesses below the stack pointer (but above the platform stack limit) are | 1637 // Accesses below the stack pointer (but above the platform stack limit) are |
1521 // not allowed in the ABI. | 1638 // not allowed in the ABI. |
1522 CheckMemoryAccess(address, stack); | 1639 CheckMemoryAccess(address, stack); |
1523 } | 1640 } |
1524 | 1641 |
1525 | 1642 |
(...skipping 15 matching lines...) Expand all Loading... |
1541 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) { | 1658 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) { |
1542 LoadStorePairHelper(instr, Offset); | 1659 LoadStorePairHelper(instr, Offset); |
1543 } | 1660 } |
1544 | 1661 |
1545 | 1662 |
1546 void Simulator::LoadStorePairHelper(Instruction* instr, | 1663 void Simulator::LoadStorePairHelper(Instruction* instr, |
1547 AddrMode addrmode) { | 1664 AddrMode addrmode) { |
1548 unsigned rt = instr->Rt(); | 1665 unsigned rt = instr->Rt(); |
1549 unsigned rt2 = instr->Rt2(); | 1666 unsigned rt2 = instr->Rt2(); |
1550 unsigned addr_reg = instr->Rn(); | 1667 unsigned addr_reg = instr->Rn(); |
1551 int offset = instr->ImmLSPair() << instr->SizeLSPair(); | 1668 size_t access_size = 1 << instr->SizeLSPair(); |
1552 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); | 1669 int64_t offset = instr->ImmLSPair() * access_size; |
1553 uint8_t* stack = NULL; | 1670 uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode); |
| 1671 uintptr_t address2 = address + access_size; |
| 1672 uintptr_t stack = 0; |
1554 | 1673 |
1555 // Handle the writeback for stores before the store. On a CPU the writeback | 1674 // 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 | 1675 // 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 | 1676 // 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 | 1677 // 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 | 1678 // 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 | 1679 // below ensures that push operations are safe even when interrupted: the |
1561 // stack pointer will be decremented before adding an element to the stack. | 1680 // stack pointer will be decremented before adding an element to the stack. |
1562 if (instr->IsStore()) { | 1681 if (instr->IsStore()) { |
1563 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1682 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1564 | 1683 |
1565 // For store the address post writeback is used to check access below the | 1684 // For store the address post writeback is used to check access below the |
1566 // stack. | 1685 // stack. |
1567 stack = reinterpret_cast<uint8_t*>(sp()); | 1686 stack = sp(); |
1568 } | 1687 } |
1569 | 1688 |
1570 LoadStorePairOp op = | 1689 LoadStorePairOp op = |
1571 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); | 1690 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); |
1572 | 1691 |
1573 // 'rt' and 'rt2' can only be aliased for stores. | 1692 // 'rt' and 'rt2' can only be aliased for stores. |
1574 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); | 1693 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); |
1575 | 1694 |
1576 switch (op) { | 1695 switch (op) { |
| 1696 // Use _no_log variants to suppress the register trace (LOG_REGS, |
| 1697 // LOG_FP_REGS). We will print a more detailed log. |
1577 case LDP_w: { | 1698 case LDP_w: { |
1578 set_wreg(rt, MemoryRead<uint32_t>(address)); | 1699 DCHECK(access_size == kWRegSize); |
1579 set_wreg(rt2, MemoryRead<uint32_t>(address + kWRegSize)); | 1700 set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); |
| 1701 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2)); |
1580 break; | 1702 break; |
1581 } | 1703 } |
1582 case LDP_s: { | 1704 case LDP_s: { |
1583 set_sreg(rt, MemoryRead<float>(address)); | 1705 DCHECK(access_size == kSRegSize); |
1584 set_sreg(rt2, MemoryRead<float>(address + kSRegSize)); | 1706 set_sreg_no_log(rt, MemoryRead<float>(address)); |
| 1707 set_sreg_no_log(rt2, MemoryRead<float>(address2)); |
1585 break; | 1708 break; |
1586 } | 1709 } |
1587 case LDP_x: { | 1710 case LDP_x: { |
1588 set_xreg(rt, MemoryRead<uint64_t>(address)); | 1711 DCHECK(access_size == kXRegSize); |
1589 set_xreg(rt2, MemoryRead<uint64_t>(address + kXRegSize)); | 1712 set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); |
| 1713 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2)); |
1590 break; | 1714 break; |
1591 } | 1715 } |
1592 case LDP_d: { | 1716 case LDP_d: { |
1593 set_dreg(rt, MemoryRead<double>(address)); | 1717 DCHECK(access_size == kDRegSize); |
1594 set_dreg(rt2, MemoryRead<double>(address + kDRegSize)); | 1718 set_dreg_no_log(rt, MemoryRead<double>(address)); |
| 1719 set_dreg_no_log(rt2, MemoryRead<double>(address2)); |
1595 break; | 1720 break; |
1596 } | 1721 } |
1597 case LDPSW_x: { | 1722 case LDPSW_x: { |
1598 set_xreg(rt, MemoryRead<int32_t>(address)); | 1723 DCHECK(access_size == kWRegSize); |
1599 set_xreg(rt2, MemoryRead<int32_t>(address + kWRegSize)); | 1724 set_xreg_no_log(rt, MemoryRead<int32_t>(address)); |
| 1725 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2)); |
1600 break; | 1726 break; |
1601 } | 1727 } |
1602 case STP_w: { | 1728 case STP_w: { |
| 1729 DCHECK(access_size == kWRegSize); |
1603 MemoryWrite<uint32_t>(address, wreg(rt)); | 1730 MemoryWrite<uint32_t>(address, wreg(rt)); |
1604 MemoryWrite<uint32_t>(address + kWRegSize, wreg(rt2)); | 1731 MemoryWrite<uint32_t>(address2, wreg(rt2)); |
1605 break; | 1732 break; |
1606 } | 1733 } |
1607 case STP_s: { | 1734 case STP_s: { |
| 1735 DCHECK(access_size == kSRegSize); |
1608 MemoryWrite<float>(address, sreg(rt)); | 1736 MemoryWrite<float>(address, sreg(rt)); |
1609 MemoryWrite<float>(address + kSRegSize, sreg(rt2)); | 1737 MemoryWrite<float>(address2, sreg(rt2)); |
1610 break; | 1738 break; |
1611 } | 1739 } |
1612 case STP_x: { | 1740 case STP_x: { |
| 1741 DCHECK(access_size == kXRegSize); |
1613 MemoryWrite<uint64_t>(address, xreg(rt)); | 1742 MemoryWrite<uint64_t>(address, xreg(rt)); |
1614 MemoryWrite<uint64_t>(address + kXRegSize, xreg(rt2)); | 1743 MemoryWrite<uint64_t>(address2, xreg(rt2)); |
1615 break; | 1744 break; |
1616 } | 1745 } |
1617 case STP_d: { | 1746 case STP_d: { |
| 1747 DCHECK(access_size == kDRegSize); |
1618 MemoryWrite<double>(address, dreg(rt)); | 1748 MemoryWrite<double>(address, dreg(rt)); |
1619 MemoryWrite<double>(address + kDRegSize, dreg(rt2)); | 1749 MemoryWrite<double>(address2, dreg(rt2)); |
1620 break; | 1750 break; |
1621 } | 1751 } |
1622 default: UNREACHABLE(); | 1752 default: UNREACHABLE(); |
1623 } | 1753 } |
1624 | 1754 |
| 1755 // Print a detailed trace (including the memory address) instead of the basic |
| 1756 // register:value trace generated by set_*reg(). |
| 1757 if (instr->IsLoad()) { |
| 1758 if ((op == LDP_s) || (op == LDP_d)) { |
| 1759 LogReadFP(address, access_size, rt); |
| 1760 LogReadFP(address2, access_size, rt2); |
| 1761 } else { |
| 1762 LogRead(address, access_size, rt); |
| 1763 LogRead(address2, access_size, rt2); |
| 1764 } |
| 1765 } else { |
| 1766 if ((op == STP_s) || (op == STP_d)) { |
| 1767 LogWriteFP(address, access_size, rt); |
| 1768 LogWriteFP(address2, access_size, rt2); |
| 1769 } else { |
| 1770 LogWrite(address, access_size, rt); |
| 1771 LogWrite(address2, access_size, rt2); |
| 1772 } |
| 1773 } |
| 1774 |
1625 // Handle the writeback for loads after the load to ensure safe pop | 1775 // 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 | 1776 // 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 | 1777 // 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. | 1778 // sp <= fp expected while walking the stack in the sampler. |
1629 if (instr->IsLoad()) { | 1779 if (instr->IsLoad()) { |
1630 // For loads the address pre writeback is used to check access below the | 1780 // For loads the address pre writeback is used to check access below the |
1631 // stack. | 1781 // stack. |
1632 stack = reinterpret_cast<uint8_t*>(sp()); | 1782 stack = sp(); |
1633 | 1783 |
1634 LoadStoreWriteBack(addr_reg, offset, addrmode); | 1784 LoadStoreWriteBack(addr_reg, offset, addrmode); |
1635 } | 1785 } |
1636 | 1786 |
1637 // Accesses below the stack pointer (but above the platform stack limit) are | 1787 // Accesses below the stack pointer (but above the platform stack limit) are |
1638 // not allowed in the ABI. | 1788 // not allowed in the ABI. |
1639 CheckMemoryAccess(address, stack); | 1789 CheckMemoryAccess(address, stack); |
1640 } | 1790 } |
1641 | 1791 |
1642 | 1792 |
1643 void Simulator::VisitLoadLiteral(Instruction* instr) { | 1793 void Simulator::VisitLoadLiteral(Instruction* instr) { |
1644 uint8_t* address = instr->LiteralAddress(); | 1794 uintptr_t address = instr->LiteralAddress(); |
1645 unsigned rt = instr->Rt(); | 1795 unsigned rt = instr->Rt(); |
1646 | 1796 |
1647 switch (instr->Mask(LoadLiteralMask)) { | 1797 switch (instr->Mask(LoadLiteralMask)) { |
1648 case LDR_w_lit: set_wreg(rt, MemoryRead<uint32_t>(address)); break; | 1798 // Use _no_log variants to suppress the register trace (LOG_REGS, |
1649 case LDR_x_lit: set_xreg(rt, MemoryRead<uint64_t>(address)); break; | 1799 // LOG_FP_REGS), then print a more detailed log. |
1650 case LDR_s_lit: set_sreg(rt, MemoryRead<float>(address)); break; | 1800 case LDR_w_lit: |
1651 case LDR_d_lit: set_dreg(rt, MemoryRead<double>(address)); break; | 1801 set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); |
| 1802 LogRead(address, kWRegSize, rt); |
| 1803 break; |
| 1804 case LDR_x_lit: |
| 1805 set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); |
| 1806 LogRead(address, kXRegSize, rt); |
| 1807 break; |
| 1808 case LDR_s_lit: |
| 1809 set_sreg_no_log(rt, MemoryRead<float>(address)); |
| 1810 LogReadFP(address, kSRegSize, rt); |
| 1811 break; |
| 1812 case LDR_d_lit: |
| 1813 set_dreg_no_log(rt, MemoryRead<double>(address)); |
| 1814 LogReadFP(address, kDRegSize, rt); |
| 1815 break; |
1652 default: UNREACHABLE(); | 1816 default: UNREACHABLE(); |
1653 } | 1817 } |
1654 } | 1818 } |
1655 | 1819 |
1656 | 1820 |
1657 uint8_t* Simulator::LoadStoreAddress(unsigned addr_reg, | 1821 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset, |
1658 int64_t offset, | 1822 AddrMode addrmode) { |
1659 AddrMode addrmode) { | |
1660 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; | 1823 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; |
1661 int64_t address = xreg(addr_reg, Reg31IsStackPointer); | 1824 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); |
1662 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) { | 1825 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) { |
1663 // When the base register is SP the stack pointer is required to be | 1826 // When the base register is SP the stack pointer is required to be |
1664 // quadword aligned prior to the address calculation and write-backs. | 1827 // quadword aligned prior to the address calculation and write-backs. |
1665 // Misalignment will cause a stack alignment fault. | 1828 // Misalignment will cause a stack alignment fault. |
1666 FATAL("ALIGNMENT EXCEPTION"); | 1829 FATAL("ALIGNMENT EXCEPTION"); |
1667 } | 1830 } |
1668 | 1831 |
1669 if ((addrmode == Offset) || (addrmode == PreIndex)) { | 1832 if ((addrmode == Offset) || (addrmode == PreIndex)) { |
1670 address += offset; | 1833 address += offset; |
1671 } | 1834 } |
1672 | 1835 |
1673 return reinterpret_cast<uint8_t*>(address); | 1836 return address; |
1674 } | 1837 } |
1675 | 1838 |
1676 | 1839 |
1677 void Simulator::LoadStoreWriteBack(unsigned addr_reg, | 1840 void Simulator::LoadStoreWriteBack(unsigned addr_reg, |
1678 int64_t offset, | 1841 int64_t offset, |
1679 AddrMode addrmode) { | 1842 AddrMode addrmode) { |
1680 if ((addrmode == PreIndex) || (addrmode == PostIndex)) { | 1843 if ((addrmode == PreIndex) || (addrmode == PostIndex)) { |
1681 DCHECK(offset != 0); | 1844 DCHECK(offset != 0); |
1682 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); | 1845 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); |
1683 set_reg(addr_reg, address + offset, Reg31IsStackPointer); | 1846 set_reg(addr_reg, address + offset, Reg31IsStackPointer); |
1684 } | 1847 } |
1685 } | 1848 } |
1686 | 1849 |
1687 | 1850 |
1688 void Simulator::CheckMemoryAccess(uint8_t* address, uint8_t* stack) { | 1851 void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) { |
1689 if ((address >= stack_limit_) && (address < stack)) { | 1852 if ((address >= stack_limit_) && (address < stack)) { |
1690 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); | 1853 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); |
1691 fprintf(stream_, " sp is here: 0x%16p\n", stack); | 1854 fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n", stack); |
1692 fprintf(stream_, " access was here: 0x%16p\n", address); | 1855 fprintf(stream_, " access was here: 0x%016" PRIx64 "\n", address); |
1693 fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_); | 1856 fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n", stack_limit_); |
1694 fprintf(stream_, "\n"); | 1857 fprintf(stream_, "\n"); |
1695 FATAL("ACCESS BELOW STACK POINTER"); | 1858 FATAL("ACCESS BELOW STACK POINTER"); |
1696 } | 1859 } |
1697 } | 1860 } |
1698 | 1861 |
1699 | 1862 |
1700 void Simulator::VisitMoveWideImmediate(Instruction* instr) { | 1863 void Simulator::VisitMoveWideImmediate(Instruction* instr) { |
1701 MoveWideImmediateOp mov_op = | 1864 MoveWideImmediateOp mov_op = |
1702 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); | 1865 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); |
1703 int64_t new_xn_val = 0; | 1866 int64_t new_xn_val = 0; |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2238 case FCCMP_d: { | 2401 case FCCMP_d: { |
2239 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { | 2402 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { |
2240 // If the condition passes, set the status flags to the result of | 2403 // If the condition passes, set the status flags to the result of |
2241 // comparing the operands. | 2404 // comparing the operands. |
2242 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits | 2405 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits |
2243 : kSRegSizeInBits; | 2406 : kSRegSizeInBits; |
2244 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); | 2407 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); |
2245 } else { | 2408 } else { |
2246 // If the condition fails, set the status flags to the nzcv immediate. | 2409 // If the condition fails, set the status flags to the nzcv immediate. |
2247 nzcv().SetFlags(instr->Nzcv()); | 2410 nzcv().SetFlags(instr->Nzcv()); |
| 2411 LogSystemRegister(NZCV); |
2248 } | 2412 } |
2249 break; | 2413 break; |
2250 } | 2414 } |
2251 default: UNIMPLEMENTED(); | 2415 default: UNIMPLEMENTED(); |
2252 } | 2416 } |
2253 } | 2417 } |
2254 | 2418 |
2255 | 2419 |
2256 void Simulator::VisitFPConditionalSelect(Instruction* instr) { | 2420 void Simulator::VisitFPConditionalSelect(Instruction* instr) { |
2257 AssertSupportedFPCR(); | 2421 AssertSupportedFPCR(); |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3020 case MRS: { | 3184 case MRS: { |
3021 switch (instr->ImmSystemRegister()) { | 3185 switch (instr->ImmSystemRegister()) { |
3022 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; | 3186 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; |
3023 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; | 3187 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; |
3024 default: UNIMPLEMENTED(); | 3188 default: UNIMPLEMENTED(); |
3025 } | 3189 } |
3026 break; | 3190 break; |
3027 } | 3191 } |
3028 case MSR: { | 3192 case MSR: { |
3029 switch (instr->ImmSystemRegister()) { | 3193 switch (instr->ImmSystemRegister()) { |
3030 case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break; | 3194 case NZCV: |
3031 case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break; | 3195 nzcv().SetRawValue(xreg(instr->Rt())); |
| 3196 LogSystemRegister(NZCV); |
| 3197 break; |
| 3198 case FPCR: |
| 3199 fpcr().SetRawValue(xreg(instr->Rt())); |
| 3200 LogSystemRegister(FPCR); |
| 3201 break; |
3032 default: UNIMPLEMENTED(); | 3202 default: UNIMPLEMENTED(); |
3033 } | 3203 } |
3034 break; | 3204 break; |
3035 } | 3205 } |
3036 } | 3206 } |
3037 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { | 3207 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { |
3038 DCHECK(instr->Mask(SystemHintMask) == HINT); | 3208 DCHECK(instr->Mask(SystemHintMask) == HINT); |
3039 switch (instr->ImmHint()) { | 3209 switch (instr->ImmHint()) { |
3040 case NOP: break; | 3210 case NOP: break; |
3041 default: UNIMPLEMENTED(); | 3211 default: UNIMPLEMENTED(); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3232 | 3402 |
3233 // Disassemble. | 3403 // Disassemble. |
3234 PrintInstructionsAt(reinterpret_cast<Instruction*>(address), | 3404 PrintInstructionsAt(reinterpret_cast<Instruction*>(address), |
3235 n_of_instrs_to_disasm); | 3405 n_of_instrs_to_disasm); |
3236 PrintF("\n"); | 3406 PrintF("\n"); |
3237 | 3407 |
3238 // print / p ------------------------------------------------------------- | 3408 // print / p ------------------------------------------------------------- |
3239 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) { | 3409 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) { |
3240 if (argc == 2) { | 3410 if (argc == 2) { |
3241 if (strcmp(arg1, "all") == 0) { | 3411 if (strcmp(arg1, "all") == 0) { |
3242 PrintRegisters(true); | 3412 PrintRegisters(); |
3243 PrintFPRegisters(true); | 3413 PrintFPRegisters(); |
3244 } else { | 3414 } else { |
3245 if (!PrintValue(arg1)) { | 3415 if (!PrintValue(arg1)) { |
3246 PrintF("%s unrecognized\n", arg1); | 3416 PrintF("%s unrecognized\n", arg1); |
3247 } | 3417 } |
3248 } | 3418 } |
3249 } else { | 3419 } else { |
3250 PrintF( | 3420 PrintF( |
3251 "print <register>\n" | 3421 "print <register>\n" |
3252 " Print the content of a register. (alias 'p')\n" | 3422 " Print the content of a register. (alias 'p')\n" |
3253 " 'print all' will print all registers.\n" | 3423 " 'print all' will print all registers.\n" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3437 char const *message = | 3607 char const *message = |
3438 reinterpret_cast<char const*>( | 3608 reinterpret_cast<char const*>( |
3439 pc_->InstructionAtOffset(kDebugMessageOffset)); | 3609 pc_->InstructionAtOffset(kDebugMessageOffset)); |
3440 | 3610 |
3441 // Always print something when we hit a debug point that breaks. | 3611 // 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 | 3612 // We are going to break, so printing something is not an issue in |
3443 // terms of speed. | 3613 // terms of speed. |
3444 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) { | 3614 if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) { |
3445 if (message != NULL) { | 3615 if (message != NULL) { |
3446 PrintF(stream_, | 3616 PrintF(stream_, |
3447 "%sDebugger hit %d: %s%s%s\n", | 3617 "# %sDebugger hit %d: %s%s%s\n", |
3448 clr_debug_number, | 3618 clr_debug_number, |
3449 code, | 3619 code, |
3450 clr_debug_message, | 3620 clr_debug_message, |
3451 message, | 3621 message, |
3452 clr_normal); | 3622 clr_normal); |
3453 } else { | 3623 } else { |
3454 PrintF(stream_, | 3624 PrintF(stream_, |
3455 "%sDebugger hit %d.%s\n", | 3625 "# %sDebugger hit %d.%s\n", |
3456 clr_debug_number, | 3626 clr_debug_number, |
3457 code, | 3627 code, |
3458 clr_normal); | 3628 clr_normal); |
3459 } | 3629 } |
3460 } | 3630 } |
3461 | 3631 |
3462 // Other options. | 3632 // Other options. |
3463 switch (parameters & kDebuggerTracingDirectivesMask) { | 3633 switch (parameters & kDebuggerTracingDirectivesMask) { |
3464 case TRACE_ENABLE: | 3634 case TRACE_ENABLE: |
3465 set_log_parameters(log_parameters() | parameters); | 3635 set_log_parameters(log_parameters() | parameters); |
3466 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); } | 3636 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); } |
3467 if (parameters & LOG_REGS) { PrintRegisters(); } | 3637 if (parameters & LOG_REGS) { PrintRegisters(); } |
3468 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); } | 3638 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); } |
3469 break; | 3639 break; |
3470 case TRACE_DISABLE: | 3640 case TRACE_DISABLE: |
3471 set_log_parameters(log_parameters() & ~parameters); | 3641 set_log_parameters(log_parameters() & ~parameters); |
3472 break; | 3642 break; |
3473 case TRACE_OVERRIDE: | 3643 case TRACE_OVERRIDE: |
3474 set_log_parameters(parameters); | 3644 set_log_parameters(parameters); |
3475 break; | 3645 break; |
3476 default: | 3646 default: |
3477 // We don't support a one-shot LOG_DISASM. | 3647 // We don't support a one-shot LOG_DISASM. |
3478 DCHECK((parameters & LOG_DISASM) == 0); | 3648 DCHECK((parameters & LOG_DISASM) == 0); |
3479 // Don't print information that is already being traced. | 3649 // Don't print information that is already being traced. |
3480 parameters &= ~log_parameters(); | 3650 parameters &= ~log_parameters(); |
3481 // Print the requested information. | 3651 // Print the requested information. |
3482 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true); | 3652 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(); |
3483 if (parameters & LOG_REGS) PrintRegisters(true); | 3653 if (parameters & LOG_REGS) PrintRegisters(); |
3484 if (parameters & LOG_FP_REGS) PrintFPRegisters(true); | 3654 if (parameters & LOG_FP_REGS) PrintFPRegisters(); |
3485 } | 3655 } |
3486 | 3656 |
3487 // The stop parameters are inlined in the code. Skip them: | 3657 // The stop parameters are inlined in the code. Skip them: |
3488 // - Skip to the end of the message string. | 3658 // - Skip to the end of the message string. |
3489 size_t size = kDebugMessageOffset + strlen(message) + 1; | 3659 size_t size = kDebugMessageOffset + strlen(message) + 1; |
3490 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize)); | 3660 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize)); |
3491 // - Verify that the unreachable marker is present. | 3661 // - Verify that the unreachable marker is present. |
3492 DCHECK(pc_->Mask(ExceptionMask) == HLT); | 3662 DCHECK(pc_->Mask(ExceptionMask) == HLT); |
3493 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable); | 3663 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable); |
3494 // - Skip past the unreachable marker. | 3664 // - Skip past the unreachable marker. |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3643 | 3813 |
3644 delete[] format; | 3814 delete[] format; |
3645 } | 3815 } |
3646 | 3816 |
3647 | 3817 |
3648 #endif // USE_SIMULATOR | 3818 #endif // USE_SIMULATOR |
3649 | 3819 |
3650 } } // namespace v8::internal | 3820 } } // namespace v8::internal |
3651 | 3821 |
3652 #endif // V8_TARGET_ARCH_ARM64 | 3822 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |