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