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