| 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_ARM) | 9 #if defined(TARGET_ARCH_ARM) |
| 10 | 10 |
| 11 // Only build the simulator if not compiling for real ARM hardware. | 11 // Only build the simulator if not compiling for real ARM hardware. |
| 12 #if !defined(HOST_ARCH_ARM) | 12 #if !defined(HOST_ARCH_ARM) |
| 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_arm.h" | 17 #include "vm/constants_arm.h" |
| 18 #include "vm/cpu.h" | 18 #include "vm/cpu.h" |
| 19 #include "vm/disassembler.h" | 19 #include "vm/disassembler.h" |
| 20 #include "vm/lockers.h" | 20 #include "vm/lockers.h" |
| 21 #include "vm/native_arguments.h" | 21 #include "vm/native_arguments.h" |
| 22 #include "vm/stack_frame.h" | 22 #include "vm/stack_frame.h" |
| 23 #include "vm/thread.h" | 23 #include "vm/thread.h" |
| 24 | 24 |
| 25 namespace dart { | 25 namespace dart { |
| 26 | 26 |
| 27 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); | 27 DEFINE_FLAG(int, trace_sim_after, -1, |
| 28 DEFINE_FLAG(int, stop_sim_at, 0, | 28 "Trace simulator execution after instruction count reached."); |
| 29 DEFINE_FLAG(int, stop_sim_at, -1, |
| 29 "Instruction address or instruction count to stop simulator at."); | 30 "Instruction address or instruction count to stop simulator at."); |
| 30 | 31 |
| 31 | 32 |
| 32 // This macro provides a platform independent use of sscanf. The reason for | 33 // This macro provides a platform independent use of sscanf. The reason for |
| 33 // SScanF not being implemented in a platform independent way through | 34 // 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 | 35 // OS in the same way as SNPrint is that the Windows C Run-Time |
| 35 // Library does not provide vsscanf. | 36 // Library does not provide vsscanf. |
| 36 #define SScanF sscanf // NOLINT | 37 #define SScanF sscanf // NOLINT |
| 37 | 38 |
| 38 | 39 |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 OS::Print("V flag: %d\n", sim_->fp_v_flag_); | 587 OS::Print("V flag: %d\n", sim_->fp_v_flag_); |
| 587 } else if (strcmp(cmd, "unstop") == 0) { | 588 } else if (strcmp(cmd, "unstop") == 0) { |
| 588 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 589 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
| 589 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 590 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
| 590 if (stop_instr->IsSvc() || stop_instr->IsBkpt()) { | 591 if (stop_instr->IsSvc() || stop_instr->IsBkpt()) { |
| 591 stop_instr->SetInstructionBits(Instr::kNopInstruction); | 592 stop_instr->SetInstructionBits(Instr::kNopInstruction); |
| 592 } else { | 593 } else { |
| 593 OS::Print("Not at debugger stop.\n"); | 594 OS::Print("Not at debugger stop.\n"); |
| 594 } | 595 } |
| 595 } else if (strcmp(cmd, "trace") == 0) { | 596 } else if (strcmp(cmd, "trace") == 0) { |
| 596 FLAG_trace_sim = !FLAG_trace_sim; | 597 if (FLAG_trace_sim_after == -1) { |
| 597 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); | 598 FLAG_trace_sim_after = sim_->get_icount(); |
| 599 OS::Print("execution tracing on\n"); |
| 600 } else { |
| 601 FLAG_trace_sim_after = -1; |
| 602 OS::Print("execution tracing off\n"); |
| 603 } |
| 598 } else if (strcmp(cmd, "bt") == 0) { | 604 } else if (strcmp(cmd, "bt") == 0) { |
| 599 PrintBacktrace(); | 605 PrintBacktrace(); |
| 600 } else { | 606 } else { |
| 601 OS::Print("Unknown command: %s\n", cmd); | 607 OS::Print("Unknown command: %s\n", cmd); |
| 602 } | 608 } |
| 603 } | 609 } |
| 604 delete[] line; | 610 delete[] line; |
| 605 } | 611 } |
| 606 | 612 |
| 607 // Add all the breakpoints back to stop execution and enter the debugger | 613 // Add all the breakpoints back to stop execution and enter the debugger |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 // Returns the top of the stack area to enable checking for stack pointer | 1168 // Returns the top of the stack area to enable checking for stack pointer |
| 1163 // validity. | 1169 // validity. |
| 1164 uword Simulator::StackTop() const { | 1170 uword Simulator::StackTop() const { |
| 1165 // To be safe in potential stack underflows we leave some buffer above and | 1171 // To be safe in potential stack underflows we leave some buffer above and |
| 1166 // set the stack top. | 1172 // set the stack top. |
| 1167 return reinterpret_cast<uword>(stack_) + | 1173 return reinterpret_cast<uword>(stack_) + |
| 1168 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); | 1174 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); |
| 1169 } | 1175 } |
| 1170 | 1176 |
| 1171 | 1177 |
| 1178 bool Simulator::IsTracingExecution() const { |
| 1179 // Integer flag values are signed, so we must cast to unsigned. |
| 1180 // The default of -1 hence becomes the maximum unsigned value. |
| 1181 return (static_cast<uintptr_t>(icount_) > |
| 1182 static_cast<uintptr_t>(FLAG_trace_sim_after)); |
| 1183 } |
| 1184 |
| 1185 |
| 1172 // Unsupported instructions use Format to print an error and stop execution. | 1186 // Unsupported instructions use Format to print an error and stop execution. |
| 1173 void Simulator::Format(Instr* instr, const char* format) { | 1187 void Simulator::Format(Instr* instr, const char* format) { |
| 1174 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", | 1188 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", |
| 1175 instr, | 1189 instr, |
| 1176 format); | 1190 format); |
| 1177 UNIMPLEMENTED(); | 1191 UNIMPLEMENTED(); |
| 1178 } | 1192 } |
| 1179 | 1193 |
| 1180 | 1194 |
| 1181 // Checks if the current instruction should be executed based on its | 1195 // Checks if the current instruction should be executed based on its |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 void Simulator::SupervisorCall(Instr* instr) { | 1503 void Simulator::SupervisorCall(Instr* instr) { |
| 1490 int svc = instr->SvcField(); | 1504 int svc = instr->SvcField(); |
| 1491 switch (svc) { | 1505 switch (svc) { |
| 1492 case kRedirectionSvcCode: { | 1506 case kRedirectionSvcCode: { |
| 1493 SimulatorSetjmpBuffer buffer(this); | 1507 SimulatorSetjmpBuffer buffer(this); |
| 1494 | 1508 |
| 1495 if (!setjmp(buffer.buffer_)) { | 1509 if (!setjmp(buffer.buffer_)) { |
| 1496 int32_t saved_lr = get_register(LR); | 1510 int32_t saved_lr = get_register(LR); |
| 1497 Redirection* redirection = Redirection::FromSvcInstruction(instr); | 1511 Redirection* redirection = Redirection::FromSvcInstruction(instr); |
| 1498 uword external = redirection->external_function(); | 1512 uword external = redirection->external_function(); |
| 1499 if (FLAG_trace_sim) { | 1513 if (IsTracingExecution()) { |
| 1500 OS::Print("Call to host function at 0x%" Pd "\n", external); | 1514 OS::Print("Call to host function at 0x%" Pd "\n", external); |
| 1501 } | 1515 } |
| 1502 | 1516 |
| 1503 if ((redirection->call_kind() == kRuntimeCall) || | 1517 if ((redirection->call_kind() == kRuntimeCall) || |
| 1504 (redirection->call_kind() == kBootstrapNativeCall) || | 1518 (redirection->call_kind() == kBootstrapNativeCall) || |
| 1505 (redirection->call_kind() == kNativeCall)) { | 1519 (redirection->call_kind() == kNativeCall)) { |
| 1506 // Set the top_exit_frame_info of this simulator to the native stack. | 1520 // Set the top_exit_frame_info of this simulator to the native stack. |
| 1507 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); | 1521 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
| 1508 } | 1522 } |
| 1509 if (redirection->call_kind() == kRuntimeCall) { | 1523 if (redirection->call_kind() == kRuntimeCall) { |
| (...skipping 2049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3559 } else { | 3573 } else { |
| 3560 UnimplementedInstruction(instr); | 3574 UnimplementedInstruction(instr); |
| 3561 } | 3575 } |
| 3562 } | 3576 } |
| 3563 } | 3577 } |
| 3564 | 3578 |
| 3565 | 3579 |
| 3566 // Executes the current instruction. | 3580 // Executes the current instruction. |
| 3567 void Simulator::InstructionDecode(Instr* instr) { | 3581 void Simulator::InstructionDecode(Instr* instr) { |
| 3568 pc_modified_ = false; | 3582 pc_modified_ = false; |
| 3569 if (FLAG_trace_sim) { | 3583 if (IsTracingExecution()) { |
| 3584 OS::Print("%u ", icount_); |
| 3570 const uword start = reinterpret_cast<uword>(instr); | 3585 const uword start = reinterpret_cast<uword>(instr); |
| 3571 const uword end = start + Instr::kInstrSize; | 3586 const uword end = start + Instr::kInstrSize; |
| 3572 Disassembler::Disassemble(start, end); | 3587 Disassembler::Disassemble(start, end); |
| 3573 } | 3588 } |
| 3574 if (instr->ConditionField() == kSpecialCondition) { | 3589 if (instr->ConditionField() == kSpecialCondition) { |
| 3575 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { | 3590 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { |
| 3576 // Format(instr, "clrex"); | 3591 // Format(instr, "clrex"); |
| 3577 ClearExclusive(); | 3592 ClearExclusive(); |
| 3578 } else { | 3593 } else { |
| 3579 if (instr->IsSIMDDataProcessing()) { | 3594 if (instr->IsSIMDDataProcessing()) { |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3857 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 3872 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
| 3858 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 3873 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
| 3859 buf->Longjmp(); | 3874 buf->Longjmp(); |
| 3860 } | 3875 } |
| 3861 | 3876 |
| 3862 } // namespace dart | 3877 } // namespace dart |
| 3863 | 3878 |
| 3864 #endif // !defined(HOST_ARCH_ARM) | 3879 #endif // !defined(HOST_ARCH_ARM) |
| 3865 | 3880 |
| 3866 #endif // defined TARGET_ARCH_ARM | 3881 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |