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