| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 // Only build the simulator if not compiling for real ARM hardware. | 42 // Only build the simulator if not compiling for real ARM hardware. |
| 43 namespace v8 { | 43 namespace v8 { |
| 44 namespace internal { | 44 namespace internal { |
| 45 | 45 |
| 46 // This macro provides a platform independent use of sscanf. The reason for | 46 // This macro provides a platform independent use of sscanf. The reason for |
| 47 // SScanF not being implemented in a platform independent way through | 47 // SScanF not being implemented in a platform independent way through |
| 48 // ::v8::internal::OS in the same way as SNPrintF is that the | 48 // ::v8::internal::OS in the same way as SNPrintF is that the |
| 49 // Windows C Run-Time Library does not provide vsscanf. | 49 // Windows C Run-Time Library does not provide vsscanf. |
| 50 #define SScanF sscanf // NOLINT | 50 #define SScanF sscanf // NOLINT |
| 51 | 51 |
| 52 // The Debugger class is used by the simulator while debugging simulated ARM | 52 // The ArmDebugger class is used by the simulator while debugging simulated ARM |
| 53 // code. | 53 // code. |
| 54 class Debugger { | 54 class ArmDebugger { |
| 55 public: | 55 public: |
| 56 explicit Debugger(Simulator* sim); | 56 explicit ArmDebugger(Simulator* sim); |
| 57 ~Debugger(); | 57 ~ArmDebugger(); |
| 58 | 58 |
| 59 void Stop(Instruction* instr); | 59 void Stop(Instruction* instr); |
| 60 void Debug(); | 60 void Debug(); |
| 61 | 61 |
| 62 private: | 62 private: |
| 63 static const Instr kBreakpointInstr = | 63 static const Instr kBreakpointInstr = |
| 64 (al | (7*B25) | (1*B24) | kBreakpoint); | 64 (al | (7*B25) | (1*B24) | kBreakpoint); |
| 65 static const Instr kNopInstr = (al | (13*B21)); | 65 static const Instr kNopInstr = (al | (13*B21)); |
| 66 | 66 |
| 67 Simulator* sim_; | 67 Simulator* sim_; |
| 68 | 68 |
| 69 int32_t GetRegisterValue(int regnum); | 69 int32_t GetRegisterValue(int regnum); |
| 70 double GetVFPDoubleRegisterValue(int regnum); | 70 double GetVFPDoubleRegisterValue(int regnum); |
| 71 bool GetValue(const char* desc, int32_t* value); | 71 bool GetValue(const char* desc, int32_t* value); |
| 72 bool GetVFPSingleValue(const char* desc, float* value); | 72 bool GetVFPSingleValue(const char* desc, float* value); |
| 73 bool GetVFPDoubleValue(const char* desc, double* value); | 73 bool GetVFPDoubleValue(const char* desc, double* value); |
| 74 | 74 |
| 75 // Set or delete a breakpoint. Returns true if successful. | 75 // Set or delete a breakpoint. Returns true if successful. |
| 76 bool SetBreakpoint(Instruction* breakpc); | 76 bool SetBreakpoint(Instruction* breakpc); |
| 77 bool DeleteBreakpoint(Instruction* breakpc); | 77 bool DeleteBreakpoint(Instruction* breakpc); |
| 78 | 78 |
| 79 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 79 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
| 80 // execution to skip past breakpoints when run from the debugger. | 80 // execution to skip past breakpoints when run from the debugger. |
| 81 void UndoBreakpoints(); | 81 void UndoBreakpoints(); |
| 82 void RedoBreakpoints(); | 82 void RedoBreakpoints(); |
| 83 }; | 83 }; |
| 84 | 84 |
| 85 | 85 |
| 86 Debugger::Debugger(Simulator* sim) { | 86 ArmDebugger::ArmDebugger(Simulator* sim) { |
| 87 sim_ = sim; | 87 sim_ = sim; |
| 88 } | 88 } |
| 89 | 89 |
| 90 | 90 |
| 91 Debugger::~Debugger() { | 91 ArmDebugger::~ArmDebugger() { |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 | 95 |
| 96 #ifdef GENERATED_CODE_COVERAGE | 96 #ifdef GENERATED_CODE_COVERAGE |
| 97 static FILE* coverage_log = NULL; | 97 static FILE* coverage_log = NULL; |
| 98 | 98 |
| 99 | 99 |
| 100 static void InitializeCoverage() { | 100 static void InitializeCoverage() { |
| 101 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); | 101 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); |
| 102 if (file_name != NULL) { | 102 if (file_name != NULL) { |
| 103 coverage_log = fopen(file_name, "aw+"); | 103 coverage_log = fopen(file_name, "aw+"); |
| 104 } | 104 } |
| 105 } | 105 } |
| 106 | 106 |
| 107 | 107 |
| 108 void Debugger::Stop(Instruction* instr) { | 108 void ArmDebugger::Stop(Instruction* instr) { |
| 109 // Get the stop code. | 109 // Get the stop code. |
| 110 uint32_t code = instr->SvcValue() & kStopCodeMask; | 110 uint32_t code = instr->SvcValue() & kStopCodeMask; |
| 111 // Retrieve the encoded address, which comes just after this stop. | 111 // Retrieve the encoded address, which comes just after this stop. |
| 112 char** msg_address = | 112 char** msg_address = |
| 113 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); | 113 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); |
| 114 char* msg = *msg_address; | 114 char* msg = *msg_address; |
| 115 ASSERT(msg != NULL); | 115 ASSERT(msg != NULL); |
| 116 | 116 |
| 117 // Update this stop description. | 117 // Update this stop description. |
| 118 if (isWatchedStop(code) && !watched_stops[code].desc) { | 118 if (isWatchedStop(code) && !watched_stops[code].desc) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 130 } | 130 } |
| 131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); | 131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
| 132 } | 132 } |
| 133 | 133 |
| 134 #else // ndef GENERATED_CODE_COVERAGE | 134 #else // ndef GENERATED_CODE_COVERAGE |
| 135 | 135 |
| 136 static void InitializeCoverage() { | 136 static void InitializeCoverage() { |
| 137 } | 137 } |
| 138 | 138 |
| 139 | 139 |
| 140 void Debugger::Stop(Instruction* instr) { | 140 void ArmDebugger::Stop(Instruction* instr) { |
| 141 // Get the stop code. | 141 // Get the stop code. |
| 142 uint32_t code = instr->SvcValue() & kStopCodeMask; | 142 uint32_t code = instr->SvcValue() & kStopCodeMask; |
| 143 // Retrieve the encoded address, which comes just after this stop. | 143 // Retrieve the encoded address, which comes just after this stop. |
| 144 char* msg = *reinterpret_cast<char**>(sim_->get_pc() | 144 char* msg = *reinterpret_cast<char**>(sim_->get_pc() |
| 145 + Instruction::kInstrSize); | 145 + Instruction::kInstrSize); |
| 146 // Update this stop description. | 146 // Update this stop description. |
| 147 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) { | 147 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) { |
| 148 sim_->watched_stops[code].desc = msg; | 148 sim_->watched_stops[code].desc = msg; |
| 149 } | 149 } |
| 150 // Print the stop message and code if it is not the default code. | 150 // Print the stop message and code if it is not the default code. |
| 151 if (code != kMaxStopCode) { | 151 if (code != kMaxStopCode) { |
| 152 PrintF("Simulator hit stop %u: %s\n", code, msg); | 152 PrintF("Simulator hit stop %u: %s\n", code, msg); |
| 153 } else { | 153 } else { |
| 154 PrintF("Simulator hit %s\n", msg); | 154 PrintF("Simulator hit %s\n", msg); |
| 155 } | 155 } |
| 156 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); | 156 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); |
| 157 Debug(); | 157 Debug(); |
| 158 } | 158 } |
| 159 #endif | 159 #endif |
| 160 | 160 |
| 161 | 161 |
| 162 int32_t Debugger::GetRegisterValue(int regnum) { | 162 int32_t ArmDebugger::GetRegisterValue(int regnum) { |
| 163 if (regnum == kPCRegister) { | 163 if (regnum == kPCRegister) { |
| 164 return sim_->get_pc(); | 164 return sim_->get_pc(); |
| 165 } else { | 165 } else { |
| 166 return sim_->get_register(regnum); | 166 return sim_->get_register(regnum); |
| 167 } | 167 } |
| 168 } | 168 } |
| 169 | 169 |
| 170 | 170 |
| 171 double Debugger::GetVFPDoubleRegisterValue(int regnum) { | 171 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) { |
| 172 return sim_->get_double_from_d_register(regnum); | 172 return sim_->get_double_from_d_register(regnum); |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 bool Debugger::GetValue(const char* desc, int32_t* value) { | 176 bool ArmDebugger::GetValue(const char* desc, int32_t* value) { |
| 177 int regnum = Registers::Number(desc); | 177 int regnum = Registers::Number(desc); |
| 178 if (regnum != kNoRegister) { | 178 if (regnum != kNoRegister) { |
| 179 *value = GetRegisterValue(regnum); | 179 *value = GetRegisterValue(regnum); |
| 180 return true; | 180 return true; |
| 181 } else { | 181 } else { |
| 182 if (strncmp(desc, "0x", 2) == 0) { | 182 if (strncmp(desc, "0x", 2) == 0) { |
| 183 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1; | 183 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1; |
| 184 } else { | 184 } else { |
| 185 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1; | 185 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1; |
| 186 } | 186 } |
| 187 } | 187 } |
| 188 return false; | 188 return false; |
| 189 } | 189 } |
| 190 | 190 |
| 191 | 191 |
| 192 bool Debugger::GetVFPSingleValue(const char* desc, float* value) { | 192 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) { |
| 193 bool is_double; | 193 bool is_double; |
| 194 int regnum = VFPRegisters::Number(desc, &is_double); | 194 int regnum = VFPRegisters::Number(desc, &is_double); |
| 195 if (regnum != kNoRegister && !is_double) { | 195 if (regnum != kNoRegister && !is_double) { |
| 196 *value = sim_->get_float_from_s_register(regnum); | 196 *value = sim_->get_float_from_s_register(regnum); |
| 197 return true; | 197 return true; |
| 198 } | 198 } |
| 199 return false; | 199 return false; |
| 200 } | 200 } |
| 201 | 201 |
| 202 | 202 |
| 203 bool Debugger::GetVFPDoubleValue(const char* desc, double* value) { | 203 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) { |
| 204 bool is_double; | 204 bool is_double; |
| 205 int regnum = VFPRegisters::Number(desc, &is_double); | 205 int regnum = VFPRegisters::Number(desc, &is_double); |
| 206 if (regnum != kNoRegister && is_double) { | 206 if (regnum != kNoRegister && is_double) { |
| 207 *value = sim_->get_double_from_d_register(regnum); | 207 *value = sim_->get_double_from_d_register(regnum); |
| 208 return true; | 208 return true; |
| 209 } | 209 } |
| 210 return false; | 210 return false; |
| 211 } | 211 } |
| 212 | 212 |
| 213 | 213 |
| 214 bool Debugger::SetBreakpoint(Instruction* breakpc) { | 214 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) { |
| 215 // Check if a breakpoint can be set. If not return without any side-effects. | 215 // Check if a breakpoint can be set. If not return without any side-effects. |
| 216 if (sim_->break_pc_ != NULL) { | 216 if (sim_->break_pc_ != NULL) { |
| 217 return false; | 217 return false; |
| 218 } | 218 } |
| 219 | 219 |
| 220 // Set the breakpoint. | 220 // Set the breakpoint. |
| 221 sim_->break_pc_ = breakpc; | 221 sim_->break_pc_ = breakpc; |
| 222 sim_->break_instr_ = breakpc->InstructionBits(); | 222 sim_->break_instr_ = breakpc->InstructionBits(); |
| 223 // Not setting the breakpoint instruction in the code itself. It will be set | 223 // Not setting the breakpoint instruction in the code itself. It will be set |
| 224 // when the debugger shell continues. | 224 // when the debugger shell continues. |
| 225 return true; | 225 return true; |
| 226 } | 226 } |
| 227 | 227 |
| 228 | 228 |
| 229 bool Debugger::DeleteBreakpoint(Instruction* breakpc) { | 229 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) { |
| 230 if (sim_->break_pc_ != NULL) { | 230 if (sim_->break_pc_ != NULL) { |
| 231 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 231 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
| 232 } | 232 } |
| 233 | 233 |
| 234 sim_->break_pc_ = NULL; | 234 sim_->break_pc_ = NULL; |
| 235 sim_->break_instr_ = 0; | 235 sim_->break_instr_ = 0; |
| 236 return true; | 236 return true; |
| 237 } | 237 } |
| 238 | 238 |
| 239 | 239 |
| 240 void Debugger::UndoBreakpoints() { | 240 void ArmDebugger::UndoBreakpoints() { |
| 241 if (sim_->break_pc_ != NULL) { | 241 if (sim_->break_pc_ != NULL) { |
| 242 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 242 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
| 243 } | 243 } |
| 244 } | 244 } |
| 245 | 245 |
| 246 | 246 |
| 247 void Debugger::RedoBreakpoints() { | 247 void ArmDebugger::RedoBreakpoints() { |
| 248 if (sim_->break_pc_ != NULL) { | 248 if (sim_->break_pc_ != NULL) { |
| 249 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); | 249 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); |
| 250 } | 250 } |
| 251 } | 251 } |
| 252 | 252 |
| 253 | 253 |
| 254 void Debugger::Debug() { | 254 void ArmDebugger::Debug() { |
| 255 intptr_t last_pc = -1; | 255 intptr_t last_pc = -1; |
| 256 bool done = false; | 256 bool done = false; |
| 257 | 257 |
| 258 #define COMMAND_SIZE 63 | 258 #define COMMAND_SIZE 63 |
| 259 #define ARG_SIZE 255 | 259 #define ARG_SIZE 255 |
| 260 | 260 |
| 261 #define STR(a) #a | 261 #define STR(a) #a |
| 262 #define XSTR(a) STR(a) | 262 #define XSTR(a) STR(a) |
| 263 | 263 |
| 264 char cmd[COMMAND_SIZE + 1]; | 264 char cmd[COMMAND_SIZE + 1]; |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 PrintF(" set a break point on the address\n"); | 532 PrintF(" set a break point on the address\n"); |
| 533 PrintF("del\n"); | 533 PrintF("del\n"); |
| 534 PrintF(" delete the breakpoint\n"); | 534 PrintF(" delete the breakpoint\n"); |
| 535 PrintF("trace (alias 't')\n"); | 535 PrintF("trace (alias 't')\n"); |
| 536 PrintF(" toogle the tracing of all executed statements\n"); | 536 PrintF(" toogle the tracing of all executed statements\n"); |
| 537 PrintF("stop feature:\n"); | 537 PrintF("stop feature:\n"); |
| 538 PrintF(" Description:\n"); | 538 PrintF(" Description:\n"); |
| 539 PrintF(" Stops are debug instructions inserted by\n"); | 539 PrintF(" Stops are debug instructions inserted by\n"); |
| 540 PrintF(" the Assembler::stop() function.\n"); | 540 PrintF(" the Assembler::stop() function.\n"); |
| 541 PrintF(" When hitting a stop, the Simulator will\n"); | 541 PrintF(" When hitting a stop, the Simulator will\n"); |
| 542 PrintF(" stop and and give control to the Debugger.\n"); | 542 PrintF(" stop and and give control to the ArmDebugger.\n"); |
| 543 PrintF(" The first %d stop codes are watched:\n", | 543 PrintF(" The first %d stop codes are watched:\n", |
| 544 Simulator::kNumOfWatchedStops); | 544 Simulator::kNumOfWatchedStops); |
| 545 PrintF(" - They can be enabled / disabled: the Simulator\n"); | 545 PrintF(" - They can be enabled / disabled: the Simulator\n"); |
| 546 PrintF(" will / won't stop when hitting them.\n"); | 546 PrintF(" will / won't stop when hitting them.\n"); |
| 547 PrintF(" - The Simulator keeps track of how many times they \n"); | 547 PrintF(" - The Simulator keeps track of how many times they \n"); |
| 548 PrintF(" are met. (See the info command.) Going over a\n"); | 548 PrintF(" are met. (See the info command.) Going over a\n"); |
| 549 PrintF(" disabled stop still increases its counter. \n"); | 549 PrintF(" disabled stop still increases its counter. \n"); |
| 550 PrintF(" Commands:\n"); | 550 PrintF(" Commands:\n"); |
| 551 PrintF(" stop info all/<code> : print infos about number <code>\n"); | 551 PrintF(" stop info all/<code> : print infos about number <code>\n"); |
| 552 PrintF(" or all stop(s).\n"); | 552 PrintF(" or all stop(s).\n"); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 } | 586 } |
| 587 | 587 |
| 588 | 588 |
| 589 static bool AllOnOnePage(uintptr_t start, int size) { | 589 static bool AllOnOnePage(uintptr_t start, int size) { |
| 590 intptr_t start_page = (start & ~CachePage::kPageMask); | 590 intptr_t start_page = (start & ~CachePage::kPageMask); |
| 591 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); | 591 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); |
| 592 return start_page == end_page; | 592 return start_page == end_page; |
| 593 } | 593 } |
| 594 | 594 |
| 595 | 595 |
| 596 void Simulator::FlushICache(void* start_addr, size_t size) { | 596 void Simulator::FlushICache(v8::internal::HashMap* i_cache, |
| 597 void* start_addr, |
| 598 size_t size) { |
| 597 intptr_t start = reinterpret_cast<intptr_t>(start_addr); | 599 intptr_t start = reinterpret_cast<intptr_t>(start_addr); |
| 598 int intra_line = (start & CachePage::kLineMask); | 600 int intra_line = (start & CachePage::kLineMask); |
| 599 start -= intra_line; | 601 start -= intra_line; |
| 600 size += intra_line; | 602 size += intra_line; |
| 601 size = ((size - 1) | CachePage::kLineMask) + 1; | 603 size = ((size - 1) | CachePage::kLineMask) + 1; |
| 602 int offset = (start & CachePage::kPageMask); | 604 int offset = (start & CachePage::kPageMask); |
| 603 while (!AllOnOnePage(start, size - 1)) { | 605 while (!AllOnOnePage(start, size - 1)) { |
| 604 int bytes_to_flush = CachePage::kPageSize - offset; | 606 int bytes_to_flush = CachePage::kPageSize - offset; |
| 605 FlushOnePage(start, bytes_to_flush); | 607 FlushOnePage(i_cache, start, bytes_to_flush); |
| 606 start += bytes_to_flush; | 608 start += bytes_to_flush; |
| 607 size -= bytes_to_flush; | 609 size -= bytes_to_flush; |
| 608 ASSERT_EQ(0, start & CachePage::kPageMask); | 610 ASSERT_EQ(0, start & CachePage::kPageMask); |
| 609 offset = 0; | 611 offset = 0; |
| 610 } | 612 } |
| 611 if (size != 0) { | 613 if (size != 0) { |
| 612 FlushOnePage(start, size); | 614 FlushOnePage(i_cache, start, size); |
| 613 } | 615 } |
| 614 } | 616 } |
| 615 | 617 |
| 616 | 618 |
| 617 CachePage* Simulator::GetCachePage(void* page) { | 619 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) { |
| 618 v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page, | 620 v8::internal::HashMap::Entry* entry = i_cache->Lookup(page, |
| 619 ICacheHash(page), | 621 ICacheHash(page), |
| 620 true); | 622 true); |
| 621 if (entry->value == NULL) { | 623 if (entry->value == NULL) { |
| 622 CachePage* new_page = new CachePage(); | 624 CachePage* new_page = new CachePage(); |
| 623 entry->value = new_page; | 625 entry->value = new_page; |
| 624 } | 626 } |
| 625 return reinterpret_cast<CachePage*>(entry->value); | 627 return reinterpret_cast<CachePage*>(entry->value); |
| 626 } | 628 } |
| 627 | 629 |
| 628 | 630 |
| 629 // Flush from start up to and not including start + size. | 631 // Flush from start up to and not including start + size. |
| 630 void Simulator::FlushOnePage(intptr_t start, int size) { | 632 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, |
| 633 intptr_t start, |
| 634 int size) { |
| 631 ASSERT(size <= CachePage::kPageSize); | 635 ASSERT(size <= CachePage::kPageSize); |
| 632 ASSERT(AllOnOnePage(start, size - 1)); | 636 ASSERT(AllOnOnePage(start, size - 1)); |
| 633 ASSERT((start & CachePage::kLineMask) == 0); | 637 ASSERT((start & CachePage::kLineMask) == 0); |
| 634 ASSERT((size & CachePage::kLineMask) == 0); | 638 ASSERT((size & CachePage::kLineMask) == 0); |
| 635 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); | 639 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); |
| 636 int offset = (start & CachePage::kPageMask); | 640 int offset = (start & CachePage::kPageMask); |
| 637 CachePage* cache_page = GetCachePage(page); | 641 CachePage* cache_page = GetCachePage(i_cache, page); |
| 638 char* valid_bytemap = cache_page->ValidityByte(offset); | 642 char* valid_bytemap = cache_page->ValidityByte(offset); |
| 639 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); | 643 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); |
| 640 } | 644 } |
| 641 | 645 |
| 642 | 646 |
| 643 void Simulator::CheckICache(Instruction* instr) { | 647 void Simulator::CheckICache(v8::internal::HashMap* i_cache, |
| 648 Instruction* instr) { |
| 644 intptr_t address = reinterpret_cast<intptr_t>(instr); | 649 intptr_t address = reinterpret_cast<intptr_t>(instr); |
| 645 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); | 650 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); |
| 646 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); | 651 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); |
| 647 int offset = (address & CachePage::kPageMask); | 652 int offset = (address & CachePage::kPageMask); |
| 648 CachePage* cache_page = GetCachePage(page); | 653 CachePage* cache_page = GetCachePage(i_cache, page); |
| 649 char* cache_valid_byte = cache_page->ValidityByte(offset); | 654 char* cache_valid_byte = cache_page->ValidityByte(offset); |
| 650 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); | 655 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); |
| 651 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); | 656 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); |
| 652 if (cache_hit) { | 657 if (cache_hit) { |
| 653 // Check that the data in memory matches the contents of the I-cache. | 658 // Check that the data in memory matches the contents of the I-cache. |
| 654 CHECK(memcmp(reinterpret_cast<void*>(instr), | 659 CHECK(memcmp(reinterpret_cast<void*>(instr), |
| 655 cache_page->CachedData(offset), | 660 cache_page->CachedData(offset), |
| 656 Instruction::kInstrSize) == 0); | 661 Instruction::kInstrSize) == 0); |
| 657 } else { | 662 } else { |
| 658 // Cache miss. Load memory into the cache. | 663 // Cache miss. Load memory into the cache. |
| 659 memcpy(cached_line, line, CachePage::kLineLength); | 664 memcpy(cached_line, line, CachePage::kLineLength); |
| 660 *cache_valid_byte = CachePage::LINE_VALID; | 665 *cache_valid_byte = CachePage::LINE_VALID; |
| 661 } | 666 } |
| 662 } | 667 } |
| 663 | 668 |
| 664 | 669 |
| 665 // Create one simulator per thread and keep it in thread local storage. | |
| 666 static v8::internal::Thread::LocalStorageKey simulator_key; | |
| 667 | |
| 668 | |
| 669 bool Simulator::initialized_ = false; | |
| 670 | |
| 671 | |
| 672 void Simulator::Initialize() { | 670 void Simulator::Initialize() { |
| 673 if (initialized_) return; | 671 if (Isolate::Current()->simulator_initialized()) return; |
| 674 simulator_key = v8::internal::Thread::CreateThreadLocalKey(); | 672 Isolate::Current()->set_simulator_initialized(true); |
| 675 initialized_ = true; | |
| 676 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); | 673 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); |
| 677 } | 674 } |
| 678 | 675 |
| 679 | 676 |
| 680 v8::internal::HashMap* Simulator::i_cache_ = NULL; | 677 Simulator::Simulator() : isolate_(Isolate::Current()) { |
| 681 | 678 i_cache_ = isolate_->simulator_i_cache(); |
| 682 | |
| 683 Simulator::Simulator() { | |
| 684 if (i_cache_ == NULL) { | 679 if (i_cache_ == NULL) { |
| 685 i_cache_ = new v8::internal::HashMap(&ICacheMatch); | 680 i_cache_ = new v8::internal::HashMap(&ICacheMatch); |
| 681 isolate_->set_simulator_i_cache(i_cache_); |
| 686 } | 682 } |
| 687 Initialize(); | 683 Initialize(); |
| 688 // Setup simulator support first. Some of this information is needed to | 684 // Setup simulator support first. Some of this information is needed to |
| 689 // setup the architecture state. | 685 // setup the architecture state. |
| 690 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack | 686 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack |
| 691 stack_ = reinterpret_cast<char*>(malloc(stack_size)); | 687 stack_ = reinterpret_cast<char*>(malloc(stack_size)); |
| 692 pc_modified_ = false; | 688 pc_modified_ = false; |
| 693 icount_ = 0; | 689 icount_ = 0; |
| 694 break_pc_ = NULL; | 690 break_pc_ = NULL; |
| 695 break_instr_ = 0; | 691 break_instr_ = 0; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 // execute it with the simulator. We do that by redirecting the external | 737 // execute it with the simulator. We do that by redirecting the external |
| 742 // reference to a svc (Supervisor Call) instruction that is handled by | 738 // reference to a svc (Supervisor Call) instruction that is handled by |
| 743 // the simulator. We write the original destination of the jump just at a known | 739 // the simulator. We write the original destination of the jump just at a known |
| 744 // offset from the svc instruction so the simulator knows what to call. | 740 // offset from the svc instruction so the simulator knows what to call. |
| 745 class Redirection { | 741 class Redirection { |
| 746 public: | 742 public: |
| 747 Redirection(void* external_function, ExternalReference::Type type) | 743 Redirection(void* external_function, ExternalReference::Type type) |
| 748 : external_function_(external_function), | 744 : external_function_(external_function), |
| 749 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), | 745 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), |
| 750 type_(type), | 746 type_(type), |
| 751 next_(list_) { | 747 next_(NULL) { |
| 752 Simulator::current()-> | 748 Isolate* isolate = Isolate::Current(); |
| 753 FlushICache(reinterpret_cast<void*>(&swi_instruction_), | 749 next_ = isolate->simulator_redirection(); |
| 754 Instruction::kInstrSize); | 750 Simulator::current(isolate)-> |
| 755 list_ = this; | 751 FlushICache(isolate->simulator_i_cache(), |
| 752 reinterpret_cast<void*>(&swi_instruction_), |
| 753 Instruction::kInstrSize); |
| 754 isolate->set_simulator_redirection(this); |
| 756 } | 755 } |
| 757 | 756 |
| 758 void* address_of_swi_instruction() { | 757 void* address_of_swi_instruction() { |
| 759 return reinterpret_cast<void*>(&swi_instruction_); | 758 return reinterpret_cast<void*>(&swi_instruction_); |
| 760 } | 759 } |
| 761 | 760 |
| 762 void* external_function() { return external_function_; } | 761 void* external_function() { return external_function_; } |
| 763 ExternalReference::Type type() { return type_; } | 762 ExternalReference::Type type() { return type_; } |
| 764 | 763 |
| 765 static Redirection* Get(void* external_function, | 764 static Redirection* Get(void* external_function, |
| 766 ExternalReference::Type type) { | 765 ExternalReference::Type type) { |
| 767 Redirection* current; | 766 Isolate* isolate = Isolate::Current(); |
| 768 for (current = list_; current != NULL; current = current->next_) { | 767 Redirection* current = isolate->simulator_redirection(); |
| 768 for (; current != NULL; current = current->next_) { |
| 769 if (current->external_function_ == external_function) return current; | 769 if (current->external_function_ == external_function) return current; |
| 770 } | 770 } |
| 771 return new Redirection(external_function, type); | 771 return new Redirection(external_function, type); |
| 772 } | 772 } |
| 773 | 773 |
| 774 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { | 774 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { |
| 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); | 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); |
| 776 char* addr_of_redirection = | 776 char* addr_of_redirection = |
| 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); | 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); |
| 778 return reinterpret_cast<Redirection*>(addr_of_redirection); | 778 return reinterpret_cast<Redirection*>(addr_of_redirection); |
| 779 } | 779 } |
| 780 | 780 |
| 781 private: | 781 private: |
| 782 void* external_function_; | 782 void* external_function_; |
| 783 uint32_t swi_instruction_; | 783 uint32_t swi_instruction_; |
| 784 ExternalReference::Type type_; | 784 ExternalReference::Type type_; |
| 785 Redirection* next_; | 785 Redirection* next_; |
| 786 static Redirection* list_; | |
| 787 }; | 786 }; |
| 788 | 787 |
| 789 | 788 |
| 790 Redirection* Redirection::list_ = NULL; | |
| 791 | |
| 792 | |
| 793 void* Simulator::RedirectExternalReference(void* external_function, | 789 void* Simulator::RedirectExternalReference(void* external_function, |
| 794 ExternalReference::Type type) { | 790 ExternalReference::Type type) { |
| 795 Redirection* redirection = Redirection::Get(external_function, type); | 791 Redirection* redirection = Redirection::Get(external_function, type); |
| 796 return redirection->address_of_swi_instruction(); | 792 return redirection->address_of_swi_instruction(); |
| 797 } | 793 } |
| 798 | 794 |
| 799 | 795 |
| 800 // Get the active Simulator for the current thread. | 796 // Get the active Simulator for the current thread. |
| 801 Simulator* Simulator::current() { | 797 Simulator* Simulator::current(Isolate* isolate) { |
| 802 Initialize(); | 798 v8::internal::Isolate::PerIsolateThreadData* isolate_data = |
| 803 Simulator* sim = reinterpret_cast<Simulator*>( | 799 Isolate::CurrentPerIsolateThreadData(); |
| 804 v8::internal::Thread::GetThreadLocal(simulator_key)); | 800 if (isolate_data == NULL) { |
| 801 Isolate::EnterDefaultIsolate(); |
| 802 isolate_data = Isolate::CurrentPerIsolateThreadData(); |
| 803 } |
| 804 ASSERT(isolate_data != NULL); |
| 805 |
| 806 Simulator* sim = isolate_data->simulator(); |
| 805 if (sim == NULL) { | 807 if (sim == NULL) { |
| 806 // TODO(146): delete the simulator object when a thread goes away. | 808 // TODO(146): delete the simulator object when a thread/isolate goes away. |
| 807 sim = new Simulator(); | 809 sim = new Simulator(); |
| 808 v8::internal::Thread::SetThreadLocal(simulator_key, sim); | 810 isolate_data->set_simulator(sim); |
| 809 } | 811 } |
| 810 return sim; | 812 return sim; |
| 811 } | 813 } |
| 812 | 814 |
| 813 | 815 |
| 814 // Sets the register in the architecture state. It will also deal with updating | 816 // Sets the register in the architecture state. It will also deal with updating |
| 815 // Simulator internal state for special registers such as PC. | 817 // Simulator internal state for special registers such as PC. |
| 816 void Simulator::set_register(int reg, int32_t value) { | 818 void Simulator::set_register(int reg, int32_t value) { |
| 817 ASSERT((reg >= 0) && (reg < num_registers)); | 819 ASSERT((reg >= 0) && (reg < num_registers)); |
| 818 if (reg == pc) { | 820 if (reg == pc) { |
| (...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1526 // Calls into the V8 runtime are based on this very simple interface. | 1528 // Calls into the V8 runtime are based on this very simple interface. |
| 1527 // Note: To be able to return two values from some calls the code in runtime.cc | 1529 // Note: To be able to return two values from some calls the code in runtime.cc |
| 1528 // uses the ObjectPair which is essentially two 32-bit values stuffed into a | 1530 // uses the ObjectPair which is essentially two 32-bit values stuffed into a |
| 1529 // 64-bit value. With the code below we assume that all runtime calls return | 1531 // 64-bit value. With the code below we assume that all runtime calls return |
| 1530 // 64 bits of result. If they don't, the r1 result register contains a bogus | 1532 // 64 bits of result. If they don't, the r1 result register contains a bogus |
| 1531 // value, which is fine because it is caller-saved. | 1533 // value, which is fine because it is caller-saved. |
| 1532 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, | 1534 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, |
| 1533 int32_t arg1, | 1535 int32_t arg1, |
| 1534 int32_t arg2, | 1536 int32_t arg2, |
| 1535 int32_t arg3, | 1537 int32_t arg3, |
| 1536 int32_t arg4); | 1538 int32_t arg4, |
| 1539 int32_t arg5); |
| 1537 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, | 1540 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, |
| 1538 int32_t arg1, | 1541 int32_t arg1, |
| 1539 int32_t arg2, | 1542 int32_t arg2, |
| 1540 int32_t arg3); | 1543 int32_t arg3); |
| 1541 | 1544 |
| 1542 // This signature supports direct call in to API function native callback | 1545 // This signature supports direct call in to API function native callback |
| 1543 // (refer to InvocationCallback in v8.h). | 1546 // (refer to InvocationCallback in v8.h). |
| 1544 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); | 1547 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); |
| 1545 | 1548 |
| 1546 // This signature supports direct call to accessor getter callback. | 1549 // This signature supports direct call to accessor getter callback. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1557 // include information on the function called. | 1560 // include information on the function called. |
| 1558 bool stack_aligned = | 1561 bool stack_aligned = |
| 1559 (get_register(sp) | 1562 (get_register(sp) |
| 1560 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; | 1563 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; |
| 1561 Redirection* redirection = Redirection::FromSwiInstruction(instr); | 1564 Redirection* redirection = Redirection::FromSwiInstruction(instr); |
| 1562 int32_t arg0 = get_register(r0); | 1565 int32_t arg0 = get_register(r0); |
| 1563 int32_t arg1 = get_register(r1); | 1566 int32_t arg1 = get_register(r1); |
| 1564 int32_t arg2 = get_register(r2); | 1567 int32_t arg2 = get_register(r2); |
| 1565 int32_t arg3 = get_register(r3); | 1568 int32_t arg3 = get_register(r3); |
| 1566 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); | 1569 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); |
| 1567 int32_t arg4 = *stack_pointer; | 1570 int32_t arg4 = stack_pointer[0]; |
| 1571 int32_t arg5 = stack_pointer[1]; |
| 1568 // This is dodgy but it works because the C entry stubs are never moved. | 1572 // This is dodgy but it works because the C entry stubs are never moved. |
| 1569 // See comment in codegen-arm.cc and bug 1242173. | 1573 // See comment in codegen-arm.cc and bug 1242173. |
| 1570 int32_t saved_lr = get_register(lr); | 1574 int32_t saved_lr = get_register(lr); |
| 1571 intptr_t external = | 1575 intptr_t external = |
| 1572 reinterpret_cast<intptr_t>(redirection->external_function()); | 1576 reinterpret_cast<intptr_t>(redirection->external_function()); |
| 1573 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { | 1577 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { |
| 1574 SimulatorRuntimeFPCall target = | 1578 SimulatorRuntimeFPCall target = |
| 1575 reinterpret_cast<SimulatorRuntimeFPCall>(external); | 1579 reinterpret_cast<SimulatorRuntimeFPCall>(external); |
| 1576 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1580 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1577 double x, y; | 1581 double x, y; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1620 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); | 1624 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); |
| 1621 } | 1625 } |
| 1622 set_register(r0, (int32_t) *result); | 1626 set_register(r0, (int32_t) *result); |
| 1623 } else { | 1627 } else { |
| 1624 // builtin call. | 1628 // builtin call. |
| 1625 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); | 1629 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); |
| 1626 SimulatorRuntimeCall target = | 1630 SimulatorRuntimeCall target = |
| 1627 reinterpret_cast<SimulatorRuntimeCall>(external); | 1631 reinterpret_cast<SimulatorRuntimeCall>(external); |
| 1628 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { | 1632 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { |
| 1629 PrintF( | 1633 PrintF( |
| 1630 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", | 1634 "Call to host function at %p" |
| 1635 "args %08x, %08x, %08x, %08x, %08x, %08x", |
| 1631 FUNCTION_ADDR(target), | 1636 FUNCTION_ADDR(target), |
| 1632 arg0, | 1637 arg0, |
| 1633 arg1, | 1638 arg1, |
| 1634 arg2, | 1639 arg2, |
| 1635 arg3, | 1640 arg3, |
| 1636 arg4); | 1641 arg4, |
| 1642 arg5); |
| 1637 if (!stack_aligned) { | 1643 if (!stack_aligned) { |
| 1638 PrintF(" with unaligned stack %08x\n", get_register(sp)); | 1644 PrintF(" with unaligned stack %08x\n", get_register(sp)); |
| 1639 } | 1645 } |
| 1640 PrintF("\n"); | 1646 PrintF("\n"); |
| 1641 } | 1647 } |
| 1642 CHECK(stack_aligned); | 1648 CHECK(stack_aligned); |
| 1643 int64_t result = target(arg0, arg1, arg2, arg3, arg4); | 1649 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5); |
| 1644 int32_t lo_res = static_cast<int32_t>(result); | 1650 int32_t lo_res = static_cast<int32_t>(result); |
| 1645 int32_t hi_res = static_cast<int32_t>(result >> 32); | 1651 int32_t hi_res = static_cast<int32_t>(result >> 32); |
| 1646 if (::v8::internal::FLAG_trace_sim) { | 1652 if (::v8::internal::FLAG_trace_sim) { |
| 1647 PrintF("Returned %08x\n", lo_res); | 1653 PrintF("Returned %08x\n", lo_res); |
| 1648 } | 1654 } |
| 1649 set_register(r0, lo_res); | 1655 set_register(r0, lo_res); |
| 1650 set_register(r1, hi_res); | 1656 set_register(r1, hi_res); |
| 1651 } | 1657 } |
| 1652 set_register(lr, saved_lr); | 1658 set_register(lr, saved_lr); |
| 1653 set_pc(get_register(lr)); | 1659 set_pc(get_register(lr)); |
| 1654 break; | 1660 break; |
| 1655 } | 1661 } |
| 1656 case kBreakpoint: { | 1662 case kBreakpoint: { |
| 1657 Debugger dbg(this); | 1663 ArmDebugger dbg(this); |
| 1658 dbg.Debug(); | 1664 dbg.Debug(); |
| 1659 break; | 1665 break; |
| 1660 } | 1666 } |
| 1661 // stop uses all codes greater than 1 << 23. | 1667 // stop uses all codes greater than 1 << 23. |
| 1662 default: { | 1668 default: { |
| 1663 if (svc >= (1 << 23)) { | 1669 if (svc >= (1 << 23)) { |
| 1664 uint32_t code = svc & kStopCodeMask; | 1670 uint32_t code = svc & kStopCodeMask; |
| 1665 if (isWatchedStop(code)) { | 1671 if (isWatchedStop(code)) { |
| 1666 IncreaseStopCounter(code); | 1672 IncreaseStopCounter(code); |
| 1667 } | 1673 } |
| 1668 // Stop if it is enabled, otherwise go on jumping over the stop | 1674 // Stop if it is enabled, otherwise go on jumping over the stop |
| 1669 // and the message address. | 1675 // and the message address. |
| 1670 if (isEnabledStop(code)) { | 1676 if (isEnabledStop(code)) { |
| 1671 Debugger dbg(this); | 1677 ArmDebugger dbg(this); |
| 1672 dbg.Stop(instr); | 1678 dbg.Stop(instr); |
| 1673 } else { | 1679 } else { |
| 1674 set_pc(get_pc() + 2 * Instruction::kInstrSize); | 1680 set_pc(get_pc() + 2 * Instruction::kInstrSize); |
| 1675 } | 1681 } |
| 1676 } else { | 1682 } else { |
| 1677 // This is not a valid svc code. | 1683 // This is not a valid svc code. |
| 1678 UNREACHABLE(); | 1684 UNREACHABLE(); |
| 1679 break; | 1685 break; |
| 1680 } | 1686 } |
| 1681 } | 1687 } |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1969 case BX: | 1975 case BX: |
| 1970 set_pc(get_register(rm)); | 1976 set_pc(get_register(rm)); |
| 1971 break; | 1977 break; |
| 1972 case BLX: { | 1978 case BLX: { |
| 1973 uint32_t old_pc = get_pc(); | 1979 uint32_t old_pc = get_pc(); |
| 1974 set_pc(get_register(rm)); | 1980 set_pc(get_register(rm)); |
| 1975 set_register(lr, old_pc + Instruction::kInstrSize); | 1981 set_register(lr, old_pc + Instruction::kInstrSize); |
| 1976 break; | 1982 break; |
| 1977 } | 1983 } |
| 1978 case BKPT: { | 1984 case BKPT: { |
| 1979 Debugger dbg(this); | 1985 ArmDebugger dbg(this); |
| 1980 PrintF("Simulator hit BKPT.\n"); | 1986 PrintF("Simulator hit BKPT.\n"); |
| 1981 dbg.Debug(); | 1987 dbg.Debug(); |
| 1982 break; | 1988 break; |
| 1983 } | 1989 } |
| 1984 default: | 1990 default: |
| 1985 UNIMPLEMENTED(); | 1991 UNIMPLEMENTED(); |
| 1986 } | 1992 } |
| 1987 } else if (instr->Bits(22, 21) == 3) { | 1993 } else if (instr->Bits(22, 21) == 3) { |
| 1988 int rm = instr->RmValue(); | 1994 int rm = instr->RmValue(); |
| 1989 int rd = instr->RdValue(); | 1995 int rd = instr->RdValue(); |
| (...skipping 967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2957 } | 2963 } |
| 2958 } else { | 2964 } else { |
| 2959 UNIMPLEMENTED(); // Not used by V8. | 2965 UNIMPLEMENTED(); // Not used by V8. |
| 2960 } | 2966 } |
| 2961 } | 2967 } |
| 2962 | 2968 |
| 2963 | 2969 |
| 2964 // Executes the current instruction. | 2970 // Executes the current instruction. |
| 2965 void Simulator::InstructionDecode(Instruction* instr) { | 2971 void Simulator::InstructionDecode(Instruction* instr) { |
| 2966 if (v8::internal::FLAG_check_icache) { | 2972 if (v8::internal::FLAG_check_icache) { |
| 2967 CheckICache(instr); | 2973 CheckICache(isolate_->simulator_i_cache(), instr); |
| 2968 } | 2974 } |
| 2969 pc_modified_ = false; | 2975 pc_modified_ = false; |
| 2970 if (::v8::internal::FLAG_trace_sim) { | 2976 if (::v8::internal::FLAG_trace_sim) { |
| 2971 disasm::NameConverter converter; | 2977 disasm::NameConverter converter; |
| 2972 disasm::Disassembler dasm(converter); | 2978 disasm::Disassembler dasm(converter); |
| 2973 // use a reasonably large buffer | 2979 // use a reasonably large buffer |
| 2974 v8::internal::EmbeddedVector<char, 256> buffer; | 2980 v8::internal::EmbeddedVector<char, 256> buffer; |
| 2975 dasm.InstructionDecode(buffer, | 2981 dasm.InstructionDecode(buffer, |
| 2976 reinterpret_cast<byte*>(instr)); | 2982 reinterpret_cast<byte*>(instr)); |
| 2977 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); | 2983 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3040 InstructionDecode(instr); | 3046 InstructionDecode(instr); |
| 3041 program_counter = get_pc(); | 3047 program_counter = get_pc(); |
| 3042 } | 3048 } |
| 3043 } else { | 3049 } else { |
| 3044 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 3050 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 3045 // we reach the particular instuction count. | 3051 // we reach the particular instuction count. |
| 3046 while (program_counter != end_sim_pc) { | 3052 while (program_counter != end_sim_pc) { |
| 3047 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); | 3053 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); |
| 3048 icount_++; | 3054 icount_++; |
| 3049 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { | 3055 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { |
| 3050 Debugger dbg(this); | 3056 ArmDebugger dbg(this); |
| 3051 dbg.Debug(); | 3057 dbg.Debug(); |
| 3052 } else { | 3058 } else { |
| 3053 InstructionDecode(instr); | 3059 InstructionDecode(instr); |
| 3054 } | 3060 } |
| 3055 program_counter = get_pc(); | 3061 program_counter = get_pc(); |
| 3056 } | 3062 } |
| 3057 } | 3063 } |
| 3058 } | 3064 } |
| 3059 | 3065 |
| 3060 | 3066 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3163 uintptr_t address = *stack_slot; | 3169 uintptr_t address = *stack_slot; |
| 3164 set_register(sp, current_sp + sizeof(uintptr_t)); | 3170 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3165 return address; | 3171 return address; |
| 3166 } | 3172 } |
| 3167 | 3173 |
| 3168 } } // namespace v8::internal | 3174 } } // namespace v8::internal |
| 3169 | 3175 |
| 3170 #endif // USE_SIMULATOR | 3176 #endif // USE_SIMULATOR |
| 3171 | 3177 |
| 3172 #endif // V8_TARGET_ARCH_ARM | 3178 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |