| 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 "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 // Only build the simulator if not compiling for real MIPS hardware. | 8 // Only build the simulator if not compiling for real MIPS hardware. |
| 9 #if !defined(HOST_ARCH_MIPS) | 9 #if !defined(HOST_ARCH_MIPS) |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #define SScanF sscanf // NOLINT | 26 #define SScanF sscanf // NOLINT |
| 27 | 27 |
| 28 | 28 |
| 29 // The SimulatorDebugger class is used by the simulator while debugging | 29 // The SimulatorDebugger class is used by the simulator while debugging |
| 30 // simulated MIPS code. | 30 // simulated MIPS code. |
| 31 class SimulatorDebugger { | 31 class SimulatorDebugger { |
| 32 public: | 32 public: |
| 33 explicit SimulatorDebugger(Simulator* sim); | 33 explicit SimulatorDebugger(Simulator* sim); |
| 34 ~SimulatorDebugger(); | 34 ~SimulatorDebugger(); |
| 35 | 35 |
| 36 // Enter interactive debugging, and attach to the simulator. |
| 37 void Attach(Instr* instr, const char *message); |
| 38 |
| 39 // Enter interactive debugging if debugging is already attached to |
| 40 // the simulator, and otherwise return immediately. |
| 36 void Stop(Instr* instr, const char* message); | 41 void Stop(Instr* instr, const char* message); |
| 37 void Debug(); | 42 void Debug(); |
| 38 char* ReadLine(const char* prompt); | 43 char* ReadLine(const char* prompt); |
| 39 | 44 |
| 40 private: | 45 private: |
| 41 Simulator* sim_; | 46 Simulator* sim_; |
| 42 | 47 |
| 43 bool GetValue(char* desc, uint32_t* value); | 48 bool GetValue(char* desc, uint32_t* value); |
| 44 bool GetFValue(char* desc, double* value); | 49 bool GetFValue(char* desc, double* value); |
| 45 | 50 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 56 | 61 |
| 57 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { | 62 SimulatorDebugger::SimulatorDebugger(Simulator* sim) { |
| 58 sim_ = sim; | 63 sim_ = sim; |
| 59 } | 64 } |
| 60 | 65 |
| 61 | 66 |
| 62 SimulatorDebugger::~SimulatorDebugger() { | 67 SimulatorDebugger::~SimulatorDebugger() { |
| 63 } | 68 } |
| 64 | 69 |
| 65 | 70 |
| 71 void SimulatorDebugger::Attach(Instr* instr, const char* message) { |
| 72 sim_->set_debugger_attached(true); |
| 73 Stop(instr, message); |
| 74 } |
| 75 |
| 76 |
| 66 void SimulatorDebugger::Stop(Instr* instr, const char* message) { | 77 void SimulatorDebugger::Stop(Instr* instr, const char* message) { |
| 67 OS::Print("Simulator hit %s\n", message); | 78 OS::Print("Simulator hit %s\n", message); |
| 68 Debug(); | 79 Debug(); |
| 69 } | 80 } |
| 70 | 81 |
| 71 | 82 |
| 72 static Register LookupCpuRegisterByName(const char* name) { | 83 static Register LookupCpuRegisterByName(const char* name) { |
| 73 static const char* kNames[] = { | 84 static const char* kNames[] = { |
| 74 "r0", "r1", "r2", "r3", | 85 "r0", "r1", "r2", "r3", |
| 75 "r4", "r5", "r6", "r7", | 86 "r4", "r5", "r6", "r7", |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 void SimulatorDebugger::RedoBreakpoints() { | 223 void SimulatorDebugger::RedoBreakpoints() { |
| 213 if (sim_->break_pc_ != NULL) { | 224 if (sim_->break_pc_ != NULL) { |
| 214 sim_->break_pc_->SetInstructionBits(Instr::kBreakPointInstruction); | 225 sim_->break_pc_->SetInstructionBits(Instr::kBreakPointInstruction); |
| 215 } | 226 } |
| 216 } | 227 } |
| 217 | 228 |
| 218 | 229 |
| 219 void SimulatorDebugger::Debug() { | 230 void SimulatorDebugger::Debug() { |
| 220 intptr_t last_pc = -1; | 231 intptr_t last_pc = -1; |
| 221 bool done = false; | 232 bool done = false; |
| 222 bool decoded = true; | |
| 223 | 233 |
| 224 #define COMMAND_SIZE 63 | 234 #define COMMAND_SIZE 63 |
| 225 #define ARG_SIZE 255 | 235 #define ARG_SIZE 255 |
| 226 | 236 |
| 227 #define STR(a) #a | 237 #define STR(a) #a |
| 228 #define XSTR(a) STR(a) | 238 #define XSTR(a) STR(a) |
| 229 | 239 |
| 230 char cmd[COMMAND_SIZE + 1]; | 240 char cmd[COMMAND_SIZE + 1]; |
| 231 char arg1[ARG_SIZE + 1]; | 241 char arg1[ARG_SIZE + 1]; |
| 232 char arg2[ARG_SIZE + 1]; | 242 char arg2[ARG_SIZE + 1]; |
| 233 | 243 |
| 244 // If the simulator does not already have debugging attached, then return--- |
| 245 // we aren't in interactive mode. |
| 246 if (!sim_->debugger_attached()) { |
| 247 return; |
| 248 } |
| 249 |
| 234 // make sure to have a proper terminating character if reaching the limit | 250 // make sure to have a proper terminating character if reaching the limit |
| 235 cmd[COMMAND_SIZE] = 0; | 251 cmd[COMMAND_SIZE] = 0; |
| 236 arg1[ARG_SIZE] = 0; | 252 arg1[ARG_SIZE] = 0; |
| 237 arg2[ARG_SIZE] = 0; | 253 arg2[ARG_SIZE] = 0; |
| 238 | 254 |
| 239 // Undo all set breakpoints while running in the debugger shell. This will | 255 // Undo all set breakpoints while running in the debugger shell. This will |
| 240 // make them invisible to all commands. | 256 // make them invisible to all commands. |
| 241 UndoBreakpoints(); | 257 UndoBreakpoints(); |
| 242 | 258 |
| 243 while (!done) { | 259 while (!done) { |
| 244 if (last_pc != sim_->get_pc()) { | 260 if (last_pc != sim_->get_pc()) { |
| 245 last_pc = sim_->get_pc(); | 261 last_pc = sim_->get_pc(); |
| 246 decoded = Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); | 262 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); |
| 247 } | 263 } |
| 248 char* line = ReadLine("sim> "); | 264 char* line = ReadLine("sim> "); |
| 249 if (line == NULL) { | 265 if (line == NULL) { |
| 250 break; | 266 break; |
| 251 } else { | 267 } else { |
| 252 // Use sscanf to parse the individual parts of the command line. At the | 268 // Use sscanf to parse the individual parts of the command line. At the |
| 253 // moment no command expects more than two parameters. | 269 // moment no command expects more than two parameters. |
| 254 int args = SScanF(line, | 270 int args = SScanF(line, |
| 255 "%" XSTR(COMMAND_SIZE) "s " | 271 "%" XSTR(COMMAND_SIZE) "s " |
| 256 "%" XSTR(ARG_SIZE) "s " | 272 "%" XSTR(ARG_SIZE) "s " |
| (...skipping 13 matching lines...) Expand all Loading... |
| 270 "p/print <reg or value or *addr> -- print integer value\n" | 286 "p/print <reg or value or *addr> -- print integer value\n" |
| 271 "pf/printfloat <freg or *addr> -- print float value\n" | 287 "pf/printfloat <freg or *addr> -- print float value\n" |
| 272 "po/printobject <*reg or *addr> -- print object\n" | 288 "po/printobject <*reg or *addr> -- print object\n" |
| 273 "si/stepi -- single step an instruction\n" | 289 "si/stepi -- single step an instruction\n" |
| 274 "unstop -- if current pc is a stop instr make it a nop\n" | 290 "unstop -- if current pc is a stop instr make it a nop\n" |
| 275 "q/quit -- Quit the debugger and exit the program\n"); | 291 "q/quit -- Quit the debugger and exit the program\n"); |
| 276 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 292 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
| 277 OS::Print("Quitting\n"); | 293 OS::Print("Quitting\n"); |
| 278 OS::Exit(0); | 294 OS::Exit(0); |
| 279 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 295 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 280 if (decoded) { | 296 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 281 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | |
| 282 } else { | |
| 283 OS::Print("Instruction could not be decoded. Stepping disabled.\n"); | |
| 284 } | |
| 285 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 297 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 286 if (decoded) { | 298 // Execute the one instruction we broke at with breakpoints disabled. |
| 287 // Execute the one instruction we broke at with breakpoints disabled. | 299 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 288 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 300 // Leave the debugger shell. |
| 289 // Leave the debugger shell. | 301 done = true; |
| 290 done = true; | |
| 291 } else { | |
| 292 OS::Print("Instruction could not be decoded. Cannot continue.\n"); | |
| 293 } | |
| 294 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 302 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
| 295 if (args == 2) { | 303 if (args == 2) { |
| 296 uint32_t value; | 304 uint32_t value; |
| 297 if (GetValue(arg1, &value)) { | 305 if (GetValue(arg1, &value)) { |
| 298 OS::Print("%s: %u 0x%x\n", arg1, value, value); | 306 OS::Print("%s: %u 0x%x\n", arg1, value, value); |
| 299 } else { | 307 } else { |
| 300 OS::Print("%s unrecognized\n", arg1); | 308 OS::Print("%s unrecognized\n", arg1); |
| 301 } | 309 } |
| 302 } else { | 310 } else { |
| 303 OS::Print("print <reg or value or *addr>\n"); | 311 OS::Print("print <reg or value or *addr>\n"); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 // handling stack overflow exceptions. To be safe in potential | 500 // handling stack overflow exceptions. To be safe in potential |
| 493 // stack underflows we also add some underflow buffer space. | 501 // stack underflows we also add some underflow buffer space. |
| 494 stack_ = new char[(Isolate::GetSpecifiedStackSize() + | 502 stack_ = new char[(Isolate::GetSpecifiedStackSize() + |
| 495 Isolate::kStackSizeBuffer + | 503 Isolate::kStackSizeBuffer + |
| 496 kSimulatorStackUnderflowSize)]; | 504 kSimulatorStackUnderflowSize)]; |
| 497 icount_ = 0; | 505 icount_ = 0; |
| 498 delay_slot_ = false; | 506 delay_slot_ = false; |
| 499 break_pc_ = NULL; | 507 break_pc_ = NULL; |
| 500 break_instr_ = 0; | 508 break_instr_ = 0; |
| 501 | 509 |
| 510 debugger_attached_ = false; |
| 511 |
| 502 // Setup architecture state. | 512 // Setup architecture state. |
| 503 // All registers are initialized to zero to start with. | 513 // All registers are initialized to zero to start with. |
| 504 for (int i = 0; i < kNumberOfCpuRegisters; i++) { | 514 for (int i = 0; i < kNumberOfCpuRegisters; i++) { |
| 505 registers_[i] = 0; | 515 registers_[i] = 0; |
| 506 } | 516 } |
| 507 pc_ = 0; | 517 pc_ = 0; |
| 508 // The sp is initialized to point to the bottom (high address) of the | 518 // The sp is initialized to point to the bottom (high address) of the |
| 509 // allocated stack area. | 519 // allocated stack area. |
| 510 registers_[SP] = StackTop(); | 520 registers_[SP] = StackTop(); |
| 511 } | 521 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 fregisters_[reg] = value; | 564 fregisters_[reg] = value; |
| 555 } | 565 } |
| 556 | 566 |
| 557 | 567 |
| 558 double Simulator::get_fregister(FRegister reg) const { | 568 double Simulator::get_fregister(FRegister reg) const { |
| 559 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters)); | 569 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters)); |
| 560 return fregisters_[reg]; | 570 return fregisters_[reg]; |
| 561 } | 571 } |
| 562 | 572 |
| 563 | 573 |
| 574 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 575 char buffer[64]; |
| 576 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
| 577 SimulatorDebugger dbg(this); |
| 578 dbg.Stop(instr, buffer); |
| 579 FATAL("Cannot continue execution after unimplemented instruction."); |
| 580 } |
| 581 |
| 582 |
| 564 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 583 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
| 565 uword fault_pc = get_pc(); | 584 uword fault_pc = get_pc(); |
| 566 // The debugger will not be able to single step past this instruction, but | 585 // The debugger will not be able to single step past this instruction, but |
| 567 // it will be possible to disassemble the code and inspect registers. | 586 // it will be possible to disassemble the code and inspect registers. |
| 568 char buffer[128]; | 587 char buffer[128]; |
| 569 snprintf(buffer, sizeof(buffer), | 588 snprintf(buffer, sizeof(buffer), |
| 570 "illegal memory access at 0x%"Px", pc=0x%"Px"\n", | 589 "illegal memory access at 0x%"Px", pc=0x%"Px"\n", |
| 571 addr, fault_pc); | 590 addr, fault_pc); |
| 572 SimulatorDebugger dbg(this); | 591 SimulatorDebugger dbg(this); |
| 573 dbg.Stop(instr, buffer); | 592 dbg.Stop(instr, buffer); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 case AND: { | 724 case AND: { |
| 706 ASSERT(instr->SaField() == 0); | 725 ASSERT(instr->SaField() == 0); |
| 707 // Format(instr, "and 'rd, 'rs, 'rt"); | 726 // Format(instr, "and 'rd, 'rs, 'rt"); |
| 708 int32_t rs_val = get_register(instr->RsField()); | 727 int32_t rs_val = get_register(instr->RsField()); |
| 709 int32_t rt_val = get_register(instr->RtField()); | 728 int32_t rt_val = get_register(instr->RtField()); |
| 710 set_register(instr->RdField(), rs_val & rt_val); | 729 set_register(instr->RdField(), rs_val & rt_val); |
| 711 break; | 730 break; |
| 712 } | 731 } |
| 713 case BREAK: { | 732 case BREAK: { |
| 714 SimulatorDebugger dbg(this); | 733 SimulatorDebugger dbg(this); |
| 715 dbg.Stop(instr, "breakpoint"); | 734 dbg.Attach(instr, "breakpoint"); |
| 716 break; | 735 break; |
| 717 } | 736 } |
| 718 case DIV: { | 737 case DIV: { |
| 719 ASSERT(instr->RdField() == 0); | 738 ASSERT(instr->RdField() == 0); |
| 720 ASSERT(instr->SaField() == 0); | 739 ASSERT(instr->SaField() == 0); |
| 721 // Format(instr, "div 'rs, 'rt"); | 740 // Format(instr, "div 'rs, 'rt"); |
| 722 int32_t rs_val = get_register(instr->RsField()); | 741 int32_t rs_val = get_register(instr->RsField()); |
| 723 int32_t rt_val = get_register(instr->RtField()); | 742 int32_t rt_val = get_register(instr->RtField()); |
| 724 if (rt_val == 0) { | 743 if (rt_val == 0) { |
| 725 // Results are unpredictable. | 744 // Results are unpredictable. |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 case XOR: { | 953 case XOR: { |
| 935 ASSERT(instr->SaField() == 0); | 954 ASSERT(instr->SaField() == 0); |
| 936 // Format(instr, "xor 'rd, 'rs, 'rt"); | 955 // Format(instr, "xor 'rd, 'rs, 'rt"); |
| 937 int32_t rs_val = get_register(instr->RsField()); | 956 int32_t rs_val = get_register(instr->RsField()); |
| 938 int32_t rt_val = get_register(instr->RtField()); | 957 int32_t rt_val = get_register(instr->RtField()); |
| 939 set_register(instr->RdField(), rs_val ^ rt_val); | 958 set_register(instr->RdField(), rs_val ^ rt_val); |
| 940 break; | 959 break; |
| 941 } | 960 } |
| 942 default: { | 961 default: { |
| 943 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); | 962 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); |
| 944 UNIMPLEMENTED(); | 963 UnimplementedInstruction(instr); |
| 945 break; | 964 break; |
| 946 } | 965 } |
| 947 } | 966 } |
| 948 } | 967 } |
| 949 | 968 |
| 950 | 969 |
| 951 void Simulator::DecodeSpecial2(Instr* instr) { | 970 void Simulator::DecodeSpecial2(Instr* instr) { |
| 952 ASSERT(instr->OpcodeField() == SPECIAL2); | 971 ASSERT(instr->OpcodeField() == SPECIAL2); |
| 953 switch (instr->FunctionField()) { | 972 switch (instr->FunctionField()) { |
| 954 case CLO: { | 973 case CLO: { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 976 rs_val <<= 1; | 995 rs_val <<= 1; |
| 977 } | 996 } |
| 978 } else { | 997 } else { |
| 979 bitcount = 32; | 998 bitcount = 32; |
| 980 } | 999 } |
| 981 set_register(instr->RdField(), bitcount); | 1000 set_register(instr->RdField(), bitcount); |
| 982 break; | 1001 break; |
| 983 } | 1002 } |
| 984 default: { | 1003 default: { |
| 985 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); | 1004 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); |
| 986 UNIMPLEMENTED(); | 1005 UnimplementedInstruction(instr); |
| 987 break; | 1006 break; |
| 988 } | 1007 } |
| 989 } | 1008 } |
| 990 } | 1009 } |
| 991 | 1010 |
| 992 | 1011 |
| 993 void Simulator::InstructionDecode(Instr* instr) { | 1012 void Simulator::InstructionDecode(Instr* instr) { |
| 994 switch (instr->OpcodeField()) { | 1013 switch (instr->OpcodeField()) { |
| 995 case SPECIAL: { | 1014 case SPECIAL: { |
| 996 DecodeSpecial(instr); | 1015 DecodeSpecial(instr); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1126 if (Simulator::IsIllegalAddress(addr)) { | 1145 if (Simulator::IsIllegalAddress(addr)) { |
| 1127 HandleIllegalAccess(addr, instr); | 1146 HandleIllegalAccess(addr, instr); |
| 1128 } else { | 1147 } else { |
| 1129 WriteW(addr, rt_val, instr); | 1148 WriteW(addr, rt_val, instr); |
| 1130 } | 1149 } |
| 1131 break; | 1150 break; |
| 1132 } | 1151 } |
| 1133 default: { | 1152 default: { |
| 1134 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", | 1153 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", |
| 1135 instr->InstructionBits(), instr); | 1154 instr->InstructionBits(), instr); |
| 1136 UNIMPLEMENTED(); | 1155 UnimplementedInstruction(instr); |
| 1137 break; | 1156 break; |
| 1138 } | 1157 } |
| 1139 } | 1158 } |
| 1140 pc_ += Instr::kInstrSize; | 1159 pc_ += Instr::kInstrSize; |
| 1141 } | 1160 } |
| 1142 | 1161 |
| 1143 | 1162 |
| 1144 void Simulator::ExecuteDelaySlot() { | 1163 void Simulator::ExecuteDelaySlot() { |
| 1145 ASSERT(pc_ != kEndSimulatingPC); | 1164 ASSERT(pc_ != kEndSimulatingPC); |
| 1146 delay_slot_ = true; | 1165 delay_slot_ = true; |
| 1147 icount_++; | 1166 icount_++; |
| 1167 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); |
| 1148 if (icount_ == FLAG_stop_sim_at) { | 1168 if (icount_ == FLAG_stop_sim_at) { |
| 1149 UNIMPLEMENTED(); | 1169 SimulatorDebugger dbg(this); |
| 1170 dbg.Attach(instr, "Instruction count reached"); |
| 1150 } | 1171 } |
| 1151 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); | |
| 1152 InstructionDecode(instr); | 1172 InstructionDecode(instr); |
| 1153 delay_slot_ = false; | 1173 delay_slot_ = false; |
| 1154 } | 1174 } |
| 1155 | 1175 |
| 1156 | 1176 |
| 1157 void Simulator::Execute() { | 1177 void Simulator::Execute() { |
| 1158 if (FLAG_stop_sim_at == 0) { | 1178 if (FLAG_stop_sim_at == 0) { |
| 1159 // Fast version of the dispatch loop without checking whether the simulator | 1179 // Fast version of the dispatch loop without checking whether the simulator |
| 1160 // should be stopping at a particular executed instruction. | 1180 // should be stopping at a particular executed instruction. |
| 1161 while (pc_ != kEndSimulatingPC) { | 1181 while (pc_ != kEndSimulatingPC) { |
| 1162 icount_++; | 1182 icount_++; |
| 1163 Instr* instr = Instr::At(pc_); | 1183 Instr* instr = Instr::At(pc_); |
| 1164 InstructionDecode(instr); | 1184 if (IsIllegalAddress(pc_)) { |
| 1185 HandleIllegalAccess(pc_, instr); |
| 1186 } else { |
| 1187 InstructionDecode(instr); |
| 1188 } |
| 1165 } | 1189 } |
| 1166 } else { | 1190 } else { |
| 1167 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 1191 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 1168 // we reach the particular instruction count. | 1192 // we reach the particular instruction count. |
| 1169 while (pc_ != kEndSimulatingPC) { | 1193 while (pc_ != kEndSimulatingPC) { |
| 1170 icount_++; | 1194 icount_++; |
| 1195 Instr* instr = Instr::At(pc_); |
| 1171 if (icount_ == FLAG_stop_sim_at) { | 1196 if (icount_ == FLAG_stop_sim_at) { |
| 1172 UNIMPLEMENTED(); | 1197 SimulatorDebugger dbg(this); |
| 1198 dbg.Attach(instr, "Instruction count reached"); |
| 1173 } else { | 1199 } else { |
| 1174 Instr* instr = Instr::At(pc_); | 1200 if (IsIllegalAddress(pc_)) { |
| 1175 InstructionDecode(instr); | 1201 HandleIllegalAccess(pc_, instr); |
| 1202 } else { |
| 1203 InstructionDecode(instr); |
| 1204 } |
| 1176 } | 1205 } |
| 1177 } | 1206 } |
| 1178 } | 1207 } |
| 1179 } | 1208 } |
| 1180 | 1209 |
| 1181 | 1210 |
| 1182 int64_t Simulator::Call(int32_t entry, | 1211 int64_t Simulator::Call(int32_t entry, |
| 1183 int32_t parameter0, | 1212 int32_t parameter0, |
| 1184 int32_t parameter1, | 1213 int32_t parameter1, |
| 1185 int32_t parameter2, | 1214 int32_t parameter2, |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 // Restore the SP register and return R1:R0. | 1287 // Restore the SP register and return R1:R0. |
| 1259 set_register(SP, sp_before_call); | 1288 set_register(SP, sp_before_call); |
| 1260 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); | 1289 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); |
| 1261 } | 1290 } |
| 1262 | 1291 |
| 1263 } // namespace dart | 1292 } // namespace dart |
| 1264 | 1293 |
| 1265 #endif // !defined(HOST_ARCH_MIPS) | 1294 #endif // !defined(HOST_ARCH_MIPS) |
| 1266 | 1295 |
| 1267 #endif // defined TARGET_ARCH_MIPS | 1296 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |