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