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 |