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