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