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