1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdarg.h>
6 #include <stdlib.h>
7 #include <cmath>
8
9 #include "src/v8.h"
10
11 #if V8_TARGET_ARCH_ARM
12
13 #include "src/arm/constants-arm.h"
14 #include "src/arm/simulator-arm.h"
15 #include "src/assembler.h"
16 #include "src/codegen.h"
17 #include "src/disasm.h"
18
19 #if defined(USE_SIMULATOR)
20
21 // Only build the simulator if not compiling for real ARM hardware.
22 namespace v8 {
23 namespace internal {
24
25 // This macro provides a platform independent use of sscanf. The reason for
26 // SScanF not being implemented in a platform independent way through
27 // ::v8::internal::OS in the same way as SNPrintF is that the
28 // Windows C Run-Time Library does not provide vsscanf.
29 #define SScanF sscanf // NOLINT
30
31 // The ArmDebugger class is used by the simulator while debugging simulated ARM
32 // code.
33 class ArmDebugger {
34 public:
ArmDebugger(Simulator * sim)35 explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
36 ~ArmDebugger();
37
38 void Stop(Instruction* instr);
39 void Debug();
40
41 private:
42 static const Instr kBreakpointInstr =
43 (al | (7*B25) | (1*B24) | kBreakpoint);
44 static const Instr kNopInstr = (al | (13*B21));
45
46 Simulator* sim_;
47
48 int32_t GetRegisterValue(int regnum);
49 double GetRegisterPairDoubleValue(int regnum);
50 double GetVFPDoubleRegisterValue(int regnum);
51 bool GetValue(const char* desc, int32_t* value);
52 bool GetVFPSingleValue(const char* desc, float* value);
53 bool GetVFPDoubleValue(const char* desc, double* value);
54
55 // Set or delete a breakpoint. Returns true if successful.
56 bool SetBreakpoint(Instruction* breakpc);
57 bool DeleteBreakpoint(Instruction* breakpc);
58
59 // Undo and redo all breakpoints. This is needed to bracket disassembly and
60 // execution to skip past breakpoints when run from the debugger.
61 void UndoBreakpoints();
62 void RedoBreakpoints();
63 };
64
65
~ArmDebugger()66 ArmDebugger::~ArmDebugger() {
67 }
68
69
70
71 #ifdef GENERATED_CODE_COVERAGE
72 static FILE* coverage_log = NULL;
73
74
InitializeCoverage()75 static void InitializeCoverage() {
76 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
77 if (file_name != NULL) {
78 coverage_log = fopen(file_name, "aw+");
79 }
80 }
81
82
Stop(Instruction * instr)83 void ArmDebugger::Stop(Instruction* instr) {
84 // Get the stop code.
85 uint32_t code = instr->SvcValue() & kStopCodeMask;
86 // Retrieve the encoded address, which comes just after this stop.
87 char** msg_address =
88 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
89 char* msg = *msg_address;
90 DCHECK(msg != NULL);
91
92 // Update this stop description.
93 if (isWatchedStop(code) && !watched_stops_[code].desc) {
94 watched_stops_[code].desc = msg;
95 }
96
97 if (strlen(msg) > 0) {
98 if (coverage_log != NULL) {
99 fprintf(coverage_log, "%s\n", msg);
100 fflush(coverage_log);
101 }
102 // Overwrite the instruction and address with nops.
103 instr->SetInstructionBits(kNopInstr);
104 reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr);
105 }
106 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
107 }
108
109 #else // ndef GENERATED_CODE_COVERAGE
110
InitializeCoverage()111 static void InitializeCoverage() {
112 }
113
114
Stop(Instruction * instr)115 void ArmDebugger::Stop(Instruction* instr) {
116 // Get the stop code.
117 uint32_t code = instr->SvcValue() & kStopCodeMask;
118 // Retrieve the encoded address, which comes just after this stop.
119 char* msg = *reinterpret_cast<char**>(sim_->get_pc()
120 + Instruction::kInstrSize);
121 // Update this stop description.
122 if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
123 sim_->watched_stops_[code].desc = msg;
124 }
125 // Print the stop message and code if it is not the default code.
126 if (code != kMaxStopCode) {
127 PrintF("Simulator hit stop %u: %s\n", code, msg);
128 } else {
129 PrintF("Simulator hit %s\n", msg);
130 }
131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
132 Debug();
133 }
134 #endif
135
136
GetRegisterValue(int regnum)137 int32_t ArmDebugger::GetRegisterValue(int regnum) {
138 if (regnum == kPCRegister) {
139 return sim_->get_pc();
140 } else {
141 return sim_->get_register(regnum);
142 }
143 }
144
145
GetRegisterPairDoubleValue(int regnum)146 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
147 return sim_->get_double_from_register_pair(regnum);
148 }
149
150
GetVFPDoubleRegisterValue(int regnum)151 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
152 return sim_->get_double_from_d_register(regnum);
153 }
154
155
GetValue(const char * desc,int32_t * value)156 bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
157 int regnum = Registers::Number(desc);
158 if (regnum != kNoRegister) {
159 *value = GetRegisterValue(regnum);
160 return true;
161 } else {
162 if (strncmp(desc, "0x", 2) == 0) {
163 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
164 } else {
165 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
166 }
167 }
168 return false;
169 }
170
171
GetVFPSingleValue(const char * desc,float * value)172 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
173 bool is_double;
174 int regnum = VFPRegisters::Number(desc, &is_double);
175 if (regnum != kNoRegister && !is_double) {
176 *value = sim_->get_float_from_s_register(regnum);
177 return true;
178 }
179 return false;
180 }
181
182
GetVFPDoubleValue(const char * desc,double * value)183 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
184 bool is_double;
185 int regnum = VFPRegisters::Number(desc, &is_double);
186 if (regnum != kNoRegister && is_double) {
187 *value = sim_->get_double_from_d_register(regnum);
188 return true;
189 }
190 return false;
191 }
192
193
SetBreakpoint(Instruction * breakpc)194 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
195 // Check if a breakpoint can be set. If not return without any side-effects.
196 if (sim_->break_pc_ != NULL) {
197 return false;
198 }
199
200 // Set the breakpoint.
201 sim_->break_pc_ = breakpc;
202 sim_->break_instr_ = breakpc->InstructionBits();
203 // Not setting the breakpoint instruction in the code itself. It will be set
204 // when the debugger shell continues.
205 return true;
206 }
207
208
DeleteBreakpoint(Instruction * breakpc)209 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
210 if (sim_->break_pc_ != NULL) {
211 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
212 }
213
214 sim_->break_pc_ = NULL;
215 sim_->break_instr_ = 0;
216 return true;
217 }
218
219
UndoBreakpoints()220 void ArmDebugger::UndoBreakpoints() {
221 if (sim_->break_pc_ != NULL) {
222 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
223 }
224 }
225
226
RedoBreakpoints()227 void ArmDebugger::RedoBreakpoints() {
228 if (sim_->break_pc_ != NULL) {
229 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
230 }
231 }
232
233
Debug()234 void ArmDebugger::Debug() {
235 intptr_t last_pc = -1;
236 bool done = false;
237
238 #define COMMAND_SIZE 63
239 #define ARG_SIZE 255
240
241 #define STR(a) #a
242 #define XSTR(a) STR(a)
243
244 char cmd[COMMAND_SIZE + 1];
245 char arg1[ARG_SIZE + 1];
246 char arg2[ARG_SIZE + 1];
247 char* argv[3] = { cmd, arg1, arg2 };
248
249 // make sure to have a proper terminating character if reaching the limit
250 cmd[COMMAND_SIZE] = 0;
251 arg1[ARG_SIZE] = 0;
252 arg2[ARG_SIZE] = 0;
253
254 // Undo all set breakpoints while running in the debugger shell. This will
255 // make them invisible to all commands.
256 UndoBreakpoints();
257
258 while (!done && !sim_->has_bad_pc()) {
259 if (last_pc != sim_->get_pc()) {
260 disasm::NameConverter converter;
261 disasm::Disassembler dasm(converter);
262 // use a reasonably large buffer
263 v8::internal::EmbeddedVector<char, 256> buffer;
264 dasm.InstructionDecode(buffer,
265 reinterpret_cast<byte*>(sim_->get_pc()));
266 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
267 last_pc = sim_->get_pc();
268 }
269 char* line = ReadLine("sim> ");
270 if (line == NULL) {
271 break;
272 } else {
273 char* last_input = sim_->last_debugger_input();
274 if (strcmp(line, "\n") == 0 && last_input != NULL) {
275 line = last_input;
276 } else {
277 // Ownership is transferred to sim_;
278 sim_->set_last_debugger_input(line);
279 }
280 // Use sscanf to parse the individual parts of the command line. At the
281 // moment no command expects more than two parameters.
282 int argc = SScanF(line,
283 "%" XSTR(COMMAND_SIZE) "s "
284 "%" XSTR(ARG_SIZE) "s "
285 "%" XSTR(ARG_SIZE) "s",
286 cmd, arg1, arg2);
287 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
288 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
289 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
290 // Execute the one instruction we broke at with breakpoints disabled.
291 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
292 // Leave the debugger shell.
293 done = true;
294 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
295 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
296 int32_t value;
297 float svalue;
298 double dvalue;
299 if (strcmp(arg1, "all") == 0) {
300 for (int i = 0; i < kNumRegisters; i++) {
301 value = GetRegisterValue(i);
302 PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value);
303 if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
304 i < 8 &&
305 (i % 2) == 0) {
306 dvalue = GetRegisterPairDoubleValue(i);
307 PrintF(" (%f)\n", dvalue);
308 } else {
309 PrintF("\n");
310 }
311 }
312 for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) {
313 dvalue = GetVFPDoubleRegisterValue(i);
314 uint64_t as_words = bit_cast<uint64_t>(dvalue);
315 PrintF("%3s: %f 0x%08x %08x\n",
316 VFPRegisters::Name(i, true),
317 dvalue,
318 static_cast<uint32_t>(as_words >> 32),
319 static_cast<uint32_t>(as_words & 0xffffffff));
320 }
321 } else {
322 if (GetValue(arg1, &value)) {
323 PrintF("%s: 0x%08x %d \n", arg1, value, value);
324 } else if (GetVFPSingleValue(arg1, &svalue)) {
325 uint32_t as_word = bit_cast<uint32_t>(svalue);
326 PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
327 } else if (GetVFPDoubleValue(arg1, &dvalue)) {
328 uint64_t as_words = bit_cast<uint64_t>(dvalue);
329 PrintF("%s: %f 0x%08x %08x\n",
330 arg1,
331 dvalue,
332 static_cast<uint32_t>(as_words >> 32),
333 static_cast<uint32_t>(as_words & 0xffffffff));
334 } else {
335 PrintF("%s unrecognized\n", arg1);
336 }
337 }
338 } else {
339 PrintF("print <register>\n");
340 }
341 } else if ((strcmp(cmd, "po") == 0)
342 || (strcmp(cmd, "printobject") == 0)) {
343 if (argc == 2) {
344 int32_t value;
345 OFStream os(stdout);
346 if (GetValue(arg1, &value)) {
347 Object* obj = reinterpret_cast<Object*>(value);
348 os << arg1 << ": \n";
349 #ifdef DEBUG
350 obj->Print(os);
351 os << "\n";
352 #else
353 os << Brief(obj) << "\n";
354 #endif
355 } else {
356 os << arg1 << " unrecognized\n";
357 }
358 } else {
359 PrintF("printobject <value>\n");
360 }
361 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
362 int32_t* cur = NULL;
363 int32_t* end = NULL;
364 int next_arg = 1;
365
366 if (strcmp(cmd, "stack") == 0) {
367 cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
368 } else { // "mem"
369 int32_t value;
370 if (!GetValue(arg1, &value)) {
371 PrintF("%s unrecognized\n", arg1);
372 continue;
373 }
374 cur = reinterpret_cast<int32_t*>(value);
375 next_arg++;
376 }
377
378 int32_t words;
379 if (argc == next_arg) {
380 words = 10;
381 } else {
382 if (!GetValue(argv[next_arg], &words)) {
383 words = 10;
384 }
385 }
386 end = cur + words;
387
388 while (cur < end) {
389 PrintF(" 0x%08x: 0x%08x %10d",
390 reinterpret_cast<intptr_t>(cur), *cur, *cur);
391 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
392 int value = *cur;
393 Heap* current_heap = v8::internal::Isolate::Current()->heap();
394 if (((value & 1) == 0) || current_heap->Contains(obj)) {
395 PrintF(" (");
396 if ((value & 1) == 0) {
397 PrintF("smi %d", value / 2);
398 } else {
399 obj->ShortPrint();
400 }
401 PrintF(")");
402 }
403 PrintF("\n");
404 cur++;
405 }
406 } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
407 disasm::NameConverter converter;
408 disasm::Disassembler dasm(converter);
409 // use a reasonably large buffer
410 v8::internal::EmbeddedVector<char, 256> buffer;
411
412 byte* prev = NULL;
413 byte* cur = NULL;
414 byte* end = NULL;
415
416 if (argc == 1) {
417 cur = reinterpret_cast<byte*>(sim_->get_pc());
418 end = cur + (10 * Instruction::kInstrSize);
419 } else if (argc == 2) {
420 int regnum = Registers::Number(arg1);
421 if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
422 // The argument is an address or a register name.
423 int32_t value;
424 if (GetValue(arg1, &value)) {
425 cur = reinterpret_cast<byte*>(value);
426 // Disassemble 10 instructions at <arg1>.
427 end = cur + (10 * Instruction::kInstrSize);
428 }
429 } else {
430 // The argument is the number of instructions.
431 int32_t value;
432 if (GetValue(arg1, &value)) {
433 cur = reinterpret_cast<byte*>(sim_->get_pc());
434 // Disassemble <arg1> instructions.
435 end = cur + (value * Instruction::kInstrSize);
436 }
437 }
438 } else {
439 int32_t value1;
440 int32_t value2;
441 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
442 cur = reinterpret_cast<byte*>(value1);
443 end = cur + (value2 * Instruction::kInstrSize);
444 }
445 }
446
447 while (cur < end) {
448 prev = cur;
449 cur += dasm.InstructionDecode(buffer, cur);
450 PrintF(" 0x%08x %s\n",
451 reinterpret_cast<intptr_t>(prev), buffer.start());
452 }
453 } else if (strcmp(cmd, "gdb") == 0) {
454 PrintF("relinquishing control to gdb\n");
455 v8::base::OS::DebugBreak();
456 PrintF("regaining control from gdb\n");
457 } else if (strcmp(cmd, "break") == 0) {
458 if (argc == 2) {
459 int32_t value;
460 if (GetValue(arg1, &value)) {
461 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
462 PrintF("setting breakpoint failed\n");
463 }
464 } else {
465 PrintF("%s unrecognized\n", arg1);
466 }
467 } else {
468 PrintF("break <address>\n");
469 }
470 } else if (strcmp(cmd, "del") == 0) {
471 if (!DeleteBreakpoint(NULL)) {
472 PrintF("deleting breakpoint failed\n");
473 }
474 } else if (strcmp(cmd, "flags") == 0) {
475 PrintF("N flag: %d; ", sim_->n_flag_);
476 PrintF("Z flag: %d; ", sim_->z_flag_);
477 PrintF("C flag: %d; ", sim_->c_flag_);
478 PrintF("V flag: %d\n", sim_->v_flag_);
479 PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
480 PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
481 PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
482 PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
483 PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
484 } else if (strcmp(cmd, "stop") == 0) {
485 int32_t value;
486 intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize;
487 Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
488 Instruction* msg_address =
489 reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
490 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
491 // Remove the current stop.
492 if (sim_->isStopInstruction(stop_instr)) {
493 stop_instr->SetInstructionBits(kNopInstr);
494 msg_address->SetInstructionBits(kNopInstr);
495 } else {
496 PrintF("Not at debugger stop.\n");
497 }
498 } else if (argc == 3) {
499 // Print information about all/the specified breakpoint(s).
500 if (strcmp(arg1, "info") == 0) {
501 if (strcmp(arg2, "all") == 0) {
502 PrintF("Stop information:\n");
503 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
504 sim_->PrintStopInfo(i);
505 }
506 } else if (GetValue(arg2, &value)) {
507 sim_->PrintStopInfo(value);
508 } else {
509 PrintF("Unrecognized argument.\n");
510 }
511 } else if (strcmp(arg1, "enable") == 0) {
512 // Enable all/the specified breakpoint(s).
513 if (strcmp(arg2, "all") == 0) {
514 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
515 sim_->EnableStop(i);
516 }
517 } else if (GetValue(arg2, &value)) {
518 sim_->EnableStop(value);
519 } else {
520 PrintF("Unrecognized argument.\n");
521 }
522 } else if (strcmp(arg1, "disable") == 0) {
523 // Disable all/the specified breakpoint(s).
524 if (strcmp(arg2, "all") == 0) {
525 for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
526 sim_->DisableStop(i);
527 }
528 } else if (GetValue(arg2, &value)) {
529 sim_->DisableStop(value);
530 } else {
531 PrintF("Unrecognized argument.\n");
532 }
533 }
534 } else {
535 PrintF("Wrong usage. Use help command for more information.\n");
536 }
537 } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
538 ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
539 PrintF("Trace of executed instructions is %s\n",
540 ::v8::internal::FLAG_trace_sim ? "on" : "off");
541 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
542 PrintF("cont\n");
543 PrintF(" continue execution (alias 'c')\n");
544 PrintF("stepi\n");
545 PrintF(" step one instruction (alias 'si')\n");
546 PrintF("print <register>\n");
547 PrintF(" print register content (alias 'p')\n");
548 PrintF(" use register name 'all' to print all registers\n");
549 PrintF(" add argument 'fp' to print register pair double values\n");
550 PrintF("printobject <register>\n");
551 PrintF(" print an object from a register (alias 'po')\n");
552 PrintF("flags\n");
553 PrintF(" print flags\n");
554 PrintF("stack [<words>]\n");
555 PrintF(" dump stack content, default dump 10 words)\n");
556 PrintF("mem <address> [<words>]\n");
557 PrintF(" dump memory content, default dump 10 words)\n");
558 PrintF("disasm [<instructions>]\n");
559 PrintF("disasm [<address/register>]\n");
560 PrintF("disasm [[<address/register>] <instructions>]\n");
561 PrintF(" disassemble code, default is 10 instructions\n");
562 PrintF(" from pc (alias 'di')\n");
563 PrintF("gdb\n");
564 PrintF(" enter gdb\n");
565 PrintF("break <address>\n");
566 PrintF(" set a break point on the address\n");
567 PrintF("del\n");
568 PrintF(" delete the breakpoint\n");
569 PrintF("trace (alias 't')\n");
570 PrintF(" toogle the tracing of all executed statements\n");
571 PrintF("stop feature:\n");
572 PrintF(" Description:\n");
573 PrintF(" Stops are debug instructions inserted by\n");
574 PrintF(" the Assembler::stop() function.\n");
575 PrintF(" When hitting a stop, the Simulator will\n");
576 PrintF(" stop and and give control to the ArmDebugger.\n");
577 PrintF(" The first %d stop codes are watched:\n",
578 Simulator::kNumOfWatchedStops);
579 PrintF(" - They can be enabled / disabled: the Simulator\n");
580 PrintF(" will / won't stop when hitting them.\n");
581 PrintF(" - The Simulator keeps track of how many times they \n");
582 PrintF(" are met. (See the info command.) Going over a\n");
583 PrintF(" disabled stop still increases its counter. \n");
584 PrintF(" Commands:\n");
585 PrintF(" stop info all/<code> : print infos about number <code>\n");
586 PrintF(" or all stop(s).\n");
587 PrintF(" stop enable/disable all/<code> : enables / disables\n");
588 PrintF(" all or number <code> stop(s)\n");
589 PrintF(" stop unstop\n");
590 PrintF(" ignore the stop instruction at the current location\n");
591 PrintF(" from now on\n");
592 } else {
593 PrintF("Unknown command: %s\n", cmd);
594 }
595 }
596 }
597
598 // Add all the breakpoints back to stop execution and enter the debugger
599 // shell when hit.
600 RedoBreakpoints();
601
602 #undef COMMAND_SIZE
603 #undef ARG_SIZE
604
605 #undef STR
606 #undef XSTR
607 }
608
609
ICacheMatch(void * one,void * two)610 static bool ICacheMatch(void* one, void* two) {
611 DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
612 DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
613 return one == two;
614 }
615
616
ICacheHash(void * key)617 static uint32_t ICacheHash(void* key) {
618 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
619 }
620
621
AllOnOnePage(uintptr_t start,int size)622 static bool AllOnOnePage(uintptr_t start, int size) {
623 intptr_t start_page = (start & ~CachePage::kPageMask);
624 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
625 return start_page == end_page;
626 }
627
628
set_last_debugger_input(char * input)629 void Simulator::set_last_debugger_input(char* input) {
630 DeleteArray(last_debugger_input_);
631 last_debugger_input_ = input;
632 }
633
634
FlushICache(v8::internal::HashMap * i_cache,void * start_addr,size_t size)635 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
636 void* start_addr,
637 size_t size) {
638 intptr_t start = reinterpret_cast<intptr_t>(start_addr);
639 int intra_line = (start & CachePage::kLineMask);
640 start -= intra_line;
641 size += intra_line;
642 size = ((size - 1) | CachePage::kLineMask) + 1;
643 int offset = (start & CachePage::kPageMask);
644 while (!AllOnOnePage(start, size - 1)) {
645 int bytes_to_flush = CachePage::kPageSize - offset;
646 FlushOnePage(i_cache, start, bytes_to_flush);
647 start += bytes_to_flush;
648 size -= bytes_to_flush;
649 DCHECK_EQ(0, start & CachePage::kPageMask);
650 offset = 0;
651 }
652 if (size != 0) {
653 FlushOnePage(i_cache, start, size);
654 }
655 }
656
657
GetCachePage(v8::internal::HashMap * i_cache,void * page)658 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
659 v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
660 ICacheHash(page),
661 true);
662 if (entry->value == NULL) {
663 CachePage* new_page = new CachePage();
664 entry->value = new_page;
665 }
666 return reinterpret_cast<CachePage*>(entry->value);
667 }
668
669
670 // Flush from start up to and not including start + size.
FlushOnePage(v8::internal::HashMap * i_cache,intptr_t start,int size)671 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
672 intptr_t start,
673 int size) {
674 DCHECK(size <= CachePage::kPageSize);
675 DCHECK(AllOnOnePage(start, size - 1));
676 DCHECK((start & CachePage::kLineMask) == 0);
677 DCHECK((size & CachePage::kLineMask) == 0);
678 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
679 int offset = (start & CachePage::kPageMask);
680 CachePage* cache_page = GetCachePage(i_cache, page);
681 char* valid_bytemap = cache_page->ValidityByte(offset);
682 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
683 }
684
685
CheckICache(v8::internal::HashMap * i_cache,Instruction * instr)686 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
687 Instruction* instr) {
688 intptr_t address = reinterpret_cast<intptr_t>(instr);
689 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
690 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
691 int offset = (address & CachePage::kPageMask);
692 CachePage* cache_page = GetCachePage(i_cache, page);
693 char* cache_valid_byte = cache_page->ValidityByte(offset);
694 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
695 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
696 if (cache_hit) {
697 // Check that the data in memory matches the contents of the I-cache.
698 CHECK_EQ(0,
699 memcmp(reinterpret_cast<void*>(instr),
700 cache_page->CachedData(offset), Instruction::kInstrSize));
701 } else {
702 // Cache miss. Load memory into the cache.
703 memcpy(cached_line, line, CachePage::kLineLength);
704 *cache_valid_byte = CachePage::LINE_VALID;
705 }
706 }
707
708
Initialize(Isolate * isolate)709 void Simulator::Initialize(Isolate* isolate) {
710 if (isolate->simulator_initialized()) return;
711 isolate->set_simulator_initialized(true);
712 ::v8::internal::ExternalReference::set_redirector(isolate,
713 &RedirectExternalReference);
714 }
715
716
Simulator(Isolate * isolate)717 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
718 i_cache_ = isolate_->simulator_i_cache();
719 if (i_cache_ == NULL) {
720 i_cache_ = new v8::internal::HashMap(&ICacheMatch);
721 isolate_->set_simulator_i_cache(i_cache_);
722 }
723 Initialize(isolate);
724 // Set up simulator support first. Some of this information is needed to
725 // setup the architecture state.
726 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
727 stack_ = reinterpret_cast<char*>(malloc(stack_size));
728 pc_modified_ = false;
729 icount_ = 0;
730 break_pc_ = NULL;
731 break_instr_ = 0;
732
733 // Set up architecture state.
734 // All registers are initialized to zero to start with.
735 for (int i = 0; i < num_registers; i++) {
736 registers_[i] = 0;
737 }
738 n_flag_ = false;
739 z_flag_ = false;
740 c_flag_ = false;
741 v_flag_ = false;
742
743 // Initializing VFP registers.
744 // All registers are initialized to zero to start with
745 // even though s_registers_ & d_registers_ share the same
746 // physical registers in the target.
747 for (int i = 0; i < num_d_registers * 2; i++) {
748 vfp_registers_[i] = 0;
749 }
750 n_flag_FPSCR_ = false;
751 z_flag_FPSCR_ = false;
752 c_flag_FPSCR_ = false;
753 v_flag_FPSCR_ = false;
754 FPSCR_rounding_mode_ = RN;
755 FPSCR_default_NaN_mode_ = false;
756
757 inv_op_vfp_flag_ = false;
758 div_zero_vfp_flag_ = false;
759 overflow_vfp_flag_ = false;
760 underflow_vfp_flag_ = false;
761 inexact_vfp_flag_ = false;
762
763 // The sp is initialized to point to the bottom (high address) of the
764 // allocated stack area. To be safe in potential stack underflows we leave
765 // some buffer below.
766 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
767 // The lr and pc are initialized to a known bad value that will cause an
768 // access violation if the simulator ever tries to execute it.
769 registers_[pc] = bad_lr;
770 registers_[lr] = bad_lr;
771 InitializeCoverage();
772
773 last_debugger_input_ = NULL;
774 }
775
776
~Simulator()777 Simulator::~Simulator() {
778 }
779
780
781 // When the generated code calls an external reference we need to catch that in
782 // the simulator. The external reference will be a function compiled for the
783 // host architecture. We need to call that function instead of trying to
784 // execute it with the simulator. We do that by redirecting the external
785 // reference to a svc (Supervisor Call) instruction that is handled by
786 // the simulator. We write the original destination of the jump just at a known
787 // offset from the svc instruction so the simulator knows what to call.
788 class Redirection {
789 public:
Redirection(void * external_function,ExternalReference::Type type)790 Redirection(void* external_function, ExternalReference::Type type)
791 : external_function_(external_function),
792 swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
793 type_(type),
794 next_(NULL) {
795 Isolate* isolate = Isolate::Current();
796 next_ = isolate->simulator_redirection();
797 Simulator::current(isolate)->
798 FlushICache(isolate->simulator_i_cache(),
799 reinterpret_cast<void*>(&swi_instruction_),
800 Instruction::kInstrSize);
801 isolate->set_simulator_redirection(this);
802 }
803
address_of_swi_instruction()804 void* address_of_swi_instruction() {
805 return reinterpret_cast<void*>(&swi_instruction_);
806 }
807
external_function()808 void* external_function() { return external_function_; }
type()809 ExternalReference::Type type() { return type_; }
810
Get(void * external_function,ExternalReference::Type type)811 static Redirection* Get(void* external_function,
812 ExternalReference::Type type) {
813 Isolate* isolate = Isolate::Current();
814 Redirection* current = isolate->simulator_redirection();
815 for (; current != NULL; current = current->next_) {
816 if (current->external_function_ == external_function) {
817 DCHECK_EQ(current->type(), type);
818 return current;
819 }
820 }
821 return new Redirection(external_function, type);
822 }
823
FromSwiInstruction(Instruction * swi_instruction)824 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
825 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
826 char* addr_of_redirection =
827 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
828 return reinterpret_cast<Redirection*>(addr_of_redirection);
829 }
830
ReverseRedirection(int32_t reg)831 static void* ReverseRedirection(int32_t reg) {
832 Redirection* redirection = FromSwiInstruction(
833 reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
834 return redirection->external_function();
835 }
836
837 private:
838 void* external_function_;
839 uint32_t swi_instruction_;
840 ExternalReference::Type type_;
841 Redirection* next_;
842 };
843
844
RedirectExternalReference(void * external_function,ExternalReference::Type type)845 void* Simulator::RedirectExternalReference(void* external_function,
846 ExternalReference::Type type) {
847 Redirection* redirection = Redirection::Get(external_function, type);
848 return redirection->address_of_swi_instruction();
849 }
850
851
852 // Get the active Simulator for the current thread.
current(Isolate * isolate)853 Simulator* Simulator::current(Isolate* isolate) {
854 v8::internal::Isolate::PerIsolateThreadData* isolate_data =
855 isolate->FindOrAllocatePerThreadDataForThisThread();
856 DCHECK(isolate_data != NULL);
857
858 Simulator* sim = isolate_data->simulator();
859 if (sim == NULL) {
860 // TODO(146): delete the simulator object when a thread/isolate goes away.
861 sim = new Simulator(isolate);
862 isolate_data->set_simulator(sim);
863 }
864 return sim;
865 }
866
867
868 // Sets the register in the architecture state. It will also deal with updating
869 // Simulator internal state for special registers such as PC.
set_register(int reg,int32_t value)870 void Simulator::set_register(int reg, int32_t value) {
871 DCHECK((reg >= 0) && (reg < num_registers));
872 if (reg == pc) {
873 pc_modified_ = true;
874 }
875 registers_[reg] = value;
876 }
877
878
879 // Get the register from the architecture state. This function does handle
880 // the special case of accessing the PC register.
get_register(int reg) const881 int32_t Simulator::get_register(int reg) const {
882 DCHECK((reg >= 0) && (reg < num_registers));
883 // Stupid code added to avoid bug in GCC.
884 // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
885 if (reg >= num_registers) return 0;
886 // End stupid code.
887 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
888 }
889
890
get_double_from_register_pair(int reg)891 double Simulator::get_double_from_register_pair(int reg) {
892 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
893
894 double dm_val = 0.0;
895 // Read the bits from the unsigned integer register_[] array
896 // into the double precision floating point value and return it.
897 char buffer[2 * sizeof(vfp_registers_[0])];
898 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0]));
899 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
900 return(dm_val);
901 }
902
903
set_register_pair_from_double(int reg,double * value)904 void Simulator::set_register_pair_from_double(int reg, double* value) {
905 DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
906 memcpy(registers_ + reg, value, sizeof(*value));
907 }
908
909
set_dw_register(int dreg,const int * dbl)910 void Simulator::set_dw_register(int dreg, const int* dbl) {
911 DCHECK((dreg >= 0) && (dreg < num_d_registers));
912 registers_[dreg] = dbl[0];
913 registers_[dreg + 1] = dbl[1];
914 }
915
916
get_d_register(int dreg,uint64_t * value)917 void Simulator::get_d_register(int dreg, uint64_t* value) {
918 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
919 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
920 }
921
922
set_d_register(int dreg,const uint64_t * value)923 void Simulator::set_d_register(int dreg, const uint64_t* value) {
924 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
925 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
926 }
927
928
get_d_register(int dreg,uint32_t * value)929 void Simulator::get_d_register(int dreg, uint32_t* value) {
930 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
931 memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
932 }
933
934
set_d_register(int dreg,const uint32_t * value)935 void Simulator::set_d_register(int dreg, const uint32_t* value) {
936 DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
937 memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
938 }
939
940
get_q_register(int qreg,uint64_t * value)941 void Simulator::get_q_register(int qreg, uint64_t* value) {
942 DCHECK((qreg >= 0) && (qreg < num_q_registers));
943 memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 2);
944 }
945
946
set_q_register(int qreg,const uint64_t * value)947 void Simulator::set_q_register(int qreg, const uint64_t* value) {
948 DCHECK((qreg >= 0) && (qreg < num_q_registers));
949 memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 2);
950 }
951
952
get_q_register(int qreg,uint32_t * value)953 void Simulator::get_q_register(int qreg, uint32_t* value) {
954 DCHECK((qreg >= 0) && (qreg < num_q_registers));
955 memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 4);
956 }
957
958
set_q_register(int qreg,const uint32_t * value)959 void Simulator::set_q_register(int qreg, const uint32_t* value) {
960 DCHECK((qreg >= 0) && (qreg < num_q_registers));
961 memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 4);
962 }
963
964
965 // Raw access to the PC register.
set_pc(int32_t value)966 void Simulator::set_pc(int32_t value) {
967 pc_modified_ = true;
968 registers_[pc] = value;
969 }
970
971
has_bad_pc() const972 bool Simulator::has_bad_pc() const {
973 return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
974 }
975
976
977 // Raw access to the PC register without the special adjustment when reading.
get_pc() const978 int32_t Simulator::get_pc() const {
979 return registers_[pc];
980 }
981
982
983 // Getting from and setting into VFP registers.
set_s_register(int sreg,unsigned int value)984 void Simulator::set_s_register(int sreg, unsigned int value) {
985 DCHECK((sreg >= 0) && (sreg < num_s_registers));
986 vfp_registers_[sreg] = value;
987 }
988
989
get_s_register(int sreg) const990 unsigned int Simulator::get_s_register(int sreg) const {
991 DCHECK((sreg >= 0) && (sreg < num_s_registers));
992 return vfp_registers_[sreg];
993 }
994
995
996 template<class InputType, int register_size>
SetVFPRegister(int reg_index,const InputType & value)997 void Simulator::SetVFPRegister(int reg_index, const InputType& value) {
998 DCHECK(reg_index >= 0);
999 if (register_size == 1) DCHECK(reg_index < num_s_registers);
1000 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
1001
1002 char buffer[register_size * sizeof(vfp_registers_[0])];
1003 memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
1004 memcpy(&vfp_registers_[reg_index * register_size], buffer,
1005 register_size * sizeof(vfp_registers_[0]));
1006 }
1007
1008
1009 template<class ReturnType, int register_size>
GetFromVFPRegister(int reg_index)1010 ReturnType Simulator::GetFromVFPRegister(int reg_index) {
1011 DCHECK(reg_index >= 0);
1012 if (register_size == 1) DCHECK(reg_index < num_s_registers);
1013 if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
1014
1015 ReturnType value = 0;
1016 char buffer[register_size * sizeof(vfp_registers_[0])];
1017 memcpy(buffer, &vfp_registers_[register_size * reg_index],
1018 register_size * sizeof(vfp_registers_[0]));
1019 memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
1020 return value;
1021 }
1022
1023
1024 // Runtime FP routines take:
1025 // - two double arguments
1026 // - one double argument and zero or one integer arguments.
1027 // All are consructed here from r0-r3 or d0, d1 and r0.
GetFpArgs(double * x,double * y,int32_t * z)1028 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1029 if (use_eabi_hardfloat()) {
1030 *x = get_double_from_d_register(0);
1031 *y = get_double_from_d_register(1);
1032 *z = get_register(0);
1033 } else {
1034 // Registers 0 and 1 -> x.
1035 *x = get_double_from_register_pair(0);
1036 // Register 2 and 3 -> y.
1037 *y = get_double_from_register_pair(2);
1038 // Register 2 -> z
1039 *z = get_register(2);
1040 }
1041 }
1042
1043
1044 // The return value is either in r0/r1 or d0.
SetFpResult(const double & result)1045 void Simulator::SetFpResult(const double& result) {
1046 if (use_eabi_hardfloat()) {
1047 char buffer[2 * sizeof(vfp_registers_[0])];
1048 memcpy(buffer, &result, sizeof(buffer));
1049 // Copy result to d0.
1050 memcpy(vfp_registers_, buffer, sizeof(buffer));
1051 } else {
1052 char buffer[2 * sizeof(registers_[0])];
1053 memcpy(buffer, &result, sizeof(buffer));
1054 // Copy result to r0 and r1.
1055 memcpy(registers_, buffer, sizeof(buffer));
1056 }
1057 }
1058
1059
TrashCallerSaveRegisters()1060 void Simulator::TrashCallerSaveRegisters() {
1061 // We don't trash the registers with the return value.
1062 registers_[2] = 0x50Bad4U;
1063 registers_[3] = 0x50Bad4U;
1064 registers_[12] = 0x50Bad4U;
1065 }
1066
1067
1068 // Some Operating Systems allow unaligned access on ARMv7 targets. We
1069 // assume that unaligned accesses are not allowed unless the v8 build system
1070 // defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
1071 // The following statements below describes the behavior of the ARM CPUs
1072 // that don't support unaligned access.
1073 // Some ARM platforms raise an interrupt on detecting unaligned access.
1074 // On others it does a funky rotation thing. For now we
1075 // simply disallow unaligned reads. Note that simulator runs have the runtime
1076 // system running directly on the host system and only generated code is
1077 // executed in the simulator. Since the host is typically IA32 we will not
1078 // get the correct ARM-like behaviour on unaligned accesses for those ARM
1079 // targets that don't support unaligned loads and stores.
1080
1081
ReadW(int32_t addr,Instruction * instr)1082 int Simulator::ReadW(int32_t addr, Instruction* instr) {
1083 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1084 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1085 return *ptr;
1086 } else {
1087 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1088 addr,
1089 reinterpret_cast<intptr_t>(instr));
1090 UNIMPLEMENTED();
1091 return 0;
1092 }
1093 }
1094
1095
WriteW(int32_t addr,int value,Instruction * instr)1096 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1097 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1098 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1099 *ptr = value;
1100 } else {
1101 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1102 addr,
1103 reinterpret_cast<intptr_t>(instr));
1104 UNIMPLEMENTED();
1105 }
1106 }
1107
1108
ReadHU(int32_t addr,Instruction * instr)1109 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1110 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1111 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1112 return *ptr;
1113 } else {
1114 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08"
1115 V8PRIxPTR "\n",
1116 addr,
1117 reinterpret_cast<intptr_t>(instr));
1118 UNIMPLEMENTED();
1119 return 0;
1120 }
1121 }
1122
1123
ReadH(int32_t addr,Instruction * instr)1124 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1125 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1126 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1127 return *ptr;
1128 } else {
1129 PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
1130 UNIMPLEMENTED();
1131 return 0;
1132 }
1133 }
1134
1135
WriteH(int32_t addr,uint16_t value,Instruction * instr)1136 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1137 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1138 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1139 *ptr = value;
1140 } else {
1141 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1142 V8PRIxPTR "\n",
1143 addr,
1144 reinterpret_cast<intptr_t>(instr));
1145 UNIMPLEMENTED();
1146 }
1147 }
1148
1149
WriteH(int32_t addr,int16_t value,Instruction * instr)1150 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1151 if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1152 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1153 *ptr = value;
1154 } else {
1155 PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1156 addr,
1157 reinterpret_cast<intptr_t>(instr));
1158 UNIMPLEMENTED();
1159 }
1160 }
1161
1162
ReadBU(int32_t addr)1163 uint8_t Simulator::ReadBU(int32_t addr) {
1164 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1165 return *ptr;
1166 }
1167
1168
ReadB(int32_t addr)1169 int8_t Simulator::ReadB(int32_t addr) {
1170 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1171 return *ptr;
1172 }
1173
1174
WriteB(int32_t addr,uint8_t value)1175 void Simulator::WriteB(int32_t addr, uint8_t value) {
1176 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1177 *ptr = value;
1178 }
1179
1180
WriteB(int32_t addr,int8_t value)1181 void Simulator::WriteB(int32_t addr, int8_t value) {
1182 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1183 *ptr = value;
1184 }
1185
1186
ReadDW(int32_t addr)1187 int32_t* Simulator::ReadDW(int32_t addr) {
1188 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1189 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1190 return ptr;
1191 } else {
1192 PrintF("Unaligned read at 0x%08x\n", addr);
1193 UNIMPLEMENTED();
1194 return 0;
1195 }
1196 }
1197
1198
WriteDW(int32_t addr,int32_t value1,int32_t value2)1199 void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1200 if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1201 int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1202 *ptr++ = value1;
1203 *ptr = value2;
1204 } else {
1205 PrintF("Unaligned write at 0x%08x\n", addr);
1206 UNIMPLEMENTED();
1207 }
1208 }
1209
1210
1211 // Returns the limit of the stack area to enable checking for stack overflows.
StackLimit() const1212 uintptr_t Simulator::StackLimit() const {
1213 // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1214 // pushing values.
1215 return reinterpret_cast<uintptr_t>(stack_) + 1024;
1216 }
1217
1218
1219 // Unsupported instructions use Format to print an error and stop execution.
Format(Instruction * instr,const char * format)1220 void Simulator::Format(Instruction* instr, const char* format) {
1221 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1222 reinterpret_cast<intptr_t>(instr), format);
1223 UNIMPLEMENTED();
1224 }
1225
1226
1227 // Checks if the current instruction should be executed based on its
1228 // condition bits.
ConditionallyExecute(Instruction * instr)1229 bool Simulator::ConditionallyExecute(Instruction* instr) {
1230 switch (instr->ConditionField()) {
1231 case eq: return z_flag_;
1232 case ne: return !z_flag_;
1233 case cs: return c_flag_;
1234 case cc: return !c_flag_;
1235 case mi: return n_flag_;
1236 case pl: return !n_flag_;
1237 case vs: return v_flag_;
1238 case vc: return !v_flag_;
1239 case hi: return c_flag_ && !z_flag_;
1240 case ls: return !c_flag_ || z_flag_;
1241 case ge: return n_flag_ == v_flag_;
1242 case lt: return n_flag_ != v_flag_;
1243 case gt: return !z_flag_ && (n_flag_ == v_flag_);
1244 case le: return z_flag_ || (n_flag_ != v_flag_);
1245 case al: return true;
1246 default: UNREACHABLE();
1247 }
1248 return false;
1249 }
1250
1251
1252 // Calculate and set the Negative and Zero flags.
SetNZFlags(int32_t val)1253 void Simulator::SetNZFlags(int32_t val) {
1254 n_flag_ = (val < 0);
1255 z_flag_ = (val == 0);
1256 }
1257
1258
1259 // Set the Carry flag.
SetCFlag(bool val)1260 void Simulator::SetCFlag(bool val) {
1261 c_flag_ = val;
1262 }
1263
1264
1265 // Set the oVerflow flag.
SetVFlag(bool val)1266 void Simulator::SetVFlag(bool val) {
1267 v_flag_ = val;
1268 }
1269
1270
1271 // Calculate C flag value for additions.
CarryFrom(int32_t left,int32_t right,int32_t carry)1272 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1273 uint32_t uleft = static_cast<uint32_t>(left);
1274 uint32_t uright = static_cast<uint32_t>(right);
1275 uint32_t urest = 0xffffffffU - uleft;
1276
1277 return (uright > urest) ||
1278 (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1279 }
1280
1281
1282 // Calculate C flag value for subtractions.
BorrowFrom(int32_t left,int32_t right)1283 bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1284 uint32_t uleft = static_cast<uint32_t>(left);
1285 uint32_t uright = static_cast<uint32_t>(right);
1286
1287 return (uright > uleft);
1288 }
1289
1290
1291 // Calculate V flag value for additions and subtractions.
OverflowFrom(int32_t alu_out,int32_t left,int32_t right,bool addition)1292 bool Simulator::OverflowFrom(int32_t alu_out,
1293 int32_t left, int32_t right, bool addition) {
1294 bool overflow;
1295 if (addition) {
1296 // operands have the same sign
1297 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1298 // and operands and result have different sign
1299 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1300 } else {
1301 // operands have different signs
1302 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1303 // and first operand and result have different signs
1304 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1305 }
1306 return overflow;
1307 }
1308
1309
1310 // Support for VFP comparisons.
Compute_FPSCR_Flags(double val1,double val2)1311 void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
1312 if (std::isnan(val1) || std::isnan(val2)) {
1313 n_flag_FPSCR_ = false;
1314 z_flag_FPSCR_ = false;
1315 c_flag_FPSCR_ = true;
1316 v_flag_FPSCR_ = true;
1317 // All non-NaN cases.
1318 } else if (val1 == val2) {
1319 n_flag_FPSCR_ = false;
1320 z_flag_FPSCR_ = true;
1321 c_flag_FPSCR_ = true;
1322 v_flag_FPSCR_ = false;
1323 } else if (val1 < val2) {
1324 n_flag_FPSCR_ = true;
1325 z_flag_FPSCR_ = false;
1326 c_flag_FPSCR_ = false;
1327 v_flag_FPSCR_ = false;
1328 } else {
1329 // Case when (val1 > val2).
1330 n_flag_FPSCR_ = false;
1331 z_flag_FPSCR_ = false;
1332 c_flag_FPSCR_ = true;
1333 v_flag_FPSCR_ = false;
1334 }
1335 }
1336
1337
Copy_FPSCR_to_APSR()1338 void Simulator::Copy_FPSCR_to_APSR() {
1339 n_flag_ = n_flag_FPSCR_;
1340 z_flag_ = z_flag_FPSCR_;
1341 c_flag_ = c_flag_FPSCR_;
1342 v_flag_ = v_flag_FPSCR_;
1343 }
1344
1345
1346 // Addressing Mode 1 - Data-processing operands:
1347 // Get the value based on the shifter_operand with register.
GetShiftRm(Instruction * instr,bool * carry_out)1348 int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
1349 ShiftOp shift = instr->ShiftField();
1350 int shift_amount = instr->ShiftAmountValue();
1351 int32_t result = get_register(instr->RmValue());
1352 if (instr->Bit(4) == 0) {
1353 // by immediate
1354 if ((shift == ROR) && (shift_amount == 0)) {
1355 UNIMPLEMENTED();
1356 return result;
1357 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1358 shift_amount = 32;
1359 }
1360 switch (shift) {
1361 case ASR: {
1362 if (shift_amount == 0) {
1363 if (result < 0) {
1364 result = 0xffffffff;
1365 *carry_out = true;
1366 } else {
1367 result = 0;
1368 *carry_out = false;
1369 }
1370 } else {
1371 result >>= (shift_amount - 1);
1372 *carry_out = (result & 1) == 1;
1373 result >>= 1;
1374 }
1375 break;
1376 }
1377
1378 case LSL: {
1379 if (shift_amount == 0) {
1380 *carry_out = c_flag_;
1381 } else {
1382 result <<= (shift_amount - 1);
1383 *carry_out = (result < 0);
1384 result <<= 1;
1385 }
1386 break;
1387 }
1388
1389 case LSR: {
1390 if (shift_amount == 0) {
1391 result = 0;
1392 *carry_out = c_flag_;
1393 } else {
1394 uint32_t uresult = static_cast<uint32_t>(result);
1395 uresult >>= (shift_amount - 1);
1396 *carry_out = (uresult & 1) == 1;
1397 uresult >>= 1;
1398 result = static_cast<int32_t>(uresult);
1399 }
1400 break;
1401 }
1402
1403 case ROR: {
1404 if (shift_amount == 0) {
1405 *carry_out = c_flag_;
1406 } else {
1407 uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1408 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1409 result = right | left;
1410 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1411 }
1412 break;
1413 }
1414
1415 default: {
1416 UNREACHABLE();
1417 break;
1418 }
1419 }
1420 } else {
1421 // by register
1422 int rs = instr->RsValue();
1423 shift_amount = get_register(rs) &0xff;
1424 switch (shift) {
1425 case ASR: {
1426 if (shift_amount == 0) {
1427 *carry_out = c_flag_;
1428 } else if (shift_amount < 32) {
1429 result >>= (shift_amount - 1);
1430 *carry_out = (result & 1) == 1;
1431 result >>= 1;
1432 } else {
1433 DCHECK(shift_amount >= 32);
1434 if (result < 0) {
1435 *carry_out = true;
1436 result = 0xffffffff;
1437 } else {
1438 *carry_out = false;
1439 result = 0;
1440 }
1441 }
1442 break;
1443 }
1444
1445 case LSL: {
1446 if (shift_amount == 0) {
1447 *carry_out = c_flag_;
1448 } else if (shift_amount < 32) {
1449 result <<= (shift_amount - 1);
1450 *carry_out = (result < 0);
1451 result <<= 1;
1452 } else if (shift_amount == 32) {
1453 *carry_out = (result & 1) == 1;
1454 result = 0;
1455 } else {
1456 DCHECK(shift_amount > 32);
1457 *carry_out = false;
1458 result = 0;
1459 }
1460 break;
1461 }
1462
1463 case LSR: {
1464 if (shift_amount == 0) {
1465 *carry_out = c_flag_;
1466 } else if (shift_amount < 32) {
1467 uint32_t uresult = static_cast<uint32_t>(result);
1468 uresult >>= (shift_amount - 1);
1469 *carry_out = (uresult & 1) == 1;
1470 uresult >>= 1;
1471 result = static_cast<int32_t>(uresult);
1472 } else if (shift_amount == 32) {
1473 *carry_out = (result < 0);
1474 result = 0;
1475 } else {
1476 *carry_out = false;
1477 result = 0;
1478 }
1479 break;
1480 }
1481
1482 case ROR: {
1483 if (shift_amount == 0) {
1484 *carry_out = c_flag_;
1485 } else {
1486 uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1487 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1488 result = right | left;
1489 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1490 }
1491 break;
1492 }
1493
1494 default: {
1495 UNREACHABLE();
1496 break;
1497 }
1498 }
1499 }
1500 return result;
1501 }
1502
1503
1504 // Addressing Mode 1 - Data-processing operands:
1505 // Get the value based on the shifter_operand with immediate.
GetImm(Instruction * instr,bool * carry_out)1506 int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
1507 int rotate = instr->RotateValue() * 2;
1508 int immed8 = instr->Immed8Value();
1509 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1510 *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1511 return imm;
1512 }
1513
1514
count_bits(int bit_vector)1515 static int count_bits(int bit_vector) {
1516 int count = 0;
1517 while (bit_vector != 0) {
1518 if ((bit_vector & 1) != 0) {
1519 count++;
1520 }
1521 bit_vector >>= 1;
1522 }
1523 return count;
1524 }
1525
1526
ProcessPU(Instruction * instr,int num_regs,int reg_size,intptr_t * start_address,intptr_t * end_address)1527 int32_t Simulator::ProcessPU(Instruction* instr,
1528 int num_regs,
1529 int reg_size,
1530 intptr_t* start_address,
1531 intptr_t* end_address) {
1532 int rn = instr->RnValue();
1533 int32_t rn_val = get_register(rn);
1534 switch (instr->PUField()) {
1535 case da_x: {
1536 UNIMPLEMENTED();
1537 break;
1538 }
1539 case ia_x: {
1540 *start_address = rn_val;
1541 *end_address = rn_val + (num_regs * reg_size) - reg_size;
1542 rn_val = rn_val + (num_regs * reg_size);
1543 break;
1544 }
1545 case db_x: {
1546 *start_address = rn_val - (num_regs * reg_size);
1547 *end_address = rn_val - reg_size;
1548 rn_val = *start_address;
1549 break;
1550 }
1551 case ib_x: {
1552 *start_address = rn_val + reg_size;
1553 *end_address = rn_val + (num_regs * reg_size);
1554 rn_val = *end_address;
1555 break;
1556 }
1557 default: {
1558 UNREACHABLE();
1559 break;
1560 }
1561 }
1562 return rn_val;
1563 }
1564
1565
1566 // Addressing Mode 4 - Load and Store Multiple
HandleRList(Instruction * instr,bool load)1567 void Simulator::HandleRList(Instruction* instr, bool load) {
1568 int rlist = instr->RlistValue();
1569 int num_regs = count_bits(rlist);
1570
1571 intptr_t start_address = 0;
1572 intptr_t end_address = 0;
1573 int32_t rn_val =
1574 ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
1575
1576 intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1577 // Catch null pointers a little earlier.
1578 DCHECK(start_address > 8191 || start_address < 0);
1579 int reg = 0;
1580 while (rlist != 0) {
1581 if ((rlist & 1) != 0) {
1582 if (load) {
1583 set_register(reg, *address);
1584 } else {
1585 *address = get_register(reg);
1586 }
1587 address += 1;
1588 }
1589 reg++;
1590 rlist >>= 1;
1591 }
1592 DCHECK(end_address == ((intptr_t)address) - 4);
1593 if (instr->HasW()) {
1594 set_register(instr->RnValue(), rn_val);
1595 }
1596 }
1597
1598
1599 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
HandleVList(Instruction * instr)1600 void Simulator::HandleVList(Instruction* instr) {
1601 VFPRegPrecision precision =
1602 (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1603 int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1604
1605 bool load = (instr->VLValue() == 0x1);
1606
1607 int vd;
1608 int num_regs;
1609 vd = instr->VFPDRegValue(precision);
1610 if (precision == kSinglePrecision) {
1611 num_regs = instr->Immed8Value();
1612 } else {
1613 num_regs = instr->Immed8Value() / 2;
1614 }
1615
1616 intptr_t start_address = 0;
1617 intptr_t end_address = 0;
1618 int32_t rn_val =
1619 ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1620
1621 intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1622 for (int reg = vd; reg < vd + num_regs; reg++) {
1623 if (precision == kSinglePrecision) {
1624 if (load) {
1625 set_s_register_from_sinteger(
1626 reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1627 } else {
1628 WriteW(reinterpret_cast<int32_t>(address),
1629 get_sinteger_from_s_register(reg), instr);
1630 }
1631 address += 1;
1632 } else {
1633 if (load) {
1634 int32_t data[] = {
1635 ReadW(reinterpret_cast<int32_t>(address), instr),
1636 ReadW(reinterpret_cast<int32_t>(address + 1), instr)
1637 };
1638 double d;
1639 memcpy(&d, data, 8);
1640 set_d_register_from_double(reg, d);
1641 } else {
1642 int32_t data[2];
1643 double d = get_double_from_d_register(reg);
1644 memcpy(data, &d, 8);
1645 WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
1646 WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
1647 }
1648 address += 2;
1649 }
1650 }
1651 DCHECK(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1652 if (instr->HasW()) {
1653 set_register(instr->RnValue(), rn_val);
1654 }
1655 }
1656
1657
1658 // Calls into the V8 runtime are based on this very simple interface.
1659 // Note: To be able to return two values from some calls the code in runtime.cc
1660 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1661 // 64-bit value. With the code below we assume that all runtime calls return
1662 // 64 bits of result. If they don't, the r1 result register contains a bogus
1663 // value, which is fine because it is caller-saved.
1664 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1665 int32_t arg1,
1666 int32_t arg2,
1667 int32_t arg3,
1668 int32_t arg4,
1669 int32_t arg5);
1670
1671 // These prototypes handle the four types of FP calls.
1672 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1673 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1674 typedef double (*SimulatorRuntimeFPCall)(double darg0);
1675 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1676
1677 // This signature supports direct call in to API function native callback
1678 // (refer to InvocationCallback in v8.h).
1679 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1680 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
1681
1682 // This signature supports direct call to accessor getter callback.
1683 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1684 typedef void (*SimulatorRuntimeProfilingGetterCall)(
1685 int32_t arg0, int32_t arg1, void* arg2);
1686
1687 // Software interrupt instructions are used by the simulator to call into the
1688 // C-based V8 runtime.
SoftwareInterrupt(Instruction * instr)1689 void Simulator::SoftwareInterrupt(Instruction* instr) {
1690 int svc = instr->SvcValue();
1691 switch (svc) {
1692 case kCallRtRedirected: {
1693 // Check if stack is aligned. Error if not aligned is reported below to
1694 // include information on the function called.
1695 bool stack_aligned =
1696 (get_register(sp)
1697 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1698 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1699 int32_t arg0 = get_register(r0);
1700 int32_t arg1 = get_register(r1);
1701 int32_t arg2 = get_register(r2);
1702 int32_t arg3 = get_register(r3);
1703 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1704 int32_t arg4 = stack_pointer[0];
1705 int32_t arg5 = stack_pointer[1];
1706 bool fp_call =
1707 (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1708 (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1709 (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1710 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1711 // This is dodgy but it works because the C entry stubs are never moved.
1712 // See comment in codegen-arm.cc and bug 1242173.
1713 int32_t saved_lr = get_register(lr);
1714 intptr_t external =
1715 reinterpret_cast<intptr_t>(redirection->external_function());
1716 if (fp_call) {
1717 double dval0, dval1; // one or two double parameters
1718 int32_t ival; // zero or one integer parameters
1719 int64_t iresult = 0; // integer return value
1720 double dresult = 0; // double return value
1721 GetFpArgs(&dval0, &dval1, &ival);
1722 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1723 SimulatorRuntimeCall generic_target =
1724 reinterpret_cast<SimulatorRuntimeCall>(external);
1725 switch (redirection->type()) {
1726 case ExternalReference::BUILTIN_FP_FP_CALL:
1727 case ExternalReference::BUILTIN_COMPARE_CALL:
1728 PrintF("Call to host function at %p with args %f, %f",
1729 FUNCTION_ADDR(generic_target), dval0, dval1);
1730 break;
1731 case ExternalReference::BUILTIN_FP_CALL:
1732 PrintF("Call to host function at %p with arg %f",
1733 FUNCTION_ADDR(generic_target), dval0);
1734 break;
1735 case ExternalReference::BUILTIN_FP_INT_CALL:
1736 PrintF("Call to host function at %p with args %f, %d",
1737 FUNCTION_ADDR(generic_target), dval0, ival);
1738 break;
1739 default:
1740 UNREACHABLE();
1741 break;
1742 }
1743 if (!stack_aligned) {
1744 PrintF(" with unaligned stack %08x\n", get_register(sp));
1745 }
1746 PrintF("\n");
1747 }
1748 CHECK(stack_aligned);
1749 switch (redirection->type()) {
1750 case ExternalReference::BUILTIN_COMPARE_CALL: {
1751 SimulatorRuntimeCompareCall target =
1752 reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1753 iresult = target(dval0, dval1);
1754 set_register(r0, static_cast<int32_t>(iresult));
1755 set_register(r1, static_cast<int32_t>(iresult >> 32));
1756 break;
1757 }
1758 case ExternalReference::BUILTIN_FP_FP_CALL: {
1759 SimulatorRuntimeFPFPCall target =
1760 reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1761 dresult = target(dval0, dval1);
1762 SetFpResult(dresult);
1763 break;
1764 }
1765 case ExternalReference::BUILTIN_FP_CALL: {
1766 SimulatorRuntimeFPCall target =
1767 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1768 dresult = target(dval0);
1769 SetFpResult(dresult);
1770 break;
1771 }
1772 case ExternalReference::BUILTIN_FP_INT_CALL: {
1773 SimulatorRuntimeFPIntCall target =
1774 reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1775 dresult = target(dval0, ival);
1776 SetFpResult(dresult);
1777 break;
1778 }
1779 default:
1780 UNREACHABLE();
1781 break;
1782 }
1783 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1784 switch (redirection->type()) {
1785 case ExternalReference::BUILTIN_COMPARE_CALL:
1786 PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1787 break;
1788 case ExternalReference::BUILTIN_FP_FP_CALL:
1789 case ExternalReference::BUILTIN_FP_CALL:
1790 case ExternalReference::BUILTIN_FP_INT_CALL:
1791 PrintF("Returned %f\n", dresult);
1792 break;
1793 default:
1794 UNREACHABLE();
1795 break;
1796 }
1797 }
1798 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1799 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1800 PrintF("Call to host function at %p args %08x",
1801 reinterpret_cast<void*>(external), arg0);
1802 if (!stack_aligned) {
1803 PrintF(" with unaligned stack %08x\n", get_register(sp));
1804 }
1805 PrintF("\n");
1806 }
1807 CHECK(stack_aligned);
1808 SimulatorRuntimeDirectApiCall target =
1809 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1810 target(arg0);
1811 } else if (
1812 redirection->type() == ExternalReference::PROFILING_API_CALL) {
1813 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1814 PrintF("Call to host function at %p args %08x %08x",
1815 reinterpret_cast<void*>(external), arg0, arg1);
1816 if (!stack_aligned) {
1817 PrintF(" with unaligned stack %08x\n", get_register(sp));
1818 }
1819 PrintF("\n");
1820 }
1821 CHECK(stack_aligned);
1822 SimulatorRuntimeProfilingApiCall target =
1823 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1824 target(arg0, Redirection::ReverseRedirection(arg1));
1825 } else if (
1826 redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1827 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1828 PrintF("Call to host function at %p args %08x %08x",
1829 reinterpret_cast<void*>(external), arg0, arg1);
1830 if (!stack_aligned) {
1831 PrintF(" with unaligned stack %08x\n", get_register(sp));
1832 }
1833 PrintF("\n");
1834 }
1835 CHECK(stack_aligned);
1836 SimulatorRuntimeDirectGetterCall target =
1837 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1838 target(arg0, arg1);
1839 } else if (
1840 redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1841 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1842 PrintF("Call to host function at %p args %08x %08x %08x",
1843 reinterpret_cast<void*>(external), arg0, arg1, arg2);
1844 if (!stack_aligned) {
1845 PrintF(" with unaligned stack %08x\n", get_register(sp));
1846 }
1847 PrintF("\n");
1848 }
1849 CHECK(stack_aligned);
1850 SimulatorRuntimeProfilingGetterCall target =
1851 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
1852 external);
1853 target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1854 } else {
1855 // builtin call.
1856 DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL);
1857 SimulatorRuntimeCall target =
1858 reinterpret_cast<SimulatorRuntimeCall>(external);
1859 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1860 PrintF(
1861 "Call to host function at %p "
1862 "args %08x, %08x, %08x, %08x, %08x, %08x",
1863 FUNCTION_ADDR(target),
1864 arg0,
1865 arg1,
1866 arg2,
1867 arg3,
1868 arg4,
1869 arg5);
1870 if (!stack_aligned) {
1871 PrintF(" with unaligned stack %08x\n", get_register(sp));
1872 }
1873 PrintF("\n");
1874 }
1875 CHECK(stack_aligned);
1876 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1877 int32_t lo_res = static_cast<int32_t>(result);
1878 int32_t hi_res = static_cast<int32_t>(result >> 32);
1879 if (::v8::internal::FLAG_trace_sim) {
1880 PrintF("Returned %08x\n", lo_res);
1881 }
1882 set_register(r0, lo_res);
1883 set_register(r1, hi_res);
1884 }
1885 set_register(lr, saved_lr);
1886 set_pc(get_register(lr));
1887 break;
1888 }
1889 case kBreakpoint: {
1890 ArmDebugger dbg(this);
1891 dbg.Debug();
1892 break;
1893 }
1894 // stop uses all codes greater than 1 << 23.
1895 default: {
1896 if (svc >= (1 << 23)) {
1897 uint32_t code = svc & kStopCodeMask;
1898 if (isWatchedStop(code)) {
1899 IncreaseStopCounter(code);
1900 }
1901 // Stop if it is enabled, otherwise go on jumping over the stop
1902 // and the message address.
1903 if (isEnabledStop(code)) {
1904 ArmDebugger dbg(this);
1905 dbg.Stop(instr);
1906 } else {
1907 set_pc(get_pc() + 2 * Instruction::kInstrSize);
1908 }
1909 } else {
1910 // This is not a valid svc code.
1911 UNREACHABLE();
1912 break;
1913 }
1914 }
1915 }
1916 }
1917
1918
canonicalizeNaN(double value)1919 double Simulator::canonicalizeNaN(double value) {
1920 return (FPSCR_default_NaN_mode_ && std::isnan(value)) ?
1921 FixedDoubleArray::canonical_not_the_hole_nan_as_double() : value;
1922 }
1923
1924
1925 // Stop helper functions.
isStopInstruction(Instruction * instr)1926 bool Simulator::isStopInstruction(Instruction* instr) {
1927 return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1928 }
1929
1930
isWatchedStop(uint32_t code)1931 bool Simulator::isWatchedStop(uint32_t code) {
1932 DCHECK(code <= kMaxStopCode);
1933 return code < kNumOfWatchedStops;
1934 }
1935
1936
isEnabledStop(uint32_t code)1937 bool Simulator::isEnabledStop(uint32_t code) {
1938 DCHECK(code <= kMaxStopCode);
1939 // Unwatched stops are always enabled.
1940 return !isWatchedStop(code) ||
1941 !(watched_stops_[code].count & kStopDisabledBit);
1942 }
1943
1944
EnableStop(uint32_t code)1945 void Simulator::EnableStop(uint32_t code) {
1946 DCHECK(isWatchedStop(code));
1947 if (!isEnabledStop(code)) {
1948 watched_stops_[code].count &= ~kStopDisabledBit;
1949 }
1950 }
1951
1952
DisableStop(uint32_t code)1953 void Simulator::DisableStop(uint32_t code) {
1954 DCHECK(isWatchedStop(code));
1955 if (isEnabledStop(code)) {
1956 watched_stops_[code].count |= kStopDisabledBit;
1957 }
1958 }
1959
1960
IncreaseStopCounter(uint32_t code)1961 void Simulator::IncreaseStopCounter(uint32_t code) {
1962 DCHECK(code <= kMaxStopCode);
1963 DCHECK(isWatchedStop(code));
1964 if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1965 PrintF("Stop counter for code %i has overflowed.\n"
1966 "Enabling this code and reseting the counter to 0.\n", code);
1967 watched_stops_[code].count = 0;
1968 EnableStop(code);
1969 } else {
1970 watched_stops_[code].count++;
1971 }
1972 }
1973
1974
1975 // Print a stop status.
PrintStopInfo(uint32_t code)1976 void Simulator::PrintStopInfo(uint32_t code) {
1977 DCHECK(code <= kMaxStopCode);
1978 if (!isWatchedStop(code)) {
1979 PrintF("Stop not watched.");
1980 } else {
1981 const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1982 int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1983 // Don't print the state of unused breakpoints.
1984 if (count != 0) {
1985 if (watched_stops_[code].desc) {
1986 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1987 code, code, state, count, watched_stops_[code].desc);
1988 } else {
1989 PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
1990 code, code, state, count);
1991 }
1992 }
1993 }
1994 }
1995
1996
1997 // Handle execution based on instruction types.
1998
1999 // Instruction types 0 and 1 are both rolled into one function because they
2000 // only differ in the handling of the shifter_operand.
DecodeType01(Instruction * instr)2001 void Simulator::DecodeType01(Instruction* instr) {
2002 int type = instr->TypeValue();
2003 if ((type == 0) && instr->IsSpecialType0()) {
2004 // multiply instruction or extra loads and stores
2005 if (instr->Bits(7, 4) == 9) {
2006 if (instr->Bit(24) == 0) {
2007 // Raw field decoding here. Multiply instructions have their Rd in
2008 // funny places.
2009 int rn = instr->RnValue();
2010 int rm = instr->RmValue();
2011 int rs = instr->RsValue();
2012 int32_t rs_val = get_register(rs);
2013 int32_t rm_val = get_register(rm);
2014 if (instr->Bit(23) == 0) {
2015 if (instr->Bit(21) == 0) {
2016 // The MUL instruction description (A 4.1.33) refers to Rd as being
2017 // the destination for the operation, but it confusingly uses the
2018 // Rn field to encode it.
2019 // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
2020 int rd = rn; // Remap the rn field to the Rd register.
2021 int32_t alu_out = rm_val * rs_val;
2022 set_register(rd, alu_out);
2023 if (instr->HasS()) {
2024 SetNZFlags(alu_out);
2025 }
2026 } else {
2027 int rd = instr->RdValue();
2028 int32_t acc_value = get_register(rd);
2029 if (instr->Bit(22) == 0) {
2030 // The MLA instruction description (A 4.1.28) refers to the order
2031 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
2032 // Rn field to encode the Rd register and the Rd field to encode
2033 // the Rn register.
2034 // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
2035 int32_t mul_out = rm_val * rs_val;
2036 int32_t result = acc_value + mul_out;
2037 set_register(rn, result);
2038 } else {
2039 // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
2040 int32_t mul_out = rm_val * rs_val;
2041 int32_t result = acc_value - mul_out;
2042 set_register(rn, result);
2043 }
2044 }
2045 } else {
2046 // The signed/long multiply instructions use the terms RdHi and RdLo
2047 // when referring to the target registers. They are mapped to the Rn
2048 // and Rd fields as follows:
2049 // RdLo == Rd
2050 // RdHi == Rn (This is confusingly stored in variable rd here
2051 // because the mul instruction from above uses the
2052 // Rn field to encode the Rd register. Good luck figuring
2053 // this out without reading the ARM instruction manual
2054 // at a very detailed level.)
2055 // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
2056 int rd_hi = rn; // Remap the rn field to the RdHi register.
2057 int rd_lo = instr->RdValue();
2058 int32_t hi_res = 0;
2059 int32_t lo_res = 0;
2060 if (instr->Bit(22) == 1) {
2061 int64_t left_op = static_cast<int32_t>(rm_val);
2062 int64_t right_op = static_cast<int32_t>(rs_val);
2063 uint64_t result = left_op * right_op;
2064 hi_res = static_cast<int32_t>(result >> 32);
2065 lo_res = static_cast<int32_t>(result & 0xffffffff);
2066 } else {
2067 // unsigned multiply
2068 uint64_t left_op = static_cast<uint32_t>(rm_val);
2069 uint64_t right_op = static_cast<uint32_t>(rs_val);
2070 uint64_t result = left_op * right_op;
2071 hi_res = static_cast<int32_t>(result >> 32);
2072 lo_res = static_cast<int32_t>(result & 0xffffffff);
2073 }
2074 set_register(rd_lo, lo_res);
2075 set_register(rd_hi, hi_res);
2076 if (instr->HasS()) {
2077 UNIMPLEMENTED();
2078 }
2079 }
2080 } else {
2081 UNIMPLEMENTED(); // Not used by V8.
2082 }
2083 } else {
2084 // extra load/store instructions
2085 int rd = instr->RdValue();
2086 int rn = instr->RnValue();
2087 int32_t rn_val = get_register(rn);
2088 int32_t addr = 0;
2089 if (instr->Bit(22) == 0) {
2090 int rm = instr->RmValue();
2091 int32_t rm_val = get_register(rm);
2092 switch (instr->PUField()) {
2093 case da_x: {
2094 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
2095 DCHECK(!instr->HasW());
2096 addr = rn_val;
2097 rn_val -= rm_val;
2098 set_register(rn, rn_val);
2099 break;
2100 }
2101 case ia_x: {
2102 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
2103 DCHECK(!instr->HasW());
2104 addr = rn_val;
2105 rn_val += rm_val;
2106 set_register(rn, rn_val);
2107 break;
2108 }
2109 case db_x: {
2110 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
2111 rn_val -= rm_val;
2112 addr = rn_val;
2113 if (instr->HasW()) {
2114 set_register(rn, rn_val);
2115 }
2116 break;
2117 }
2118 case ib_x: {
2119 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
2120 rn_val += rm_val;
2121 addr = rn_val;
2122 if (instr->HasW()) {
2123 set_register(rn, rn_val);
2124 }
2125 break;
2126 }
2127 default: {
2128 // The PU field is a 2-bit field.
2129 UNREACHABLE();
2130 break;
2131 }
2132 }
2133 } else {
2134 int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2135 switch (instr->PUField()) {
2136 case da_x: {
2137 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
2138 DCHECK(!instr->HasW());
2139 addr = rn_val;
2140 rn_val -= imm_val;
2141 set_register(rn, rn_val);
2142 break;
2143 }
2144 case ia_x: {
2145 // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
2146 DCHECK(!instr->HasW());
2147 addr = rn_val;
2148 rn_val += imm_val;
2149 set_register(rn, rn_val);
2150 break;
2151 }
2152 case db_x: {
2153 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
2154 rn_val -= imm_val;
2155 addr = rn_val;
2156 if (instr->HasW()) {
2157 set_register(rn, rn_val);
2158 }
2159 break;
2160 }
2161 case ib_x: {
2162 // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
2163 rn_val += imm_val;
2164 addr = rn_val;
2165 if (instr->HasW()) {
2166 set_register(rn, rn_val);
2167 }
2168 break;
2169 }
2170 default: {
2171 // The PU field is a 2-bit field.
2172 UNREACHABLE();
2173 break;
2174 }
2175 }
2176 }
2177 if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2178 DCHECK((rd % 2) == 0);
2179 if (instr->HasH()) {
2180 // The strd instruction.
2181 int32_t value1 = get_register(rd);
2182 int32_t value2 = get_register(rd+1);
2183 WriteDW(addr, value1, value2);
2184 } else {
2185 // The ldrd instruction.
2186 int* rn_data = ReadDW(addr);
2187 set_dw_register(rd, rn_data);
2188 }
2189 } else if (instr->HasH()) {
2190 if (instr->HasSign()) {
2191 if (instr->HasL()) {
2192 int16_t val = ReadH(addr, instr);
2193 set_register(rd, val);
2194 } else {
2195 int16_t val = get_register(rd);
2196 WriteH(addr, val, instr);
2197 }
2198 } else {
2199 if (instr->HasL()) {
2200 uint16_t val = ReadHU(addr, instr);
2201 set_register(rd, val);
2202 } else {
2203 uint16_t val = get_register(rd);
2204 WriteH(addr, val, instr);
2205 }
2206 }
2207 } else {
2208 // signed byte loads
2209 DCHECK(instr->HasSign());
2210 DCHECK(instr->HasL());
2211 int8_t val = ReadB(addr);
2212 set_register(rd, val);
2213 }
2214 return;
2215 }
2216 } else if ((type == 0) && instr->IsMiscType0()) {
2217 if (instr->Bits(22, 21) == 1) {
2218 int rm = instr->RmValue();
2219 switch (instr->BitField(7, 4)) {
2220 case BX:
2221 set_pc(get_register(rm));
2222 break;
2223 case BLX: {
2224 uint32_t old_pc = get_pc();
2225 set_pc(get_register(rm));
2226 set_register(lr, old_pc + Instruction::kInstrSize);
2227 break;
2228 }
2229 case BKPT: {
2230 ArmDebugger dbg(this);
2231 PrintF("Simulator hit BKPT.\n");
2232 dbg.Debug();
2233 break;
2234 }
2235 default:
2236 UNIMPLEMENTED();
2237 }
2238 } else if (instr->Bits(22, 21) == 3) {
2239 int rm = instr->RmValue();
2240 int rd = instr->RdValue();
2241 switch (instr->BitField(7, 4)) {
2242 case CLZ: {
2243 uint32_t bits = get_register(rm);
2244 int leading_zeros = 0;
2245 if (bits == 0) {
2246 leading_zeros = 32;
2247 } else {
2248 while ((bits & 0x80000000u) == 0) {
2249 bits <<= 1;
2250 leading_zeros++;
2251 }
2252 }
2253 set_register(rd, leading_zeros);
2254 break;
2255 }
2256 default:
2257 UNIMPLEMENTED();
2258 }
2259 } else {
2260 PrintF("%08x\n", instr->InstructionBits());
2261 UNIMPLEMENTED();
2262 }
2263 } else if ((type == 1) && instr->IsNopType1()) {
2264 // NOP.
2265 } else {
2266 int rd = instr->RdValue();
2267 int rn = instr->RnValue();
2268 int32_t rn_val = get_register(rn);
2269 int32_t shifter_operand = 0;
2270 bool shifter_carry_out = 0;
2271 if (type == 0) {
2272 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2273 } else {
2274 DCHECK(instr->TypeValue() == 1);
2275 shifter_operand = GetImm(instr, &shifter_carry_out);
2276 }
2277 int32_t alu_out;
2278
2279 switch (instr->OpcodeField()) {
2280 case AND: {
2281 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2282 // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2283 alu_out = rn_val & shifter_operand;
2284 set_register(rd, alu_out);
2285 if (instr->HasS()) {
2286 SetNZFlags(alu_out);
2287 SetCFlag(shifter_carry_out);
2288 }
2289 break;
2290 }
2291
2292 case EOR: {
2293 // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
2294 // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
2295 alu_out = rn_val ^ shifter_operand;
2296 set_register(rd, alu_out);
2297 if (instr->HasS()) {
2298 SetNZFlags(alu_out);
2299 SetCFlag(shifter_carry_out);
2300 }
2301 break;
2302 }
2303
2304 case SUB: {
2305 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2306 // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2307 alu_out = rn_val - shifter_operand;
2308 set_register(rd, alu_out);
2309 if (instr->HasS()) {
2310 SetNZFlags(alu_out);
2311 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2312 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2313 }
2314 break;
2315 }
2316
2317 case RSB: {
2318 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2319 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2320 alu_out = shifter_operand - rn_val;
2321 set_register(rd, alu_out);
2322 if (instr->HasS()) {
2323 SetNZFlags(alu_out);
2324 SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2325 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
2326 }
2327 break;
2328 }
2329
2330 case ADD: {
2331 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2332 // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2333 alu_out = rn_val + shifter_operand;
2334 set_register(rd, alu_out);
2335 if (instr->HasS()) {
2336 SetNZFlags(alu_out);
2337 SetCFlag(CarryFrom(rn_val, shifter_operand));
2338 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2339 }
2340 break;
2341 }
2342
2343 case ADC: {
2344 // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2345 // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2346 alu_out = rn_val + shifter_operand + GetCarry();
2347 set_register(rd, alu_out);
2348 if (instr->HasS()) {
2349 SetNZFlags(alu_out);
2350 SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2351 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2352 }
2353 break;
2354 }
2355
2356 case SBC: {
2357 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2358 Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2359 break;
2360 }
2361
2362 case RSC: {
2363 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2364 Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2365 break;
2366 }
2367
2368 case TST: {
2369 if (instr->HasS()) {
2370 // Format(instr, "tst'cond 'rn, 'shift_rm");
2371 // Format(instr, "tst'cond 'rn, 'imm");
2372 alu_out = rn_val & shifter_operand;
2373 SetNZFlags(alu_out);
2374 SetCFlag(shifter_carry_out);
2375 } else {
2376 // Format(instr, "movw'cond 'rd, 'imm").
2377 alu_out = instr->ImmedMovwMovtValue();
2378 set_register(rd, alu_out);
2379 }
2380 break;
2381 }
2382
2383 case TEQ: {
2384 if (instr->HasS()) {
2385 // Format(instr, "teq'cond 'rn, 'shift_rm");
2386 // Format(instr, "teq'cond 'rn, 'imm");
2387 alu_out = rn_val ^ shifter_operand;
2388 SetNZFlags(alu_out);
2389 SetCFlag(shifter_carry_out);
2390 } else {
2391 // Other instructions matching this pattern are handled in the
2392 // miscellaneous instructions part above.
2393 UNREACHABLE();
2394 }
2395 break;
2396 }
2397
2398 case CMP: {
2399 if (instr->HasS()) {
2400 // Format(instr, "cmp'cond 'rn, 'shift_rm");
2401 // Format(instr, "cmp'cond 'rn, 'imm");
2402 alu_out = rn_val - shifter_operand;
2403 SetNZFlags(alu_out);
2404 SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2405 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2406 } else {
2407 // Format(instr, "movt'cond 'rd, 'imm").
2408 alu_out = (get_register(rd) & 0xffff) |
2409 (instr->ImmedMovwMovtValue() << 16);
2410 set_register(rd, alu_out);
2411 }
2412 break;
2413 }
2414
2415 case CMN: {
2416 if (instr->HasS()) {
2417 // Format(instr, "cmn'cond 'rn, 'shift_rm");
2418 // Format(instr, "cmn'cond 'rn, 'imm");
2419 alu_out = rn_val + shifter_operand;
2420 SetNZFlags(alu_out);
2421 SetCFlag(CarryFrom(rn_val, shifter_operand));
2422 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2423 } else {
2424 // Other instructions matching this pattern are handled in the
2425 // miscellaneous instructions part above.
2426 UNREACHABLE();
2427 }
2428 break;
2429 }
2430
2431 case ORR: {
2432 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2433 // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2434 alu_out = rn_val | shifter_operand;
2435 set_register(rd, alu_out);
2436 if (instr->HasS()) {
2437 SetNZFlags(alu_out);
2438 SetCFlag(shifter_carry_out);
2439 }
2440 break;
2441 }
2442
2443 case MOV: {
2444 // Format(instr, "mov'cond's 'rd, 'shift_rm");
2445 // Format(instr, "mov'cond's 'rd, 'imm");
2446 alu_out = shifter_operand;
2447 set_register(rd, alu_out);
2448 if (instr->HasS()) {
2449 SetNZFlags(alu_out);
2450 SetCFlag(shifter_carry_out);
2451 }
2452 break;
2453 }
2454
2455 case BIC: {
2456 // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
2457 // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
2458 alu_out = rn_val & ~shifter_operand;
2459 set_register(rd, alu_out);
2460 if (instr->HasS()) {
2461 SetNZFlags(alu_out);
2462 SetCFlag(shifter_carry_out);
2463 }
2464 break;
2465 }
2466
2467 case MVN: {
2468 // Format(instr, "mvn'cond's 'rd, 'shift_rm");
2469 // Format(instr, "mvn'cond's 'rd, 'imm");
2470 alu_out = ~shifter_operand;
2471 set_register(rd, alu_out);
2472 if (instr->HasS()) {
2473 SetNZFlags(alu_out);
2474 SetCFlag(shifter_carry_out);
2475 }
2476 break;
2477 }
2478
2479 default: {
2480 UNREACHABLE();
2481 break;
2482 }
2483 }
2484 }
2485 }
2486
2487
DecodeType2(Instruction * instr)2488 void Simulator::DecodeType2(Instruction* instr) {
2489 int rd = instr->RdValue();
2490 int rn = instr->RnValue();
2491 int32_t rn_val = get_register(rn);
2492 int32_t im_val = instr->Offset12Value();
2493 int32_t addr = 0;
2494 switch (instr->PUField()) {
2495 case da_x: {
2496 // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
2497 DCHECK(!instr->HasW());
2498 addr = rn_val;
2499 rn_val -= im_val;
2500 set_register(rn, rn_val);
2501 break;
2502 }
2503 case ia_x: {
2504 // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
2505 DCHECK(!instr->HasW());
2506 addr = rn_val;
2507 rn_val += im_val;
2508 set_register(rn, rn_val);
2509 break;
2510 }
2511 case db_x: {
2512 // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
2513 rn_val -= im_val;
2514 addr = rn_val;
2515 if (instr->HasW()) {
2516 set_register(rn, rn_val);
2517 }
2518 break;
2519 }
2520 case ib_x: {
2521 // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
2522 rn_val += im_val;
2523 addr = rn_val;
2524 if (instr->HasW()) {
2525 set_register(rn, rn_val);
2526 }
2527 break;
2528 }
2529 default: {
2530 UNREACHABLE();
2531 break;
2532 }
2533 }
2534 if (instr->HasB()) {
2535 if (instr->HasL()) {
2536 byte val = ReadBU(addr);
2537 set_register(rd, val);
2538 } else {
2539 byte val = get_register(rd);
2540 WriteB(addr, val);
2541 }
2542 } else {
2543 if (instr->HasL()) {
2544 set_register(rd, ReadW(addr, instr));
2545 } else {
2546 WriteW(addr, get_register(rd), instr);
2547 }
2548 }
2549 }
2550
2551
DecodeType3(Instruction * instr)2552 void Simulator::DecodeType3(Instruction* instr) {
2553 int rd = instr->RdValue();
2554 int rn = instr->RnValue();
2555 int32_t rn_val = get_register(rn);
2556 bool shifter_carry_out = 0;
2557 int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2558 int32_t addr = 0;
2559 switch (instr->PUField()) {
2560 case da_x: {
2561 DCHECK(!instr->HasW());
2562 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
2563 UNIMPLEMENTED();
2564 break;
2565 }
2566 case ia_x: {
2567 if (instr->Bit(4) == 0) {
2568 // Memop.
2569 } else {
2570 if (instr->Bit(5) == 0) {
2571 switch (instr->Bits(22, 21)) {
2572 case 0:
2573 if (instr->Bit(20) == 0) {
2574 if (instr->Bit(6) == 0) {
2575 // Pkhbt.
2576 uint32_t rn_val = get_register(rn);
2577 uint32_t rm_val = get_register(instr->RmValue());
2578 int32_t shift = instr->Bits(11, 7);
2579 rm_val <<= shift;
2580 set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2581 } else {
2582 // Pkhtb.
2583 uint32_t rn_val = get_register(rn);
2584 int32_t rm_val = get_register(instr->RmValue());
2585 int32_t shift = instr->Bits(11, 7);
2586 if (shift == 0) {
2587 shift = 32;
2588 }
2589 rm_val >>= shift;
2590 set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2591 }
2592 } else {
2593 UNIMPLEMENTED();
2594 }
2595 break;
2596 case 1:
2597 UNIMPLEMENTED();
2598 break;
2599 case 2:
2600 UNIMPLEMENTED();
2601 break;
2602 case 3: {
2603 // Usat.
2604 int32_t sat_pos = instr->Bits(20, 16);
2605 int32_t sat_val = (1 << sat_pos) - 1;
2606 int32_t shift = instr->Bits(11, 7);
2607 int32_t shift_type = instr->Bit(6);
2608 int32_t rm_val = get_register(instr->RmValue());
2609 if (shift_type == 0) { // LSL
2610 rm_val <<= shift;
2611 } else { // ASR
2612 rm_val >>= shift;
2613 }
2614 // If saturation occurs, the Q flag should be set in the CPSR.
2615 // There is no Q flag yet, and no instruction (MRS) to read the
2616 // CPSR directly.
2617 if (rm_val > sat_val) {
2618 rm_val = sat_val;
2619 } else if (rm_val < 0) {
2620 rm_val = 0;
2621 }
2622 set_register(rd, rm_val);
2623 break;
2624 }
2625 }
2626 } else {
2627 switch (instr->Bits(22, 21)) {
2628 case 0:
2629 UNIMPLEMENTED();
2630 break;
2631 case 1:
2632 UNIMPLEMENTED();
2633 break;
2634 case 2:
2635 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2636 if (instr->Bits(19, 16) == 0xF) {
2637 // Uxtb16.
2638 uint32_t rm_val = get_register(instr->RmValue());
2639 int32_t rotate = instr->Bits(11, 10);
2640 switch (rotate) {
2641 case 0:
2642 break;
2643 case 1:
2644 rm_val = (rm_val >> 8) | (rm_val << 24);
2645 break;
2646 case 2:
2647 rm_val = (rm_val >> 16) | (rm_val << 16);
2648 break;
2649 case 3:
2650 rm_val = (rm_val >> 24) | (rm_val << 8);
2651 break;
2652 }
2653 set_register(rd,
2654 (rm_val & 0xFF) | (rm_val & 0xFF0000));
2655 } else {
2656 UNIMPLEMENTED();
2657 }
2658 } else {
2659 UNIMPLEMENTED();
2660 }
2661 break;
2662 case 3:
2663 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2664 if (instr->Bits(19, 16) == 0xF) {
2665 // Uxtb.
2666 uint32_t rm_val = get_register(instr->RmValue());
2667 int32_t rotate = instr->Bits(11, 10);
2668 switch (rotate) {
2669 case 0:
2670 break;
2671 case 1:
2672 rm_val = (rm_val >> 8) | (rm_val << 24);
2673 break;
2674 case 2:
2675 rm_val = (rm_val >> 16) | (rm_val << 16);
2676 break;
2677 case 3:
2678 rm_val = (rm_val >> 24) | (rm_val << 8);
2679 break;
2680 }
2681 set_register(rd, (rm_val & 0xFF));
2682 } else {
2683 // Uxtab.
2684 uint32_t rn_val = get_register(rn);
2685 uint32_t rm_val = get_register(instr->RmValue());
2686 int32_t rotate = instr->Bits(11, 10);
2687 switch (rotate) {
2688 case 0:
2689 break;
2690 case 1:
2691 rm_val = (rm_val >> 8) | (rm_val << 24);
2692 break;
2693 case 2:
2694 rm_val = (rm_val >> 16) | (rm_val << 16);
2695 break;
2696 case 3:
2697 rm_val = (rm_val >> 24) | (rm_val << 8);
2698 break;
2699 }
2700 set_register(rd, rn_val + (rm_val & 0xFF));
2701 }
2702 } else {
2703 UNIMPLEMENTED();
2704 }
2705 break;
2706 }
2707 }
2708 return;
2709 }
2710 break;
2711 }
2712 case db_x: {
2713 if (FLAG_enable_sudiv) {
2714 if (instr->Bits(5, 4) == 0x1) {
2715 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2716 // (s/u)div (in V8 notation matching ARM ISA format) rn = rm/rs
2717 // Format(instr, "'(s/u)div'cond'b 'rn, 'rm, 'rs);
2718 int rm = instr->RmValue();
2719 int32_t rm_val = get_register(rm);
2720 int rs = instr->RsValue();
2721 int32_t rs_val = get_register(rs);
2722 int32_t ret_val = 0;
2723 DCHECK(rs_val != 0);
2724 // udiv
2725 if (instr->Bit(21) == 0x1) {
2726 ret_val = static_cast<int32_t>(static_cast<uint32_t>(rm_val) /
2727 static_cast<uint32_t>(rs_val));
2728 } else if ((rm_val == kMinInt) && (rs_val == -1)) {
2729 ret_val = kMinInt;
2730 } else {
2731 ret_val = rm_val / rs_val;
2732 }
2733 set_register(rn, ret_val);
2734 return;
2735 }
2736 }
2737 }
2738 // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
2739 addr = rn_val - shifter_operand;
2740 if (instr->HasW()) {
2741 set_register(rn, addr);
2742 }
2743 break;
2744 }
2745 case ib_x: {
2746 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2747 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
2748 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2749 uint32_t msbit = widthminus1 + lsbit;
2750 if (msbit <= 31) {
2751 if (instr->Bit(22)) {
2752 // ubfx - unsigned bitfield extract.
2753 uint32_t rm_val =
2754 static_cast<uint32_t>(get_register(instr->RmValue()));
2755 uint32_t extr_val = rm_val << (31 - msbit);
2756 extr_val = extr_val >> (31 - widthminus1);
2757 set_register(instr->RdValue(), extr_val);
2758 } else {
2759 // sbfx - signed bitfield extract.
2760 int32_t rm_val = get_register(instr->RmValue());
2761 int32_t extr_val = rm_val << (31 - msbit);
2762 extr_val = extr_val >> (31 - widthminus1);
2763 set_register(instr->RdValue(), extr_val);
2764 }
2765 } else {
2766 UNREACHABLE();
2767 }
2768 return;
2769 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2770 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2771 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
2772 if (msbit >= lsbit) {
2773 // bfc or bfi - bitfield clear/insert.
2774 uint32_t rd_val =
2775 static_cast<uint32_t>(get_register(instr->RdValue()));
2776 uint32_t bitcount = msbit - lsbit + 1;
2777 uint32_t mask = 0xffffffffu >> (32 - bitcount);
2778 rd_val &= ~(mask << lsbit);
2779 if (instr->RmValue() != 15) {
2780 // bfi - bitfield insert.
2781 uint32_t rm_val =
2782 static_cast<uint32_t>(get_register(instr->RmValue()));
2783 rm_val &= mask;
2784 rd_val |= rm_val << lsbit;
2785 }
2786 set_register(instr->RdValue(), rd_val);
2787 } else {
2788 UNREACHABLE();
2789 }
2790 return;
2791 } else {
2792 // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
2793 addr = rn_val + shifter_operand;
2794 if (instr->HasW()) {
2795 set_register(rn, addr);
2796 }
2797 }
2798 break;
2799 }
2800 default: {
2801 UNREACHABLE();
2802 break;
2803 }
2804 }
2805 if (instr->HasB()) {
2806 if (instr->HasL()) {
2807 uint8_t byte = ReadB(addr);
2808 set_register(rd, byte);
2809 } else {
2810 uint8_t byte = get_register(rd);
2811 WriteB(addr, byte);
2812 }
2813 } else {
2814 if (instr->HasL()) {
2815 set_register(rd, ReadW(addr, instr));
2816 } else {
2817 WriteW(addr, get_register(rd), instr);
2818 }
2819 }
2820 }
2821
2822
DecodeType4(Instruction * instr)2823 void Simulator::DecodeType4(Instruction* instr) {
2824 DCHECK(instr->Bit(22) == 0); // only allowed to be set in privileged mode
2825 if (instr->HasL()) {
2826 // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
2827 HandleRList(instr, true);
2828 } else {
2829 // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
2830 HandleRList(instr, false);
2831 }
2832 }
2833
2834
DecodeType5(Instruction * instr)2835 void Simulator::DecodeType5(Instruction* instr) {
2836 // Format(instr, "b'l'cond 'target");
2837 int off = (instr->SImmed24Value() << 2);
2838 intptr_t pc_address = get_pc();
2839 if (instr->HasLink()) {
2840 set_register(lr, pc_address + Instruction::kInstrSize);
2841 }
2842 int pc_reg = get_register(pc);
2843 set_pc(pc_reg + off);
2844 }
2845
2846
DecodeType6(Instruction * instr)2847 void Simulator::DecodeType6(Instruction* instr) {
2848 DecodeType6CoprocessorIns(instr);
2849 }
2850
2851
DecodeType7(Instruction * instr)2852 void Simulator::DecodeType7(Instruction* instr) {
2853 if (instr->Bit(24) == 1) {
2854 SoftwareInterrupt(instr);
2855 } else {
2856 DecodeTypeVFP(instr);
2857 }
2858 }
2859
2860
2861 // void Simulator::DecodeTypeVFP(Instruction* instr)
2862 // The Following ARMv7 VFPv instructions are currently supported.
2863 // vmov :Sn = Rt
2864 // vmov :Rt = Sn
2865 // vcvt: Dd = Sm
2866 // vcvt: Sd = Dm
2867 // vcvt.f64.s32 Dd, Dd, #<fbits>
2868 // Dd = vabs(Dm)
2869 // Dd = vneg(Dm)
2870 // Dd = vadd(Dn, Dm)
2871 // Dd = vsub(Dn, Dm)
2872 // Dd = vmul(Dn, Dm)
2873 // Dd = vdiv(Dn, Dm)
2874 // vcmp(Dd, Dm)
2875 // vmrs
2876 // Dd = vsqrt(Dm)
DecodeTypeVFP(Instruction * instr)2877 void Simulator::DecodeTypeVFP(Instruction* instr) {
2878 DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2879 DCHECK(instr->Bits(11, 9) == 0x5);
2880
2881 // Obtain double precision register codes.
2882 int vm = instr->VFPMRegValue(kDoublePrecision);
2883 int vd = instr->VFPDRegValue(kDoublePrecision);
2884 int vn = instr->VFPNRegValue(kDoublePrecision);
2885
2886 if (instr->Bit(4) == 0) {
2887 if (instr->Opc1Value() == 0x7) {
2888 // Other data processing instructions
2889 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2890 // vmov register to register.
2891 if (instr->SzValue() == 0x1) {
2892 int m = instr->VFPMRegValue(kDoublePrecision);
2893 int d = instr->VFPDRegValue(kDoublePrecision);
2894 set_d_register_from_double(d, get_double_from_d_register(m));
2895 } else {
2896 int m = instr->VFPMRegValue(kSinglePrecision);
2897 int d = instr->VFPDRegValue(kSinglePrecision);
2898 set_s_register_from_float(d, get_float_from_s_register(m));
2899 }
2900 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2901 // vabs
2902 double dm_value = get_double_from_d_register(vm);
2903 double dd_value = std::fabs(dm_value);
2904 dd_value = canonicalizeNaN(dd_value);
2905 set_d_register_from_double(vd, dd_value);
2906 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2907 // vneg
2908 double dm_value = get_double_from_d_register(vm);
2909 double dd_value = -dm_value;
2910 dd_value = canonicalizeNaN(dd_value);
2911 set_d_register_from_double(vd, dd_value);
2912 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2913 DecodeVCVTBetweenDoubleAndSingle(instr);
2914 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2915 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2916 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
2917 (instr->Bit(8) == 1)) {
2918 // vcvt.f64.s32 Dd, Dd, #<fbits>
2919 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
2920 int fixed_value = get_sinteger_from_s_register(vd * 2);
2921 double divide = 1 << fraction_bits;
2922 set_d_register_from_double(vd, fixed_value / divide);
2923 } else if (((instr->Opc2Value() >> 1) == 0x6) &&
2924 (instr->Opc3Value() & 0x1)) {
2925 DecodeVCVTBetweenFloatingPointAndInteger(instr);
2926 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2927 (instr->Opc3Value() & 0x1)) {
2928 DecodeVCMP(instr);
2929 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2930 // vsqrt
2931 double dm_value = get_double_from_d_register(vm);
2932 double dd_value = std::sqrt(dm_value);
2933 dd_value = canonicalizeNaN(dd_value);
2934 set_d_register_from_double(vd, dd_value);
2935 } else if (instr->Opc3Value() == 0x0) {
2936 // vmov immediate.
2937 if (instr->SzValue() == 0x1) {
2938 set_d_register_from_double(vd, instr->DoubleImmedVmov());
2939 } else {
2940 UNREACHABLE(); // Not used by v8.
2941 }
2942 } else {
2943 UNREACHABLE(); // Not used by V8.
2944 }
2945 } else if (instr->Opc1Value() == 0x3) {
2946 if (instr->SzValue() != 0x1) {
2947 UNREACHABLE(); // Not used by V8.
2948 }
2949
2950 if (instr->Opc3Value() & 0x1) {
2951 // vsub
2952 double dn_value = get_double_from_d_register(vn);
2953 double dm_value = get_double_from_d_register(vm);
2954 double dd_value = dn_value - dm_value;
2955 dd_value = canonicalizeNaN(dd_value);
2956 set_d_register_from_double(vd, dd_value);
2957 } else {
2958 // vadd
2959 double dn_value = get_double_from_d_register(vn);
2960 double dm_value = get_double_from_d_register(vm);
2961 double dd_value = dn_value + dm_value;
2962 dd_value = canonicalizeNaN(dd_value);
2963 set_d_register_from_double(vd, dd_value);
2964 }
2965 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2966 // vmul
2967 if (instr->SzValue() != 0x1) {
2968 UNREACHABLE(); // Not used by V8.
2969 }
2970
2971 double dn_value = get_double_from_d_register(vn);
2972 double dm_value = get_double_from_d_register(vm);
2973 double dd_value = dn_value * dm_value;
2974 dd_value = canonicalizeNaN(dd_value);
2975 set_d_register_from_double(vd, dd_value);
2976 } else if ((instr->Opc1Value() == 0x0)) {
2977 // vmla, vmls
2978 const bool is_vmls = (instr->Opc3Value() & 0x1);
2979
2980 if (instr->SzValue() != 0x1) {
2981 UNREACHABLE(); // Not used by V8.
2982 }
2983
2984 const double dd_val = get_double_from_d_register(vd);
2985 const double dn_val = get_double_from_d_register(vn);
2986 const double dm_val = get_double_from_d_register(vm);
2987
2988 // Note: we do the mul and add/sub in separate steps to avoid getting a
2989 // result with too high precision.
2990 set_d_register_from_double(vd, dn_val * dm_val);
2991 if (is_vmls) {
2992 set_d_register_from_double(
2993 vd,
2994 canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
2995 } else {
2996 set_d_register_from_double(
2997 vd,
2998 canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
2999 }
3000 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3001 // vdiv
3002 if (instr->SzValue() != 0x1) {
3003 UNREACHABLE(); // Not used by V8.
3004 }
3005
3006 double dn_value = get_double_from_d_register(vn);
3007 double dm_value = get_double_from_d_register(vm);
3008 double dd_value = dn_value / dm_value;
3009 div_zero_vfp_flag_ = (dm_value == 0);
3010 dd_value = canonicalizeNaN(dd_value);
3011 set_d_register_from_double(vd, dd_value);
3012 } else {
3013 UNIMPLEMENTED(); // Not used by V8.
3014 }
3015 } else {
3016 if ((instr->VCValue() == 0x0) &&
3017 (instr->VAValue() == 0x0)) {
3018 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3019 } else if ((instr->VLValue() == 0x0) &&
3020 (instr->VCValue() == 0x1) &&
3021 (instr->Bit(23) == 0x0)) {
3022 // vmov (ARM core register to scalar)
3023 int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3024 double dd_value = get_double_from_d_register(vd);
3025 int32_t data[2];
3026 memcpy(data, &dd_value, 8);
3027 data[instr->Bit(21)] = get_register(instr->RtValue());
3028 memcpy(&dd_value, data, 8);
3029 set_d_register_from_double(vd, dd_value);
3030 } else if ((instr->VLValue() == 0x1) &&
3031 (instr->VCValue() == 0x1) &&
3032 (instr->Bit(23) == 0x0)) {
3033 // vmov (scalar to ARM core register)
3034 int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3035 double dn_value = get_double_from_d_register(vn);
3036 int32_t data[2];
3037 memcpy(data, &dn_value, 8);
3038 set_register(instr->RtValue(), data[instr->Bit(21)]);
3039 } else if ((instr->VLValue() == 0x1) &&
3040 (instr->VCValue() == 0x0) &&
3041 (instr->VAValue() == 0x7) &&
3042 (instr->Bits(19, 16) == 0x1)) {
3043 // vmrs
3044 uint32_t rt = instr->RtValue();
3045 if (rt == 0xF) {
3046 Copy_FPSCR_to_APSR();
3047 } else {
3048 // Emulate FPSCR from the Simulator flags.
3049 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3050 (z_flag_FPSCR_ << 30) |
3051 (c_flag_FPSCR_ << 29) |
3052 (v_flag_FPSCR_ << 28) |
3053 (FPSCR_default_NaN_mode_ << 25) |
3054 (inexact_vfp_flag_ << 4) |
3055 (underflow_vfp_flag_ << 3) |
3056 (overflow_vfp_flag_ << 2) |
3057 (div_zero_vfp_flag_ << 1) |
3058 (inv_op_vfp_flag_ << 0) |
3059 (FPSCR_rounding_mode_);
3060 set_register(rt, fpscr);
3061 }
3062 } else if ((instr->VLValue() == 0x0) &&
3063 (instr->VCValue() == 0x0) &&
3064 (instr->VAValue() == 0x7) &&
3065 (instr->Bits(19, 16) == 0x1)) {
3066 // vmsr
3067 uint32_t rt = instr->RtValue();
3068 if (rt == pc) {
3069 UNREACHABLE();
3070 } else {
3071 uint32_t rt_value = get_register(rt);
3072 n_flag_FPSCR_ = (rt_value >> 31) & 1;
3073 z_flag_FPSCR_ = (rt_value >> 30) & 1;
3074 c_flag_FPSCR_ = (rt_value >> 29) & 1;
3075 v_flag_FPSCR_ = (rt_value >> 28) & 1;
3076 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3077 inexact_vfp_flag_ = (rt_value >> 4) & 1;
3078 underflow_vfp_flag_ = (rt_value >> 3) & 1;
3079 overflow_vfp_flag_ = (rt_value >> 2) & 1;
3080 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3081 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3082 FPSCR_rounding_mode_ =
3083 static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
3084 }
3085 } else {
3086 UNIMPLEMENTED(); // Not used by V8.
3087 }
3088 }
3089 }
3090
3091
DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction * instr)3092 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3093 Instruction* instr) {
3094 DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3095 (instr->VAValue() == 0x0));
3096
3097 int t = instr->RtValue();
3098 int n = instr->VFPNRegValue(kSinglePrecision);
3099 bool to_arm_register = (instr->VLValue() == 0x1);
3100
3101 if (to_arm_register) {
3102 int32_t int_value = get_sinteger_from_s_register(n);
3103 set_register(t, int_value);
3104 } else {
3105 int32_t rs_val = get_register(t);
3106 set_s_register_from_sinteger(n, rs_val);
3107 }
3108 }
3109
3110
DecodeVCMP(Instruction * instr)3111 void Simulator::DecodeVCMP(Instruction* instr) {
3112 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3113 DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3114 (instr->Opc3Value() & 0x1));
3115 // Comparison.
3116
3117 VFPRegPrecision precision = kSinglePrecision;
3118 if (instr->SzValue() == 1) {
3119 precision = kDoublePrecision;
3120 }
3121
3122 int d = instr->VFPDRegValue(precision);
3123 int m = 0;
3124 if (instr->Opc2Value() == 0x4) {
3125 m = instr->VFPMRegValue(precision);
3126 }
3127
3128 if (precision == kDoublePrecision) {
3129 double dd_value = get_double_from_d_register(d);
3130 double dm_value = 0.0;
3131 if (instr->Opc2Value() == 0x4) {
3132 dm_value = get_double_from_d_register(m);
3133 }
3134
3135 // Raise exceptions for quiet NaNs if necessary.
3136 if (instr->Bit(7) == 1) {
3137 if (std::isnan(dd_value)) {
3138 inv_op_vfp_flag_ = true;
3139 }
3140 }
3141
3142 Compute_FPSCR_Flags(dd_value, dm_value);
3143 } else {
3144 UNIMPLEMENTED(); // Not used by V8.
3145 }
3146 }
3147
3148
DecodeVCVTBetweenDoubleAndSingle(Instruction * instr)3149 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3150 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3151 DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3152
3153 VFPRegPrecision dst_precision = kDoublePrecision;
3154 VFPRegPrecision src_precision = kSinglePrecision;
3155 if (instr->SzValue() == 1) {
3156 dst_precision = kSinglePrecision;
3157 src_precision = kDoublePrecision;
3158 }
3159
3160 int dst = instr->VFPDRegValue(dst_precision);
3161 int src = instr->VFPMRegValue(src_precision);
3162
3163 if (dst_precision == kSinglePrecision) {
3164 double val = get_double_from_d_register(src);
3165 set_s_register_from_float(dst, static_cast<float>(val));
3166 } else {
3167 float val = get_float_from_s_register(src);
3168 set_d_register_from_double(dst, static_cast<double>(val));
3169 }
3170 }
3171
get_inv_op_vfp_flag(VFPRoundingMode mode,double val,bool unsigned_)3172 bool get_inv_op_vfp_flag(VFPRoundingMode mode,
3173 double val,
3174 bool unsigned_) {
3175 DCHECK((mode == RN) || (mode == RM) || (mode == RZ));
3176 double max_uint = static_cast<double>(0xffffffffu);
3177 double max_int = static_cast<double>(kMaxInt);
3178 double min_int = static_cast<double>(kMinInt);
3179
3180 // Check for NaN.
3181 if (val != val) {
3182 return true;
3183 }
3184
3185 // Check for overflow. This code works because 32bit integers can be
3186 // exactly represented by ieee-754 64bit floating-point values.
3187 switch (mode) {
3188 case RN:
3189 return unsigned_ ? (val >= (max_uint + 0.5)) ||
3190 (val < -0.5)
3191 : (val >= (max_int + 0.5)) ||
3192 (val < (min_int - 0.5));
3193
3194 case RM:
3195 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3196 (val < 0)
3197 : (val >= (max_int + 1.0)) ||
3198 (val < min_int);
3199
3200 case RZ:
3201 return unsigned_ ? (val >= (max_uint + 1.0)) ||
3202 (val <= -1)
3203 : (val >= (max_int + 1.0)) ||
3204 (val <= (min_int - 1.0));
3205 default:
3206 UNREACHABLE();
3207 return true;
3208 }
3209 }
3210
3211
3212 // We call this function only if we had a vfp invalid exception.
3213 // It returns the correct saturated value.
VFPConversionSaturate(double val,bool unsigned_res)3214 int VFPConversionSaturate(double val, bool unsigned_res) {
3215 if (val != val) {
3216 return 0;
3217 } else {
3218 if (unsigned_res) {
3219 return (val < 0) ? 0 : 0xffffffffu;
3220 } else {
3221 return (val < 0) ? kMinInt : kMaxInt;
3222 }
3223 }
3224 }
3225
3226
DecodeVCVTBetweenFloatingPointAndInteger(Instruction * instr)3227 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3228 DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3229 (instr->Bits(27, 23) == 0x1D));
3230 DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3231 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3232
3233 // Conversion between floating-point and integer.
3234 bool to_integer = (instr->Bit(18) == 1);
3235
3236 VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3237 : kSinglePrecision;
3238
3239 if (to_integer) {
3240 // We are playing with code close to the C++ standard's limits below,
3241 // hence the very simple code and heavy checks.
3242 //
3243 // Note:
3244 // C++ defines default type casting from floating point to integer as
3245 // (close to) rounding toward zero ("fractional part discarded").
3246
3247 int dst = instr->VFPDRegValue(kSinglePrecision);
3248 int src = instr->VFPMRegValue(src_precision);
3249
3250 // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
3251 // mode or the default Round to Zero mode.
3252 VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3253 : RZ;
3254 DCHECK((mode == RM) || (mode == RZ) || (mode == RN));
3255
3256 bool unsigned_integer = (instr->Bit(16) == 0);
3257 bool double_precision = (src_precision == kDoublePrecision);
3258
3259 double val = double_precision ? get_double_from_d_register(src)
3260 : get_float_from_s_register(src);
3261
3262 int temp = unsigned_integer ? static_cast<uint32_t>(val)
3263 : static_cast<int32_t>(val);
3264
3265 inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3266
3267 double abs_diff =
3268 unsigned_integer ? std::fabs(val - static_cast<uint32_t>(temp))
3269 : std::fabs(val - temp);
3270
3271 inexact_vfp_flag_ = (abs_diff != 0);
3272
3273 if (inv_op_vfp_flag_) {
3274 temp = VFPConversionSaturate(val, unsigned_integer);
3275 } else {
3276 switch (mode) {
3277 case RN: {
3278 int val_sign = (val > 0) ? 1 : -1;
3279 if (abs_diff > 0.5) {
3280 temp += val_sign;
3281 } else if (abs_diff == 0.5) {
3282 // Round to even if exactly halfway.
3283 temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3284 }
3285 break;
3286 }
3287
3288 case RM:
3289 temp = temp > val ? temp - 1 : temp;
3290 break;
3291
3292 case RZ:
3293 // Nothing to do.
3294 break;
3295
3296 default:
3297 UNREACHABLE();
3298 }
3299 }
3300
3301 // Update the destination register.
3302 set_s_register_from_sinteger(dst, temp);
3303
3304 } else {
3305 bool unsigned_integer = (instr->Bit(7) == 0);
3306
3307 int dst = instr->VFPDRegValue(src_precision);
3308 int src = instr->VFPMRegValue(kSinglePrecision);
3309
3310 int val = get_sinteger_from_s_register(src);
3311
3312 if (src_precision == kDoublePrecision) {
3313 if (unsigned_integer) {
3314 set_d_register_from_double(
3315 dst, static_cast<double>(static_cast<uint32_t>(val)));
3316 } else {
3317 set_d_register_from_double(dst, static_cast<double>(val));
3318 }
3319 } else {
3320 if (unsigned_integer) {
3321 set_s_register_from_float(
3322 dst, static_cast<float>(static_cast<uint32_t>(val)));
3323 } else {
3324 set_s_register_from_float(dst, static_cast<float>(val));
3325 }
3326 }
3327 }
3328 }
3329
3330
3331 // void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
3332 // Decode Type 6 coprocessor instructions.
3333 // Dm = vmov(Rt, Rt2)
3334 // <Rt, Rt2> = vmov(Dm)
3335 // Ddst = MEM(Rbase + 4*offset).
3336 // MEM(Rbase + 4*offset) = Dsrc.
DecodeType6CoprocessorIns(Instruction * instr)3337 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3338 DCHECK((instr->TypeValue() == 6));
3339
3340 if (instr->CoprocessorValue() == 0xA) {
3341 switch (instr->OpcodeValue()) {
3342 case 0x8:
3343 case 0xA:
3344 case 0xC:
3345 case 0xE: { // Load and store single precision float to memory.
3346 int rn = instr->RnValue();
3347 int vd = instr->VFPDRegValue(kSinglePrecision);
3348 int offset = instr->Immed8Value();
3349 if (!instr->HasU()) {
3350 offset = -offset;
3351 }
3352
3353 int32_t address = get_register(rn) + 4 * offset;
3354 if (instr->HasL()) {
3355 // Load double from memory: vldr.
3356 set_s_register_from_sinteger(vd, ReadW(address, instr));
3357 } else {
3358 // Store double to memory: vstr.
3359 WriteW(address, get_sinteger_from_s_register(vd), instr);
3360 }
3361 break;
3362 }
3363 case 0x4:
3364 case 0x5:
3365 case 0x6:
3366 case 0x7:
3367 case 0x9:
3368 case 0xB:
3369 // Load/store multiple single from memory: vldm/vstm.
3370 HandleVList(instr);
3371 break;
3372 default:
3373 UNIMPLEMENTED(); // Not used by V8.
3374 }
3375 } else if (instr->CoprocessorValue() == 0xB) {
3376 switch (instr->OpcodeValue()) {
3377 case 0x2:
3378 // Load and store double to two GP registers
3379 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3380 UNIMPLEMENTED(); // Not used by V8.
3381 } else {
3382 int rt = instr->RtValue();
3383 int rn = instr->RnValue();
3384 int vm = instr->VFPMRegValue(kDoublePrecision);
3385 if (instr->HasL()) {
3386 int32_t data[2];
3387 double d = get_double_from_d_register(vm);
3388 memcpy(data, &d, 8);
3389 set_register(rt, data[0]);
3390 set_register(rn, data[1]);
3391 } else {
3392 int32_t data[] = { get_register(rt), get_register(rn) };
3393 double d;
3394 memcpy(&d, data, 8);
3395 set_d_register_from_double(vm, d);
3396 }
3397 }
3398 break;
3399 case 0x8:
3400 case 0xA:
3401 case 0xC:
3402 case 0xE: { // Load and store double to memory.
3403 int rn = instr->RnValue();
3404 int vd = instr->VFPDRegValue(kDoublePrecision);
3405 int offset = instr->Immed8Value();
3406 if (!instr->HasU()) {
3407 offset = -offset;
3408 }
3409 int32_t address = get_register(rn) + 4 * offset;
3410 if (instr->HasL()) {
3411 // Load double from memory: vldr.
3412 int32_t data[] = {
3413 ReadW(address, instr),
3414 ReadW(address + 4, instr)
3415 };
3416 double val;
3417 memcpy(&val, data, 8);
3418 set_d_register_from_double(vd, val);
3419 } else {
3420 // Store double to memory: vstr.
3421 int32_t data[2];
3422 double val = get_double_from_d_register(vd);
3423 memcpy(data, &val, 8);
3424 WriteW(address, data[0], instr);
3425 WriteW(address + 4, data[1], instr);
3426 }
3427 break;
3428 }
3429 case 0x4:
3430 case 0x5:
3431 case 0x6:
3432 case 0x7:
3433 case 0x9:
3434 case 0xB:
3435 // Load/store multiple double from memory: vldm/vstm.
3436 HandleVList(instr);
3437 break;
3438 default:
3439 UNIMPLEMENTED(); // Not used by V8.
3440 }
3441 } else {
3442 UNIMPLEMENTED(); // Not used by V8.
3443 }
3444 }
3445
3446
DecodeSpecialCondition(Instruction * instr)3447 void Simulator::DecodeSpecialCondition(Instruction* instr) {
3448 switch (instr->SpecialValue()) {
3449 case 5:
3450 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3451 (instr->Bit(4) == 1)) {
3452 // vmovl signed
3453 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
3454 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3455 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3456 int imm3 = instr->Bits(21, 19);
3457 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3458 int esize = 8 * imm3;
3459 int elements = 64 / esize;
3460 int8_t from[8];
3461 get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3462 int16_t to[8];
3463 int e = 0;
3464 while (e < elements) {
3465 to[e] = from[e];
3466 e++;
3467 }
3468 set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3469 } else {
3470 UNIMPLEMENTED();
3471 }
3472 break;
3473 case 7:
3474 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3475 (instr->Bit(4) == 1)) {
3476 // vmovl unsigned
3477 if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
3478 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
3479 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3480 int imm3 = instr->Bits(21, 19);
3481 if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3482 int esize = 8 * imm3;
3483 int elements = 64 / esize;
3484 uint8_t from[8];
3485 get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3486 uint16_t to[8];
3487 int e = 0;
3488 while (e < elements) {
3489 to[e] = from[e];
3490 e++;
3491 }
3492 set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3493 } else {
3494 UNIMPLEMENTED();
3495 }
3496 break;
3497 case 8:
3498 if (instr->Bits(21, 20) == 0) {
3499 // vst1
3500 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3501 int Rn = instr->VnValue();
3502 int type = instr->Bits(11, 8);
3503 int Rm = instr->VmValue();
3504 int32_t address = get_register(Rn);
3505 int regs = 0;
3506 switch (type) {
3507 case nlt_1:
3508 regs = 1;
3509 break;
3510 case nlt_2:
3511 regs = 2;
3512 break;
3513 case nlt_3:
3514 regs = 3;
3515 break;
3516 case nlt_4:
3517 regs = 4;
3518 break;
3519 default:
3520 UNIMPLEMENTED();
3521 break;
3522 }
3523 int r = 0;
3524 while (r < regs) {
3525 uint32_t data[2];
3526 get_d_register(Vd + r, data);
3527 WriteW(address, data[0], instr);
3528 WriteW(address + 4, data[1], instr);
3529 address += 8;
3530 r++;
3531 }
3532 if (Rm != 15) {
3533 if (Rm == 13) {
3534 set_register(Rn, address);
3535 } else {
3536 set_register(Rn, get_register(Rn) + get_register(Rm));
3537 }
3538 }
3539 } else if (instr->Bits(21, 20) == 2) {
3540 // vld1
3541 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3542 int Rn = instr->VnValue();
3543 int type = instr->Bits(11, 8);
3544 int Rm = instr->VmValue();
3545 int32_t address = get_register(Rn);
3546 int regs = 0;
3547 switch (type) {
3548 case nlt_1:
3549 regs = 1;
3550 break;
3551 case nlt_2:
3552 regs = 2;
3553 break;
3554 case nlt_3:
3555 regs = 3;
3556 break;
3557 case nlt_4:
3558 regs = 4;
3559 break;
3560 default:
3561 UNIMPLEMENTED();
3562 break;
3563 }
3564 int r = 0;
3565 while (r < regs) {
3566 uint32_t data[2];
3567 data[0] = ReadW(address, instr);
3568 data[1] = ReadW(address + 4, instr);
3569 set_d_register(Vd + r, data);
3570 address += 8;
3571 r++;
3572 }
3573 if (Rm != 15) {
3574 if (Rm == 13) {
3575 set_register(Rn, address);
3576 } else {
3577 set_register(Rn, get_register(Rn) + get_register(Rm));
3578 }
3579 }
3580 } else {
3581 UNIMPLEMENTED();
3582 }
3583 break;
3584 case 0xA:
3585 case 0xB:
3586 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
3587 // pld: ignore instruction.
3588 } else {
3589 UNIMPLEMENTED();
3590 }
3591 break;
3592 default:
3593 UNIMPLEMENTED();
3594 break;
3595 }
3596 }
3597
3598
3599 // Executes the current instruction.
InstructionDecode(Instruction * instr)3600 void Simulator::InstructionDecode(Instruction* instr) {
3601 if (v8::internal::FLAG_check_icache) {
3602 CheckICache(isolate_->simulator_i_cache(), instr);
3603 }
3604 pc_modified_ = false;
3605 if (::v8::internal::FLAG_trace_sim) {
3606 disasm::NameConverter converter;
3607 disasm::Disassembler dasm(converter);
3608 // use a reasonably large buffer
3609 v8::internal::EmbeddedVector<char, 256> buffer;
3610 dasm.InstructionDecode(buffer,
3611 reinterpret_cast<byte*>(instr));
3612 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
3613 }
3614 if (instr->ConditionField() == kSpecialCondition) {
3615 DecodeSpecialCondition(instr);
3616 } else if (ConditionallyExecute(instr)) {
3617 switch (instr->TypeValue()) {
3618 case 0:
3619 case 1: {
3620 DecodeType01(instr);
3621 break;
3622 }
3623 case 2: {
3624 DecodeType2(instr);
3625 break;
3626 }
3627 case 3: {
3628 DecodeType3(instr);
3629 break;
3630 }
3631 case 4: {
3632 DecodeType4(instr);
3633 break;
3634 }
3635 case 5: {
3636 DecodeType5(instr);
3637 break;
3638 }
3639 case 6: {
3640 DecodeType6(instr);
3641 break;
3642 }
3643 case 7: {
3644 DecodeType7(instr);
3645 break;
3646 }
3647 default: {
3648 UNIMPLEMENTED();
3649 break;
3650 }
3651 }
3652 // If the instruction is a non taken conditional stop, we need to skip the
3653 // inlined message address.
3654 } else if (instr->IsStop()) {
3655 set_pc(get_pc() + 2 * Instruction::kInstrSize);
3656 }
3657 if (!pc_modified_) {
3658 set_register(pc, reinterpret_cast<int32_t>(instr)
3659 + Instruction::kInstrSize);
3660 }
3661 }
3662
3663
Execute()3664 void Simulator::Execute() {
3665 // Get the PC to simulate. Cannot use the accessor here as we need the
3666 // raw PC value and not the one used as input to arithmetic instructions.
3667 int program_counter = get_pc();
3668
3669 if (::v8::internal::FLAG_stop_sim_at == 0) {
3670 // Fast version of the dispatch loop without checking whether the simulator
3671 // should be stopping at a particular executed instruction.
3672 while (program_counter != end_sim_pc) {
3673 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3674 icount_++;
3675 InstructionDecode(instr);
3676 program_counter = get_pc();
3677 }
3678 } else {
3679 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3680 // we reach the particular instuction count.
3681 while (program_counter != end_sim_pc) {
3682 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3683 icount_++;
3684 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3685 ArmDebugger dbg(this);
3686 dbg.Debug();
3687 } else {
3688 InstructionDecode(instr);
3689 }
3690 program_counter = get_pc();
3691 }
3692 }
3693 }
3694
3695
CallInternal(byte * entry)3696 void Simulator::CallInternal(byte* entry) {
3697 // Prepare to execute the code at entry
3698 set_register(pc, reinterpret_cast<int32_t>(entry));
3699 // Put down marker for end of simulation. The simulator will stop simulation
3700 // when the PC reaches this value. By saving the "end simulation" value into
3701 // the LR the simulation stops when returning to this call point.
3702 set_register(lr, end_sim_pc);
3703
3704 // Remember the values of callee-saved registers.
3705 // The code below assumes that r9 is not used as sb (static base) in
3706 // simulator code and therefore is regarded as a callee-saved register.
3707 int32_t r4_val = get_register(r4);
3708 int32_t r5_val = get_register(r5);
3709 int32_t r6_val = get_register(r6);
3710 int32_t r7_val = get_register(r7);
3711 int32_t r8_val = get_register(r8);
3712 int32_t r9_val = get_register(r9);
3713 int32_t r10_val = get_register(r10);
3714 int32_t r11_val = get_register(r11);
3715
3716 // Set up the callee-saved registers with a known value. To be able to check
3717 // that they are preserved properly across JS execution.
3718 int32_t callee_saved_value = icount_;
3719 set_register(r4, callee_saved_value);
3720 set_register(r5, callee_saved_value);
3721 set_register(r6, callee_saved_value);
3722 set_register(r7, callee_saved_value);
3723 set_register(r8, callee_saved_value);
3724 set_register(r9, callee_saved_value);
3725 set_register(r10, callee_saved_value);
3726 set_register(r11, callee_saved_value);
3727
3728 // Start the simulation
3729 Execute();
3730
3731 // Check that the callee-saved registers have been preserved.
3732 CHECK_EQ(callee_saved_value, get_register(r4));
3733 CHECK_EQ(callee_saved_value, get_register(r5));
3734 CHECK_EQ(callee_saved_value, get_register(r6));
3735 CHECK_EQ(callee_saved_value, get_register(r7));
3736 CHECK_EQ(callee_saved_value, get_register(r8));
3737 CHECK_EQ(callee_saved_value, get_register(r9));
3738 CHECK_EQ(callee_saved_value, get_register(r10));
3739 CHECK_EQ(callee_saved_value, get_register(r11));
3740
3741 // Restore callee-saved registers with the original value.
3742 set_register(r4, r4_val);
3743 set_register(r5, r5_val);
3744 set_register(r6, r6_val);
3745 set_register(r7, r7_val);
3746 set_register(r8, r8_val);
3747 set_register(r9, r9_val);
3748 set_register(r10, r10_val);
3749 set_register(r11, r11_val);
3750 }
3751
3752
Call(byte * entry,int argument_count,...)3753 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
3754 va_list parameters;
3755 va_start(parameters, argument_count);
3756 // Set up arguments
3757
3758 // First four arguments passed in registers.
3759 DCHECK(argument_count >= 4);
3760 set_register(r0, va_arg(parameters, int32_t));
3761 set_register(r1, va_arg(parameters, int32_t));
3762 set_register(r2, va_arg(parameters, int32_t));
3763 set_register(r3, va_arg(parameters, int32_t));
3764
3765 // Remaining arguments passed on stack.
3766 int original_stack = get_register(sp);
3767 // Compute position of stack on entry to generated code.
3768 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
3769 if (base::OS::ActivationFrameAlignment() != 0) {
3770 entry_stack &= -base::OS::ActivationFrameAlignment();
3771 }
3772 // Store remaining arguments on stack, from low to high memory.
3773 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
3774 for (int i = 4; i < argument_count; i++) {
3775 stack_argument[i - 4] = va_arg(parameters, int32_t);
3776 }
3777 va_end(parameters);
3778 set_register(sp, entry_stack);
3779
3780 CallInternal(entry);
3781
3782 // Pop stack passed arguments.
3783 CHECK_EQ(entry_stack, get_register(sp));
3784 set_register(sp, original_stack);
3785
3786 int32_t result = get_register(r0);
3787 return result;
3788 }
3789
3790
CallFP(byte * entry,double d0,double d1)3791 void Simulator::CallFP(byte* entry, double d0, double d1) {
3792 if (use_eabi_hardfloat()) {
3793 set_d_register_from_double(0, d0);
3794 set_d_register_from_double(1, d1);
3795 } else {
3796 set_register_pair_from_double(0, &d0);
3797 set_register_pair_from_double(2, &d1);
3798 }
3799 CallInternal(entry);
3800 }
3801
3802
CallFPReturnsInt(byte * entry,double d0,double d1)3803 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
3804 CallFP(entry, d0, d1);
3805 int32_t result = get_register(r0);
3806 return result;
3807 }
3808
3809
CallFPReturnsDouble(byte * entry,double d0,double d1)3810 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
3811 CallFP(entry, d0, d1);
3812 if (use_eabi_hardfloat()) {
3813 return get_double_from_d_register(0);
3814 } else {
3815 return get_double_from_register_pair(0);
3816 }
3817 }
3818
3819
PushAddress(uintptr_t address)3820 uintptr_t Simulator::PushAddress(uintptr_t address) {
3821 int new_sp = get_register(sp) - sizeof(uintptr_t);
3822 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
3823 *stack_slot = address;
3824 set_register(sp, new_sp);
3825 return new_sp;
3826 }
3827
3828
PopAddress()3829 uintptr_t Simulator::PopAddress() {
3830 int current_sp = get_register(sp);
3831 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
3832 uintptr_t address = *stack_slot;
3833 set_register(sp, current_sp + sizeof(uintptr_t));
3834 return address;
3835 }
3836
3837 } } // namespace v8::internal
3838
3839 #endif // USE_SIMULATOR
3840
3841 #endif // V8_TARGET_ARCH_ARM
3842