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(bool, trace_sim, false, "Trace simulator execution."); |
28 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); | 28 DEFINE_FLAG(int, stop_sim_at, 0, |
| 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 |
38 // Unimplemented counter class for debugging and measurement purposes. | |
39 class StatsCounter { | |
40 public: | |
41 explicit StatsCounter(const char* name) { | |
42 // UNIMPLEMENTED(); | |
43 } | |
44 | |
45 void Increment() { | |
46 // UNIMPLEMENTED(); | |
47 } | |
48 }; | |
49 | |
50 | |
51 // SimulatorSetjmpBuffer are linked together, and the last created one | 39 // SimulatorSetjmpBuffer are linked together, and the last created one |
52 // is referenced by the Simulator. When an exception is thrown, the exception | 40 // is referenced by the Simulator. When an exception is thrown, the exception |
53 // runtime looks at where to jump and finds the corresponding | 41 // runtime looks at where to jump and finds the corresponding |
54 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. | 42 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler. |
55 // The runtime then does a Longjmp on that buffer to return to the simulator. | 43 // The runtime then does a Longjmp on that buffer to return to the simulator. |
56 class SimulatorSetjmpBuffer { | 44 class SimulatorSetjmpBuffer { |
57 public: | 45 public: |
58 int Setjmp() { return setjmp(buffer_); } | 46 int Setjmp() { return setjmp(buffer_); } |
59 void Longjmp() { | 47 void Longjmp() { |
60 // "This" is now the last setjmp buffer. | 48 // "This" is now the last setjmp buffer. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 | 81 |
94 // The SimulatorDebugger class is used by the simulator while debugging | 82 // The SimulatorDebugger class is used by the simulator while debugging |
95 // simulated ARM code. | 83 // simulated ARM code. |
96 class SimulatorDebugger { | 84 class SimulatorDebugger { |
97 public: | 85 public: |
98 explicit SimulatorDebugger(Simulator* sim); | 86 explicit SimulatorDebugger(Simulator* sim); |
99 ~SimulatorDebugger(); | 87 ~SimulatorDebugger(); |
100 | 88 |
101 void Stop(Instr* instr, const char* message); | 89 void Stop(Instr* instr, const char* message); |
102 void Debug(); | 90 void Debug(); |
103 | |
104 char* ReadLine(const char* prompt); | 91 char* ReadLine(const char* prompt); |
105 | 92 |
106 private: | 93 private: |
107 static const int32_t kSimulatorBreakpointInstr = // svc #kBreakpointSvcCode | |
108 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode); | |
109 static const int32_t kNopInstr = // nop | |
110 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12)); | |
111 | |
112 Simulator* sim_; | 94 Simulator* sim_; |
113 | 95 |
114 bool GetValue(char* desc, uint32_t* value); | 96 bool GetValue(char* desc, uint32_t* value); |
115 bool GetFValue(char* desc, float* value); | 97 bool GetFValue(char* desc, float* value); |
116 bool GetDValue(char* desc, double* value); | 98 bool GetDValue(char* desc, double* value); |
117 | 99 |
118 static intptr_t GetApproximateTokenIndex(const Code& code, uword pc); | 100 static intptr_t GetApproximateTokenIndex(const Code& code, uword pc); |
119 | 101 |
120 static void PrintDartFrame(uword pc, uword fp, uword sp, | 102 static void PrintDartFrame(uword pc, uword fp, uword sp, |
121 const Function& function, | 103 const Function& function, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 if (desc[0] == '*') { | 192 if (desc[0] == '*') { |
211 uint32_t addr; | 193 uint32_t addr; |
212 if (GetValue(desc + 1, &addr)) { | 194 if (GetValue(desc + 1, &addr)) { |
213 if (Simulator::IsIllegalAddress(addr)) { | 195 if (Simulator::IsIllegalAddress(addr)) { |
214 return false; | 196 return false; |
215 } | 197 } |
216 *value = *(reinterpret_cast<uint32_t*>(addr)); | 198 *value = *(reinterpret_cast<uint32_t*>(addr)); |
217 return true; | 199 return true; |
218 } | 200 } |
219 } | 201 } |
| 202 if (strcmp("icount", desc) == 0) { |
| 203 *value = sim_->get_icount(); |
| 204 return true; |
| 205 } |
220 bool retval = SScanF(desc, "0x%x", value) == 1; | 206 bool retval = SScanF(desc, "0x%x", value) == 1; |
221 if (!retval) { | 207 if (!retval) { |
222 retval = SScanF(desc, "%x", value) == 1; | 208 retval = SScanF(desc, "%x", value) == 1; |
223 } | 209 } |
224 return retval; | 210 return retval; |
225 } | 211 } |
226 | 212 |
227 | 213 |
228 bool SimulatorDebugger::GetFValue(char* desc, float* value) { | 214 bool SimulatorDebugger::GetFValue(char* desc, float* value) { |
229 SRegister sreg = LookupSRegisterByName(desc); | 215 SRegister sreg = LookupSRegisterByName(desc); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 371 |
386 void SimulatorDebugger::UndoBreakpoints() { | 372 void SimulatorDebugger::UndoBreakpoints() { |
387 if (sim_->break_pc_ != NULL) { | 373 if (sim_->break_pc_ != NULL) { |
388 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); | 374 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); |
389 } | 375 } |
390 } | 376 } |
391 | 377 |
392 | 378 |
393 void SimulatorDebugger::RedoBreakpoints() { | 379 void SimulatorDebugger::RedoBreakpoints() { |
394 if (sim_->break_pc_ != NULL) { | 380 if (sim_->break_pc_ != NULL) { |
395 sim_->break_pc_->SetInstructionBits(kSimulatorBreakpointInstr); | 381 sim_->break_pc_->SetInstructionBits(Instr::kSimulatorBreakpointInstruction); |
396 } | 382 } |
397 } | 383 } |
398 | 384 |
399 | 385 |
400 void SimulatorDebugger::Debug() { | 386 void SimulatorDebugger::Debug() { |
401 intptr_t last_pc = -1; | 387 intptr_t last_pc = -1; |
402 bool done = false; | 388 bool done = false; |
403 | 389 |
404 #define COMMAND_SIZE 63 | 390 #define COMMAND_SIZE 63 |
405 #define ARG_SIZE 255 | 391 #define ARG_SIZE 255 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 "disasm -- disassemble instrs at current pc location\n" | 431 "disasm -- disassemble instrs at current pc location\n" |
446 " other variants are:\n" | 432 " other variants are:\n" |
447 " disasm <address>\n" | 433 " disasm <address>\n" |
448 " disasm <address> <number_of_instructions>\n" | 434 " disasm <address> <number_of_instructions>\n" |
449 " by default 10 instrs are disassembled\n" | 435 " by default 10 instrs are disassembled\n" |
450 "del -- delete breakpoints\n" | 436 "del -- delete breakpoints\n" |
451 "flags -- print flag values\n" | 437 "flags -- print flag values\n" |
452 "gdb -- transfer control to gdb\n" | 438 "gdb -- transfer control to gdb\n" |
453 "h/help -- print this help string\n" | 439 "h/help -- print this help string\n" |
454 "break <address> -- set break point at specified address\n" | 440 "break <address> -- set break point at specified address\n" |
455 "p/print <reg or value or *addr> -- print integer value\n" | 441 "p/print <reg or icount or value or *addr> -- print integer\n" |
456 "ps/printsingle <sreg or *addr> -- print float value\n" | 442 "ps/printsingle <sreg or *addr> -- print float value\n" |
457 "pd/printdouble <dreg or *addr> -- print double value\n" | 443 "pd/printdouble <dreg or *addr> -- print double value\n" |
458 "po/printobject <*reg or *addr> -- print object\n" | 444 "po/printobject <*reg or *addr> -- print object\n" |
459 "si/stepi -- single step an instruction\n" | 445 "si/stepi -- single step an instruction\n" |
460 "trace -- toggle execution tracing mode\n" | 446 "trace -- toggle execution tracing mode\n" |
461 "bt -- print backtrace\n" | 447 "bt -- print backtrace\n" |
462 "unstop -- if current pc is a stop instr make it a nop\n" | 448 "unstop -- if current pc is a stop instr make it a nop\n" |
463 "q/quit -- Quit the debugger and exit the program\n"); | 449 "q/quit -- Quit the debugger and exit the program\n"); |
464 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 450 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
465 OS::Print("Quitting\n"); | 451 OS::Print("Quitting\n"); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 OS::Print("printobject <*reg or *addr>\n"); | 519 OS::Print("printobject <*reg or *addr>\n"); |
534 } | 520 } |
535 } else if (strcmp(cmd, "disasm") == 0) { | 521 } else if (strcmp(cmd, "disasm") == 0) { |
536 uint32_t start = 0; | 522 uint32_t start = 0; |
537 uint32_t end = 0; | 523 uint32_t end = 0; |
538 if (args == 1) { | 524 if (args == 1) { |
539 start = sim_->get_pc(); | 525 start = sim_->get_pc(); |
540 end = start + (10 * Instr::kInstrSize); | 526 end = start + (10 * Instr::kInstrSize); |
541 } else if (args == 2) { | 527 } else if (args == 2) { |
542 if (GetValue(arg1, &start)) { | 528 if (GetValue(arg1, &start)) { |
543 // no length parameter passed, assume 10 instructions | 529 // No length parameter passed, assume 10 instructions. |
| 530 if (Simulator::IsIllegalAddress(start)) { |
| 531 // If start isn't a valid address, warn and use PC instead. |
| 532 OS::Print("First argument yields invalid address: 0x%x\n", start); |
| 533 OS::Print("Using PC instead\n"); |
| 534 start = sim_->get_pc(); |
| 535 } |
544 end = start + (10 * Instr::kInstrSize); | 536 end = start + (10 * Instr::kInstrSize); |
545 } | 537 } |
546 } else { | 538 } else { |
547 uint32_t length; | 539 uint32_t length; |
548 if (GetValue(arg1, &start) && GetValue(arg2, &length)) { | 540 if (GetValue(arg1, &start) && GetValue(arg2, &length)) { |
| 541 if (Simulator::IsIllegalAddress(start)) { |
| 542 // If start isn't a valid address, warn and use PC instead. |
| 543 OS::Print("First argument yields invalid address: 0x%x\n", start); |
| 544 OS::Print("Using PC instead\n"); |
| 545 start = sim_->get_pc(); |
| 546 } |
549 end = start + (length * Instr::kInstrSize); | 547 end = start + (length * Instr::kInstrSize); |
550 } | 548 } |
551 } | 549 } |
552 | 550 if ((start > 0) && (end > start)) { |
553 Disassembler::Disassemble(start, end); | 551 Disassembler::Disassemble(start, end); |
| 552 } else { |
| 553 OS::Print("disasm [<address> [<number_of_instructions>]]\n"); |
| 554 } |
554 } else if (strcmp(cmd, "gdb") == 0) { | 555 } else if (strcmp(cmd, "gdb") == 0) { |
555 OS::Print("relinquishing control to gdb\n"); | 556 OS::Print("relinquishing control to gdb\n"); |
556 OS::DebugBreak(); | 557 OS::DebugBreak(); |
557 OS::Print("regaining control from gdb\n"); | 558 OS::Print("regaining control from gdb\n"); |
558 } else if (strcmp(cmd, "break") == 0) { | 559 } else if (strcmp(cmd, "break") == 0) { |
559 if (args == 2) { | 560 if (args == 2) { |
560 uint32_t addr; | 561 uint32_t addr; |
561 if (GetValue(arg1, &addr)) { | 562 if (GetValue(arg1, &addr)) { |
562 if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) { | 563 if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) { |
563 OS::Print("setting breakpoint failed\n"); | 564 OS::Print("setting breakpoint failed\n"); |
(...skipping 16 matching lines...) Expand all Loading... |
580 OS::Print("V flag: %d\n", sim_->v_flag_); | 581 OS::Print("V flag: %d\n", sim_->v_flag_); |
581 OS::Print("FPSCR: "); | 582 OS::Print("FPSCR: "); |
582 OS::Print("N flag: %d; ", sim_->fp_n_flag_); | 583 OS::Print("N flag: %d; ", sim_->fp_n_flag_); |
583 OS::Print("Z flag: %d; ", sim_->fp_z_flag_); | 584 OS::Print("Z flag: %d; ", sim_->fp_z_flag_); |
584 OS::Print("C flag: %d; ", sim_->fp_c_flag_); | 585 OS::Print("C flag: %d; ", sim_->fp_c_flag_); |
585 OS::Print("V flag: %d\n", sim_->fp_v_flag_); | 586 OS::Print("V flag: %d\n", sim_->fp_v_flag_); |
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->IsSvc() || stop_instr->IsBkpt()) { | 590 if (stop_instr->IsSvc() || stop_instr->IsBkpt()) { |
590 stop_instr->SetInstructionBits(kNopInstr); | 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 FLAG_trace_sim = !FLAG_trace_sim; |
596 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); | 597 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); |
597 } else if (strcmp(cmd, "bt") == 0) { | 598 } else if (strcmp(cmd, "bt") == 0) { |
598 PrintBacktrace(); | 599 PrintBacktrace(); |
599 } else { | 600 } else { |
600 OS::Print("Unknown command: %s\n", cmd); | 601 OS::Print("Unknown command: %s\n", cmd); |
(...skipping 10 matching lines...) Expand all Loading... |
611 #undef ARG_SIZE | 612 #undef ARG_SIZE |
612 | 613 |
613 #undef STR | 614 #undef STR |
614 #undef XSTR | 615 #undef XSTR |
615 } | 616 } |
616 | 617 |
617 | 618 |
618 char* SimulatorDebugger::ReadLine(const char* prompt) { | 619 char* SimulatorDebugger::ReadLine(const char* prompt) { |
619 char* result = NULL; | 620 char* result = NULL; |
620 char line_buf[256]; | 621 char line_buf[256]; |
621 int offset = 0; | 622 intptr_t offset = 0; |
622 bool keep_going = true; | 623 bool keep_going = true; |
623 OS::Print("%s", prompt); | 624 OS::Print("%s", prompt); |
624 while (keep_going) { | 625 while (keep_going) { |
625 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { | 626 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) { |
626 // fgets got an error. Just give up. | 627 // fgets got an error. Just give up. |
627 if (result != NULL) { | 628 if (result != NULL) { |
628 delete[] result; | 629 delete[] result; |
629 } | 630 } |
630 return NULL; | 631 return NULL; |
631 } | 632 } |
632 int len = strlen(line_buf); | 633 intptr_t len = strlen(line_buf); |
633 if (len > 1 && | 634 if (len > 1 && |
634 line_buf[len - 2] == '\\' && | 635 line_buf[len - 2] == '\\' && |
635 line_buf[len - 1] == '\n') { | 636 line_buf[len - 1] == '\n') { |
636 // When we read a line that ends with a "\" we remove the escape and | 637 // When we read a line that ends with a "\" we remove the escape and |
637 // append the remainder. | 638 // append the remainder. |
638 line_buf[len - 2] = '\n'; | 639 line_buf[len - 2] = '\n'; |
639 line_buf[len - 1] = 0; | 640 line_buf[len - 1] = 0; |
640 len -= 1; | 641 len -= 1; |
641 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { | 642 } else if ((len > 0) && (line_buf[len - 1] == '\n')) { |
642 // Since we read a new line we are done reading the line. This | 643 // Since we read a new line we are done reading the line. This |
643 // will exit the loop after copying this buffer into the result. | 644 // will exit the loop after copying this buffer into the result. |
644 keep_going = false; | 645 keep_going = false; |
645 } | 646 } |
646 if (result == NULL) { | 647 if (result == NULL) { |
647 // Allocate the initial result and make room for the terminating '\0' | 648 // Allocate the initial result and make room for the terminating '\0' |
648 result = new char[len + 1]; | 649 result = new char[len + 1]; |
649 if (result == NULL) { | 650 if (result == NULL) { |
650 // OOM, so cannot readline anymore. | 651 // OOM, so cannot readline anymore. |
651 return NULL; | 652 return NULL; |
652 } | 653 } |
653 } else { | 654 } else { |
654 // Allocate a new result with enough room for the new addition. | 655 // Allocate a new result with enough room for the new addition. |
655 int new_len = offset + len + 1; | 656 intptr_t new_len = offset + len + 1; |
656 char* new_result = new char[new_len]; | 657 char* new_result = new char[new_len]; |
657 if (new_result == NULL) { | 658 if (new_result == NULL) { |
658 // OOM, free the buffer allocated so far and return NULL. | 659 // OOM, free the buffer allocated so far and return NULL. |
659 delete[] result; | 660 delete[] result; |
660 return NULL; | 661 return NULL; |
661 } else { | 662 } else { |
662 // Copy the existing input into the new array and set the new | 663 // Copy the existing input into the new array and set the new |
663 // array as the result. | 664 // array as the result. |
664 memmove(new_result, result, offset); | 665 memmove(new_result, result, offset); |
665 delete[] result; | 666 delete[] result; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 Redirection* current; | 791 Redirection* current; |
791 for (current = list_; current != NULL; current = current->next_) { | 792 for (current = list_; current != NULL; current = current->next_) { |
792 if (current->address_of_svc_instruction() == address_of_svc) { | 793 if (current->address_of_svc_instruction() == address_of_svc) { |
793 return current->external_function_; | 794 return current->external_function_; |
794 } | 795 } |
795 } | 796 } |
796 return 0; | 797 return 0; |
797 } | 798 } |
798 | 799 |
799 private: | 800 private: |
800 static const int32_t kRedirectSvcInstruction = | |
801 ((AL << kConditionShift) | (0xf << 24) | kRedirectionSvcCode); | |
802 Redirection(uword external_function, | 801 Redirection(uword external_function, |
803 Simulator::CallKind call_kind, | 802 Simulator::CallKind call_kind, |
804 int argument_count) | 803 int argument_count) |
805 : external_function_(external_function), | 804 : external_function_(external_function), |
806 call_kind_(call_kind), | 805 call_kind_(call_kind), |
807 argument_count_(argument_count), | 806 argument_count_(argument_count), |
808 svc_instruction_(kRedirectSvcInstruction), | 807 svc_instruction_(Instr::kSimulatorRedirectInstruction), |
809 next_(list_) { | 808 next_(list_) { |
810 list_ = this; | 809 list_ = this; |
811 } | 810 } |
812 | 811 |
813 uword external_function_; | 812 uword external_function_; |
814 Simulator::CallKind call_kind_; | 813 Simulator::CallKind call_kind_; |
815 int argument_count_; | 814 int argument_count_; |
816 uint32_t svc_instruction_; | 815 uint32_t svc_instruction_; |
817 Redirection* next_; | 816 Redirection* next_; |
818 static Redirection* list_; | 817 static Redirection* list_; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 void Simulator::UnimplementedInstruction(Instr* instr) { | 994 void Simulator::UnimplementedInstruction(Instr* instr) { |
996 char buffer[64]; | 995 char buffer[64]; |
997 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | 996 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
998 SimulatorDebugger dbg(this); | 997 SimulatorDebugger dbg(this); |
999 dbg.Stop(instr, buffer); | 998 dbg.Stop(instr, buffer); |
1000 FATAL("Cannot continue execution after unimplemented instruction."); | 999 FATAL("Cannot continue execution after unimplemented instruction."); |
1001 } | 1000 } |
1002 | 1001 |
1003 | 1002 |
1004 intptr_t Simulator::ReadW(uword addr, Instr* instr) { | 1003 intptr_t Simulator::ReadW(uword addr, Instr* instr) { |
1005 static StatsCounter counter_read_w("Simulated word reads"); | |
1006 counter_read_w.Increment(); | |
1007 if ((addr & 3) == 0) { | 1004 if ((addr & 3) == 0) { |
1008 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1005 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
1009 return *ptr; | 1006 return *ptr; |
1010 } | 1007 } |
1011 UnalignedAccess("read", addr, instr); | 1008 UnalignedAccess("read", addr, instr); |
1012 return 0; | 1009 return 0; |
1013 } | 1010 } |
1014 | 1011 |
1015 | 1012 |
1016 void Simulator::WriteW(uword addr, intptr_t value, Instr* instr) { | 1013 void Simulator::WriteW(uword addr, intptr_t value, Instr* instr) { |
1017 static StatsCounter counter_write_w("Simulated word writes"); | |
1018 counter_write_w.Increment(); | |
1019 if ((addr & 3) == 0) { | 1014 if ((addr & 3) == 0) { |
1020 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1015 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
1021 *ptr = value; | 1016 *ptr = value; |
1022 return; | 1017 return; |
1023 } | 1018 } |
1024 UnalignedAccess("write", addr, instr); | 1019 UnalignedAccess("write", addr, instr); |
1025 } | 1020 } |
1026 | 1021 |
1027 | 1022 |
1028 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { | 1023 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { |
1029 static StatsCounter counter_read_hu("Simulated unsigned halfword reads"); | |
1030 counter_read_hu.Increment(); | |
1031 if ((addr & 1) == 0) { | 1024 if ((addr & 1) == 0) { |
1032 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1025 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
1033 return *ptr; | 1026 return *ptr; |
1034 } | 1027 } |
1035 UnalignedAccess("unsigned halfword read", addr, instr); | 1028 UnalignedAccess("unsigned halfword read", addr, instr); |
1036 return 0; | 1029 return 0; |
1037 } | 1030 } |
1038 | 1031 |
1039 | 1032 |
1040 int16_t Simulator::ReadH(uword addr, Instr* instr) { | 1033 int16_t Simulator::ReadH(uword addr, Instr* instr) { |
1041 static StatsCounter counter_read_h("Simulated signed halfword reads"); | |
1042 counter_read_h.Increment(); | |
1043 if ((addr & 1) == 0) { | 1034 if ((addr & 1) == 0) { |
1044 int16_t* ptr = reinterpret_cast<int16_t*>(addr); | 1035 int16_t* ptr = reinterpret_cast<int16_t*>(addr); |
1045 return *ptr; | 1036 return *ptr; |
1046 } | 1037 } |
1047 UnalignedAccess("signed halfword read", addr, instr); | 1038 UnalignedAccess("signed halfword read", addr, instr); |
1048 return 0; | 1039 return 0; |
1049 } | 1040 } |
1050 | 1041 |
1051 | 1042 |
1052 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { | 1043 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { |
1053 static StatsCounter counter_write_h("Simulated halfword writes"); | |
1054 counter_write_h.Increment(); | |
1055 if ((addr & 1) == 0) { | 1044 if ((addr & 1) == 0) { |
1056 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); | 1045 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); |
1057 *ptr = value; | 1046 *ptr = value; |
1058 return; | 1047 return; |
1059 } | 1048 } |
1060 UnalignedAccess("halfword write", addr, instr); | 1049 UnalignedAccess("halfword write", addr, instr); |
1061 } | 1050 } |
1062 | 1051 |
1063 | 1052 |
1064 uint8_t Simulator::ReadBU(uword addr) { | 1053 uint8_t Simulator::ReadBU(uword addr) { |
1065 static StatsCounter counter_read_bu("Simulated unsigned byte reads"); | |
1066 counter_read_bu.Increment(); | |
1067 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1054 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
1068 return *ptr; | 1055 return *ptr; |
1069 } | 1056 } |
1070 | 1057 |
1071 | 1058 |
1072 int8_t Simulator::ReadB(uword addr) { | 1059 int8_t Simulator::ReadB(uword addr) { |
1073 static StatsCounter counter_read_b("Simulated signed byte reads"); | |
1074 counter_read_b.Increment(); | |
1075 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 1060 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
1076 return *ptr; | 1061 return *ptr; |
1077 } | 1062 } |
1078 | 1063 |
1079 | 1064 |
1080 void Simulator::WriteB(uword addr, uint8_t value) { | 1065 void Simulator::WriteB(uword addr, uint8_t value) { |
1081 static StatsCounter counter_write_b("Simulated byte writes"); | |
1082 counter_write_b.Increment(); | |
1083 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1066 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
1084 *ptr = value; | 1067 *ptr = value; |
1085 } | 1068 } |
1086 | 1069 |
1087 | 1070 |
1088 // Synchronization primitives support. | 1071 // Synchronization primitives support. |
1089 void Simulator::SetExclusiveAccess(uword addr) { | 1072 void Simulator::SetExclusiveAccess(uword addr) { |
1090 Isolate* isolate = Isolate::Current(); | 1073 Isolate* isolate = Isolate::Current(); |
1091 ASSERT(isolate != NULL); | 1074 ASSERT(isolate != NULL); |
1092 DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate); | 1075 DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate); |
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1633 break; | 1616 break; |
1634 } | 1617 } |
1635 case kStopMessageSvcCode: { | 1618 case kStopMessageSvcCode: { |
1636 SimulatorDebugger dbg(this); | 1619 SimulatorDebugger dbg(this); |
1637 const char* message = *reinterpret_cast<const char**>( | 1620 const char* message = *reinterpret_cast<const char**>( |
1638 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); | 1621 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize); |
1639 set_pc(get_pc() + Instr::kInstrSize); | 1622 set_pc(get_pc() + Instr::kInstrSize); |
1640 dbg.Stop(instr, message); | 1623 dbg.Stop(instr, message); |
1641 break; | 1624 break; |
1642 } | 1625 } |
1643 case kWordSpillMarkerSvcCode: { | |
1644 static StatsCounter counter_spill_w("Simulated word spills"); | |
1645 counter_spill_w.Increment(); | |
1646 break; | |
1647 } | |
1648 case kDWordSpillMarkerSvcCode: { | |
1649 static StatsCounter counter_spill_d("Simulated double word spills"); | |
1650 counter_spill_d.Increment(); | |
1651 break; | |
1652 } | |
1653 default: { | 1626 default: { |
1654 UNREACHABLE(); | 1627 UNREACHABLE(); |
1655 break; | 1628 break; |
1656 } | 1629 } |
1657 } | 1630 } |
1658 } | 1631 } |
1659 | 1632 |
1660 | 1633 |
1661 // Handle execution based on instruction types. | 1634 // Handle execution based on instruction types. |
1662 | 1635 |
(...skipping 1984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3647 } | 3620 } |
3648 } | 3621 } |
3649 } | 3622 } |
3650 if (!pc_modified_) { | 3623 if (!pc_modified_) { |
3651 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); | 3624 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize); |
3652 } | 3625 } |
3653 } | 3626 } |
3654 | 3627 |
3655 | 3628 |
3656 void Simulator::Execute() { | 3629 void Simulator::Execute() { |
3657 static StatsCounter counter_instructions("Simulated instructions"); | |
3658 | |
3659 // Get the PC to simulate. Cannot use the accessor here as we need the | 3630 // Get the PC to simulate. Cannot use the accessor here as we need the |
3660 // raw PC value and not the one used as input to arithmetic instructions. | 3631 // raw PC value and not the one used as input to arithmetic instructions. |
3661 uword program_counter = get_pc(); | 3632 uword program_counter = get_pc(); |
3662 | 3633 |
3663 if (FLAG_stop_sim_at == 0) { | 3634 if (FLAG_stop_sim_at == 0) { |
3664 // Fast version of the dispatch loop without checking whether the simulator | 3635 // Fast version of the dispatch loop without checking whether the simulator |
3665 // should be stopping at a particular executed instruction. | 3636 // should be stopping at a particular executed instruction. |
3666 while (program_counter != kEndSimulatingPC) { | 3637 while (program_counter != kEndSimulatingPC) { |
3667 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3638 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
3668 icount_++; | 3639 icount_++; |
3669 counter_instructions.Increment(); | |
3670 if (IsIllegalAddress(program_counter)) { | 3640 if (IsIllegalAddress(program_counter)) { |
3671 HandleIllegalAccess(program_counter, instr); | 3641 HandleIllegalAccess(program_counter, instr); |
3672 } else { | 3642 } else { |
3673 InstructionDecode(instr); | 3643 InstructionDecode(instr); |
3674 } | 3644 } |
3675 program_counter = get_pc(); | 3645 program_counter = get_pc(); |
3676 } | 3646 } |
3677 } else { | 3647 } else { |
3678 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 3648 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
3679 // we reach the particular instruction count. | 3649 // we reach the particular instruction count or address. |
3680 while (program_counter != kEndSimulatingPC) { | 3650 while (program_counter != kEndSimulatingPC) { |
3681 Instr* instr = reinterpret_cast<Instr*>(program_counter); | 3651 Instr* instr = reinterpret_cast<Instr*>(program_counter); |
3682 icount_++; | 3652 icount_++; |
3683 counter_instructions.Increment(); | 3653 if (static_cast<intptr_t>(icount_) == FLAG_stop_sim_at) { |
3684 if (icount_ == FLAG_stop_sim_at) { | |
3685 SimulatorDebugger dbg(this); | 3654 SimulatorDebugger dbg(this); |
3686 dbg.Stop(instr, "Instruction count reached"); | 3655 dbg.Stop(instr, "Instruction count reached"); |
| 3656 } else if (reinterpret_cast<intptr_t>(instr) == FLAG_stop_sim_at) { |
| 3657 SimulatorDebugger dbg(this); |
| 3658 dbg.Stop(instr, "Instruction address reached"); |
3687 } else if (IsIllegalAddress(program_counter)) { | 3659 } else if (IsIllegalAddress(program_counter)) { |
3688 HandleIllegalAccess(program_counter, instr); | 3660 HandleIllegalAccess(program_counter, instr); |
3689 } else { | 3661 } else { |
3690 InstructionDecode(instr); | 3662 InstructionDecode(instr); |
3691 } | 3663 } |
3692 program_counter = get_pc(); | 3664 program_counter = get_pc(); |
3693 } | 3665 } |
3694 } | 3666 } |
3695 } | 3667 } |
3696 | 3668 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3885 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 3857 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
3886 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 3858 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
3887 buf->Longjmp(); | 3859 buf->Longjmp(); |
3888 } | 3860 } |
3889 | 3861 |
3890 } // namespace dart | 3862 } // namespace dart |
3891 | 3863 |
3892 #endif // !defined(HOST_ARCH_ARM) | 3864 #endif // !defined(HOST_ARCH_ARM) |
3893 | 3865 |
3894 #endif // defined TARGET_ARCH_ARM | 3866 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |