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(HOST_ARCH_MIPS) | 12 #if !defined(HOST_ARCH_MIPS) |
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(int, trace_sim_after, -1, | 26 DEFINE_FLAG(uint64_t, trace_sim_after, ULLONG_MAX, |
27 "Trace simulator execution after instruction count reached."); | 27 "Trace simulator execution after instruction count reached."); |
28 DEFINE_FLAG(int, stop_sim_at, -1, | 28 DEFINE_FLAG(uint64_t, stop_sim_at, ULLONG_MAX, |
29 "Instruction address or instruction count to stop simulator at."); | 29 "Instruction address or instruction count to stop simulator at."); |
30 | 30 |
31 | 31 |
32 // This macro provides a platform independent use of sscanf. The reason for | 32 // This macro provides a platform independent use of sscanf. The reason for |
33 // SScanF not being implemented in a platform independent way through | 33 // 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 | 34 // OS in the same way as SNPrint is that the Windows C Run-Time |
35 // Library does not provide vsscanf. | 35 // Library does not provide vsscanf. |
36 #define SScanF sscanf // NOLINT | 36 #define SScanF sscanf // NOLINT |
37 | 37 |
38 | 38 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 return false; | 204 return false; |
205 } | 205 } |
206 *value = *(reinterpret_cast<uint32_t*>(addr)); | 206 *value = *(reinterpret_cast<uint32_t*>(addr)); |
207 return true; | 207 return true; |
208 } | 208 } |
209 } | 209 } |
210 if (strcmp("pc", desc) == 0) { | 210 if (strcmp("pc", desc) == 0) { |
211 *value = sim_->get_pc(); | 211 *value = sim_->get_pc(); |
212 return true; | 212 return true; |
213 } | 213 } |
214 if (strcmp("icount", desc) == 0) { | |
215 *value = sim_->get_icount(); | |
216 return true; | |
217 } | |
218 bool retval = SScanF(desc, "0x%x", value) == 1; | 214 bool retval = SScanF(desc, "0x%x", value) == 1; |
219 if (!retval) { | 215 if (!retval) { |
220 retval = SScanF(desc, "%x", value) == 1; | 216 retval = SScanF(desc, "%x", value) == 1; |
221 } | 217 } |
222 return retval; | 218 return retval; |
223 } | 219 } |
224 | 220 |
225 | 221 |
226 bool SimulatorDebugger::GetFValue(char* desc, double* value) { | 222 bool SimulatorDebugger::GetFValue(char* desc, double* value) { |
227 FRegister freg = LookupFRegisterByName(desc); | 223 FRegister freg = LookupFRegisterByName(desc); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 460 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
465 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 461 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
466 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 462 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
467 // Execute the one instruction we broke at with breakpoints disabled. | 463 // Execute the one instruction we broke at with breakpoints disabled. |
468 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 464 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
469 // Leave the debugger shell. | 465 // Leave the debugger shell. |
470 done = true; | 466 done = true; |
471 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 467 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
472 if (args == 2) { | 468 if (args == 2) { |
473 uint32_t value; | 469 uint32_t value; |
474 if (GetValue(arg1, &value)) { | 470 if (strcmp(arg1, "icount") == 0) { |
| 471 const uint64_t icount = sim_->get_icount(); |
| 472 OS::Print("icount: %"Pu64" 0x%"Px64"\n", icount, icount); |
| 473 } else if (GetValue(arg1, &value)) { |
475 OS::Print("%s: %u 0x%x\n", arg1, value, value); | 474 OS::Print("%s: %u 0x%x\n", arg1, value, value); |
476 } else { | 475 } else { |
477 OS::Print("%s unrecognized\n", arg1); | 476 OS::Print("%s unrecognized\n", arg1); |
478 } | 477 } |
479 } else { | 478 } else { |
480 OS::Print("print <reg or value or *addr>\n"); | 479 OS::Print("print <reg or icount or value or *addr>\n"); |
481 } | 480 } |
482 } else if ((strcmp(cmd, "pf") == 0) || | 481 } else if ((strcmp(cmd, "pf") == 0) || |
483 (strcmp(cmd, "printfloat") == 0)) { | 482 (strcmp(cmd, "printfloat") == 0)) { |
484 if (args == 2) { | 483 if (args == 2) { |
485 double dvalue; | 484 double dvalue; |
486 if (GetFValue(arg1, &dvalue)) { | 485 if (GetFValue(arg1, &dvalue)) { |
487 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); | 486 uint64_t long_value = bit_cast<uint64_t, double>(dvalue); |
488 OS::Print("%s: %llu 0x%llx %.8g\n", | 487 OS::Print("%s: %llu 0x%llx %.8g\n", |
489 arg1, long_value, long_value, dvalue); | 488 arg1, long_value, long_value, dvalue); |
490 } else { | 489 } else { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 } | 586 } |
588 } else if (strcmp(cmd, "unstop") == 0) { | 587 } else if (strcmp(cmd, "unstop") == 0) { |
589 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 588 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
590 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 589 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
591 if (stop_instr->IsBreakPoint()) { | 590 if (stop_instr->IsBreakPoint()) { |
592 stop_instr->SetInstructionBits(Instr::kNopInstruction); | 591 stop_instr->SetInstructionBits(Instr::kNopInstruction); |
593 } else { | 592 } else { |
594 OS::Print("Not at debugger stop.\n"); | 593 OS::Print("Not at debugger stop.\n"); |
595 } | 594 } |
596 } else if (strcmp(cmd, "trace") == 0) { | 595 } else if (strcmp(cmd, "trace") == 0) { |
597 if (FLAG_trace_sim_after == -1) { | 596 if (FLAG_trace_sim_after == ULLONG_MAX) { |
598 FLAG_trace_sim_after = sim_->get_icount(); | 597 FLAG_trace_sim_after = sim_->get_icount(); |
599 OS::Print("execution tracing on\n"); | 598 OS::Print("execution tracing on\n"); |
600 } else { | 599 } else { |
601 FLAG_trace_sim_after = -1; | 600 FLAG_trace_sim_after = ULLONG_MAX; |
602 OS::Print("execution tracing off\n"); | 601 OS::Print("execution tracing off\n"); |
603 } | 602 } |
604 } else if (strcmp(cmd, "bt") == 0) { | 603 } else if (strcmp(cmd, "bt") == 0) { |
605 PrintBacktrace(); | 604 PrintBacktrace(); |
606 } else { | 605 } else { |
607 OS::Print("Unknown command: %s\n", cmd); | 606 OS::Print("Unknown command: %s\n", cmd); |
608 } | 607 } |
609 } | 608 } |
610 delete[] line; | 609 delete[] line; |
611 } | 610 } |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 // validity. | 998 // validity. |
1000 uword Simulator::StackTop() const { | 999 uword Simulator::StackTop() const { |
1001 // To be safe in potential stack underflows we leave some buffer above and | 1000 // To be safe in potential stack underflows we leave some buffer above and |
1002 // set the stack top. | 1001 // set the stack top. |
1003 return reinterpret_cast<uword>(stack_) + | 1002 return reinterpret_cast<uword>(stack_) + |
1004 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); | 1003 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); |
1005 } | 1004 } |
1006 | 1005 |
1007 | 1006 |
1008 bool Simulator::IsTracingExecution() const { | 1007 bool Simulator::IsTracingExecution() const { |
1009 // Integer flag values are signed, so we must cast to unsigned. | 1008 return icount_ > FLAG_trace_sim_after; |
1010 // The default of -1 hence becomes the maximum unsigned value. | |
1011 return (static_cast<uintptr_t>(icount_) > | |
1012 static_cast<uintptr_t>(FLAG_trace_sim_after)); | |
1013 } | 1009 } |
1014 | 1010 |
1015 | 1011 |
1016 void Simulator::Format(Instr* instr, const char* format) { | 1012 void Simulator::Format(Instr* instr, const char* format) { |
1017 OS::PrintErr("Simulator - unknown instruction: %s\n", format); | 1013 OS::PrintErr("Simulator - unknown instruction: %s\n", format); |
1018 UNIMPLEMENTED(); | 1014 UNIMPLEMENTED(); |
1019 } | 1015 } |
1020 | 1016 |
1021 | 1017 |
1022 int8_t Simulator::ReadB(uword addr) { | 1018 int8_t Simulator::ReadB(uword addr) { |
(...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1982 UnimplementedInstruction(instr); | 1978 UnimplementedInstruction(instr); |
1983 break; | 1979 break; |
1984 } | 1980 } |
1985 } | 1981 } |
1986 } | 1982 } |
1987 } | 1983 } |
1988 | 1984 |
1989 | 1985 |
1990 void Simulator::InstructionDecode(Instr* instr) { | 1986 void Simulator::InstructionDecode(Instr* instr) { |
1991 if (IsTracingExecution()) { | 1987 if (IsTracingExecution()) { |
1992 OS::Print("%" Pd " ", icount_); | 1988 OS::Print("%"Pu64, icount_); |
1993 const uword start = reinterpret_cast<uword>(instr); | 1989 const uword start = reinterpret_cast<uword>(instr); |
1994 const uword end = start + Instr::kInstrSize; | 1990 const uword end = start + Instr::kInstrSize; |
1995 Disassembler::Disassemble(start, end); | 1991 Disassembler::Disassemble(start, end); |
1996 } | 1992 } |
1997 | 1993 |
1998 switch (instr->OpcodeField()) { | 1994 switch (instr->OpcodeField()) { |
1999 case SPECIAL: { | 1995 case SPECIAL: { |
2000 DecodeSpecial(instr); | 1996 DecodeSpecial(instr); |
2001 break; | 1997 break; |
2002 } | 1998 } |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2281 } | 2277 } |
2282 pc_ += Instr::kInstrSize; | 2278 pc_ += Instr::kInstrSize; |
2283 } | 2279 } |
2284 | 2280 |
2285 | 2281 |
2286 void Simulator::ExecuteDelaySlot() { | 2282 void Simulator::ExecuteDelaySlot() { |
2287 ASSERT(pc_ != kEndSimulatingPC); | 2283 ASSERT(pc_ != kEndSimulatingPC); |
2288 delay_slot_ = true; | 2284 delay_slot_ = true; |
2289 icount_++; | 2285 icount_++; |
2290 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); | 2286 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); |
2291 if (FLAG_stop_sim_at != -1) { | 2287 if (FLAG_stop_sim_at != ULLONG_MAX) { |
2292 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { | 2288 if (icount_ == FLAG_stop_sim_at) { |
2293 SimulatorDebugger dbg(this); | 2289 SimulatorDebugger dbg(this); |
2294 dbg.Stop(instr, "Instruction count reached"); | 2290 dbg.Stop(instr, "Instruction count reached"); |
2295 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { | 2291 } else if (reinterpret_cast<uint64_t>(instr) == FLAG_stop_sim_at) { |
2296 SimulatorDebugger dbg(this); | 2292 SimulatorDebugger dbg(this); |
2297 dbg.Stop(instr, "Instruction address reached"); | 2293 dbg.Stop(instr, "Instruction address reached"); |
2298 } | 2294 } |
2299 } | 2295 } |
2300 InstructionDecode(instr); | 2296 InstructionDecode(instr); |
2301 delay_slot_ = false; | 2297 delay_slot_ = false; |
2302 } | 2298 } |
2303 | 2299 |
2304 | 2300 |
2305 void Simulator::Execute() { | 2301 void Simulator::Execute() { |
2306 if (FLAG_stop_sim_at == -1) { | 2302 if (FLAG_stop_sim_at == ULLONG_MAX) { |
2307 // Fast version of the dispatch loop without checking whether the simulator | 2303 // Fast version of the dispatch loop without checking whether the simulator |
2308 // should be stopping at a particular executed instruction. | 2304 // should be stopping at a particular executed instruction. |
2309 while (pc_ != kEndSimulatingPC) { | 2305 while (pc_ != kEndSimulatingPC) { |
2310 icount_++; | 2306 icount_++; |
2311 Instr* instr = Instr::At(pc_); | 2307 Instr* instr = Instr::At(pc_); |
2312 if (IsIllegalAddress(pc_)) { | 2308 if (IsIllegalAddress(pc_)) { |
2313 HandleIllegalAccess(pc_, instr); | 2309 HandleIllegalAccess(pc_, instr); |
2314 } else { | 2310 } else { |
2315 InstructionDecode(instr); | 2311 InstructionDecode(instr); |
2316 } | 2312 } |
2317 } | 2313 } |
2318 } else { | 2314 } else { |
2319 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 2315 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
2320 // we reach the particular instruction count or address. | 2316 // we reach the particular instruction count or address. |
2321 while (pc_ != kEndSimulatingPC) { | 2317 while (pc_ != kEndSimulatingPC) { |
2322 Instr* instr = Instr::At(pc_); | 2318 Instr* instr = Instr::At(pc_); |
2323 icount_++; | 2319 icount_++; |
2324 if (static_cast<intptr_t>(icount_) == FLAG_stop_sim_at) { | 2320 if (icount_ == FLAG_stop_sim_at) { |
2325 SimulatorDebugger dbg(this); | 2321 SimulatorDebugger dbg(this); |
2326 dbg.Stop(instr, "Instruction count reached"); | 2322 dbg.Stop(instr, "Instruction count reached"); |
2327 } else if (reinterpret_cast<intptr_t>(instr) == FLAG_stop_sim_at) { | 2323 } else if (reinterpret_cast<uint64_t>(instr) == FLAG_stop_sim_at) { |
2328 SimulatorDebugger dbg(this); | 2324 SimulatorDebugger dbg(this); |
2329 dbg.Stop(instr, "Instruction address reached"); | 2325 dbg.Stop(instr, "Instruction address reached"); |
2330 } else if (IsIllegalAddress(pc_)) { | 2326 } else if (IsIllegalAddress(pc_)) { |
2331 HandleIllegalAccess(pc_, instr); | 2327 HandleIllegalAccess(pc_, instr); |
2332 } else { | 2328 } else { |
2333 InstructionDecode(instr); | 2329 InstructionDecode(instr); |
2334 } | 2330 } |
2335 } | 2331 } |
2336 } | 2332 } |
2337 } | 2333 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2498 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 2494 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
2499 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 2495 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
2500 buf->Longjmp(); | 2496 buf->Longjmp(); |
2501 } | 2497 } |
2502 | 2498 |
2503 } // namespace dart | 2499 } // namespace dart |
2504 | 2500 |
2505 #endif // !defined(HOST_ARCH_MIPS) | 2501 #endif // !defined(HOST_ARCH_MIPS) |
2506 | 2502 |
2507 #endif // defined TARGET_ARCH_MIPS | 2503 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |