| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 <stdarg.h> | 5 #include <stdarg.h> |
| 6 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #if V8_TARGET_ARCH_ARM | 9 #if V8_TARGET_ARCH_ARM |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 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 // The ArmDebugger class is used by the simulator while debugging simulated ARM | 31 // The ArmDebugger class is used by the simulator while debugging simulated ARM |
| 32 // code. | 32 // code. |
| 33 class ArmDebugger { | 33 class ArmDebugger { |
| 34 public: | 34 public: |
| 35 explicit ArmDebugger(Simulator* sim) : sim_(sim) { } | 35 explicit ArmDebugger(Simulator* sim) : sim_(sim) { } |
| 36 ~ArmDebugger(); | |
| 37 | 36 |
| 38 void Stop(Instruction* instr); | 37 void Stop(Instruction* instr); |
| 39 void Debug(); | 38 void Debug(); |
| 40 | 39 |
| 41 private: | 40 private: |
| 42 static const Instr kBreakpointInstr = | 41 static const Instr kBreakpointInstr = |
| 43 (al | (7*B25) | (1*B24) | kBreakpoint); | 42 (al | (7*B25) | (1*B24) | kBreakpoint); |
| 44 static const Instr kNopInstr = (al | (13*B21)); | 43 static const Instr kNopInstr = (al | (13*B21)); |
| 45 | 44 |
| 46 Simulator* sim_; | 45 Simulator* sim_; |
| 47 | 46 |
| 48 int32_t GetRegisterValue(int regnum); | 47 int32_t GetRegisterValue(int regnum); |
| 49 double GetRegisterPairDoubleValue(int regnum); | 48 double GetRegisterPairDoubleValue(int regnum); |
| 50 double GetVFPDoubleRegisterValue(int regnum); | 49 double GetVFPDoubleRegisterValue(int regnum); |
| 51 bool GetValue(const char* desc, int32_t* value); | 50 bool GetValue(const char* desc, int32_t* value); |
| 52 bool GetVFPSingleValue(const char* desc, float* value); | 51 bool GetVFPSingleValue(const char* desc, float* value); |
| 53 bool GetVFPDoubleValue(const char* desc, double* value); | 52 bool GetVFPDoubleValue(const char* desc, double* value); |
| 54 | 53 |
| 55 // Set or delete a breakpoint. Returns true if successful. | 54 // Set or delete a breakpoint. Returns true if successful. |
| 56 bool SetBreakpoint(Instruction* breakpc); | 55 bool SetBreakpoint(Instruction* breakpc); |
| 57 bool DeleteBreakpoint(Instruction* breakpc); | 56 bool DeleteBreakpoint(Instruction* breakpc); |
| 58 | 57 |
| 59 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 58 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
| 60 // execution to skip past breakpoints when run from the debugger. | 59 // execution to skip past breakpoints when run from the debugger. |
| 61 void UndoBreakpoints(); | 60 void UndoBreakpoints(); |
| 62 void RedoBreakpoints(); | 61 void RedoBreakpoints(); |
| 63 }; | 62 }; |
| 64 | 63 |
| 65 | |
| 66 ArmDebugger::~ArmDebugger() { | |
| 67 } | |
| 68 | |
| 69 | |
| 70 | |
| 71 #ifdef GENERATED_CODE_COVERAGE | |
| 72 static FILE* coverage_log = NULL; | |
| 73 | |
| 74 | |
| 75 static void InitializeCoverage() { | |
| 76 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | |
| 77 if (file_name != NULL) { | |
| 78 coverage_log = fopen(file_name, "aw+"); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 | |
| 83 void ArmDebugger::Stop(Instruction* instr) { | 64 void ArmDebugger::Stop(Instruction* instr) { |
| 84 // Get the stop code. | 65 // Get the stop code. |
| 85 uint32_t code = instr->SvcValue() & kStopCodeMask; | 66 uint32_t code = instr->SvcValue() & kStopCodeMask; |
| 86 // Retrieve the encoded address, which comes just after this stop. | |
| 87 char** msg_address = | |
| 88 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); | |
| 89 char* msg = *msg_address; | |
| 90 DCHECK(msg != NULL); | |
| 91 | |
| 92 // Update this stop description. | |
| 93 if (isWatchedStop(code) && !watched_stops_[code].desc) { | |
| 94 watched_stops_[code].desc = msg; | |
| 95 } | |
| 96 | |
| 97 if (strlen(msg) > 0) { | |
| 98 if (coverage_log != NULL) { | |
| 99 fprintf(coverage_log, "%s\n", msg); | |
| 100 fflush(coverage_log); | |
| 101 } | |
| 102 // Overwrite the instruction and address with nops. | |
| 103 instr->SetInstructionBits(kNopInstr); | |
| 104 reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr); | |
| 105 } | |
| 106 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); | |
| 107 } | |
| 108 | |
| 109 #else // ndef GENERATED_CODE_COVERAGE | |
| 110 | |
| 111 static void InitializeCoverage() { | |
| 112 } | |
| 113 | |
| 114 | |
| 115 void ArmDebugger::Stop(Instruction* instr) { | |
| 116 // Get the stop code. | |
| 117 uint32_t code = instr->SvcValue() & kStopCodeMask; | |
| 118 // Retrieve the encoded address, which comes just after this stop. | 67 // Retrieve the encoded address, which comes just after this stop. |
| 119 char* msg = *reinterpret_cast<char**>(sim_->get_pc() | 68 char* msg = *reinterpret_cast<char**>(sim_->get_pc() |
| 120 + Instruction::kInstrSize); | 69 + Instruction::kInstrSize); |
| 121 // Update this stop description. | 70 // Update this stop description. |
| 122 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) { | 71 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) { |
| 123 sim_->watched_stops_[code].desc = msg; | 72 sim_->watched_stops_[code].desc = msg; |
| 124 } | 73 } |
| 125 // Print the stop message and code if it is not the default code. | 74 // Print the stop message and code if it is not the default code. |
| 126 if (code != kMaxStopCode) { | 75 if (code != kMaxStopCode) { |
| 127 PrintF("Simulator hit stop %u: %s\n", code, msg); | 76 PrintF("Simulator hit stop %u: %s\n", code, msg); |
| 128 } else { | 77 } else { |
| 129 PrintF("Simulator hit %s\n", msg); | 78 PrintF("Simulator hit %s\n", msg); |
| 130 } | 79 } |
| 131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); | 80 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
| 132 Debug(); | 81 Debug(); |
| 133 } | 82 } |
| 134 #endif | |
| 135 | |
| 136 | 83 |
| 137 int32_t ArmDebugger::GetRegisterValue(int regnum) { | 84 int32_t ArmDebugger::GetRegisterValue(int regnum) { |
| 138 if (regnum == kPCRegister) { | 85 if (regnum == kPCRegister) { |
| 139 return sim_->get_pc(); | 86 return sim_->get_pc(); |
| 140 } else { | 87 } else { |
| 141 return sim_->get_register(regnum); | 88 return sim_->get_register(regnum); |
| 142 } | 89 } |
| 143 } | 90 } |
| 144 | 91 |
| 145 | |
| 146 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) { | 92 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) { |
| 147 return sim_->get_double_from_register_pair(regnum); | 93 return sim_->get_double_from_register_pair(regnum); |
| 148 } | 94 } |
| 149 | 95 |
| 150 | 96 |
| 151 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { | 97 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { |
| 152 return sim_->get_double_from_d_register(regnum); | 98 return sim_->get_double_from_d_register(regnum); |
| 153 } | 99 } |
| 154 | 100 |
| 155 | 101 |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 inexact_vfp_flag_ = false; | 703 inexact_vfp_flag_ = false; |
| 758 | 704 |
| 759 // The sp is initialized to point to the bottom (high address) of the | 705 // The sp is initialized to point to the bottom (high address) of the |
| 760 // allocated stack area. To be safe in potential stack underflows we leave | 706 // allocated stack area. To be safe in potential stack underflows we leave |
| 761 // some buffer below. | 707 // some buffer below. |
| 762 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; | 708 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; |
| 763 // The lr and pc are initialized to a known bad value that will cause an | 709 // The lr and pc are initialized to a known bad value that will cause an |
| 764 // access violation if the simulator ever tries to execute it. | 710 // access violation if the simulator ever tries to execute it. |
| 765 registers_[pc] = bad_lr; | 711 registers_[pc] = bad_lr; |
| 766 registers_[lr] = bad_lr; | 712 registers_[lr] = bad_lr; |
| 767 InitializeCoverage(); | |
| 768 | 713 |
| 769 last_debugger_input_ = NULL; | 714 last_debugger_input_ = NULL; |
| 770 } | 715 } |
| 771 | 716 |
| 772 | 717 |
| 773 Simulator::~Simulator() { free(stack_); } | 718 Simulator::~Simulator() { free(stack_); } |
| 774 | 719 |
| 775 | 720 |
| 776 // When the generated code calls an external reference we need to catch that in | 721 // When the generated code calls an external reference we need to catch that in |
| 777 // the simulator. The external reference will be a function compiled for the | 722 // the simulator. The external reference will be a function compiled for the |
| (...skipping 3531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4309 set_register(sp, current_sp + sizeof(uintptr_t)); | 4254 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 4310 return address; | 4255 return address; |
| 4311 } | 4256 } |
| 4312 | 4257 |
| 4313 } // namespace internal | 4258 } // namespace internal |
| 4314 } // namespace v8 | 4259 } // namespace v8 |
| 4315 | 4260 |
| 4316 #endif // USE_SIMULATOR | 4261 #endif // USE_SIMULATOR |
| 4317 | 4262 |
| 4318 #endif // V8_TARGET_ARCH_ARM | 4263 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |