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