| 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 |