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

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

Issue 12431016: Copies Simulator Debugger from ARM to MIPS. (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/disassembler_arm.cc ('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
11 #include "vm/simulator.h" 11 #include "vm/simulator.h"
12 12
13 #include "vm/assembler.h" 13 #include "vm/assembler.h"
14 #include "vm/constants_mips.h" 14 #include "vm/constants_mips.h"
15 #include "vm/disassembler.h" 15 #include "vm/disassembler.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); 19 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at.");
20 20
21
22 // This macro provides a platform independent use of sscanf. The reason for
23 // SScanF not being implemented in a platform independent way through
24 // OS in the same way as SNPrint is that the Windows C Run-Time
25 // Library does not provide vsscanf.
26 #define SScanF sscanf // NOLINT
27
28
29 // The SimulatorDebugger class is used by the simulator while debugging
30 // simulated MIPS code.
31 class SimulatorDebugger {
32 public:
33 explicit SimulatorDebugger(Simulator* sim);
34 ~SimulatorDebugger();
35
36 void Stop(Instr* instr, const char* message);
37 void Debug();
38 char* ReadLine(const char* prompt);
39
40 private:
41 Simulator* sim_;
42
43 bool GetValue(char* desc, uint32_t* value);
44 bool GetFValue(char* desc, double* value);
45
46 // Set or delete a breakpoint. Returns true if successful.
47 bool SetBreakpoint(Instr* breakpc);
48 bool DeleteBreakpoint(Instr* breakpc);
49
50 // Undo and redo all breakpoints. This is needed to bracket disassembly and
51 // execution to skip past breakpoints when run from the debugger.
52 void UndoBreakpoints();
53 void RedoBreakpoints();
54 };
55
56
57 SimulatorDebugger::SimulatorDebugger(Simulator* sim) {
58 sim_ = sim;
59 }
60
61
62 SimulatorDebugger::~SimulatorDebugger() {
63 }
64
65
66 void SimulatorDebugger::Stop(Instr* instr, const char* message) {
67 OS::Print("Simulator hit %s\n", message);
68 Debug();
69 }
70
71
72 static Register LookupCpuRegisterByName(const char* name) {
73 static const char* kNames[] = {
74 "r0", "r1", "r2", "r3",
75 "r4", "r5", "r6", "r7",
76 "r8", "r9", "r10", "r11",
77 "r12", "r13", "r14", "r15",
78 "r16", "r17", "r18", "r19",
79 "r20", "r21", "r22", "r23",
80 "r24", "r25", "r26", "r27",
81 "r28", "r29", "r30", "r31",
82
83 "zr", "at", "v0", "v1",
84 "a0", "a1", "a2", "a3",
85 "t0", "t1", "t2", "t3",
86 "t4", "t5", "t6", "t7",
87 "s0", "s1", "s2", "s3",
88 "s4", "s5", "s6", "s7",
89 "t8", "t9", "k0", "k1",
90 "gp", "sp", "fp", "ra"
91 };
92 static const Register kRegisters[] = {
93 R0, R1, R2, R3,
94 R4, R5, R6, R7,
95 R8, R9, R10, R11,
96 R12, R13, R14, R15,
97 R16, R17, R18, R19,
98 R20, R21, R22, R23,
99 R24, R25, R26, R27,
100 R28, R29, R30, R31,
101
102 ZR, AT, V0, V1,
103 A0, A1, A2, A3,
104 T0, T1, T2, T3,
105 T4, T5, T6, T7,
106 S0, S1, S2, S3,
107 S4, S5, S6, S7,
108 T8, T9, K0, K1,
109 GP, SP, FP, RA
110 };
111 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
112 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
113 if (strcmp(kNames[i], name) == 0) {
114 return kRegisters[i];
115 }
116 }
117 return kNoRegister;
118 }
119
120
121 static FRegister LookupFRegisterByName(const char* name) {
122 int reg_nr = -1;
123 bool ok = SScanF(name, "f%d", &reg_nr);
124 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfFRegisters)) {
125 return static_cast<FRegister>(reg_nr);
126 }
127 return kNoFRegister;
128 }
129
130
131 bool SimulatorDebugger::GetValue(char* desc, uint32_t* value) {
132 Register reg = LookupCpuRegisterByName(desc);
133 if (reg != kNoRegister) {
134 *value = sim_->get_register(reg);
135 return true;
136 }
137 if ((desc[0] == '*')) {
138 uint32_t addr;
139 if (GetValue(desc + 1, &addr)) {
140 if (Simulator::IsIllegalAddress(addr)) {
141 return false;
142 }
143 *value = *(reinterpret_cast<uint32_t*>(addr));
144 return true;
145 }
146 }
147 if (strcmp("pc", desc) == 0) {
148 *value = sim_->get_pc();
149 return true;
150 }
151 bool retval = SScanF(desc, "0x%x", value) == 1;
152 if (!retval) {
153 retval = SScanF(desc, "%x", value) == 1;
154 }
155 return retval;
156 }
157
158
159 bool SimulatorDebugger::GetFValue(char* desc, double* value) {
160 FRegister freg = LookupFRegisterByName(desc);
161 if (freg != kNoFRegister) {
162 *value = sim_->get_fregister(freg);
163 return true;
164 }
165 if ((desc[0] == '*')) {
166 uint32_t addr;
167 if (GetValue(desc + 1, &addr)) {
168 if (Simulator::IsIllegalAddress(addr)) {
169 return false;
170 }
171 *value = *(reinterpret_cast<float*>(addr));
172 return true;
173 }
174 }
175 return false;
176 }
177
178
179 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) {
180 // Check if a breakpoint can be set. If not return without any side-effects.
181 if (sim_->break_pc_ != NULL) {
182 return false;
183 }
184
185 // Set the breakpoint.
186 sim_->break_pc_ = breakpc;
187 sim_->break_instr_ = breakpc->InstructionBits();
188 // Not setting the breakpoint instruction in the code itself. It will be set
189 // when the debugger shell continues.
190 return true;
191 }
192
193
194 bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) {
195 if (sim_->break_pc_ != NULL) {
196 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
197 }
198
199 sim_->break_pc_ = NULL;
200 sim_->break_instr_ = 0;
201 return true;
202 }
203
204
205 void SimulatorDebugger::UndoBreakpoints() {
206 if (sim_->break_pc_ != NULL) {
207 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
208 }
209 }
210
211
212 void SimulatorDebugger::RedoBreakpoints() {
213 if (sim_->break_pc_ != NULL) {
214 sim_->break_pc_->SetInstructionBits(Instr::kBreakPointInstruction);
215 }
216 }
217
218
219 void SimulatorDebugger::Debug() {
220 intptr_t last_pc = -1;
221 bool done = false;
222 bool decoded = true;
223
224 #define COMMAND_SIZE 63
225 #define ARG_SIZE 255
226
227 #define STR(a) #a
228 #define XSTR(a) STR(a)
229
230 char cmd[COMMAND_SIZE + 1];
231 char arg1[ARG_SIZE + 1];
232 char arg2[ARG_SIZE + 1];
233
234 // make sure to have a proper terminating character if reaching the limit
235 cmd[COMMAND_SIZE] = 0;
236 arg1[ARG_SIZE] = 0;
237 arg2[ARG_SIZE] = 0;
238
239 // Undo all set breakpoints while running in the debugger shell. This will
240 // make them invisible to all commands.
241 UndoBreakpoints();
242
243 while (!done) {
244 if (last_pc != sim_->get_pc()) {
245 last_pc = sim_->get_pc();
246 decoded = Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
247 }
248 char* line = ReadLine("sim> ");
249 if (line == NULL) {
250 break;
251 } else {
252 // Use sscanf to parse the individual parts of the command line. At the
253 // moment no command expects more than two parameters.
254 int args = SScanF(line,
255 "%" XSTR(COMMAND_SIZE) "s "
256 "%" XSTR(ARG_SIZE) "s "
257 "%" XSTR(ARG_SIZE) "s",
258 cmd, arg1, arg2);
259 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
260 OS::Print("c/cont -- continue execution\n"
261 "disasm -- disassemble instrs at current pc location\n"
262 " other variants are:\n"
263 " disasm <address>\n"
264 " disasm <address> <number_of_instructions>\n"
265 " by default 10 instrs are disassembled\n"
266 "del -- delete breakpoints\n"
267 "gdb -- transfer control to gdb\n"
268 "h/help -- print this help string\n"
269 "break <address> -- set break point at specified address\n"
270 "p/print <reg or value or *addr> -- print integer value\n"
271 "pf/printfloat <freg or *addr> -- print float value\n"
272 "po/printobject <*reg or *addr> -- print object\n"
273 "si/stepi -- single step an instruction\n"
274 "unstop -- if current pc is a stop instr make it a nop\n"
275 "q/quit -- Quit the debugger and exit program\n");
276 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) {
277 OS::Print("Quitting\n");
278 OS::Exit(0);
279 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
280 if (decoded) {
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)) {
286 if (decoded) {
287 // Execute the one instruction we broke at with breakpoints disabled.
288 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
289 // Leave the debugger shell.
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)) {
295 if (args == 2) {
296 uint32_t value;
297 if (GetValue(arg1, &value)) {
298 OS::Print("%s: %u 0x%x\n", arg1, value, value);
299 } else {
300 OS::Print("%s unrecognized\n", arg1);
301 }
302 } else {
303 OS::Print("print <reg or value or *addr>\n");
304 }
305 } else if ((strcmp(cmd, "pf") == 0) ||
306 (strcmp(cmd, "printfloat") == 0)) {
307 if (args == 2) {
308 double dvalue;
309 if (GetFValue(arg1, &dvalue)) {
310 uint64_t long_value = bit_cast<uint64_t, double>(dvalue);
311 OS::Print("%s: %llu 0x%llx %.8g\n",
312 arg1, long_value, long_value, dvalue);
313 } else {
314 OS::Print("%s unrecognized\n", arg1);
315 }
316 } else {
317 OS::Print("printfloat <dreg or *addr>\n");
318 }
319 } else if ((strcmp(cmd, "po") == 0) ||
320 (strcmp(cmd, "printobject") == 0)) {
321 if (args == 2) {
322 uint32_t value;
323 // Make the dereferencing '*' optional.
324 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) ||
325 GetValue(arg1, &value)) {
326 if (Isolate::Current()->heap()->Contains(value)) {
327 OS::Print("%s: \n", arg1);
328 #if defined(DEBUG)
329 const Object& obj = Object::Handle(
330 reinterpret_cast<RawObject*>(value));
331 obj.Print();
332 #endif // defined(DEBUG)
333 } else {
334 OS::Print("0x%x is not an object reference\n", value);
335 }
336 } else {
337 OS::Print("%s unrecognized\n", arg1);
338 }
339 } else {
340 OS::Print("printobject <*reg or *addr>\n");
341 }
342 } else if (strcmp(cmd, "disasm") == 0) {
343 uint32_t start = 0;
344 uint32_t end = 0;
345 if (args == 1) {
346 start = sim_->get_pc();
347 end = start + (10 * Instr::kInstrSize);
348 } else if (args == 2) {
349 if (GetValue(arg1, &start)) {
350 // no length parameter passed, assume 10 instructions
351 if (Simulator::IsIllegalAddress(start)) {
352 // If start isn't a valid address, warn and use PC instead
353 OS::Print("First argument yields invalid address: 0x%x\n", start);
354 OS::Print("Using PC instead");
355 start = sim_->get_pc();
356 }
357 end = start + (10 * Instr::kInstrSize);
358 }
359 } else {
360 uint32_t length;
361 if (GetValue(arg1, &start) && GetValue(arg2, &length)) {
362 if (Simulator::IsIllegalAddress(start)) {
363 // If start isn't a valid address, warn and use PC instead
364 OS::Print("First argument yields invalid address: 0x%x\n", start);
365 OS::Print("Using PC instead\n");
366 start = sim_->get_pc();
367 }
368 end = start + (length * Instr::kInstrSize);
369 }
370 }
371
372 Disassembler::Disassemble(start, end);
373 } else if (strcmp(cmd, "gdb") == 0) {
374 OS::Print("relinquishing control to gdb\n");
375 OS::DebugBreak();
376 OS::Print("regaining control from gdb\n");
377 } else if (strcmp(cmd, "break") == 0) {
378 if (args == 2) {
379 uint32_t addr;
380 if (GetValue(arg1, &addr)) {
381 if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) {
382 OS::Print("setting breakpoint failed\n");
383 }
384 } else {
385 OS::Print("%s unrecognized\n", arg1);
386 }
387 } else {
388 OS::Print("break <addr>\n");
389 }
390 } else if (strcmp(cmd, "del") == 0) {
391 if (!DeleteBreakpoint(NULL)) {
392 OS::Print("deleting breakpoint failed\n");
393 }
394 } else if (strcmp(cmd, "unstop") == 0) {
395 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
396 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
397 if (stop_instr->IsBreakPoint()) {
398 stop_instr->SetInstructionBits(Instr::kNopInstruction);
399 } else {
400 OS::Print("Not at debugger stop.\n");
401 }
402 } else {
403 OS::Print("Unknown command: %s\n", cmd);
404 }
405 }
406 delete[] line;
407 }
408
409 // Add all the breakpoints back to stop execution and enter the debugger
410 // shell when hit.
411 RedoBreakpoints();
412
413 #undef COMMAND_SIZE
414 #undef ARG_SIZE
415
416 #undef STR
417 #undef XSTR
418 }
419
420
421 char* SimulatorDebugger::ReadLine(const char* prompt) {
422 char* result = NULL;
423 char line_buf[256];
424 int offset = 0;
425 bool keep_going = true;
426 fprintf(stdout, "%s", prompt);
427 fflush(stdout);
428 while (keep_going) {
429 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
430 // fgets got an error. Just give up.
431 if (result != NULL) {
432 delete[] result;
433 }
434 return NULL;
435 }
436 int len = strlen(line_buf);
437 if (len > 1 &&
438 line_buf[len - 2] == '\\' &&
439 line_buf[len - 1] == '\n') {
440 // When we read a line that ends with a "\" we remove the escape and
441 // append the remainder.
442 line_buf[len - 2] = '\n';
443 line_buf[len - 1] = 0;
444 len -= 1;
445 } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
446 // Since we read a new line we are done reading the line. This
447 // will exit the loop after copying this buffer into the result.
448 keep_going = false;
449 }
450 if (result == NULL) {
451 // Allocate the initial result and make room for the terminating '\0'
452 result = new char[len + 1];
453 if (result == NULL) {
454 // OOM, so cannot readline anymore.
455 return NULL;
456 }
457 } else {
458 // Allocate a new result with enough room for the new addition.
459 int new_len = offset + len + 1;
460 char* new_result = new char[new_len];
461 if (new_result == NULL) {
462 // OOM, free the buffer allocated so far and return NULL.
463 delete[] result;
464 return NULL;
465 } else {
466 // Copy the existing input into the new array and set the new
467 // array as the result.
468 memmove(new_result, result, offset);
469 delete[] result;
470 result = new_result;
471 }
472 }
473 // Copy the newly read line into the result.
474 memmove(result + offset, line_buf, len);
475 offset += len;
476 }
477 ASSERT(result != NULL);
478 result[offset] = '\0';
479 return result;
480 }
481
482
21 void Simulator::InitOnce() { 483 void Simulator::InitOnce() {
22 } 484 }
23 485
24 486
25 Simulator::Simulator() { 487 Simulator::Simulator() {
26 // Setup simulator support first. Some of this information is needed to 488 // Setup simulator support first. Some of this information is needed to
27 // setup the architecture state. 489 // setup the architecture state.
28 // We allocate the stack here, the size is computed as the sum of 490 // We allocate the stack here, the size is computed as the sum of
29 // the size specified by the user and the buffer space needed for 491 // the size specified by the user and the buffer space needed for
30 // handling stack overflow exceptions. To be safe in potential 492 // handling stack overflow exceptions. To be safe in potential
31 // stack underflows we also add some underflow buffer space. 493 // stack underflows we also add some underflow buffer space.
32 stack_ = new char[(Isolate::GetSpecifiedStackSize() + 494 stack_ = new char[(Isolate::GetSpecifiedStackSize() +
33 Isolate::kStackSizeBuffer + 495 Isolate::kStackSizeBuffer +
34 kSimulatorStackUnderflowSize)]; 496 kSimulatorStackUnderflowSize)];
35 icount_ = 0; 497 icount_ = 0;
36 delay_slot_ = false; 498 delay_slot_ = false;
499 break_pc_ = NULL;
500 break_instr_ = 0;
37 501
38 // Setup architecture state. 502 // Setup architecture state.
39 // All registers are initialized to zero to start with. 503 // All registers are initialized to zero to start with.
40 for (int i = 0; i < kNumberOfCpuRegisters; i++) { 504 for (int i = 0; i < kNumberOfCpuRegisters; i++) {
41 registers_[i] = 0; 505 registers_[i] = 0;
42 } 506 }
43 pc_ = 0; 507 pc_ = 0;
44 // The sp is initialized to point to the bottom (high address) of the 508 // The sp is initialized to point to the bottom (high address) of the
45 // allocated stack area. 509 // allocated stack area.
46 registers_[SP] = StackTop(); 510 registers_[SP] = StackTop();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 // Get the register from the architecture state. This function does handle 542 // Get the register from the architecture state. This function does handle
79 // the special case of accessing the PC register. 543 // the special case of accessing the PC register.
80 int32_t Simulator::get_register(Register reg) const { 544 int32_t Simulator::get_register(Register reg) const {
81 if (reg == R0) { 545 if (reg == R0) {
82 return 0; 546 return 0;
83 } 547 }
84 return registers_[reg]; 548 return registers_[reg];
85 } 549 }
86 550
87 551
552 void Simulator::set_fregister(FRegister reg, double value) {
553 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters));
554 fregisters_[reg] = value;
555 }
556
557
558 double Simulator::get_fregister(FRegister reg) const {
559 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters));
560 return fregisters_[reg];
561 }
562
563
564 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) {
565 uword fault_pc = get_pc();
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.
568 char buffer[128];
569 snprintf(buffer, sizeof(buffer),
570 "illegal memory access at 0x%"Px", pc=0x%"Px"\n",
571 addr, fault_pc);
572 SimulatorDebugger dbg(this);
573 dbg.Stop(instr, buffer);
574 // The debugger will return control in non-interactive mode.
575 FATAL("Cannot continue execution after illegal memory access.");
576 }
577
578
579 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) {
580 // The debugger will not be able to single step past this instruction, but
581 // it will be possible to disassemble the code and inspect registers.
582 char buffer[64];
583 snprintf(buffer, sizeof(buffer),
584 "unaligned %s at 0x%"Px", pc=%p\n", msg, addr, instr);
585 SimulatorDebugger dbg(this);
586 dbg.Stop(instr, buffer);
587 // The debugger will return control in non-interactive mode.
588 FATAL("Cannot continue execution after unaligned access.");
589 }
590
591
88 // Returns the top of the stack area to enable checking for stack pointer 592 // Returns the top of the stack area to enable checking for stack pointer
89 // validity. 593 // validity.
90 uword Simulator::StackTop() const { 594 uword Simulator::StackTop() const {
91 // To be safe in potential stack underflows we leave some buffer above and 595 // To be safe in potential stack underflows we leave some buffer above and
92 // set the stack top. 596 // set the stack top.
93 return reinterpret_cast<uword>(stack_) + 597 return reinterpret_cast<uword>(stack_) +
94 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); 598 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
95 } 599 }
96 600
97 601
(...skipping 13 matching lines...) Expand all
111 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 615 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
112 return *ptr; 616 return *ptr;
113 } 617 }
114 618
115 619
116 int16_t Simulator::ReadH(uword addr, Instr* instr) { 620 int16_t Simulator::ReadH(uword addr, Instr* instr) {
117 if ((addr & 1) == 0) { 621 if ((addr & 1) == 0) {
118 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 622 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
119 return *ptr; 623 return *ptr;
120 } 624 }
121 // TODO(zra) unaligned access. Trap into debugger. 625 UnalignedAccess("signed halfword read", addr, instr);
122 UNIMPLEMENTED();
123 return 0; 626 return 0;
124 } 627 }
125 628
126 629
127 uint16_t Simulator::ReadHU(uword addr, Instr* instr) { 630 uint16_t Simulator::ReadHU(uword addr, Instr* instr) {
128 if ((addr & 1) == 0) { 631 if ((addr & 1) == 0) {
129 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 632 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
130 return *ptr; 633 return *ptr;
131 } 634 }
132 // TODO(zra) unaligned access. Trap into debugger. 635 UnalignedAccess("unsigned halfword read", addr, instr);
133 UNIMPLEMENTED();
134 return 0; 636 return 0;
135 } 637 }
136 638
137 639
138 int Simulator::ReadW(uword addr, Instr* instr) { 640 int Simulator::ReadW(uword addr, Instr* instr) {
139 if ((addr & 3) == 0) { 641 if ((addr & 3) == 0) {
140 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 642 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
141 return *ptr; 643 return *ptr;
142 } 644 }
143 // TODO(zra) unaligned access. Trap into debugger. 645 UnalignedAccess("read", addr, instr);
144 UNIMPLEMENTED();
145 return 0; 646 return 0;
146 } 647 }
147 648
148 649
149 void Simulator::WriteB(uword addr, uint8_t value) { 650 void Simulator::WriteB(uword addr, uint8_t value) {
150 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 651 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
151 *ptr = value; 652 *ptr = value;
152 } 653 }
153 654
154 655
155 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) { 656 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) {
156 if ((addr & 1) == 0) { 657 if ((addr & 1) == 0) {
157 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 658 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
158 *ptr = value; 659 *ptr = value;
159 return; 660 return;
160 } 661 }
161 // TODO(zra) unaligned access. Trap into debugger. 662 UnalignedAccess("halfword write", addr, instr);
162 UNIMPLEMENTED();
163 } 663 }
164 664
165 665
166 void Simulator::WriteW(uword addr, int value, Instr* instr) { 666 void Simulator::WriteW(uword addr, int value, Instr* instr) {
167 if ((addr & 3) == 0) { 667 if ((addr & 3) == 0) {
168 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 668 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
169 *ptr = value; 669 *ptr = value;
170 return; 670 return;
171 } 671 }
172 // TODO(zra) unaligned access. Trap into debugger. 672 UnalignedAccess("write", addr, instr);
173 UNIMPLEMENTED();
174 } 673 }
175 674
176 675
177 bool Simulator::OverflowFrom(int32_t alu_out, 676 bool Simulator::OverflowFrom(int32_t alu_out,
178 int32_t left, int32_t right, bool addition) { 677 int32_t left, int32_t right, bool addition) {
179 bool overflow; 678 bool overflow;
180 if (addition) { 679 if (addition) {
181 // Operands have the same sign. 680 // Operands have the same sign.
182 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) 681 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
183 // And operands and result have different sign. 682 // And operands and result have different sign.
(...skipping 20 matching lines...) Expand all
204 break; 703 break;
205 } 704 }
206 case AND: { 705 case AND: {
207 ASSERT(instr->SaField() == 0); 706 ASSERT(instr->SaField() == 0);
208 // Format(instr, "and 'rd, 'rs, 'rt"); 707 // Format(instr, "and 'rd, 'rs, 'rt");
209 int32_t rs_val = get_register(instr->RsField()); 708 int32_t rs_val = get_register(instr->RsField());
210 int32_t rt_val = get_register(instr->RtField()); 709 int32_t rt_val = get_register(instr->RtField());
211 set_register(instr->RdField(), rs_val & rt_val); 710 set_register(instr->RdField(), rs_val & rt_val);
212 break; 711 break;
213 } 712 }
713 case BREAK: {
714 SimulatorDebugger dbg(this);
715 dbg.Stop(instr, "breakpoint");
716 break;
717 }
214 case DIV: { 718 case DIV: {
215 ASSERT(instr->RdField() == 0); 719 ASSERT(instr->RdField() == 0);
216 ASSERT(instr->SaField() == 0); 720 ASSERT(instr->SaField() == 0);
217 // Format(instr, "div 'rs, 'rt"); 721 // Format(instr, "div 'rs, 'rt");
218 int32_t rs_val = get_register(instr->RsField()); 722 int32_t rs_val = get_register(instr->RsField());
219 int32_t rt_val = get_register(instr->RtField()); 723 int32_t rt_val = get_register(instr->RtField());
220 if (rt_val == 0) { 724 if (rt_val == 0) {
221 // Results are unpredictable. 725 // Results are unpredictable.
222 set_hi_register(0); 726 set_hi_register(0);
223 set_lo_register(0); 727 set_lo_register(0);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 ASSERT(instr->RdField() == R0); 792 ASSERT(instr->RdField() == R0);
289 ASSERT(!delay_slot_); 793 ASSERT(!delay_slot_);
290 // Format(instr, "jr'hint 'rs"); 794 // Format(instr, "jr'hint 'rs");
291 uword next_pc = get_register(instr->RsField()); 795 uword next_pc = get_register(instr->RsField());
292 ExecuteDelaySlot(); 796 ExecuteDelaySlot();
293 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment. 797 pc_ = next_pc - Instr::kInstrSize; // Account for regular PC increment.
294 break; 798 break;
295 } 799 }
296 default: { 800 default: {
297 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits()); 801 OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
298 UNREACHABLE(); 802 UNIMPLEMENTED();
299 break; 803 break;
300 } 804 }
301 } 805 }
302 } 806 }
303 807
304 808
305 void Simulator::DecodeSpecial2(Instr* instr) { 809 void Simulator::DecodeSpecial2(Instr* instr) {
306 ASSERT(instr->OpcodeField() == SPECIAL2); 810 ASSERT(instr->OpcodeField() == SPECIAL2);
307 switch (instr->FunctionField()) { 811 switch (instr->FunctionField()) {
308 case CLO: { 812 case CLO: {
(...skipping 21 matching lines...) Expand all
330 rs_val <<= 1; 834 rs_val <<= 1;
331 } 835 }
332 } else { 836 } else {
333 bitcount = 32; 837 bitcount = 32;
334 } 838 }
335 set_register(instr->RdField(), bitcount); 839 set_register(instr->RdField(), bitcount);
336 break; 840 break;
337 } 841 }
338 default: { 842 default: {
339 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits()); 843 OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits());
340 UNREACHABLE(); 844 UNIMPLEMENTED();
341 break;
342 }
343 }
344 }
345
346
347 void Simulator::DecodeSpecial3(Instr* instr) {
348 ASSERT(instr->OpcodeField() == SPECIAL3);
349 switch (instr->FunctionField()) {
350 default: {
351 OS::PrintErr("DecodeSpecial3: 0x%x\n", instr->InstructionBits());
352 UNREACHABLE();
353 break; 845 break;
354 } 846 }
355 } 847 }
356 } 848 }
357 849
358 850
359 void Simulator::InstructionDecode(Instr* instr) { 851 void Simulator::InstructionDecode(Instr* instr) {
360 switch (instr->OpcodeField()) { 852 switch (instr->OpcodeField()) {
361 case SPECIAL: { 853 case SPECIAL: {
362 DecodeSpecial(instr); 854 DecodeSpecial(instr);
363 break; 855 break;
364 } 856 }
365 case SPECIAL2: { 857 case SPECIAL2: {
366 DecodeSpecial2(instr); 858 DecodeSpecial2(instr);
367 break; 859 break;
368 } 860 }
369 case SPECIAL3: {
370 DecodeSpecial3(instr);
371 break;
372 }
373 case ADDIU: { 861 case ADDIU: {
374 // Format(instr, "addiu 'rt, 'rs, 'imms"); 862 // Format(instr, "addiu 'rt, 'rs, 'imms");
375 int32_t rs_val = get_register(instr->RsField()); 863 int32_t rs_val = get_register(instr->RsField());
376 int32_t imm_val = instr->SImmField(); 864 int32_t imm_val = instr->SImmField();
377 int32_t res = rs_val + imm_val; 865 int32_t res = rs_val + imm_val;
378 // Rt is set even on overflow. 866 // Rt is set even on overflow.
379 set_register(instr->RtField(), res); 867 set_register(instr->RtField(), res);
380 break; 868 break;
381 } 869 }
382 case ANDI: { 870 case ANDI: {
383 // Format(instr, "andi 'rt, 'rs, 'immu"); 871 // Format(instr, "andi 'rt, 'rs, 'immu");
384 int32_t rs_val = get_register(instr->RsField()); 872 int32_t rs_val = get_register(instr->RsField());
385 set_register(instr->RtField(), rs_val & instr->UImmField()); 873 set_register(instr->RtField(), rs_val & instr->UImmField());
386 break; 874 break;
387 } 875 }
388 case LB: { 876 case LB: {
389 // Format(instr, "lb 'rt, 'imms('rs)"); 877 // Format(instr, "lb 'rt, 'imms('rs)");
390 int32_t base_val = get_register(instr->RsField()); 878 int32_t base_val = get_register(instr->RsField());
391 int32_t imm_val = instr->SImmField(); 879 int32_t imm_val = instr->SImmField();
392 uword addr = base_val + imm_val; 880 uword addr = base_val + imm_val;
393 if (Simulator::IsIllegalAddress(addr)) { 881 if (Simulator::IsIllegalAddress(addr)) {
394 // TODO(zra) trap into debugger. 882 HandleIllegalAccess(addr, instr);
395 UNIMPLEMENTED();
396 } else { 883 } else {
397 int32_t res = ReadB(addr); 884 int32_t res = ReadB(addr);
398 set_register(instr->RtField(), res); 885 set_register(instr->RtField(), res);
399 } 886 }
400 break; 887 break;
401 } 888 }
402 case LBU: { 889 case LBU: {
403 // Format(instr, "lbu 'rt, 'imms('rs)"); 890 // Format(instr, "lbu 'rt, 'imms('rs)");
404 int32_t base_val = get_register(instr->RsField()); 891 int32_t base_val = get_register(instr->RsField());
405 int32_t imm_val = instr->SImmField(); 892 int32_t imm_val = instr->SImmField();
406 uword addr = base_val + imm_val; 893 uword addr = base_val + imm_val;
407 if (Simulator::IsIllegalAddress(addr)) { 894 if (Simulator::IsIllegalAddress(addr)) {
408 // TODO(zra) trap into debugger. 895 HandleIllegalAccess(addr, instr);
409 UNIMPLEMENTED();
410 } else { 896 } else {
411 int32_t res = ReadBU(addr); 897 int32_t res = ReadBU(addr);
412 set_register(instr->RtField(), res); 898 set_register(instr->RtField(), res);
413 } 899 }
414 break; 900 break;
415 } 901 }
416 case LH: { 902 case LH: {
417 // Format(instr, "lh 'rt, 'imms('rs)"); 903 // Format(instr, "lh 'rt, 'imms('rs)");
418 int32_t base_val = get_register(instr->RsField()); 904 int32_t base_val = get_register(instr->RsField());
419 int32_t imm_val = instr->SImmField(); 905 int32_t imm_val = instr->SImmField();
420 uword addr = base_val + imm_val; 906 uword addr = base_val + imm_val;
421 if (Simulator::IsIllegalAddress(addr)) { 907 if (Simulator::IsIllegalAddress(addr)) {
422 // TODO(zra) trap into debugger. 908 HandleIllegalAccess(addr, instr);
423 UNIMPLEMENTED();
424 } else { 909 } else {
425 int32_t res = ReadH(addr, instr); 910 int32_t res = ReadH(addr, instr);
426 set_register(instr->RtField(), res); 911 set_register(instr->RtField(), res);
427 } 912 }
428 break; 913 break;
429 } 914 }
430 case LHU: { 915 case LHU: {
431 // Format(instr, "lhu 'rt, 'imms('rs)"); 916 // Format(instr, "lhu 'rt, 'imms('rs)");
432 int32_t base_val = get_register(instr->RsField()); 917 int32_t base_val = get_register(instr->RsField());
433 int32_t imm_val = instr->SImmField(); 918 int32_t imm_val = instr->SImmField();
434 uword addr = base_val + imm_val; 919 uword addr = base_val + imm_val;
435 if (Simulator::IsIllegalAddress(addr)) { 920 if (Simulator::IsIllegalAddress(addr)) {
436 // TODO(zra) trap into debugger. 921 HandleIllegalAccess(addr, instr);
437 UNIMPLEMENTED();
438 } else { 922 } else {
439 int32_t res = ReadHU(addr, instr); 923 int32_t res = ReadHU(addr, instr);
440 set_register(instr->RtField(), res); 924 set_register(instr->RtField(), res);
441 } 925 }
442 break; 926 break;
443 } 927 }
444 case LUI: { 928 case LUI: {
445 ASSERT(instr->RsField() == 0); 929 ASSERT(instr->RsField() == 0);
446 set_register(instr->RtField(), instr->UImmField() << 16); 930 set_register(instr->RtField(), instr->UImmField() << 16);
447 break; 931 break;
448 } 932 }
449 case LW: { 933 case LW: {
450 // Format(instr, "lw 'rt, 'imms('rs)"); 934 // Format(instr, "lw 'rt, 'imms('rs)");
451 int32_t base_val = get_register(instr->RsField()); 935 int32_t base_val = get_register(instr->RsField());
452 int32_t imm_val = instr->SImmField(); 936 int32_t imm_val = instr->SImmField();
453 uword addr = base_val + imm_val; 937 uword addr = base_val + imm_val;
454 if (Simulator::IsIllegalAddress(addr)) { 938 if (Simulator::IsIllegalAddress(addr)) {
455 // TODO(zra) trap into debugger. 939 HandleIllegalAccess(addr, instr);
456 UNIMPLEMENTED();
457 } else { 940 } else {
458 int32_t res = ReadW(addr, instr); 941 int32_t res = ReadW(addr, instr);
459 set_register(instr->RtField(), res); 942 set_register(instr->RtField(), res);
460 } 943 }
461 break; 944 break;
462 } 945 }
463 case ORI: { 946 case ORI: {
464 // Format(instr, "ori 'rt, 'rs, 'immu"); 947 // Format(instr, "ori 'rt, 'rs, 'immu");
465 int32_t rs_val = get_register(instr->RsField()); 948 int32_t rs_val = get_register(instr->RsField());
466 set_register(instr->RtField(), rs_val | instr->UImmField()); 949 set_register(instr->RtField(), rs_val | instr->UImmField());
467 break; 950 break;
468 } 951 }
469 case SB: { 952 case SB: {
470 // Format(instr, "sb 'rt, 'imms('rs)"); 953 // Format(instr, "sb 'rt, 'imms('rs)");
471 int32_t rt_val = get_register(instr->RtField()); 954 int32_t rt_val = get_register(instr->RtField());
472 int32_t base_val = get_register(instr->RsField()); 955 int32_t base_val = get_register(instr->RsField());
473 int32_t imm_val = instr->SImmField(); 956 int32_t imm_val = instr->SImmField();
474 uword addr = base_val + imm_val; 957 uword addr = base_val + imm_val;
475 if (Simulator::IsIllegalAddress(addr)) { 958 if (Simulator::IsIllegalAddress(addr)) {
476 // TODO(zra) trap into debugger. 959 HandleIllegalAccess(addr, instr);
477 UNIMPLEMENTED();
478 } else { 960 } else {
479 WriteB(addr, rt_val & 0xff); 961 WriteB(addr, rt_val & 0xff);
480 } 962 }
481 break; 963 break;
482 } 964 }
483 case SH: { 965 case SH: {
484 // Format(instr, "sh 'rt, 'imms('rs)"); 966 // Format(instr, "sh 'rt, 'imms('rs)");
485 int32_t rt_val = get_register(instr->RtField()); 967 int32_t rt_val = get_register(instr->RtField());
486 int32_t base_val = get_register(instr->RsField()); 968 int32_t base_val = get_register(instr->RsField());
487 int32_t imm_val = instr->SImmField(); 969 int32_t imm_val = instr->SImmField();
488 uword addr = base_val + imm_val; 970 uword addr = base_val + imm_val;
489 if (Simulator::IsIllegalAddress(addr)) { 971 if (Simulator::IsIllegalAddress(addr)) {
490 // TODO(zra) trap into debugger. 972 HandleIllegalAccess(addr, instr);
491 UNIMPLEMENTED();
492 } else { 973 } else {
493 WriteH(addr, rt_val & 0xffff, instr); 974 WriteH(addr, rt_val & 0xffff, instr);
494 } 975 }
495 break; 976 break;
496 } 977 }
497 case SW: { 978 case SW: {
498 // Format(instr, "sw 'rt, 'imms('rs)"); 979 // Format(instr, "sw 'rt, 'imms('rs)");
499 int32_t rt_val = get_register(instr->RtField()); 980 int32_t rt_val = get_register(instr->RtField());
500 int32_t base_val = get_register(instr->RsField()); 981 int32_t base_val = get_register(instr->RsField());
501 int32_t imm_val = instr->SImmField(); 982 int32_t imm_val = instr->SImmField();
502 uword addr = base_val + imm_val; 983 uword addr = base_val + imm_val;
503 if (Simulator::IsIllegalAddress(addr)) { 984 if (Simulator::IsIllegalAddress(addr)) {
504 // TODO(zra) trap into debugger. 985 HandleIllegalAccess(addr, instr);
505 UNIMPLEMENTED();
506 } else { 986 } else {
507 WriteW(addr, rt_val, instr); 987 WriteW(addr, rt_val, instr);
508 } 988 }
509 break; 989 break;
510 } 990 }
511 default: { 991 default: {
512 OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits()); 992 OS::PrintErr("Undecoded instruction: 0x%x at %p\n",
513 UNREACHABLE(); 993 instr->InstructionBits(), instr);
994 UNIMPLEMENTED();
514 break; 995 break;
515 } 996 }
516 } 997 }
517 pc_ += Instr::kInstrSize; 998 pc_ += Instr::kInstrSize;
518 } 999 }
519 1000
520 1001
521 void Simulator::ExecuteDelaySlot() { 1002 void Simulator::ExecuteDelaySlot() {
522 ASSERT(pc_ != kEndSimulatingPC); 1003 ASSERT(pc_ != kEndSimulatingPC);
523 delay_slot_ = true; 1004 delay_slot_ = true;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 // Restore the SP register and return R1:R0. 1116 // Restore the SP register and return R1:R0.
636 set_register(SP, sp_before_call); 1117 set_register(SP, sp_before_call);
637 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); 1118 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1));
638 } 1119 }
639 1120
640 } // namespace dart 1121 } // namespace dart
641 1122
642 #endif // !defined(HOST_ARCH_MIPS) 1123 #endif // !defined(HOST_ARCH_MIPS)
643 1124
644 #endif // defined TARGET_ARCH_MIPS 1125 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« runtime/vm/disassembler_arm.cc ('K') | « runtime/vm/simulator_mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698