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