OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <setjmp.h> // NOLINT | 5 #include <setjmp.h> // NOLINT |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 | 7 |
8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
9 #if defined(TARGET_ARCH_MIPS) | 9 #if defined(TARGET_ARCH_MIPS) |
10 | 10 |
11 // Only build the simulator if not compiling for real MIPS hardware. | 11 // Only build the simulator if not compiling for real MIPS hardware. |
12 #if defined(USING_SIMULATOR) | 12 #if defined(USING_SIMULATOR) |
13 | 13 |
14 #include "vm/simulator.h" | 14 #include "vm/simulator.h" |
15 | 15 |
16 #include "vm/assembler.h" | 16 #include "vm/assembler.h" |
17 #include "vm/constants_mips.h" | 17 #include "vm/constants_mips.h" |
18 #include "vm/disassembler.h" | 18 #include "vm/disassembler.h" |
19 #include "vm/lockers.h" | 19 #include "vm/lockers.h" |
20 #include "vm/native_arguments.h" | 20 #include "vm/native_arguments.h" |
21 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
22 #include "vm/os_thread.h" | 22 #include "vm/os_thread.h" |
23 | 23 |
24 namespace dart { | 24 namespace dart { |
25 | 25 |
26 DEFINE_FLAG(uint64_t, trace_sim_after, ULLONG_MAX, | 26 DEFINE_FLAG(uint64_t, |
| 27 trace_sim_after, |
| 28 ULLONG_MAX, |
27 "Trace simulator execution after instruction count reached."); | 29 "Trace simulator execution after instruction count reached."); |
28 DEFINE_FLAG(uint64_t, stop_sim_at, ULLONG_MAX, | 30 DEFINE_FLAG(uint64_t, |
| 31 stop_sim_at, |
| 32 ULLONG_MAX, |
29 "Instruction address or instruction count to stop simulator at."); | 33 "Instruction address or instruction count to stop simulator at."); |
30 | 34 |
31 | 35 |
32 // This macro provides a platform independent use of sscanf. The reason for | 36 // This macro provides a platform independent use of sscanf. The reason for |
33 // SScanF not being implemented in a platform independent way through | 37 // SScanF not being implemented in a platform independent way through |
34 // OS in the same way as SNPrint is that the Windows C Run-Time | 38 // OS in the same way as SNPrint is that the Windows C Run-Time |
35 // Library does not provide vsscanf. | 39 // Library does not provide vsscanf. |
36 #define SScanF sscanf // NOLINT | 40 #define SScanF sscanf // NOLINT |
37 | 41 |
38 | 42 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 | 92 |
89 private: | 93 private: |
90 Simulator* sim_; | 94 Simulator* sim_; |
91 | 95 |
92 bool GetValue(char* desc, uint32_t* value); | 96 bool GetValue(char* desc, uint32_t* value); |
93 bool GetFValue(char* desc, double* value); | 97 bool GetFValue(char* desc, double* value); |
94 bool GetDValue(char* desc, double* value); | 98 bool GetDValue(char* desc, double* value); |
95 | 99 |
96 static TokenPosition GetApproximateTokenIndex(const Code& code, uword pc); | 100 static TokenPosition GetApproximateTokenIndex(const Code& code, uword pc); |
97 | 101 |
98 static void PrintDartFrame(uword pc, uword fp, uword sp, | 102 static void PrintDartFrame(uword pc, |
| 103 uword fp, |
| 104 uword sp, |
99 const Function& function, | 105 const Function& function, |
100 TokenPosition token_pos, | 106 TokenPosition token_pos, |
101 bool is_optimized, | 107 bool is_optimized, |
102 bool is_inlined); | 108 bool is_inlined); |
103 void PrintBacktrace(); | 109 void PrintBacktrace(); |
104 | 110 |
105 // Set or delete a breakpoint. Returns true if successful. | 111 // Set or delete a breakpoint. Returns true if successful. |
106 bool SetBreakpoint(Instr* breakpc); | 112 bool SetBreakpoint(Instr* breakpc); |
107 bool DeleteBreakpoint(Instr* breakpc); | 113 bool DeleteBreakpoint(Instr* breakpc); |
108 | 114 |
109 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 115 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
110 // execution to skip past breakpoints when run from the debugger. | 116 // execution to skip past breakpoints when run from the debugger. |
111 void UndoBreakpoints(); | 117 void UndoBreakpoints(); |
112 void RedoBreakpoints(); | 118 void RedoBreakpoints(); |
113 }; | 119 }; |
114 | 120 |
115 | 121 |
116 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { | 122 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { |
117 sim_ = sim; | 123 sim_ = sim; |
118 } | 124 } |
119 | 125 |
120 | 126 |
121 SimulatorDebugger::~SimulatorDebugger() { | 127 SimulatorDebugger::~SimulatorDebugger() {} |
122 } | |
123 | 128 |
124 | 129 |
125 void SimulatorDebugger::Stop(Instr* instr, const char* message) { | 130 void SimulatorDebugger::Stop(Instr* instr, const char* message) { |
126 OS::Print("Simulator hit %s\n", message); | 131 OS::Print("Simulator hit %s\n", message); |
127 Debug(); | 132 Debug(); |
128 } | 133 } |
129 | 134 |
130 | 135 |
131 static Register LookupCpuRegisterByName(const char* name) { | 136 static Register LookupCpuRegisterByName(const char* name) { |
132 static const char* kNames[] = { | 137 static const char* kNames[] = { |
133 "r0", "r1", "r2", "r3", | 138 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
134 "r4", "r5", "r6", "r7", | 139 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
135 "r8", "r9", "r10", "r11", | 140 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
136 "r12", "r13", "r14", "r15", | 141 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", |
137 "r16", "r17", "r18", "r19", | |
138 "r20", "r21", "r22", "r23", | |
139 "r24", "r25", "r26", "r27", | |
140 "r28", "r29", "r30", "r31", | |
141 | 142 |
142 "zr", "at", "v0", "v1", | 143 "zr", "at", "v0", "v1", "a0", "a1", "a2", "a3", |
143 "a0", "a1", "a2", "a3", | 144 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", |
144 "t0", "t1", "t2", "t3", | 145 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
145 "t4", "t5", "t6", "t7", | 146 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"}; |
146 "s0", "s1", "s2", "s3", | |
147 "s4", "s5", "s6", "s7", | |
148 "t8", "t9", "k0", "k1", | |
149 "gp", "sp", "fp", "ra" | |
150 }; | |
151 static const Register kRegisters[] = { | 147 static const Register kRegisters[] = { |
152 R0, R1, R2, R3, | 148 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, |
153 R4, R5, R6, R7, | 149 R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, |
154 R8, R9, R10, R11, | 150 R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, |
155 R12, R13, R14, R15, | |
156 R16, R17, R18, R19, | |
157 R20, R21, R22, R23, | |
158 R24, R25, R26, R27, | |
159 R28, R29, R30, R31, | |
160 | 151 |
161 ZR, AT, V0, V1, | 152 ZR, AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, |
162 A0, A1, A2, A3, | 153 T3, T4, T5, T6, T7, S0, S1, S2, S3, S4, S5, |
163 T0, T1, T2, T3, | 154 S6, S7, T8, T9, K0, K1, GP, SP, FP, RA}; |
164 T4, T5, T6, T7, | |
165 S0, S1, S2, S3, | |
166 S4, S5, S6, S7, | |
167 T8, T9, K0, K1, | |
168 GP, SP, FP, RA | |
169 }; | |
170 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); | 155 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters)); |
171 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { | 156 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) { |
172 if (strcmp(kNames[i], name) == 0) { | 157 if (strcmp(kNames[i], name) == 0) { |
173 return kRegisters[i]; | 158 return kRegisters[i]; |
174 } | 159 } |
175 } | 160 } |
176 return kNoRegister; | 161 return kNoRegister; |
177 } | 162 } |
178 | 163 |
179 | 164 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 } | 234 } |
250 *value = *(reinterpret_cast<double*>(addr)); | 235 *value = *(reinterpret_cast<double*>(addr)); |
251 return true; | 236 return true; |
252 } | 237 } |
253 } | 238 } |
254 return false; | 239 return false; |
255 } | 240 } |
256 | 241 |
257 | 242 |
258 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, | 243 TokenPosition SimulatorDebugger::GetApproximateTokenIndex(const Code& code, |
259 uword pc) { | 244 uword pc) { |
260 TokenPosition token_pos = TokenPosition::kNoSource; | 245 TokenPosition token_pos = TokenPosition::kNoSource; |
261 uword pc_offset = pc - code.PayloadStart(); | 246 uword pc_offset = pc - code.PayloadStart(); |
262 const PcDescriptors& descriptors = | 247 const PcDescriptors& descriptors = |
263 PcDescriptors::Handle(code.pc_descriptors()); | 248 PcDescriptors::Handle(code.pc_descriptors()); |
264 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); | 249 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); |
265 while (iter.MoveNext()) { | 250 while (iter.MoveNext()) { |
266 if (iter.PcOffset() == pc_offset) { | 251 if (iter.PcOffset() == pc_offset) { |
267 return iter.TokenPos(); | 252 return iter.TokenPos(); |
268 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { | 253 } else if (!token_pos.IsReal() && (iter.PcOffset() > pc_offset)) { |
269 token_pos = iter.TokenPos(); | 254 token_pos = iter.TokenPos(); |
270 } | 255 } |
271 } | 256 } |
272 return token_pos; | 257 return token_pos; |
273 } | 258 } |
274 | 259 |
275 | 260 |
276 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp, | 261 void SimulatorDebugger::PrintDartFrame(uword pc, |
| 262 uword fp, |
| 263 uword sp, |
277 const Function& function, | 264 const Function& function, |
278 TokenPosition token_pos, | 265 TokenPosition token_pos, |
279 bool is_optimized, | 266 bool is_optimized, |
280 bool is_inlined) { | 267 bool is_inlined) { |
281 const Script& script = Script::Handle(function.script()); | 268 const Script& script = Script::Handle(function.script()); |
282 const String& func_name = String::Handle(function.QualifiedScrubbedName()); | 269 const String& func_name = String::Handle(function.QualifiedScrubbedName()); |
283 const String& url = String::Handle(script.url()); | 270 const String& url = String::Handle(script.url()); |
284 intptr_t line = -1; | 271 intptr_t line = -1; |
285 intptr_t column = -1; | 272 intptr_t column = -1; |
286 if (token_pos.IsReal()) { | 273 if (token_pos.IsReal()) { |
287 script.GetTokenLocation(token_pos, &line, &column); | 274 script.GetTokenLocation(token_pos, &line, &column); |
288 } | 275 } |
289 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd | 276 OS::Print( |
290 ":%" Pd ")\n", | 277 "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc, |
291 pc, fp, sp, | 278 fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", |
292 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", | 279 func_name.ToCString(), url.ToCString(), line, column); |
293 func_name.ToCString(), | |
294 url.ToCString(), | |
295 line, column); | |
296 } | 280 } |
297 | 281 |
298 | 282 |
299 void SimulatorDebugger::PrintBacktrace() { | 283 void SimulatorDebugger::PrintBacktrace() { |
300 StackFrameIterator frames(sim_->get_register(FP), | 284 StackFrameIterator frames(sim_->get_register(FP), sim_->get_register(SP), |
301 sim_->get_register(SP), | |
302 sim_->get_pc(), | 285 sim_->get_pc(), |
303 StackFrameIterator::kDontValidateFrames); | 286 StackFrameIterator::kDontValidateFrames); |
304 StackFrame* frame = frames.NextFrame(); | 287 StackFrame* frame = frames.NextFrame(); |
305 ASSERT(frame != NULL); | 288 ASSERT(frame != NULL); |
306 Function& function = Function::Handle(); | 289 Function& function = Function::Handle(); |
307 Function& inlined_function = Function::Handle(); | 290 Function& inlined_function = Function::Handle(); |
308 Code& code = Code::Handle(); | 291 Code& code = Code::Handle(); |
309 Code& unoptimized_code = Code::Handle(); | 292 Code& unoptimized_code = Code::Handle(); |
310 while (frame != NULL) { | 293 while (frame != NULL) { |
311 if (frame->IsDartFrame()) { | 294 if (frame->IsDartFrame()) { |
312 code = frame->LookupDartCode(); | 295 code = frame->LookupDartCode(); |
313 function = code.function(); | 296 function = code.function(); |
314 if (code.is_optimized()) { | 297 if (code.is_optimized()) { |
315 // For optimized frames, extract all the inlined functions if any | 298 // For optimized frames, extract all the inlined functions if any |
316 // into the stack trace. | 299 // into the stack trace. |
317 InlinedFunctionsIterator it(code, frame->pc()); | 300 InlinedFunctionsIterator it(code, frame->pc()); |
318 while (!it.Done()) { | 301 while (!it.Done()) { |
319 // Print each inlined frame with its pc in the corresponding | 302 // Print each inlined frame with its pc in the corresponding |
320 // unoptimized frame. | 303 // unoptimized frame. |
321 inlined_function = it.function(); | 304 inlined_function = it.function(); |
322 unoptimized_code = it.code(); | 305 unoptimized_code = it.code(); |
323 uword unoptimized_pc = it.pc(); | 306 uword unoptimized_pc = it.pc(); |
324 it.Advance(); | 307 it.Advance(); |
325 if (!it.Done()) { | 308 if (!it.Done()) { |
326 PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(), | 309 PrintDartFrame( |
327 inlined_function, | 310 unoptimized_pc, frame->fp(), frame->sp(), inlined_function, |
328 GetApproximateTokenIndex(unoptimized_code, | 311 GetApproximateTokenIndex(unoptimized_code, unoptimized_pc), |
329 unoptimized_pc), | 312 true, true); |
330 true, true); | |
331 } | 313 } |
332 } | 314 } |
333 // Print the optimized inlining frame below. | 315 // Print the optimized inlining frame below. |
334 } | 316 } |
335 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), | 317 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), function, |
336 function, | |
337 GetApproximateTokenIndex(code, frame->pc()), | 318 GetApproximateTokenIndex(code, frame->pc()), |
338 code.is_optimized(), false); | 319 code.is_optimized(), false); |
339 } else { | 320 } else { |
340 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", | 321 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", |
341 frame->pc(), frame->fp(), frame->sp(), | 322 frame->pc(), frame->fp(), frame->sp(), |
342 frame->IsEntryFrame() ? "entry" : | 323 frame->IsEntryFrame() |
343 frame->IsExitFrame() ? "exit" : | 324 ? "entry" |
344 frame->IsStubFrame() ? "stub" : "invalid"); | 325 : frame->IsExitFrame() |
| 326 ? "exit" |
| 327 : frame->IsStubFrame() ? "stub" : "invalid"); |
345 } | 328 } |
346 frame = frames.NextFrame(); | 329 frame = frames.NextFrame(); |
347 } | 330 } |
348 } | 331 } |
349 | 332 |
350 | 333 |
351 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { | 334 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
352 // Check if a breakpoint can be set. If not return without any side-effects. | 335 // Check if a breakpoint can be set. If not return without any side-effects. |
353 if (sim_->break_pc_ != NULL) { | 336 if (sim_->break_pc_ != NULL) { |
354 return false; | 337 return false; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 FATAL("ReadLine failed"); | 412 FATAL("ReadLine failed"); |
430 } else { | 413 } else { |
431 // Use sscanf to parse the individual parts of the command line. At the | 414 // Use sscanf to parse the individual parts of the command line. At the |
432 // moment no command expects more than two parameters. | 415 // moment no command expects more than two parameters. |
433 int args = SScanF(line, | 416 int args = SScanF(line, |
434 "%" XSTR(COMMAND_SIZE) "s " | 417 "%" XSTR(COMMAND_SIZE) "s " |
435 "%" XSTR(ARG_SIZE) "s " | 418 "%" XSTR(ARG_SIZE) "s " |
436 "%" XSTR(ARG_SIZE) "s", | 419 "%" XSTR(ARG_SIZE) "s", |
437 cmd, arg1, arg2); | 420 cmd, arg1, arg2); |
438 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | 421 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { |
439 OS::Print("c/cont -- continue execution\n" | 422 OS::Print( |
440 "disasm -- disassemble instrs at current pc location\n" | 423 "c/cont -- continue execution\n" |
441 " other variants are:\n" | 424 "disasm -- disassemble instrs at current pc location\n" |
442 " disasm <address>\n" | 425 " other variants are:\n" |
443 " disasm <address> <number_of_instructions>\n" | 426 " disasm <address>\n" |
444 " by default 10 instrs are disassembled\n" | 427 " disasm <address> <number_of_instructions>\n" |
445 "del -- delete breakpoints\n" | 428 " by default 10 instrs are disassembled\n" |
446 "gdb -- transfer control to gdb\n" | 429 "del -- delete breakpoints\n" |
447 "h/help -- print this help string\n" | 430 "gdb -- transfer control to gdb\n" |
448 "break <address> -- set break point at specified address\n" | 431 "h/help -- print this help string\n" |
449 "p/print <reg or icount or value or *addr> -- print integer\n" | 432 "break <address> -- set break point at specified address\n" |
450 "pf/printfloat <freg or *addr> -- print float value\n" | 433 "p/print <reg or icount or value or *addr> -- print integer\n" |
451 "po/printobject <*reg or *addr> -- print object\n" | 434 "pf/printfloat <freg or *addr> -- print float value\n" |
452 "si/stepi -- single step an instruction\n" | 435 "po/printobject <*reg or *addr> -- print object\n" |
453 "trace -- toggle execution tracing mode\n" | 436 "si/stepi -- single step an instruction\n" |
454 "bt -- print backtrace\n" | 437 "trace -- toggle execution tracing mode\n" |
455 "unstop -- if current pc is a stop instr make it a nop\n" | 438 "bt -- print backtrace\n" |
456 "q/quit -- Quit the debugger and exit the program\n"); | 439 "unstop -- if current pc is a stop instr make it a nop\n" |
| 440 "q/quit -- Quit the debugger and exit the program\n"); |
457 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 441 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
458 OS::Print("Quitting\n"); | 442 OS::Print("Quitting\n"); |
459 OS::Exit(0); | 443 OS::Exit(0); |
460 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 444 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
461 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 445 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
462 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 446 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
463 // Execute the one instruction we broke at with breakpoints disabled. | 447 // Execute the one instruction we broke at with breakpoints disabled. |
464 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 448 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
465 // Leave the debugger shell. | 449 // Leave the debugger shell. |
466 done = true; | 450 done = true; |
467 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 451 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
468 if (args == 2) { | 452 if (args == 2) { |
469 uint32_t value; | 453 uint32_t value; |
470 if (strcmp(arg1, "icount") == 0) { | 454 if (strcmp(arg1, "icount") == 0) { |
471 const uint64_t icount = sim_->get_icount(); | 455 const uint64_t icount = sim_->get_icount(); |
472 OS::Print("icount: %" Pu64 " 0x%" Px64 "\n", icount, icount); | 456 OS::Print("icount: %" Pu64 " 0x%" Px64 "\n", icount, icount); |
473 } else if (GetValue(arg1, &value)) { | 457 } else if (GetValue(arg1, &value)) { |
474 OS::Print("%s: %u 0x%x\n", arg1, value, value); | 458 OS::Print("%s: %u 0x%x\n", arg1, value, value); |
475 } else { | 459 } else { |
476 OS::Print("%s unrecognized\n", arg1); | 460 OS::Print("%s unrecognized\n", arg1); |
477 } | 461 } |
478 } else { | 462 } else { |
479 OS::Print("print <reg or icount or value or *addr>\n"); | 463 OS::Print("print <reg or icount or value or *addr>\n"); |
480 } | 464 } |
481 } else if ((strcmp(cmd, "pf") == 0) || | 465 } else if ((strcmp(cmd, "pf") == 0) || (strcmp(cmd, "printfloat") == 0)) { |
482 (strcmp(cmd, "printfloat") == 0)) { | |
483 if (args == 2) { | 466 if (args == 2) { |
484 double dvalue; | 467 double dvalue; |
485 if (GetFValue(arg1, &dvalue)) { | 468 if (GetFValue(arg1, &dvalue)) { |
486 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); | 469 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); |
487 OS::Print("%s: %llu 0x%llx %.8g\n", | 470 OS::Print("%s: %llu 0x%llx %.8g\n", arg1, long_value, long_value, |
488 arg1, long_value, long_value, dvalue); | 471 dvalue); |
489 } else { | 472 } else { |
490 OS::Print("%s unrecognized\n", arg1); | 473 OS::Print("%s unrecognized\n", arg1); |
491 } | 474 } |
492 } else { | 475 } else { |
493 OS::Print("printfloat <dreg or *addr>\n"); | 476 OS::Print("printfloat <dreg or *addr>\n"); |
494 } | 477 } |
495 } else if ((strcmp(cmd, "pd") == 0) || | 478 } else if ((strcmp(cmd, "pd") == 0) || |
496 (strcmp(cmd, "printdouble") == 0)) { | 479 (strcmp(cmd, "printdouble") == 0)) { |
497 if (args == 2) { | 480 if (args == 2) { |
498 double dvalue; | 481 double dvalue; |
499 if (GetDValue(arg1, &dvalue)) { | 482 if (GetDValue(arg1, &dvalue)) { |
500 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); | 483 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); |
501 OS::Print("%s: %llu 0x%llx %.8g\n", | 484 OS::Print("%s: %llu 0x%llx %.8g\n", arg1, long_value, long_value, |
502 arg1, long_value, long_value, dvalue); | 485 dvalue); |
503 } else { | 486 } else { |
504 OS::Print("%s unrecognized\n", arg1); | 487 OS::Print("%s unrecognized\n", arg1); |
505 } | 488 } |
506 } else { | 489 } else { |
507 OS::Print("printfloat <dreg or *addr>\n"); | 490 OS::Print("printfloat <dreg or *addr>\n"); |
508 } | 491 } |
509 } else if ((strcmp(cmd, "po") == 0) || | 492 } else if ((strcmp(cmd, "po") == 0) || |
510 (strcmp(cmd, "printobject") == 0)) { | 493 (strcmp(cmd, "printobject") == 0)) { |
511 if (args == 2) { | 494 if (args == 2) { |
512 uint32_t value; | 495 uint32_t value; |
513 // Make the dereferencing '*' optional. | 496 // Make the dereferencing '*' optional. |
514 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || | 497 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) || |
515 GetValue(arg1, &value)) { | 498 GetValue(arg1, &value)) { |
516 if (Isolate::Current()->heap()->Contains(value)) { | 499 if (Isolate::Current()->heap()->Contains(value)) { |
517 OS::Print("%s: \n", arg1); | 500 OS::Print("%s: \n", arg1); |
518 #if defined(DEBUG) | 501 #if defined(DEBUG) |
519 const Object& obj = Object::Handle( | 502 const Object& obj = |
520 reinterpret_cast<RawObject*>(value)); | 503 Object::Handle(reinterpret_cast<RawObject*>(value)); |
521 obj.Print(); | 504 obj.Print(); |
522 #endif // defined(DEBUG) | 505 #endif // defined(DEBUG) |
523 } else { | 506 } else { |
524 OS::Print("0x%x is not an object reference\n", value); | 507 OS::Print("0x%x is not an object reference\n", value); |
525 } | 508 } |
526 } else { | 509 } else { |
527 OS::Print("%s unrecognized\n", arg1); | 510 OS::Print("%s unrecognized\n", arg1); |
528 } | 511 } |
529 } else { | 512 } else { |
530 OS::Print("printobject <*reg or *addr>\n"); | 513 OS::Print("printobject <*reg or *addr>\n"); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 OS::Print("%s", prompt); | 616 OS::Print("%s", prompt); |
634 while (keep_going) { | 617 while (keep_going) { |
635 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { | 618 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { |
636 // fgets got an error. Just give up. | 619 // fgets got an error. Just give up. |
637 if (result != NULL) { | 620 if (result != NULL) { |
638 delete[] result; | 621 delete[] result; |
639 } | 622 } |
640 return NULL; | 623 return NULL; |
641 } | 624 } |
642 intptr_t len = strlen(line_buf); | 625 intptr_t len = strlen(line_buf); |
643 if (len > 1 && | 626 if (len > 1 && line_buf[len - 2] == '\\' && line_buf[len - 1] == '\n') { |
644 line_buf[len - 2] == '\\' && | |
645 line_buf[len - 1] == '\n') { | |
646 // When we read a line that ends with a "\" we remove the escape and | 627 // When we read a line that ends with a "\" we remove the escape and |
647 // append the remainder. | 628 // append the remainder. |
648 line_buf[len - 2] = '\n'; | 629 line_buf[len - 2] = '\n'; |
649 line_buf[len - 1] = 0; | 630 line_buf[len - 1] = 0; |
650 len -= 1; | 631 len -= 1; |
651 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { | 632 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { |
652 // Since we read a new line we are done reading the line. This | 633 // Since we read a new line we are done reading the line. This |
653 // will exit the loop after copying this buffer into the result. | 634 // will exit the loop after copying this buffer into the result. |
654 keep_going = false; | 635 keep_going = false; |
655 } | 636 } |
(...skipping 25 matching lines...) Expand all Loading... |
681 offset += len; | 662 offset += len; |
682 } | 663 } |
683 ASSERT(result != NULL); | 664 ASSERT(result != NULL); |
684 result[offset] = '\0'; | 665 result[offset] = '\0'; |
685 return result; | 666 return result; |
686 } | 667 } |
687 | 668 |
688 | 669 |
689 // Synchronization primitives support. | 670 // Synchronization primitives support. |
690 Mutex* Simulator::exclusive_access_lock_ = NULL; | 671 Mutex* Simulator::exclusive_access_lock_ = NULL; |
691 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = | 672 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { |
692 {{NULL, 0}}; | 673 {NULL, 0}}; |
693 int Simulator::next_address_tag_ = 0; | 674 int Simulator::next_address_tag_ = 0; |
694 | 675 |
695 | 676 |
696 void Simulator::InitOnce() { | 677 void Simulator::InitOnce() { |
697 // Setup exclusive access state lock. | 678 // Setup exclusive access state lock. |
698 exclusive_access_lock_ = new Mutex(); | 679 exclusive_access_lock_ = new Mutex(); |
699 } | 680 } |
700 | 681 |
701 | 682 |
702 Simulator::Simulator() { | 683 Simulator::Simulator() { |
703 // Setup simulator support first. Some of this information is needed to | 684 // Setup simulator support first. Some of this information is needed to |
704 // setup the architecture state. | 685 // setup the architecture state. |
705 // We allocate the stack here, the size is computed as the sum of | 686 // We allocate the stack here, the size is computed as the sum of |
706 // the size specified by the user and the buffer space needed for | 687 // the size specified by the user and the buffer space needed for |
707 // handling stack overflow exceptions. To be safe in potential | 688 // handling stack overflow exceptions. To be safe in potential |
708 // stack underflows we also add some underflow buffer space. | 689 // stack underflows we also add some underflow buffer space. |
709 stack_ = new char[(OSThread::GetSpecifiedStackSize() + | 690 stack_ = |
710 OSThread::kStackSizeBuffer + | 691 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
711 kSimulatorStackUnderflowSize)]; | 692 kSimulatorStackUnderflowSize)]; |
712 icount_ = 0; | 693 icount_ = 0; |
713 delay_slot_ = false; | 694 delay_slot_ = false; |
714 break_pc_ = NULL; | 695 break_pc_ = NULL; |
715 break_instr_ = 0; | 696 break_instr_ = 0; |
716 last_setjmp_buffer_ = NULL; | 697 last_setjmp_buffer_ = NULL; |
717 top_exit_frame_info_ = 0; | 698 top_exit_frame_info_ = 0; |
718 | 699 |
719 // Setup architecture state. | 700 // Setup architecture state. |
720 // All registers are initialized to zero to start with. | 701 // All registers are initialized to zero to start with. |
721 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | 702 for (int i = 0; i < kNumberOfCpuRegisters; i++) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 : external_function_(external_function), | 777 : external_function_(external_function), |
797 call_kind_(call_kind), | 778 call_kind_(call_kind), |
798 argument_count_(argument_count), | 779 argument_count_(argument_count), |
799 break_instruction_(Instr::kSimulatorRedirectInstruction), | 780 break_instruction_(Instr::kSimulatorRedirectInstruction), |
800 next_(list_) { | 781 next_(list_) { |
801 // Atomically prepend this element to the front of the global list. | 782 // Atomically prepend this element to the front of the global list. |
802 // Note: Since elements are never removed, there is no ABA issue. | 783 // Note: Since elements are never removed, there is no ABA issue. |
803 Redirection* list_head = list_; | 784 Redirection* list_head = list_; |
804 do { | 785 do { |
805 next_ = list_head; | 786 next_ = list_head; |
806 list_head = reinterpret_cast<Redirection*>( | 787 list_head = |
807 AtomicOperations::CompareAndSwapWord( | 788 reinterpret_cast<Redirection*>(AtomicOperations::CompareAndSwapWord( |
808 reinterpret_cast<uword*>(&list_), | 789 reinterpret_cast<uword*>(&list_), reinterpret_cast<uword>(next_), |
809 reinterpret_cast<uword>(next_), | |
810 reinterpret_cast<uword>(this))); | 790 reinterpret_cast<uword>(this))); |
811 } while (list_head != next_); | 791 } while (list_head != next_); |
812 } | 792 } |
813 | 793 |
814 uword external_function_; | 794 uword external_function_; |
815 Simulator::CallKind call_kind_; | 795 Simulator::CallKind call_kind_; |
816 int argument_count_; | 796 int argument_count_; |
817 uint32_t break_instruction_; | 797 uint32_t break_instruction_; |
818 Redirection* next_; | 798 Redirection* next_; |
819 static Redirection* list_; | 799 static Redirection* list_; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 FATAL("Cannot continue execution after unimplemented instruction."); | 949 FATAL("Cannot continue execution after unimplemented instruction."); |
970 } | 950 } |
971 | 951 |
972 | 952 |
973 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 953 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
974 uword fault_pc = get_pc(); | 954 uword fault_pc = get_pc(); |
975 // The debugger will not be able to single step past this instruction, but | 955 // The debugger will not be able to single step past this instruction, but |
976 // it will be possible to disassemble the code and inspect registers. | 956 // it will be possible to disassemble the code and inspect registers. |
977 char buffer[128]; | 957 char buffer[128]; |
978 snprintf(buffer, sizeof(buffer), | 958 snprintf(buffer, sizeof(buffer), |
979 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", | 959 "illegal memory access at 0x%" Px ", pc=0x%" Px "\n", addr, |
980 addr, fault_pc); | 960 fault_pc); |
981 SimulatorDebugger dbg(this); | 961 SimulatorDebugger dbg(this); |
982 dbg.Stop(instr, buffer); | 962 dbg.Stop(instr, buffer); |
983 // The debugger will return control in non-interactive mode. | 963 // The debugger will return control in non-interactive mode. |
984 FATAL("Cannot continue execution after illegal memory access."); | 964 FATAL("Cannot continue execution after illegal memory access."); |
985 } | 965 } |
986 | 966 |
987 | 967 |
988 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { | 968 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) { |
989 // The debugger will not be able to single step past this instruction, but | 969 // The debugger will not be able to single step past this instruction, but |
990 // it will be possible to disassemble the code and inspect registers. | 970 // it will be possible to disassemble the code and inspect registers. |
991 char buffer[128]; | 971 char buffer[128]; |
992 snprintf(buffer, sizeof(buffer), | 972 snprintf(buffer, sizeof(buffer), "pc=%p, unaligned %s at 0x%" Px "\n", instr, |
993 "pc=%p, unaligned %s at 0x%" Px "\n", instr, msg, addr); | 973 msg, addr); |
994 SimulatorDebugger dbg(this); | 974 SimulatorDebugger dbg(this); |
995 dbg.Stop(instr, buffer); | 975 dbg.Stop(instr, buffer); |
996 // The debugger will return control in non-interactive mode. | 976 // The debugger will return control in non-interactive mode. |
997 FATAL("Cannot continue execution after unaligned access."); | 977 FATAL("Cannot continue execution after unaligned access."); |
998 } | 978 } |
999 | 979 |
1000 | 980 |
1001 // Returns the top of the stack area to enable checking for stack pointer | 981 // Returns the top of the stack area to enable checking for stack pointer |
1002 // validity. | 982 // validity. |
1003 uword Simulator::StackTop() const { | 983 uword Simulator::StackTop() const { |
1004 // To be safe in potential stack underflows we leave some buffer above and | 984 // To be safe in potential stack underflows we leave some buffer above and |
1005 // set the stack top. | 985 // set the stack top. |
1006 return StackBase() + | 986 return StackBase() + |
1007 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 987 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
1008 } | 988 } |
1009 | 989 |
1010 | 990 |
1011 bool Simulator::IsTracingExecution() const { | 991 bool Simulator::IsTracingExecution() const { |
1012 return icount_ > FLAG_trace_sim_after; | 992 return icount_ > FLAG_trace_sim_after; |
1013 } | 993 } |
1014 | 994 |
1015 | 995 |
1016 void Simulator::Format(Instr* instr, const char* format) { | 996 void Simulator::Format(Instr* instr, const char* format) { |
1017 OS::PrintErr("Simulator - unknown instruction: %s\n", format); | 997 OS::PrintErr("Simulator - unknown instruction: %s\n", format); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 return CompareExchange(reinterpret_cast<uword*>(address), | 1185 return CompareExchange(reinterpret_cast<uword*>(address), |
1206 static_cast<uword>(compare_value), | 1186 static_cast<uword>(compare_value), |
1207 static_cast<uword>(new_value)); | 1187 static_cast<uword>(new_value)); |
1208 } | 1188 } |
1209 | 1189 |
1210 | 1190 |
1211 // Calls into the Dart runtime are based on this interface. | 1191 // Calls into the Dart runtime are based on this interface. |
1212 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 1192 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
1213 | 1193 |
1214 // Calls to leaf Dart runtime functions are based on this interface. | 1194 // Calls to leaf Dart runtime functions are based on this interface. |
1215 typedef int32_t (*SimulatorLeafRuntimeCall)( | 1195 typedef int32_t (*SimulatorLeafRuntimeCall)(int32_t r0, |
1216 int32_t r0, int32_t r1, int32_t r2, int32_t r3); | 1196 int32_t r1, |
| 1197 int32_t r2, |
| 1198 int32_t r3); |
1217 | 1199 |
1218 // Calls to leaf float Dart runtime functions are based on this interface. | 1200 // Calls to leaf float Dart runtime functions are based on this interface. |
1219 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); | 1201 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
1220 | 1202 |
1221 // Calls to native Dart functions are based on this interface. | 1203 // Calls to native Dart functions are based on this interface. |
1222 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | 1204 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
1223 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | 1205 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
1224 | 1206 |
1225 | 1207 |
1226 void Simulator::DoBreak(Instr *instr) { | 1208 void Simulator::DoBreak(Instr* instr) { |
1227 ASSERT(instr->OpcodeField() == SPECIAL); | 1209 ASSERT(instr->OpcodeField() == SPECIAL); |
1228 ASSERT(instr->FunctionField() == BREAK); | 1210 ASSERT(instr->FunctionField() == BREAK); |
1229 if (instr->BreakCodeField() == Instr::kStopMessageCode) { | 1211 if (instr->BreakCodeField() == Instr::kStopMessageCode) { |
1230 SimulatorDebugger dbg(this); | 1212 SimulatorDebugger dbg(this); |
1231 const char* message = *reinterpret_cast<const char**>( | 1213 const char* message = *reinterpret_cast<const char**>( |
1232 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1214 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1233 set_pc(get_pc() + Instr::kInstrSize); | 1215 set_pc(get_pc() + Instr::kInstrSize); |
1234 dbg.Stop(instr, message); | 1216 dbg.Stop(instr, message); |
1235 // Adjust for extra pc increment. | 1217 // Adjust for extra pc increment. |
1236 set_pc(get_pc() - Instr::kInstrSize); | 1218 set_pc(get_pc() - Instr::kInstrSize); |
1237 } else if (instr->BreakCodeField() == Instr::kSimulatorRedirectCode) { | 1219 } else if (instr->BreakCodeField() == Instr::kSimulatorRedirectCode) { |
1238 SimulatorSetjmpBuffer buffer(this); | 1220 SimulatorSetjmpBuffer buffer(this); |
1239 | 1221 |
1240 if (!setjmp(buffer.buffer_)) { | 1222 if (!setjmp(buffer.buffer_)) { |
1241 int32_t saved_ra = get_register(RA); | 1223 int32_t saved_ra = get_register(RA); |
1242 Redirection* redirection = Redirection::FromBreakInstruction(instr); | 1224 Redirection* redirection = Redirection::FromBreakInstruction(instr); |
1243 uword external = redirection->external_function(); | 1225 uword external = redirection->external_function(); |
1244 if (IsTracingExecution()) { | 1226 if (IsTracingExecution()) { |
1245 THR_Print("Call to host function at 0x%" Pd "\n", external); | 1227 THR_Print("Call to host function at 0x%" Pd "\n", external); |
1246 } | 1228 } |
1247 | 1229 |
1248 if ((redirection->call_kind() == kRuntimeCall) || | 1230 if ((redirection->call_kind() == kRuntimeCall) || |
1249 (redirection->call_kind() == kBootstrapNativeCall) || | 1231 (redirection->call_kind() == kBootstrapNativeCall) || |
1250 (redirection->call_kind() == kNativeCall)) { | 1232 (redirection->call_kind() == kNativeCall)) { |
1251 // Set the top_exit_frame_info of this simulator to the native stack. | 1233 // Set the top_exit_frame_info of this simulator to the native stack. |
1252 set_top_exit_frame_info(Thread::GetCurrentStackPointer()); | 1234 set_top_exit_frame_info(Thread::GetCurrentStackPointer()); |
1253 } | 1235 } |
1254 if (redirection->call_kind() == kRuntimeCall) { | 1236 if (redirection->call_kind() == kRuntimeCall) { |
1255 NativeArguments arguments; | 1237 NativeArguments arguments; |
1256 ASSERT(sizeof(NativeArguments) == 4*kWordSize); | 1238 ASSERT(sizeof(NativeArguments) == 4 * kWordSize); |
1257 arguments.thread_ = reinterpret_cast<Thread*>(get_register(A0)); | 1239 arguments.thread_ = reinterpret_cast<Thread*>(get_register(A0)); |
1258 arguments.argc_tag_ = get_register(A1); | 1240 arguments.argc_tag_ = get_register(A1); |
1259 arguments.argv_ = reinterpret_cast<RawObject**>(get_register(A2)); | 1241 arguments.argv_ = reinterpret_cast<RawObject**>(get_register(A2)); |
1260 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(A3)); | 1242 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(A3)); |
1261 SimulatorRuntimeCall target = | 1243 SimulatorRuntimeCall target = |
1262 reinterpret_cast<SimulatorRuntimeCall>(external); | 1244 reinterpret_cast<SimulatorRuntimeCall>(external); |
1263 target(arguments); | 1245 target(arguments); |
1264 set_register(V0, icount_); // Zap result registers from void function. | 1246 set_register(V0, icount_); // Zap result registers from void function. |
1265 set_register(V1, icount_); | 1247 set_register(V1, icount_); |
1266 } else if (redirection->call_kind() == kLeafRuntimeCall) { | 1248 } else if (redirection->call_kind() == kLeafRuntimeCall) { |
1267 int32_t a0 = get_register(A0); | 1249 int32_t a0 = get_register(A0); |
1268 int32_t a1 = get_register(A1); | 1250 int32_t a1 = get_register(A1); |
1269 int32_t a2 = get_register(A2); | 1251 int32_t a2 = get_register(A2); |
1270 int32_t a3 = get_register(A3); | 1252 int32_t a3 = get_register(A3); |
1271 SimulatorLeafRuntimeCall target = | 1253 SimulatorLeafRuntimeCall target = |
1272 reinterpret_cast<SimulatorLeafRuntimeCall>(external); | 1254 reinterpret_cast<SimulatorLeafRuntimeCall>(external); |
1273 a0 = target(a0, a1, a2, a3); | 1255 a0 = target(a0, a1, a2, a3); |
1274 set_register(V0, a0); // Set returned result from function. | 1256 set_register(V0, a0); // Set returned result from function. |
1275 set_register(V1, icount_); // Zap second result register. | 1257 set_register(V1, icount_); // Zap second result register. |
1276 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { | 1258 } else if (redirection->call_kind() == kLeafFloatRuntimeCall) { |
1277 ASSERT((0 <= redirection->argument_count()) && | 1259 ASSERT((0 <= redirection->argument_count()) && |
1278 (redirection->argument_count() <= 2)); | 1260 (redirection->argument_count() <= 2)); |
1279 // double values are passed and returned in floating point registers. | 1261 // double values are passed and returned in floating point registers. |
1280 SimulatorLeafFloatRuntimeCall target = | 1262 SimulatorLeafFloatRuntimeCall target = |
1281 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); | 1263 reinterpret_cast<SimulatorLeafFloatRuntimeCall>(external); |
1282 double d0 = 0.0; | 1264 double d0 = 0.0; |
1283 double d6 = get_fregister_double(F12); | 1265 double d6 = get_fregister_double(F12); |
1284 double d7 = get_fregister_double(F14); | 1266 double d7 = get_fregister_double(F14); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 } | 1399 } |
1418 set_lo_register(rs_val / rt_val); | 1400 set_lo_register(rs_val / rt_val); |
1419 set_hi_register(rs_val % rt_val); | 1401 set_hi_register(rs_val % rt_val); |
1420 break; | 1402 break; |
1421 } | 1403 } |
1422 case JALR: { | 1404 case JALR: { |
1423 ASSERT(instr->RtField() == R0); | 1405 ASSERT(instr->RtField() == R0); |
1424 ASSERT(instr->RsField() != instr->RdField()); | 1406 ASSERT(instr->RsField() != instr->RdField()); |
1425 ASSERT(!delay_slot_); | 1407 ASSERT(!delay_slot_); |
1426 // Format(instr, "jalr'hint 'rd, rs"); | 1408 // Format(instr, "jalr'hint 'rd, rs"); |
1427 set_register(instr->RdField(), pc_ + 2*Instr::kInstrSize); | 1409 set_register(instr->RdField(), pc_ + 2 * Instr::kInstrSize); |
1428 uword next_pc = get_register(instr->RsField()); | 1410 uword next_pc = get_register(instr->RsField()); |
1429 ExecuteDelaySlot(); | 1411 ExecuteDelaySlot(); |
1430 // Set return address to be the instruction after the delay slot. | 1412 // Set return address to be the instruction after the delay slot. |
1431 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment. | 1413 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment. |
1432 break; | 1414 break; |
1433 } | 1415 } |
1434 case JR: { | 1416 case JR: { |
1435 ASSERT(instr->RtField() == R0); | 1417 ASSERT(instr->RtField() == R0); |
1436 ASSERT(instr->RdField() == R0); | 1418 ASSERT(instr->RdField() == R0); |
1437 ASSERT(!delay_slot_); | 1419 ASSERT(!delay_slot_); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1540 case OR: { | 1522 case OR: { |
1541 ASSERT(instr->SaField() == 0); | 1523 ASSERT(instr->SaField() == 0); |
1542 // Format(instr, "or 'rd, 'rs, 'rt"); | 1524 // Format(instr, "or 'rd, 'rs, 'rt"); |
1543 int32_t rs_val = get_register(instr->RsField()); | 1525 int32_t rs_val = get_register(instr->RsField()); |
1544 int32_t rt_val = get_register(instr->RtField()); | 1526 int32_t rt_val = get_register(instr->RtField()); |
1545 set_register(instr->RdField(), rs_val | rt_val); | 1527 set_register(instr->RdField(), rs_val | rt_val); |
1546 break; | 1528 break; |
1547 } | 1529 } |
1548 case SLL: { | 1530 case SLL: { |
1549 ASSERT(instr->RsField() == 0); | 1531 ASSERT(instr->RsField() == 0); |
1550 if ((instr->RdField() == R0) && | 1532 if ((instr->RdField() == R0) && (instr->RtField() == R0) && |
1551 (instr->RtField() == R0) && | |
1552 (instr->SaField() == 0)) { | 1533 (instr->SaField() == 0)) { |
1553 // Format(instr, "nop"); | 1534 // Format(instr, "nop"); |
1554 // Nothing to be done for NOP. | 1535 // Nothing to be done for NOP. |
1555 } else { | 1536 } else { |
1556 int32_t rt_val = get_register(instr->RtField()); | 1537 int32_t rt_val = get_register(instr->RtField()); |
1557 int sa = instr->SaField(); | 1538 int sa = instr->SaField(); |
1558 set_register(instr->RdField(), rt_val << sa); | 1539 set_register(instr->RdField(), rt_val << sa); |
1559 } | 1540 } |
1560 break; | 1541 break; |
1561 } | 1542 } |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1738 switch (instr->RegImmFnField()) { | 1719 switch (instr->RegImmFnField()) { |
1739 case BGEZ: { | 1720 case BGEZ: { |
1740 // Format(instr, "bgez 'rs, 'dest"); | 1721 // Format(instr, "bgez 'rs, 'dest"); |
1741 int32_t rs_val = get_register(instr->RsField()); | 1722 int32_t rs_val = get_register(instr->RsField()); |
1742 DoBranch(instr, rs_val >= 0, false); | 1723 DoBranch(instr, rs_val >= 0, false); |
1743 break; | 1724 break; |
1744 } | 1725 } |
1745 case BGEZAL: { | 1726 case BGEZAL: { |
1746 int32_t rs_val = get_register(instr->RsField()); | 1727 int32_t rs_val = get_register(instr->RsField()); |
1747 // Return address is one after the delay slot. | 1728 // Return address is one after the delay slot. |
1748 set_register(RA, pc_ + (2*Instr::kInstrSize)); | 1729 set_register(RA, pc_ + (2 * Instr::kInstrSize)); |
1749 DoBranch(instr, rs_val >= 0, false); | 1730 DoBranch(instr, rs_val >= 0, false); |
1750 break; | 1731 break; |
1751 } | 1732 } |
1752 case BLTZAL: { | 1733 case BLTZAL: { |
1753 int32_t rs_val = get_register(instr->RsField()); | 1734 int32_t rs_val = get_register(instr->RsField()); |
1754 // Return address is one after the delay slot. | 1735 // Return address is one after the delay slot. |
1755 set_register(RA, pc_ + (2*Instr::kInstrSize)); | 1736 set_register(RA, pc_ + (2 * Instr::kInstrSize)); |
1756 DoBranch(instr, rs_val < 0, false); | 1737 DoBranch(instr, rs_val < 0, false); |
1757 break; | 1738 break; |
1758 } | 1739 } |
1759 case BGEZL: { | 1740 case BGEZL: { |
1760 // Format(instr, "bgezl 'rs, 'dest"); | 1741 // Format(instr, "bgezl 'rs, 'dest"); |
1761 int32_t rs_val = get_register(instr->RsField()); | 1742 int32_t rs_val = get_register(instr->RsField()); |
1762 DoBranch(instr, rs_val >= 0, true); | 1743 DoBranch(instr, rs_val >= 0, true); |
1763 break; | 1744 break; |
1764 } | 1745 } |
1765 case BLTZ: { | 1746 case BLTZ: { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1851 case COP1_C_EQ: { | 1832 case COP1_C_EQ: { |
1852 ASSERT(instr->FormatField() == FMT_D); // Only D supported. | 1833 ASSERT(instr->FormatField() == FMT_D); // Only D supported. |
1853 ASSERT(instr->FdField() == F0); | 1834 ASSERT(instr->FdField() == F0); |
1854 set_fcsr_bit(fcsr_cc, (fs_val == ft_val)); | 1835 set_fcsr_bit(fcsr_cc, (fs_val == ft_val)); |
1855 break; | 1836 break; |
1856 } | 1837 } |
1857 case COP1_C_UEQ: { | 1838 case COP1_C_UEQ: { |
1858 ASSERT(instr->FormatField() == FMT_D); // Only D supported. | 1839 ASSERT(instr->FormatField() == FMT_D); // Only D supported. |
1859 ASSERT(instr->FdField() == F0); | 1840 ASSERT(instr->FdField() == F0); |
1860 set_fcsr_bit(fcsr_cc, | 1841 set_fcsr_bit(fcsr_cc, |
1861 (fs_val == ft_val) || isnan(fs_val) || isnan(ft_val)); | 1842 (fs_val == ft_val) || isnan(fs_val) || isnan(ft_val)); |
1862 break; | 1843 break; |
1863 } | 1844 } |
1864 case COP1_C_OLT: { | 1845 case COP1_C_OLT: { |
1865 ASSERT(instr->FormatField() == FMT_D); // Only D supported. | 1846 ASSERT(instr->FormatField() == FMT_D); // Only D supported. |
1866 ASSERT(instr->FdField() == F0); | 1847 ASSERT(instr->FdField() == F0); |
1867 set_fcsr_bit(fcsr_cc, (fs_val < ft_val)); | 1848 set_fcsr_bit(fcsr_cc, (fs_val < ft_val)); |
1868 break; | 1849 break; |
1869 } | 1850 } |
1870 case COP1_C_ULT: { | 1851 case COP1_C_ULT: { |
1871 ASSERT(instr->FormatField() == FMT_D); // Only D supported. | 1852 ASSERT(instr->FormatField() == FMT_D); // Only D supported. |
1872 ASSERT(instr->FdField() == F0); | 1853 ASSERT(instr->FdField() == F0); |
1873 set_fcsr_bit(fcsr_cc, | 1854 set_fcsr_bit(fcsr_cc, |
1874 (fs_val < ft_val) || isnan(fs_val) || isnan(ft_val)); | 1855 (fs_val < ft_val) || isnan(fs_val) || isnan(ft_val)); |
1875 break; | 1856 break; |
1876 } | 1857 } |
1877 case COP1_C_OLE: { | 1858 case COP1_C_OLE: { |
1878 ASSERT(instr->FormatField() == FMT_D); // Only D supported. | 1859 ASSERT(instr->FormatField() == FMT_D); // Only D supported. |
1879 ASSERT(instr->FdField() == F0); | 1860 ASSERT(instr->FdField() == F0); |
1880 set_fcsr_bit(fcsr_cc, (fs_val <= ft_val)); | 1861 set_fcsr_bit(fcsr_cc, (fs_val <= ft_val)); |
1881 break; | 1862 break; |
1882 } | 1863 } |
1883 case COP1_C_ULE: { | 1864 case COP1_C_ULE: { |
1884 ASSERT(instr->FormatField() == FMT_D); // Only D supported. | 1865 ASSERT(instr->FormatField() == FMT_D); // Only D supported. |
1885 ASSERT(instr->FdField() == F0); | 1866 ASSERT(instr->FdField() == F0); |
1886 set_fcsr_bit(fcsr_cc, | 1867 set_fcsr_bit(fcsr_cc, |
1887 (fs_val <= ft_val) || isnan(fs_val) || isnan(ft_val)); | 1868 (fs_val <= ft_val) || isnan(fs_val) || isnan(ft_val)); |
1888 break; | 1869 break; |
1889 } | 1870 } |
1890 case COP1_TRUNC_W: { | 1871 case COP1_TRUNC_W: { |
1891 switch (instr->FormatField()) { | 1872 switch (instr->FormatField()) { |
1892 case FMT_D: { | 1873 case FMT_D: { |
1893 double fs_dbl = get_fregister_double(instr->FsField()); | 1874 double fs_dbl = get_fregister_double(instr->FsField()); |
1894 int32_t fs_int; | 1875 int32_t fs_int; |
1895 if (isnan(fs_dbl) || isinf(fs_dbl) || (fs_dbl > kMaxInt32) || | 1876 if (isnan(fs_dbl) || isinf(fs_dbl) || (fs_dbl > kMaxInt32) || |
1896 (fs_dbl < kMinInt32)) { | 1877 (fs_dbl < kMinInt32)) { |
1897 fs_int = kMaxInt32; | 1878 fs_int = kMaxInt32; |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2303 } | 2284 } |
2304 case XORI: { | 2285 case XORI: { |
2305 // Format(instr, "xori 'rt, 'rs, 'immu"); | 2286 // Format(instr, "xori 'rt, 'rs, 'immu"); |
2306 int32_t rs_val = get_register(instr->RsField()); | 2287 int32_t rs_val = get_register(instr->RsField()); |
2307 set_register(instr->RtField(), rs_val ^ instr->UImmField()); | 2288 set_register(instr->RtField(), rs_val ^ instr->UImmField()); |
2308 break; | 2289 break; |
2309 break; | 2290 break; |
2310 } | 2291 } |
2311 default: { | 2292 default: { |
2312 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", | 2293 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", |
2313 instr->InstructionBits(), instr); | 2294 instr->InstructionBits(), instr); |
2314 UnimplementedInstruction(instr); | 2295 UnimplementedInstruction(instr); |
2315 break; | 2296 break; |
2316 } | 2297 } |
2317 } | 2298 } |
2318 pc_ += Instr::kInstrSize; | 2299 pc_ += Instr::kInstrSize; |
2319 } | 2300 } |
2320 | 2301 |
2321 | 2302 |
2322 void Simulator::ExecuteDelaySlot() { | 2303 void Simulator::ExecuteDelaySlot() { |
2323 ASSERT(pc_ != kEndSimulatingPC); | 2304 ASSERT(pc_ != kEndSimulatingPC); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2524 set_register(THR, reinterpret_cast<int32_t>(thread)); | 2505 set_register(THR, reinterpret_cast<int32_t>(thread)); |
2525 // Set the tag. | 2506 // Set the tag. |
2526 thread->set_vm_tag(VMTag::kDartTagId); | 2507 thread->set_vm_tag(VMTag::kDartTagId); |
2527 // Clear top exit frame. | 2508 // Clear top exit frame. |
2528 thread->set_top_exit_frame_info(0); | 2509 thread->set_top_exit_frame_info(0); |
2529 | 2510 |
2530 ASSERT(raw_exception != Object::null()); | 2511 ASSERT(raw_exception != Object::null()); |
2531 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 2512 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
2532 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 2513 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
2533 // Restore pool pointer. | 2514 // Restore pool pointer. |
2534 int32_t code = *reinterpret_cast<int32_t*>( | 2515 int32_t code = |
2535 fp + kPcMarkerSlotFromFp * kWordSize); | 2516 *reinterpret_cast<int32_t*>(fp + kPcMarkerSlotFromFp * kWordSize); |
2536 int32_t pp = *reinterpret_cast<int32_t*>( | 2517 int32_t pp = *reinterpret_cast<int32_t*>(code + Code::object_pool_offset() - |
2537 code + Code::object_pool_offset() - kHeapObjectTag); | 2518 kHeapObjectTag); |
2538 set_register(CODE_REG, code); | 2519 set_register(CODE_REG, code); |
2539 set_register(PP, pp); | 2520 set_register(PP, pp); |
2540 buf->Longjmp(); | 2521 buf->Longjmp(); |
2541 } | 2522 } |
2542 | 2523 |
2543 } // namespace dart | 2524 } // namespace dart |
2544 | 2525 |
2545 #endif // defined(USING_SIMULATOR) | 2526 #endif // defined(USING_SIMULATOR) |
2546 | 2527 |
2547 #endif // defined TARGET_ARCH_MIPS | 2528 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |