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