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