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