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// static
26base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
27    LAZY_INSTANCE_INITIALIZER;
28
29// This macro provides a platform independent use of sscanf. The reason for
30// SScanF not being implemented in a platform independent way through
31// ::v8::internal::OS in the same way as SNPrintF is that the
32// Windows C Run-Time Library does not provide vsscanf.
33#define SScanF sscanf  // NOLINT
34
35// The ArmDebugger class is used by the simulator while debugging simulated ARM
36// code.
37class ArmDebugger {
38 public:
39  explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
40
41  void Stop(Instruction* instr);
42  void Debug();
43
44 private:
45  static const Instr kBreakpointInstr =
46      (al | (7*B25) | (1*B24) | kBreakpoint);
47  static const Instr kNopInstr = (al | (13*B21));
48
49  Simulator* sim_;
50
51  int32_t GetRegisterValue(int regnum);
52  double GetRegisterPairDoubleValue(int regnum);
53  double GetVFPDoubleRegisterValue(int regnum);
54  bool GetValue(const char* desc, int32_t* value);
55  bool GetVFPSingleValue(const char* desc, float* value);
56  bool GetVFPDoubleValue(const char* desc, double* value);
57
58  // Set or delete a breakpoint. Returns true if successful.
59  bool SetBreakpoint(Instruction* breakpc);
60  bool DeleteBreakpoint(Instruction* breakpc);
61
62  // Undo and redo all breakpoints. This is needed to bracket disassembly and
63  // execution to skip past breakpoints when run from the debugger.
64  void UndoBreakpoints();
65  void RedoBreakpoints();
66};
67
68void ArmDebugger::Stop(Instruction* instr) {
69  // Get the stop code.
70  uint32_t code = instr->SvcValue() & kStopCodeMask;
71  // Print the stop message and code if it is not the default code.
72  if (code != kMaxStopCode) {
73    PrintF("Simulator hit stop %u\n", code);
74  } else {
75    PrintF("Simulator hit\n");
76  }
77  sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
78  Debug();
79}
80
81int32_t ArmDebugger::GetRegisterValue(int regnum) {
82  if (regnum == kPCRegister) {
83    return sim_->get_pc();
84  } else {
85    return sim_->get_register(regnum);
86  }
87}
88
89double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
90  return sim_->get_double_from_register_pair(regnum);
91}
92
93
94double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
95  return sim_->get_double_from_d_register(regnum);
96}
97
98
99bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
100  int regnum = Registers::Number(desc);
101  if (regnum != kNoRegister) {
102    *value = GetRegisterValue(regnum);
103    return true;
104  } else {
105    if (strncmp(desc, "0x", 2) == 0) {
106      return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
107    } else {
108      return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
109    }
110  }
111  return false;
112}
113
114
115bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
116  bool is_double;
117  int regnum = VFPRegisters::Number(desc, &is_double);
118  if (regnum != kNoRegister && !is_double) {
119    *value = sim_->get_float_from_s_register(regnum);
120    return true;
121  }
122  return false;
123}
124
125
126bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
127  bool is_double;
128  int regnum = VFPRegisters::Number(desc, &is_double);
129  if (regnum != kNoRegister && is_double) {
130    *value = sim_->get_double_from_d_register(regnum);
131    return true;
132  }
133  return false;
134}
135
136
137bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
138  // Check if a breakpoint can be set. If not return without any side-effects.
139  if (sim_->break_pc_ != NULL) {
140    return false;
141  }
142
143  // Set the breakpoint.
144  sim_->break_pc_ = breakpc;
145  sim_->break_instr_ = breakpc->InstructionBits();
146  // Not setting the breakpoint instruction in the code itself. It will be set
147  // when the debugger shell continues.
148  return true;
149}
150
151
152bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
153  if (sim_->break_pc_ != NULL) {
154    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
155  }
156
157  sim_->break_pc_ = NULL;
158  sim_->break_instr_ = 0;
159  return true;
160}
161
162
163void ArmDebugger::UndoBreakpoints() {
164  if (sim_->break_pc_ != NULL) {
165    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
166  }
167}
168
169
170void ArmDebugger::RedoBreakpoints() {
171  if (sim_->break_pc_ != NULL) {
172    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
173  }
174}
175
176
177void ArmDebugger::Debug() {
178  intptr_t last_pc = -1;
179  bool done = false;
180
181#define COMMAND_SIZE 63
182#define ARG_SIZE 255
183
184#define STR(a) #a
185#define XSTR(a) STR(a)
186
187  char cmd[COMMAND_SIZE + 1];
188  char arg1[ARG_SIZE + 1];
189  char arg2[ARG_SIZE + 1];
190  char* argv[3] = { cmd, arg1, arg2 };
191
192  // make sure to have a proper terminating character if reaching the limit
193  cmd[COMMAND_SIZE] = 0;
194  arg1[ARG_SIZE] = 0;
195  arg2[ARG_SIZE] = 0;
196
197  // Undo all set breakpoints while running in the debugger shell. This will
198  // make them invisible to all commands.
199  UndoBreakpoints();
200
201  while (!done && !sim_->has_bad_pc()) {
202    if (last_pc != sim_->get_pc()) {
203      disasm::NameConverter converter;
204      disasm::Disassembler dasm(converter);
205      // use a reasonably large buffer
206      v8::internal::EmbeddedVector<char, 256> buffer;
207      dasm.InstructionDecode(buffer,
208                             reinterpret_cast<byte*>(sim_->get_pc()));
209      PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
210      last_pc = sim_->get_pc();
211    }
212    char* line = ReadLine("sim> ");
213    if (line == NULL) {
214      break;
215    } else {
216      char* last_input = sim_->last_debugger_input();
217      if (strcmp(line, "\n") == 0 && last_input != NULL) {
218        line = last_input;
219      } else {
220        // Ownership is transferred to sim_;
221        sim_->set_last_debugger_input(line);
222      }
223      // Use sscanf to parse the individual parts of the command line. At the
224      // moment no command expects more than two parameters.
225      int argc = SScanF(line,
226                        "%" XSTR(COMMAND_SIZE) "s "
227                        "%" XSTR(ARG_SIZE) "s "
228                        "%" XSTR(ARG_SIZE) "s",
229                        cmd, arg1, arg2);
230      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
231        sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
232      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
233        // Execute the one instruction we broke at with breakpoints disabled.
234        sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
235        // Leave the debugger shell.
236        done = true;
237      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
238        if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
239          int32_t value;
240          float svalue;
241          double dvalue;
242          if (strcmp(arg1, "all") == 0) {
243            for (int i = 0; i < kNumRegisters; i++) {
244              value = GetRegisterValue(i);
245              PrintF(
246                  "%3s: 0x%08x %10d",
247                  RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
248                      i),
249                  value, value);
250              if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
251                  i < 8 &&
252                  (i % 2) == 0) {
253                dvalue = GetRegisterPairDoubleValue(i);
254                PrintF(" (%f)\n", dvalue);
255              } else {
256                PrintF("\n");
257              }
258            }
259            for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) {
260              dvalue = GetVFPDoubleRegisterValue(i);
261              uint64_t as_words = bit_cast<uint64_t>(dvalue);
262              PrintF("%3s: %f 0x%08x %08x\n",
263                     VFPRegisters::Name(i, true),
264                     dvalue,
265                     static_cast<uint32_t>(as_words >> 32),
266                     static_cast<uint32_t>(as_words & 0xffffffff));
267            }
268          } else {
269            if (GetValue(arg1, &value)) {
270              PrintF("%s: 0x%08x %d \n", arg1, value, value);
271            } else if (GetVFPSingleValue(arg1, &svalue)) {
272              uint32_t as_word = bit_cast<uint32_t>(svalue);
273              PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
274            } else if (GetVFPDoubleValue(arg1, &dvalue)) {
275              uint64_t as_words = bit_cast<uint64_t>(dvalue);
276              PrintF("%s: %f 0x%08x %08x\n",
277                     arg1,
278                     dvalue,
279                     static_cast<uint32_t>(as_words >> 32),
280                     static_cast<uint32_t>(as_words & 0xffffffff));
281            } else {
282              PrintF("%s unrecognized\n", arg1);
283            }
284          }
285        } else {
286          PrintF("print <register>\n");
287        }
288      } else if ((strcmp(cmd, "po") == 0)
289                 || (strcmp(cmd, "printobject") == 0)) {
290        if (argc == 2) {
291          int32_t value;
292          OFStream os(stdout);
293          if (GetValue(arg1, &value)) {
294            Object* obj = reinterpret_cast<Object*>(value);
295            os << arg1 << ": \n";
296#ifdef DEBUG
297            obj->Print(os);
298            os << "\n";
299#else
300            os << Brief(obj) << "\n";
301#endif
302          } else {
303            os << arg1 << " unrecognized\n";
304          }
305        } else {
306          PrintF("printobject <value>\n");
307        }
308      } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
309        int32_t* cur = NULL;
310        int32_t* end = NULL;
311        int next_arg = 1;
312
313        if (strcmp(cmd, "stack") == 0) {
314          cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
315        } else {  // "mem"
316          int32_t value;
317          if (!GetValue(arg1, &value)) {
318            PrintF("%s unrecognized\n", arg1);
319            continue;
320          }
321          cur = reinterpret_cast<int32_t*>(value);
322          next_arg++;
323        }
324
325        int32_t words;
326        if (argc == next_arg) {
327          words = 10;
328        } else {
329          if (!GetValue(argv[next_arg], &words)) {
330            words = 10;
331          }
332        }
333        end = cur + words;
334
335        while (cur < end) {
336          PrintF("  0x%08" V8PRIxPTR ":  0x%08x %10d",
337                 reinterpret_cast<intptr_t>(cur), *cur, *cur);
338          HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
339          int value = *cur;
340          Heap* current_heap = sim_->isolate_->heap();
341          if (((value & 1) == 0) ||
342              current_heap->ContainsSlow(obj->address())) {
343            PrintF(" (");
344            if ((value & 1) == 0) {
345              PrintF("smi %d", value / 2);
346            } else {
347              obj->ShortPrint();
348            }
349            PrintF(")");
350          }
351          PrintF("\n");
352          cur++;
353        }
354      } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
355        disasm::NameConverter converter;
356        disasm::Disassembler dasm(converter);
357        // use a reasonably large buffer
358        v8::internal::EmbeddedVector<char, 256> buffer;
359
360        byte* prev = NULL;
361        byte* cur = NULL;
362        byte* end = NULL;
363
364        if (argc == 1) {
365          cur = reinterpret_cast<byte*>(sim_->get_pc());
366          end = cur + (10 * Instruction::kInstrSize);
367        } else if (argc == 2) {
368          int regnum = Registers::Number(arg1);
369          if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
370            // The argument is an address or a register name.
371            int32_t value;
372            if (GetValue(arg1, &value)) {
373              cur = reinterpret_cast<byte*>(value);
374              // Disassemble 10 instructions at <arg1>.
375              end = cur + (10 * Instruction::kInstrSize);
376            }
377          } else {
378            // The argument is the number of instructions.
379            int32_t value;
380            if (GetValue(arg1, &value)) {
381              cur = reinterpret_cast<byte*>(sim_->get_pc());
382              // Disassemble <arg1> instructions.
383              end = cur + (value * Instruction::kInstrSize);
384            }
385          }
386        } else {
387          int32_t value1;
388          int32_t value2;
389          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
390            cur = reinterpret_cast<byte*>(value1);
391            end = cur + (value2 * Instruction::kInstrSize);
392          }
393        }
394
395        while (cur < end) {
396          prev = cur;
397          cur += dasm.InstructionDecode(buffer, cur);
398          PrintF("  0x%08" V8PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(prev),
399                 buffer.start());
400        }
401      } else if (strcmp(cmd, "gdb") == 0) {
402        PrintF("relinquishing control to gdb\n");
403        v8::base::OS::DebugBreak();
404        PrintF("regaining control from gdb\n");
405      } else if (strcmp(cmd, "break") == 0) {
406        if (argc == 2) {
407          int32_t value;
408          if (GetValue(arg1, &value)) {
409            if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
410              PrintF("setting breakpoint failed\n");
411            }
412          } else {
413            PrintF("%s unrecognized\n", arg1);
414          }
415        } else {
416          PrintF("break <address>\n");
417        }
418      } else if (strcmp(cmd, "del") == 0) {
419        if (!DeleteBreakpoint(NULL)) {
420          PrintF("deleting breakpoint failed\n");
421        }
422      } else if (strcmp(cmd, "flags") == 0) {
423        PrintF("N flag: %d; ", sim_->n_flag_);
424        PrintF("Z flag: %d; ", sim_->z_flag_);
425        PrintF("C flag: %d; ", sim_->c_flag_);
426        PrintF("V flag: %d\n", sim_->v_flag_);
427        PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
428        PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
429        PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
430        PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
431        PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
432      } else if (strcmp(cmd, "stop") == 0) {
433        int32_t value;
434        intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize;
435        Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
436        Instruction* msg_address =
437          reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
438        if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
439          // Remove the current stop.
440          if (sim_->isStopInstruction(stop_instr)) {
441            stop_instr->SetInstructionBits(kNopInstr);
442            msg_address->SetInstructionBits(kNopInstr);
443          } else {
444            PrintF("Not at debugger stop.\n");
445          }
446        } else if (argc == 3) {
447          // Print information about all/the specified breakpoint(s).
448          if (strcmp(arg1, "info") == 0) {
449            if (strcmp(arg2, "all") == 0) {
450              PrintF("Stop information:\n");
451              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
452                sim_->PrintStopInfo(i);
453              }
454            } else if (GetValue(arg2, &value)) {
455              sim_->PrintStopInfo(value);
456            } else {
457              PrintF("Unrecognized argument.\n");
458            }
459          } else if (strcmp(arg1, "enable") == 0) {
460            // Enable all/the specified breakpoint(s).
461            if (strcmp(arg2, "all") == 0) {
462              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
463                sim_->EnableStop(i);
464              }
465            } else if (GetValue(arg2, &value)) {
466              sim_->EnableStop(value);
467            } else {
468              PrintF("Unrecognized argument.\n");
469            }
470          } else if (strcmp(arg1, "disable") == 0) {
471            // Disable all/the specified breakpoint(s).
472            if (strcmp(arg2, "all") == 0) {
473              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
474                sim_->DisableStop(i);
475              }
476            } else if (GetValue(arg2, &value)) {
477              sim_->DisableStop(value);
478            } else {
479              PrintF("Unrecognized argument.\n");
480            }
481          }
482        } else {
483          PrintF("Wrong usage. Use help command for more information.\n");
484        }
485      } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
486        ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
487        PrintF("Trace of executed instructions is %s\n",
488               ::v8::internal::FLAG_trace_sim ? "on" : "off");
489      } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
490        PrintF("cont\n");
491        PrintF("  continue execution (alias 'c')\n");
492        PrintF("stepi\n");
493        PrintF("  step one instruction (alias 'si')\n");
494        PrintF("print <register>\n");
495        PrintF("  print register content (alias 'p')\n");
496        PrintF("  use register name 'all' to print all registers\n");
497        PrintF("  add argument 'fp' to print register pair double values\n");
498        PrintF("printobject <register>\n");
499        PrintF("  print an object from a register (alias 'po')\n");
500        PrintF("flags\n");
501        PrintF("  print flags\n");
502        PrintF("stack [<words>]\n");
503        PrintF("  dump stack content, default dump 10 words)\n");
504        PrintF("mem <address> [<words>]\n");
505        PrintF("  dump memory content, default dump 10 words)\n");
506        PrintF("disasm [<instructions>]\n");
507        PrintF("disasm [<address/register>]\n");
508        PrintF("disasm [[<address/register>] <instructions>]\n");
509        PrintF("  disassemble code, default is 10 instructions\n");
510        PrintF("  from pc (alias 'di')\n");
511        PrintF("gdb\n");
512        PrintF("  enter gdb\n");
513        PrintF("break <address>\n");
514        PrintF("  set a break point on the address\n");
515        PrintF("del\n");
516        PrintF("  delete the breakpoint\n");
517        PrintF("trace (alias 't')\n");
518        PrintF("  toogle the tracing of all executed statements\n");
519        PrintF("stop feature:\n");
520        PrintF("  Description:\n");
521        PrintF("    Stops are debug instructions inserted by\n");
522        PrintF("    the Assembler::stop() function.\n");
523        PrintF("    When hitting a stop, the Simulator will\n");
524        PrintF("    stop and and give control to the ArmDebugger.\n");
525        PrintF("    The first %d stop codes are watched:\n",
526               Simulator::kNumOfWatchedStops);
527        PrintF("    - They can be enabled / disabled: the Simulator\n");
528        PrintF("      will / won't stop when hitting them.\n");
529        PrintF("    - The Simulator keeps track of how many times they \n");
530        PrintF("      are met. (See the info command.) Going over a\n");
531        PrintF("      disabled stop still increases its counter. \n");
532        PrintF("  Commands:\n");
533        PrintF("    stop info all/<code> : print infos about number <code>\n");
534        PrintF("      or all stop(s).\n");
535        PrintF("    stop enable/disable all/<code> : enables / disables\n");
536        PrintF("      all or number <code> stop(s)\n");
537        PrintF("    stop unstop\n");
538        PrintF("      ignore the stop instruction at the current location\n");
539        PrintF("      from now on\n");
540      } else {
541        PrintF("Unknown command: %s\n", cmd);
542      }
543    }
544  }
545
546  // Add all the breakpoints back to stop execution and enter the debugger
547  // shell when hit.
548  RedoBreakpoints();
549
550#undef COMMAND_SIZE
551#undef ARG_SIZE
552
553#undef STR
554#undef XSTR
555}
556
557
558static bool ICacheMatch(void* one, void* two) {
559  DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
560  DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
561  return one == two;
562}
563
564
565static uint32_t ICacheHash(void* key) {
566  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
567}
568
569
570static bool AllOnOnePage(uintptr_t start, int size) {
571  intptr_t start_page = (start & ~CachePage::kPageMask);
572  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
573  return start_page == end_page;
574}
575
576void Simulator::set_last_debugger_input(char* input) {
577  DeleteArray(last_debugger_input_);
578  last_debugger_input_ = input;
579}
580
581void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
582                            void* start_addr, size_t size) {
583  intptr_t start = reinterpret_cast<intptr_t>(start_addr);
584  int intra_line = (start & CachePage::kLineMask);
585  start -= intra_line;
586  size += intra_line;
587  size = ((size - 1) | CachePage::kLineMask) + 1;
588  int offset = (start & CachePage::kPageMask);
589  while (!AllOnOnePage(start, size - 1)) {
590    int bytes_to_flush = CachePage::kPageSize - offset;
591    FlushOnePage(i_cache, start, bytes_to_flush);
592    start += bytes_to_flush;
593    size -= bytes_to_flush;
594    DCHECK_EQ(0, start & CachePage::kPageMask);
595    offset = 0;
596  }
597  if (size != 0) {
598    FlushOnePage(i_cache, start, size);
599  }
600}
601
602CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
603                                   void* page) {
604  base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
605  if (entry->value == NULL) {
606    CachePage* new_page = new CachePage();
607    entry->value = new_page;
608  }
609  return reinterpret_cast<CachePage*>(entry->value);
610}
611
612
613// Flush from start up to and not including start + size.
614void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
615                             intptr_t start, int size) {
616  DCHECK(size <= CachePage::kPageSize);
617  DCHECK(AllOnOnePage(start, size - 1));
618  DCHECK((start & CachePage::kLineMask) == 0);
619  DCHECK((size & CachePage::kLineMask) == 0);
620  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
621  int offset = (start & CachePage::kPageMask);
622  CachePage* cache_page = GetCachePage(i_cache, page);
623  char* valid_bytemap = cache_page->ValidityByte(offset);
624  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
625}
626
627void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
628                            Instruction* instr) {
629  intptr_t address = reinterpret_cast<intptr_t>(instr);
630  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
631  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
632  int offset = (address & CachePage::kPageMask);
633  CachePage* cache_page = GetCachePage(i_cache, page);
634  char* cache_valid_byte = cache_page->ValidityByte(offset);
635  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
636  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
637  if (cache_hit) {
638    // Check that the data in memory matches the contents of the I-cache.
639    CHECK_EQ(0,
640             memcmp(reinterpret_cast<void*>(instr),
641                    cache_page->CachedData(offset), Instruction::kInstrSize));
642  } else {
643    // Cache miss.  Load memory into the cache.
644    memcpy(cached_line, line, CachePage::kLineLength);
645    *cache_valid_byte = CachePage::LINE_VALID;
646  }
647}
648
649
650void Simulator::Initialize(Isolate* isolate) {
651  if (isolate->simulator_initialized()) return;
652  isolate->set_simulator_initialized(true);
653  ::v8::internal::ExternalReference::set_redirector(isolate,
654                                                    &RedirectExternalReference);
655}
656
657
658Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
659  i_cache_ = isolate_->simulator_i_cache();
660  if (i_cache_ == NULL) {
661    i_cache_ = new base::CustomMatcherHashMap(&ICacheMatch);
662    isolate_->set_simulator_i_cache(i_cache_);
663  }
664  Initialize(isolate);
665  // Set up simulator support first. Some of this information is needed to
666  // setup the architecture state.
667  size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
668  stack_ = reinterpret_cast<char*>(malloc(stack_size));
669  pc_modified_ = false;
670  icount_ = 0;
671  break_pc_ = NULL;
672  break_instr_ = 0;
673
674  // Set up architecture state.
675  // All registers are initialized to zero to start with.
676  for (int i = 0; i < num_registers; i++) {
677    registers_[i] = 0;
678  }
679  n_flag_ = false;
680  z_flag_ = false;
681  c_flag_ = false;
682  v_flag_ = false;
683
684  // Initializing VFP registers.
685  // All registers are initialized to zero to start with
686  // even though s_registers_ & d_registers_ share the same
687  // physical registers in the target.
688  for (int i = 0; i < num_d_registers * 2; i++) {
689    vfp_registers_[i] = 0;
690  }
691  n_flag_FPSCR_ = false;
692  z_flag_FPSCR_ = false;
693  c_flag_FPSCR_ = false;
694  v_flag_FPSCR_ = false;
695  FPSCR_rounding_mode_ = RN;
696  FPSCR_default_NaN_mode_ = false;
697
698  inv_op_vfp_flag_ = false;
699  div_zero_vfp_flag_ = false;
700  overflow_vfp_flag_ = false;
701  underflow_vfp_flag_ = false;
702  inexact_vfp_flag_ = false;
703
704  // The sp is initialized to point to the bottom (high address) of the
705  // allocated stack area. To be safe in potential stack underflows we leave
706  // some buffer below.
707  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
708  // The lr and pc are initialized to a known bad value that will cause an
709  // access violation if the simulator ever tries to execute it.
710  registers_[pc] = bad_lr;
711  registers_[lr] = bad_lr;
712
713  last_debugger_input_ = NULL;
714}
715
716Simulator::~Simulator() {
717  global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
718  free(stack_);
719}
720
721// When the generated code calls an external reference we need to catch that in
722// the simulator.  The external reference will be a function compiled for the
723// host architecture.  We need to call that function instead of trying to
724// execute it with the simulator.  We do that by redirecting the external
725// reference to a svc (Supervisor Call) instruction that is handled by
726// the simulator.  We write the original destination of the jump just at a known
727// offset from the svc instruction so the simulator knows what to call.
728class Redirection {
729 public:
730  Redirection(Isolate* isolate, void* external_function,
731              ExternalReference::Type type)
732      : external_function_(external_function),
733        swi_instruction_(al | (0xf * B24) | kCallRtRedirected),
734        type_(type),
735        next_(NULL) {
736    next_ = isolate->simulator_redirection();
737    Simulator::current(isolate)->
738        FlushICache(isolate->simulator_i_cache(),
739                    reinterpret_cast<void*>(&swi_instruction_),
740                    Instruction::kInstrSize);
741    isolate->set_simulator_redirection(this);
742  }
743
744  void* address_of_swi_instruction() {
745    return reinterpret_cast<void*>(&swi_instruction_);
746  }
747
748  void* external_function() { return external_function_; }
749  ExternalReference::Type type() { return type_; }
750
751  static Redirection* Get(Isolate* isolate, void* external_function,
752                          ExternalReference::Type type) {
753    Redirection* current = isolate->simulator_redirection();
754    for (; current != NULL; current = current->next_) {
755      if (current->external_function_ == external_function) {
756        DCHECK_EQ(current->type(), type);
757        return current;
758      }
759    }
760    return new Redirection(isolate, external_function, type);
761  }
762
763  static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
764    char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
765    char* addr_of_redirection =
766        addr_of_swi - offsetof(Redirection, swi_instruction_);
767    return reinterpret_cast<Redirection*>(addr_of_redirection);
768  }
769
770  static void* ReverseRedirection(int32_t reg) {
771    Redirection* redirection = FromSwiInstruction(
772        reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
773    return redirection->external_function();
774  }
775
776  static void DeleteChain(Redirection* redirection) {
777    while (redirection != nullptr) {
778      Redirection* next = redirection->next_;
779      delete redirection;
780      redirection = next;
781    }
782  }
783
784 private:
785  void* external_function_;
786  uint32_t swi_instruction_;
787  ExternalReference::Type type_;
788  Redirection* next_;
789};
790
791
792// static
793void Simulator::TearDown(base::CustomMatcherHashMap* i_cache,
794                         Redirection* first) {
795  Redirection::DeleteChain(first);
796  if (i_cache != nullptr) {
797    for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
798         entry = i_cache->Next(entry)) {
799      delete static_cast<CachePage*>(entry->value);
800    }
801    delete i_cache;
802  }
803}
804
805
806void* Simulator::RedirectExternalReference(Isolate* isolate,
807                                           void* external_function,
808                                           ExternalReference::Type type) {
809  Redirection* redirection = Redirection::Get(isolate, external_function, type);
810  return redirection->address_of_swi_instruction();
811}
812
813
814// Get the active Simulator for the current thread.
815Simulator* Simulator::current(Isolate* isolate) {
816  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
817      isolate->FindOrAllocatePerThreadDataForThisThread();
818  DCHECK(isolate_data != NULL);
819
820  Simulator* sim = isolate_data->simulator();
821  if (sim == NULL) {
822    // TODO(146): delete the simulator object when a thread/isolate goes away.
823    sim = new Simulator(isolate);
824    isolate_data->set_simulator(sim);
825  }
826  return sim;
827}
828
829
830// Sets the register in the architecture state. It will also deal with updating
831// Simulator internal state for special registers such as PC.
832void Simulator::set_register(int reg, int32_t value) {
833  DCHECK((reg >= 0) && (reg < num_registers));
834  if (reg == pc) {
835    pc_modified_ = true;
836  }
837  registers_[reg] = value;
838}
839
840
841// Get the register from the architecture state. This function does handle
842// the special case of accessing the PC register.
843int32_t Simulator::get_register(int reg) const {
844  DCHECK((reg >= 0) && (reg < num_registers));
845  // Stupid code added to avoid bug in GCC.
846  // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
847  if (reg >= num_registers) return 0;
848  // End stupid code.
849  return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
850}
851
852
853double Simulator::get_double_from_register_pair(int reg) {
854  DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
855
856  double dm_val = 0.0;
857  // Read the bits from the unsigned integer register_[] array
858  // into the double precision floating point value and return it.
859  char buffer[2 * sizeof(vfp_registers_[0])];
860  memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
861  memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
862  return(dm_val);
863}
864
865
866void Simulator::set_register_pair_from_double(int reg, double* value) {
867  DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
868  memcpy(registers_ + reg, value, sizeof(*value));
869}
870
871
872void Simulator::set_dw_register(int dreg, const int* dbl) {
873  DCHECK((dreg >= 0) && (dreg < num_d_registers));
874  registers_[dreg] = dbl[0];
875  registers_[dreg + 1] = dbl[1];
876}
877
878
879void Simulator::get_d_register(int dreg, uint64_t* value) {
880  DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
881  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
882}
883
884
885void Simulator::set_d_register(int dreg, const uint64_t* value) {
886  DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
887  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
888}
889
890
891void Simulator::get_d_register(int dreg, uint32_t* value) {
892  DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
893  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
894}
895
896
897void Simulator::set_d_register(int dreg, const uint32_t* value) {
898  DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
899  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
900}
901
902template <typename T>
903void Simulator::get_q_register(int qreg, T* value) {
904  DCHECK((qreg >= 0) && (qreg < num_q_registers));
905  memcpy(value, vfp_registers_ + qreg * 4, kSimd128Size);
906}
907
908template <typename T>
909void Simulator::set_q_register(int qreg, const T* value) {
910  DCHECK((qreg >= 0) && (qreg < num_q_registers));
911  memcpy(vfp_registers_ + qreg * 4, value, kSimd128Size);
912}
913
914
915// Raw access to the PC register.
916void Simulator::set_pc(int32_t value) {
917  pc_modified_ = true;
918  registers_[pc] = value;
919}
920
921
922bool Simulator::has_bad_pc() const {
923  return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
924}
925
926
927// Raw access to the PC register without the special adjustment when reading.
928int32_t Simulator::get_pc() const {
929  return registers_[pc];
930}
931
932
933// Getting from and setting into VFP registers.
934void Simulator::set_s_register(int sreg, unsigned int value) {
935  DCHECK((sreg >= 0) && (sreg < num_s_registers));
936  vfp_registers_[sreg] = value;
937}
938
939
940unsigned int Simulator::get_s_register(int sreg) const {
941  DCHECK((sreg >= 0) && (sreg < num_s_registers));
942  return vfp_registers_[sreg];
943}
944
945
946template<class InputType, int register_size>
947void Simulator::SetVFPRegister(int reg_index, const InputType& value) {
948  DCHECK(reg_index >= 0);
949  if (register_size == 1) DCHECK(reg_index < num_s_registers);
950  if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
951
952  char buffer[register_size * sizeof(vfp_registers_[0])];
953  memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
954  memcpy(&vfp_registers_[reg_index * register_size], buffer,
955         register_size * sizeof(vfp_registers_[0]));
956}
957
958
959template<class ReturnType, int register_size>
960ReturnType Simulator::GetFromVFPRegister(int reg_index) {
961  DCHECK(reg_index >= 0);
962  if (register_size == 1) DCHECK(reg_index < num_s_registers);
963  if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
964
965  ReturnType value = 0;
966  char buffer[register_size * sizeof(vfp_registers_[0])];
967  memcpy(buffer, &vfp_registers_[register_size * reg_index],
968         register_size * sizeof(vfp_registers_[0]));
969  memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
970  return value;
971}
972
973void Simulator::SetSpecialRegister(SRegisterFieldMask reg_and_mask,
974                                   uint32_t value) {
975  // Only CPSR_f is implemented. Of that, only N, Z, C and V are implemented.
976  if ((reg_and_mask == CPSR_f) && ((value & ~kSpecialCondition) == 0)) {
977    n_flag_ = ((value & (1 << 31)) != 0);
978    z_flag_ = ((value & (1 << 30)) != 0);
979    c_flag_ = ((value & (1 << 29)) != 0);
980    v_flag_ = ((value & (1 << 28)) != 0);
981  } else {
982    UNIMPLEMENTED();
983  }
984}
985
986uint32_t Simulator::GetFromSpecialRegister(SRegister reg) {
987  uint32_t result = 0;
988  // Only CPSR_f is implemented.
989  if (reg == CPSR) {
990    if (n_flag_) result |= (1 << 31);
991    if (z_flag_) result |= (1 << 30);
992    if (c_flag_) result |= (1 << 29);
993    if (v_flag_) result |= (1 << 28);
994  } else {
995    UNIMPLEMENTED();
996  }
997  return result;
998}
999
1000// Runtime FP routines take:
1001// - two double arguments
1002// - one double argument and zero or one integer arguments.
1003// All are consructed here from r0-r3 or d0, d1 and r0.
1004void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1005  if (use_eabi_hardfloat()) {
1006    *x = get_double_from_d_register(0);
1007    *y = get_double_from_d_register(1);
1008    *z = get_register(0);
1009  } else {
1010    // Registers 0 and 1 -> x.
1011    *x = get_double_from_register_pair(0);
1012    // Register 2 and 3 -> y.
1013    *y = get_double_from_register_pair(2);
1014    // Register 2 -> z
1015    *z = get_register(2);
1016  }
1017}
1018
1019
1020// The return value is either in r0/r1 or d0.
1021void Simulator::SetFpResult(const double& result) {
1022  if (use_eabi_hardfloat()) {
1023    char buffer[2 * sizeof(vfp_registers_[0])];
1024    memcpy(buffer, &result, sizeof(buffer));
1025    // Copy result to d0.
1026    memcpy(vfp_registers_, buffer, sizeof(buffer));
1027  } else {
1028    char buffer[2 * sizeof(registers_[0])];
1029    memcpy(buffer, &result, sizeof(buffer));
1030    // Copy result to r0 and r1.
1031    memcpy(registers_, buffer, sizeof(buffer));
1032  }
1033}
1034
1035
1036void Simulator::TrashCallerSaveRegisters() {
1037  // We don't trash the registers with the return value.
1038  registers_[2] = 0x50Bad4U;
1039  registers_[3] = 0x50Bad4U;
1040  registers_[12] = 0x50Bad4U;
1041}
1042
1043
1044int Simulator::ReadW(int32_t addr, Instruction* instr) {
1045  // All supported ARM targets allow unaligned accesses, so we don't need to
1046  // check the alignment here.
1047  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1048  local_monitor_.NotifyLoad(addr);
1049  intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1050  return *ptr;
1051}
1052
1053int Simulator::ReadExW(int32_t addr, Instruction* instr) {
1054  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1055  local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word);
1056  global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1057                                                   &global_monitor_processor_);
1058  intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1059  return *ptr;
1060}
1061
1062void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1063  // All supported ARM targets allow unaligned accesses, so we don't need to
1064  // check the alignment here.
1065  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1066  local_monitor_.NotifyStore(addr);
1067  global_monitor_.Pointer()->NotifyStore_Locked(addr,
1068                                                &global_monitor_processor_);
1069  intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1070  *ptr = value;
1071}
1072
1073int Simulator::WriteExW(int32_t addr, int value, Instruction* instr) {
1074  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1075  if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) &&
1076      global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1077          addr, &global_monitor_processor_)) {
1078    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1079    *ptr = value;
1080    return 0;
1081  } else {
1082    return 1;
1083  }
1084}
1085
1086uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1087  // All supported ARM targets allow unaligned accesses, so we don't need to
1088  // check the alignment here.
1089  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1090  local_monitor_.NotifyLoad(addr);
1091  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1092  return *ptr;
1093}
1094
1095int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1096  // All supported ARM targets allow unaligned accesses, so we don't need to
1097  // check the alignment here.
1098  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1099  local_monitor_.NotifyLoad(addr);
1100  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1101  return *ptr;
1102}
1103
1104uint16_t Simulator::ReadExHU(int32_t addr, Instruction* instr) {
1105  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1106  local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord);
1107  global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1108                                                   &global_monitor_processor_);
1109  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1110  return *ptr;
1111}
1112
1113void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1114  // All supported ARM targets allow unaligned accesses, so we don't need to
1115  // check the alignment here.
1116  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1117  local_monitor_.NotifyStore(addr);
1118  global_monitor_.Pointer()->NotifyStore_Locked(addr,
1119                                                &global_monitor_processor_);
1120  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1121  *ptr = value;
1122}
1123
1124void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1125  // All supported ARM targets allow unaligned accesses, so we don't need to
1126  // check the alignment here.
1127  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1128  local_monitor_.NotifyStore(addr);
1129  global_monitor_.Pointer()->NotifyStore_Locked(addr,
1130                                                &global_monitor_processor_);
1131  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1132  *ptr = value;
1133}
1134
1135int Simulator::WriteExH(int32_t addr, uint16_t value, Instruction* instr) {
1136  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1137  if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) &&
1138      global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1139          addr, &global_monitor_processor_)) {
1140    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1141    *ptr = value;
1142    return 0;
1143  } else {
1144    return 1;
1145  }
1146}
1147
1148uint8_t Simulator::ReadBU(int32_t addr) {
1149  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1150  local_monitor_.NotifyLoad(addr);
1151  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1152  return *ptr;
1153}
1154
1155int8_t Simulator::ReadB(int32_t addr) {
1156  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1157  local_monitor_.NotifyLoad(addr);
1158  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1159  return *ptr;
1160}
1161
1162uint8_t Simulator::ReadExBU(int32_t addr) {
1163  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1164  local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte);
1165  global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
1166                                                   &global_monitor_processor_);
1167  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1168  return *ptr;
1169}
1170
1171void Simulator::WriteB(int32_t addr, uint8_t value) {
1172  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1173  local_monitor_.NotifyStore(addr);
1174  global_monitor_.Pointer()->NotifyStore_Locked(addr,
1175                                                &global_monitor_processor_);
1176  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1177  *ptr = value;
1178}
1179
1180void Simulator::WriteB(int32_t addr, int8_t value) {
1181  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1182  local_monitor_.NotifyStore(addr);
1183  global_monitor_.Pointer()->NotifyStore_Locked(addr,
1184                                                &global_monitor_processor_);
1185  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1186  *ptr = value;
1187}
1188
1189int Simulator::WriteExB(int32_t addr, uint8_t value) {
1190  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1191  if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) &&
1192      global_monitor_.Pointer()->NotifyStoreExcl_Locked(
1193          addr, &global_monitor_processor_)) {
1194    uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1195    *ptr = value;
1196    return 0;
1197  } else {
1198    return 1;
1199  }
1200}
1201
1202int32_t* Simulator::ReadDW(int32_t addr) {
1203  // All supported ARM targets allow unaligned accesses, so we don't need to
1204  // check the alignment here.
1205  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1206  local_monitor_.NotifyLoad(addr);
1207  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1208  return ptr;
1209}
1210
1211
1212void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1213  // All supported ARM targets allow unaligned accesses, so we don't need to
1214  // check the alignment here.
1215  base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
1216  local_monitor_.NotifyStore(addr);
1217  global_monitor_.Pointer()->NotifyStore_Locked(addr,
1218                                                &global_monitor_processor_);
1219  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1220  *ptr++ = value1;
1221  *ptr = value2;
1222}
1223
1224
1225// Returns the limit of the stack area to enable checking for stack overflows.
1226uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
1227  // The simulator uses a separate JS stack. If we have exhausted the C stack,
1228  // we also drop down the JS limit to reflect the exhaustion on the JS stack.
1229  if (GetCurrentStackPosition() < c_limit) {
1230    return reinterpret_cast<uintptr_t>(get_sp());
1231  }
1232
1233  // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
1234  // to prevent overrunning the stack when pushing values.
1235  return reinterpret_cast<uintptr_t>(stack_) + 1024;
1236}
1237
1238
1239// Unsupported instructions use Format to print an error and stop execution.
1240void Simulator::Format(Instruction* instr, const char* format) {
1241  PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
1242         reinterpret_cast<intptr_t>(instr), format);
1243  UNIMPLEMENTED();
1244}
1245
1246
1247// Checks if the current instruction should be executed based on its
1248// condition bits.
1249bool Simulator::ConditionallyExecute(Instruction* instr) {
1250  switch (instr->ConditionField()) {
1251    case eq: return z_flag_;
1252    case ne: return !z_flag_;
1253    case cs: return c_flag_;
1254    case cc: return !c_flag_;
1255    case mi: return n_flag_;
1256    case pl: return !n_flag_;
1257    case vs: return v_flag_;
1258    case vc: return !v_flag_;
1259    case hi: return c_flag_ && !z_flag_;
1260    case ls: return !c_flag_ || z_flag_;
1261    case ge: return n_flag_ == v_flag_;
1262    case lt: return n_flag_ != v_flag_;
1263    case gt: return !z_flag_ && (n_flag_ == v_flag_);
1264    case le: return z_flag_ || (n_flag_ != v_flag_);
1265    case al: return true;
1266    default: UNREACHABLE();
1267  }
1268  return false;
1269}
1270
1271
1272// Calculate and set the Negative and Zero flags.
1273void Simulator::SetNZFlags(int32_t val) {
1274  n_flag_ = (val < 0);
1275  z_flag_ = (val == 0);
1276}
1277
1278
1279// Set the Carry flag.
1280void Simulator::SetCFlag(bool val) {
1281  c_flag_ = val;
1282}
1283
1284
1285// Set the oVerflow flag.
1286void Simulator::SetVFlag(bool val) {
1287  v_flag_ = val;
1288}
1289
1290
1291// Calculate C flag value for additions.
1292bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1293  uint32_t uleft = static_cast<uint32_t>(left);
1294  uint32_t uright = static_cast<uint32_t>(right);
1295  uint32_t urest  = 0xffffffffU - uleft;
1296
1297  return (uright > urest) ||
1298         (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1299}
1300
1301
1302// Calculate C flag value for subtractions.
1303bool Simulator::BorrowFrom(int32_t left, int32_t right, int32_t carry) {
1304  uint32_t uleft = static_cast<uint32_t>(left);
1305  uint32_t uright = static_cast<uint32_t>(right);
1306
1307  return (uright > uleft) ||
1308         (!carry && (((uright + 1) > uleft) || (uright > (uleft - 1))));
1309}
1310
1311
1312// Calculate V flag value for additions and subtractions.
1313bool Simulator::OverflowFrom(int32_t alu_out,
1314                             int32_t left, int32_t right, bool addition) {
1315  bool overflow;
1316  if (addition) {
1317               // operands have the same sign
1318    overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1319               // and operands and result have different sign
1320               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1321  } else {
1322               // operands have different signs
1323    overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1324               // and first operand and result have different signs
1325               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1326  }
1327  return overflow;
1328}
1329
1330
1331// Support for VFP comparisons.
1332void Simulator::Compute_FPSCR_Flags(float val1, float val2) {
1333  if (std::isnan(val1) || std::isnan(val2)) {
1334    n_flag_FPSCR_ = false;
1335    z_flag_FPSCR_ = false;
1336    c_flag_FPSCR_ = true;
1337    v_flag_FPSCR_ = true;
1338    // All non-NaN cases.
1339  } else if (val1 == val2) {
1340    n_flag_FPSCR_ = false;
1341    z_flag_FPSCR_ = true;
1342    c_flag_FPSCR_ = true;
1343    v_flag_FPSCR_ = false;
1344  } else if (val1 < val2) {
1345    n_flag_FPSCR_ = true;
1346    z_flag_FPSCR_ = false;
1347    c_flag_FPSCR_ = false;
1348    v_flag_FPSCR_ = false;
1349  } else {
1350    // Case when (val1 > val2).
1351    n_flag_FPSCR_ = false;
1352    z_flag_FPSCR_ = false;
1353    c_flag_FPSCR_ = true;
1354    v_flag_FPSCR_ = false;
1355  }
1356}
1357
1358
1359void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
1360  if (std::isnan(val1) || std::isnan(val2)) {
1361    n_flag_FPSCR_ = false;
1362    z_flag_FPSCR_ = false;
1363    c_flag_FPSCR_ = true;
1364    v_flag_FPSCR_ = true;
1365  // All non-NaN cases.
1366  } else if (val1 == val2) {
1367    n_flag_FPSCR_ = false;
1368    z_flag_FPSCR_ = true;
1369    c_flag_FPSCR_ = true;
1370    v_flag_FPSCR_ = false;
1371  } else if (val1 < val2) {
1372    n_flag_FPSCR_ = true;
1373    z_flag_FPSCR_ = false;
1374    c_flag_FPSCR_ = false;
1375    v_flag_FPSCR_ = false;
1376  } else {
1377    // Case when (val1 > val2).
1378    n_flag_FPSCR_ = false;
1379    z_flag_FPSCR_ = false;
1380    c_flag_FPSCR_ = true;
1381    v_flag_FPSCR_ = false;
1382  }
1383}
1384
1385
1386void Simulator::Copy_FPSCR_to_APSR() {
1387  n_flag_ = n_flag_FPSCR_;
1388  z_flag_ = z_flag_FPSCR_;
1389  c_flag_ = c_flag_FPSCR_;
1390  v_flag_ = v_flag_FPSCR_;
1391}
1392
1393
1394// Addressing Mode 1 - Data-processing operands:
1395// Get the value based on the shifter_operand with register.
1396int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
1397  ShiftOp shift = instr->ShiftField();
1398  int shift_amount = instr->ShiftAmountValue();
1399  int32_t result = get_register(instr->RmValue());
1400  if (instr->Bit(4) == 0) {
1401    // by immediate
1402    if ((shift == ROR) && (shift_amount == 0)) {
1403      UNIMPLEMENTED();
1404      return result;
1405    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1406      shift_amount = 32;
1407    }
1408    switch (shift) {
1409      case ASR: {
1410        if (shift_amount == 0) {
1411          if (result < 0) {
1412            result = 0xffffffff;
1413            *carry_out = true;
1414          } else {
1415            result = 0;
1416            *carry_out = false;
1417          }
1418        } else {
1419          result >>= (shift_amount - 1);
1420          *carry_out = (result & 1) == 1;
1421          result >>= 1;
1422        }
1423        break;
1424      }
1425
1426      case LSL: {
1427        if (shift_amount == 0) {
1428          *carry_out = c_flag_;
1429        } else {
1430          result <<= (shift_amount - 1);
1431          *carry_out = (result < 0);
1432          result <<= 1;
1433        }
1434        break;
1435      }
1436
1437      case LSR: {
1438        if (shift_amount == 0) {
1439          result = 0;
1440          *carry_out = c_flag_;
1441        } else {
1442          uint32_t uresult = static_cast<uint32_t>(result);
1443          uresult >>= (shift_amount - 1);
1444          *carry_out = (uresult & 1) == 1;
1445          uresult >>= 1;
1446          result = static_cast<int32_t>(uresult);
1447        }
1448        break;
1449      }
1450
1451      case ROR: {
1452        if (shift_amount == 0) {
1453          *carry_out = c_flag_;
1454        } else {
1455          uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1456          uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1457          result = right | left;
1458          *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1459        }
1460        break;
1461      }
1462
1463      default: {
1464        UNREACHABLE();
1465        break;
1466      }
1467    }
1468  } else {
1469    // by register
1470    int rs = instr->RsValue();
1471    shift_amount = get_register(rs) &0xff;
1472    switch (shift) {
1473      case ASR: {
1474        if (shift_amount == 0) {
1475          *carry_out = c_flag_;
1476        } else if (shift_amount < 32) {
1477          result >>= (shift_amount - 1);
1478          *carry_out = (result & 1) == 1;
1479          result >>= 1;
1480        } else {
1481          DCHECK(shift_amount >= 32);
1482          if (result < 0) {
1483            *carry_out = true;
1484            result = 0xffffffff;
1485          } else {
1486            *carry_out = false;
1487            result = 0;
1488          }
1489        }
1490        break;
1491      }
1492
1493      case LSL: {
1494        if (shift_amount == 0) {
1495          *carry_out = c_flag_;
1496        } else if (shift_amount < 32) {
1497          result <<= (shift_amount - 1);
1498          *carry_out = (result < 0);
1499          result <<= 1;
1500        } else if (shift_amount == 32) {
1501          *carry_out = (result & 1) == 1;
1502          result = 0;
1503        } else {
1504          DCHECK(shift_amount > 32);
1505          *carry_out = false;
1506          result = 0;
1507        }
1508        break;
1509      }
1510
1511      case LSR: {
1512        if (shift_amount == 0) {
1513          *carry_out = c_flag_;
1514        } else if (shift_amount < 32) {
1515          uint32_t uresult = static_cast<uint32_t>(result);
1516          uresult >>= (shift_amount - 1);
1517          *carry_out = (uresult & 1) == 1;
1518          uresult >>= 1;
1519          result = static_cast<int32_t>(uresult);
1520        } else if (shift_amount == 32) {
1521          *carry_out = (result < 0);
1522          result = 0;
1523        } else {
1524          *carry_out = false;
1525          result = 0;
1526        }
1527        break;
1528      }
1529
1530      case ROR: {
1531        if (shift_amount == 0) {
1532          *carry_out = c_flag_;
1533        } else {
1534          uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1535          uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1536          result = right | left;
1537          *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1538        }
1539        break;
1540      }
1541
1542      default: {
1543        UNREACHABLE();
1544        break;
1545      }
1546    }
1547  }
1548  return result;
1549}
1550
1551
1552// Addressing Mode 1 - Data-processing operands:
1553// Get the value based on the shifter_operand with immediate.
1554int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
1555  int rotate = instr->RotateValue() * 2;
1556  int immed8 = instr->Immed8Value();
1557  int imm = base::bits::RotateRight32(immed8, rotate);
1558  *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1559  return imm;
1560}
1561
1562
1563static int count_bits(int bit_vector) {
1564  int count = 0;
1565  while (bit_vector != 0) {
1566    if ((bit_vector & 1) != 0) {
1567      count++;
1568    }
1569    bit_vector >>= 1;
1570  }
1571  return count;
1572}
1573
1574
1575int32_t Simulator::ProcessPU(Instruction* instr,
1576                             int num_regs,
1577                             int reg_size,
1578                             intptr_t* start_address,
1579                             intptr_t* end_address) {
1580  int rn = instr->RnValue();
1581  int32_t rn_val = get_register(rn);
1582  switch (instr->PUField()) {
1583    case da_x: {
1584      UNIMPLEMENTED();
1585      break;
1586    }
1587    case ia_x: {
1588      *start_address = rn_val;
1589      *end_address = rn_val + (num_regs * reg_size) - reg_size;
1590      rn_val = rn_val + (num_regs * reg_size);
1591      break;
1592    }
1593    case db_x: {
1594      *start_address = rn_val - (num_regs * reg_size);
1595      *end_address = rn_val - reg_size;
1596      rn_val = *start_address;
1597      break;
1598    }
1599    case ib_x: {
1600      *start_address = rn_val + reg_size;
1601      *end_address = rn_val + (num_regs * reg_size);
1602      rn_val = *end_address;
1603      break;
1604    }
1605    default: {
1606      UNREACHABLE();
1607      break;
1608    }
1609  }
1610  return rn_val;
1611}
1612
1613
1614// Addressing Mode 4 - Load and Store Multiple
1615void Simulator::HandleRList(Instruction* instr, bool load) {
1616  int rlist = instr->RlistValue();
1617  int num_regs = count_bits(rlist);
1618
1619  intptr_t start_address = 0;
1620  intptr_t end_address = 0;
1621  int32_t rn_val =
1622      ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
1623
1624  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1625  // Catch null pointers a little earlier.
1626  DCHECK(start_address > 8191 || start_address < 0);
1627  int reg = 0;
1628  while (rlist != 0) {
1629    if ((rlist & 1) != 0) {
1630      if (load) {
1631        set_register(reg, *address);
1632      } else {
1633        *address = get_register(reg);
1634      }
1635      address += 1;
1636    }
1637    reg++;
1638    rlist >>= 1;
1639  }
1640  DCHECK(end_address == ((intptr_t)address) - 4);
1641  if (instr->HasW()) {
1642    set_register(instr->RnValue(), rn_val);
1643  }
1644}
1645
1646
1647// Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
1648void Simulator::HandleVList(Instruction* instr) {
1649  VFPRegPrecision precision =
1650      (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1651  int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1652
1653  bool load = (instr->VLValue() == 0x1);
1654
1655  int vd;
1656  int num_regs;
1657  vd = instr->VFPDRegValue(precision);
1658  if (precision == kSinglePrecision) {
1659    num_regs = instr->Immed8Value();
1660  } else {
1661    num_regs = instr->Immed8Value() / 2;
1662  }
1663
1664  intptr_t start_address = 0;
1665  intptr_t end_address = 0;
1666  int32_t rn_val =
1667      ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1668
1669  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1670  for (int reg = vd; reg < vd + num_regs; reg++) {
1671    if (precision == kSinglePrecision) {
1672      if (load) {
1673        set_s_register_from_sinteger(
1674            reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1675      } else {
1676        WriteW(reinterpret_cast<int32_t>(address),
1677               get_sinteger_from_s_register(reg), instr);
1678      }
1679      address += 1;
1680    } else {
1681      if (load) {
1682        int32_t data[] = {
1683          ReadW(reinterpret_cast<int32_t>(address), instr),
1684          ReadW(reinterpret_cast<int32_t>(address + 1), instr)
1685        };
1686        set_d_register(reg, reinterpret_cast<uint32_t*>(data));
1687      } else {
1688        uint32_t data[2];
1689        get_d_register(reg, data);
1690        WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
1691        WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
1692      }
1693      address += 2;
1694    }
1695  }
1696  DCHECK(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1697  if (instr->HasW()) {
1698    set_register(instr->RnValue(), rn_val);
1699  }
1700}
1701
1702
1703// Calls into the V8 runtime are based on this very simple interface.
1704// Note: To be able to return two values from some calls the code in runtime.cc
1705// uses the ObjectPair which is essentially two 32-bit values stuffed into a
1706// 64-bit value. With the code below we assume that all runtime calls return
1707// 64 bits of result. If they don't, the r1 result register contains a bogus
1708// value, which is fine because it is caller-saved.
1709typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1710                                        int32_t arg1,
1711                                        int32_t arg2,
1712                                        int32_t arg3,
1713                                        int32_t arg4,
1714                                        int32_t arg5);
1715
1716typedef ObjectTriple (*SimulatorRuntimeTripleCall)(int32_t arg0, int32_t arg1,
1717                                                   int32_t arg2, int32_t arg3,
1718                                                   int32_t arg4);
1719
1720// These prototypes handle the four types of FP calls.
1721typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1722typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1723typedef double (*SimulatorRuntimeFPCall)(double darg0);
1724typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1725
1726// This signature supports direct call in to API function native callback
1727// (refer to InvocationCallback in v8.h).
1728typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1729typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
1730
1731// This signature supports direct call to accessor getter callback.
1732typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1733typedef void (*SimulatorRuntimeProfilingGetterCall)(
1734    int32_t arg0, int32_t arg1, void* arg2);
1735
1736// Software interrupt instructions are used by the simulator to call into the
1737// C-based V8 runtime.
1738void Simulator::SoftwareInterrupt(Instruction* instr) {
1739  int svc = instr->SvcValue();
1740  switch (svc) {
1741    case kCallRtRedirected: {
1742      // Check if stack is aligned. Error if not aligned is reported below to
1743      // include information on the function called.
1744      bool stack_aligned =
1745          (get_register(sp)
1746           & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1747      Redirection* redirection = Redirection::FromSwiInstruction(instr);
1748      int32_t arg0 = get_register(r0);
1749      int32_t arg1 = get_register(r1);
1750      int32_t arg2 = get_register(r2);
1751      int32_t arg3 = get_register(r3);
1752      int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1753      int32_t arg4 = stack_pointer[0];
1754      int32_t arg5 = stack_pointer[1];
1755      bool fp_call =
1756         (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1757         (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1758         (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1759         (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1760      // This is dodgy but it works because the C entry stubs are never moved.
1761      // See comment in codegen-arm.cc and bug 1242173.
1762      int32_t saved_lr = get_register(lr);
1763      intptr_t external =
1764          reinterpret_cast<intptr_t>(redirection->external_function());
1765      if (fp_call) {
1766        double dval0, dval1;  // one or two double parameters
1767        int32_t ival;         // zero or one integer parameters
1768        int64_t iresult = 0;  // integer return value
1769        double dresult = 0;   // double return value
1770        GetFpArgs(&dval0, &dval1, &ival);
1771        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1772          SimulatorRuntimeCall generic_target =
1773            reinterpret_cast<SimulatorRuntimeCall>(external);
1774          switch (redirection->type()) {
1775          case ExternalReference::BUILTIN_FP_FP_CALL:
1776          case ExternalReference::BUILTIN_COMPARE_CALL:
1777            PrintF("Call to host function at %p with args %f, %f",
1778                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
1779                   dval1);
1780            break;
1781          case ExternalReference::BUILTIN_FP_CALL:
1782            PrintF("Call to host function at %p with arg %f",
1783                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
1784            break;
1785          case ExternalReference::BUILTIN_FP_INT_CALL:
1786            PrintF("Call to host function at %p with args %f, %d",
1787                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
1788                   ival);
1789            break;
1790          default:
1791            UNREACHABLE();
1792            break;
1793          }
1794          if (!stack_aligned) {
1795            PrintF(" with unaligned stack %08x\n", get_register(sp));
1796          }
1797          PrintF("\n");
1798        }
1799        CHECK(stack_aligned);
1800        switch (redirection->type()) {
1801        case ExternalReference::BUILTIN_COMPARE_CALL: {
1802          SimulatorRuntimeCompareCall target =
1803            reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1804          iresult = target(dval0, dval1);
1805          set_register(r0, static_cast<int32_t>(iresult));
1806          set_register(r1, static_cast<int32_t>(iresult >> 32));
1807          break;
1808        }
1809        case ExternalReference::BUILTIN_FP_FP_CALL: {
1810          SimulatorRuntimeFPFPCall target =
1811            reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1812          dresult = target(dval0, dval1);
1813          SetFpResult(dresult);
1814          break;
1815        }
1816        case ExternalReference::BUILTIN_FP_CALL: {
1817          SimulatorRuntimeFPCall target =
1818            reinterpret_cast<SimulatorRuntimeFPCall>(external);
1819          dresult = target(dval0);
1820          SetFpResult(dresult);
1821          break;
1822        }
1823        case ExternalReference::BUILTIN_FP_INT_CALL: {
1824          SimulatorRuntimeFPIntCall target =
1825            reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1826          dresult = target(dval0, ival);
1827          SetFpResult(dresult);
1828          break;
1829        }
1830        default:
1831          UNREACHABLE();
1832          break;
1833        }
1834        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1835          switch (redirection->type()) {
1836          case ExternalReference::BUILTIN_COMPARE_CALL:
1837            PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1838            break;
1839          case ExternalReference::BUILTIN_FP_FP_CALL:
1840          case ExternalReference::BUILTIN_FP_CALL:
1841          case ExternalReference::BUILTIN_FP_INT_CALL:
1842            PrintF("Returned %f\n", dresult);
1843            break;
1844          default:
1845            UNREACHABLE();
1846            break;
1847          }
1848        }
1849      } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1850        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1851          PrintF("Call to host function at %p args %08x",
1852              reinterpret_cast<void*>(external), arg0);
1853          if (!stack_aligned) {
1854            PrintF(" with unaligned stack %08x\n", get_register(sp));
1855          }
1856          PrintF("\n");
1857        }
1858        CHECK(stack_aligned);
1859        SimulatorRuntimeDirectApiCall target =
1860            reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1861        target(arg0);
1862      } else if (
1863          redirection->type() == ExternalReference::PROFILING_API_CALL) {
1864        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1865          PrintF("Call to host function at %p args %08x %08x",
1866              reinterpret_cast<void*>(external), arg0, arg1);
1867          if (!stack_aligned) {
1868            PrintF(" with unaligned stack %08x\n", get_register(sp));
1869          }
1870          PrintF("\n");
1871        }
1872        CHECK(stack_aligned);
1873        SimulatorRuntimeProfilingApiCall target =
1874            reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1875        target(arg0, Redirection::ReverseRedirection(arg1));
1876      } else if (
1877          redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1878        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1879          PrintF("Call to host function at %p args %08x %08x",
1880              reinterpret_cast<void*>(external), arg0, arg1);
1881          if (!stack_aligned) {
1882            PrintF(" with unaligned stack %08x\n", get_register(sp));
1883          }
1884          PrintF("\n");
1885        }
1886        CHECK(stack_aligned);
1887        SimulatorRuntimeDirectGetterCall target =
1888            reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1889        target(arg0, arg1);
1890      } else if (
1891          redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1892        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1893          PrintF("Call to host function at %p args %08x %08x %08x",
1894              reinterpret_cast<void*>(external), arg0, arg1, arg2);
1895          if (!stack_aligned) {
1896            PrintF(" with unaligned stack %08x\n", get_register(sp));
1897          }
1898          PrintF("\n");
1899        }
1900        CHECK(stack_aligned);
1901        SimulatorRuntimeProfilingGetterCall target =
1902            reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
1903                external);
1904        target(arg0, arg1, Redirection::ReverseRedirection(arg2));
1905      } else if (redirection->type() ==
1906                 ExternalReference::BUILTIN_CALL_TRIPLE) {
1907        // builtin call returning ObjectTriple.
1908        SimulatorRuntimeTripleCall target =
1909            reinterpret_cast<SimulatorRuntimeTripleCall>(external);
1910        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1911          PrintF(
1912              "Call to host triple returning runtime function %p "
1913              "args %08x, %08x, %08x, %08x, %08x",
1914              static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
1915              arg5);
1916          if (!stack_aligned) {
1917            PrintF(" with unaligned stack %08x\n", get_register(sp));
1918          }
1919          PrintF("\n");
1920        }
1921        CHECK(stack_aligned);
1922        // arg0 is a hidden argument pointing to the return location, so don't
1923        // pass it to the target function.
1924        ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
1925        if (::v8::internal::FLAG_trace_sim) {
1926          PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
1927                 static_cast<void*>(result.y), static_cast<void*>(result.z));
1928        }
1929        // Return is passed back in address pointed to by hidden first argument.
1930        ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
1931        *sim_result = result;
1932        set_register(r0, arg0);
1933      } else {
1934        // builtin call.
1935        DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
1936               redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
1937        SimulatorRuntimeCall target =
1938            reinterpret_cast<SimulatorRuntimeCall>(external);
1939        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1940          PrintF(
1941              "Call to host function at %p "
1942              "args %08x, %08x, %08x, %08x, %08x, %08x",
1943              static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
1944              arg4, arg5);
1945          if (!stack_aligned) {
1946            PrintF(" with unaligned stack %08x\n", get_register(sp));
1947          }
1948          PrintF("\n");
1949        }
1950        CHECK(stack_aligned);
1951        int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1952        int32_t lo_res = static_cast<int32_t>(result);
1953        int32_t hi_res = static_cast<int32_t>(result >> 32);
1954        if (::v8::internal::FLAG_trace_sim) {
1955          PrintF("Returned %08x\n", lo_res);
1956        }
1957        set_register(r0, lo_res);
1958        set_register(r1, hi_res);
1959      }
1960      set_register(lr, saved_lr);
1961      set_pc(get_register(lr));
1962      break;
1963    }
1964    case kBreakpoint: {
1965      ArmDebugger dbg(this);
1966      dbg.Debug();
1967      break;
1968    }
1969    // stop uses all codes greater than 1 << 23.
1970    default: {
1971      if (svc >= (1 << 23)) {
1972        uint32_t code = svc & kStopCodeMask;
1973        if (isWatchedStop(code)) {
1974          IncreaseStopCounter(code);
1975        }
1976        // Stop if it is enabled, otherwise go on jumping over the stop
1977        // and the message address.
1978        if (isEnabledStop(code)) {
1979          ArmDebugger dbg(this);
1980          dbg.Stop(instr);
1981        } else {
1982          set_pc(get_pc() + 2 * Instruction::kInstrSize);
1983        }
1984      } else {
1985        // This is not a valid svc code.
1986        UNREACHABLE();
1987        break;
1988      }
1989    }
1990  }
1991}
1992
1993
1994float Simulator::canonicalizeNaN(float value) {
1995  // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
1996  // choices" of the ARM Reference Manual.
1997  const uint32_t kDefaultNaN = 0x7FC00000u;
1998  if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
1999    value = bit_cast<float>(kDefaultNaN);
2000  }
2001  return value;
2002}
2003
2004
2005double Simulator::canonicalizeNaN(double value) {
2006  // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
2007  // choices" of the ARM Reference Manual.
2008  const uint64_t kDefaultNaN = V8_UINT64_C(0x7FF8000000000000);
2009  if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
2010    value = bit_cast<double>(kDefaultNaN);
2011  }
2012  return value;
2013}
2014
2015
2016// Stop helper functions.
2017bool Simulator::isStopInstruction(Instruction* instr) {
2018  return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
2019}
2020
2021
2022bool Simulator::isWatchedStop(uint32_t code) {
2023  DCHECK(code <= kMaxStopCode);
2024  return code < kNumOfWatchedStops;
2025}
2026
2027
2028bool Simulator::isEnabledStop(uint32_t code) {
2029  DCHECK(code <= kMaxStopCode);
2030  // Unwatched stops are always enabled.
2031  return !isWatchedStop(code) ||
2032    !(watched_stops_[code].count & kStopDisabledBit);
2033}
2034
2035
2036void Simulator::EnableStop(uint32_t code) {
2037  DCHECK(isWatchedStop(code));
2038  if (!isEnabledStop(code)) {
2039    watched_stops_[code].count &= ~kStopDisabledBit;
2040  }
2041}
2042
2043
2044void Simulator::DisableStop(uint32_t code) {
2045  DCHECK(isWatchedStop(code));
2046  if (isEnabledStop(code)) {
2047    watched_stops_[code].count |= kStopDisabledBit;
2048  }
2049}
2050
2051
2052void Simulator::IncreaseStopCounter(uint32_t code) {
2053  DCHECK(code <= kMaxStopCode);
2054  DCHECK(isWatchedStop(code));
2055  if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
2056    PrintF("Stop counter for code %i has overflowed.\n"
2057           "Enabling this code and reseting the counter to 0.\n", code);
2058    watched_stops_[code].count = 0;
2059    EnableStop(code);
2060  } else {
2061    watched_stops_[code].count++;
2062  }
2063}
2064
2065
2066// Print a stop status.
2067void Simulator::PrintStopInfo(uint32_t code) {
2068  DCHECK(code <= kMaxStopCode);
2069  if (!isWatchedStop(code)) {
2070    PrintF("Stop not watched.");
2071  } else {
2072    const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
2073    int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
2074    // Don't print the state of unused breakpoints.
2075    if (count != 0) {
2076      if (watched_stops_[code].desc) {
2077        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
2078               code, code, state, count, watched_stops_[code].desc);
2079      } else {
2080        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
2081               code, code, state, count);
2082      }
2083    }
2084  }
2085}
2086
2087
2088// Handle execution based on instruction types.
2089
2090// Instruction types 0 and 1 are both rolled into one function because they
2091// only differ in the handling of the shifter_operand.
2092void Simulator::DecodeType01(Instruction* instr) {
2093  int type = instr->TypeValue();
2094  if ((type == 0) && instr->IsSpecialType0()) {
2095    // multiply instruction or extra loads and stores
2096    if (instr->Bits(7, 4) == 9) {
2097      if (instr->Bit(24) == 0) {
2098        // Raw field decoding here. Multiply instructions have their Rd in
2099        // funny places.
2100        int rn = instr->RnValue();
2101        int rm = instr->RmValue();
2102        int rs = instr->RsValue();
2103        int32_t rs_val = get_register(rs);
2104        int32_t rm_val = get_register(rm);
2105        if (instr->Bit(23) == 0) {
2106          if (instr->Bit(21) == 0) {
2107            // The MUL instruction description (A 4.1.33) refers to Rd as being
2108            // the destination for the operation, but it confusingly uses the
2109            // Rn field to encode it.
2110            // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
2111            int rd = rn;  // Remap the rn field to the Rd register.
2112            int32_t alu_out = rm_val * rs_val;
2113            set_register(rd, alu_out);
2114            if (instr->HasS()) {
2115              SetNZFlags(alu_out);
2116            }
2117          } else {
2118            int rd = instr->RdValue();
2119            int32_t acc_value = get_register(rd);
2120            if (instr->Bit(22) == 0) {
2121              // The MLA instruction description (A 4.1.28) refers to the order
2122              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
2123              // Rn field to encode the Rd register and the Rd field to encode
2124              // the Rn register.
2125              // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
2126              int32_t mul_out = rm_val * rs_val;
2127              int32_t result = acc_value + mul_out;
2128              set_register(rn, result);
2129            } else {
2130              // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
2131              int32_t mul_out = rm_val * rs_val;
2132              int32_t result = acc_value - mul_out;
2133              set_register(rn, result);
2134            }
2135          }
2136        } else {
2137          // The signed/long multiply instructions use the terms RdHi and RdLo
2138          // when referring to the target registers. They are mapped to the Rn
2139          // and Rd fields as follows:
2140          // RdLo == Rd
2141          // RdHi == Rn (This is confusingly stored in variable rd here
2142          //             because the mul instruction from above uses the
2143          //             Rn field to encode the Rd register. Good luck figuring
2144          //             this out without reading the ARM instruction manual
2145          //             at a very detailed level.)
2146          // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
2147          int rd_hi = rn;  // Remap the rn field to the RdHi register.
2148          int rd_lo = instr->RdValue();
2149          int32_t hi_res = 0;
2150          int32_t lo_res = 0;
2151          if (instr->Bit(22) == 1) {
2152            int64_t left_op  = static_cast<int32_t>(rm_val);
2153            int64_t right_op = static_cast<int32_t>(rs_val);
2154            uint64_t result = left_op * right_op;
2155            hi_res = static_cast<int32_t>(result >> 32);
2156            lo_res = static_cast<int32_t>(result & 0xffffffff);
2157          } else {
2158            // unsigned multiply
2159            uint64_t left_op  = static_cast<uint32_t>(rm_val);
2160            uint64_t right_op = static_cast<uint32_t>(rs_val);
2161            uint64_t result = left_op * right_op;
2162            hi_res = static_cast<int32_t>(result >> 32);
2163            lo_res = static_cast<int32_t>(result & 0xffffffff);
2164          }
2165          set_register(rd_lo, lo_res);
2166          set_register(rd_hi, hi_res);
2167          if (instr->HasS()) {
2168            UNIMPLEMENTED();
2169          }
2170        }
2171      } else {
2172        if (instr->Bits(24, 23) == 3) {
2173          if (instr->Bit(20) == 1) {
2174            // ldrex
2175            int rt = instr->RtValue();
2176            int rn = instr->RnValue();
2177            int32_t addr = get_register(rn);
2178            switch (instr->Bits(22, 21)) {
2179              case 0: {
2180                // Format(instr, "ldrex'cond 'rt, ['rn]");
2181                int value = ReadExW(addr, instr);
2182                set_register(rt, value);
2183                break;
2184              }
2185              case 2: {
2186                // Format(instr, "ldrexb'cond 'rt, ['rn]");
2187                uint8_t value = ReadExBU(addr);
2188                set_register(rt, value);
2189                break;
2190              }
2191              case 3: {
2192                // Format(instr, "ldrexh'cond 'rt, ['rn]");
2193                uint16_t value = ReadExHU(addr, instr);
2194                set_register(rt, value);
2195                break;
2196              }
2197              default:
2198                UNREACHABLE();
2199                break;
2200            }
2201          } else {
2202            // The instruction is documented as strex rd, rt, [rn], but the
2203            // "rt" register is using the rm bits.
2204            int rd = instr->RdValue();
2205            int rt = instr->RmValue();
2206            int rn = instr->RnValue();
2207            int32_t addr = get_register(rn);
2208            switch (instr->Bits(22, 21)) {
2209              case 0: {
2210                // Format(instr, "strex'cond 'rd, 'rm, ['rn]");
2211                int value = get_register(rt);
2212                int status = WriteExW(addr, value, instr);
2213                set_register(rd, status);
2214                break;
2215              }
2216              case 2: {
2217                // Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
2218                uint8_t value = get_register(rt);
2219                int status = WriteExB(addr, value);
2220                set_register(rd, status);
2221                break;
2222              }
2223              case 3: {
2224                // Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
2225                uint16_t value = get_register(rt);
2226                int status = WriteExH(addr, value, instr);
2227                set_register(rd, status);
2228                break;
2229              }
2230              default:
2231                UNREACHABLE();
2232                break;
2233            }
2234          }
2235        } else {
2236          UNIMPLEMENTED();  // Not used by V8.
2237        }
2238      }
2239    } else {
2240      // extra load/store instructions
2241      int rd = instr->RdValue();
2242      int rn = instr->RnValue();
2243      int32_t rn_val = get_register(rn);
2244      int32_t addr = 0;
2245      if (instr->Bit(22) == 0) {
2246        int rm = instr->RmValue();
2247        int32_t rm_val = get_register(rm);
2248        switch (instr->PUField()) {
2249          case da_x: {
2250            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
2251            DCHECK(!instr->HasW());
2252            addr = rn_val;
2253            rn_val -= rm_val;
2254            set_register(rn, rn_val);
2255            break;
2256          }
2257          case ia_x: {
2258            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
2259            DCHECK(!instr->HasW());
2260            addr = rn_val;
2261            rn_val += rm_val;
2262            set_register(rn, rn_val);
2263            break;
2264          }
2265          case db_x: {
2266            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
2267            rn_val -= rm_val;
2268            addr = rn_val;
2269            if (instr->HasW()) {
2270              set_register(rn, rn_val);
2271            }
2272            break;
2273          }
2274          case ib_x: {
2275            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
2276            rn_val += rm_val;
2277            addr = rn_val;
2278            if (instr->HasW()) {
2279              set_register(rn, rn_val);
2280            }
2281            break;
2282          }
2283          default: {
2284            // The PU field is a 2-bit field.
2285            UNREACHABLE();
2286            break;
2287          }
2288        }
2289      } else {
2290        int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2291        switch (instr->PUField()) {
2292          case da_x: {
2293            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
2294            DCHECK(!instr->HasW());
2295            addr = rn_val;
2296            rn_val -= imm_val;
2297            set_register(rn, rn_val);
2298            break;
2299          }
2300          case ia_x: {
2301            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
2302            DCHECK(!instr->HasW());
2303            addr = rn_val;
2304            rn_val += imm_val;
2305            set_register(rn, rn_val);
2306            break;
2307          }
2308          case db_x: {
2309            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
2310            rn_val -= imm_val;
2311            addr = rn_val;
2312            if (instr->HasW()) {
2313              set_register(rn, rn_val);
2314            }
2315            break;
2316          }
2317          case ib_x: {
2318            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
2319            rn_val += imm_val;
2320            addr = rn_val;
2321            if (instr->HasW()) {
2322              set_register(rn, rn_val);
2323            }
2324            break;
2325          }
2326          default: {
2327            // The PU field is a 2-bit field.
2328            UNREACHABLE();
2329            break;
2330          }
2331        }
2332      }
2333      if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2334        DCHECK((rd % 2) == 0);
2335        if (instr->HasH()) {
2336          // The strd instruction.
2337          int32_t value1 = get_register(rd);
2338          int32_t value2 = get_register(rd+1);
2339          WriteDW(addr, value1, value2);
2340        } else {
2341          // The ldrd instruction.
2342          int* rn_data = ReadDW(addr);
2343          set_dw_register(rd, rn_data);
2344        }
2345      } else if (instr->HasH()) {
2346        if (instr->HasSign()) {
2347          if (instr->HasL()) {
2348            int16_t val = ReadH(addr, instr);
2349            set_register(rd, val);
2350          } else {
2351            int16_t val = get_register(rd);
2352            WriteH(addr, val, instr);
2353          }
2354        } else {
2355          if (instr->HasL()) {
2356            uint16_t val = ReadHU(addr, instr);
2357            set_register(rd, val);
2358          } else {
2359            uint16_t val = get_register(rd);
2360            WriteH(addr, val, instr);
2361          }
2362        }
2363      } else {
2364        // signed byte loads
2365        DCHECK(instr->HasSign());
2366        DCHECK(instr->HasL());
2367        int8_t val = ReadB(addr);
2368        set_register(rd, val);
2369      }
2370      return;
2371    }
2372  } else if ((type == 0) && instr->IsMiscType0()) {
2373    if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
2374        (instr->Bits(15, 4) == 0xf00)) {
2375      // MSR
2376      int rm = instr->RmValue();
2377      DCHECK_NE(pc, rm);  // UNPREDICTABLE
2378      SRegisterFieldMask sreg_and_mask =
2379          instr->BitField(22, 22) | instr->BitField(19, 16);
2380      SetSpecialRegister(sreg_and_mask, get_register(rm));
2381    } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
2382               (instr->Bits(11, 0) == 0)) {
2383      // MRS
2384      int rd = instr->RdValue();
2385      DCHECK_NE(pc, rd);  // UNPREDICTABLE
2386      SRegister sreg = static_cast<SRegister>(instr->BitField(22, 22));
2387      set_register(rd, GetFromSpecialRegister(sreg));
2388    } else if (instr->Bits(22, 21) == 1) {
2389      int rm = instr->RmValue();
2390      switch (instr->BitField(7, 4)) {
2391        case BX:
2392          set_pc(get_register(rm));
2393          break;
2394        case BLX: {
2395          uint32_t old_pc = get_pc();
2396          set_pc(get_register(rm));
2397          set_register(lr, old_pc + Instruction::kInstrSize);
2398          break;
2399        }
2400        case BKPT: {
2401          ArmDebugger dbg(this);
2402          PrintF("Simulator hit BKPT.\n");
2403          dbg.Debug();
2404          break;
2405        }
2406        default:
2407          UNIMPLEMENTED();
2408      }
2409    } else if (instr->Bits(22, 21) == 3) {
2410      int rm = instr->RmValue();
2411      int rd = instr->RdValue();
2412      switch (instr->BitField(7, 4)) {
2413        case CLZ: {
2414          uint32_t bits = get_register(rm);
2415          int leading_zeros = 0;
2416          if (bits == 0) {
2417            leading_zeros = 32;
2418          } else {
2419            while ((bits & 0x80000000u) == 0) {
2420              bits <<= 1;
2421              leading_zeros++;
2422            }
2423          }
2424          set_register(rd, leading_zeros);
2425          break;
2426        }
2427        default:
2428          UNIMPLEMENTED();
2429      }
2430    } else {
2431      PrintF("%08x\n", instr->InstructionBits());
2432      UNIMPLEMENTED();
2433    }
2434  } else if ((type == 1) && instr->IsNopType1()) {
2435    // NOP.
2436  } else {
2437    int rd = instr->RdValue();
2438    int rn = instr->RnValue();
2439    int32_t rn_val = get_register(rn);
2440    int32_t shifter_operand = 0;
2441    bool shifter_carry_out = 0;
2442    if (type == 0) {
2443      shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2444    } else {
2445      DCHECK(instr->TypeValue() == 1);
2446      shifter_operand = GetImm(instr, &shifter_carry_out);
2447    }
2448    int32_t alu_out;
2449
2450    switch (instr->OpcodeField()) {
2451      case AND: {
2452        // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2453        // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2454        alu_out = rn_val & shifter_operand;
2455        set_register(rd, alu_out);
2456        if (instr->HasS()) {
2457          SetNZFlags(alu_out);
2458          SetCFlag(shifter_carry_out);
2459        }
2460        break;
2461      }
2462
2463      case EOR: {
2464        // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
2465        // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
2466        alu_out = rn_val ^ shifter_operand;
2467        set_register(rd, alu_out);
2468        if (instr->HasS()) {
2469          SetNZFlags(alu_out);
2470          SetCFlag(shifter_carry_out);
2471        }
2472        break;
2473      }
2474
2475      case SUB: {
2476        // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2477        // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2478        alu_out = rn_val - shifter_operand;
2479        set_register(rd, alu_out);
2480        if (instr->HasS()) {
2481          SetNZFlags(alu_out);
2482          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2483          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2484        }
2485        break;
2486      }
2487
2488      case RSB: {
2489        // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2490        // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2491        alu_out = shifter_operand - rn_val;
2492        set_register(rd, alu_out);
2493        if (instr->HasS()) {
2494          SetNZFlags(alu_out);
2495          SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2496          SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
2497        }
2498        break;
2499      }
2500
2501      case ADD: {
2502        // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2503        // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2504        alu_out = rn_val + shifter_operand;
2505        set_register(rd, alu_out);
2506        if (instr->HasS()) {
2507          SetNZFlags(alu_out);
2508          SetCFlag(CarryFrom(rn_val, shifter_operand));
2509          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2510        }
2511        break;
2512      }
2513
2514      case ADC: {
2515        // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2516        // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2517        alu_out = rn_val + shifter_operand + GetCarry();
2518        set_register(rd, alu_out);
2519        if (instr->HasS()) {
2520          SetNZFlags(alu_out);
2521          SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2522          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2523        }
2524        break;
2525      }
2526
2527      case SBC: {
2528        //        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2529        //        Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2530        alu_out = (rn_val - shifter_operand) - (GetCarry() ? 0 : 1);
2531        set_register(rd, alu_out);
2532        if (instr->HasS()) {
2533          SetNZFlags(alu_out);
2534          SetCFlag(!BorrowFrom(rn_val, shifter_operand, GetCarry()));
2535          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2536        }
2537        break;
2538      }
2539
2540      case RSC: {
2541        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2542        Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2543        break;
2544      }
2545
2546      case TST: {
2547        if (instr->HasS()) {
2548          // Format(instr, "tst'cond 'rn, 'shift_rm");
2549          // Format(instr, "tst'cond 'rn, 'imm");
2550          alu_out = rn_val & shifter_operand;
2551          SetNZFlags(alu_out);
2552          SetCFlag(shifter_carry_out);
2553        } else {
2554          // Format(instr, "movw'cond 'rd, 'imm").
2555          alu_out = instr->ImmedMovwMovtValue();
2556          set_register(rd, alu_out);
2557        }
2558        break;
2559      }
2560
2561      case TEQ: {
2562        if (instr->HasS()) {
2563          // Format(instr, "teq'cond 'rn, 'shift_rm");
2564          // Format(instr, "teq'cond 'rn, 'imm");
2565          alu_out = rn_val ^ shifter_operand;
2566          SetNZFlags(alu_out);
2567          SetCFlag(shifter_carry_out);
2568        } else {
2569          // Other instructions matching this pattern are handled in the
2570          // miscellaneous instructions part above.
2571          UNREACHABLE();
2572        }
2573        break;
2574      }
2575
2576      case CMP: {
2577        if (instr->HasS()) {
2578          // Format(instr, "cmp'cond 'rn, 'shift_rm");
2579          // Format(instr, "cmp'cond 'rn, 'imm");
2580          alu_out = rn_val - shifter_operand;
2581          SetNZFlags(alu_out);
2582          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2583          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2584        } else {
2585          // Format(instr, "movt'cond 'rd, 'imm").
2586          alu_out = (get_register(rd) & 0xffff) |
2587              (instr->ImmedMovwMovtValue() << 16);
2588          set_register(rd, alu_out);
2589        }
2590        break;
2591      }
2592
2593      case CMN: {
2594        if (instr->HasS()) {
2595          // Format(instr, "cmn'cond 'rn, 'shift_rm");
2596          // Format(instr, "cmn'cond 'rn, 'imm");
2597          alu_out = rn_val + shifter_operand;
2598          SetNZFlags(alu_out);
2599          SetCFlag(CarryFrom(rn_val, shifter_operand));
2600          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2601        } else {
2602          // Other instructions matching this pattern are handled in the
2603          // miscellaneous instructions part above.
2604          UNREACHABLE();
2605        }
2606        break;
2607      }
2608
2609      case ORR: {
2610        // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2611        // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2612        alu_out = rn_val | shifter_operand;
2613        set_register(rd, alu_out);
2614        if (instr->HasS()) {
2615          SetNZFlags(alu_out);
2616          SetCFlag(shifter_carry_out);
2617        }
2618        break;
2619      }
2620
2621      case MOV: {
2622        // Format(instr, "mov'cond's 'rd, 'shift_rm");
2623        // Format(instr, "mov'cond's 'rd, 'imm");
2624        alu_out = shifter_operand;
2625        set_register(rd, alu_out);
2626        if (instr->HasS()) {
2627          SetNZFlags(alu_out);
2628          SetCFlag(shifter_carry_out);
2629        }
2630        break;
2631      }
2632
2633      case BIC: {
2634        // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
2635        // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
2636        alu_out = rn_val & ~shifter_operand;
2637        set_register(rd, alu_out);
2638        if (instr->HasS()) {
2639          SetNZFlags(alu_out);
2640          SetCFlag(shifter_carry_out);
2641        }
2642        break;
2643      }
2644
2645      case MVN: {
2646        // Format(instr, "mvn'cond's 'rd, 'shift_rm");
2647        // Format(instr, "mvn'cond's 'rd, 'imm");
2648        alu_out = ~shifter_operand;
2649        set_register(rd, alu_out);
2650        if (instr->HasS()) {
2651          SetNZFlags(alu_out);
2652          SetCFlag(shifter_carry_out);
2653        }
2654        break;
2655      }
2656
2657      default: {
2658        UNREACHABLE();
2659        break;
2660      }
2661    }
2662  }
2663}
2664
2665
2666void Simulator::DecodeType2(Instruction* instr) {
2667  int rd = instr->RdValue();
2668  int rn = instr->RnValue();
2669  int32_t rn_val = get_register(rn);
2670  int32_t im_val = instr->Offset12Value();
2671  int32_t addr = 0;
2672  switch (instr->PUField()) {
2673    case da_x: {
2674      // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
2675      DCHECK(!instr->HasW());
2676      addr = rn_val;
2677      rn_val -= im_val;
2678      set_register(rn, rn_val);
2679      break;
2680    }
2681    case ia_x: {
2682      // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
2683      DCHECK(!instr->HasW());
2684      addr = rn_val;
2685      rn_val += im_val;
2686      set_register(rn, rn_val);
2687      break;
2688    }
2689    case db_x: {
2690      // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
2691      rn_val -= im_val;
2692      addr = rn_val;
2693      if (instr->HasW()) {
2694        set_register(rn, rn_val);
2695      }
2696      break;
2697    }
2698    case ib_x: {
2699      // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
2700      rn_val += im_val;
2701      addr = rn_val;
2702      if (instr->HasW()) {
2703        set_register(rn, rn_val);
2704      }
2705      break;
2706    }
2707    default: {
2708      UNREACHABLE();
2709      break;
2710    }
2711  }
2712  if (instr->HasB()) {
2713    if (instr->HasL()) {
2714      byte val = ReadBU(addr);
2715      set_register(rd, val);
2716    } else {
2717      byte val = get_register(rd);
2718      WriteB(addr, val);
2719    }
2720  } else {
2721    if (instr->HasL()) {
2722      set_register(rd, ReadW(addr, instr));
2723    } else {
2724      WriteW(addr, get_register(rd), instr);
2725    }
2726  }
2727}
2728
2729
2730void Simulator::DecodeType3(Instruction* instr) {
2731  int rd = instr->RdValue();
2732  int rn = instr->RnValue();
2733  int32_t rn_val = get_register(rn);
2734  bool shifter_carry_out = 0;
2735  int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2736  int32_t addr = 0;
2737  switch (instr->PUField()) {
2738    case da_x: {
2739      DCHECK(!instr->HasW());
2740      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
2741      UNIMPLEMENTED();
2742      break;
2743    }
2744    case ia_x: {
2745      if (instr->Bit(4) == 0) {
2746        // Memop.
2747      } else {
2748        if (instr->Bit(5) == 0) {
2749          switch (instr->Bits(22, 21)) {
2750            case 0:
2751              if (instr->Bit(20) == 0) {
2752                if (instr->Bit(6) == 0) {
2753                  // Pkhbt.
2754                  uint32_t rn_val = get_register(rn);
2755                  uint32_t rm_val = get_register(instr->RmValue());
2756                  int32_t shift = instr->Bits(11, 7);
2757                  rm_val <<= shift;
2758                  set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2759                } else {
2760                  // Pkhtb.
2761                  uint32_t rn_val = get_register(rn);
2762                  int32_t rm_val = get_register(instr->RmValue());
2763                  int32_t shift = instr->Bits(11, 7);
2764                  if (shift == 0) {
2765                    shift = 32;
2766                  }
2767                  rm_val >>= shift;
2768                  set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2769                }
2770              } else {
2771                UNIMPLEMENTED();
2772              }
2773              break;
2774            case 1:
2775              UNIMPLEMENTED();
2776              break;
2777            case 2:
2778              UNIMPLEMENTED();
2779              break;
2780            case 3: {
2781              // Usat.
2782              int32_t sat_pos = instr->Bits(20, 16);
2783              int32_t sat_val = (1 << sat_pos) - 1;
2784              int32_t shift = instr->Bits(11, 7);
2785              int32_t shift_type = instr->Bit(6);
2786              int32_t rm_val = get_register(instr->RmValue());
2787              if (shift_type == 0) {  // LSL
2788                rm_val <<= shift;
2789              } else {  // ASR
2790                rm_val >>= shift;
2791              }
2792              // If saturation occurs, the Q flag should be set in the CPSR.
2793              // There is no Q flag yet, and no instruction (MRS) to read the
2794              // CPSR directly.
2795              if (rm_val > sat_val) {
2796                rm_val = sat_val;
2797              } else if (rm_val < 0) {
2798                rm_val = 0;
2799              }
2800              set_register(rd, rm_val);
2801              break;
2802            }
2803          }
2804        } else {
2805          switch (instr->Bits(22, 21)) {
2806            case 0:
2807              UNIMPLEMENTED();
2808              break;
2809            case 1:
2810              if (instr->Bits(9, 6) == 1) {
2811                if (instr->Bit(20) == 0) {
2812                  if (instr->Bits(19, 16) == 0xF) {
2813                    // Sxtb.
2814                    int32_t rm_val = get_register(instr->RmValue());
2815                    int32_t rotate = instr->Bits(11, 10);
2816                    switch (rotate) {
2817                      case 0:
2818                        break;
2819                      case 1:
2820                        rm_val = (rm_val >> 8) | (rm_val << 24);
2821                        break;
2822                      case 2:
2823                        rm_val = (rm_val >> 16) | (rm_val << 16);
2824                        break;
2825                      case 3:
2826                        rm_val = (rm_val >> 24) | (rm_val << 8);
2827                        break;
2828                    }
2829                    set_register(rd, static_cast<int8_t>(rm_val));
2830                  } else {
2831                    // Sxtab.
2832                    int32_t rn_val = get_register(rn);
2833                    int32_t rm_val = get_register(instr->RmValue());
2834                    int32_t rotate = instr->Bits(11, 10);
2835                    switch (rotate) {
2836                      case 0:
2837                        break;
2838                      case 1:
2839                        rm_val = (rm_val >> 8) | (rm_val << 24);
2840                        break;
2841                      case 2:
2842                        rm_val = (rm_val >> 16) | (rm_val << 16);
2843                        break;
2844                      case 3:
2845                        rm_val = (rm_val >> 24) | (rm_val << 8);
2846                        break;
2847                    }
2848                    set_register(rd, rn_val + static_cast<int8_t>(rm_val));
2849                  }
2850                } else {
2851                  if (instr->Bits(19, 16) == 0xF) {
2852                    // Sxth.
2853                    int32_t rm_val = get_register(instr->RmValue());
2854                    int32_t rotate = instr->Bits(11, 10);
2855                    switch (rotate) {
2856                      case 0:
2857                        break;
2858                      case 1:
2859                        rm_val = (rm_val >> 8) | (rm_val << 24);
2860                        break;
2861                      case 2:
2862                        rm_val = (rm_val >> 16) | (rm_val << 16);
2863                        break;
2864                      case 3:
2865                        rm_val = (rm_val >> 24) | (rm_val << 8);
2866                        break;
2867                    }
2868                    set_register(rd, static_cast<int16_t>(rm_val));
2869                  } else {
2870                    // Sxtah.
2871                    int32_t rn_val = get_register(rn);
2872                    int32_t rm_val = get_register(instr->RmValue());
2873                    int32_t rotate = instr->Bits(11, 10);
2874                    switch (rotate) {
2875                      case 0:
2876                        break;
2877                      case 1:
2878                        rm_val = (rm_val >> 8) | (rm_val << 24);
2879                        break;
2880                      case 2:
2881                        rm_val = (rm_val >> 16) | (rm_val << 16);
2882                        break;
2883                      case 3:
2884                        rm_val = (rm_val >> 24) | (rm_val << 8);
2885                        break;
2886                    }
2887                    set_register(rd, rn_val + static_cast<int16_t>(rm_val));
2888                  }
2889                }
2890              } else {
2891                UNREACHABLE();
2892              }
2893              break;
2894            case 2:
2895              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2896                if (instr->Bits(19, 16) == 0xF) {
2897                  // Uxtb16.
2898                  uint32_t rm_val = get_register(instr->RmValue());
2899                  int32_t rotate = instr->Bits(11, 10);
2900                  switch (rotate) {
2901                    case 0:
2902                      break;
2903                    case 1:
2904                      rm_val = (rm_val >> 8) | (rm_val << 24);
2905                      break;
2906                    case 2:
2907                      rm_val = (rm_val >> 16) | (rm_val << 16);
2908                      break;
2909                    case 3:
2910                      rm_val = (rm_val >> 24) | (rm_val << 8);
2911                      break;
2912                  }
2913                  set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000));
2914                } else {
2915                  UNIMPLEMENTED();
2916                }
2917              } else {
2918                UNIMPLEMENTED();
2919              }
2920              break;
2921            case 3:
2922              if ((instr->Bits(9, 6) == 1)) {
2923                if (instr->Bit(20) == 0) {
2924                  if (instr->Bits(19, 16) == 0xF) {
2925                    // Uxtb.
2926                    uint32_t rm_val = get_register(instr->RmValue());
2927                    int32_t rotate = instr->Bits(11, 10);
2928                    switch (rotate) {
2929                      case 0:
2930                        break;
2931                      case 1:
2932                        rm_val = (rm_val >> 8) | (rm_val << 24);
2933                        break;
2934                      case 2:
2935                        rm_val = (rm_val >> 16) | (rm_val << 16);
2936                        break;
2937                      case 3:
2938                        rm_val = (rm_val >> 24) | (rm_val << 8);
2939                        break;
2940                    }
2941                    set_register(rd, (rm_val & 0xFF));
2942                  } else {
2943                    // Uxtab.
2944                    uint32_t rn_val = get_register(rn);
2945                    uint32_t rm_val = get_register(instr->RmValue());
2946                    int32_t rotate = instr->Bits(11, 10);
2947                    switch (rotate) {
2948                      case 0:
2949                        break;
2950                      case 1:
2951                        rm_val = (rm_val >> 8) | (rm_val << 24);
2952                        break;
2953                      case 2:
2954                        rm_val = (rm_val >> 16) | (rm_val << 16);
2955                        break;
2956                      case 3:
2957                        rm_val = (rm_val >> 24) | (rm_val << 8);
2958                        break;
2959                    }
2960                    set_register(rd, rn_val + (rm_val & 0xFF));
2961                  }
2962                } else {
2963                  if (instr->Bits(19, 16) == 0xF) {
2964                    // Uxth.
2965                    uint32_t rm_val = get_register(instr->RmValue());
2966                    int32_t rotate = instr->Bits(11, 10);
2967                    switch (rotate) {
2968                      case 0:
2969                        break;
2970                      case 1:
2971                        rm_val = (rm_val >> 8) | (rm_val << 24);
2972                        break;
2973                      case 2:
2974                        rm_val = (rm_val >> 16) | (rm_val << 16);
2975                        break;
2976                      case 3:
2977                        rm_val = (rm_val >> 24) | (rm_val << 8);
2978                        break;
2979                    }
2980                    set_register(rd, (rm_val & 0xFFFF));
2981                  } else {
2982                    // Uxtah.
2983                    uint32_t rn_val = get_register(rn);
2984                    uint32_t rm_val = get_register(instr->RmValue());
2985                    int32_t rotate = instr->Bits(11, 10);
2986                    switch (rotate) {
2987                      case 0:
2988                        break;
2989                      case 1:
2990                        rm_val = (rm_val >> 8) | (rm_val << 24);
2991                        break;
2992                      case 2:
2993                        rm_val = (rm_val >> 16) | (rm_val << 16);
2994                        break;
2995                      case 3:
2996                        rm_val = (rm_val >> 24) | (rm_val << 8);
2997                        break;
2998                    }
2999                    set_register(rd, rn_val + (rm_val & 0xFFFF));
3000                  }
3001                }
3002              } else {
3003                // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
3004                if ((instr->Bits(20, 16) == 0x1f) &&
3005                    (instr->Bits(11, 4) == 0xf3)) {
3006                  // Rbit.
3007                  uint32_t rm_val = get_register(instr->RmValue());
3008                  set_register(rd, base::bits::ReverseBits(rm_val));
3009                } else {
3010                  UNIMPLEMENTED();
3011                }
3012              }
3013              break;
3014          }
3015        }
3016        return;
3017      }
3018      break;
3019    }
3020    case db_x: {
3021      if (instr->Bits(22, 20) == 0x5) {
3022        if (instr->Bits(7, 4) == 0x1) {
3023          int rm = instr->RmValue();
3024          int32_t rm_val = get_register(rm);
3025          int rs = instr->RsValue();
3026          int32_t rs_val = get_register(rs);
3027          if (instr->Bits(15, 12) == 0xF) {
3028            // SMMUL (in V8 notation matching ARM ISA format)
3029            // Format(instr, "smmul'cond 'rn, 'rm, 'rs");
3030            rn_val = base::bits::SignedMulHigh32(rm_val, rs_val);
3031          } else {
3032            // SMMLA (in V8 notation matching ARM ISA format)
3033            // Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
3034            int rd = instr->RdValue();
3035            int32_t rd_val = get_register(rd);
3036            rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val);
3037          }
3038          set_register(rn, rn_val);
3039          return;
3040        }
3041      }
3042      if (instr->Bits(5, 4) == 0x1) {
3043        if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
3044          // (s/u)div (in V8 notation matching ARM ISA format) rn = rm/rs
3045          // Format(instr, "'(s/u)div'cond'b 'rn, 'rm, 'rs);
3046          int rm = instr->RmValue();
3047          int32_t rm_val = get_register(rm);
3048          int rs = instr->RsValue();
3049          int32_t rs_val = get_register(rs);
3050          int32_t ret_val = 0;
3051          // udiv
3052          if (instr->Bit(21) == 0x1) {
3053            ret_val = bit_cast<int32_t>(base::bits::UnsignedDiv32(
3054                bit_cast<uint32_t>(rm_val), bit_cast<uint32_t>(rs_val)));
3055          } else {
3056            ret_val = base::bits::SignedDiv32(rm_val, rs_val);
3057          }
3058          set_register(rn, ret_val);
3059          return;
3060        }
3061      }
3062      // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
3063      addr = rn_val - shifter_operand;
3064      if (instr->HasW()) {
3065        set_register(rn, addr);
3066      }
3067      break;
3068    }
3069    case ib_x: {
3070      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
3071        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
3072        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
3073        uint32_t msbit = widthminus1 + lsbit;
3074        if (msbit <= 31) {
3075          if (instr->Bit(22)) {
3076            // ubfx - unsigned bitfield extract.
3077            uint32_t rm_val =
3078                static_cast<uint32_t>(get_register(instr->RmValue()));
3079            uint32_t extr_val = rm_val << (31 - msbit);
3080            extr_val = extr_val >> (31 - widthminus1);
3081            set_register(instr->RdValue(), extr_val);
3082          } else {
3083            // sbfx - signed bitfield extract.
3084            int32_t rm_val = get_register(instr->RmValue());
3085            int32_t extr_val = rm_val << (31 - msbit);
3086            extr_val = extr_val >> (31 - widthminus1);
3087            set_register(instr->RdValue(), extr_val);
3088          }
3089        } else {
3090          UNREACHABLE();
3091        }
3092        return;
3093      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
3094        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
3095        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
3096        if (msbit >= lsbit) {
3097          // bfc or bfi - bitfield clear/insert.
3098          uint32_t rd_val =
3099              static_cast<uint32_t>(get_register(instr->RdValue()));
3100          uint32_t bitcount = msbit - lsbit + 1;
3101          uint32_t mask = 0xffffffffu >> (32 - bitcount);
3102          rd_val &= ~(mask << lsbit);
3103          if (instr->RmValue() != 15) {
3104            // bfi - bitfield insert.
3105            uint32_t rm_val =
3106                static_cast<uint32_t>(get_register(instr->RmValue()));
3107            rm_val &= mask;
3108            rd_val |= rm_val << lsbit;
3109          }
3110          set_register(instr->RdValue(), rd_val);
3111        } else {
3112          UNREACHABLE();
3113        }
3114        return;
3115      } else {
3116        // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
3117        addr = rn_val + shifter_operand;
3118        if (instr->HasW()) {
3119          set_register(rn, addr);
3120        }
3121      }
3122      break;
3123    }
3124    default: {
3125      UNREACHABLE();
3126      break;
3127    }
3128  }
3129  if (instr->HasB()) {
3130    if (instr->HasL()) {
3131      uint8_t byte = ReadB(addr);
3132      set_register(rd, byte);
3133    } else {
3134      uint8_t byte = get_register(rd);
3135      WriteB(addr, byte);
3136    }
3137  } else {
3138    if (instr->HasL()) {
3139      set_register(rd, ReadW(addr, instr));
3140    } else {
3141      WriteW(addr, get_register(rd), instr);
3142    }
3143  }
3144}
3145
3146
3147void Simulator::DecodeType4(Instruction* instr) {
3148  DCHECK(instr->Bit(22) == 0);  // only allowed to be set in privileged mode
3149  if (instr->HasL()) {
3150    // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
3151    HandleRList(instr, true);
3152  } else {
3153    // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
3154    HandleRList(instr, false);
3155  }
3156}
3157
3158
3159void Simulator::DecodeType5(Instruction* instr) {
3160  // Format(instr, "b'l'cond 'target");
3161  int off = (instr->SImmed24Value() << 2);
3162  intptr_t pc_address = get_pc();
3163  if (instr->HasLink()) {
3164    set_register(lr, pc_address + Instruction::kInstrSize);
3165  }
3166  int pc_reg = get_register(pc);
3167  set_pc(pc_reg + off);
3168}
3169
3170
3171void Simulator::DecodeType6(Instruction* instr) {
3172  DecodeType6CoprocessorIns(instr);
3173}
3174
3175
3176void Simulator::DecodeType7(Instruction* instr) {
3177  if (instr->Bit(24) == 1) {
3178    SoftwareInterrupt(instr);
3179  } else {
3180    switch (instr->CoprocessorValue()) {
3181      case 10:  // Fall through.
3182      case 11:
3183        DecodeTypeVFP(instr);
3184        break;
3185      case 15:
3186        DecodeTypeCP15(instr);
3187        break;
3188      default:
3189        UNIMPLEMENTED();
3190    }
3191  }
3192}
3193
3194
3195// void Simulator::DecodeTypeVFP(Instruction* instr)
3196// The Following ARMv7 VFPv instructions are currently supported.
3197// vmov :Sn = Rt
3198// vmov :Rt = Sn
3199// vcvt: Dd = Sm
3200// vcvt: Sd = Dm
3201// vcvt.f64.s32 Dd, Dd, #<fbits>
3202// Dd = vabs(Dm)
3203// Sd = vabs(Sm)
3204// Dd = vneg(Dm)
3205// Sd = vneg(Sm)
3206// Dd = vadd(Dn, Dm)
3207// Sd = vadd(Sn, Sm)
3208// Dd = vsub(Dn, Dm)
3209// Sd = vsub(Sn, Sm)
3210// Dd = vmul(Dn, Dm)
3211// Sd = vmul(Sn, Sm)
3212// Dd = vdiv(Dn, Dm)
3213// Sd = vdiv(Sn, Sm)
3214// vcmp(Dd, Dm)
3215// vcmp(Sd, Sm)
3216// Dd = vsqrt(Dm)
3217// Sd = vsqrt(Sm)
3218// vmrs
3219// vdup.size Qd, Rt.
3220void Simulator::DecodeTypeVFP(Instruction* instr) {
3221  DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
3222  DCHECK(instr->Bits(11, 9) == 0x5);
3223
3224  // Obtain single precision register codes.
3225  int m = instr->VFPMRegValue(kSinglePrecision);
3226  int d = instr->VFPDRegValue(kSinglePrecision);
3227  int n = instr->VFPNRegValue(kSinglePrecision);
3228  // Obtain double precision register codes.
3229  int vm = instr->VFPMRegValue(kDoublePrecision);
3230  int vd = instr->VFPDRegValue(kDoublePrecision);
3231  int vn = instr->VFPNRegValue(kDoublePrecision);
3232
3233  if (instr->Bit(4) == 0) {
3234    if (instr->Opc1Value() == 0x7) {
3235      // Other data processing instructions
3236      if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
3237        // vmov register to register.
3238        if (instr->SzValue() == 0x1) {
3239          uint32_t data[2];
3240          get_d_register(vm, data);
3241          set_d_register(vd, data);
3242        } else {
3243          set_s_register(d, get_s_register(m));
3244        }
3245      } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
3246        // vabs
3247        if (instr->SzValue() == 0x1) {
3248          double dm_value = get_double_from_d_register(vm);
3249          double dd_value = std::fabs(dm_value);
3250          dd_value = canonicalizeNaN(dd_value);
3251          set_d_register_from_double(vd, dd_value);
3252        } else {
3253          float sm_value = get_float_from_s_register(m);
3254          float sd_value = std::fabs(sm_value);
3255          sd_value = canonicalizeNaN(sd_value);
3256          set_s_register_from_float(d, sd_value);
3257        }
3258      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
3259        // vneg
3260        if (instr->SzValue() == 0x1) {
3261          double dm_value = get_double_from_d_register(vm);
3262          double dd_value = -dm_value;
3263          dd_value = canonicalizeNaN(dd_value);
3264          set_d_register_from_double(vd, dd_value);
3265        } else {
3266          float sm_value = get_float_from_s_register(m);
3267          float sd_value = -sm_value;
3268          sd_value = canonicalizeNaN(sd_value);
3269          set_s_register_from_float(d, sd_value);
3270        }
3271      } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
3272        DecodeVCVTBetweenDoubleAndSingle(instr);
3273      } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
3274        DecodeVCVTBetweenFloatingPointAndInteger(instr);
3275      } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
3276                 (instr->Bit(8) == 1)) {
3277        // vcvt.f64.s32 Dd, Dd, #<fbits>
3278        int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
3279        int fixed_value = get_sinteger_from_s_register(vd * 2);
3280        double divide = 1 << fraction_bits;
3281        set_d_register_from_double(vd, fixed_value / divide);
3282      } else if (((instr->Opc2Value() >> 1) == 0x6) &&
3283                 (instr->Opc3Value() & 0x1)) {
3284        DecodeVCVTBetweenFloatingPointAndInteger(instr);
3285      } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3286                 (instr->Opc3Value() & 0x1)) {
3287        DecodeVCMP(instr);
3288      } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
3289        // vsqrt
3290        lazily_initialize_fast_sqrt(isolate_);
3291        if (instr->SzValue() == 0x1) {
3292          double dm_value = get_double_from_d_register(vm);
3293          double dd_value = fast_sqrt(dm_value, isolate_);
3294          dd_value = canonicalizeNaN(dd_value);
3295          set_d_register_from_double(vd, dd_value);
3296        } else {
3297          float sm_value = get_float_from_s_register(m);
3298          float sd_value = fast_sqrt(sm_value, isolate_);
3299          sd_value = canonicalizeNaN(sd_value);
3300          set_s_register_from_float(d, sd_value);
3301        }
3302      } else if (instr->Opc3Value() == 0x0) {
3303        // vmov immediate.
3304        if (instr->SzValue() == 0x1) {
3305          set_d_register_from_double(vd, instr->DoubleImmedVmov());
3306        } else {
3307          set_s_register_from_float(d, instr->DoubleImmedVmov());
3308        }
3309      } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) {
3310        // vrintz - truncate
3311        if (instr->SzValue() == 0x1) {
3312          double dm_value = get_double_from_d_register(vm);
3313          double dd_value = trunc(dm_value);
3314          dd_value = canonicalizeNaN(dd_value);
3315          set_d_register_from_double(vd, dd_value);
3316        } else {
3317          float sm_value = get_float_from_s_register(m);
3318          float sd_value = truncf(sm_value);
3319          sd_value = canonicalizeNaN(sd_value);
3320          set_s_register_from_float(d, sd_value);
3321        }
3322      } else {
3323        UNREACHABLE();  // Not used by V8.
3324      }
3325    } else if (instr->Opc1Value() == 0x3) {
3326      if (instr->Opc3Value() & 0x1) {
3327        // vsub
3328        if (instr->SzValue() == 0x1) {
3329          double dn_value = get_double_from_d_register(vn);
3330          double dm_value = get_double_from_d_register(vm);
3331          double dd_value = dn_value - dm_value;
3332          dd_value = canonicalizeNaN(dd_value);
3333          set_d_register_from_double(vd, dd_value);
3334        } else {
3335          float sn_value = get_float_from_s_register(n);
3336          float sm_value = get_float_from_s_register(m);
3337          float sd_value = sn_value - sm_value;
3338          sd_value = canonicalizeNaN(sd_value);
3339          set_s_register_from_float(d, sd_value);
3340        }
3341      } else {
3342        // vadd
3343        if (instr->SzValue() == 0x1) {
3344          double dn_value = get_double_from_d_register(vn);
3345          double dm_value = get_double_from_d_register(vm);
3346          double dd_value = dn_value + dm_value;
3347          dd_value = canonicalizeNaN(dd_value);
3348          set_d_register_from_double(vd, dd_value);
3349        } else {
3350          float sn_value = get_float_from_s_register(n);
3351          float sm_value = get_float_from_s_register(m);
3352          float sd_value = sn_value + sm_value;
3353          sd_value = canonicalizeNaN(sd_value);
3354          set_s_register_from_float(d, sd_value);
3355        }
3356      }
3357    } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
3358      // vmul
3359      if (instr->SzValue() == 0x1) {
3360        double dn_value = get_double_from_d_register(vn);
3361        double dm_value = get_double_from_d_register(vm);
3362        double dd_value = dn_value * dm_value;
3363        dd_value = canonicalizeNaN(dd_value);
3364        set_d_register_from_double(vd, dd_value);
3365      } else {
3366        float sn_value = get_float_from_s_register(n);
3367        float sm_value = get_float_from_s_register(m);
3368        float sd_value = sn_value * sm_value;
3369        sd_value = canonicalizeNaN(sd_value);
3370        set_s_register_from_float(d, sd_value);
3371      }
3372    } else if ((instr->Opc1Value() == 0x0)) {
3373      // vmla, vmls
3374      const bool is_vmls = (instr->Opc3Value() & 0x1);
3375      if (instr->SzValue() == 0x1) {
3376        const double dd_val = get_double_from_d_register(vd);
3377        const double dn_val = get_double_from_d_register(vn);
3378        const double dm_val = get_double_from_d_register(vm);
3379
3380        // Note: we do the mul and add/sub in separate steps to avoid getting a
3381        // result with too high precision.
3382        set_d_register_from_double(vd, dn_val * dm_val);
3383        if (is_vmls) {
3384          set_d_register_from_double(
3385              vd, canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
3386        } else {
3387          set_d_register_from_double(
3388              vd, canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3389        }
3390      } else {
3391        const float sd_val = get_float_from_s_register(d);
3392        const float sn_val = get_float_from_s_register(n);
3393        const float sm_val = get_float_from_s_register(m);
3394
3395        // Note: we do the mul and add/sub in separate steps to avoid getting a
3396        // result with too high precision.
3397        set_s_register_from_float(d, sn_val * sm_val);
3398        if (is_vmls) {
3399          set_s_register_from_float(
3400              d, canonicalizeNaN(sd_val - get_float_from_s_register(d)));
3401        } else {
3402          set_s_register_from_float(
3403              d, canonicalizeNaN(sd_val + get_float_from_s_register(d)));
3404        }
3405      }
3406    } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3407      // vdiv
3408      if (instr->SzValue() == 0x1) {
3409        double dn_value = get_double_from_d_register(vn);
3410        double dm_value = get_double_from_d_register(vm);
3411        double dd_value = dn_value / dm_value;
3412        div_zero_vfp_flag_ = (dm_value == 0);
3413        dd_value = canonicalizeNaN(dd_value);
3414        set_d_register_from_double(vd, dd_value);
3415      } else {
3416        float sn_value = get_float_from_s_register(n);
3417        float sm_value = get_float_from_s_register(m);
3418        float sd_value = sn_value / sm_value;
3419        div_zero_vfp_flag_ = (sm_value == 0);
3420        sd_value = canonicalizeNaN(sd_value);
3421        set_s_register_from_float(d, sd_value);
3422      }
3423    } else {
3424      UNIMPLEMENTED();  // Not used by V8.
3425    }
3426  } else {
3427    if ((instr->VCValue() == 0x0) &&
3428        (instr->VAValue() == 0x0)) {
3429      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3430    } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
3431      if (instr->Bit(23) == 0) {
3432        // vmov (ARM core register to scalar)
3433        int vd = instr->VFPNRegValue(kDoublePrecision);
3434        int rt = instr->RtValue();
3435        int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
3436        if ((opc1_opc2 & 0xb) == 0) {
3437          // NeonS32/NeonU32
3438          uint32_t data[2];
3439          get_d_register(vd, data);
3440          data[instr->Bit(21)] = get_register(rt);
3441          set_d_register(vd, data);
3442        } else {
3443          uint64_t data;
3444          get_d_register(vd, &data);
3445          uint64_t rt_value = get_register(rt);
3446          if ((opc1_opc2 & 0x8) != 0) {
3447            // NeonS8 / NeonU8
3448            int i = opc1_opc2 & 0x7;
3449            int shift = i * kBitsPerByte;
3450            const uint64_t mask = 0xFF;
3451            data &= ~(mask << shift);
3452            data |= (rt_value & mask) << shift;
3453            set_d_register(vd, &data);
3454          } else if ((opc1_opc2 & 0x1) != 0) {
3455            // NeonS16 / NeonU16
3456            int i = (opc1_opc2 >> 1) & 0x3;
3457            int shift = i * kBitsPerByte * kShortSize;
3458            const uint64_t mask = 0xFFFF;
3459            data &= ~(mask << shift);
3460            data |= (rt_value & mask) << shift;
3461            set_d_register(vd, &data);
3462          } else {
3463            UNREACHABLE();  // Not used by V8.
3464          }
3465        }
3466      } else {
3467        // vdup.size Qd, Rt.
3468        NeonSize size = Neon32;
3469        if (instr->Bit(5) != 0)
3470          size = Neon16;
3471        else if (instr->Bit(22) != 0)
3472          size = Neon8;
3473        int vd = instr->VFPNRegValue(kSimd128Precision);
3474        int rt = instr->RtValue();
3475        uint32_t rt_value = get_register(rt);
3476        uint32_t q_data[4];
3477        switch (size) {
3478          case Neon8: {
3479            rt_value &= 0xFF;
3480            uint8_t* dst = reinterpret_cast<uint8_t*>(q_data);
3481            for (int i = 0; i < 16; i++) {
3482              dst[i] = rt_value;
3483            }
3484            break;
3485          }
3486          case Neon16: {
3487            // Perform pairwise op.
3488            rt_value &= 0xFFFFu;
3489            uint32_t rt_rt = (rt_value << 16) | (rt_value & 0xFFFFu);
3490            for (int i = 0; i < 4; i++) {
3491              q_data[i] = rt_rt;
3492            }
3493            break;
3494          }
3495          case Neon32: {
3496            for (int i = 0; i < 4; i++) {
3497              q_data[i] = rt_value;
3498            }
3499            break;
3500          }
3501          default:
3502            UNREACHABLE();
3503            break;
3504        }
3505        set_q_register(vd, q_data);
3506      }
3507    } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
3508      // vmov (scalar to ARM core register)
3509      int vn = instr->VFPNRegValue(kDoublePrecision);
3510      int rt = instr->RtValue();
3511      int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
3512      uint64_t data;
3513      get_d_register(vn, &data);
3514      if ((opc1_opc2 & 0xb) == 0) {
3515        // NeonS32 / NeonU32
3516        int32_t int_data[2];
3517        memcpy(int_data, &data, sizeof(int_data));
3518        set_register(rt, int_data[instr->Bit(21)]);
3519      } else {
3520        uint64_t data;
3521        get_d_register(vn, &data);
3522        bool u = instr->Bit(23) != 0;
3523        if ((opc1_opc2 & 0x8) != 0) {
3524          // NeonS8 / NeonU8
3525          int i = opc1_opc2 & 0x7;
3526          int shift = i * kBitsPerByte;
3527          uint32_t scalar = (data >> shift) & 0xFFu;
3528          if (!u && (scalar & 0x80) != 0) scalar |= 0xffffff00;
3529          set_register(rt, scalar);
3530        } else if ((opc1_opc2 & 0x1) != 0) {
3531          // NeonS16 / NeonU16
3532          int i = (opc1_opc2 >> 1) & 0x3;
3533          int shift = i * kBitsPerByte * kShortSize;
3534          uint32_t scalar = (data >> shift) & 0xFFFFu;
3535          if (!u && (scalar & 0x8000) != 0) scalar |= 0xffff0000;
3536          set_register(rt, scalar);
3537        } else {
3538          UNREACHABLE();  // Not used by V8.
3539        }
3540      }
3541    } else if ((instr->VLValue() == 0x1) &&
3542               (instr->VCValue() == 0x0) &&
3543               (instr->VAValue() == 0x7) &&
3544               (instr->Bits(19, 16) == 0x1)) {
3545      // vmrs
3546      uint32_t rt = instr->RtValue();
3547      if (rt == 0xF) {
3548        Copy_FPSCR_to_APSR();
3549      } else {
3550        // Emulate FPSCR from the Simulator flags.
3551        uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3552                         (z_flag_FPSCR_ << 30) |
3553                         (c_flag_FPSCR_ << 29) |
3554                         (v_flag_FPSCR_ << 28) |
3555                         (FPSCR_default_NaN_mode_ << 25) |
3556                         (inexact_vfp_flag_ << 4) |
3557                         (underflow_vfp_flag_ << 3) |
3558                         (overflow_vfp_flag_ << 2) |
3559                         (div_zero_vfp_flag_ << 1) |
3560                         (inv_op_vfp_flag_ << 0) |
3561                         (FPSCR_rounding_mode_);
3562        set_register(rt, fpscr);
3563      }
3564    } else if ((instr->VLValue() == 0x0) &&
3565               (instr->VCValue() == 0x0) &&
3566               (instr->VAValue() == 0x7) &&
3567               (instr->Bits(19, 16) == 0x1)) {
3568      // vmsr
3569      uint32_t rt = instr->RtValue();
3570      if (rt == pc) {
3571        UNREACHABLE();
3572      } else {
3573        uint32_t rt_value = get_register(rt);
3574        n_flag_FPSCR_ = (rt_value >> 31) & 1;
3575        z_flag_FPSCR_ = (rt_value >> 30) & 1;
3576        c_flag_FPSCR_ = (rt_value >> 29) & 1;
3577        v_flag_FPSCR_ = (rt_value >> 28) & 1;
3578        FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3579        inexact_vfp_flag_ = (rt_value >> 4) & 1;
3580        underflow_vfp_flag_ = (rt_value >> 3) & 1;
3581        overflow_vfp_flag_ = (rt_value >> 2) & 1;
3582        div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3583        inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3584        FPSCR_rounding_mode_ =
3585            static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
3586      }
3587    } else {
3588      UNIMPLEMENTED();  // Not used by V8.
3589    }
3590  }
3591}
3592
3593void Simulator::DecodeTypeCP15(Instruction* instr) {
3594  DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
3595  DCHECK(instr->CoprocessorValue() == 15);
3596
3597  if (instr->Bit(4) == 1) {
3598    // mcr
3599    int crn = instr->Bits(19, 16);
3600    int crm = instr->Bits(3, 0);
3601    int opc1 = instr->Bits(23, 21);
3602    int opc2 = instr->Bits(7, 5);
3603    if ((opc1 == 0) && (crn == 7)) {
3604      // ARMv6 memory barrier operations.
3605      // Details available in ARM DDI 0406C.b, B3-1750.
3606      if (((crm == 10) && (opc2 == 5)) ||  // CP15DMB
3607          ((crm == 10) && (opc2 == 4)) ||  // CP15DSB
3608          ((crm == 5) && (opc2 == 4))) {   // CP15ISB
3609        // These are ignored by the simulator for now.
3610      } else {
3611        UNIMPLEMENTED();
3612      }
3613    }
3614  } else {
3615    UNIMPLEMENTED();
3616  }
3617}
3618
3619void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3620    Instruction* instr) {
3621  DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3622         (instr->VAValue() == 0x0));
3623
3624  int t = instr->RtValue();
3625  int n = instr->VFPNRegValue(kSinglePrecision);
3626  bool to_arm_register = (instr->VLValue() == 0x1);
3627
3628  if (to_arm_register) {
3629    int32_t int_value = get_sinteger_from_s_register(n);
3630    set_register(t, int_value);
3631  } else {
3632    int32_t rs_val = get_register(t);
3633    set_s_register_from_sinteger(n, rs_val);
3634  }
3635}
3636
3637
3638void Simulator::DecodeVCMP(Instruction* instr) {
3639  DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3640  DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3641         (instr->Opc3Value() & 0x1));
3642  // Comparison.
3643
3644  VFPRegPrecision precision = kSinglePrecision;
3645  if (instr->SzValue() == 0x1) {
3646    precision = kDoublePrecision;
3647  }
3648
3649  int d = instr->VFPDRegValue(precision);
3650  int m = 0;
3651  if (instr->Opc2Value() == 0x4) {
3652    m = instr->VFPMRegValue(precision);
3653  }
3654
3655  if (precision == kDoublePrecision) {
3656    double dd_value = get_double_from_d_register(d);
3657    double dm_value = 0.0;
3658    if (instr->Opc2Value() == 0x4) {
3659      dm_value = get_double_from_d_register(m);
3660    }
3661
3662    // Raise exceptions for quiet NaNs if necessary.
3663    if (instr->Bit(7) == 1) {
3664      if (std::isnan(dd_value)) {
3665        inv_op_vfp_flag_ = true;
3666      }
3667    }
3668
3669    Compute_FPSCR_Flags(dd_value, dm_value);
3670  } else {
3671    float sd_value = get_float_from_s_register(d);
3672    float sm_value = 0.0;
3673    if (instr->Opc2Value() == 0x4) {
3674      sm_value = get_float_from_s_register(m);
3675    }
3676
3677    // Raise exceptions for quiet NaNs if necessary.
3678    if (instr->Bit(7) == 1) {
3679      if (std::isnan(sd_value)) {
3680        inv_op_vfp_flag_ = true;
3681      }
3682    }
3683
3684    Compute_FPSCR_Flags(sd_value, sm_value);
3685  }
3686}
3687
3688
3689void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3690  DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3691  DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3692
3693  VFPRegPrecision dst_precision = kDoublePrecision;
3694  VFPRegPrecision src_precision = kSinglePrecision;
3695  if (instr->SzValue() == 1) {
3696    dst_precision = kSinglePrecision;
3697    src_precision = kDoublePrecision;
3698  }
3699
3700  int dst = instr->VFPDRegValue(dst_precision);
3701  int src = instr->VFPMRegValue(src_precision);
3702
3703  if (dst_precision == kSinglePrecision) {
3704    double val = get_double_from_d_register(src);
3705    set_s_register_from_float(dst, static_cast<float>(val));
3706  } else {
3707    float val = get_float_from_s_register(src);
3708    set_d_register_from_double(dst, static_cast<double>(val));
3709  }
3710}
3711
3712bool get_inv_op_vfp_flag(VFPRoundingMode mode,
3713                         double val,
3714                         bool unsigned_) {
3715  DCHECK((mode == RN) || (mode == RM) || (mode == RZ));
3716  double max_uint = static_cast<double>(0xffffffffu);
3717  double max_int = static_cast<double>(kMaxInt);
3718  double min_int = static_cast<double>(kMinInt);
3719
3720  // Check for NaN.
3721  if (val != val) {
3722    return true;
3723  }
3724
3725  // Check for overflow. This code works because 32bit integers can be
3726  // exactly represented by ieee-754 64bit floating-point values.
3727  switch (mode) {
3728    case RN:
3729      return  unsigned_ ? (val >= (max_uint + 0.5)) ||
3730                          (val < -0.5)
3731                        : (val >= (max_int + 0.5)) ||
3732                          (val < (min_int - 0.5));
3733
3734    case RM:
3735      return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3736                          (val < 0)
3737                        : (val >= (max_int + 1.0)) ||
3738                          (val < min_int);
3739
3740    case RZ:
3741      return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3742                          (val <= -1)
3743                        : (val >= (max_int + 1.0)) ||
3744                          (val <= (min_int - 1.0));
3745    default:
3746      UNREACHABLE();
3747      return true;
3748  }
3749}
3750
3751
3752// We call this function only if we had a vfp invalid exception.
3753// It returns the correct saturated value.
3754int VFPConversionSaturate(double val, bool unsigned_res) {
3755  if (val != val) {
3756    return 0;
3757  } else {
3758    if (unsigned_res) {
3759      return (val < 0) ? 0 : 0xffffffffu;
3760    } else {
3761      return (val < 0) ? kMinInt : kMaxInt;
3762    }
3763  }
3764}
3765
3766int32_t Simulator::ConvertDoubleToInt(double val, bool unsigned_integer,
3767                                      VFPRoundingMode mode) {
3768  int32_t result =
3769      unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val);
3770
3771  inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3772
3773  double abs_diff = unsigned_integer
3774                        ? std::fabs(val - static_cast<uint32_t>(result))
3775                        : std::fabs(val - result);
3776
3777  inexact_vfp_flag_ = (abs_diff != 0);
3778
3779  if (inv_op_vfp_flag_) {
3780    result = VFPConversionSaturate(val, unsigned_integer);
3781  } else {
3782    switch (mode) {
3783      case RN: {
3784        int val_sign = (val > 0) ? 1 : -1;
3785        if (abs_diff > 0.5) {
3786          result += val_sign;
3787        } else if (abs_diff == 0.5) {
3788          // Round to even if exactly halfway.
3789          result = ((result % 2) == 0) ? result : result + val_sign;
3790        }
3791        break;
3792      }
3793
3794      case RM:
3795        result = result > val ? result - 1 : result;
3796        break;
3797
3798      case RZ:
3799        // Nothing to do.
3800        break;
3801
3802      default:
3803        UNREACHABLE();
3804    }
3805  }
3806  return result;
3807}
3808
3809void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3810  DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3811         (instr->Bits(27, 23) == 0x1D));
3812  DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3813         (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3814
3815  // Conversion between floating-point and integer.
3816  bool to_integer = (instr->Bit(18) == 1);
3817
3818  VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3819                                                          : kSinglePrecision;
3820
3821  if (to_integer) {
3822    // We are playing with code close to the C++ standard's limits below,
3823    // hence the very simple code and heavy checks.
3824    //
3825    // Note:
3826    // C++ defines default type casting from floating point to integer as
3827    // (close to) rounding toward zero ("fractional part discarded").
3828
3829    int dst = instr->VFPDRegValue(kSinglePrecision);
3830    int src = instr->VFPMRegValue(src_precision);
3831
3832    // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
3833    // mode or the default Round to Zero mode.
3834    VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3835                                                : RZ;
3836    DCHECK((mode == RM) || (mode == RZ) || (mode == RN));
3837
3838    bool unsigned_integer = (instr->Bit(16) == 0);
3839    bool double_precision = (src_precision == kDoublePrecision);
3840
3841    double val = double_precision ? get_double_from_d_register(src)
3842                                  : get_float_from_s_register(src);
3843
3844    int32_t temp = ConvertDoubleToInt(val, unsigned_integer, mode);
3845
3846    // Update the destination register.
3847    set_s_register_from_sinteger(dst, temp);
3848
3849  } else {
3850    bool unsigned_integer = (instr->Bit(7) == 0);
3851
3852    int dst = instr->VFPDRegValue(src_precision);
3853    int src = instr->VFPMRegValue(kSinglePrecision);
3854
3855    int val = get_sinteger_from_s_register(src);
3856
3857    if (src_precision == kDoublePrecision) {
3858      if (unsigned_integer) {
3859        set_d_register_from_double(
3860            dst, static_cast<double>(static_cast<uint32_t>(val)));
3861      } else {
3862        set_d_register_from_double(dst, static_cast<double>(val));
3863      }
3864    } else {
3865      if (unsigned_integer) {
3866        set_s_register_from_float(
3867            dst, static_cast<float>(static_cast<uint32_t>(val)));
3868      } else {
3869        set_s_register_from_float(dst, static_cast<float>(val));
3870      }
3871    }
3872  }
3873}
3874
3875
3876// void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
3877// Decode Type 6 coprocessor instructions.
3878// Dm = vmov(Rt, Rt2)
3879// <Rt, Rt2> = vmov(Dm)
3880// Ddst = MEM(Rbase + 4*offset).
3881// MEM(Rbase + 4*offset) = Dsrc.
3882void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3883  DCHECK((instr->TypeValue() == 6));
3884
3885  if (instr->CoprocessorValue() == 0xA) {
3886    switch (instr->OpcodeValue()) {
3887      case 0x8:
3888      case 0xA:
3889      case 0xC:
3890      case 0xE: {  // Load and store single precision float to memory.
3891        int rn = instr->RnValue();
3892        int vd = instr->VFPDRegValue(kSinglePrecision);
3893        int offset = instr->Immed8Value();
3894        if (!instr->HasU()) {
3895          offset = -offset;
3896        }
3897
3898        int32_t address = get_register(rn) + 4 * offset;
3899        // Load and store address for singles must be at least four-byte
3900        // aligned.
3901        DCHECK((address % 4) == 0);
3902        if (instr->HasL()) {
3903          // Load single from memory: vldr.
3904          set_s_register_from_sinteger(vd, ReadW(address, instr));
3905        } else {
3906          // Store single to memory: vstr.
3907          WriteW(address, get_sinteger_from_s_register(vd), instr);
3908        }
3909        break;
3910      }
3911      case 0x4:
3912      case 0x5:
3913      case 0x6:
3914      case 0x7:
3915      case 0x9:
3916      case 0xB:
3917        // Load/store multiple single from memory: vldm/vstm.
3918        HandleVList(instr);
3919        break;
3920      default:
3921        UNIMPLEMENTED();  // Not used by V8.
3922    }
3923  } else if (instr->CoprocessorValue() == 0xB) {
3924    switch (instr->OpcodeValue()) {
3925      case 0x2:
3926        // Load and store double to two GP registers
3927        if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3928          UNIMPLEMENTED();  // Not used by V8.
3929        } else {
3930          int rt = instr->RtValue();
3931          int rn = instr->RnValue();
3932          int vm = instr->VFPMRegValue(kDoublePrecision);
3933          if (instr->HasL()) {
3934            uint32_t data[2];
3935            get_d_register(vm, data);
3936            set_register(rt, data[0]);
3937            set_register(rn, data[1]);
3938          } else {
3939            int32_t data[] = { get_register(rt), get_register(rn) };
3940            set_d_register(vm, reinterpret_cast<uint32_t*>(data));
3941          }
3942        }
3943        break;
3944      case 0x8:
3945      case 0xA:
3946      case 0xC:
3947      case 0xE: {  // Load and store double to memory.
3948        int rn = instr->RnValue();
3949        int vd = instr->VFPDRegValue(kDoublePrecision);
3950        int offset = instr->Immed8Value();
3951        if (!instr->HasU()) {
3952          offset = -offset;
3953        }
3954        int32_t address = get_register(rn) + 4 * offset;
3955        // Load and store address for doubles must be at least four-byte
3956        // aligned.
3957        DCHECK((address % 4) == 0);
3958        if (instr->HasL()) {
3959          // Load double from memory: vldr.
3960          int32_t data[] = {
3961            ReadW(address, instr),
3962            ReadW(address + 4, instr)
3963          };
3964          set_d_register(vd, reinterpret_cast<uint32_t*>(data));
3965        } else {
3966          // Store double to memory: vstr.
3967          uint32_t data[2];
3968          get_d_register(vd, data);
3969          WriteW(address, data[0], instr);
3970          WriteW(address + 4, data[1], instr);
3971        }
3972        break;
3973      }
3974      case 0x4:
3975      case 0x5:
3976      case 0x6:
3977      case 0x7:
3978      case 0x9:
3979      case 0xB:
3980        // Load/store multiple double from memory: vldm/vstm.
3981        HandleVList(instr);
3982        break;
3983      default:
3984        UNIMPLEMENTED();  // Not used by V8.
3985    }
3986  } else {
3987    UNIMPLEMENTED();  // Not used by V8.
3988  }
3989}
3990
3991// Templated operations for NEON instructions.
3992// TODO(bbudge) Add more templates for use in DecodeSpecialCondition.
3993template <typename T>
3994int64_t Widen(T value) {
3995  static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller");
3996  return static_cast<int64_t>(value);
3997}
3998
3999template <typename T>
4000T Clamp(int64_t value) {
4001  static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller");
4002  int64_t min = static_cast<int64_t>(std::numeric_limits<T>::min());
4003  int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max());
4004  int64_t clamped = std::max(min, std::min(max, value));
4005  return static_cast<T>(clamped);
4006}
4007
4008template <typename T>
4009void AddSaturate(Simulator* simulator, int Vd, int Vm, int Vn) {
4010  static const int kLanes = 16 / sizeof(T);
4011  T src1[kLanes], src2[kLanes];
4012  simulator->get_q_register(Vn, src1);
4013  simulator->get_q_register(Vm, src2);
4014  for (int i = 0; i < kLanes; i++) {
4015    src1[i] = Clamp<T>(Widen(src1[i]) + Widen(src2[i]));
4016  }
4017  simulator->set_q_register(Vd, src1);
4018}
4019
4020template <typename T>
4021void SubSaturate(Simulator* simulator, int Vd, int Vm, int Vn) {
4022  static const int kLanes = 16 / sizeof(T);
4023  T src1[kLanes], src2[kLanes];
4024  simulator->get_q_register(Vn, src1);
4025  simulator->get_q_register(Vm, src2);
4026  for (int i = 0; i < kLanes; i++) {
4027    src1[i] = Clamp<T>(Widen(src1[i]) - Widen(src2[i]));
4028  }
4029  simulator->set_q_register(Vd, src1);
4030}
4031
4032void Simulator::DecodeSpecialCondition(Instruction* instr) {
4033  switch (instr->SpecialValue()) {
4034    case 4: {
4035      int Vd, Vm, Vn;
4036      if (instr->Bit(6) == 0) {
4037        Vd = instr->VFPDRegValue(kDoublePrecision);
4038        Vm = instr->VFPMRegValue(kDoublePrecision);
4039        Vn = instr->VFPNRegValue(kDoublePrecision);
4040      } else {
4041        Vd = instr->VFPDRegValue(kSimd128Precision);
4042        Vm = instr->VFPMRegValue(kSimd128Precision);
4043        Vn = instr->VFPNRegValue(kSimd128Precision);
4044      }
4045      switch (instr->Bits(11, 8)) {
4046        case 0x0: {
4047          if (instr->Bit(4) == 1) {
4048            // vqadd.s<size> Qd, Qm, Qn.
4049            NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4050            switch (size) {
4051              case Neon8:
4052                AddSaturate<int8_t>(this, Vd, Vm, Vn);
4053                break;
4054              case Neon16:
4055                AddSaturate<int16_t>(this, Vd, Vm, Vn);
4056                break;
4057              case Neon32:
4058                AddSaturate<int32_t>(this, Vd, Vm, Vn);
4059                break;
4060              default:
4061                UNREACHABLE();
4062                break;
4063            }
4064          } else {
4065            UNIMPLEMENTED();
4066          }
4067          break;
4068        }
4069        case 0x1: {
4070          if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 &&
4071              instr->Bit(4) == 1) {
4072            // vmov Qd, Qm.
4073            // vorr, Qd, Qm, Qn.
4074            uint32_t src1[4];
4075            get_q_register(Vm, src1);
4076            if (Vm != Vn) {
4077              uint32_t src2[4];
4078              get_q_register(Vn, src2);
4079              for (int i = 0; i < 4; i++) {
4080                src1[i] = src1[i] | src2[i];
4081              }
4082            }
4083            set_q_register(Vd, src1);
4084          } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
4085                     instr->Bit(4) == 1) {
4086            // vand Qd, Qm, Qn.
4087            uint32_t src1[4], src2[4];
4088            get_q_register(Vn, src1);
4089            get_q_register(Vm, src2);
4090            for (int i = 0; i < 4; i++) {
4091              src1[i] = src1[i] & src2[i];
4092            }
4093            set_q_register(Vd, src1);
4094          } else {
4095            UNIMPLEMENTED();
4096          }
4097          break;
4098        }
4099        case 0x2: {
4100          if (instr->Bit(4) == 1) {
4101            // vqsub.s<size> Qd, Qm, Qn.
4102            NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4103            switch (size) {
4104              case Neon8:
4105                SubSaturate<int8_t>(this, Vd, Vm, Vn);
4106                break;
4107              case Neon16:
4108                SubSaturate<int16_t>(this, Vd, Vm, Vn);
4109                break;
4110              case Neon32:
4111                SubSaturate<int32_t>(this, Vd, Vm, Vn);
4112                break;
4113              default:
4114                UNREACHABLE();
4115                break;
4116            }
4117          } else {
4118            UNIMPLEMENTED();
4119          }
4120          break;
4121        }
4122        case 0x3: {
4123          // vcge/vcgt.s<size> Qd, Qm, Qn.
4124          bool ge = instr->Bit(4) == 1;
4125          NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4126          switch (size) {
4127            case Neon8: {
4128              int8_t src1[16], src2[16];
4129              get_q_register(Vn, src1);
4130              get_q_register(Vm, src2);
4131              for (int i = 0; i < 16; i++) {
4132                if (ge)
4133                  src1[i] = src1[i] >= src2[i] ? 0xFF : 0;
4134                else
4135                  src1[i] = src1[i] > src2[i] ? 0xFF : 0;
4136              }
4137              set_q_register(Vd, src1);
4138              break;
4139            }
4140            case Neon16: {
4141              int16_t src1[8], src2[8];
4142              get_q_register(Vn, src1);
4143              get_q_register(Vm, src2);
4144              for (int i = 0; i < 8; i++) {
4145                if (ge)
4146                  src1[i] = src1[i] >= src2[i] ? 0xFFFF : 0;
4147                else
4148                  src1[i] = src1[i] > src2[i] ? 0xFFFF : 0;
4149              }
4150              set_q_register(Vd, src1);
4151              break;
4152            }
4153            case Neon32: {
4154              int32_t src1[4], src2[4];
4155              get_q_register(Vn, src1);
4156              get_q_register(Vm, src2);
4157              for (int i = 0; i < 4; i++) {
4158                if (ge)
4159                  src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFF : 0;
4160                else
4161                  src1[i] = src1[i] > src2[i] ? 0xFFFFFFFF : 0;
4162              }
4163              set_q_register(Vd, src1);
4164              break;
4165            }
4166            default:
4167              UNREACHABLE();
4168              break;
4169          }
4170          break;
4171        }
4172        case 0x6: {
4173          // vmin/vmax.s<size> Qd, Qm, Qn.
4174          NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4175          bool min = instr->Bit(4) != 0;
4176          switch (size) {
4177            case Neon8: {
4178              int8_t src1[16], src2[16];
4179              get_q_register(Vn, src1);
4180              get_q_register(Vm, src2);
4181              for (int i = 0; i < 16; i++) {
4182                if (min)
4183                  src1[i] = std::min(src1[i], src2[i]);
4184                else
4185                  src1[i] = std::max(src1[i], src2[i]);
4186              }
4187              set_q_register(Vd, src1);
4188              break;
4189            }
4190            case Neon16: {
4191              int16_t src1[8], src2[8];
4192              get_q_register(Vn, src1);
4193              get_q_register(Vm, src2);
4194              for (int i = 0; i < 8; i++) {
4195                if (min)
4196                  src1[i] = std::min(src1[i], src2[i]);
4197                else
4198                  src1[i] = std::max(src1[i], src2[i]);
4199              }
4200              set_q_register(Vd, src1);
4201              break;
4202            }
4203            case Neon32: {
4204              int32_t src1[4], src2[4];
4205              get_q_register(Vn, src1);
4206              get_q_register(Vm, src2);
4207              for (int i = 0; i < 4; i++) {
4208                if (min)
4209                  src1[i] = std::min(src1[i], src2[i]);
4210                else
4211                  src1[i] = std::max(src1[i], src2[i]);
4212              }
4213              set_q_register(Vd, src1);
4214              break;
4215            }
4216            default:
4217              UNREACHABLE();
4218              break;
4219          }
4220          break;
4221        }
4222        case 0x8: {
4223          // vadd/vtst
4224          NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4225          if (instr->Bit(4) == 0) {
4226            // vadd.i<size> Qd, Qm, Qn.
4227            switch (size) {
4228              case Neon8: {
4229                uint8_t src1[16], src2[16];
4230                get_q_register(Vn, src1);
4231                get_q_register(Vm, src2);
4232                for (int i = 0; i < 16; i++) {
4233                  src1[i] += src2[i];
4234                }
4235                set_q_register(Vd, src1);
4236                break;
4237              }
4238              case Neon16: {
4239                uint16_t src1[8], src2[8];
4240                get_q_register(Vn, src1);
4241                get_q_register(Vm, src2);
4242                for (int i = 0; i < 8; i++) {
4243                  src1[i] += src2[i];
4244                }
4245                set_q_register(Vd, src1);
4246                break;
4247              }
4248              case Neon32: {
4249                uint32_t src1[4], src2[4];
4250                get_q_register(Vn, src1);
4251                get_q_register(Vm, src2);
4252                for (int i = 0; i < 4; i++) {
4253                  src1[i] += src2[i];
4254                }
4255                set_q_register(Vd, src1);
4256                break;
4257              }
4258              default:
4259                UNREACHABLE();
4260                break;
4261            }
4262          } else {
4263            // vtst.i<size> Qd, Qm, Qn.
4264            switch (size) {
4265              case Neon8: {
4266                uint8_t src1[16], src2[16];
4267                get_q_register(Vn, src1);
4268                get_q_register(Vm, src2);
4269                for (int i = 0; i < 16; i++) {
4270                  src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFu : 0;
4271                }
4272                set_q_register(Vd, src1);
4273                break;
4274              }
4275              case Neon16: {
4276                uint16_t src1[8], src2[8];
4277                get_q_register(Vn, src1);
4278                get_q_register(Vm, src2);
4279                for (int i = 0; i < 8; i++) {
4280                  src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFu : 0;
4281                }
4282                set_q_register(Vd, src1);
4283                break;
4284              }
4285              case Neon32: {
4286                uint32_t src1[4], src2[4];
4287                get_q_register(Vn, src1);
4288                get_q_register(Vm, src2);
4289                for (int i = 0; i < 4; i++) {
4290                  src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFFFFFu : 0;
4291                }
4292                set_q_register(Vd, src1);
4293                break;
4294              }
4295              default:
4296                UNREACHABLE();
4297                break;
4298            }
4299          }
4300          break;
4301        }
4302        case 0x9: {
4303          if (instr->Bit(6) == 1 && instr->Bit(4) == 1) {
4304            // vmul.i<size> Qd, Qm, Qn.
4305            NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4306            switch (size) {
4307              case Neon8: {
4308                uint8_t src1[16], src2[16];
4309                get_q_register(Vn, src1);
4310                get_q_register(Vm, src2);
4311                for (int i = 0; i < 16; i++) {
4312                  src1[i] *= src2[i];
4313                }
4314                set_q_register(Vd, src1);
4315                break;
4316              }
4317              case Neon16: {
4318                uint16_t src1[8], src2[8];
4319                get_q_register(Vn, src1);
4320                get_q_register(Vm, src2);
4321                for (int i = 0; i < 8; i++) {
4322                  src1[i] *= src2[i];
4323                }
4324                set_q_register(Vd, src1);
4325                break;
4326              }
4327              case Neon32: {
4328                uint32_t src1[4], src2[4];
4329                get_q_register(Vn, src1);
4330                get_q_register(Vm, src2);
4331                for (int i = 0; i < 4; i++) {
4332                  src1[i] *= src2[i];
4333                }
4334                set_q_register(Vd, src1);
4335                break;
4336              }
4337              default:
4338                UNREACHABLE();
4339                break;
4340            }
4341          } else {
4342            UNIMPLEMENTED();
4343          }
4344          break;
4345        }
4346        case 0xd: {
4347          if (instr->Bit(4) == 0) {
4348            float src1[4], src2[4];
4349            get_q_register(Vn, src1);
4350            get_q_register(Vm, src2);
4351            for (int i = 0; i < 4; i++) {
4352              if (instr->Bit(21) == 0) {
4353                // vadd.f32 Qd, Qm, Qn.
4354                src1[i] = src1[i] + src2[i];
4355              } else {
4356                // vsub.f32 Qd, Qm, Qn.
4357                src1[i] = src1[i] - src2[i];
4358              }
4359            }
4360            set_q_register(Vd, src1);
4361          } else {
4362            UNIMPLEMENTED();
4363          }
4364          break;
4365        }
4366        case 0xe: {
4367          if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) {
4368            // vceq.f32.
4369            float src1[4], src2[4];
4370            get_q_register(Vn, src1);
4371            get_q_register(Vm, src2);
4372            uint32_t dst[4];
4373            for (int i = 0; i < 4; i++) {
4374              dst[i] = (src1[i] == src2[i]) ? 0xFFFFFFFF : 0;
4375            }
4376            set_q_register(Vd, dst);
4377          } else {
4378            UNIMPLEMENTED();
4379          }
4380          break;
4381        }
4382        case 0xf: {
4383          if (instr->Bit(20) == 0 && instr->Bit(6) == 1) {
4384            float src1[4], src2[4];
4385            get_q_register(Vn, src1);
4386            get_q_register(Vm, src2);
4387            if (instr->Bit(4) == 1) {
4388              if (instr->Bit(21) == 0) {
4389                // vrecps.f32 Qd, Qm, Qn.
4390                for (int i = 0; i < 4; i++) {
4391                  src1[i] = 2.0f - src1[i] * src2[i];
4392                }
4393              } else {
4394                // vrsqrts.f32 Qd, Qm, Qn.
4395                for (int i = 0; i < 4; i++) {
4396                  src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f;
4397                }
4398              }
4399            } else {
4400              if (instr->Bit(21) == 1) {
4401                // vmin.f32 Qd, Qm, Qn.
4402                for (int i = 0; i < 4; i++) {
4403                  src1[i] = std::min(src1[i], src2[i]);
4404                }
4405              } else {
4406                // vmax.f32 Qd, Qm, Qn.
4407                for (int i = 0; i < 4; i++) {
4408                  src1[i] = std::max(src1[i], src2[i]);
4409                }
4410              }
4411            }
4412            set_q_register(Vd, src1);
4413          } else {
4414            UNIMPLEMENTED();
4415          }
4416          break;
4417        }
4418        default:
4419          UNIMPLEMENTED();
4420          break;
4421      }
4422      break;
4423    }
4424    case 5:
4425      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
4426          (instr->Bit(4) == 1)) {
4427        // vmovl signed
4428        if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
4429        int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
4430        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
4431        int imm3 = instr->Bits(21, 19);
4432        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
4433        int esize = 8 * imm3;
4434        int elements = 64 / esize;
4435        int8_t from[8];
4436        get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
4437        int16_t to[8];
4438        int e = 0;
4439        while (e < elements) {
4440          to[e] = from[e];
4441          e++;
4442        }
4443        set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
4444      } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) {
4445        // vext.
4446        int imm4 = instr->Bits(11, 8);
4447        int Vd = instr->VFPDRegValue(kSimd128Precision);
4448        int Vm = instr->VFPMRegValue(kSimd128Precision);
4449        int Vn = instr->VFPNRegValue(kSimd128Precision);
4450        uint8_t src1[16], src2[16], dst[16];
4451        get_q_register(Vn, src1);
4452        get_q_register(Vm, src2);
4453        int boundary = kSimd128Size - imm4;
4454        int i = 0;
4455        for (; i < boundary; i++) {
4456          dst[i] = src1[i + imm4];
4457        }
4458        for (; i < 16; i++) {
4459          dst[i] = src2[i - boundary];
4460        }
4461        set_q_register(Vd, dst);
4462      } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
4463        // vshl.i<size> Qd, Qm, shift
4464        int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
4465        int shift = instr->Bits(21, 16) - size;
4466        int Vd = instr->VFPDRegValue(kSimd128Precision);
4467        int Vm = instr->VFPMRegValue(kSimd128Precision);
4468        NeonSize ns = static_cast<NeonSize>(size / 16);
4469        switch (ns) {
4470          case Neon8: {
4471            uint8_t src[16];
4472            get_q_register(Vm, src);
4473            for (int i = 0; i < 16; i++) {
4474              src[i] <<= shift;
4475            }
4476            set_q_register(Vd, src);
4477            break;
4478          }
4479          case Neon16: {
4480            uint16_t src[8];
4481            get_q_register(Vm, src);
4482            for (int i = 0; i < 8; i++) {
4483              src[i] <<= shift;
4484            }
4485            set_q_register(Vd, src);
4486            break;
4487          }
4488          case Neon32: {
4489            uint32_t src[4];
4490            get_q_register(Vm, src);
4491            for (int i = 0; i < 4; i++) {
4492              src[i] <<= shift;
4493            }
4494            set_q_register(Vd, src);
4495            break;
4496          }
4497          default:
4498            UNREACHABLE();
4499            break;
4500        }
4501      } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
4502        // vshr.s<size> Qd, Qm, shift
4503        int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
4504        int shift = 2 * size - instr->Bits(21, 16);
4505        int Vd = instr->VFPDRegValue(kSimd128Precision);
4506        int Vm = instr->VFPMRegValue(kSimd128Precision);
4507        NeonSize ns = static_cast<NeonSize>(size / 16);
4508        switch (ns) {
4509          case Neon8: {
4510            int8_t src[16];
4511            get_q_register(Vm, src);
4512            for (int i = 0; i < 16; i++) {
4513              src[i] = ArithmeticShiftRight(src[i], shift);
4514            }
4515            set_q_register(Vd, src);
4516            break;
4517          }
4518          case Neon16: {
4519            int16_t src[8];
4520            get_q_register(Vm, src);
4521            for (int i = 0; i < 8; i++) {
4522              src[i] = ArithmeticShiftRight(src[i], shift);
4523            }
4524            set_q_register(Vd, src);
4525            break;
4526          }
4527          case Neon32: {
4528            int32_t src[4];
4529            get_q_register(Vm, src);
4530            for (int i = 0; i < 4; i++) {
4531              src[i] = ArithmeticShiftRight(src[i], shift);
4532            }
4533            set_q_register(Vd, src);
4534            break;
4535          }
4536          default:
4537            UNREACHABLE();
4538            break;
4539        }
4540      } else {
4541        UNIMPLEMENTED();
4542      }
4543      break;
4544    case 6: {
4545      int Vd, Vm, Vn;
4546      if (instr->Bit(6) == 0) {
4547        Vd = instr->VFPDRegValue(kDoublePrecision);
4548        Vm = instr->VFPMRegValue(kDoublePrecision);
4549        Vn = instr->VFPNRegValue(kDoublePrecision);
4550      } else {
4551        Vd = instr->VFPDRegValue(kSimd128Precision);
4552        Vm = instr->VFPMRegValue(kSimd128Precision);
4553        Vn = instr->VFPNRegValue(kSimd128Precision);
4554      }
4555      switch (instr->Bits(11, 8)) {
4556        case 0x0: {
4557          if (instr->Bit(4) == 1) {
4558            // vqadd.u<size> Qd, Qm, Qn.
4559            NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4560            switch (size) {
4561              case Neon8:
4562                AddSaturate<uint8_t>(this, Vd, Vm, Vn);
4563                break;
4564              case Neon16:
4565                AddSaturate<uint16_t>(this, Vd, Vm, Vn);
4566                break;
4567              case Neon32:
4568                AddSaturate<uint32_t>(this, Vd, Vm, Vn);
4569                break;
4570              default:
4571                UNREACHABLE();
4572                break;
4573            }
4574          } else {
4575            UNIMPLEMENTED();
4576          }
4577          break;
4578        }
4579        case 0x1: {
4580          if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) {
4581            // vbsl.size Qd, Qm, Qn.
4582            uint32_t dst[4], src1[4], src2[4];
4583            get_q_register(Vd, dst);
4584            get_q_register(Vn, src1);
4585            get_q_register(Vm, src2);
4586            for (int i = 0; i < 4; i++) {
4587              dst[i] = (dst[i] & src1[i]) | (~dst[i] & src2[i]);
4588            }
4589            set_q_register(Vd, dst);
4590          } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) {
4591            if (instr->Bit(6) == 0) {
4592              // veor Dd, Dn, Dm
4593              uint64_t src1, src2;
4594              get_d_register(Vn, &src1);
4595              get_d_register(Vm, &src2);
4596              src1 ^= src2;
4597              set_d_register(Vd, &src1);
4598
4599            } else {
4600              // veor Qd, Qn, Qm
4601              uint32_t src1[4], src2[4];
4602              get_q_register(Vn, src1);
4603              get_q_register(Vm, src2);
4604              for (int i = 0; i < 4; i++) src1[i] ^= src2[i];
4605              set_q_register(Vd, src1);
4606            }
4607          } else {
4608            UNIMPLEMENTED();
4609          }
4610          break;
4611        }
4612        case 0x2: {
4613          if (instr->Bit(4) == 1) {
4614            // vqsub.u<size> Qd, Qm, Qn.
4615            NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4616            switch (size) {
4617              case Neon8:
4618                SubSaturate<uint8_t>(this, Vd, Vm, Vn);
4619                break;
4620              case Neon16:
4621                SubSaturate<uint16_t>(this, Vd, Vm, Vn);
4622                break;
4623              case Neon32:
4624                SubSaturate<uint32_t>(this, Vd, Vm, Vn);
4625                break;
4626              default:
4627                UNREACHABLE();
4628                break;
4629            }
4630          } else {
4631            UNIMPLEMENTED();
4632          }
4633          break;
4634        }
4635        case 0x3: {
4636          // vcge/vcgt.u<size> Qd, Qm, Qn.
4637          bool ge = instr->Bit(4) == 1;
4638          NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4639          switch (size) {
4640            case Neon8: {
4641              uint8_t src1[16], src2[16];
4642              get_q_register(Vn, src1);
4643              get_q_register(Vm, src2);
4644              for (int i = 0; i < 16; i++) {
4645                if (ge)
4646                  src1[i] = src1[i] >= src2[i] ? 0xFFu : 0;
4647                else
4648                  src1[i] = src1[i] > src2[i] ? 0xFFu : 0;
4649              }
4650              set_q_register(Vd, src1);
4651              break;
4652            }
4653            case Neon16: {
4654              uint16_t src1[8], src2[8];
4655              get_q_register(Vn, src1);
4656              get_q_register(Vm, src2);
4657              for (int i = 0; i < 8; i++) {
4658                if (ge)
4659                  src1[i] = src1[i] >= src2[i] ? 0xFFFFu : 0;
4660                else
4661                  src1[i] = src1[i] > src2[i] ? 0xFFFFu : 0;
4662              }
4663              set_q_register(Vd, src1);
4664              break;
4665            }
4666            case Neon32: {
4667              uint32_t src1[4], src2[4];
4668              get_q_register(Vn, src1);
4669              get_q_register(Vm, src2);
4670              for (int i = 0; i < 4; i++) {
4671                if (ge)
4672                  src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0;
4673                else
4674                  src1[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0;
4675              }
4676              set_q_register(Vd, src1);
4677              break;
4678            }
4679            default:
4680              UNREACHABLE();
4681              break;
4682          }
4683          break;
4684        }
4685        case 0x6: {
4686          // vmin/vmax.u<size> Qd, Qm, Qn.
4687          NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4688          bool min = instr->Bit(4) != 0;
4689          switch (size) {
4690            case Neon8: {
4691              uint8_t src1[16], src2[16];
4692              get_q_register(Vn, src1);
4693              get_q_register(Vm, src2);
4694              for (int i = 0; i < 16; i++) {
4695                if (min)
4696                  src1[i] = std::min(src1[i], src2[i]);
4697                else
4698                  src1[i] = std::max(src1[i], src2[i]);
4699              }
4700              set_q_register(Vd, src1);
4701              break;
4702            }
4703            case Neon16: {
4704              uint16_t src1[8], src2[8];
4705              get_q_register(Vn, src1);
4706              get_q_register(Vm, src2);
4707              for (int i = 0; i < 8; i++) {
4708                if (min)
4709                  src1[i] = std::min(src1[i], src2[i]);
4710                else
4711                  src1[i] = std::max(src1[i], src2[i]);
4712              }
4713              set_q_register(Vd, src1);
4714              break;
4715            }
4716            case Neon32: {
4717              uint32_t src1[4], src2[4];
4718              get_q_register(Vn, src1);
4719              get_q_register(Vm, src2);
4720              for (int i = 0; i < 4; i++) {
4721                if (min)
4722                  src1[i] = std::min(src1[i], src2[i]);
4723                else
4724                  src1[i] = std::max(src1[i], src2[i]);
4725              }
4726              set_q_register(Vd, src1);
4727              break;
4728            }
4729            default:
4730              UNREACHABLE();
4731              break;
4732          }
4733          break;
4734        }
4735        case 0x8: {
4736          if (instr->Bit(4) == 0) {
4737            // vsub.size Qd, Qm, Qn.
4738            NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4739            switch (size) {
4740              case Neon8: {
4741                uint8_t src1[16], src2[16];
4742                get_q_register(Vn, src1);
4743                get_q_register(Vm, src2);
4744                for (int i = 0; i < 16; i++) {
4745                  src1[i] -= src2[i];
4746                }
4747                set_q_register(Vd, src1);
4748                break;
4749              }
4750              case Neon16: {
4751                uint16_t src1[8], src2[8];
4752                get_q_register(Vn, src1);
4753                get_q_register(Vm, src2);
4754                for (int i = 0; i < 8; i++) {
4755                  src1[i] -= src2[i];
4756                }
4757                set_q_register(Vd, src1);
4758                break;
4759              }
4760              case Neon32: {
4761                uint32_t src1[4], src2[4];
4762                get_q_register(Vn, src1);
4763                get_q_register(Vm, src2);
4764                for (int i = 0; i < 4; i++) {
4765                  src1[i] -= src2[i];
4766                }
4767                set_q_register(Vd, src1);
4768                break;
4769              }
4770              default:
4771                UNREACHABLE();
4772                break;
4773            }
4774          } else {
4775            // vceq.size Qd, Qm, Qn.
4776            NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
4777            switch (size) {
4778              case Neon8: {
4779                uint8_t src1[16], src2[16];
4780                get_q_register(Vn, src1);
4781                get_q_register(Vm, src2);
4782                for (int i = 0; i < 16; i++) {
4783                  src1[i] = (src1[i] == src2[i]) ? 0xFFu : 0;
4784                }
4785                set_q_register(Vd, src1);
4786                break;
4787              }
4788              case Neon16: {
4789                uint16_t src1[8], src2[8];
4790                get_q_register(Vn, src1);
4791                get_q_register(Vm, src2);
4792                for (int i = 0; i < 8; i++) {
4793                  src1[i] = (src1[i] == src2[i]) ? 0xFFFFu : 0;
4794                }
4795                set_q_register(Vd, src1);
4796                break;
4797              }
4798              case Neon32: {
4799                uint32_t src1[4], src2[4];
4800                get_q_register(Vn, src1);
4801                get_q_register(Vm, src2);
4802                for (int i = 0; i < 4; i++) {
4803                  src1[i] = (src1[i] == src2[i]) ? 0xFFFFFFFFu : 0;
4804                }
4805                set_q_register(Vd, src1);
4806                break;
4807              }
4808              default:
4809                UNREACHABLE();
4810                break;
4811            }
4812          }
4813          break;
4814        }
4815        case 0xd: {
4816          if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) {
4817            // vmul.f32 Qd, Qn, Qm
4818            float src1[4], src2[4];
4819            get_q_register(Vn, src1);
4820            get_q_register(Vm, src2);
4821            for (int i = 0; i < 4; i++) {
4822              src1[i] = src1[i] * src2[i];
4823            }
4824            set_q_register(Vd, src1);
4825          } else {
4826            UNIMPLEMENTED();
4827          }
4828          break;
4829        }
4830        case 0xe: {
4831          if (instr->Bit(20) == 0 && instr->Bit(4) == 0) {
4832            // vcge/vcgt.f32 Qd, Qm, Qn
4833            bool ge = instr->Bit(21) == 0;
4834            float src1[4], src2[4];
4835            get_q_register(Vn, src1);
4836            get_q_register(Vm, src2);
4837            uint32_t dst[4];
4838            for (int i = 0; i < 4; i++) {
4839              if (ge) {
4840                dst[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0;
4841              } else {
4842                dst[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0;
4843              }
4844            }
4845            set_q_register(Vd, dst);
4846          } else {
4847            UNIMPLEMENTED();
4848          }
4849          break;
4850        }
4851        default:
4852          UNREACHABLE();
4853          break;
4854      }
4855      break;
4856    }
4857    case 7:
4858      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
4859          (instr->Bit(4) == 1)) {
4860        // vmovl unsigned
4861        if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
4862        int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
4863        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
4864        int imm3 = instr->Bits(21, 19);
4865        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
4866        int esize = 8 * imm3;
4867        int elements = 64 / esize;
4868        uint8_t from[8];
4869        get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
4870        uint16_t to[8];
4871        int e = 0;
4872        while (e < elements) {
4873          to[e] = from[e];
4874          e++;
4875        }
4876        set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
4877      } else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
4878        if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 &&
4879            instr->Bit(6) == 1) {
4880          // vcvt.<Td>.<Tm> Qd, Qm.
4881          int Vd = instr->VFPDRegValue(kSimd128Precision);
4882          int Vm = instr->VFPMRegValue(kSimd128Precision);
4883          uint32_t q_data[4];
4884          get_q_register(Vm, q_data);
4885          int op = instr->Bits(8, 7);
4886          for (int i = 0; i < 4; i++) {
4887            switch (op) {
4888              case 0:
4889                // f32 <- s32, round towards nearest.
4890                q_data[i] = bit_cast<uint32_t>(std::round(
4891                    static_cast<float>(bit_cast<int32_t>(q_data[i]))));
4892                break;
4893              case 1:
4894                // f32 <- u32, round towards nearest.
4895                q_data[i] = bit_cast<uint32_t>(
4896                    std::round(static_cast<float>(q_data[i])));
4897                break;
4898              case 2:
4899                // s32 <- f32, round to zero.
4900                q_data[i] = static_cast<uint32_t>(
4901                    ConvertDoubleToInt(bit_cast<float>(q_data[i]), false, RZ));
4902                break;
4903              case 3:
4904                // u32 <- f32, round to zero.
4905                q_data[i] = static_cast<uint32_t>(
4906                    ConvertDoubleToInt(bit_cast<float>(q_data[i]), true, RZ));
4907                break;
4908            }
4909          }
4910          set_q_register(Vd, q_data);
4911        } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) {
4912          if (instr->Bit(6) == 0) {
4913            // vswp Dd, Dm.
4914            uint64_t dval, mval;
4915            int vd = instr->VFPDRegValue(kDoublePrecision);
4916            int vm = instr->VFPMRegValue(kDoublePrecision);
4917            get_d_register(vd, &dval);
4918            get_d_register(vm, &mval);
4919            set_d_register(vm, &dval);
4920            set_d_register(vd, &mval);
4921          } else {
4922            // vswp Qd, Qm.
4923            uint32_t dval[4], mval[4];
4924            int vd = instr->VFPDRegValue(kSimd128Precision);
4925            int vm = instr->VFPMRegValue(kSimd128Precision);
4926            get_q_register(vd, dval);
4927            get_q_register(vm, mval);
4928            set_q_register(vm, dval);
4929            set_q_register(vd, mval);
4930          }
4931        } else if (instr->Bits(11, 7) == 0x18) {
4932          // vdup.32 Qd, Sm.
4933          int vd = instr->VFPDRegValue(kSimd128Precision);
4934          int vm = instr->VFPMRegValue(kDoublePrecision);
4935          int index = instr->Bit(19);
4936          uint32_t s_data = get_s_register(vm * 2 + index);
4937          uint32_t q_data[4];
4938          for (int i = 0; i < 4; i++) q_data[i] = s_data;
4939          set_q_register(vd, q_data);
4940        } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
4941          // vmvn Qd, Qm.
4942          int vd = instr->VFPDRegValue(kSimd128Precision);
4943          int vm = instr->VFPMRegValue(kSimd128Precision);
4944          uint32_t q_data[4];
4945          get_q_register(vm, q_data);
4946          for (int i = 0; i < 4; i++) q_data[i] = ~q_data[i];
4947          set_q_register(vd, q_data);
4948        } else if (instr->Bits(11, 10) == 0x2) {
4949          // vtb[l,x] Dd, <list>, Dm.
4950          int vd = instr->VFPDRegValue(kDoublePrecision);
4951          int vn = instr->VFPNRegValue(kDoublePrecision);
4952          int vm = instr->VFPMRegValue(kDoublePrecision);
4953          int table_len = (instr->Bits(9, 8) + 1) * kDoubleSize;
4954          bool vtbx = instr->Bit(6) != 0;  // vtbl / vtbx
4955          uint64_t destination = 0, indices = 0, result = 0;
4956          get_d_register(vd, &destination);
4957          get_d_register(vm, &indices);
4958          for (int i = 0; i < kDoubleSize; i++) {
4959            int shift = i * kBitsPerByte;
4960            int index = (indices >> shift) & 0xFF;
4961            if (index < table_len) {
4962              uint64_t table;
4963              get_d_register(vn + index / kDoubleSize, &table);
4964              result |=
4965                  ((table >> ((index % kDoubleSize) * kBitsPerByte)) & 0xFF)
4966                  << shift;
4967            } else if (vtbx) {
4968              result |= destination & (0xFFull << shift);
4969            }
4970          }
4971          set_d_register(vd, &result);
4972        } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x7) {
4973          // vzip.<size> Qd, Qm.
4974          NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
4975          int Vd = instr->VFPDRegValue(kSimd128Precision);
4976          int Vm = instr->VFPMRegValue(kSimd128Precision);
4977          switch (size) {
4978            case Neon8: {
4979              uint8_t src1[16], src2[16], dst1[16], dst2[16];
4980              get_q_register(Vd, src1);
4981              get_q_register(Vm, src2);
4982              for (int i = 0; i < 8; i++) {
4983                dst1[i * 2] = src1[i];
4984                dst1[i * 2 + 1] = src2[i];
4985                dst2[i * 2] = src1[i + 8];
4986                dst2[i * 2 + 1] = src2[i + 8];
4987              }
4988              set_q_register(Vd, dst1);
4989              set_q_register(Vm, dst2);
4990              break;
4991            }
4992            case Neon16: {
4993              uint16_t src1[8], src2[8], dst1[8], dst2[8];
4994              get_q_register(Vd, src1);
4995              get_q_register(Vm, src2);
4996              for (int i = 0; i < 8; i += 2) {
4997                dst1[i] = src1[i / 2];
4998                dst1[i + 1] = src2[i / 2];
4999                dst2[i] = src1[i / 2 + 4];
5000                dst2[i + 1] = src2[i / 2 + 4];
5001              }
5002              set_q_register(Vd, dst1);
5003              set_q_register(Vm, dst2);
5004              break;
5005            }
5006            case Neon32: {
5007              uint32_t src1[4], src2[4], dst1[4], dst2[4];
5008              get_q_register(Vd, src1);
5009              get_q_register(Vm, src2);
5010              for (int i = 0; i < 2; i++) {
5011                dst1[i * 2] = src1[i];
5012                dst1[i * 2 + 1] = src2[i];
5013                dst2[i * 2] = src1[i + 2];
5014                dst2[i * 2 + 1] = src2[i + 2];
5015              }
5016              set_q_register(Vd, dst1);
5017              set_q_register(Vm, dst2);
5018              break;
5019            }
5020            default:
5021              UNREACHABLE();
5022              break;
5023          }
5024        } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) {
5025          // vrev<op>.size Qd, Qm
5026          int Vd = instr->VFPDRegValue(kSimd128Precision);
5027          int Vm = instr->VFPMRegValue(kSimd128Precision);
5028          NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
5029          NeonSize op = static_cast<NeonSize>(static_cast<int>(Neon64) -
5030                                              instr->Bits(8, 7));
5031          switch (op) {
5032            case Neon16: {
5033              DCHECK_EQ(Neon8, size);
5034              uint8_t src[16];
5035              get_q_register(Vm, src);
5036              for (int i = 0; i < 16; i += 2) {
5037                std::swap(src[i], src[i + 1]);
5038              }
5039              set_q_register(Vd, src);
5040              break;
5041            }
5042            case Neon32: {
5043              switch (size) {
5044                case Neon16: {
5045                  uint16_t src[8];
5046                  get_q_register(Vm, src);
5047                  for (int i = 0; i < 8; i += 2) {
5048                    std::swap(src[i], src[i + 1]);
5049                  }
5050                  set_q_register(Vd, src);
5051                  break;
5052                }
5053                case Neon8: {
5054                  uint8_t src[16];
5055                  get_q_register(Vm, src);
5056                  for (int i = 0; i < 4; i++) {
5057                    std::swap(src[i * 4], src[i * 4 + 3]);
5058                    std::swap(src[i * 4 + 1], src[i * 4 + 2]);
5059                  }
5060                  set_q_register(Vd, src);
5061                  break;
5062                }
5063                default:
5064                  UNREACHABLE();
5065                  break;
5066              }
5067              break;
5068            }
5069            case Neon64: {
5070              switch (size) {
5071                case Neon32: {
5072                  uint32_t src[4];
5073                  get_q_register(Vm, src);
5074                  std::swap(src[0], src[1]);
5075                  std::swap(src[2], src[3]);
5076                  set_q_register(Vd, src);
5077                  break;
5078                }
5079                case Neon16: {
5080                  uint16_t src[8];
5081                  get_q_register(Vm, src);
5082                  for (int i = 0; i < 4; i++) {
5083                    std::swap(src[i * 4], src[i * 4 + 3]);
5084                    std::swap(src[i * 4 + 1], src[i * 4 + 2]);
5085                  }
5086                  set_q_register(Vd, src);
5087                  break;
5088                }
5089                case Neon8: {
5090                  uint8_t src[16];
5091                  get_q_register(Vm, src);
5092                  for (int i = 0; i < 4; i++) {
5093                    std::swap(src[i], src[7 - i]);
5094                    std::swap(src[i + 8], src[15 - i]);
5095                  }
5096                  set_q_register(Vd, src);
5097                  break;
5098                }
5099                default:
5100                  UNREACHABLE();
5101                  break;
5102              }
5103              break;
5104            }
5105            default:
5106              UNREACHABLE();
5107              break;
5108          }
5109        } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) {
5110          int Vd = instr->VFPDRegValue(kSimd128Precision);
5111          int Vm = instr->VFPMRegValue(kSimd128Precision);
5112          NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
5113          if (instr->Bits(9, 6) == 0xd) {
5114            // vabs<type>.<size> Qd, Qm
5115            if (instr->Bit(10) != 0) {
5116              // floating point (clear sign bits)
5117              uint32_t src[4];
5118              get_q_register(Vm, src);
5119              for (int i = 0; i < 4; i++) {
5120                src[i] &= ~0x80000000;
5121              }
5122              set_q_register(Vd, src);
5123            } else {
5124              // signed integer
5125              switch (size) {
5126                case Neon8: {
5127                  int8_t src[16];
5128                  get_q_register(Vm, src);
5129                  for (int i = 0; i < 16; i++) {
5130                    src[i] = std::abs(src[i]);
5131                  }
5132                  set_q_register(Vd, src);
5133                  break;
5134                }
5135                case Neon16: {
5136                  int16_t src[8];
5137                  get_q_register(Vm, src);
5138                  for (int i = 0; i < 8; i++) {
5139                    src[i] = std::abs(src[i]);
5140                  }
5141                  set_q_register(Vd, src);
5142                  break;
5143                }
5144                case Neon32: {
5145                  int32_t src[4];
5146                  get_q_register(Vm, src);
5147                  for (int i = 0; i < 4; i++) {
5148                    src[i] = std::abs(src[i]);
5149                  }
5150                  set_q_register(Vd, src);
5151                  break;
5152                }
5153                default:
5154                  UNIMPLEMENTED();
5155                  break;
5156              }
5157            }
5158          } else if (instr->Bits(9, 6) == 0xf) {
5159            // vneg<type>.<size> Qd, Qm (signed integer)
5160            if (instr->Bit(10) != 0) {
5161              // floating point (toggle sign bits)
5162              uint32_t src[4];
5163              get_q_register(Vm, src);
5164              for (int i = 0; i < 4; i++) {
5165                src[i] ^= 0x80000000;
5166              }
5167              set_q_register(Vd, src);
5168            } else {
5169              // signed integer
5170              switch (size) {
5171                case Neon8: {
5172                  int8_t src[16];
5173                  get_q_register(Vm, src);
5174                  for (int i = 0; i < 16; i++) {
5175                    src[i] = -src[i];
5176                  }
5177                  set_q_register(Vd, src);
5178                  break;
5179                }
5180                case Neon16:
5181                  int16_t src[8];
5182                  get_q_register(Vm, src);
5183                  for (int i = 0; i < 8; i++) {
5184                    src[i] = -src[i];
5185                  }
5186                  set_q_register(Vd, src);
5187                  break;
5188                case Neon32: {
5189                  int32_t src[4];
5190                  get_q_register(Vm, src);
5191                  for (int i = 0; i < 4; i++) {
5192                    src[i] = -src[i];
5193                  }
5194                  set_q_register(Vd, src);
5195                  break;
5196                }
5197                default:
5198                  UNIMPLEMENTED();
5199                  break;
5200              }
5201            }
5202          } else {
5203            UNIMPLEMENTED();
5204          }
5205        } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5) {
5206          // vrecpe/vrsqrte.f32 Qd, Qm.
5207          int Vd = instr->VFPDRegValue(kSimd128Precision);
5208          int Vm = instr->VFPMRegValue(kSimd128Precision);
5209          uint32_t src[4];
5210          get_q_register(Vm, src);
5211          if (instr->Bit(7) == 0) {
5212            for (int i = 0; i < 4; i++) {
5213              float denom = bit_cast<float>(src[i]);
5214              div_zero_vfp_flag_ = (denom == 0);
5215              float result = 1.0f / denom;
5216              result = canonicalizeNaN(result);
5217              src[i] = bit_cast<uint32_t>(result);
5218            }
5219          } else {
5220            lazily_initialize_fast_sqrt(isolate_);
5221            for (int i = 0; i < 4; i++) {
5222              float radicand = bit_cast<float>(src[i]);
5223              float result = 1.0f / fast_sqrt(radicand, isolate_);
5224              result = canonicalizeNaN(result);
5225              src[i] = bit_cast<uint32_t>(result);
5226            }
5227          }
5228          set_q_register(Vd, src);
5229        } else {
5230          UNIMPLEMENTED();
5231        }
5232      } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
5233        // vshr.u<size> Qd, Qm, shift
5234        int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
5235        int shift = 2 * size - instr->Bits(21, 16);
5236        int Vd = instr->VFPDRegValue(kSimd128Precision);
5237        int Vm = instr->VFPMRegValue(kSimd128Precision);
5238        NeonSize ns = static_cast<NeonSize>(size / 16);
5239        switch (ns) {
5240          case Neon8: {
5241            uint8_t src[16];
5242            get_q_register(Vm, src);
5243            for (int i = 0; i < 16; i++) {
5244              src[i] >>= shift;
5245            }
5246            set_q_register(Vd, src);
5247            break;
5248          }
5249          case Neon16: {
5250            uint16_t src[8];
5251            get_q_register(Vm, src);
5252            for (int i = 0; i < 8; i++) {
5253              src[i] >>= shift;
5254            }
5255            set_q_register(Vd, src);
5256            break;
5257          }
5258          case Neon32: {
5259            uint32_t src[4];
5260            get_q_register(Vm, src);
5261            for (int i = 0; i < 4; i++) {
5262              src[i] >>= shift;
5263            }
5264            set_q_register(Vd, src);
5265            break;
5266          }
5267          default:
5268            UNREACHABLE();
5269            break;
5270        }
5271      } else {
5272        UNIMPLEMENTED();
5273      }
5274      break;
5275    case 8:
5276      if (instr->Bits(21, 20) == 0) {
5277        // vst1
5278        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
5279        int Rn = instr->VnValue();
5280        int type = instr->Bits(11, 8);
5281        int Rm = instr->VmValue();
5282        int32_t address = get_register(Rn);
5283        int regs = 0;
5284        switch (type) {
5285          case nlt_1:
5286            regs = 1;
5287            break;
5288          case nlt_2:
5289            regs = 2;
5290            break;
5291          case nlt_3:
5292            regs = 3;
5293            break;
5294          case nlt_4:
5295            regs = 4;
5296            break;
5297          default:
5298            UNIMPLEMENTED();
5299            break;
5300        }
5301        int r = 0;
5302        while (r < regs) {
5303          uint32_t data[2];
5304          get_d_register(Vd + r, data);
5305          WriteW(address, data[0], instr);
5306          WriteW(address + 4, data[1], instr);
5307          address += 8;
5308          r++;
5309        }
5310        if (Rm != 15) {
5311          if (Rm == 13) {
5312            set_register(Rn, address);
5313          } else {
5314            set_register(Rn, get_register(Rn) + get_register(Rm));
5315          }
5316        }
5317      } else if (instr->Bits(21, 20) == 2) {
5318        // vld1
5319        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
5320        int Rn = instr->VnValue();
5321        int type = instr->Bits(11, 8);
5322        int Rm = instr->VmValue();
5323        int32_t address = get_register(Rn);
5324        int regs = 0;
5325        switch (type) {
5326          case nlt_1:
5327            regs = 1;
5328            break;
5329          case nlt_2:
5330            regs = 2;
5331            break;
5332          case nlt_3:
5333            regs = 3;
5334            break;
5335          case nlt_4:
5336            regs = 4;
5337            break;
5338          default:
5339            UNIMPLEMENTED();
5340            break;
5341        }
5342        int r = 0;
5343        while (r < regs) {
5344          uint32_t data[2];
5345          data[0] = ReadW(address, instr);
5346          data[1] = ReadW(address + 4, instr);
5347          set_d_register(Vd + r, data);
5348          address += 8;
5349          r++;
5350        }
5351        if (Rm != 15) {
5352          if (Rm == 13) {
5353            set_register(Rn, address);
5354          } else {
5355            set_register(Rn, get_register(Rn) + get_register(Rm));
5356          }
5357        }
5358      } else {
5359        UNIMPLEMENTED();
5360      }
5361      break;
5362    case 0xA:
5363    case 0xB:
5364      if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
5365        // pld: ignore instruction.
5366      } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
5367        // dsb, dmb, isb: ignore instruction for now.
5368        // TODO(binji): implement
5369        // Also refer to the ARMv6 CP15 equivalents in DecodeTypeCP15.
5370      } else {
5371        UNIMPLEMENTED();
5372      }
5373      break;
5374    case 0x1D:
5375      if (instr->Opc1Value() == 0x7 && instr->Opc3Value() == 0x1 &&
5376          instr->Bits(11, 9) == 0x5 && instr->Bits(19, 18) == 0x2) {
5377        if (instr->SzValue() == 0x1) {
5378          int vm = instr->VFPMRegValue(kDoublePrecision);
5379          int vd = instr->VFPDRegValue(kDoublePrecision);
5380          double dm_value = get_double_from_d_register(vm);
5381          double dd_value = 0.0;
5382          int rounding_mode = instr->Bits(17, 16);
5383          switch (rounding_mode) {
5384            case 0x0:  // vrinta - round with ties to away from zero
5385              dd_value = round(dm_value);
5386              break;
5387            case 0x1: {  // vrintn - round with ties to even
5388              dd_value = nearbyint(dm_value);
5389              break;
5390            }
5391            case 0x2:  // vrintp - ceil
5392              dd_value = ceil(dm_value);
5393              break;
5394            case 0x3:  // vrintm - floor
5395              dd_value = floor(dm_value);
5396              break;
5397            default:
5398              UNREACHABLE();  // Case analysis is exhaustive.
5399              break;
5400          }
5401          dd_value = canonicalizeNaN(dd_value);
5402          set_d_register_from_double(vd, dd_value);
5403        } else {
5404          int m = instr->VFPMRegValue(kSinglePrecision);
5405          int d = instr->VFPDRegValue(kSinglePrecision);
5406          float sm_value = get_float_from_s_register(m);
5407          float sd_value = 0.0;
5408          int rounding_mode = instr->Bits(17, 16);
5409          switch (rounding_mode) {
5410            case 0x0:  // vrinta - round with ties to away from zero
5411              sd_value = roundf(sm_value);
5412              break;
5413            case 0x1: {  // vrintn - round with ties to even
5414              sd_value = nearbyintf(sm_value);
5415              break;
5416            }
5417            case 0x2:  // vrintp - ceil
5418              sd_value = ceilf(sm_value);
5419              break;
5420            case 0x3:  // vrintm - floor
5421              sd_value = floorf(sm_value);
5422              break;
5423            default:
5424              UNREACHABLE();  // Case analysis is exhaustive.
5425              break;
5426          }
5427          sd_value = canonicalizeNaN(sd_value);
5428          set_s_register_from_float(d, sd_value);
5429        }
5430      } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) &&
5431                 (instr->Bit(4) == 0x0)) {
5432        if (instr->SzValue() == 0x1) {
5433          int m = instr->VFPMRegValue(kDoublePrecision);
5434          int n = instr->VFPNRegValue(kDoublePrecision);
5435          int d = instr->VFPDRegValue(kDoublePrecision);
5436          double dn_value = get_double_from_d_register(n);
5437          double dm_value = get_double_from_d_register(m);
5438          double dd_value;
5439          if (instr->Bit(6) == 0x1) {  // vminnm
5440            if ((dn_value < dm_value) || std::isnan(dm_value)) {
5441              dd_value = dn_value;
5442            } else if ((dm_value < dn_value) || std::isnan(dn_value)) {
5443              dd_value = dm_value;
5444            } else {
5445              DCHECK_EQ(dn_value, dm_value);
5446              // Make sure that we pick the most negative sign for +/-0.
5447              dd_value = std::signbit(dn_value) ? dn_value : dm_value;
5448            }
5449          } else {  // vmaxnm
5450            if ((dn_value > dm_value) || std::isnan(dm_value)) {
5451              dd_value = dn_value;
5452            } else if ((dm_value > dn_value) || std::isnan(dn_value)) {
5453              dd_value = dm_value;
5454            } else {
5455              DCHECK_EQ(dn_value, dm_value);
5456              // Make sure that we pick the most positive sign for +/-0.
5457              dd_value = std::signbit(dn_value) ? dm_value : dn_value;
5458            }
5459          }
5460          dd_value = canonicalizeNaN(dd_value);
5461          set_d_register_from_double(d, dd_value);
5462        } else {
5463          int m = instr->VFPMRegValue(kSinglePrecision);
5464          int n = instr->VFPNRegValue(kSinglePrecision);
5465          int d = instr->VFPDRegValue(kSinglePrecision);
5466          float sn_value = get_float_from_s_register(n);
5467          float sm_value = get_float_from_s_register(m);
5468          float sd_value;
5469          if (instr->Bit(6) == 0x1) {  // vminnm
5470            if ((sn_value < sm_value) || std::isnan(sm_value)) {
5471              sd_value = sn_value;
5472            } else if ((sm_value < sn_value) || std::isnan(sn_value)) {
5473              sd_value = sm_value;
5474            } else {
5475              DCHECK_EQ(sn_value, sm_value);
5476              // Make sure that we pick the most negative sign for +/-0.
5477              sd_value = std::signbit(sn_value) ? sn_value : sm_value;
5478            }
5479          } else {  // vmaxnm
5480            if ((sn_value > sm_value) || std::isnan(sm_value)) {
5481              sd_value = sn_value;
5482            } else if ((sm_value > sn_value) || std::isnan(sn_value)) {
5483              sd_value = sm_value;
5484            } else {
5485              DCHECK_EQ(sn_value, sm_value);
5486              // Make sure that we pick the most positive sign for +/-0.
5487              sd_value = std::signbit(sn_value) ? sm_value : sn_value;
5488            }
5489          }
5490          sd_value = canonicalizeNaN(sd_value);
5491          set_s_register_from_float(d, sd_value);
5492        }
5493      } else {
5494        UNIMPLEMENTED();
5495      }
5496      break;
5497    case 0x1C:
5498      if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
5499          (instr->Bit(4) == 0)) {
5500        // VSEL* (floating-point)
5501        bool condition_holds;
5502        switch (instr->Bits(21, 20)) {
5503          case 0x0:  // VSELEQ
5504            condition_holds = (z_flag_ == 1);
5505            break;
5506          case 0x1:  // VSELVS
5507            condition_holds = (v_flag_ == 1);
5508            break;
5509          case 0x2:  // VSELGE
5510            condition_holds = (n_flag_ == v_flag_);
5511            break;
5512          case 0x3:  // VSELGT
5513            condition_holds = ((z_flag_ == 0) && (n_flag_ == v_flag_));
5514            break;
5515          default:
5516            UNREACHABLE();  // Case analysis is exhaustive.
5517            break;
5518        }
5519        if (instr->SzValue() == 0x1) {
5520          int n = instr->VFPNRegValue(kDoublePrecision);
5521          int m = instr->VFPMRegValue(kDoublePrecision);
5522          int d = instr->VFPDRegValue(kDoublePrecision);
5523          double result = get_double_from_d_register(condition_holds ? n : m);
5524          set_d_register_from_double(d, result);
5525        } else {
5526          int n = instr->VFPNRegValue(kSinglePrecision);
5527          int m = instr->VFPMRegValue(kSinglePrecision);
5528          int d = instr->VFPDRegValue(kSinglePrecision);
5529          float result = get_float_from_s_register(condition_holds ? n : m);
5530          set_s_register_from_float(d, result);
5531        }
5532      } else {
5533        UNIMPLEMENTED();
5534      }
5535      break;
5536    default:
5537      UNIMPLEMENTED();
5538      break;
5539  }
5540}
5541
5542
5543// Executes the current instruction.
5544void Simulator::InstructionDecode(Instruction* instr) {
5545  if (v8::internal::FLAG_check_icache) {
5546    CheckICache(isolate_->simulator_i_cache(), instr);
5547  }
5548  pc_modified_ = false;
5549  if (::v8::internal::FLAG_trace_sim) {
5550    disasm::NameConverter converter;
5551    disasm::Disassembler dasm(converter);
5552    // use a reasonably large buffer
5553    v8::internal::EmbeddedVector<char, 256> buffer;
5554    dasm.InstructionDecode(buffer,
5555                           reinterpret_cast<byte*>(instr));
5556    PrintF("  0x%08" V8PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(instr),
5557           buffer.start());
5558  }
5559  if (instr->ConditionField() == kSpecialCondition) {
5560    DecodeSpecialCondition(instr);
5561  } else if (ConditionallyExecute(instr)) {
5562    switch (instr->TypeValue()) {
5563      case 0:
5564      case 1: {
5565        DecodeType01(instr);
5566        break;
5567      }
5568      case 2: {
5569        DecodeType2(instr);
5570        break;
5571      }
5572      case 3: {
5573        DecodeType3(instr);
5574        break;
5575      }
5576      case 4: {
5577        DecodeType4(instr);
5578        break;
5579      }
5580      case 5: {
5581        DecodeType5(instr);
5582        break;
5583      }
5584      case 6: {
5585        DecodeType6(instr);
5586        break;
5587      }
5588      case 7: {
5589        DecodeType7(instr);
5590        break;
5591      }
5592      default: {
5593        UNIMPLEMENTED();
5594        break;
5595      }
5596    }
5597  // If the instruction is a non taken conditional stop, we need to skip the
5598  // inlined message address.
5599  } else if (instr->IsStop()) {
5600    set_pc(get_pc() + 2 * Instruction::kInstrSize);
5601  }
5602  if (!pc_modified_) {
5603    set_register(pc, reinterpret_cast<int32_t>(instr)
5604                         + Instruction::kInstrSize);
5605  }
5606}
5607
5608
5609void Simulator::Execute() {
5610  // Get the PC to simulate. Cannot use the accessor here as we need the
5611  // raw PC value and not the one used as input to arithmetic instructions.
5612  int program_counter = get_pc();
5613
5614  if (::v8::internal::FLAG_stop_sim_at == 0) {
5615    // Fast version of the dispatch loop without checking whether the simulator
5616    // should be stopping at a particular executed instruction.
5617    while (program_counter != end_sim_pc) {
5618      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5619      icount_++;
5620      InstructionDecode(instr);
5621      program_counter = get_pc();
5622    }
5623  } else {
5624    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
5625    // we reach the particular instuction count.
5626    while (program_counter != end_sim_pc) {
5627      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
5628      icount_++;
5629      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
5630        ArmDebugger dbg(this);
5631        dbg.Debug();
5632      } else {
5633        InstructionDecode(instr);
5634      }
5635      program_counter = get_pc();
5636    }
5637  }
5638}
5639
5640
5641void Simulator::CallInternal(byte* entry) {
5642  // Adjust JS-based stack limit to C-based stack limit.
5643  isolate_->stack_guard()->AdjustStackLimitForSimulator();
5644
5645  // Prepare to execute the code at entry
5646  set_register(pc, reinterpret_cast<int32_t>(entry));
5647  // Put down marker for end of simulation. The simulator will stop simulation
5648  // when the PC reaches this value. By saving the "end simulation" value into
5649  // the LR the simulation stops when returning to this call point.
5650  set_register(lr, end_sim_pc);
5651
5652  // Remember the values of callee-saved registers.
5653  // The code below assumes that r9 is not used as sb (static base) in
5654  // simulator code and therefore is regarded as a callee-saved register.
5655  int32_t r4_val = get_register(r4);
5656  int32_t r5_val = get_register(r5);
5657  int32_t r6_val = get_register(r6);
5658  int32_t r7_val = get_register(r7);
5659  int32_t r8_val = get_register(r8);
5660  int32_t r9_val = get_register(r9);
5661  int32_t r10_val = get_register(r10);
5662  int32_t r11_val = get_register(r11);
5663
5664  // Set up the callee-saved registers with a known value. To be able to check
5665  // that they are preserved properly across JS execution.
5666  int32_t callee_saved_value = icount_;
5667  set_register(r4, callee_saved_value);
5668  set_register(r5, callee_saved_value);
5669  set_register(r6, callee_saved_value);
5670  set_register(r7, callee_saved_value);
5671  set_register(r8, callee_saved_value);
5672  set_register(r9, callee_saved_value);
5673  set_register(r10, callee_saved_value);
5674  set_register(r11, callee_saved_value);
5675
5676  // Start the simulation
5677  Execute();
5678
5679  // Check that the callee-saved registers have been preserved.
5680  CHECK_EQ(callee_saved_value, get_register(r4));
5681  CHECK_EQ(callee_saved_value, get_register(r5));
5682  CHECK_EQ(callee_saved_value, get_register(r6));
5683  CHECK_EQ(callee_saved_value, get_register(r7));
5684  CHECK_EQ(callee_saved_value, get_register(r8));
5685  CHECK_EQ(callee_saved_value, get_register(r9));
5686  CHECK_EQ(callee_saved_value, get_register(r10));
5687  CHECK_EQ(callee_saved_value, get_register(r11));
5688
5689  // Restore callee-saved registers with the original value.
5690  set_register(r4, r4_val);
5691  set_register(r5, r5_val);
5692  set_register(r6, r6_val);
5693  set_register(r7, r7_val);
5694  set_register(r8, r8_val);
5695  set_register(r9, r9_val);
5696  set_register(r10, r10_val);
5697  set_register(r11, r11_val);
5698}
5699
5700
5701int32_t Simulator::Call(byte* entry, int argument_count, ...) {
5702  va_list parameters;
5703  va_start(parameters, argument_count);
5704  // Set up arguments
5705
5706  // First four arguments passed in registers.
5707  DCHECK(argument_count >= 4);
5708  set_register(r0, va_arg(parameters, int32_t));
5709  set_register(r1, va_arg(parameters, int32_t));
5710  set_register(r2, va_arg(parameters, int32_t));
5711  set_register(r3, va_arg(parameters, int32_t));
5712
5713  // Remaining arguments passed on stack.
5714  int original_stack = get_register(sp);
5715  // Compute position of stack on entry to generated code.
5716  int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
5717  if (base::OS::ActivationFrameAlignment() != 0) {
5718    entry_stack &= -base::OS::ActivationFrameAlignment();
5719  }
5720  // Store remaining arguments on stack, from low to high memory.
5721  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
5722  for (int i = 4; i < argument_count; i++) {
5723    stack_argument[i - 4] = va_arg(parameters, int32_t);
5724  }
5725  va_end(parameters);
5726  set_register(sp, entry_stack);
5727
5728  CallInternal(entry);
5729
5730  // Pop stack passed arguments.
5731  CHECK_EQ(entry_stack, get_register(sp));
5732  set_register(sp, original_stack);
5733
5734  int32_t result = get_register(r0);
5735  return result;
5736}
5737
5738
5739void Simulator::CallFP(byte* entry, double d0, double d1) {
5740  if (use_eabi_hardfloat()) {
5741    set_d_register_from_double(0, d0);
5742    set_d_register_from_double(1, d1);
5743  } else {
5744    set_register_pair_from_double(0, &d0);
5745    set_register_pair_from_double(2, &d1);
5746  }
5747  CallInternal(entry);
5748}
5749
5750
5751int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
5752  CallFP(entry, d0, d1);
5753  int32_t result = get_register(r0);
5754  return result;
5755}
5756
5757
5758double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
5759  CallFP(entry, d0, d1);
5760  if (use_eabi_hardfloat()) {
5761    return get_double_from_d_register(0);
5762  } else {
5763    return get_double_from_register_pair(0);
5764  }
5765}
5766
5767
5768uintptr_t Simulator::PushAddress(uintptr_t address) {
5769  int new_sp = get_register(sp) - sizeof(uintptr_t);
5770  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
5771  *stack_slot = address;
5772  set_register(sp, new_sp);
5773  return new_sp;
5774}
5775
5776
5777uintptr_t Simulator::PopAddress() {
5778  int current_sp = get_register(sp);
5779  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
5780  uintptr_t address = *stack_slot;
5781  set_register(sp, current_sp + sizeof(uintptr_t));
5782  return address;
5783}
5784
5785Simulator::LocalMonitor::LocalMonitor()
5786    : access_state_(MonitorAccess::Open),
5787      tagged_addr_(0),
5788      size_(TransactionSize::None) {}
5789
5790void Simulator::LocalMonitor::Clear() {
5791  access_state_ = MonitorAccess::Open;
5792  tagged_addr_ = 0;
5793  size_ = TransactionSize::None;
5794}
5795
5796void Simulator::LocalMonitor::NotifyLoad(int32_t addr) {
5797  if (access_state_ == MonitorAccess::Exclusive) {
5798    // A load could cause a cache eviction which will affect the monitor. As a
5799    // result, it's most strict to unconditionally clear the local monitor on
5800    // load.
5801    Clear();
5802  }
5803}
5804
5805void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr,
5806                                             TransactionSize size) {
5807  access_state_ = MonitorAccess::Exclusive;
5808  tagged_addr_ = addr;
5809  size_ = size;
5810}
5811
5812void Simulator::LocalMonitor::NotifyStore(int32_t addr) {
5813  if (access_state_ == MonitorAccess::Exclusive) {
5814    // It is implementation-defined whether a non-exclusive store to an address
5815    // covered by the local monitor during exclusive access transitions to open
5816    // or exclusive access. See ARM DDI 0406C.b, A3.4.1.
5817    //
5818    // However, a store could cause a cache eviction which will affect the
5819    // monitor. As a result, it's most strict to unconditionally clear the
5820    // local monitor on store.
5821    Clear();
5822  }
5823}
5824
5825bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr,
5826                                              TransactionSize size) {
5827  if (access_state_ == MonitorAccess::Exclusive) {
5828    // It is allowed for a processor to require that the address matches
5829    // exactly (A3.4.5), so this comparison does not mask addr.
5830    if (addr == tagged_addr_ && size_ == size) {
5831      Clear();
5832      return true;
5833    } else {
5834      // It is implementation-defined whether an exclusive store to a
5835      // non-tagged address will update memory. Behavior is unpredictable if
5836      // the transaction size of the exclusive store differs from that of the
5837      // exclusive load. See ARM DDI 0406C.b, A3.4.5.
5838      Clear();
5839      return false;
5840    }
5841  } else {
5842    DCHECK(access_state_ == MonitorAccess::Open);
5843    return false;
5844  }
5845}
5846
5847Simulator::GlobalMonitor::Processor::Processor()
5848    : access_state_(MonitorAccess::Open),
5849      tagged_addr_(0),
5850      next_(nullptr),
5851      prev_(nullptr),
5852      failure_counter_(0) {}
5853
5854void Simulator::GlobalMonitor::Processor::Clear_Locked() {
5855  access_state_ = MonitorAccess::Open;
5856  tagged_addr_ = 0;
5857}
5858
5859void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) {
5860  access_state_ = MonitorAccess::Exclusive;
5861  tagged_addr_ = addr;
5862}
5863
5864void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
5865    int32_t addr, bool is_requesting_processor) {
5866  if (access_state_ == MonitorAccess::Exclusive) {
5867    // It is implementation-defined whether a non-exclusive store by the
5868    // requesting processor to an address covered by the global monitor
5869    // during exclusive access transitions to open or exclusive access.
5870    //
5871    // For any other processor, the access state always transitions to open
5872    // access.
5873    //
5874    // See ARM DDI 0406C.b, A3.4.2.
5875    //
5876    // However, similar to the local monitor, it is possible that a store
5877    // caused a cache eviction, which can affect the montior, so
5878    // conservatively, we always clear the monitor.
5879    Clear_Locked();
5880  }
5881}
5882
5883bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
5884    int32_t addr, bool is_requesting_processor) {
5885  if (access_state_ == MonitorAccess::Exclusive) {
5886    if (is_requesting_processor) {
5887      // It is allowed for a processor to require that the address matches
5888      // exactly (A3.4.5), so this comparison does not mask addr.
5889      if (addr == tagged_addr_) {
5890        // The access state for the requesting processor after a successful
5891        // exclusive store is implementation-defined, but according to the ARM
5892        // DDI, this has no effect on the subsequent operation of the global
5893        // monitor.
5894        Clear_Locked();
5895        // Introduce occasional strex failures. This is to simulate the
5896        // behavior of hardware, which can randomly fail due to background
5897        // cache evictions.
5898        if (failure_counter_++ >= kMaxFailureCounter) {
5899          failure_counter_ = 0;
5900          return false;
5901        } else {
5902          return true;
5903        }
5904      }
5905    } else if ((addr & kExclusiveTaggedAddrMask) ==
5906               (tagged_addr_ & kExclusiveTaggedAddrMask)) {
5907      // Check the masked addresses when responding to a successful lock by
5908      // another processor so the implementation is more conservative (i.e. the
5909      // granularity of locking is as large as possible.)
5910      Clear_Locked();
5911      return false;
5912    }
5913  }
5914  return false;
5915}
5916
5917Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
5918
5919void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr,
5920                                                     Processor* processor) {
5921  processor->NotifyLoadExcl_Locked(addr);
5922  PrependProcessor_Locked(processor);
5923}
5924
5925void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr,
5926                                                  Processor* processor) {
5927  // Notify each processor of the store operation.
5928  for (Processor* iter = head_; iter; iter = iter->next_) {
5929    bool is_requesting_processor = iter == processor;
5930    iter->NotifyStore_Locked(addr, is_requesting_processor);
5931  }
5932}
5933
5934bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr,
5935                                                      Processor* processor) {
5936  DCHECK(IsProcessorInLinkedList_Locked(processor));
5937  if (processor->NotifyStoreExcl_Locked(addr, true)) {
5938    // Notify the other processors that this StoreExcl succeeded.
5939    for (Processor* iter = head_; iter; iter = iter->next_) {
5940      if (iter != processor) {
5941        iter->NotifyStoreExcl_Locked(addr, false);
5942      }
5943    }
5944    return true;
5945  } else {
5946    return false;
5947  }
5948}
5949
5950bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
5951    Processor* processor) const {
5952  return head_ == processor || processor->next_ || processor->prev_;
5953}
5954
5955void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
5956  if (IsProcessorInLinkedList_Locked(processor)) {
5957    return;
5958  }
5959
5960  if (head_) {
5961    head_->prev_ = processor;
5962  }
5963  processor->prev_ = nullptr;
5964  processor->next_ = head_;
5965  head_ = processor;
5966}
5967
5968void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
5969  base::LockGuard<base::Mutex> lock_guard(&mutex);
5970  if (!IsProcessorInLinkedList_Locked(processor)) {
5971    return;
5972  }
5973
5974  if (processor->prev_) {
5975    processor->prev_->next_ = processor->next_;
5976  } else {
5977    head_ = processor->next_;
5978  }
5979  if (processor->next_) {
5980    processor->next_->prev_ = processor->prev_;
5981  }
5982  processor->prev_ = nullptr;
5983  processor->next_ = nullptr;
5984}
5985
5986}  // namespace internal
5987}  // namespace v8
5988
5989#endif  // USE_SIMULATOR
5990
5991#endif  // V8_TARGET_ARCH_ARM
5992