Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: runtime/vm/simulator_mips.cc

Issue 12903006: Drops into Simulator Debugger only in a session that is already interactive. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« runtime/vm/simulator_mips.h ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« runtime/vm/simulator_mips.h ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698