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

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

Issue 12041056: Initial revision of ARM simulator and (empty) MIPS simulator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 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
« no previous file with comments | « runtime/vm/simulator_arm.h ('k') | runtime/vm/simulator_mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include <math.h> // for isnan.
6 #include <setjmp.h>
7 #include <stdlib.h>
8 #include <pthread.h>
9
10 #include "vm/globals.h"
11 #if defined(TARGET_ARCH_ARM)
12
13 // Only build the simulator if not compiling for real ARM hardware.
14 #if !defined(HOST_ARCH_ARM)
15
16 #include "vm/simulator.h"
17
18 #include "vm/assembler.h"
19 #include "vm/constants_arm.h"
20 #include "vm/disassembler.h"
21 #include "vm/native_arguments.h"
22 #include "vm/thread.h"
23
24 namespace dart {
25
26 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution.");
27 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at.");
28
29
30 // This macro provides a platform independent use of sscanf. The reason for
31 // SScanF not being implemented in a platform independent way through
32 // OS in the same way as SNPrint is that the Windows C Run-Time
33 // Library does not provide vsscanf.
34 #define SScanF sscanf // NOLINT
35
36
37 // Unimplemented counter class for debugging and measurement purposes.
38 class StatsCounter {
39 public:
40 explicit StatsCounter(const char* name) {
41 UNIMPLEMENTED();
42 }
43
44 void Increment() {
45 UNIMPLEMENTED();
46 }
47 };
48
49
50 // SimulatorSetjmpBuffer are linked together, and the last created one
51 // is referenced by the Simulator. When an exception is thrown, the exception
52 // runtime looks at where to jump and finds the corresponding
53 // SimulatorSetjmpBuffer based on the stack pointer of the exception handler.
54 // The runtime then does a Longjmp on that buffer to return to the simulator.
55 class SimulatorSetjmpBuffer {
56 public:
57 int Setjmp() { return setjmp(buffer_); }
58 void Longjmp() {
59 // "This" is now the last setjmp buffer.
60 simulator_->set_last_setjmp_buffer(this);
61 longjmp(buffer_, 1);
62 }
63
64 explicit SimulatorSetjmpBuffer(Simulator* sim) {
65 simulator_ = sim;
66 link_ = sim->last_setjmp_buffer();
67 sim->set_last_setjmp_buffer(this);
68 sp_ = sim->get_register(SP);
69 }
70
71 ~SimulatorSetjmpBuffer() {
72 ASSERT(simulator_->last_setjmp_buffer() == this);
73 simulator_->set_last_setjmp_buffer(link_);
74 }
75
76 SimulatorSetjmpBuffer* link() { return link_; }
77
78 int32_t sp() { return sp_; }
79
80 private:
81 int32_t sp_;
82 Simulator* simulator_;
83 SimulatorSetjmpBuffer* link_;
84 jmp_buf buffer_;
85
86 friend class Simulator;
87 };
88
89
90 // The SimulatorDebugger class is used by the simulator while debugging
91 // simulated ARM code.
92 class SimulatorDebugger {
93 public:
94 explicit SimulatorDebugger(Simulator* sim);
95 ~SimulatorDebugger();
96
97 void Stop(Instr* instr, const char* message);
98 void Debug();
99 char* ReadLine(const char* prompt);
100
101 private:
102 static const int32_t kSimulatorBreakpointInstr = // svc #kBreakpointSvcCode
103 ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode);
104 static const int32_t kNopInstr = // nop
105 ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12));
106
107 Simulator* sim_;
108
109 bool GetValue(char* desc, uint32_t* value);
110 bool GetFValue(char* desc, float* value);
111 bool GetDValue(char* desc, double* value);
112
113 // Set or delete a breakpoint. Returns true if successful.
114 bool SetBreakpoint(Instr* breakpc);
115 bool DeleteBreakpoint(Instr* breakpc);
116
117 // Undo and redo all breakpoints. This is needed to bracket disassembly and
118 // execution to skip past breakpoints when run from the debugger.
119 void UndoBreakpoints();
120 void RedoBreakpoints();
121 };
122
123
124 SimulatorDebugger::SimulatorDebugger(Simulator* sim) {
125 sim_ = sim;
126 }
127
128
129 SimulatorDebugger::~SimulatorDebugger() {
130 }
131
132
133 void SimulatorDebugger::Stop(Instr* instr, const char* message) {
134 OS::Print("Simulator hit %s\n", message);
135 Debug();
136 }
137
138
139 static Register LookupCoreRegisterByName(const char* name) {
140 static const char* kNames[] = {
141 "r0", "r1", "r2", "r3",
142 "r4", "r5", "r6", "r7",
143 "r8", "r9", "r10", "r11",
144 "r12", "r13", "r14", "r15",
145 "pc", "lr", "sp", "ip",
146 "fp", "sl"
147 };
148 static const Register kRegisters[] = {
149 R0, R1, R2, R3,
150 R4, R5, R6, R7,
151 R8, R9, R10, R11,
152 R12, R13, R14, R15,
153 PC, LR, SP, IP,
154 FP, R10
155 };
156 ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
157 for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
158 if (strcmp(kNames[i], name) == 0) {
159 return kRegisters[i];
160 }
161 }
162 return kNoRegister;
163 }
164
165
166 static SRegister LookupSRegisterByName(const char* name) {
167 int reg_nr = -1;
168 bool ok = SScanF(name, "s%d", &reg_nr);
169 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfSRegisters)) {
170 return static_cast<SRegister>(reg_nr);
171 }
172 return kNoSRegister;
173 }
174
175
176 static DRegister LookupDRegisterByName(const char* name) {
177 int reg_nr = -1;
178 bool ok = SScanF(name, "d%d", &reg_nr);
179 if (ok && (0 <= reg_nr) && (reg_nr < kNumberOfDRegisters)) {
180 return static_cast<DRegister>(reg_nr);
181 }
182 return kNoDRegister;
183 }
184
185
186 bool SimulatorDebugger::GetValue(char* desc, uint32_t* value) {
187 Register reg = LookupCoreRegisterByName(desc);
188 if (reg != kNoRegister) {
189 if (reg == PC) {
190 *value = sim_->get_pc();
191 } else {
192 *value = sim_->get_register(reg);
193 }
194 return true;
195 }
196 if ((desc[0] == '*')) {
197 uint32_t addr;
198 if (GetValue(desc + 1, &addr)) {
199 *value = *(reinterpret_cast<uint32_t*>(addr));
200 return true;
201 }
202 }
203 bool retval = SScanF(desc, "0x%x", value) == 1;
204 if (!retval) {
205 retval = SScanF(desc, "%x", value) == 1;
206 }
207 return retval;
208 }
209
210
211 bool SimulatorDebugger::GetFValue(char* desc, float* value) {
212 SRegister sreg = LookupSRegisterByName(desc);
213 if (sreg != kNoSRegister) {
214 *value = sim_->get_sregister(sreg);
215 return true;
216 }
217 if ((desc[0] == '*')) {
218 uint32_t addr;
219 if (GetValue(desc + 1, &addr)) {
220 *value = *(reinterpret_cast<float*>(addr));
221 return true;
222 }
223 }
224 return false;
225 }
226
227
228 bool SimulatorDebugger::GetDValue(char* desc, double* value) {
229 DRegister dreg = LookupDRegisterByName(desc);
230 if (dreg != kNoDRegister) {
231 *value = sim_->get_dregister(dreg);
232 return true;
233 }
234 if ((desc[0] == '*')) {
235 uint32_t addr;
236 if (GetValue(desc + 1, &addr)) {
237 *value = *(reinterpret_cast<double*>(addr));
238 return true;
239 }
240 }
241 return false;
242 }
243
244
245 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) {
246 // Check if a breakpoint can be set. If not return without any side-effects.
247 if (sim_->break_pc_ != NULL) {
248 return false;
249 }
250
251 // Set the breakpoint.
252 sim_->break_pc_ = breakpc;
253 sim_->break_instr_ = breakpc->InstructionBits();
254 // Not setting the breakpoint instruction in the code itself. It will be set
255 // when the debugger shell continues.
256 return true;
257 }
258
259
260 bool SimulatorDebugger::DeleteBreakpoint(Instr* breakpc) {
261 if (sim_->break_pc_ != NULL) {
262 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
263 }
264
265 sim_->break_pc_ = NULL;
266 sim_->break_instr_ = 0;
267 return true;
268 }
269
270
271 void SimulatorDebugger::UndoBreakpoints() {
272 if (sim_->break_pc_ != NULL) {
273 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
274 }
275 }
276
277
278 void SimulatorDebugger::RedoBreakpoints() {
279 if (sim_->break_pc_ != NULL) {
280 sim_->break_pc_->SetInstructionBits(kSimulatorBreakpointInstr);
281 }
282 }
283
284
285 void SimulatorDebugger::Debug() {
286 intptr_t last_pc = -1;
287 bool done = false;
288
289 #define COMMAND_SIZE 63
290 #define ARG_SIZE 255
291
292 #define STR(a) #a
293 #define XSTR(a) STR(a)
294
295 char cmd[COMMAND_SIZE + 1];
296 char arg1[ARG_SIZE + 1];
297 char arg2[ARG_SIZE + 1];
298
299 // make sure to have a proper terminating character if reaching the limit
300 cmd[COMMAND_SIZE] = 0;
301 arg1[ARG_SIZE] = 0;
302 arg2[ARG_SIZE] = 0;
303
304 // Undo all set breakpoints while running in the debugger shell. This will
305 // make them invisible to all commands.
306 UndoBreakpoints();
307
308 while (!done) {
309 if (last_pc != sim_->get_pc()) {
310 last_pc = sim_->get_pc();
311 Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
312 }
313 char* line = ReadLine("sim> ");
314 if (line == NULL) {
315 break;
316 } else {
317 // Use sscanf to parse the individual parts of the command line. At the
318 // moment no command expects more than two parameters.
319 int args = SScanF(line,
320 "%" XSTR(COMMAND_SIZE) "s "
321 "%" XSTR(ARG_SIZE) "s "
322 "%" XSTR(ARG_SIZE) "s",
323 cmd, arg1, arg2);
324 if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
325 OS::Print("c/cont -- continue execution\n"
326 "disasm -- disassemble instrs at current pc location\n"
327 " other variants are:\n"
328 " disasm <address>\n"
329 " disasm <address> <number_of_instructions>\n"
330 " by default 10 instrs are disassembled\n"
331 "del -- delete breakpoints\n"
332 "flags -- print flag values\n"
333 "gdb -- transfer control to gdb\n"
334 "h/help -- print this help string\n"
335 "break <address> -- set break point at specified address\n"
336 "p/print <reg or value or *addr> -- print integer value\n"
337 "pf/printfloat <sreg or *addr> -- print float value\n"
338 "pd/printdouble <dreg or *addr> -- print double value\n"
339 "po/printobject <*reg or *addr> -- print object\n"
340 "si/stepi -- single step an instruction\n"
341 "unstop -- if current pc is a stop instr make it a nop\n");
342 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
343 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
344 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
345 // Execute the one instruction we broke at with breakpoints disabled.
346 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
347 // Leave the debugger shell.
348 done = true;
349 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
350 if (args == 2) {
351 uint32_t value;
352 if (GetValue(arg1, &value)) {
353 OS::Print("%s: %u 0x%x\n", arg1, value, value);
354 } else {
355 OS::Print("%s unrecognized\n", arg1);
356 }
357 } else {
358 OS::Print("print <reg or value or *addr>\n");
359 }
360 } else if ((strcmp(cmd, "pf") == 0) || (strcmp(cmd, "printfloat") == 0)) {
361 if (args == 2) {
362 float fvalue;
363 if (GetFValue(arg1, &fvalue)) {
364 uint32_t value = bit_cast<uint32_t, float>(fvalue);
365 OS::Print("%s: 0%u 0x%x %.8g\n", arg1, value, value, fvalue);
366 } else {
367 OS::Print("%s unrecognized\n", arg1);
368 }
369 } else {
370 OS::Print("printfloat <sreg or *addr>\n");
371 }
372 } else if ((strcmp(cmd, "pd") == 0) ||
373 (strcmp(cmd, "printdouble") == 0)) {
374 if (args == 2) {
375 double dvalue;
376 if (GetDValue(arg1, &dvalue)) {
377 uint64_t long_value = bit_cast<uint64_t, double>(dvalue);
378 OS::Print("%s: %llu 0x%llx %.8g\n",
379 arg1, long_value, long_value, dvalue);
380 } else {
381 OS::Print("%s unrecognized\n", arg1);
382 }
383 } else {
384 OS::Print("printdouble <dreg or *addr>\n");
385 }
386 } else if ((strcmp(cmd, "po") == 0) ||
387 (strcmp(cmd, "printobject") == 0)) {
388 if (args == 2) {
389 uint32_t value;
390 // Make the dereferencing '*' optional.
391 if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) ||
392 GetValue(arg1, &value)) {
393 if (Isolate::Current()->heap()->Contains(value)) {
394 OS::Print("%s: \n", arg1);
395 #if defined(DEBUG)
396 const Object& obj = Object::Handle(
397 reinterpret_cast<RawObject*>(value));
398 obj.Print();
399 #endif // defined(DEBUG)
400 } else {
401 OS::Print("0x%x is not an object reference\n", value);
402 }
403 } else {
404 OS::Print("%s unrecognized\n", arg1);
405 }
406 } else {
407 OS::Print("printobject <*reg or *addr>\n");
408 }
409 } else if (strcmp(cmd, "disasm") == 0) {
410 uint32_t start = 0;
411 uint32_t end = 0;
412 if (args == 1) {
413 start = sim_->get_pc();
414 end = start + (10 * Instr::kInstrSize);
415 } else if (args == 2) {
416 if (GetValue(arg1, &start)) {
417 // no length parameter passed, assume 10 instructions
418 end = start + (10 * Instr::kInstrSize);
419 }
420 } else {
421 uint32_t length;
422 if (GetValue(arg1, &start) && GetValue(arg2, &length)) {
423 end = start + (length * Instr::kInstrSize);
424 }
425 }
426
427 Disassembler::Disassemble(start, end);
428 } else if (strcmp(cmd, "gdb") == 0) {
429 OS::Print("relinquishing control to gdb\n");
430 OS::DebugBreak();
431 OS::Print("regaining control from gdb\n");
432 } else if (strcmp(cmd, "break") == 0) {
433 if (args == 2) {
434 uint32_t addr;
435 if (GetValue(arg1, &addr)) {
436 if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) {
437 OS::Print("setting breakpoint failed\n");
438 }
439 } else {
440 OS::Print("%s unrecognized\n", arg1);
441 }
442 } else {
443 OS::Print("break <addr>\n");
444 }
445 } else if (strcmp(cmd, "del") == 0) {
446 if (!DeleteBreakpoint(NULL)) {
447 OS::Print("deleting breakpoint failed\n");
448 }
449 } else if (strcmp(cmd, "flags") == 0) {
450 OS::Print("APSR: ");
451 OS::Print("N flag: %d; ", sim_->n_flag_);
452 OS::Print("Z flag: %d; ", sim_->z_flag_);
453 OS::Print("C flag: %d; ", sim_->c_flag_);
454 OS::Print("V flag: %d\n", sim_->v_flag_);
455 OS::Print("FPSCR: ");
456 OS::Print("N flag: %d; ", sim_->fp_n_flag_);
457 OS::Print("Z flag: %d; ", sim_->fp_z_flag_);
458 OS::Print("C flag: %d; ", sim_->fp_c_flag_);
459 OS::Print("V flag: %d\n", sim_->fp_v_flag_);
460 } else if (strcmp(cmd, "unstop") == 0) {
461 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
462 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
463 if (stop_instr->IsSvc() || stop_instr->IsBkpt()) {
464 stop_instr->SetInstructionBits(kNopInstr);
465 } else {
466 OS::Print("Not at debugger stop.\n");
467 }
468 } else {
469 OS::Print("Unknown command: %s\n", cmd);
470 }
471 }
472 delete[] line;
473 }
474
475 // Add all the breakpoints back to stop execution and enter the debugger
476 // shell when hit.
477 RedoBreakpoints();
478
479 #undef COMMAND_SIZE
480 #undef ARG_SIZE
481
482 #undef STR
483 #undef XSTR
484 }
485
486 char* SimulatorDebugger::ReadLine(const char* prompt) {
487 char* result = NULL;
488 char line_buf[256];
489 int offset = 0;
490 bool keep_going = true;
491 fprintf(stdout, "%s", prompt);
492 fflush(stdout);
493 while (keep_going) {
494 if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
495 // fgets got an error. Just give up.
496 if (result != NULL) {
497 delete[] result;
498 }
499 return NULL;
500 }
501 int len = strlen(line_buf);
502 if (len > 1 &&
503 line_buf[len - 2] == '\\' &&
504 line_buf[len - 1] == '\n') {
505 // When we read a line that ends with a "\" we remove the escape and
506 // append the remainder.
507 line_buf[len - 2] = '\n';
508 line_buf[len - 1] = 0;
509 len -= 1;
510 } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
511 // Since we read a new line we are done reading the line. This
512 // will exit the loop after copying this buffer into the result.
513 keep_going = false;
514 }
515 if (result == NULL) {
516 // Allocate the initial result and make room for the terminating '\0'
517 result = new char[len + 1];
518 if (result == NULL) {
519 // OOM, so cannot readline anymore.
520 return NULL;
521 }
522 } else {
523 // Allocate a new result with enough room for the new addition.
524 int new_len = offset + len + 1;
525 char* new_result = new char[new_len];
526 if (new_result == NULL) {
527 // OOM, free the buffer allocated so far and return NULL.
528 delete[] result;
529 return NULL;
530 } else {
531 // Copy the existing input into the new array and set the new
532 // array as the result.
533 memmove(new_result, result, offset);
534 delete[] result;
535 result = new_result;
536 }
537 }
538 // Copy the newly read line into the result.
539 memmove(result + offset, line_buf, len);
540 offset += len;
541 }
542 ASSERT(result != NULL);
543 result[offset] = '\0';
544 return result;
545 }
546
547
548 // Synchronization primitives support.
549 Mutex* Simulator::exclusive_access_lock_ = NULL;
550 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags];
551 int Simulator::next_address_tag_;
552
553
554 void Simulator::SetExclusiveAccess(uword addr) {
555 Isolate* isolate = Isolate::Current();
556 ASSERT(isolate != NULL);
557 int i = 0;
558 while ((i < kNumAddressTags) &&
559 (exclusive_access_state_[i].isolate != isolate)) {
560 i++;
561 }
562 if (i == kNumAddressTags) {
563 i = next_address_tag_;
564 if (++next_address_tag_ == kNumAddressTags) next_address_tag_ = 0;
565 exclusive_access_state_[i].isolate = isolate;
566 }
567 exclusive_access_state_[i].addr = addr;
568 }
569
570
571 bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
572 Isolate* isolate = Isolate::Current();
573 ASSERT(isolate != NULL);
574 bool result = false;
575 for (int i = 0; i < kNumAddressTags; i++) {
576 if (exclusive_access_state_[i].isolate == isolate) {
577 if (exclusive_access_state_[i].addr == addr) {
578 result = true;
579 }
580 exclusive_access_state_[i].addr = NULL;
581 continue;
582 }
583 if (exclusive_access_state_[i].addr == addr) {
584 exclusive_access_state_[i].addr = NULL;
585 }
586 }
587 return result;
588 }
589
590
591 void Simulator::InitOnce() {
592 // Setup exclusive access state.
593 exclusive_access_lock_ = new Mutex();
594 for (int i = 0; i < kNumAddressTags; i++) {
595 exclusive_access_state_[i].isolate = NULL;
596 exclusive_access_state_[i].addr = NULL;
597 }
598 next_address_tag_ = 0;
599 }
600
601
602 Simulator::Simulator() {
603 // Setup simulator support first. Some of this information is needed to
604 // setup the architecture state.
605 // We allocate the stack here, the size is computed as the sum of
606 // the size specified by the user and the buffer space needed for
607 // handling stack overflow exceptions. To be safe in potential
608 // stack underflows we also add some underflow buffer space.
609 stack_ = new char[(Isolate::GetSpecifiedStackSize() +
610 Isolate::kStackSizeBuffer +
611 kSimulatorStackUnderflowSize)];
612 pc_modified_ = false;
613 icount_ = 0;
614 break_pc_ = NULL;
615 break_instr_ = 0;
616 last_setjmp_buffer_ = NULL;
617
618 // Setup architecture state.
619 // All registers are initialized to zero to start with.
620 for (int i = 0; i < kNumberOfCpuRegisters; i++) {
621 registers_[i] = 0;
622 }
623 n_flag_ = false;
624 z_flag_ = false;
625 c_flag_ = false;
626 v_flag_ = false;
627
628 // The sp is initialized to point to the bottom (high address) of the
629 // allocated stack area.
630 registers_[SP] = StackTop();
631 // The lr and pc are initialized to a known bad value that will cause an
632 // access violation if the simulator ever tries to execute it.
633 registers_[PC] = kBadLR;
634 registers_[LR] = kBadLR;
635
636 // All double-precision registers are initialized to zero.
637 for (int i = 0; i < kNumberOfDRegisters; i++) {
638 dregisters_[i] = 0.0;
639 }
640 // Since VFP registers are overlapping, single-precision registers should
641 // already be initialized.
642 ASSERT(2*kNumberOfDRegisters >= kNumberOfSRegisters);
643 for (int i = 0; i < kNumberOfSRegisters; i++) {
644 ASSERT(sregisters_[i] == 0.0);
645 }
646 fp_n_flag_ = false;
647 fp_z_flag_ = false;
648 fp_c_flag_ = false;
649 fp_v_flag_ = false;
650 }
651
652
653 Simulator::~Simulator() {
654 delete[] stack_;
655 Isolate::Current()->set_simulator(NULL);
656 }
657
658
659 // When the generated code calls an external reference we need to catch that in
660 // the simulator. The external reference will be a function compiled for the
661 // host architecture. We need to call that function instead of trying to
662 // execute it with the simulator. We do that by redirecting the external
663 // reference to a svc (supervisor call) instruction that is handled by
664 // the simulator. We write the original destination of the jump just at a known
665 // offset from the svc instruction so the simulator knows what to call.
666 class Redirection {
667 public:
668 uword address_of_svc_instruction() {
669 return reinterpret_cast<uword>(&svc_instruction_);
670 }
671
672 void* external_function() const { return external_function_; }
673
674 uint32_t argument_count() const { return argument_count_; }
675
676 static Redirection* Get(void* external_function, uint32_t argument_count) {
677 Redirection* current;
678 for (current = list_; current != NULL; current = current->next_) {
679 if (current->external_function_ == external_function) return current;
680 }
681 return new Redirection(external_function, argument_count);
682 }
683
684 static Redirection* FromSvcInstruction(Instr* svc_instruction) {
685 char* addr_of_svc = reinterpret_cast<char*>(svc_instruction);
686 char* addr_of_redirection =
687 addr_of_svc - OFFSET_OF(Redirection, svc_instruction_);
688 return reinterpret_cast<Redirection*>(addr_of_redirection);
689 }
690
691 private:
692 static const int32_t kRedirectSvcInstruction =
693 ((AL << kConditionShift) | (0xf << 24) | kRedirectionSvcCode);
694 Redirection(void* external_function, uint32_t argument_count)
695 : external_function_(external_function),
696 argument_count_(argument_count),
697 svc_instruction_(kRedirectSvcInstruction),
698 next_(list_) {
699 list_ = this;
700 }
701
702 void* external_function_;
703 const uint32_t argument_count_;
704 uint32_t svc_instruction_;
705 Redirection* next_;
706 static Redirection* list_;
707 };
708
709
710 Redirection* Redirection::list_ = NULL;
711
712
713 uword Simulator::RedirectExternalReference(void* function,
714 uint32_t argument_count) {
715 Redirection* redirection = Redirection::Get(function, argument_count);
716 return redirection->address_of_svc_instruction();
717 }
718
719
720 // Get the active Simulator for the current isolate.
721 Simulator* Simulator::Current() {
722 Simulator* simulator = Isolate::Current()->simulator();
723 if (simulator == NULL) {
724 simulator = new Simulator();
725 Isolate::Current()->set_simulator(simulator);
726 }
727 return simulator;
728 }
729
730
731 // Sets the register in the architecture state. It will also deal with updating
732 // Simulator internal state for special registers such as PC.
733 void Simulator::set_register(Register reg, int32_t value) {
734 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
735 if (reg == PC) {
736 pc_modified_ = true;
737 }
738 registers_[reg] = value;
739 }
740
741
742 // Get the register from the architecture state. This function does handle
743 // the special case of accessing the PC register.
744 int32_t Simulator::get_register(Register reg) const {
745 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
746 return registers_[reg] + ((reg == PC) ? Instr::kPCReadOffset : 0);
747 }
748
749
750 // Raw access to the PC register.
751 void Simulator::set_pc(int32_t value) {
752 pc_modified_ = true;
753 registers_[PC] = value;
754 }
755
756
757 // Raw access to the PC register without the special adjustment when reading.
758 int32_t Simulator::get_pc() const {
759 return registers_[PC];
760 }
761
762
763 // Accessors for VFP register state.
764 void Simulator::set_sregister(SRegister reg, float value) {
765 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
766 sregisters_[reg] = value;
767 }
768
769
770 float Simulator::get_sregister(SRegister reg) const {
771 ASSERT((reg >= 0) && (reg < kNumberOfSRegisters));
772 return sregisters_[reg];
773 }
774
775
776 void Simulator::set_dregister(DRegister reg, double value) {
777 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
778 dregisters_[reg] = value;
779 }
780
781
782 double Simulator::get_dregister(DRegister reg) const {
783 ASSERT((reg >= 0) && (reg < kNumberOfDRegisters));
784 return dregisters_[reg];
785 }
786
787
788 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) {
789 uword fault_pc = get_pc();
790 // The debugger will not be able to single step past this instruction, but
791 // it will be possible to disassemble the code and inspect registers.
792 char buffer[128];
793 snprintf(buffer, sizeof(buffer),
794 "illegal memory access at 0x%x, pc=0x%x\n",
795 addr, fault_pc);
796 SimulatorDebugger dbg(this);
797 dbg.Stop(instr, buffer);
798 // The debugger will return control in non-interactive mode.
799 FATAL("Cannot continue execution after illegal memory access.");
800 }
801
802
803 // Processor versions prior to ARMv7 could not do unaligned reads and writes.
804 // On some ARM platforms an interrupt is caused. On others it does a funky
805 // rotation thing. However, from version v7, unaligned access is supported.
806 // Note that simulator runs have the runtime system running directly on the host
807 // system and only generated code is executed in the simulator. Since the host
808 // is typically IA32 we will get the correct ARMv7-like behaviour on unaligned
809 // accesses, but we should actually not generate code accessing unaligned data,
810 // so we still want to know and abort if we encounter such code.
811 void Simulator::UnalignedAccess(const char* msg, uword addr, Instr* instr) {
812 // The debugger will not be able to single step past this instruction, but
813 // it will be possible to disassemble the code and inspect registers.
814 char buffer[64];
815 snprintf(buffer, sizeof(buffer),
816 "unaligned %s at 0x%x, pc=%p\n", msg, addr, instr);
817 SimulatorDebugger dbg(this);
818 dbg.Stop(instr, buffer);
819 // The debugger will return control in non-interactive mode.
820 FATAL("Cannot continue execution after unaligned access.");
821 }
822
823
824 int Simulator::ReadW(uword addr, Instr* instr) {
825 static StatsCounter counter_read_w("Simulated word reads");
826 counter_read_w.Increment();
827 if ((addr & 3) == 0) {
828 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
829 return *ptr;
830 }
831 UnalignedAccess("read", addr, instr);
832 return 0;
833 }
834
835
836 void Simulator::WriteW(uword addr, int value, Instr* instr) {
837 static StatsCounter counter_write_w("Simulated word writes");
838 counter_write_w.Increment();
839 if ((addr & 3) == 0) {
840 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
841 *ptr = value;
842 return;
843 }
844 UnalignedAccess("write", addr, instr);
845 }
846
847
848 uint16_t Simulator::ReadHU(uword addr, Instr* instr) {
849 static StatsCounter counter_read_hu("Simulated unsigned halfword reads");
850 counter_read_hu.Increment();
851 if ((addr & 1) == 0) {
852 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
853 return *ptr;
854 }
855 UnalignedAccess("unsigned halfword read", addr, instr);
856 return 0;
857 }
858
859
860 int16_t Simulator::ReadH(uword addr, Instr* instr) {
861 static StatsCounter counter_read_h("Simulated signed halfword reads");
862 counter_read_h.Increment();
863 if ((addr & 1) == 0) {
864 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
865 return *ptr;
866 }
867 UnalignedAccess("signed halfword read", addr, instr);
868 return 0;
869 }
870
871
872 void Simulator::WriteH(uword addr, uint16_t value, Instr* instr) {
873 static StatsCounter counter_write_h("Simulated halfword writes");
874 counter_write_h.Increment();
875 if ((addr & 1) == 0) {
876 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
877 *ptr = value;
878 return;
879 }
880 UnalignedAccess("halfword write", addr, instr);
881 }
882
883
884 uint8_t Simulator::ReadBU(uword addr) {
885 static StatsCounter counter_read_bu("Simulated unsigned byte reads");
886 counter_read_bu.Increment();
887 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
888 return *ptr;
889 }
890
891
892 int8_t Simulator::ReadB(uword addr) {
893 static StatsCounter counter_read_b("Simulated signed byte reads");
894 counter_read_b.Increment();
895 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
896 return *ptr;
897 }
898
899
900 void Simulator::WriteB(uword addr, uint8_t value) {
901 static StatsCounter counter_write_b("Simulated byte writes");
902 counter_write_b.Increment();
903 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
904 *ptr = value;
905 }
906
907
908 // Synchronization primitives support.
909 void Simulator::ClearExclusive() {
910 // This lock is initialized in Simulator::InitOnce().
911 MutexLocker ml(exclusive_access_lock_);
912 // Set exclusive access to open state for this isolate.
913 HasExclusiveAccessAndOpen(NULL);
914 }
915
916
917 int Simulator::ReadExclusiveW(uword addr, Instr* instr) {
918 // This lock is initialized in Simulator::InitOnce().
919 MutexLocker ml(exclusive_access_lock_);
920 SetExclusiveAccess(addr);
921 return ReadW(addr, instr);
922 }
923
924
925 int Simulator::WriteExclusiveW(uword addr, int value, Instr* instr) {
926 // This lock is initialized in Simulator::InitOnce().
927 MutexLocker ml(exclusive_access_lock_);
928 bool write_allowed = HasExclusiveAccessAndOpen(addr);
929 if (write_allowed) {
930 WriteW(addr, value, instr);
931 return 0; // Success.
932 }
933 return 1; // Failure.
934 }
935
936
937 uword Simulator::CompareExchange(uword* address,
938 uword compare_value,
939 uword new_value) {
940 // This lock is initialized in Simulator::InitOnce().
941 MutexLocker ml(exclusive_access_lock_);
942 uword value = *address;
943 if (value == compare_value) {
944 *address = new_value;
945 // Same effect on exclusive access state as a successful STREX.
946 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address));
947 } else {
948 // Same effect on exclusive access state as an LDREX.
949 SetExclusiveAccess(reinterpret_cast<uword>(address));
950 }
951 return value;
952 }
953
954
955 // Returns the top of the stack area to enable checking for stack pointer
956 // validity.
957 uintptr_t Simulator::StackTop() const {
958 // To be safe in potential stack underflows we leave some buffer above and
959 // set the stack top.
960 return reinterpret_cast<uintptr_t>(stack_) +
961 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
962 }
963
964
965 // Unsupported instructions use Format to print an error and stop execution.
966 void Simulator::Format(Instr* instr, const char* format) {
967 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n",
968 instr,
969 format);
970 UNIMPLEMENTED();
971 }
972
973
974 // Checks if the current instruction should be executed based on its
975 // condition bits.
976 bool Simulator::ConditionallyExecute(Instr* instr) {
977 switch (instr->ConditionField()) {
978 case EQ: return z_flag_;
979 case NE: return !z_flag_;
980 case CS: return c_flag_;
981 case CC: return !c_flag_;
982 case MI: return n_flag_;
983 case PL: return !n_flag_;
984 case VS: return v_flag_;
985 case VC: return !v_flag_;
986 case HI: return c_flag_ && !z_flag_;
987 case LS: return !c_flag_ || z_flag_;
988 case GE: return n_flag_ == v_flag_;
989 case LT: return n_flag_ != v_flag_;
990 case GT: return !z_flag_ && (n_flag_ == v_flag_);
991 case LE: return z_flag_ || (n_flag_ != v_flag_);
992 case AL: return true;
993 default: UNREACHABLE();
994 }
995 return false;
996 }
997
998
999 // Calculate and set the Negative and Zero flags.
1000 void Simulator::SetNZFlags(int32_t val) {
1001 n_flag_ = (val < 0);
1002 z_flag_ = (val == 0);
1003 }
1004
1005
1006 // Set the Carry flag.
1007 void Simulator::SetCFlag(bool val) {
1008 c_flag_ = val;
1009 }
1010
1011
1012 // Set the oVerflow flag.
1013 void Simulator::SetVFlag(bool val) {
1014 v_flag_ = val;
1015 }
1016
1017
1018 // Calculate C flag value for additions.
1019 bool Simulator::CarryFrom(int32_t left, int32_t right) {
1020 uint32_t uleft = static_cast<uint32_t>(left);
1021 uint32_t uright = static_cast<uint32_t>(right);
1022 uint32_t urest = 0xffffffffU - uleft;
1023
1024 return (uright > urest);
1025 }
1026
1027
1028 // Calculate C flag value for subtractions.
1029 bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1030 uint32_t uleft = static_cast<uint32_t>(left);
1031 uint32_t uright = static_cast<uint32_t>(right);
1032
1033 return (uright > uleft);
1034 }
1035
1036
1037 // Calculate V flag value for additions and subtractions.
1038 bool Simulator::OverflowFrom(int32_t alu_out,
1039 int32_t left, int32_t right, bool addition) {
1040 bool overflow;
1041 if (addition) {
1042 // operands have the same sign
1043 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1044 // and operands and result have different sign
1045 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1046 } else {
1047 // operands have different signs
1048 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1049 // and first operand and result have different signs
1050 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1051 }
1052 return overflow;
1053 }
1054
1055
1056 // Addressing Mode 1 - Data-processing operands:
1057 // Get the value based on the shifter_operand with register.
1058 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) {
1059 Shift shift = instr->ShiftField();
1060 int shift_amount = instr->ShiftAmountField();
1061 int32_t result = get_register(instr->RmField());
1062 if (instr->Bit(4) == 0) {
1063 // by immediate
1064 if ((shift == ROR) && (shift_amount == 0)) {
1065 UNIMPLEMENTED();
1066 return result;
1067 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1068 shift_amount = 32;
1069 }
1070 switch (shift) {
1071 case ASR: {
1072 if (shift_amount == 0) {
1073 if (result < 0) {
1074 result = 0xffffffff;
1075 *carry_out = true;
1076 } else {
1077 result = 0;
1078 *carry_out = false;
1079 }
1080 } else {
1081 result >>= (shift_amount - 1);
1082 *carry_out = (result & 1) == 1;
1083 result >>= 1;
1084 }
1085 break;
1086 }
1087
1088 case LSL: {
1089 if (shift_amount == 0) {
1090 *carry_out = c_flag_;
1091 } else {
1092 result <<= (shift_amount - 1);
1093 *carry_out = (result < 0);
1094 result <<= 1;
1095 }
1096 break;
1097 }
1098
1099 case LSR: {
1100 if (shift_amount == 0) {
1101 result = 0;
1102 *carry_out = c_flag_;
1103 } else {
1104 uint32_t uresult = static_cast<uint32_t>(result);
1105 uresult >>= (shift_amount - 1);
1106 *carry_out = (uresult & 1) == 1;
1107 uresult >>= 1;
1108 result = static_cast<int32_t>(uresult);
1109 }
1110 break;
1111 }
1112
1113 case ROR: {
1114 UNIMPLEMENTED();
1115 break;
1116 }
1117
1118 default: {
1119 UNREACHABLE();
1120 break;
1121 }
1122 }
1123 } else {
1124 // by register
1125 Register rs = instr->RsField();
1126 shift_amount = get_register(rs) &0xff;
1127 switch (shift) {
1128 case ASR: {
1129 if (shift_amount == 0) {
1130 *carry_out = c_flag_;
1131 } else if (shift_amount < 32) {
1132 result >>= (shift_amount - 1);
1133 *carry_out = (result & 1) == 1;
1134 result >>= 1;
1135 } else {
1136 ASSERT(shift_amount >= 32);
1137 if (result < 0) {
1138 *carry_out = true;
1139 result = 0xffffffff;
1140 } else {
1141 *carry_out = false;
1142 result = 0;
1143 }
1144 }
1145 break;
1146 }
1147
1148 case LSL: {
1149 if (shift_amount == 0) {
1150 *carry_out = c_flag_;
1151 } else if (shift_amount < 32) {
1152 result <<= (shift_amount - 1);
1153 *carry_out = (result < 0);
1154 result <<= 1;
1155 } else if (shift_amount == 32) {
1156 *carry_out = (result & 1) == 1;
1157 result = 0;
1158 } else {
1159 ASSERT(shift_amount > 32);
1160 *carry_out = false;
1161 result = 0;
1162 }
1163 break;
1164 }
1165
1166 case LSR: {
1167 if (shift_amount == 0) {
1168 *carry_out = c_flag_;
1169 } else if (shift_amount < 32) {
1170 uint32_t uresult = static_cast<uint32_t>(result);
1171 uresult >>= (shift_amount - 1);
1172 *carry_out = (uresult & 1) == 1;
1173 uresult >>= 1;
1174 result = static_cast<int32_t>(uresult);
1175 } else if (shift_amount == 32) {
1176 *carry_out = (result < 0);
1177 result = 0;
1178 } else {
1179 *carry_out = false;
1180 result = 0;
1181 }
1182 break;
1183 }
1184
1185 case ROR: {
1186 UNIMPLEMENTED();
1187 break;
1188 }
1189
1190 default: {
1191 UNREACHABLE();
1192 break;
1193 }
1194 }
1195 }
1196 return result;
1197 }
1198
1199
1200 // Addressing Mode 1 - Data-processing operands:
1201 // Get the value based on the shifter_operand with immediate.
1202 int32_t Simulator::GetImm(Instr* instr, bool* carry_out) {
1203 int rotate = instr->RotateField() * 2;
1204 int immed8 = instr->Immed8Field();
1205 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1206 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1207 return imm;
1208 }
1209
1210
1211 static int count_bits(int bit_vector) {
1212 int count = 0;
1213 while (bit_vector != 0) {
1214 if ((bit_vector & 1) != 0) {
1215 count++;
1216 }
1217 bit_vector >>= 1;
1218 }
1219 return count;
1220 }
1221
1222
1223 // Addressing Mode 4 - Load and Store Multiple
1224 void Simulator::HandleRList(Instr* instr, bool load) {
1225 Register rn = instr->RnField();
1226 int32_t rn_val = get_register(rn);
1227 int rlist = instr->RlistField();
1228 int num_regs = count_bits(rlist);
1229
1230 uword address = 0;
1231 uword end_address = 0;
1232 switch (instr->PUField()) {
1233 case 0: {
1234 // Print("da");
1235 address = rn_val - (num_regs * 4) + 4;
1236 end_address = rn_val + 4;
1237 rn_val = rn_val - (num_regs * 4);
1238 break;
1239 }
1240 case 1: {
1241 // Print("ia");
1242 address = rn_val;
1243 end_address = rn_val + (num_regs * 4);
1244 rn_val = rn_val + (num_regs * 4);
1245 break;
1246 }
1247 case 2: {
1248 // Print("db");
1249 address = rn_val - (num_regs * 4);
1250 end_address = rn_val;
1251 rn_val = address;
1252 break;
1253 }
1254 case 3: {
1255 // Print("ib");
1256 address = rn_val + 4;
1257 end_address = rn_val + (num_regs * 4) + 4;
1258 rn_val = rn_val + (num_regs * 4);
1259 break;
1260 }
1261 default: {
1262 UNREACHABLE();
1263 break;
1264 }
1265 }
1266 if (IsIllegalAddress(address)) {
1267 HandleIllegalAccess(address, instr);
1268 } else {
1269 if (instr->HasW()) {
1270 set_register(rn, rn_val);
1271 }
1272 int reg = 0;
1273 while (rlist != 0) {
1274 if ((rlist & 1) != 0) {
1275 if (load) {
1276 set_register(static_cast<Register>(reg), ReadW(address, instr));
1277 } else {
1278 WriteW(address, get_register(static_cast<Register>(reg)), instr);
1279 }
1280 address += 4;
1281 }
1282 reg++;
1283 rlist >>= 1;
1284 }
1285 ASSERT(end_address == address);
1286 }
1287 }
1288
1289
1290 // Calls into the Dart runtime are based on this simple interface.
1291 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
1292
1293
1294 static void PrintExternalCallTrace(intptr_t external,
1295 NativeArguments arguments) {
1296 // TODO(regis): Do a reverse lookup on this address and print the symbol.
1297 UNIMPLEMENTED();
1298 }
1299
1300
1301 void Simulator::SupervisorCall(Instr* instr) {
1302 int svc = instr->SvcField();
1303 switch (svc) {
1304 case kRedirectionSvcCode: {
1305 SimulatorSetjmpBuffer buffer(this);
1306
1307 if (!setjmp(buffer.buffer_)) {
1308 NativeArguments arguments;
1309 ASSERT(sizeof(NativeArguments) == 4*kWordSize);
1310 arguments.isolate_ = reinterpret_cast<Isolate*>(get_register(R0));
1311 arguments.argc_tag_ = get_register(R1);
1312 arguments.argv_ = reinterpret_cast<RawObject*(*)[]>(get_register(R2));
1313 arguments.retval_ = reinterpret_cast<RawObject**>(get_register(R3));
1314
1315 int32_t saved_lr = get_register(LR);
1316 Redirection* redirection = Redirection::FromSvcInstruction(instr);
1317 intptr_t external =
1318 reinterpret_cast<intptr_t>(redirection->external_function());
1319 SimulatorRuntimeCall target =
1320 reinterpret_cast<SimulatorRuntimeCall>(external);
1321 if (FLAG_trace_sim) {
1322 PrintExternalCallTrace(external, arguments);
1323 }
1324 target(arguments);
1325
1326 // Zap caller-saved registers, since the actual runtime call could have
1327 // used them.
1328 set_register(R2, icount_);
1329 set_register(R3, icount_);
1330 set_register(IP, icount_);
1331 set_register(LR, icount_);
1332 float zap_fvalue = static_cast<float>(icount_);
1333 for (int i = S0; i <= S15; i++) {
1334 set_sregister(static_cast<SRegister>(i), zap_fvalue);
1335 }
1336 #ifdef VFPv3_D32
1337 double zap_dvalue = static_cast<double>(icount_);
1338 for (int i = D16; i <= D31; i++) {
1339 set_dregister(static_cast<DRegister>(i), zap_dvalue);
1340 }
1341 #endif // VFPv3_D32
1342
1343 // Zap result register pair R0:R1 and return.
1344 set_register(R0, icount_);
1345 set_register(R1, icount_);
1346 set_pc(saved_lr);
1347 }
1348
1349 break;
1350 }
1351 case kBreakpointSvcCode: {
1352 SimulatorDebugger dbg(this);
1353 dbg.Stop(instr, "breakpoint");
1354 break;
1355 }
1356 case kStopMessageSvcCode: {
1357 SimulatorDebugger dbg(this);
1358 const char* message = *reinterpret_cast<const char**>(
1359 reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
1360 set_pc(get_pc() + Instr::kInstrSize);
1361 dbg.Stop(instr, message);
1362 break;
1363 }
1364 case kWordSpillMarkerSvcCode: {
1365 static StatsCounter counter_spill_w("Simulated word spills");
1366 counter_spill_w.Increment();
1367 break;
1368 }
1369 case kDWordSpillMarkerSvcCode: {
1370 static StatsCounter counter_spill_d("Simulated double word spills");
1371 counter_spill_d.Increment();
1372 break;
1373 }
1374 default: {
1375 UNREACHABLE();
1376 break;
1377 }
1378 }
1379 }
1380
1381
1382 // Handle execution based on instruction types.
1383
1384 // Instruction types 0 and 1 are both rolled into one function because they
1385 // only differ in the handling of the shifter_operand.
1386 void Simulator::DecodeType01(Instr* instr) {
1387 if (!instr->IsDataProcessing()) {
1388 // miscellaneous, multiply, sync primitives, extra loads and stores.
1389 if (instr->IsMiscellaneous()) {
1390 switch (instr->Bits(4, 3)) {
1391 case 1: {
1392 ASSERT(instr->Bits(21, 2) == 0x3);
1393 // Format(instr, "clz'cond 'rd, 'rm");
1394 Register rm = instr->RmField();
1395 Register rd = instr->RdField();
1396 int32_t rm_val = get_register(rm);
1397 int32_t rd_val = 0;
1398 if (rm_val != 0) {
1399 while (rm_val > 0) {
1400 rd_val++;
1401 rm_val <<= 1;
1402 }
1403 } else {
1404 rd_val = 32;
1405 }
1406 set_register(rd, rd_val);
1407 break;
1408 }
1409 case 3: {
1410 ASSERT(instr->Bits(21, 2) == 0x1);
1411 // Format(instr, "blx'cond 'rm");
1412 Register rm = instr->RmField();
1413 int32_t rm_val = get_register(rm);
1414 intptr_t pc = get_pc();
1415 set_register(LR, pc + Instr::kInstrSize);
1416 set_pc(rm_val);
1417 break;
1418 }
1419 case 7: {
1420 if (instr->Bits(21, 2) == 0x1) {
1421 // Format(instr, "bkpt #'imm12_4");
1422 SimulatorDebugger dbg(this);
1423 set_pc(get_pc() + Instr::kInstrSize);
1424 char buffer[32];
1425 snprintf(buffer, sizeof(buffer), "bkpt #0x%x", instr->BkptField());
1426 dbg.Stop(instr, buffer);
1427 } else {
1428 // Format(instr, "smc'cond");
1429 UNIMPLEMENTED();
1430 }
1431 break;
1432 }
1433 default: {
1434 UNIMPLEMENTED();
1435 break;
1436 }
1437 }
1438 } else if (instr->IsMultiplyOrSyncPrimitive()) {
1439 if (instr->Bit(24) == 0) {
1440 // multiply instructions.
1441 Register rn = instr->RnField();
1442 Register rd = instr->RdField();
1443 Register rs = instr->RsField();
1444 Register rm = instr->RmField();
1445 int32_t rm_val = get_register(rm);
1446 int32_t rs_val = get_register(rs);
1447 int32_t rd_val = 0;
1448 switch (instr->Bits(21, 3)) {
1449 case 1:
1450 // Registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
1451 // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
1452 case 3: {
1453 // Registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
1454 // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
1455 rd_val = get_register(rd);
1456 // fall through
1457 }
1458 case 0: {
1459 // Registers rd, rn, rm are encoded as rn, rm, rs.
1460 // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
1461 int32_t alu_out = rm_val * rs_val;
1462 if (instr->Bits(21, 3) == 3) { // mls
1463 alu_out = -alu_out;
1464 }
1465 alu_out += rd_val;
1466 set_register(rn, alu_out);
1467 if (instr->HasS()) {
1468 SetNZFlags(alu_out);
1469 }
1470 break;
1471 }
1472 case 4: {
1473 // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
1474 // Format(instr, "umull'cond's 'rd, 'rn, 'rm, 'rs");
1475 uint64_t left_op = static_cast<uint32_t>(rm_val);
1476 uint64_t right_op = static_cast<uint32_t>(rs_val);
1477 uint64_t result = left_op * right_op;
1478 int32_t hi_res = Utils::High32Bits(result);
1479 int32_t lo_res = Utils::Low32Bits(result);
1480 set_register(rd, lo_res);
1481 set_register(rn, hi_res);
1482 if (instr->HasS()) {
1483 if (lo_res != 0) {
1484 // Collapse bits 0..31 into bit 32 so that 32-bit Z check works.
1485 hi_res |= 1;
1486 }
1487 ASSERT((result == 0) == (hi_res == 0)); // Z bit
1488 ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0)); // N bit
1489 SetNZFlags(hi_res);
1490 }
1491 break;
1492 }
1493 default: {
1494 UNIMPLEMENTED();
1495 break;
1496 }
1497 }
1498 } else {
1499 // synchronization primitives
1500 Register rd = instr->RdField();
1501 Register rn = instr->RnField();
1502 uword addr = get_register(rn);
1503 switch (instr->Bits(20, 4)) {
1504 case 8: {
1505 // Format(instr, "strex'cond 'rd, 'rm, ['rn]");
1506 if (IsIllegalAddress(addr)) {
1507 HandleIllegalAccess(addr, instr);
1508 } else {
1509 Register rm = instr->RmField();
1510 set_register(rd, WriteExclusiveW(addr, get_register(rm), instr));
1511 }
1512 break;
1513 }
1514 case 9: {
1515 // Format(instr, "ldrex'cond 'rd, ['rn]");
1516 if (IsIllegalAddress(addr)) {
1517 HandleIllegalAccess(addr, instr);
1518 } else {
1519 set_register(rd, ReadExclusiveW(addr, instr));
1520 }
1521 break;
1522 }
1523 default: {
1524 UNIMPLEMENTED();
1525 break;
1526 }
1527 }
1528 }
1529 } else if (instr->Bit(25) == 1) {
1530 // 16-bit immediate loads, msr (immediate), and hints
1531 switch (instr->Bits(20, 5)) {
1532 case 16:
1533 case 20: {
1534 uint16_t imm16 = instr->MovwField();
1535 Register rd = instr->RdField();
1536 if (instr->Bit(22) == 0) {
1537 // Format(instr, "movw'cond 'rd, #'imm4_12");
1538 set_register(rd, imm16);
1539 } else {
1540 // Format(instr, "movt'cond 'rd, #'imm4_12");
1541 set_register(rd, (get_register(rd) & 0xffff) | (imm16 << 16));
1542 }
1543 break;
1544 }
1545 case 18: {
1546 if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) {
1547 // Format(instr, "nop'cond");
1548 } else {
1549 UNIMPLEMENTED();
1550 }
1551 break;
1552 }
1553 default: {
1554 UNIMPLEMENTED();
1555 break;
1556 }
1557 }
1558 } else {
1559 // extra load/store instructions
1560 Register rd = instr->RdField();
1561 Register rn = instr->RnField();
1562 int32_t rn_val = get_register(rn);
1563 uword addr = 0;
1564 bool write_back = false;
1565 if (instr->Bit(22) == 0) {
1566 Register rm = instr->RmField();
1567 int32_t rm_val = get_register(rm);
1568 switch (instr->PUField()) {
1569 case 0: {
1570 // Format(instr, "'memop'cond'x 'rd2, ['rn], -'rm");
1571 ASSERT(!instr->HasW());
1572 addr = rn_val;
1573 rn_val -= rm_val;
1574 write_back = true;
1575 break;
1576 }
1577 case 1: {
1578 // Format(instr, "'memop'cond'x 'rd2, ['rn], +'rm");
1579 ASSERT(!instr->HasW());
1580 addr = rn_val;
1581 rn_val += rm_val;
1582 write_back = true;
1583 break;
1584 }
1585 case 2: {
1586 // Format(instr, "'memop'cond'x 'rd2, ['rn, -'rm]'w");
1587 rn_val -= rm_val;
1588 addr = rn_val;
1589 write_back = instr->HasW();
1590 break;
1591 }
1592 case 3: {
1593 // Format(instr, "'memop'cond'x 'rd2, ['rn, +'rm]'w");
1594 rn_val += rm_val;
1595 addr = rn_val;
1596 write_back = instr->HasW();
1597 break;
1598 }
1599 default: {
1600 // The PU field is a 2-bit field.
1601 UNREACHABLE();
1602 break;
1603 }
1604 }
1605 } else {
1606 int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField();
1607 switch (instr->PUField()) {
1608 case 0: {
1609 // Format(instr, "'memop'cond'x 'rd2, ['rn], #-'off8");
1610 ASSERT(!instr->HasW());
1611 addr = rn_val;
1612 rn_val -= imm_val;
1613 write_back = true;
1614 break;
1615 }
1616 case 1: {
1617 // Format(instr, "'memop'cond'x 'rd2, ['rn], #+'off8");
1618 ASSERT(!instr->HasW());
1619 addr = rn_val;
1620 rn_val += imm_val;
1621 write_back = true;
1622 break;
1623 }
1624 case 2: {
1625 // Format(instr, "'memop'cond'x 'rd2, ['rn, #-'off8]'w");
1626 rn_val -= imm_val;
1627 addr = rn_val;
1628 write_back = instr->HasW();
1629 break;
1630 }
1631 case 3: {
1632 // Format(instr, "'memop'cond'x 'rd2, ['rn, #+'off8]'w");
1633 rn_val += imm_val;
1634 addr = rn_val;
1635 write_back = instr->HasW();
1636 break;
1637 }
1638 default: {
1639 // The PU field is a 2-bit field.
1640 UNREACHABLE();
1641 break;
1642 }
1643 }
1644 }
1645 if (IsIllegalAddress(addr)) {
1646 HandleIllegalAccess(addr, instr);
1647 } else {
1648 if (write_back) {
1649 set_register(rn, rn_val);
1650 }
1651 if (!instr->HasSign()) {
1652 if (instr->HasL()) {
1653 uint16_t val = ReadHU(addr, instr);
1654 set_register(rd, val);
1655 } else {
1656 uint16_t val = get_register(rd);
1657 WriteH(addr, val, instr);
1658 }
1659 } else if (instr->HasL()) {
1660 if (instr->HasH()) {
1661 int16_t val = ReadH(addr, instr);
1662 set_register(rd, val);
1663 } else {
1664 int8_t val = ReadB(addr);
1665 set_register(rd, val);
1666 }
1667 } else if ((rd & 1) == 0) {
1668 Register rd1 = static_cast<Register>(rd | 1);
1669 ASSERT(rd1 < kNumberOfCpuRegisters);
1670 if (instr->HasH()) {
1671 int32_t val_low = get_register(rd);
1672 int32_t val_high = get_register(rd1);
1673 WriteW(addr, val_low, instr);
1674 WriteW(addr + 4, val_high, instr);
1675 } else {
1676 int32_t val_low = ReadW(addr, instr);
1677 int32_t val_high = ReadW(addr + 4, instr);
1678 set_register(rd, val_low);
1679 set_register(rd1, val_high);
1680 }
1681 } else {
1682 UNIMPLEMENTED();
1683 }
1684 }
1685 }
1686 } else {
1687 Register rd = instr->RdField();
1688 Register rn = instr->RnField();
1689 int32_t rn_val = get_register(rn);
1690 int32_t shifter_operand = 0;
1691 bool shifter_carry_out = 0;
1692 if (instr->TypeField() == 0) {
1693 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1694 } else {
1695 ASSERT(instr->TypeField() == 1);
1696 shifter_operand = GetImm(instr, &shifter_carry_out);
1697 }
1698 int32_t alu_out;
1699
1700 switch (instr->OpcodeField()) {
1701 case AND: {
1702 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
1703 // Format(instr, "and'cond's 'rd, 'rn, 'imm");
1704 alu_out = rn_val & shifter_operand;
1705 set_register(rd, alu_out);
1706 if (instr->HasS()) {
1707 SetNZFlags(alu_out);
1708 SetCFlag(shifter_carry_out);
1709 }
1710 break;
1711 }
1712
1713 case EOR: {
1714 // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
1715 // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
1716 alu_out = rn_val ^ shifter_operand;
1717 set_register(rd, alu_out);
1718 if (instr->HasS()) {
1719 SetNZFlags(alu_out);
1720 SetCFlag(shifter_carry_out);
1721 }
1722 break;
1723 }
1724
1725 case SUB: {
1726 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
1727 // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
1728 alu_out = rn_val - shifter_operand;
1729 set_register(rd, alu_out);
1730 if (instr->HasS()) {
1731 SetNZFlags(alu_out);
1732 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
1733 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
1734 }
1735 break;
1736 }
1737
1738 case RSB: {
1739 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
1740 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
1741 alu_out = shifter_operand - rn_val;
1742 set_register(rd, alu_out);
1743 if (instr->HasS()) {
1744 SetNZFlags(alu_out);
1745 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
1746 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
1747 }
1748 break;
1749 }
1750
1751 case ADD: {
1752 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
1753 // Format(instr, "add'cond's 'rd, 'rn, 'imm");
1754 alu_out = rn_val + shifter_operand;
1755 set_register(rd, alu_out);
1756 if (instr->HasS()) {
1757 SetNZFlags(alu_out);
1758 SetCFlag(CarryFrom(rn_val, shifter_operand));
1759 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
1760 }
1761 break;
1762 }
1763
1764 case ADC: {
1765 // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
1766 // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
1767 alu_out = rn_val + shifter_operand + (c_flag_ ? 1 : 0);
1768 set_register(rd, alu_out);
1769 if (instr->HasS()) {
1770 SetNZFlags(alu_out);
1771 SetCFlag(CarryFrom(rn_val, shifter_operand));
1772 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
1773 }
1774 break;
1775 }
1776
1777 case SBC: {
1778 // Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
1779 // Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
1780 alu_out = rn_val - shifter_operand - (!c_flag_ ? 1 : 0);
1781 set_register(rd, alu_out);
1782 if (instr->HasS()) {
1783 SetNZFlags(alu_out);
1784 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
1785 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
1786 }
1787 break;
1788 }
1789
1790 case RSC: {
1791 // Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
1792 // Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
1793 alu_out = shifter_operand - rn_val - (!c_flag_ ? 1 : 0);
1794 set_register(rd, alu_out);
1795 if (instr->HasS()) {
1796 SetNZFlags(alu_out);
1797 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
1798 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
1799 }
1800 break;
1801 }
1802
1803 case TST: {
1804 if (instr->HasS()) {
1805 // Format(instr, "tst'cond 'rn, 'shift_rm");
1806 // Format(instr, "tst'cond 'rn, 'imm");
1807 alu_out = rn_val & shifter_operand;
1808 SetNZFlags(alu_out);
1809 SetCFlag(shifter_carry_out);
1810 } else {
1811 UNIMPLEMENTED();
1812 }
1813 break;
1814 }
1815
1816 case TEQ: {
1817 if (instr->HasS()) {
1818 // Format(instr, "teq'cond 'rn, 'shift_rm");
1819 // Format(instr, "teq'cond 'rn, 'imm");
1820 alu_out = rn_val ^ shifter_operand;
1821 SetNZFlags(alu_out);
1822 SetCFlag(shifter_carry_out);
1823 } else {
1824 UNIMPLEMENTED();
1825 }
1826 break;
1827 }
1828
1829 case CMP: {
1830 if (instr->HasS()) {
1831 // Format(instr, "cmp'cond 'rn, 'shift_rm");
1832 // Format(instr, "cmp'cond 'rn, 'imm");
1833 alu_out = rn_val - shifter_operand;
1834 SetNZFlags(alu_out);
1835 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
1836 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
1837 } else {
1838 UNIMPLEMENTED();
1839 }
1840 break;
1841 }
1842
1843 case CMN: {
1844 if (instr->HasS()) {
1845 // Format(instr, "cmn'cond 'rn, 'shift_rm");
1846 // Format(instr, "cmn'cond 'rn, 'imm");
1847 alu_out = rn_val + shifter_operand;
1848 SetNZFlags(alu_out);
1849 SetCFlag(CarryFrom(rn_val, shifter_operand));
1850 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
1851 } else {
1852 UNIMPLEMENTED();
1853 }
1854 break;
1855 }
1856
1857 case ORR: {
1858 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
1859 // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
1860 alu_out = rn_val | shifter_operand;
1861 set_register(rd, alu_out);
1862 if (instr->HasS()) {
1863 SetNZFlags(alu_out);
1864 SetCFlag(shifter_carry_out);
1865 }
1866 break;
1867 }
1868
1869 case MOV: {
1870 // Format(instr, "mov'cond's 'rd, 'shift_rm");
1871 // Format(instr, "mov'cond's 'rd, 'imm");
1872 alu_out = shifter_operand;
1873 set_register(rd, alu_out);
1874 if (instr->HasS()) {
1875 SetNZFlags(alu_out);
1876 SetCFlag(shifter_carry_out);
1877 }
1878 break;
1879 }
1880
1881 case BIC: {
1882 // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
1883 // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
1884 alu_out = rn_val & ~shifter_operand;
1885 set_register(rd, alu_out);
1886 if (instr->HasS()) {
1887 SetNZFlags(alu_out);
1888 SetCFlag(shifter_carry_out);
1889 }
1890 break;
1891 }
1892
1893 case MVN: {
1894 // Format(instr, "mvn'cond's 'rd, 'shift_rm");
1895 // Format(instr, "mvn'cond's 'rd, 'imm");
1896 alu_out = ~shifter_operand;
1897 set_register(rd, alu_out);
1898 if (instr->HasS()) {
1899 SetNZFlags(alu_out);
1900 SetCFlag(shifter_carry_out);
1901 }
1902 break;
1903 }
1904
1905 default: {
1906 UNREACHABLE();
1907 break;
1908 }
1909 }
1910 }
1911 }
1912
1913
1914 void Simulator::DecodeType2(Instr* instr) {
1915 Register rd = instr->RdField();
1916 Register rn = instr->RnField();
1917 int32_t rn_val = get_register(rn);
1918 int32_t im_val = instr->Offset12Field();
1919 uword addr = 0;
1920 bool write_back = false;
1921 switch (instr->PUField()) {
1922 case 0: {
1923 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
1924 ASSERT(!instr->HasW());
1925 addr = rn_val;
1926 rn_val -= im_val;
1927 write_back = true;
1928 break;
1929 }
1930 case 1: {
1931 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
1932 ASSERT(!instr->HasW());
1933 addr = rn_val;
1934 rn_val += im_val;
1935 write_back = true;
1936 break;
1937 }
1938 case 2: {
1939 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
1940 rn_val -= im_val;
1941 addr = rn_val;
1942 write_back = instr->HasW();
1943 break;
1944 }
1945 case 3: {
1946 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1947 rn_val += im_val;
1948 addr = rn_val;
1949 write_back = instr->HasW();
1950 break;
1951 }
1952 default: {
1953 UNREACHABLE();
1954 break;
1955 }
1956 }
1957 if (IsIllegalAddress(addr)) {
1958 HandleIllegalAccess(addr, instr);
1959 } else {
1960 if (write_back) {
1961 set_register(rn, rn_val);
1962 }
1963 if (instr->HasB()) {
1964 if (instr->HasL()) {
1965 unsigned char val = ReadBU(addr);
1966 set_register(rd, val);
1967 } else {
1968 unsigned char val = get_register(rd);
1969 WriteB(addr, val);
1970 }
1971 } else {
1972 if (instr->HasL()) {
1973 set_register(rd, ReadW(addr, instr));
1974 } else {
1975 WriteW(addr, get_register(rd), instr);
1976 }
1977 }
1978 }
1979 }
1980
1981
1982 void Simulator::DecodeType3(Instr* instr) {
1983 Register rd = instr->RdField();
1984 Register rn = instr->RnField();
1985 int32_t rn_val = get_register(rn);
1986 bool shifter_carry_out = 0;
1987 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1988 uword addr = 0;
1989 bool write_back = false;
1990 switch (instr->PUField()) {
1991 case 0: {
1992 // Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1993 ASSERT(!instr->HasW());
1994 addr = rn_val;
1995 rn_val -= shifter_operand;
1996 write_back = true;
1997 break;
1998 }
1999 case 1: {
2000 // Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
2001 ASSERT(!instr->HasW());
2002 addr = rn_val;
2003 rn_val += shifter_operand;
2004 write_back = true;
2005 break;
2006 }
2007 case 2: {
2008 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
2009 rn_val -= shifter_operand;
2010 addr = rn_val;
2011 write_back = instr->HasW();
2012 break;
2013 }
2014 case 3: {
2015 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
2016 rn_val += shifter_operand;
2017 addr = rn_val;
2018 write_back = instr->HasW();
2019 break;
2020 }
2021 default: {
2022 UNREACHABLE();
2023 break;
2024 }
2025 }
2026 if (IsIllegalAddress(addr)) {
2027 HandleIllegalAccess(addr, instr);
2028 } else {
2029 if (write_back) {
2030 set_register(rn, rn_val);
2031 }
2032 if (instr->HasB()) {
2033 if (instr->HasL()) {
2034 unsigned char val = ReadBU(addr);
2035 set_register(rd, val);
2036 } else {
2037 unsigned char val = get_register(rd);
2038 WriteB(addr, val);
2039 }
2040 } else {
2041 if (instr->HasL()) {
2042 set_register(rd, ReadW(addr, instr));
2043 } else {
2044 WriteW(addr, get_register(rd), instr);
2045 }
2046 }
2047 }
2048 }
2049
2050
2051 void Simulator::DecodeType4(Instr* instr) {
2052 ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode
2053 if (instr->HasL()) {
2054 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
2055 HandleRList(instr, true);
2056 } else {
2057 // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
2058 HandleRList(instr, false);
2059 }
2060 }
2061
2062
2063 void Simulator::DecodeType5(Instr* instr) {
2064 // Format(instr, "b'l'cond 'target");
2065 int off = (instr->SImmed24Field() << 2) + 8;
2066 intptr_t pc = get_pc();
2067 if (instr->HasLink()) {
2068 set_register(LR, pc + Instr::kInstrSize);
2069 }
2070 set_pc(pc+off);
2071 }
2072
2073
2074 void Simulator::DecodeType6(Instr* instr) {
2075 if (instr->IsVFPDoubleTransfer()) {
2076 Register rd = instr->RdField();
2077 Register rn = instr->RnField();
2078 if (instr->Bit(8) == 0) {
2079 SRegister sm = instr->SmField();
2080 SRegister sm1 = static_cast<SRegister>(sm + 1);
2081 ASSERT(sm1 < kNumberOfSRegisters);
2082 if (instr->Bit(20) == 1) {
2083 // Format(instr, "vmovrrs'cond 'rd, 'rn, {'sm', 'sm1}");
2084 set_register(rd, bit_cast<int32_t, float>(get_sregister(sm)));
2085 set_register(rn, bit_cast<int32_t, float>(get_sregister(sm1)));
2086 } else {
2087 // Format(instr, "vmovsrr'cond {'sm, 'sm1}, 'rd', 'rn");
2088 set_sregister(sm, bit_cast<float, int32_t>(get_register(rd)));
2089 set_sregister(sm1, bit_cast<float, int32_t>(get_register(rn)));
2090 }
2091 } else {
2092 DRegister dm = instr->DmField();
2093 if (instr->Bit(20) == 1) {
2094 // Format(instr, "vmovrrd'cond 'rd, 'rn, 'dm");
2095 int64_t dm_val = bit_cast<int64_t, double>(get_dregister(dm));
2096 set_register(rd, Utils::Low32Bits(dm_val));
2097 set_register(rn, Utils::High32Bits(dm_val));
2098 } else {
2099 // Format(instr, "vmovdrr'cond 'dm, 'rd, 'rn");
2100 int64_t dm_val = Utils::LowHighTo64Bits(get_register(rd),
2101 get_register(rn));
2102 set_dregister(dm, bit_cast<double, int64_t>(dm_val));
2103 }
2104 }
2105 } else if (instr-> IsVFPLoadStore()) {
2106 Register rn = instr->RnField();
2107 int32_t addr = get_register(rn);
2108 int32_t imm_val = instr->Bits(0, 8) << 2;
2109 if (instr->Bit(23) == 1) {
2110 addr += imm_val;
2111 } else {
2112 addr -= imm_val;
2113 }
2114 if (IsIllegalAddress(addr)) {
2115 HandleIllegalAccess(addr, instr);
2116 } else {
2117 if (instr->Bit(8) == 0) {
2118 SRegister sd = instr->SdField();
2119 if (instr->Bit(20) == 1) { // vldrs
2120 // Format(instr, "vldrs'cond 'sd, ['rn, #+'off10]");
2121 // Format(instr, "vldrs'cond 'sd, ['rn, #-'off10]");
2122 set_sregister(sd, bit_cast<float, int32_t>(ReadW(addr, instr)));
2123 } else { // vstrs
2124 // Format(instr, "vstrs'cond 'sd, ['rn, #+'off10]");
2125 // Format(instr, "vstrs'cond 'sd, ['rn, #-'off10]");
2126 WriteW(addr, bit_cast<int32_t, float>(get_sregister(sd)), instr);
2127 }
2128 } else {
2129 DRegister dd = instr->DdField();
2130 if (instr->Bit(20) == 1) { // vldrd
2131 // Format(instr, "vldrd'cond 'dd, ['rn, #+'off10]");
2132 // Format(instr, "vldrd'cond 'dd, ['rn, #-'off10]");
2133 int64_t dd_val = Utils::LowHighTo64Bits(ReadW(addr, instr),
2134 ReadW(addr + 4, instr));
2135 set_dregister(dd, bit_cast<double, int64_t>(dd_val));
2136 } else { // vstrd
2137 // Format(instr, "vstrd'cond 'dd, ['rn, #+'off10]");
2138 // Format(instr, "vstrd'cond 'dd, ['rn, #-'off10]");
2139 int64_t dd_val = bit_cast<int64_t, double>(get_dregister(dd));
2140 WriteW(addr, Utils::Low32Bits(dd_val), instr);
2141 WriteW(addr + 4, Utils::High32Bits(dd_val), instr);
2142 }
2143 }
2144 }
2145 } else {
2146 UNIMPLEMENTED();
2147 }
2148 }
2149
2150
2151 void Simulator::DecodeType7(Instr* instr) {
2152 if (instr->Bit(24) == 1) {
2153 // Format(instr, "svc #'svc");
2154 SupervisorCall(instr);
2155 } else if (instr->IsVFPDataProcessingOrSingleTransfer()) {
2156 if (instr->Bit(4) == 0) {
2157 // VFP Data Processing
2158 SRegister sd;
2159 SRegister sn;
2160 SRegister sm;
2161 DRegister dd;
2162 DRegister dn;
2163 DRegister dm;
2164 if (instr->Bit(8) == 0) {
2165 sd = instr->SdField();
2166 sn = instr->SnField();
2167 sm = instr->SmField();
2168 dd = kNoDRegister;
2169 dn = kNoDRegister;
2170 dm = kNoDRegister;
2171 } else {
2172 sd = kNoSRegister;
2173 sn = kNoSRegister;
2174 sm = kNoSRegister;
2175 dd = instr->DdField();
2176 dn = instr->DnField();
2177 dm = instr->DmField();
2178 }
2179 switch (instr->Bits(20, 4) & 0xb) {
2180 case 1: // vnmla, vnmls, vnmul
2181 default: {
2182 UNIMPLEMENTED();
2183 break;
2184 }
2185 case 0: { // vmla, vmls floating-point
2186 if (instr->Bit(8) == 0) {
2187 float addend = get_sregister(sn) * get_sregister(sm);
2188 float sd_val = get_sregister(sd);
2189 if (instr->Bit(6) == 0) {
2190 // Format(instr, "vmlas'cond 'sd, 'sn, 'sm");
2191 } else {
2192 // Format(instr, "vmlss'cond 'sd, 'sn, 'sm");
2193 addend = -addend;
2194 }
2195 set_sregister(sd, sd_val + addend);
2196 } else {
2197 double addend = get_dregister(dn) * get_dregister(dm);
2198 double dd_val = get_dregister(dd);
2199 if (instr->Bit(6) == 0) {
2200 // Format(instr, "vmlad'cond 'dd, 'dn, 'dm");
2201 } else {
2202 // Format(instr, "vmlsd'cond 'dd, 'dn, 'dm");
2203 addend = -addend;
2204 }
2205 set_dregister(dd, dd_val + addend);
2206 }
2207 break;
2208 }
2209 case 2: { // vmul
2210 if (instr->Bit(8) == 0) {
2211 // Format(instr, "vmuls'cond 'sd, 'sn, 'sm");
2212 set_sregister(sd, get_sregister(sn) * get_sregister(sm));
2213 } else {
2214 // Format(instr, "vmuld'cond 'dd, 'dn, 'dm");
2215 set_dregister(dd, get_dregister(dn) * get_dregister(dm));
2216 }
2217 break;
2218 }
2219 case 8: { // vdiv
2220 if (instr->Bit(8) == 0) {
2221 // Format(instr, "vdivs'cond 'sd, 'sn, 'sm");
2222 set_sregister(sd, get_sregister(sn) / get_sregister(sm));
2223 } else {
2224 // Format(instr, "vdivd'cond 'dd, 'dn, 'dm");
2225 set_dregister(dd, get_dregister(dn) / get_dregister(dm));
2226 }
2227 break;
2228 }
2229 case 3: { // vadd, vsub floating-point
2230 if (instr->Bit(8) == 0) {
2231 if (instr->Bit(6) == 0) {
2232 // Format(instr, "vadds'cond 'sd, 'sn, 'sm");
2233 set_sregister(sd, get_sregister(sn) + get_sregister(sm));
2234 } else {
2235 // Format(instr, "vsubs'cond 'sd, 'sn, 'sm");
2236 set_sregister(sd, get_sregister(sn) - get_sregister(sm));
2237 }
2238 } else {
2239 if (instr->Bit(6) == 0) {
2240 // Format(instr, "vaddd'cond 'dd, 'dn, 'dm");
2241 set_dregister(dd, get_dregister(dn) + get_dregister(dm));
2242 } else {
2243 // Format(instr, "vsubd'cond 'dd, 'dn, 'dm");
2244 set_dregister(dd, get_dregister(dn) - get_dregister(dm));
2245 }
2246 }
2247 break;
2248 }
2249 case 0xb: { // Other VFP data-processing instructions
2250 if (instr->Bit(6) == 0) { // vmov immediate
2251 if (instr->Bit(8) == 0) {
2252 // Format(instr, "vmovs'cond 'sd, #'immf");
2253 set_sregister(sd, instr->ImmFloatField());
2254 } else {
2255 // Format(instr, "vmovd'cond 'dd, #'immd");
2256 set_dregister(dd, instr->ImmDoubleField());
2257 }
2258 break;
2259 }
2260 switch (instr->Bits(16, 4)) {
2261 case 0: { // vmov immediate, vmov register, vabs
2262 switch (instr->Bits(6, 2)) {
2263 case 1: { // vmov register
2264 if (instr->Bit(8) == 0) {
2265 // Format(instr, "vmovs'cond 'sd, 'sm");
2266 set_sregister(sd, get_sregister(sm));
2267 } else {
2268 // Format(instr, "vmovd'cond 'dd, 'dm");
2269 set_dregister(dd, get_dregister(dm));
2270 }
2271 break;
2272 }
2273 case 3: { // vabs
2274 if (instr->Bit(8) == 0) {
2275 // Format(instr, "vabss'cond 'sd, 'sm");
2276 set_sregister(sd, fabsf(get_sregister(sm)));
2277 } else {
2278 // Format(instr, "vabsd'cond 'dd, 'dm");
2279 set_dregister(dd, fabs(get_dregister(dm)));
2280 }
2281 break;
2282 }
2283 default: {
2284 UNIMPLEMENTED();
2285 break;
2286 }
2287 }
2288 break;
2289 }
2290 case 1: { // vneg, vsqrt
2291 switch (instr->Bits(6, 2)) {
2292 case 1: { // vneg
2293 if (instr->Bit(8) == 0) {
2294 // Format(instr, "vnegs'cond 'sd, 'sm");
2295 set_sregister(sd, -get_sregister(sm));
2296 } else {
2297 // Format(instr, "vnegd'cond 'dd, 'dm");
2298 set_dregister(dd, -get_dregister(dm));
2299 }
2300 break;
2301 }
2302 case 3: { // vsqrt
2303 if (instr->Bit(8) == 0) {
2304 // Format(instr, "vsqrts'cond 'sd, 'sm");
2305 set_sregister(sd, sqrtf(get_sregister(sm)));
2306 } else {
2307 // Format(instr, "vsqrtd'cond 'dd, 'dm");
2308 set_dregister(dd, sqrt(get_dregister(dm)));
2309 }
2310 break;
2311 }
2312 default: {
2313 UNIMPLEMENTED();
2314 break;
2315 }
2316 }
2317 break;
2318 }
2319 case 4: // vcmp, vcmpe
2320 case 5: { // vcmp #0.0, vcmpe #0.0
2321 if (instr->Bit(7) == 1) { // vcmpe
2322 UNIMPLEMENTED();
2323 } else {
2324 fp_n_flag_ = false;
2325 fp_z_flag_ = false;
2326 fp_c_flag_ = false;
2327 fp_v_flag_ = false;
2328 if (instr->Bit(8) == 0) { // vcmps
2329 float sd_val = get_sregister(sd);
2330 float sm_val;
2331 if (instr->Bit(16) == 0) {
2332 // Format(instr, "vcmps'cond 'sd, 'sm");
2333 sm_val = get_sregister(sm);
2334 } else {
2335 // Format(instr, "vcmps'cond 'sd, #0.0");
2336 sm_val = 0.0f;
2337 }
2338 if (isnan(sd_val) || isnan(sm_val)) {
2339 fp_c_flag_ = true;
2340 fp_v_flag_ = true;
2341 } else if (sd_val == sm_val) {
2342 fp_z_flag_ = true;
2343 fp_c_flag_ = true;
2344 } else if (sd_val < sm_val) {
2345 fp_n_flag_ = true;
2346 } else {
2347 fp_c_flag_ = true;
2348 }
2349 } else { // vcmpd
2350 double dd_val = get_dregister(dd);
2351 double dm_val;
2352 if (instr->Bit(16) == 0) {
2353 // Format(instr, "vcmpd'cond 'dd, 'dm");
2354 dm_val = get_dregister(dm);
2355 } else {
2356 // Format(instr, "vcmpd'cond 'dd, #0.0");
2357 dm_val = 0.0;
2358 }
2359 if (isnan(dd_val) || isnan(dm_val)) {
2360 fp_c_flag_ = true;
2361 fp_v_flag_ = true;
2362 } else if (dd_val == dm_val) {
2363 fp_z_flag_ = true;
2364 fp_c_flag_ = true;
2365 } else if (dd_val < dm_val) {
2366 fp_n_flag_ = true;
2367 } else {
2368 fp_c_flag_ = true;
2369 }
2370 }
2371 }
2372 break;
2373 }
2374 case 7: { // vcvt between double-precision and single-precision
2375 if (instr->Bit(8) == 0) {
2376 // Format(instr, "vcvtds'cond 'dd, 'sm");
2377 dd = instr->DdField();
2378 set_dregister(dd, static_cast<double>(get_sregister(sm)));
2379 } else {
2380 // Format(instr, "vcvtsd'cond 'sd, 'dm");
2381 sd = instr->SdField();
2382 set_sregister(sd, static_cast<float>(get_dregister(dm)));
2383 }
2384 break;
2385 }
2386 case 8: { // vcvt, vcvtr between floating-point and integer
2387 sm = instr->SmField();
2388 float sm_val = get_sregister(sm);
2389 uint32_t ud_val = 0;
2390 int32_t id_val = 0;
2391 if (instr->Bit(7) == 0) { // vcvtsu, vcvtdu
2392 ud_val = bit_cast<uint32_t, float>(sm_val);
2393 } else { // vcvtsi, vcvtdi
2394 id_val = bit_cast<int32_t, float>(sm_val);
2395 }
2396 if (instr->Bit(8) == 0) {
2397 float sd_val;
2398 if (instr->Bit(7) == 0) {
2399 // Format(instr, "vcvtsu'cond 'sd, 'sm");
2400 sd_val = static_cast<float>(ud_val);
2401 } else {
2402 // Format(instr, "vcvtsi'cond 'sd, 'sm");
2403 sd_val = static_cast<float>(id_val);
2404 }
2405 set_sregister(sd, sd_val);
2406 } else {
2407 double dd_val;
2408 if (instr->Bit(7) == 0) {
2409 // Format(instr, "vcvtdu'cond 'dd, 'sm");
2410 dd_val = static_cast<double>(ud_val);
2411 } else {
2412 // Format(instr, "vcvtdi'cond 'dd, 'sm");
2413 dd_val = static_cast<double>(id_val);
2414 }
2415 set_dregister(dd, dd_val);
2416 }
2417 break;
2418 }
2419 case 12:
2420 case 13: { // vcvt, vcvtr between floating-point and integer
2421 // We do not need to record exceptions in the FPSCR cumulative
2422 // flags, because we do not use them.
2423 if (instr->Bit(7) == 0) {
2424 // We only support round-to-zero mode
2425 UNIMPLEMENTED();
2426 break;
2427 }
2428 int32_t id_val = 0;
2429 uint32_t ud_val = 0;
2430 if (instr->Bit(8) == 0) {
2431 float sm_val = get_sregister(sm);
2432 if (instr->Bit(16) == 0) {
2433 // Format(instr, "vcvtus'cond 'sd, 'sm");
2434 if (sm_val >= INT_MAX) {
2435 ud_val = INT_MAX;
2436 } else if (sm_val > 0.0) {
2437 ud_val = static_cast<uint32_t>(sm_val);
2438 }
2439 } else {
2440 // Format(instr, "vcvtis'cond 'sd, 'sm");
2441 if (sm_val <= INT_MIN) {
2442 id_val = INT_MIN;
2443 } else if (sm_val >= INT_MAX) {
2444 id_val = INT_MAX;
2445 } else {
2446 id_val = static_cast<int32_t>(sm_val);
2447 }
2448 ASSERT((id_val >= 0) || !(sm_val >= 0.0));
2449 }
2450 } else {
2451 sd = instr->SdField();
2452 double dm_val = get_dregister(dm);
2453 if (instr->Bit(16) == 0) {
2454 // Format(instr, "vcvtud'cond 'sd, 'dm");
2455 if (dm_val >= INT_MAX) {
2456 ud_val = INT_MAX;
2457 } else if (dm_val > 0.0) {
2458 ud_val = static_cast<uint32_t>(dm_val);
2459 }
2460 } else {
2461 // Format(instr, "vcvtid'cond 'sd, 'dm");
2462 if (dm_val <= INT_MIN) {
2463 id_val = INT_MIN;
2464 } else if (dm_val >= INT_MAX) {
2465 id_val = INT_MAX;
2466 } else {
2467 id_val = static_cast<int32_t>(dm_val);
2468 }
2469 ASSERT((id_val >= 0) || !(dm_val >= 0.0));
2470 }
2471 }
2472 float sd_val;
2473 if (instr->Bit(16) == 0) {
2474 sd_val = bit_cast<float, uint32_t>(ud_val);
2475 } else {
2476 sd_val = bit_cast<float, int32_t>(id_val);
2477 }
2478 set_sregister(sd, sd_val);
2479 break;
2480 }
2481 case 2: // vcvtb, vcvtt
2482 case 3: // vcvtb, vcvtt
2483 case 9: // undefined
2484 case 10: // vcvt between floating-point and fixed-point
2485 case 11: // vcvt between floating-point and fixed-point
2486 case 14: // vcvt between floating-point and fixed-point
2487 case 15: // vcvt between floating-point and fixed-point
2488 default: {
2489 UNIMPLEMENTED();
2490 break;
2491 }
2492 }
2493 }
2494 break;
2495 }
2496 } else {
2497 // 8, 16, or 32-bit Transfer between ARM Core and VFP
2498 if ((instr->Bits(21, 3) == 0) && (instr->Bit(8) == 0)) {
2499 Register rd = instr->RdField();
2500 SRegister sn = instr->SnField();
2501 if (instr->Bit(20) == 0) {
2502 // Format(instr, "vmovs'cond 'sn, 'rd");
2503 set_sregister(sn, bit_cast<float, int32_t>(get_register(rd)));
2504 } else {
2505 // Format(instr, "vmovr'cond 'rd, 'sn");
2506 set_register(rd, bit_cast<int32_t, float>(get_sregister(sn)));
2507 }
2508 } else if ((instr->Bits(20, 4) == 0xf) && (instr->Bit(8) == 0) &&
2509 (instr->Bits(12, 4) == 0xf)) {
2510 // Format(instr, "vmstat'cond");
2511 n_flag_ = fp_n_flag_;
2512 z_flag_ = fp_z_flag_;
2513 c_flag_ = fp_c_flag_;
2514 v_flag_ = fp_v_flag_;
2515 } else {
2516 UNIMPLEMENTED();
2517 }
2518 }
2519 } else {
2520 UNIMPLEMENTED();
2521 }
2522 }
2523
2524
2525 // Executes the current instruction.
2526 void Simulator::InstructionDecode(Instr* instr) {
2527 pc_modified_ = false;
2528 if (FLAG_trace_sim) {
2529 const uword start = reinterpret_cast<uword>(instr);
2530 const uword end = start + Instr::kInstrSize;
2531 Disassembler::Disassemble(start, end);
2532 }
2533 if (instr->ConditionField() == kSpecialCondition) {
2534 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
2535 // Format(instr, "clrex");
2536 ClearExclusive();
2537 } else {
2538 UNIMPLEMENTED();
2539 }
2540 } else if (ConditionallyExecute(instr)) {
2541 switch (instr->TypeField()) {
2542 case 0:
2543 case 1: {
2544 DecodeType01(instr);
2545 break;
2546 }
2547 case 2: {
2548 DecodeType2(instr);
2549 break;
2550 }
2551 case 3: {
2552 DecodeType3(instr);
2553 break;
2554 }
2555 case 4: {
2556 DecodeType4(instr);
2557 break;
2558 }
2559 case 5: {
2560 DecodeType5(instr);
2561 break;
2562 }
2563 case 6: {
2564 DecodeType6(instr);
2565 break;
2566 }
2567 case 7: {
2568 DecodeType7(instr);
2569 break;
2570 }
2571 default: {
2572 UNIMPLEMENTED();
2573 break;
2574 }
2575 }
2576 }
2577 if (!pc_modified_) {
2578 set_register(PC, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
2579 }
2580 }
2581
2582
2583 void Simulator::Execute() {
2584 static StatsCounter counter_instructions("Simulated instructions");
2585
2586 // Get the PC to simulate. Cannot use the accessor here as we need the
2587 // raw PC value and not the one used as input to arithmetic instructions.
2588 uword program_counter = get_pc();
2589
2590 if (FLAG_stop_sim_at == 0) {
2591 // Fast version of the dispatch loop without checking whether the simulator
2592 // should be stopping at a particular executed instruction.
2593 while (program_counter != kEndSimulatingPC) {
2594 Instr* instr = reinterpret_cast<Instr*>(program_counter);
2595 icount_++;
2596 counter_instructions.Increment();
2597 if (IsIllegalAddress(program_counter)) {
2598 HandleIllegalAccess(program_counter, instr);
2599 } else {
2600 InstructionDecode(instr);
2601 }
2602 program_counter = get_pc();
2603 }
2604 } else {
2605 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2606 // we reach the particular instruction count.
2607 while (program_counter != kEndSimulatingPC) {
2608 Instr* instr = reinterpret_cast<Instr*>(program_counter);
2609 icount_++;
2610 counter_instructions.Increment();
2611 if (icount_ == FLAG_stop_sim_at) {
2612 SimulatorDebugger dbg(this);
2613 dbg.Debug();
2614 } else if (IsIllegalAddress(program_counter)) {
2615 HandleIllegalAccess(program_counter, instr);
2616 } else {
2617 InstructionDecode(instr);
2618 }
2619 program_counter = get_pc();
2620 }
2621 }
2622 }
2623
2624
2625 int64_t Simulator::Call(int32_t entry,
2626 int32_t parameter0,
2627 int32_t parameter1,
2628 int32_t parameter2,
2629 int32_t parameter3,
2630 int32_t parameter4) {
2631 // Save the SP register before the call so we can restore it.
2632 int32_t sp_before_call = get_register(SP);
2633
2634 // Setup parameters.
2635 set_register(R0, parameter0);
2636 set_register(R1, parameter1);
2637 set_register(R2, parameter2);
2638 set_register(R3, parameter3);
2639
2640 // Reserve room for one stack parameter.
2641 int32_t stack_pointer = sp_before_call;
2642 stack_pointer -= kWordSize;
2643
2644 // Make sure the activation frames are properly aligned.
2645 static const int kFrameAlignment = OS::ActivationFrameAlignment();
2646 if (kFrameAlignment > 0) {
2647 stack_pointer = Utils::RoundDown(stack_pointer, kFrameAlignment);
2648 }
2649
2650 // Write the fourth parameter to the stack and update register SP.
2651 *reinterpret_cast<int32_t*>(stack_pointer) = parameter4;
2652 set_register(SP, stack_pointer);
2653
2654 // Prepare to execute the code at entry.
2655 set_register(PC, entry);
2656 // Put down marker for end of simulation. The simulator will stop simulation
2657 // when the PC reaches this value. By saving the "end simulation" value into
2658 // the LR the simulation stops when returning to this call point.
2659 set_register(LR, kEndSimulatingPC);
2660
2661 // Remember the values of callee-saved registers.
2662 // The code below assumes that r9 is not used as sb (static base) in
2663 // simulator code and therefore is regarded as a callee-saved register.
2664 int32_t r4_val = get_register(R4);
2665 int32_t r5_val = get_register(R5);
2666 int32_t r6_val = get_register(R6);
2667 int32_t r7_val = get_register(R7);
2668 int32_t r8_val = get_register(R8);
2669 int32_t r9_val = get_register(R9);
2670 int32_t r10_val = get_register(R10);
2671 int32_t r11_val = get_register(R11);
2672
2673 // Setup the callee-saved registers with a known value. To be able to check
2674 // that they are preserved properly across JS execution.
2675 int32_t callee_saved_value = icount_;
2676 set_register(R4, callee_saved_value);
2677 set_register(R5, callee_saved_value);
2678 set_register(R6, callee_saved_value);
2679 set_register(R7, callee_saved_value);
2680 set_register(R8, callee_saved_value);
2681 set_register(R9, callee_saved_value);
2682 set_register(R10, callee_saved_value);
2683 set_register(R11, callee_saved_value);
2684
2685 // Start the simulation
2686 Execute();
2687
2688 // Check that the callee-saved registers have been preserved.
2689 ASSERT(callee_saved_value == get_register(R4));
2690 ASSERT(callee_saved_value == get_register(R5));
2691 ASSERT(callee_saved_value == get_register(R6));
2692 ASSERT(callee_saved_value == get_register(R7));
2693 ASSERT(callee_saved_value == get_register(R8));
2694 ASSERT(callee_saved_value == get_register(R9));
2695 ASSERT(callee_saved_value == get_register(R10));
2696 ASSERT(callee_saved_value == get_register(R11));
2697
2698 // Restore callee-saved registers with the original value.
2699 set_register(R4, r4_val);
2700 set_register(R5, r5_val);
2701 set_register(R6, r6_val);
2702 set_register(R7, r7_val);
2703 set_register(R8, r8_val);
2704 set_register(R9, r9_val);
2705 set_register(R10, r10_val);
2706 set_register(R11, r11_val);
2707
2708 // Restore the SP register and return R1:R0.
2709 set_register(SP, sp_before_call);
2710 return Utils::LowHighTo64Bits(get_register(R0), get_register(R1));
2711 }
2712
2713
2714 void Simulator::Longjmp(
2715 int32_t pc, int32_t sp, int32_t fp, const Instance& object) {
2716 set_register(SP, sp);
2717 set_register(FP, fp);
2718 set_register(PC, pc);
2719 SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
2720
2721 // Walk over all setjmp buffers (simulated --> C++ transitions)
2722 // and try to find the setjmp associated with the stack pointer.
2723 while (buf->link() != NULL && buf->link()->sp() <= sp) {
2724 buf = buf->link();
2725 }
2726 ASSERT(buf != NULL);
2727
2728 // Clean up stack memory of C++ frames.
2729 // TODO(regis): Revisit.
2730 // isolate->PrepareForUnwinding(reinterpret_cast<uword>(buf));
2731 // isolate->ChangeStateToGeneratedCode();
2732 set_register(kExceptionObjectReg, bit_cast<int32_t>(object.raw()));
2733 buf->Longjmp();
2734 }
2735
2736 } // namespace dart
2737
2738 #endif // !defined(HOST_ARCH_ARM)
2739
2740 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm.h ('k') | runtime/vm/simulator_mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698