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