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> | 5 #include <setjmp.h> |
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/thread.h" | 22 #include "vm/thread.h" |
23 | 23 |
24 namespace dart { | 24 namespace dart { |
25 | 25 |
26 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); | 26 DEFINE_FLAG(int, trace_sim_after, -1, |
27 DEFINE_FLAG(int, stop_sim_at, 0, | 27 "Trace simulator execution after instruction count reached."); |
| 28 DEFINE_FLAG(int, stop_sim_at, -1, |
28 "Instruction address or instruction count to stop simulator at."); | 29 "Instruction address or instruction count to stop simulator at."); |
29 | 30 |
30 | 31 |
31 // 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 |
32 // SScanF not being implemented in a platform independent way through | 33 // SScanF not being implemented in a platform independent way through |
33 // 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 |
34 // Library does not provide vsscanf. | 35 // Library does not provide vsscanf. |
35 #define SScanF sscanf // NOLINT | 36 #define SScanF sscanf // NOLINT |
36 | 37 |
37 | 38 |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 } | 586 } |
586 } else if (strcmp(cmd, "unstop") == 0) { | 587 } else if (strcmp(cmd, "unstop") == 0) { |
587 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 588 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
588 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 589 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
589 if (stop_instr->IsBreakPoint()) { | 590 if (stop_instr->IsBreakPoint()) { |
590 stop_instr->SetInstructionBits(Instr::kNopInstruction); | 591 stop_instr->SetInstructionBits(Instr::kNopInstruction); |
591 } else { | 592 } else { |
592 OS::Print("Not at debugger stop.\n"); | 593 OS::Print("Not at debugger stop.\n"); |
593 } | 594 } |
594 } else if (strcmp(cmd, "trace") == 0) { | 595 } else if (strcmp(cmd, "trace") == 0) { |
595 FLAG_trace_sim = !FLAG_trace_sim; | 596 if (FLAG_trace_sim_after == -1) { |
596 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); | 597 FLAG_trace_sim_after = sim_->get_icount(); |
| 598 OS::Print("execution tracing on\n"); |
| 599 } else { |
| 600 FLAG_trace_sim_after = -1; |
| 601 OS::Print("execution tracing off\n"); |
| 602 } |
597 } else if (strcmp(cmd, "bt") == 0) { | 603 } else if (strcmp(cmd, "bt") == 0) { |
598 PrintBacktrace(); | 604 PrintBacktrace(); |
599 } else { | 605 } else { |
600 OS::Print("Unknown command: %s\n", cmd); | 606 OS::Print("Unknown command: %s\n", cmd); |
601 } | 607 } |
602 } | 608 } |
603 delete[] line; | 609 delete[] line; |
604 } | 610 } |
605 | 611 |
606 // Add all the breakpoints back to stop execution and enter the debugger | 612 // Add all the breakpoints back to stop execution and enter the debugger |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 // Returns the top of the stack area to enable checking for stack pointer | 987 // Returns the top of the stack area to enable checking for stack pointer |
982 // validity. | 988 // validity. |
983 uword Simulator::StackTop() const { | 989 uword Simulator::StackTop() const { |
984 // To be safe in potential stack underflows we leave some buffer above and | 990 // To be safe in potential stack underflows we leave some buffer above and |
985 // set the stack top. | 991 // set the stack top. |
986 return reinterpret_cast<uword>(stack_) + | 992 return reinterpret_cast<uword>(stack_) + |
987 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); | 993 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); |
988 } | 994 } |
989 | 995 |
990 | 996 |
| 997 bool Simulator::IsTracingExecution() const { |
| 998 // Integer flag values are signed, so we must cast to unsigned. |
| 999 // The default of -1 hence becomes the maximum unsigned value. |
| 1000 return (static_cast<uintptr_t>(icount_) > |
| 1001 static_cast<uintptr_t>(FLAG_trace_sim_after)); |
| 1002 } |
| 1003 |
| 1004 |
991 void Simulator::Format(Instr* instr, const char* format) { | 1005 void Simulator::Format(Instr* instr, const char* format) { |
992 OS::PrintErr("Simulator - unknown instruction: %s\n", format); | 1006 OS::PrintErr("Simulator - unknown instruction: %s\n", format); |
993 UNIMPLEMENTED(); | 1007 UNIMPLEMENTED(); |
994 } | 1008 } |
995 | 1009 |
996 | 1010 |
997 int8_t Simulator::ReadB(uword addr) { | 1011 int8_t Simulator::ReadB(uword addr) { |
998 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 1012 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
999 return *ptr; | 1013 return *ptr; |
1000 } | 1014 } |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1195 SimulatorDebugger dbg(this); | 1209 SimulatorDebugger dbg(this); |
1196 const char* message = *reinterpret_cast<const char**>( | 1210 const char* message = *reinterpret_cast<const char**>( |
1197 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1211 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1198 set_pc(get_pc() + Instr::kInstrSize); | 1212 set_pc(get_pc() + Instr::kInstrSize); |
1199 dbg.Stop(instr, message); | 1213 dbg.Stop(instr, message); |
1200 // Adjust for extra pc increment. | 1214 // Adjust for extra pc increment. |
1201 set_pc(get_pc() - Instr::kInstrSize); | 1215 set_pc(get_pc() - Instr::kInstrSize); |
1202 } else if (instr->BreakCodeField() == Instr::kSimulatorMessageCode) { | 1216 } else if (instr->BreakCodeField() == Instr::kSimulatorMessageCode) { |
1203 const char* message = *reinterpret_cast<const char**>( | 1217 const char* message = *reinterpret_cast<const char**>( |
1204 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1218 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1205 if (FLAG_trace_sim) { | 1219 if (IsTracingExecution()) { |
1206 OS::Print("Message: %s\n", message); | 1220 OS::Print("Message: %s\n", message); |
1207 } else { | |
1208 OS::PrintErr("Bad break code: 0x%x\n", instr->InstructionBits()); | |
1209 UnimplementedInstruction(instr); | |
1210 } | 1221 } |
1211 } else if (instr->BreakCodeField() == Instr::kSimulatorRedirectCode) { | 1222 } else if (instr->BreakCodeField() == Instr::kSimulatorRedirectCode) { |
1212 SimulatorSetjmpBuffer buffer(this); | 1223 SimulatorSetjmpBuffer buffer(this); |
1213 | 1224 |
1214 if (!setjmp(buffer.buffer_)) { | 1225 if (!setjmp(buffer.buffer_)) { |
1215 int32_t saved_ra = get_register(RA); | 1226 int32_t saved_ra = get_register(RA); |
1216 Redirection* redirection = Redirection::FromBreakInstruction(instr); | 1227 Redirection* redirection = Redirection::FromBreakInstruction(instr); |
1217 uword external = redirection->external_function(); | 1228 uword external = redirection->external_function(); |
1218 if (FLAG_trace_sim) { | 1229 if (IsTracingExecution()) { |
1219 OS::Print("Call to host function at 0x%" Pd "\n", external); | 1230 OS::Print("Call to host function at 0x%" Pd "\n", external); |
1220 } | 1231 } |
1221 | 1232 |
1222 if ((redirection->call_kind() == kRuntimeCall) || | 1233 if ((redirection->call_kind() == kRuntimeCall) || |
1223 (redirection->call_kind() == kBootstrapNativeCall) || | 1234 (redirection->call_kind() == kBootstrapNativeCall) || |
1224 (redirection->call_kind() == kNativeCall)) { | 1235 (redirection->call_kind() == kNativeCall)) { |
1225 // Set the top_exit_frame_info of this simulator to the native stack. | 1236 // Set the top_exit_frame_info of this simulator to the native stack. |
1226 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); | 1237 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
1227 } | 1238 } |
1228 if (redirection->call_kind() == kRuntimeCall) { | 1239 if (redirection->call_kind() == kRuntimeCall) { |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1959 OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits()); | 1970 OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits()); |
1960 UnimplementedInstruction(instr); | 1971 UnimplementedInstruction(instr); |
1961 break; | 1972 break; |
1962 } | 1973 } |
1963 } | 1974 } |
1964 } | 1975 } |
1965 } | 1976 } |
1966 | 1977 |
1967 | 1978 |
1968 void Simulator::InstructionDecode(Instr* instr) { | 1979 void Simulator::InstructionDecode(Instr* instr) { |
1969 if (FLAG_trace_sim) { | 1980 if (IsTracingExecution()) { |
| 1981 OS::Print("%u ", icount_); |
1970 const uword start = reinterpret_cast<uword>(instr); | 1982 const uword start = reinterpret_cast<uword>(instr); |
1971 const uword end = start + Instr::kInstrSize; | 1983 const uword end = start + Instr::kInstrSize; |
1972 Disassembler::Disassemble(start, end); | 1984 Disassembler::Disassemble(start, end); |
1973 } | 1985 } |
1974 | 1986 |
1975 switch (instr->OpcodeField()) { | 1987 switch (instr->OpcodeField()) { |
1976 case SPECIAL: { | 1988 case SPECIAL: { |
1977 DecodeSpecial(instr); | 1989 DecodeSpecial(instr); |
1978 break; | 1990 break; |
1979 } | 1991 } |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2258 } | 2270 } |
2259 pc_ += Instr::kInstrSize; | 2271 pc_ += Instr::kInstrSize; |
2260 } | 2272 } |
2261 | 2273 |
2262 | 2274 |
2263 void Simulator::ExecuteDelaySlot() { | 2275 void Simulator::ExecuteDelaySlot() { |
2264 ASSERT(pc_ != kEndSimulatingPC); | 2276 ASSERT(pc_ != kEndSimulatingPC); |
2265 delay_slot_ = true; | 2277 delay_slot_ = true; |
2266 icount_++; | 2278 icount_++; |
2267 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); | 2279 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); |
2268 if (FLAG_stop_sim_at != 0) { | 2280 if (FLAG_stop_sim_at != -1) { |
2269 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { | 2281 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { |
2270 SimulatorDebugger dbg(this); | 2282 SimulatorDebugger dbg(this); |
2271 dbg.Stop(instr, "Instruction count reached"); | 2283 dbg.Stop(instr, "Instruction count reached"); |
2272 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { | 2284 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { |
2273 SimulatorDebugger dbg(this); | 2285 SimulatorDebugger dbg(this); |
2274 dbg.Stop(instr, "Instruction address reached"); | 2286 dbg.Stop(instr, "Instruction address reached"); |
2275 } | 2287 } |
2276 } | 2288 } |
2277 InstructionDecode(instr); | 2289 InstructionDecode(instr); |
2278 delay_slot_ = false; | 2290 delay_slot_ = false; |
2279 } | 2291 } |
2280 | 2292 |
2281 | 2293 |
2282 void Simulator::Execute() { | 2294 void Simulator::Execute() { |
2283 if (FLAG_stop_sim_at == 0) { | 2295 if (FLAG_stop_sim_at == -1) { |
2284 // Fast version of the dispatch loop without checking whether the simulator | 2296 // Fast version of the dispatch loop without checking whether the simulator |
2285 // should be stopping at a particular executed instruction. | 2297 // should be stopping at a particular executed instruction. |
2286 while (pc_ != kEndSimulatingPC) { | 2298 while (pc_ != kEndSimulatingPC) { |
2287 icount_++; | 2299 icount_++; |
2288 Instr* instr = Instr::At(pc_); | 2300 Instr* instr = Instr::At(pc_); |
2289 if (IsIllegalAddress(pc_)) { | 2301 if (IsIllegalAddress(pc_)) { |
2290 HandleIllegalAccess(pc_, instr); | 2302 HandleIllegalAccess(pc_, instr); |
2291 } else { | 2303 } else { |
2292 InstructionDecode(instr); | 2304 InstructionDecode(instr); |
2293 } | 2305 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2475 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 2487 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
2476 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 2488 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
2477 buf->Longjmp(); | 2489 buf->Longjmp(); |
2478 } | 2490 } |
2479 | 2491 |
2480 } // namespace dart | 2492 } // namespace dart |
2481 | 2493 |
2482 #endif // !defined(HOST_ARCH_MIPS) | 2494 #endif // !defined(HOST_ARCH_MIPS) |
2483 | 2495 |
2484 #endif // defined TARGET_ARCH_MIPS | 2496 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |