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