OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 9 #if defined(TARGET_ARCH_ARM64) |
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_ARM64) | 12 #if !defined(HOST_ARCH_ARM64) |
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_arm64.h" | 17 #include "vm/constants_arm64.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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 return false; | 191 return false; |
192 } | 192 } |
193 *value = *(reinterpret_cast<int64_t*>(addr)); | 193 *value = *(reinterpret_cast<int64_t*>(addr)); |
194 return true; | 194 return true; |
195 } | 195 } |
196 } | 196 } |
197 if (strcmp("pc", desc) == 0) { | 197 if (strcmp("pc", desc) == 0) { |
198 *value = sim_->get_pc(); | 198 *value = sim_->get_pc(); |
199 return true; | 199 return true; |
200 } | 200 } |
201 if (strcmp("icount", desc) == 0) { | |
202 *value = sim_->get_icount(); | |
203 return true; | |
204 } | |
205 bool retval = SScanF(desc, "0x%"Px64, value) == 1; | 201 bool retval = SScanF(desc, "0x%"Px64, value) == 1; |
206 if (!retval) { | 202 if (!retval) { |
207 retval = SScanF(desc, "%"Px64, value) == 1; | 203 retval = SScanF(desc, "%"Px64, value) == 1; |
208 } | 204 } |
209 return retval; | 205 return retval; |
210 } | 206 } |
211 | 207 |
212 | 208 |
213 bool SimulatorDebugger::GetSValue(char* desc, uint32_t* value) { | 209 bool SimulatorDebugger::GetSValue(char* desc, uint32_t* value) { |
214 VRegister vreg = LookupVRegisterByName(desc); | 210 VRegister vreg = LookupVRegisterByName(desc); |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 470 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
475 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 471 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
476 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 472 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
477 // Execute the one instruction we broke at with breakpoints disabled. | 473 // Execute the one instruction we broke at with breakpoints disabled. |
478 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 474 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
479 // Leave the debugger shell. | 475 // Leave the debugger shell. |
480 done = true; | 476 done = true; |
481 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 477 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
482 if (args == 2) { | 478 if (args == 2) { |
483 uint64_t value; | 479 uint64_t value; |
484 if (GetValue(arg1, &value)) { | 480 if (strcmp(arg1, "icount") == 0) { |
| 481 value = sim_->get_icount(); |
| 482 OS::Print("icount: %"Pu64" 0x%"Px64"\n", value, value); |
| 483 } else if (GetValue(arg1, &value)) { |
485 OS::Print("%s: %"Pu64" 0x%"Px64"\n", arg1, value, value); | 484 OS::Print("%s: %"Pu64" 0x%"Px64"\n", arg1, value, value); |
486 } else { | 485 } else { |
487 OS::Print("%s unrecognized\n", arg1); | 486 OS::Print("%s unrecognized\n", arg1); |
488 } | 487 } |
489 } else { | 488 } else { |
490 OS::Print("print <reg or value or *addr>\n"); | 489 OS::Print("print <reg or icount or value or *addr>\n"); |
491 } | 490 } |
492 } else if ((strcmp(cmd, "pf") == 0) || | 491 } else if ((strcmp(cmd, "pf") == 0) || |
493 (strcmp(cmd, "printfloat") == 0)) { | 492 (strcmp(cmd, "printfloat") == 0)) { |
494 if (args == 2) { | 493 if (args == 2) { |
495 uint32_t value; | 494 uint32_t value; |
496 if (GetSValue(arg1, &value)) { | 495 if (GetSValue(arg1, &value)) { |
497 float svalue = bit_cast<float, uint32_t>(value); | 496 float svalue = bit_cast<float, uint32_t>(value); |
498 OS::Print("%s: %d 0x%x %.8g\n", | 497 OS::Print("%s: %d 0x%x %.8g\n", |
499 arg1, value, value, svalue); | 498 arg1, value, value, svalue); |
500 } else { | 499 } else { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 OS::Print("V flag: %d\n", sim_->v_flag_); | 633 OS::Print("V flag: %d\n", sim_->v_flag_); |
635 } else if (strcmp(cmd, "unstop") == 0) { | 634 } else if (strcmp(cmd, "unstop") == 0) { |
636 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 635 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
637 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 636 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
638 if (stop_instr->IsExceptionGenOp()) { | 637 if (stop_instr->IsExceptionGenOp()) { |
639 stop_instr->SetInstructionBits(Instr::kNopInstruction); | 638 stop_instr->SetInstructionBits(Instr::kNopInstruction); |
640 } else { | 639 } else { |
641 OS::Print("Not at debugger stop.\n"); | 640 OS::Print("Not at debugger stop.\n"); |
642 } | 641 } |
643 } else if (strcmp(cmd, "trace") == 0) { | 642 } else if (strcmp(cmd, "trace") == 0) { |
644 if (FLAG_trace_sim_after == -1) { | 643 if (FLAG_trace_sim_after == ULLONG_MAX) { |
645 FLAG_trace_sim_after = sim_->get_icount(); | 644 FLAG_trace_sim_after = sim_->get_icount(); |
646 OS::Print("execution tracing on\n"); | 645 OS::Print("execution tracing on\n"); |
647 } else { | 646 } else { |
648 FLAG_trace_sim_after = -1; | 647 FLAG_trace_sim_after = ULLONG_MAX; |
649 OS::Print("execution tracing off\n"); | 648 OS::Print("execution tracing off\n"); |
650 } | 649 } |
651 } else if (strcmp(cmd, "bt") == 0) { | 650 } else if (strcmp(cmd, "bt") == 0) { |
652 PrintBacktrace(); | 651 PrintBacktrace(); |
653 } else { | 652 } else { |
654 OS::Print("Unknown command: %s\n", cmd); | 653 OS::Print("Unknown command: %s\n", cmd); |
655 } | 654 } |
656 } | 655 } |
657 delete[] line; | 656 delete[] line; |
658 } | 657 } |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 // validity. | 1056 // validity. |
1058 uword Simulator::StackTop() const { | 1057 uword Simulator::StackTop() const { |
1059 // To be safe in potential stack underflows we leave some buffer above and | 1058 // To be safe in potential stack underflows we leave some buffer above and |
1060 // set the stack top. | 1059 // set the stack top. |
1061 return reinterpret_cast<uword>(stack_) + | 1060 return reinterpret_cast<uword>(stack_) + |
1062 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); | 1061 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); |
1063 } | 1062 } |
1064 | 1063 |
1065 | 1064 |
1066 bool Simulator::IsTracingExecution() const { | 1065 bool Simulator::IsTracingExecution() const { |
1067 // Integer flag values are signed, so we must cast to unsigned. | 1066 return icount_ > FLAG_trace_sim_after; |
1068 // The default of -1 hence becomes the maximum unsigned value. | |
1069 return (static_cast<uintptr_t>(icount_) > | |
1070 static_cast<uintptr_t>(FLAG_trace_sim_after)); | |
1071 } | 1067 } |
1072 | 1068 |
1073 | 1069 |
1074 intptr_t Simulator::ReadX(uword addr, Instr* instr) { | 1070 intptr_t Simulator::ReadX(uword addr, Instr* instr) { |
1075 if ((addr & 7) == 0) { | 1071 if ((addr & 7) == 0) { |
1076 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1072 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
1077 return *ptr; | 1073 return *ptr; |
1078 } | 1074 } |
1079 UnalignedAccess("read", addr, instr); | 1075 UnalignedAccess("read", addr, instr); |
1080 return 0; | 1076 return 0; |
(...skipping 2219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3300 } else { | 3296 } else { |
3301 UnimplementedInstruction(instr); | 3297 UnimplementedInstruction(instr); |
3302 } | 3298 } |
3303 } | 3299 } |
3304 | 3300 |
3305 | 3301 |
3306 // Executes the current instruction. | 3302 // Executes the current instruction. |
3307 void Simulator::InstructionDecode(Instr* instr) { | 3303 void Simulator::InstructionDecode(Instr* instr) { |
3308 pc_modified_ = false; | 3304 pc_modified_ = false; |
3309 if (IsTracingExecution()) { | 3305 if (IsTracingExecution()) { |
3310 OS::Print("%" Pd " ", icount_); | 3306 OS::Print("%"Pu64, icount_); |
3311 const uword start = reinterpret_cast<uword>(instr); | 3307 const uword start = reinterpret_cast<uword>(instr); |
3312 const uword end = start + Instr::kInstrSize; | 3308 const uword end = start + Instr::kInstrSize; |
3313 Disassembler::Disassemble(start, end); | 3309 Disassembler::Disassemble(start, end); |
3314 } | 3310 } |
3315 | 3311 |
3316 if (instr->IsDPImmediateOp()) { | 3312 if (instr->IsDPImmediateOp()) { |
3317 DecodeDPImmediate(instr); | 3313 DecodeDPImmediate(instr); |
3318 } else if (instr->IsCompareBranchOp()) { | 3314 } else if (instr->IsCompareBranchOp()) { |
3319 DecodeCompareBranch(instr); | 3315 DecodeCompareBranch(instr); |
3320 } else if (instr->IsLoadStoreOp()) { | 3316 } else if (instr->IsLoadStoreOp()) { |
(...skipping 12 matching lines...) Expand all Loading... |
3333 set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize); | 3329 set_pc(reinterpret_cast<int64_t>(instr) + Instr::kInstrSize); |
3334 } | 3330 } |
3335 } | 3331 } |
3336 | 3332 |
3337 | 3333 |
3338 void Simulator::Execute() { | 3334 void Simulator::Execute() { |
3339 // Get the PC to simulate. Cannot use the accessor here as we need the | 3335 // Get the PC to simulate. Cannot use the accessor here as we need the |
3340 // raw PC value and not the one used as input to arithmetic instructions. | 3336 // raw PC value and not the one used as input to arithmetic instructions. |
3341 uword program_counter = get_pc(); | 3337 uword program_counter = get_pc(); |
3342 | 3338 |
3343 if (FLAG_stop_sim_at == 0) { | 3339 if (FLAG_stop_sim_at == ULLONG_MAX) { |
3344 // Fast version of the dispatch loop without checking whether the simulator | 3340 // Fast version of the dispatch loop without checking whether the simulator |
3345 // should be stopping at a particular executed instruction. | 3341 // should be stopping at a particular executed instruction. |
3346 while (program_counter != kEndSimulatingPC) { | 3342 while (program_counter != kEndSimulatingPC) { |
3347 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3343 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
3348 icount_++; | 3344 icount_++; |
3349 if (IsIllegalAddress(program_counter)) { | 3345 if (IsIllegalAddress(program_counter)) { |
3350 HandleIllegalAccess(program_counter, instr); | 3346 HandleIllegalAccess(program_counter, instr); |
3351 } else { | 3347 } else { |
3352 InstructionDecode(instr); | 3348 InstructionDecode(instr); |
3353 } | 3349 } |
3354 program_counter = get_pc(); | 3350 program_counter = get_pc(); |
3355 } | 3351 } |
3356 } else { | 3352 } else { |
3357 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 3353 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
3358 // we reach the particular instruction count or address. | 3354 // we reach the particular instruction count or address. |
3359 while (program_counter != kEndSimulatingPC) { | 3355 while (program_counter != kEndSimulatingPC) { |
3360 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3356 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
3361 icount_++; | 3357 icount_++; |
3362 if (static_cast<intptr_t>(icount_) == FLAG_stop_sim_at) { | 3358 if (icount_ == FLAG_stop_sim_at) { |
3363 SimulatorDebugger dbg(this); | 3359 SimulatorDebugger dbg(this); |
3364 dbg.Stop(instr, "Instruction count reached"); | 3360 dbg.Stop(instr, "Instruction count reached"); |
3365 } else if (reinterpret_cast<intptr_t>(instr) == FLAG_stop_sim_at) { | 3361 } else if (reinterpret_cast<uint64_t>(instr) == FLAG_stop_sim_at) { |
3366 SimulatorDebugger dbg(this); | 3362 SimulatorDebugger dbg(this); |
3367 dbg.Stop(instr, "Instruction address reached"); | 3363 dbg.Stop(instr, "Instruction address reached"); |
3368 } else if (IsIllegalAddress(program_counter)) { | 3364 } else if (IsIllegalAddress(program_counter)) { |
3369 HandleIllegalAccess(program_counter, instr); | 3365 HandleIllegalAccess(program_counter, instr); |
3370 } else { | 3366 } else { |
3371 InstructionDecode(instr); | 3367 InstructionDecode(instr); |
3372 } | 3368 } |
3373 program_counter = get_pc(); | 3369 program_counter = get_pc(); |
3374 } | 3370 } |
3375 } | 3371 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3505 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 3501 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
3506 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 3502 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
3507 buf->Longjmp(); | 3503 buf->Longjmp(); |
3508 } | 3504 } |
3509 | 3505 |
3510 } // namespace dart | 3506 } // namespace dart |
3511 | 3507 |
3512 #endif // !defined(HOST_ARCH_ARM64) | 3508 #endif // !defined(HOST_ARCH_ARM64) |
3513 | 3509 |
3514 #endif // defined TARGET_ARCH_ARM64 | 3510 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |