| 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 void SimulatorDebugger::RedoBreakpoints() { | 212 void SimulatorDebugger::RedoBreakpoints() { |
| 213 if (sim_->break_pc_ != NULL) { | 213 if (sim_->break_pc_ != NULL) { |
| 214 sim_->break_pc_->SetInstructionBits(Instr::kBreakPointInstruction); | 214 sim_->break_pc_->SetInstructionBits(Instr::kBreakPointInstruction); |
| 215 } | 215 } |
| 216 } | 216 } |
| 217 | 217 |
| 218 | 218 |
| 219 void SimulatorDebugger::Debug() { | 219 void SimulatorDebugger::Debug() { |
| 220 intptr_t last_pc = -1; | 220 intptr_t last_pc = -1; |
| 221 bool done = false; | 221 bool done = false; |
| 222 bool decoded = true; | |
| 223 | 222 |
| 224 #define COMMAND_SIZE 63 | 223 #define COMMAND_SIZE 63 |
| 225 #define ARG_SIZE 255 | 224 #define ARG_SIZE 255 |
| 226 | 225 |
| 227 #define STR(a) #a | 226 #define STR(a) #a |
| 228 #define XSTR(a) STR(a) | 227 #define XSTR(a) STR(a) |
| 229 | 228 |
| 230 char cmd[COMMAND_SIZE + 1]; | 229 char cmd[COMMAND_SIZE + 1]; |
| 231 char arg1[ARG_SIZE + 1]; | 230 char arg1[ARG_SIZE + 1]; |
| 232 char arg2[ARG_SIZE + 1]; | 231 char arg2[ARG_SIZE + 1]; |
| 233 | 232 |
| 234 // make sure to have a proper terminating character if reaching the limit | 233 // make sure to have a proper terminating character if reaching the limit |
| 235 cmd[COMMAND_SIZE] = 0; | 234 cmd[COMMAND_SIZE] = 0; |
| 236 arg1[ARG_SIZE] = 0; | 235 arg1[ARG_SIZE] = 0; |
| 237 arg2[ARG_SIZE] = 0; | 236 arg2[ARG_SIZE] = 0; |
| 238 | 237 |
| 239 // Undo all set breakpoints while running in the debugger shell. This will | 238 // Undo all set breakpoints while running in the debugger shell. This will |
| 240 // make them invisible to all commands. | 239 // make them invisible to all commands. |
| 241 UndoBreakpoints(); | 240 UndoBreakpoints(); |
| 242 | 241 |
| 243 while (!done) { | 242 while (!done) { |
| 244 if (last_pc != sim_->get_pc()) { | 243 if (last_pc != sim_->get_pc()) { |
| 245 last_pc = sim_->get_pc(); | 244 last_pc = sim_->get_pc(); |
| 246 decoded = Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); | 245 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize); |
| 247 } | 246 } |
| 248 char* line = ReadLine("sim> "); | 247 char* line = ReadLine("sim> "); |
| 249 if (line == NULL) { | 248 if (line == NULL) { |
| 250 break; | 249 FATAL("ReadLine failed"); |
| 251 } else { | 250 } else { |
| 252 // Use sscanf to parse the individual parts of the command line. At the | 251 // Use sscanf to parse the individual parts of the command line. At the |
| 253 // moment no command expects more than two parameters. | 252 // moment no command expects more than two parameters. |
| 254 int args = SScanF(line, | 253 int args = SScanF(line, |
| 255 "%" XSTR(COMMAND_SIZE) "s " | 254 "%" XSTR(COMMAND_SIZE) "s " |
| 256 "%" XSTR(ARG_SIZE) "s " | 255 "%" XSTR(ARG_SIZE) "s " |
| 257 "%" XSTR(ARG_SIZE) "s", | 256 "%" XSTR(ARG_SIZE) "s", |
| 258 cmd, arg1, arg2); | 257 cmd, arg1, arg2); |
| 259 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { | 258 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { |
| 260 OS::Print("c/cont -- continue execution\n" | 259 OS::Print("c/cont -- continue execution\n" |
| 261 "disasm -- disassemble instrs at current pc location\n" | 260 "disasm -- disassemble instrs at current pc location\n" |
| 262 " other variants are:\n" | 261 " other variants are:\n" |
| 263 " disasm <address>\n" | 262 " disasm <address>\n" |
| 264 " disasm <address> <number_of_instructions>\n" | 263 " disasm <address> <number_of_instructions>\n" |
| 265 " by default 10 instrs are disassembled\n" | 264 " by default 10 instrs are disassembled\n" |
| 266 "del -- delete breakpoints\n" | 265 "del -- delete breakpoints\n" |
| 267 "gdb -- transfer control to gdb\n" | 266 "gdb -- transfer control to gdb\n" |
| 268 "h/help -- print this help string\n" | 267 "h/help -- print this help string\n" |
| 269 "break <address> -- set break point at specified address\n" | 268 "break <address> -- set break point at specified address\n" |
| 270 "p/print <reg or value or *addr> -- print integer value\n" | 269 "p/print <reg or value or *addr> -- print integer value\n" |
| 271 "pf/printfloat <freg or *addr> -- print float value\n" | 270 "pf/printfloat <freg or *addr> -- print float value\n" |
| 272 "po/printobject <*reg or *addr> -- print object\n" | 271 "po/printobject <*reg or *addr> -- print object\n" |
| 273 "si/stepi -- single step an instruction\n" | 272 "si/stepi -- single step an instruction\n" |
| 274 "unstop -- if current pc is a stop instr make it a nop\n" | 273 "unstop -- if current pc is a stop instr make it a nop\n" |
| 275 "q/quit -- Quit the debugger and exit the program\n"); | 274 "q/quit -- Quit the debugger and exit the program\n"); |
| 276 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 275 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
| 277 OS::Print("Quitting\n"); | 276 OS::Print("Quitting\n"); |
| 278 OS::Exit(0); | 277 OS::Exit(0); |
| 279 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 278 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 280 if (decoded) { | 279 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)) { | 280 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 286 if (decoded) { | 281 // Execute the one instruction we broke at with breakpoints disabled. |
| 287 // Execute the one instruction we broke at with breakpoints disabled. | 282 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 288 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 283 // Leave the debugger shell. |
| 289 // Leave the debugger shell. | 284 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)) { | 285 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
| 295 if (args == 2) { | 286 if (args == 2) { |
| 296 uint32_t value; | 287 uint32_t value; |
| 297 if (GetValue(arg1, &value)) { | 288 if (GetValue(arg1, &value)) { |
| 298 OS::Print("%s: %u 0x%x\n", arg1, value, value); | 289 OS::Print("%s: %u 0x%x\n", arg1, value, value); |
| 299 } else { | 290 } else { |
| 300 OS::Print("%s unrecognized\n", arg1); | 291 OS::Print("%s unrecognized\n", arg1); |
| 301 } | 292 } |
| 302 } else { | 293 } else { |
| 303 OS::Print("print <reg or value or *addr>\n"); | 294 OS::Print("print <reg or value or *addr>\n"); |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 fregisters_[reg] = value; | 545 fregisters_[reg] = value; |
| 555 } | 546 } |
| 556 | 547 |
| 557 | 548 |
| 558 double Simulator::get_fregister(FRegister reg) const { | 549 double Simulator::get_fregister(FRegister reg) const { |
| 559 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters)); | 550 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters)); |
| 560 return fregisters_[reg]; | 551 return fregisters_[reg]; |
| 561 } | 552 } |
| 562 | 553 |
| 563 | 554 |
| 555 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 556 char buffer[64]; |
| 557 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
| 558 SimulatorDebugger dbg(this); |
| 559 dbg.Stop(instr, buffer); |
| 560 FATAL("Cannot continue execution after unimplemented instruction."); |
| 561 } |
| 562 |
| 563 |
| 564 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { | 564 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) { |
| 565 uword fault_pc = get_pc(); | 565 uword fault_pc = get_pc(); |
| 566 // The debugger will not be able to single step past this instruction, but | 566 // 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. | 567 // it will be possible to disassemble the code and inspect registers. |
| 568 char buffer[128]; | 568 char buffer[128]; |
| 569 snprintf(buffer, sizeof(buffer), | 569 snprintf(buffer, sizeof(buffer), |
| 570 "illegal memory access at 0x%"Px", pc=0x%"Px"\n", | 570 "illegal memory access at 0x%"Px", pc=0x%"Px"\n", |
| 571 addr, fault_pc); | 571 addr, fault_pc); |
| 572 SimulatorDebugger dbg(this); | 572 SimulatorDebugger dbg(this); |
| 573 dbg.Stop(instr, buffer); | 573 dbg.Stop(instr, buffer); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 case XOR: { | 934 case XOR: { |
| 935 ASSERT(instr->SaField() == 0); | 935 ASSERT(instr->SaField() == 0); |
| 936 // Format(instr, "xor 'rd, 'rs, 'rt"); | 936 // Format(instr, "xor 'rd, 'rs, 'rt"); |
| 937 int32_t rs_val = get_register(instr->RsField()); | 937 int32_t rs_val = get_register(instr->RsField()); |
| 938 int32_t rt_val = get_register(instr->RtField()); | 938 int32_t rt_val = get_register(instr->RtField()); |
| 939 set_register(instr->RdField(), rs_val ^ rt_val); | 939 set_register(instr->RdField(), rs_val ^ rt_val); |
| 940 break; | 940 break; |
| 941 } | 941 } |
| 942 default: { | 942 default: { |
| 943 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); | 943 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); |
| 944 UNIMPLEMENTED(); | 944 UnimplementedInstruction(instr); |
| 945 break; | 945 break; |
| 946 } | 946 } |
| 947 } | 947 } |
| 948 } | 948 } |
| 949 | 949 |
| 950 | 950 |
| 951 void Simulator::DecodeSpecial2(Instr* instr) { | 951 void Simulator::DecodeSpecial2(Instr* instr) { |
| 952 ASSERT(instr->OpcodeField() == SPECIAL2); | 952 ASSERT(instr->OpcodeField() == SPECIAL2); |
| 953 switch (instr->FunctionField()) { | 953 switch (instr->FunctionField()) { |
| 954 case CLO: { | 954 case CLO: { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 976 rs_val <<= 1; | 976 rs_val <<= 1; |
| 977 } | 977 } |
| 978 } else { | 978 } else { |
| 979 bitcount = 32; | 979 bitcount = 32; |
| 980 } | 980 } |
| 981 set_register(instr->RdField(), bitcount); | 981 set_register(instr->RdField(), bitcount); |
| 982 break; | 982 break; |
| 983 } | 983 } |
| 984 default: { | 984 default: { |
| 985 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); | 985 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); |
| 986 UNIMPLEMENTED(); | 986 UnimplementedInstruction(instr); |
| 987 break; | 987 break; |
| 988 } | 988 } |
| 989 } | 989 } |
| 990 } | 990 } |
| 991 | 991 |
| 992 | 992 |
| 993 void Simulator::InstructionDecode(Instr* instr) { | 993 void Simulator::InstructionDecode(Instr* instr) { |
| 994 switch (instr->OpcodeField()) { | 994 switch (instr->OpcodeField()) { |
| 995 case SPECIAL: { | 995 case SPECIAL: { |
| 996 DecodeSpecial(instr); | 996 DecodeSpecial(instr); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1126 if (Simulator::IsIllegalAddress(addr)) { | 1126 if (Simulator::IsIllegalAddress(addr)) { |
| 1127 HandleIllegalAccess(addr, instr); | 1127 HandleIllegalAccess(addr, instr); |
| 1128 } else { | 1128 } else { |
| 1129 WriteW(addr, rt_val, instr); | 1129 WriteW(addr, rt_val, instr); |
| 1130 } | 1130 } |
| 1131 break; | 1131 break; |
| 1132 } | 1132 } |
| 1133 default: { | 1133 default: { |
| 1134 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", | 1134 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", |
| 1135 instr->InstructionBits(), instr); | 1135 instr->InstructionBits(), instr); |
| 1136 UNIMPLEMENTED(); | 1136 UnimplementedInstruction(instr); |
| 1137 break; | 1137 break; |
| 1138 } | 1138 } |
| 1139 } | 1139 } |
| 1140 pc_ += Instr::kInstrSize; | 1140 pc_ += Instr::kInstrSize; |
| 1141 } | 1141 } |
| 1142 | 1142 |
| 1143 | 1143 |
| 1144 void Simulator::ExecuteDelaySlot() { | 1144 void Simulator::ExecuteDelaySlot() { |
| 1145 ASSERT(pc_ != kEndSimulatingPC); | 1145 ASSERT(pc_ != kEndSimulatingPC); |
| 1146 delay_slot_ = true; | 1146 delay_slot_ = true; |
| 1147 icount_++; | 1147 icount_++; |
| 1148 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); |
| 1148 if (icount_ == FLAG_stop_sim_at) { | 1149 if (icount_ == FLAG_stop_sim_at) { |
| 1149 UNIMPLEMENTED(); | 1150 SimulatorDebugger dbg(this); |
| 1151 dbg.Stop(instr, "Instruction count reached"); |
| 1150 } | 1152 } |
| 1151 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); | |
| 1152 InstructionDecode(instr); | 1153 InstructionDecode(instr); |
| 1153 delay_slot_ = false; | 1154 delay_slot_ = false; |
| 1154 } | 1155 } |
| 1155 | 1156 |
| 1156 | 1157 |
| 1157 void Simulator::Execute() { | 1158 void Simulator::Execute() { |
| 1158 if (FLAG_stop_sim_at == 0) { | 1159 if (FLAG_stop_sim_at == 0) { |
| 1159 // Fast version of the dispatch loop without checking whether the simulator | 1160 // Fast version of the dispatch loop without checking whether the simulator |
| 1160 // should be stopping at a particular executed instruction. | 1161 // should be stopping at a particular executed instruction. |
| 1161 while (pc_ != kEndSimulatingPC) { | 1162 while (pc_ != kEndSimulatingPC) { |
| 1162 icount_++; | 1163 icount_++; |
| 1163 Instr* instr = Instr::At(pc_); | 1164 Instr* instr = Instr::At(pc_); |
| 1164 InstructionDecode(instr); | 1165 if (IsIllegalAddress(pc_)) { |
| 1166 HandleIllegalAccess(pc_, instr); |
| 1167 } else { |
| 1168 InstructionDecode(instr); |
| 1169 } |
| 1165 } | 1170 } |
| 1166 } else { | 1171 } else { |
| 1167 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 1172 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 1168 // we reach the particular instruction count. | 1173 // we reach the particular instruction count. |
| 1169 while (pc_ != kEndSimulatingPC) { | 1174 while (pc_ != kEndSimulatingPC) { |
| 1170 icount_++; | 1175 icount_++; |
| 1176 Instr* instr = Instr::At(pc_); |
| 1171 if (icount_ == FLAG_stop_sim_at) { | 1177 if (icount_ == FLAG_stop_sim_at) { |
| 1172 UNIMPLEMENTED(); | 1178 SimulatorDebugger dbg(this); |
| 1179 dbg.Stop(instr, "Instruction count reached"); |
| 1173 } else { | 1180 } else { |
| 1174 Instr* instr = Instr::At(pc_); | 1181 if (IsIllegalAddress(pc_)) { |
| 1175 InstructionDecode(instr); | 1182 HandleIllegalAccess(pc_, instr); |
| 1183 } else { |
| 1184 InstructionDecode(instr); |
| 1185 } |
| 1176 } | 1186 } |
| 1177 } | 1187 } |
| 1178 } | 1188 } |
| 1179 } | 1189 } |
| 1180 | 1190 |
| 1181 | 1191 |
| 1182 int64_t Simulator::Call(int32_t entry, | 1192 int64_t Simulator::Call(int32_t entry, |
| 1183 int32_t parameter0, | 1193 int32_t parameter0, |
| 1184 int32_t parameter1, | 1194 int32_t parameter1, |
| 1185 int32_t parameter2, | 1195 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. | 1268 // Restore the SP register and return R1:R0. |
| 1259 set_register(SP, sp_before_call); | 1269 set_register(SP, sp_before_call); |
| 1260 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); | 1270 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); |
| 1261 } | 1271 } |
| 1262 | 1272 |
| 1263 } // namespace dart | 1273 } // namespace dart |
| 1264 | 1274 |
| 1265 #endif // !defined(HOST_ARCH_MIPS) | 1275 #endif // !defined(HOST_ARCH_MIPS) |
| 1266 | 1276 |
| 1267 #endif // defined TARGET_ARCH_MIPS | 1277 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |