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 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1195 SimulatorDebugger dbg(this); | 1201 SimulatorDebugger dbg(this); |
1196 const char* message = *reinterpret_cast<const char**>( | 1202 const char* message = *reinterpret_cast<const char**>( |
1197 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1203 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1198 set_pc(get_pc() + Instr::kInstrSize); | 1204 set_pc(get_pc() + Instr::kInstrSize); |
1199 dbg.Stop(instr, message); | 1205 dbg.Stop(instr, message); |
1200 // Adjust for extra pc increment. | 1206 // Adjust for extra pc increment. |
1201 set_pc(get_pc() - Instr::kInstrSize); | 1207 set_pc(get_pc() - Instr::kInstrSize); |
1202 } else if (instr->BreakCodeField() == Instr::kSimulatorMessageCode) { | 1208 } else if (instr->BreakCodeField() == Instr::kSimulatorMessageCode) { |
1203 const char* message = *reinterpret_cast<const char**>( | 1209 const char* message = *reinterpret_cast<const char**>( |
1204 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1210 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1205 if (FLAG_trace_sim) { | 1211 if (static_cast<uintptr_t>(icount_) > |
zra
2014/12/19 17:49:47
Same comment.
regis
2014/12/22 20:17:34
Done.
| |
1212 static_cast<uintptr_t>(FLAG_trace_sim_after)) { | |
1206 OS::Print("Message: %s\n", message); | 1213 OS::Print("Message: %s\n", message); |
1207 } else { | |
1208 OS::PrintErr("Bad break code: 0x%x\n", instr->InstructionBits()); | |
1209 UnimplementedInstruction(instr); | |
1210 } | 1214 } |
1211 } else if (instr->BreakCodeField() == Instr::kSimulatorRedirectCode) { | 1215 } else if (instr->BreakCodeField() == Instr::kSimulatorRedirectCode) { |
1212 SimulatorSetjmpBuffer buffer(this); | 1216 SimulatorSetjmpBuffer buffer(this); |
1213 | 1217 |
1214 if (!setjmp(buffer.buffer_)) { | 1218 if (!setjmp(buffer.buffer_)) { |
1215 int32_t saved_ra = get_register(RA); | 1219 int32_t saved_ra = get_register(RA); |
1216 Redirection* redirection = Redirection::FromBreakInstruction(instr); | 1220 Redirection* redirection = Redirection::FromBreakInstruction(instr); |
1217 uword external = redirection->external_function(); | 1221 uword external = redirection->external_function(); |
1218 if (FLAG_trace_sim) { | 1222 if (static_cast<uintptr_t>(icount_) > |
1223 static_cast<uintptr_t>(FLAG_trace_sim_after)) { | |
1219 OS::Print("Call to host function at 0x%" Pd "\n", external); | 1224 OS::Print("Call to host function at 0x%" Pd "\n", external); |
1220 } | 1225 } |
1221 | 1226 |
1222 if ((redirection->call_kind() == kRuntimeCall) || | 1227 if ((redirection->call_kind() == kRuntimeCall) || |
1223 (redirection->call_kind() == kBootstrapNativeCall) || | 1228 (redirection->call_kind() == kBootstrapNativeCall) || |
1224 (redirection->call_kind() == kNativeCall)) { | 1229 (redirection->call_kind() == kNativeCall)) { |
1225 // Set the top_exit_frame_info of this simulator to the native stack. | 1230 // Set the top_exit_frame_info of this simulator to the native stack. |
1226 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); | 1231 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
1227 } | 1232 } |
1228 if (redirection->call_kind() == kRuntimeCall) { | 1233 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()); | 1964 OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits()); |
1960 UnimplementedInstruction(instr); | 1965 UnimplementedInstruction(instr); |
1961 break; | 1966 break; |
1962 } | 1967 } |
1963 } | 1968 } |
1964 } | 1969 } |
1965 } | 1970 } |
1966 | 1971 |
1967 | 1972 |
1968 void Simulator::InstructionDecode(Instr* instr) { | 1973 void Simulator::InstructionDecode(Instr* instr) { |
1969 if (FLAG_trace_sim) { | 1974 if (static_cast<uintptr_t>(icount_) > |
1975 static_cast<uintptr_t>(FLAG_trace_sim_after)) { | |
1976 OS::Print("%u ", icount_); | |
1970 const uword start = reinterpret_cast<uword>(instr); | 1977 const uword start = reinterpret_cast<uword>(instr); |
1971 const uword end = start + Instr::kInstrSize; | 1978 const uword end = start + Instr::kInstrSize; |
1972 Disassembler::Disassemble(start, end); | 1979 Disassembler::Disassemble(start, end); |
1973 } | 1980 } |
1974 | 1981 |
1975 switch (instr->OpcodeField()) { | 1982 switch (instr->OpcodeField()) { |
1976 case SPECIAL: { | 1983 case SPECIAL: { |
1977 DecodeSpecial(instr); | 1984 DecodeSpecial(instr); |
1978 break; | 1985 break; |
1979 } | 1986 } |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2258 } | 2265 } |
2259 pc_ += Instr::kInstrSize; | 2266 pc_ += Instr::kInstrSize; |
2260 } | 2267 } |
2261 | 2268 |
2262 | 2269 |
2263 void Simulator::ExecuteDelaySlot() { | 2270 void Simulator::ExecuteDelaySlot() { |
2264 ASSERT(pc_ != kEndSimulatingPC); | 2271 ASSERT(pc_ != kEndSimulatingPC); |
2265 delay_slot_ = true; | 2272 delay_slot_ = true; |
2266 icount_++; | 2273 icount_++; |
2267 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); | 2274 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); |
2268 if (FLAG_stop_sim_at != 0) { | 2275 if (FLAG_stop_sim_at != -1) { |
2269 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { | 2276 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { |
2270 SimulatorDebugger dbg(this); | 2277 SimulatorDebugger dbg(this); |
2271 dbg.Stop(instr, "Instruction count reached"); | 2278 dbg.Stop(instr, "Instruction count reached"); |
2272 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { | 2279 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { |
2273 SimulatorDebugger dbg(this); | 2280 SimulatorDebugger dbg(this); |
2274 dbg.Stop(instr, "Instruction address reached"); | 2281 dbg.Stop(instr, "Instruction address reached"); |
2275 } | 2282 } |
2276 } | 2283 } |
2277 InstructionDecode(instr); | 2284 InstructionDecode(instr); |
2278 delay_slot_ = false; | 2285 delay_slot_ = false; |
2279 } | 2286 } |
2280 | 2287 |
2281 | 2288 |
2282 void Simulator::Execute() { | 2289 void Simulator::Execute() { |
2283 if (FLAG_stop_sim_at == 0) { | 2290 if (FLAG_stop_sim_at == -1) { |
2284 // Fast version of the dispatch loop without checking whether the simulator | 2291 // Fast version of the dispatch loop without checking whether the simulator |
2285 // should be stopping at a particular executed instruction. | 2292 // should be stopping at a particular executed instruction. |
2286 while (pc_ != kEndSimulatingPC) { | 2293 while (pc_ != kEndSimulatingPC) { |
2287 icount_++; | 2294 icount_++; |
2288 Instr* instr = Instr::At(pc_); | 2295 Instr* instr = Instr::At(pc_); |
2289 if (IsIllegalAddress(pc_)) { | 2296 if (IsIllegalAddress(pc_)) { |
2290 HandleIllegalAccess(pc_, instr); | 2297 HandleIllegalAccess(pc_, instr); |
2291 } else { | 2298 } else { |
2292 InstructionDecode(instr); | 2299 InstructionDecode(instr); |
2293 } | 2300 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2475 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 2482 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
2476 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 2483 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
2477 buf->Longjmp(); | 2484 buf->Longjmp(); |
2478 } | 2485 } |
2479 | 2486 |
2480 } // namespace dart | 2487 } // namespace dart |
2481 | 2488 |
2482 #endif // !defined(HOST_ARCH_MIPS) | 2489 #endif // !defined(HOST_ARCH_MIPS) |
2483 | 2490 |
2484 #endif // defined TARGET_ARCH_MIPS | 2491 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |