1 // Copyright 2015, ARM Limited
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include "jstypes.h"
28 
29 #ifdef JS_SIMULATOR_ARM64
30 
31 #include "jit/arm64/vixl/Simulator-vixl.h"
32 
33 #include <cmath>
34 #include <string.h>
35 
36 #include "jit/AtomicOperations.h"
37 
38 namespace vixl {
39 
40 const Instruction* Simulator::kEndOfSimAddress = NULL;
41 
SetBits(int msb,int lsb,uint32_t bits)42 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
43   int width = msb - lsb + 1;
44   VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
45 
46   bits <<= lsb;
47   uint32_t mask = ((1 << width) - 1) << lsb;
48   VIXL_ASSERT((mask & write_ignore_mask_) == 0);
49 
50   value_ = (value_ & ~mask) | (bits & mask);
51 }
52 
53 
DefaultValueFor(SystemRegister id)54 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
55   switch (id) {
56     case NZCV:
57       return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
58     case FPCR:
59       return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
60     default:
61       VIXL_UNREACHABLE();
62       return SimSystemRegister();
63   }
64 }
65 
66 
Run()67 void Simulator::Run() {
68   pc_modified_ = false;
69   while (pc_ != kEndOfSimAddress) {
70     ExecuteInstruction();
71     LogAllWrittenRegisters();
72   }
73 }
74 
75 
RunFrom(const Instruction * first)76 void Simulator::RunFrom(const Instruction* first) {
77   set_pc(first);
78   Run();
79 }
80 
81 
82 const char* Simulator::xreg_names[] = {
83 "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
84 "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
85 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
86 "x24", "x25", "x26", "x27", "x28", "x29", "lr",  "xzr", "sp"};
87 
88 const char* Simulator::wreg_names[] = {
89 "w0",  "w1",  "w2",  "w3",  "w4",  "w5",  "w6",  "w7",
90 "w8",  "w9",  "w10", "w11", "w12", "w13", "w14", "w15",
91 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
92 "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr", "wsp"};
93 
94 const char* Simulator::sreg_names[] = {
95 "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
96 "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
97 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
98 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
99 
100 const char* Simulator::dreg_names[] = {
101 "d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
102 "d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
103 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
104 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
105 
106 const char* Simulator::vreg_names[] = {
107 "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
108 "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
109 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
110 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
111 
112 
113 
WRegNameForCode(unsigned code,Reg31Mode mode)114 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
115   VIXL_ASSERT(code < kNumberOfRegisters);
116   // If the code represents the stack pointer, index the name after zr.
117   if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
118     code = kZeroRegCode + 1;
119   }
120   return wreg_names[code];
121 }
122 
123 
XRegNameForCode(unsigned code,Reg31Mode mode)124 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
125   VIXL_ASSERT(code < kNumberOfRegisters);
126   // If the code represents the stack pointer, index the name after zr.
127   if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
128     code = kZeroRegCode + 1;
129   }
130   return xreg_names[code];
131 }
132 
133 
SRegNameForCode(unsigned code)134 const char* Simulator::SRegNameForCode(unsigned code) {
135   VIXL_ASSERT(code < kNumberOfFPRegisters);
136   return sreg_names[code];
137 }
138 
139 
DRegNameForCode(unsigned code)140 const char* Simulator::DRegNameForCode(unsigned code) {
141   VIXL_ASSERT(code < kNumberOfFPRegisters);
142   return dreg_names[code];
143 }
144 
145 
VRegNameForCode(unsigned code)146 const char* Simulator::VRegNameForCode(unsigned code) {
147   VIXL_ASSERT(code < kNumberOfVRegisters);
148   return vreg_names[code];
149 }
150 
151 
152 #define COLOUR(colour_code)       "\033[0;" colour_code "m"
153 #define COLOUR_BOLD(colour_code)  "\033[1;" colour_code "m"
154 #define NORMAL  ""
155 #define GREY    "30"
156 #define RED     "31"
157 #define GREEN   "32"
158 #define YELLOW  "33"
159 #define BLUE    "34"
160 #define MAGENTA "35"
161 #define CYAN    "36"
162 #define WHITE   "37"
set_coloured_trace(bool value)163 void Simulator::set_coloured_trace(bool value) {
164   coloured_trace_ = value;
165 
166   clr_normal          = value ? COLOUR(NORMAL)        : "";
167   clr_flag_name       = value ? COLOUR_BOLD(WHITE)    : "";
168   clr_flag_value      = value ? COLOUR(NORMAL)        : "";
169   clr_reg_name        = value ? COLOUR_BOLD(CYAN)     : "";
170   clr_reg_value       = value ? COLOUR(CYAN)          : "";
171   clr_vreg_name       = value ? COLOUR_BOLD(MAGENTA)  : "";
172   clr_vreg_value      = value ? COLOUR(MAGENTA)       : "";
173   clr_memory_address  = value ? COLOUR_BOLD(BLUE)     : "";
174   clr_warning         = value ? COLOUR_BOLD(YELLOW)   : "";
175   clr_warning_message = value ? COLOUR(YELLOW)        : "";
176   clr_printf          = value ? COLOUR(GREEN)         : "";
177 }
178 #undef COLOUR
179 #undef COLOUR_BOLD
180 #undef NORMAL
181 #undef GREY
182 #undef RED
183 #undef GREEN
184 #undef YELLOW
185 #undef BLUE
186 #undef MAGENTA
187 #undef CYAN
188 #undef WHITE
189 
190 
set_trace_parameters(int parameters)191 void Simulator::set_trace_parameters(int parameters) {
192   bool disasm_before = trace_parameters_ & LOG_DISASM;
193   trace_parameters_ = parameters;
194   bool disasm_after = trace_parameters_ & LOG_DISASM;
195 
196   if (disasm_before != disasm_after) {
197     if (disasm_after) {
198       decoder_->InsertVisitorBefore(print_disasm_, this);
199     } else {
200       decoder_->RemoveVisitor(print_disasm_);
201     }
202   }
203 }
204 
205 
set_instruction_stats(bool value)206 void Simulator::set_instruction_stats(bool value) {
207   if (instrumentation_ == nullptr) {
208     return;
209   }
210 
211   if (value != instruction_stats_) {
212     if (value) {
213       decoder_->AppendVisitor(instrumentation_);
214     } else {
215       decoder_->RemoveVisitor(instrumentation_);
216     }
217     instruction_stats_ = value;
218   }
219 }
220 
221 // Helpers ---------------------------------------------------------------------
AddWithCarry(unsigned reg_size,bool set_flags,uint64_t left,uint64_t right,int carry_in)222 uint64_t Simulator::AddWithCarry(unsigned reg_size,
223                                  bool set_flags,
224                                  uint64_t left,
225                                  uint64_t right,
226                                  int carry_in) {
227   VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
228   VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
229 
230   uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
231   uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
232   uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
233 
234   left &= reg_mask;
235   right &= reg_mask;
236   uint64_t result = (left + right + carry_in) & reg_mask;
237 
238   if (set_flags) {
239     nzcv().SetN(CalcNFlag(result, reg_size));
240     nzcv().SetZ(CalcZFlag(result));
241 
242     // Compute the C flag by comparing the result to the max unsigned integer.
243     uint64_t max_uint_2op = max_uint - carry_in;
244     bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
245     nzcv().SetC(C ? 1 : 0);
246 
247     // Overflow iff the sign bit is the same for the two inputs and different
248     // for the result.
249     uint64_t left_sign = left & sign_mask;
250     uint64_t right_sign = right & sign_mask;
251     uint64_t result_sign = result & sign_mask;
252     bool V = (left_sign == right_sign) && (left_sign != result_sign);
253     nzcv().SetV(V ? 1 : 0);
254 
255     LogSystemRegister(NZCV);
256   }
257   return result;
258 }
259 
260 
ShiftOperand(unsigned reg_size,int64_t value,Shift shift_type,unsigned amount)261 int64_t Simulator::ShiftOperand(unsigned reg_size,
262                                 int64_t value,
263                                 Shift shift_type,
264                                 unsigned amount) {
265   if (amount == 0) {
266     return value;
267   }
268   int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
269   switch (shift_type) {
270     case LSL:
271       return (value << amount) & mask;
272     case LSR:
273       return static_cast<uint64_t>(value) >> amount;
274     case ASR: {
275       // Shift used to restore the sign.
276       unsigned s_shift = kXRegSize - reg_size;
277       // Value with its sign restored.
278       int64_t s_value = (value << s_shift) >> s_shift;
279       return (s_value >> amount) & mask;
280     }
281     case ROR: {
282       if (reg_size == kWRegSize) {
283         value &= kWRegMask;
284       }
285       return (static_cast<uint64_t>(value) >> amount) |
286              ((value & ((INT64_C(1) << amount) - 1)) <<
287               (reg_size - amount));
288     }
289     default:
290       VIXL_UNIMPLEMENTED();
291       return 0;
292   }
293 }
294 
295 
ExtendValue(unsigned reg_size,int64_t value,Extend extend_type,unsigned left_shift)296 int64_t Simulator::ExtendValue(unsigned reg_size,
297                                int64_t value,
298                                Extend extend_type,
299                                unsigned left_shift) {
300   switch (extend_type) {
301     case UXTB:
302       value &= kByteMask;
303       break;
304     case UXTH:
305       value &= kHalfWordMask;
306       break;
307     case UXTW:
308       value &= kWordMask;
309       break;
310     case SXTB:
311       value = (value << 56) >> 56;
312       break;
313     case SXTH:
314       value = (value << 48) >> 48;
315       break;
316     case SXTW:
317       value = (value << 32) >> 32;
318       break;
319     case UXTX:
320     case SXTX:
321       break;
322     default:
323       VIXL_UNREACHABLE();
324   }
325   int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
326   return (value << left_shift) & mask;
327 }
328 
329 
FPCompare(double val0,double val1,FPTrapFlags trap)330 void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
331   AssertSupportedFPCR();
332 
333   // TODO: This assumes that the C++ implementation handles comparisons in the
334   // way that we expect (as per AssertSupportedFPCR()).
335   bool process_exception = false;
336   if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
337     nzcv().SetRawValue(FPUnorderedFlag);
338     if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
339         (trap == EnableTrap)) {
340       process_exception = true;
341     }
342   } else if (val0 < val1) {
343     nzcv().SetRawValue(FPLessThanFlag);
344   } else if (val0 > val1) {
345     nzcv().SetRawValue(FPGreaterThanFlag);
346   } else if (val0 == val1) {
347     nzcv().SetRawValue(FPEqualFlag);
348   } else {
349     VIXL_UNREACHABLE();
350   }
351   LogSystemRegister(NZCV);
352   if (process_exception) FPProcessException();
353 }
354 
355 
GetPrintRegisterFormatForSize(unsigned reg_size,unsigned lane_size)356 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
357     unsigned reg_size, unsigned lane_size) {
358   VIXL_ASSERT(reg_size >= lane_size);
359 
360   uint32_t format = 0;
361   if (reg_size != lane_size) {
362     switch (reg_size) {
363       default: VIXL_UNREACHABLE(); break;
364       case kQRegSizeInBytes: format = kPrintRegAsQVector; break;
365       case kDRegSizeInBytes: format = kPrintRegAsDVector; break;
366     }
367   }
368 
369   switch (lane_size) {
370     default: VIXL_UNREACHABLE(); break;
371     case kQRegSizeInBytes: format |= kPrintReg1Q; break;
372     case kDRegSizeInBytes: format |= kPrintReg1D; break;
373     case kSRegSizeInBytes: format |= kPrintReg1S; break;
374     case kHRegSizeInBytes: format |= kPrintReg1H; break;
375     case kBRegSizeInBytes: format |= kPrintReg1B; break;
376   }
377   // These sizes would be duplicate case labels.
378   VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
379   VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
380   VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
381   VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
382 
383   return static_cast<PrintRegisterFormat>(format);
384 }
385 
386 
GetPrintRegisterFormat(VectorFormat vform)387 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
388     VectorFormat vform) {
389   switch (vform) {
390     default: VIXL_UNREACHABLE(); return kPrintReg16B;
391     case kFormat16B: return kPrintReg16B;
392     case kFormat8B: return kPrintReg8B;
393     case kFormat8H: return kPrintReg8H;
394     case kFormat4H: return kPrintReg4H;
395     case kFormat4S: return kPrintReg4S;
396     case kFormat2S: return kPrintReg2S;
397     case kFormat2D: return kPrintReg2D;
398     case kFormat1D: return kPrintReg1D;
399   }
400 }
401 
402 
PrintWrittenRegisters()403 void Simulator::PrintWrittenRegisters() {
404   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
405     if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
406   }
407 }
408 
409 
PrintWrittenVRegisters()410 void Simulator::PrintWrittenVRegisters() {
411   for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
412     // At this point there is no type information, so print as a raw 1Q.
413     if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
414   }
415 }
416 
417 
PrintSystemRegisters()418 void Simulator::PrintSystemRegisters() {
419   PrintSystemRegister(NZCV);
420   PrintSystemRegister(FPCR);
421 }
422 
423 
PrintRegisters()424 void Simulator::PrintRegisters() {
425   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
426     PrintRegister(i);
427   }
428 }
429 
430 
PrintVRegisters()431 void Simulator::PrintVRegisters() {
432   for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
433     // At this point there is no type information, so print as a raw 1Q.
434     PrintVRegister(i, kPrintReg1Q);
435   }
436 }
437 
438 
439 // Print a register's name and raw value.
440 //
441 // Only the least-significant `size_in_bytes` bytes of the register are printed,
442 // but the value is aligned as if the whole register had been printed.
443 //
444 // For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
445 // -- the default -- so that the whole register is printed. Other values of
446 // size_in_bytes are intended for use when the register hasn't actually been
447 // updated (such as in PrintWrite).
448 //
449 // No newline is printed. This allows the caller to print more details (such as
450 // a memory access annotation).
PrintRegisterRawHelper(unsigned code,Reg31Mode r31mode,int size_in_bytes)451 void Simulator::PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
452                                        int size_in_bytes) {
453   // The template for all supported sizes.
454   //   "# x{code}: 0xffeeddccbbaa9988"
455   //   "# w{code}:         0xbbaa9988"
456   //   "# w{code}<15:0>:       0x9988"
457   //   "# w{code}<7:0>:          0x88"
458   unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
459 
460   const char * name = "";
461   const char * suffix = "";
462   switch (size_in_bytes) {
463     case kXRegSizeInBytes: name = XRegNameForCode(code, r31mode); break;
464     case kWRegSizeInBytes: name = WRegNameForCode(code, r31mode); break;
465     case 2:
466       name = WRegNameForCode(code, r31mode);
467       suffix = "<15:0>";
468       padding_chars -= strlen(suffix);
469       break;
470     case 1:
471       name = WRegNameForCode(code, r31mode);
472       suffix = "<7:0>";
473       padding_chars -= strlen(suffix);
474       break;
475     default:
476       VIXL_UNREACHABLE();
477   }
478   fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
479 
480   // Print leading padding spaces.
481   VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
482   for (unsigned i = 0; i < padding_chars; i++) {
483     putc(' ', stream_);
484   }
485 
486   // Print the specified bits in hexadecimal format.
487   uint64_t bits = reg<uint64_t>(code, r31mode);
488   bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
489   VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
490 
491   int chars = size_in_bytes * 2;
492   fprintf(stream_, "%s0x%0*" PRIx64 "%s",
493           clr_reg_value, chars, bits, clr_normal);
494 }
495 
496 
PrintRegister(unsigned code,Reg31Mode r31mode)497 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
498   registers_[code].NotifyRegisterLogged();
499 
500   // Don't print writes into xzr.
501   if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
502     return;
503   }
504 
505   // The template for all x and w registers:
506   //   "# x{code}: 0x{value}"
507   //   "# w{code}: 0x{value}"
508 
509   PrintRegisterRawHelper(code, r31mode);
510   fprintf(stream_, "\n");
511 }
512 
513 
514 // Print a register's name and raw value.
515 //
516 // The `bytes` and `lsb` arguments can be used to limit the bytes that are
517 // printed. These arguments are intended for use in cases where register hasn't
518 // actually been updated (such as in PrintVWrite).
519 //
520 // No newline is printed. This allows the caller to print more details (such as
521 // a floating-point interpretation or a memory access annotation).
PrintVRegisterRawHelper(unsigned code,int bytes,int lsb)522 void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
523   // The template for vector types:
524   //   "# v{code}: 0xffeeddccbbaa99887766554433221100".
525   // An example with bytes=4 and lsb=8:
526   //   "# v{code}:         0xbbaa9988                ".
527   fprintf(stream_, "# %s%5s: %s",
528           clr_vreg_name, VRegNameForCode(code), clr_vreg_value);
529 
530   int msb = lsb + bytes - 1;
531   int byte = kQRegSizeInBytes - 1;
532 
533   // Print leading padding spaces. (Two spaces per byte.)
534   while (byte > msb) {
535     fprintf(stream_, "  ");
536     byte--;
537   }
538 
539   // Print the specified part of the value, byte by byte.
540   qreg_t rawbits = qreg(code);
541   fprintf(stream_, "0x");
542   while (byte >= lsb) {
543     fprintf(stream_, "%02x", rawbits.val[byte]);
544     byte--;
545   }
546 
547   // Print trailing padding spaces.
548   while (byte >= 0) {
549     fprintf(stream_, "  ");
550     byte--;
551   }
552   fprintf(stream_, "%s", clr_normal);
553 }
554 
555 
556 // Print each of the specified lanes of a register as a float or double value.
557 //
558 // The `lane_count` and `lslane` arguments can be used to limit the lanes that
559 // are printed. These arguments are intended for use in cases where register
560 // hasn't actually been updated (such as in PrintVWrite).
561 //
562 // No newline is printed. This allows the caller to print more details (such as
563 // a memory access annotation).
PrintVRegisterFPHelper(unsigned code,unsigned lane_size_in_bytes,int lane_count,int rightmost_lane)564 void Simulator::PrintVRegisterFPHelper(unsigned code,
565                                        unsigned lane_size_in_bytes,
566                                        int lane_count,
567                                        int rightmost_lane) {
568   VIXL_ASSERT((lane_size_in_bytes == kSRegSizeInBytes) ||
569               (lane_size_in_bytes == kDRegSizeInBytes));
570 
571   unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
572   VIXL_ASSERT(msb <= kQRegSizeInBytes);
573 
574   // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
575   // name is used:
576   //   " (s{code}: {value})"
577   //   " (d{code}: {value})"
578   // For vector types, "..." is used to represent one or more omitted lanes.
579   //   " (..., {value}, {value}, ...)"
580   if ((lane_count == 1) && (rightmost_lane == 0)) {
581     const char * name =
582         (lane_size_in_bytes == kSRegSizeInBytes) ? SRegNameForCode(code)
583                                                  : DRegNameForCode(code);
584     fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
585   } else {
586     if (msb < (kQRegSizeInBytes - 1)) {
587       fprintf(stream_, " (..., ");
588     } else {
589       fprintf(stream_, " (");
590     }
591   }
592 
593   // Print the list of values.
594   const char * separator = "";
595   int leftmost_lane = rightmost_lane + lane_count - 1;
596   for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
597     double value =
598         (lane_size_in_bytes == kSRegSizeInBytes) ? vreg(code).Get<float>(lane)
599                                                  : vreg(code).Get<double>(lane);
600     fprintf(stream_, "%s%s%#g%s", separator, clr_vreg_value, value, clr_normal);
601     separator = ", ";
602   }
603 
604   if (rightmost_lane > 0) {
605     fprintf(stream_, ", ...");
606   }
607   fprintf(stream_, ")");
608 }
609 
610 
PrintVRegister(unsigned code,PrintRegisterFormat format)611 void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
612   vregisters_[code].NotifyRegisterLogged();
613 
614   int lane_size_log2 = format & kPrintRegLaneSizeMask;
615 
616   int reg_size_log2;
617   if (format & kPrintRegAsQVector) {
618     reg_size_log2 = kQRegSizeInBytesLog2;
619   } else if (format & kPrintRegAsDVector) {
620     reg_size_log2 = kDRegSizeInBytesLog2;
621   } else {
622     // Scalar types.
623     reg_size_log2 = lane_size_log2;
624   }
625 
626   int lane_count = 1 << (reg_size_log2 - lane_size_log2);
627   int lane_size = 1 << lane_size_log2;
628 
629   // The template for vector types:
630   //   "# v{code}: 0x{rawbits} (..., {value}, ...)".
631   // The template for scalar types:
632   //   "# v{code}: 0x{rawbits} ({reg}:{value})".
633   // The values in parentheses after the bit representations are floating-point
634   // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
635 
636   PrintVRegisterRawHelper(code);
637   if (format & kPrintRegAsFP) {
638     PrintVRegisterFPHelper(code, lane_size, lane_count);
639   }
640 
641   fprintf(stream_, "\n");
642 }
643 
644 
PrintSystemRegister(SystemRegister id)645 void Simulator::PrintSystemRegister(SystemRegister id) {
646   switch (id) {
647     case NZCV:
648       fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
649               clr_flag_name, clr_flag_value,
650               nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
651               clr_normal);
652       break;
653     case FPCR: {
654       static const char * rmode[] = {
655         "0b00 (Round to Nearest)",
656         "0b01 (Round towards Plus Infinity)",
657         "0b10 (Round towards Minus Infinity)",
658         "0b11 (Round towards Zero)"
659       };
660       VIXL_ASSERT(fpcr().RMode() < (sizeof(rmode) / sizeof(rmode[0])));
661       fprintf(stream_,
662               "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
663               clr_flag_name, clr_flag_value,
664               fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
665               clr_normal);
666       break;
667     }
668     default:
669       VIXL_UNREACHABLE();
670   }
671 }
672 
673 
PrintRead(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)674 void Simulator::PrintRead(uintptr_t address,
675                           unsigned reg_code,
676                           PrintRegisterFormat format) {
677   registers_[reg_code].NotifyRegisterLogged();
678 
679   USE(format);
680 
681   // The template is "# {reg}: 0x{value} <- {address}".
682   PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
683   fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
684           clr_memory_address, address, clr_normal);
685 }
686 
687 
PrintVRead(uintptr_t address,unsigned reg_code,PrintRegisterFormat format,unsigned lane)688 void Simulator::PrintVRead(uintptr_t address,
689                            unsigned reg_code,
690                            PrintRegisterFormat format,
691                            unsigned lane) {
692   vregisters_[reg_code].NotifyRegisterLogged();
693 
694   // The template is "# v{code}: 0x{rawbits} <- address".
695   PrintVRegisterRawHelper(reg_code);
696   if (format & kPrintRegAsFP) {
697     PrintVRegisterFPHelper(reg_code, GetPrintRegLaneSizeInBytes(format),
698                            GetPrintRegLaneCount(format), lane);
699   }
700   fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
701           clr_memory_address, address, clr_normal);
702 }
703 
704 
PrintWrite(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)705 void Simulator::PrintWrite(uintptr_t address,
706                            unsigned reg_code,
707                            PrintRegisterFormat format) {
708   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
709 
710   // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
711   // and readable, the value is aligned with the values in the register trace.
712   PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister,
713                          GetPrintRegSizeInBytes(format));
714   fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
715           clr_memory_address, address, clr_normal);
716 }
717 
718 
PrintVWrite(uintptr_t address,unsigned reg_code,PrintRegisterFormat format,unsigned lane)719 void Simulator::PrintVWrite(uintptr_t address,
720                             unsigned reg_code,
721                             PrintRegisterFormat format,
722                             unsigned lane) {
723   // The templates:
724   //   "# v{code}: 0x{rawbits} -> {address}"
725   //   "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
726   //   "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
727   // Because this trace doesn't represent a change to the source register's
728   // value, only the relevant part of the value is printed. To keep the trace
729   // tidy and readable, the raw value is aligned with the other values in the
730   // register trace.
731   int lane_count = GetPrintRegLaneCount(format);
732   int lane_size = GetPrintRegLaneSizeInBytes(format);
733   int reg_size = GetPrintRegSizeInBytes(format);
734   PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
735   if (format & kPrintRegAsFP) {
736     PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
737   }
738   fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
739           clr_memory_address, address, clr_normal);
740 }
741 
742 
743 // Visitors---------------------------------------------------------------------
744 
VisitUnimplemented(const Instruction * instr)745 void Simulator::VisitUnimplemented(const Instruction* instr) {
746   printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
747          reinterpret_cast<const void*>(instr), instr->InstructionBits());
748   VIXL_UNIMPLEMENTED();
749 }
750 
751 
VisitUnallocated(const Instruction * instr)752 void Simulator::VisitUnallocated(const Instruction* instr) {
753   printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
754          reinterpret_cast<const void*>(instr), instr->InstructionBits());
755   VIXL_UNIMPLEMENTED();
756 }
757 
758 
VisitPCRelAddressing(const Instruction * instr)759 void Simulator::VisitPCRelAddressing(const Instruction* instr) {
760   VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
761               (instr->Mask(PCRelAddressingMask) == ADRP));
762 
763   set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
764 }
765 
766 
VisitUnconditionalBranch(const Instruction * instr)767 void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
768   switch (instr->Mask(UnconditionalBranchMask)) {
769     case BL:
770       set_lr(instr->NextInstruction());
771       VIXL_FALLTHROUGH();
772     case B:
773       set_pc(instr->ImmPCOffsetTarget());
774       break;
775     default: VIXL_UNREACHABLE();
776   }
777 }
778 
779 
VisitConditionalBranch(const Instruction * instr)780 void Simulator::VisitConditionalBranch(const Instruction* instr) {
781   VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
782   if (ConditionPassed(instr->ConditionBranch())) {
783     set_pc(instr->ImmPCOffsetTarget());
784   }
785 }
786 
787 
VisitUnconditionalBranchToRegister(const Instruction * instr)788 void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
789   const Instruction* target = Instruction::Cast(xreg(instr->Rn()));
790 
791   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
792     case BLR:
793       set_lr(instr->NextInstruction());
794       VIXL_FALLTHROUGH();
795     case BR:
796     case RET: set_pc(target); break;
797     default: VIXL_UNREACHABLE();
798   }
799 }
800 
801 
VisitTestBranch(const Instruction * instr)802 void Simulator::VisitTestBranch(const Instruction* instr) {
803   unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
804                      instr->ImmTestBranchBit40();
805   bool bit_zero = ((xreg(instr->Rt()) >> bit_pos) & 1) == 0;
806   bool take_branch = false;
807   switch (instr->Mask(TestBranchMask)) {
808     case TBZ: take_branch = bit_zero; break;
809     case TBNZ: take_branch = !bit_zero; break;
810     default: VIXL_UNIMPLEMENTED();
811   }
812   if (take_branch) {
813     set_pc(instr->ImmPCOffsetTarget());
814   }
815 }
816 
817 
VisitCompareBranch(const Instruction * instr)818 void Simulator::VisitCompareBranch(const Instruction* instr) {
819   unsigned rt = instr->Rt();
820   bool take_branch = false;
821   switch (instr->Mask(CompareBranchMask)) {
822     case CBZ_w: take_branch = (wreg(rt) == 0); break;
823     case CBZ_x: take_branch = (xreg(rt) == 0); break;
824     case CBNZ_w: take_branch = (wreg(rt) != 0); break;
825     case CBNZ_x: take_branch = (xreg(rt) != 0); break;
826     default: VIXL_UNIMPLEMENTED();
827   }
828   if (take_branch) {
829     set_pc(instr->ImmPCOffsetTarget());
830   }
831 }
832 
833 
AddSubHelper(const Instruction * instr,int64_t op2)834 void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
835   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
836   bool set_flags = instr->FlagsUpdate();
837   int64_t new_val = 0;
838   Instr operation = instr->Mask(AddSubOpMask);
839 
840   switch (operation) {
841     case ADD:
842     case ADDS: {
843       new_val = AddWithCarry(reg_size,
844                              set_flags,
845                              reg(reg_size, instr->Rn(), instr->RnMode()),
846                              op2);
847       break;
848     }
849     case SUB:
850     case SUBS: {
851       new_val = AddWithCarry(reg_size,
852                              set_flags,
853                              reg(reg_size, instr->Rn(), instr->RnMode()),
854                              ~op2,
855                              1);
856       break;
857     }
858     default: VIXL_UNREACHABLE();
859   }
860 
861   set_reg(reg_size, instr->Rd(), new_val, LogRegWrites, instr->RdMode());
862 }
863 
864 
VisitAddSubShifted(const Instruction * instr)865 void Simulator::VisitAddSubShifted(const Instruction* instr) {
866   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
867   int64_t op2 = ShiftOperand(reg_size,
868                              reg(reg_size, instr->Rm()),
869                              static_cast<Shift>(instr->ShiftDP()),
870                              instr->ImmDPShift());
871   AddSubHelper(instr, op2);
872 }
873 
874 
VisitAddSubImmediate(const Instruction * instr)875 void Simulator::VisitAddSubImmediate(const Instruction* instr) {
876   int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
877   AddSubHelper(instr, op2);
878 }
879 
880 
VisitAddSubExtended(const Instruction * instr)881 void Simulator::VisitAddSubExtended(const Instruction* instr) {
882   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
883   int64_t op2 = ExtendValue(reg_size,
884                             reg(reg_size, instr->Rm()),
885                             static_cast<Extend>(instr->ExtendMode()),
886                             instr->ImmExtendShift());
887   AddSubHelper(instr, op2);
888 }
889 
890 
VisitAddSubWithCarry(const Instruction * instr)891 void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
892   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
893   int64_t op2 = reg(reg_size, instr->Rm());
894   int64_t new_val;
895 
896   if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
897     op2 = ~op2;
898   }
899 
900   new_val = AddWithCarry(reg_size,
901                          instr->FlagsUpdate(),
902                          reg(reg_size, instr->Rn()),
903                          op2,
904                          C());
905 
906   set_reg(reg_size, instr->Rd(), new_val);
907 }
908 
909 
VisitLogicalShifted(const Instruction * instr)910 void Simulator::VisitLogicalShifted(const Instruction* instr) {
911   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
912   Shift shift_type = static_cast<Shift>(instr->ShiftDP());
913   unsigned shift_amount = instr->ImmDPShift();
914   int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
915                              shift_amount);
916   if (instr->Mask(NOT) == NOT) {
917     op2 = ~op2;
918   }
919   LogicalHelper(instr, op2);
920 }
921 
922 
VisitLogicalImmediate(const Instruction * instr)923 void Simulator::VisitLogicalImmediate(const Instruction* instr) {
924   LogicalHelper(instr, instr->ImmLogical());
925 }
926 
927 
LogicalHelper(const Instruction * instr,int64_t op2)928 void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
929   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
930   int64_t op1 = reg(reg_size, instr->Rn());
931   int64_t result = 0;
932   bool update_flags = false;
933 
934   // Switch on the logical operation, stripping out the NOT bit, as it has a
935   // different meaning for logical immediate instructions.
936   switch (instr->Mask(LogicalOpMask & ~NOT)) {
937     case ANDS: update_flags = true; VIXL_FALLTHROUGH();
938     case AND: result = op1 & op2; break;
939     case ORR: result = op1 | op2; break;
940     case EOR: result = op1 ^ op2; break;
941     default:
942       VIXL_UNIMPLEMENTED();
943   }
944 
945   if (update_flags) {
946     nzcv().SetN(CalcNFlag(result, reg_size));
947     nzcv().SetZ(CalcZFlag(result));
948     nzcv().SetC(0);
949     nzcv().SetV(0);
950     LogSystemRegister(NZCV);
951   }
952 
953   set_reg(reg_size, instr->Rd(), result, LogRegWrites, instr->RdMode());
954 }
955 
956 
VisitConditionalCompareRegister(const Instruction * instr)957 void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
958   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
959   ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
960 }
961 
962 
VisitConditionalCompareImmediate(const Instruction * instr)963 void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
964   ConditionalCompareHelper(instr, instr->ImmCondCmp());
965 }
966 
967 
ConditionalCompareHelper(const Instruction * instr,int64_t op2)968 void Simulator::ConditionalCompareHelper(const Instruction* instr,
969                                          int64_t op2) {
970   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
971   int64_t op1 = reg(reg_size, instr->Rn());
972 
973   if (ConditionPassed(instr->Condition())) {
974     // If the condition passes, set the status flags to the result of comparing
975     // the operands.
976     if (instr->Mask(ConditionalCompareMask) == CCMP) {
977       AddWithCarry(reg_size, true, op1, ~op2, 1);
978     } else {
979       VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
980       AddWithCarry(reg_size, true, op1, op2, 0);
981     }
982   } else {
983     // If the condition fails, set the status flags to the nzcv immediate.
984     nzcv().SetFlags(instr->Nzcv());
985     LogSystemRegister(NZCV);
986   }
987 }
988 
989 
VisitLoadStoreUnsignedOffset(const Instruction * instr)990 void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
991   int offset = instr->ImmLSUnsigned() << instr->SizeLS();
992   LoadStoreHelper(instr, offset, Offset);
993 }
994 
995 
VisitLoadStoreUnscaledOffset(const Instruction * instr)996 void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
997   LoadStoreHelper(instr, instr->ImmLS(), Offset);
998 }
999 
1000 
VisitLoadStorePreIndex(const Instruction * instr)1001 void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1002   LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1003 }
1004 
1005 
VisitLoadStorePostIndex(const Instruction * instr)1006 void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1007   LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1008 }
1009 
1010 
VisitLoadStoreRegisterOffset(const Instruction * instr)1011 void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
1012   Extend ext = static_cast<Extend>(instr->ExtendMode());
1013   VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1014   unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1015 
1016   int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
1017                                shift_amount);
1018   LoadStoreHelper(instr, offset, Offset);
1019 }
1020 
1021 template<typename T>
Faulted()1022 static T Faulted() {
1023     return ~0;
1024 }
1025 
1026 template<>
Faulted()1027 Simulator::qreg_t Faulted() {
1028     static_assert(kQRegSizeInBytes == 16, "Known constraint");
1029     static Simulator::qreg_t dummy = { {
1030 	255, 255, 255, 255, 255, 255, 255, 255,
1031 	255, 255, 255, 255, 255, 255, 255, 255
1032     } };
1033     return dummy;
1034 }
1035 
1036 template<typename T> T
Read(uintptr_t address)1037 Simulator::Read(uintptr_t address)
1038 {
1039     address = Memory::AddressUntag(address);
1040     if (handle_wasm_seg_fault(address, sizeof(T)))
1041 	return Faulted<T>();
1042     return Memory::Read<T>(address);
1043 }
1044 
1045 template <typename T> void
Write(uintptr_t address,T value)1046 Simulator::Write(uintptr_t address, T value)
1047 {
1048     address = Memory::AddressUntag(address);
1049     if (handle_wasm_seg_fault(address, sizeof(T)))
1050 	return;
1051     Memory::Write<T>(address, value);
1052 }
1053 
LoadStoreHelper(const Instruction * instr,int64_t offset,AddrMode addrmode)1054 void Simulator::LoadStoreHelper(const Instruction* instr,
1055                                 int64_t offset,
1056                                 AddrMode addrmode) {
1057   unsigned srcdst = instr->Rt();
1058   uintptr_t address = AddressModeHelper(instr->Rn(), offset, addrmode);
1059 
1060   LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
1061   switch (op) {
1062     case LDRB_w:
1063       set_wreg(srcdst, Read<uint8_t>(address), NoRegLog); break;
1064     case LDRH_w:
1065       set_wreg(srcdst, Read<uint16_t>(address), NoRegLog); break;
1066     case LDR_w:
1067       set_wreg(srcdst, Read<uint32_t>(address), NoRegLog); break;
1068     case LDR_x:
1069       set_xreg(srcdst, Read<uint64_t>(address), NoRegLog); break;
1070     case LDRSB_w:
1071       set_wreg(srcdst, Read<int8_t>(address), NoRegLog); break;
1072     case LDRSH_w:
1073       set_wreg(srcdst, Read<int16_t>(address), NoRegLog); break;
1074     case LDRSB_x:
1075       set_xreg(srcdst, Read<int8_t>(address), NoRegLog); break;
1076     case LDRSH_x:
1077       set_xreg(srcdst, Read<int16_t>(address), NoRegLog); break;
1078     case LDRSW_x:
1079       set_xreg(srcdst, Read<int32_t>(address), NoRegLog); break;
1080     case LDR_b:
1081       set_breg(srcdst, Read<uint8_t>(address), NoRegLog); break;
1082     case LDR_h:
1083       set_hreg(srcdst, Read<uint16_t>(address), NoRegLog); break;
1084     case LDR_s:
1085       set_sreg(srcdst, Read<float>(address), NoRegLog); break;
1086     case LDR_d:
1087       set_dreg(srcdst, Read<double>(address), NoRegLog); break;
1088     case LDR_q:
1089       set_qreg(srcdst, Read<qreg_t>(address), NoRegLog); break;
1090 
1091     case STRB_w:  Write<uint8_t>(address, wreg(srcdst)); break;
1092     case STRH_w:  Write<uint16_t>(address, wreg(srcdst)); break;
1093     case STR_w:   Write<uint32_t>(address, wreg(srcdst)); break;
1094     case STR_x:   Write<uint64_t>(address, xreg(srcdst)); break;
1095     case STR_b:   Write<uint8_t>(address, breg(srcdst)); break;
1096     case STR_h:   Write<uint16_t>(address, hreg(srcdst)); break;
1097     case STR_s:   Write<float>(address, sreg(srcdst)); break;
1098     case STR_d:   Write<double>(address, dreg(srcdst)); break;
1099     case STR_q:   Write<qreg_t>(address, qreg(srcdst)); break;
1100 
1101     // Ignore prfm hint instructions.
1102     case PRFM: break;
1103 
1104     default: VIXL_UNIMPLEMENTED();
1105   }
1106 
1107   unsigned access_size = 1 << instr->SizeLS();
1108   if (instr->IsLoad()) {
1109     if ((op == LDR_s) || (op == LDR_d)) {
1110       LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1111     } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1112       LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1113     } else {
1114       LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1115     }
1116   } else {
1117     if ((op == STR_s) || (op == STR_d)) {
1118       LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1119     } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1120       LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1121     } else {
1122       LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1123     }
1124   }
1125 
1126   local_monitor_.MaybeClear();
1127 }
1128 
1129 
VisitLoadStorePairOffset(const Instruction * instr)1130 void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
1131   LoadStorePairHelper(instr, Offset);
1132 }
1133 
1134 
VisitLoadStorePairPreIndex(const Instruction * instr)1135 void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
1136   LoadStorePairHelper(instr, PreIndex);
1137 }
1138 
1139 
VisitLoadStorePairPostIndex(const Instruction * instr)1140 void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
1141   LoadStorePairHelper(instr, PostIndex);
1142 }
1143 
1144 
VisitLoadStorePairNonTemporal(const Instruction * instr)1145 void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
1146   LoadStorePairHelper(instr, Offset);
1147 }
1148 
1149 
LoadStorePairHelper(const Instruction * instr,AddrMode addrmode)1150 void Simulator::LoadStorePairHelper(const Instruction* instr,
1151                                     AddrMode addrmode) {
1152   unsigned rt = instr->Rt();
1153   unsigned rt2 = instr->Rt2();
1154   int element_size = 1 << instr->SizeLSPair();
1155   int64_t offset = instr->ImmLSPair() * element_size;
1156   uintptr_t address = AddressModeHelper(instr->Rn(), offset, addrmode);
1157   uintptr_t address2 = address + element_size;
1158 
1159   LoadStorePairOp op =
1160     static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1161 
1162   // 'rt' and 'rt2' can only be aliased for stores.
1163   VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1164 
1165   switch (op) {
1166     // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
1167     // will print a more detailed log.
1168     case LDP_w: {
1169       set_wreg(rt, Read<uint32_t>(address), NoRegLog);
1170       set_wreg(rt2, Read<uint32_t>(address2), NoRegLog);
1171       break;
1172     }
1173     case LDP_s: {
1174       set_sreg(rt, Read<float>(address), NoRegLog);
1175       set_sreg(rt2, Read<float>(address2), NoRegLog);
1176       break;
1177     }
1178     case LDP_x: {
1179       set_xreg(rt, Read<uint64_t>(address), NoRegLog);
1180       set_xreg(rt2, Read<uint64_t>(address2), NoRegLog);
1181       break;
1182     }
1183     case LDP_d: {
1184       set_dreg(rt, Read<double>(address), NoRegLog);
1185       set_dreg(rt2, Read<double>(address2), NoRegLog);
1186       break;
1187     }
1188     case LDP_q: {
1189       set_qreg(rt, Read<qreg_t>(address), NoRegLog);
1190       set_qreg(rt2, Read<qreg_t>(address2), NoRegLog);
1191       break;
1192     }
1193     case LDPSW_x: {
1194       set_xreg(rt, Read<int32_t>(address), NoRegLog);
1195       set_xreg(rt2, Read<int32_t>(address2), NoRegLog);
1196       break;
1197     }
1198     case STP_w: {
1199       Write<uint32_t>(address, wreg(rt));
1200       Write<uint32_t>(address2, wreg(rt2));
1201       break;
1202     }
1203     case STP_s: {
1204       Write<float>(address, sreg(rt));
1205       Write<float>(address2, sreg(rt2));
1206       break;
1207     }
1208     case STP_x: {
1209       Write<uint64_t>(address, xreg(rt));
1210       Write<uint64_t>(address2, xreg(rt2));
1211       break;
1212     }
1213     case STP_d: {
1214       Write<double>(address, dreg(rt));
1215       Write<double>(address2, dreg(rt2));
1216       break;
1217     }
1218     case STP_q: {
1219       Write<qreg_t>(address, qreg(rt));
1220       Write<qreg_t>(address2, qreg(rt2));
1221       break;
1222     }
1223     default: VIXL_UNREACHABLE();
1224   }
1225 
1226   // Print a detailed trace (including the memory address) instead of the basic
1227   // register:value trace generated by set_*reg().
1228   if (instr->IsLoad()) {
1229     if ((op == LDP_s) || (op == LDP_d)) {
1230       LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1231       LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1232     } else if (op == LDP_q) {
1233       LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1234       LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1235     } else {
1236       LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1237       LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1238     }
1239   } else {
1240     if ((op == STP_s) || (op == STP_d)) {
1241       LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1242       LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1243     } else if (op == STP_q) {
1244       LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1245       LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1246     } else {
1247       LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1248       LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1249     }
1250   }
1251 
1252   local_monitor_.MaybeClear();
1253 }
1254 
1255 
PrintExclusiveAccessWarning()1256 void Simulator::PrintExclusiveAccessWarning() {
1257   if (print_exclusive_access_warning_) {
1258     fprintf(
1259         stderr,
1260         "%sWARNING:%s VIXL simulator support for load-/store-/clear-exclusive "
1261         "instructions is limited. Refer to the README for details.%s\n",
1262         clr_warning, clr_warning_message, clr_normal);
1263     print_exclusive_access_warning_ = false;
1264   }
1265 }
1266 
1267 
VisitLoadStoreExclusive(const Instruction * instr)1268 void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
1269   PrintExclusiveAccessWarning();
1270 
1271   unsigned rs = instr->Rs();
1272   unsigned rt = instr->Rt();
1273   unsigned rt2 = instr->Rt2();
1274   unsigned rn = instr->Rn();
1275 
1276   LoadStoreExclusive op =
1277       static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
1278 
1279   bool is_acquire_release = instr->LdStXAcquireRelease();
1280   bool is_exclusive = !instr->LdStXNotExclusive();
1281   bool is_load = instr->LdStXLoad();
1282   bool is_pair = instr->LdStXPair();
1283 
1284   unsigned element_size = 1 << instr->LdStXSizeLog2();
1285   unsigned access_size = is_pair ? element_size * 2 : element_size;
1286   uint64_t address = reg<uint64_t>(rn, Reg31IsStackPointer);
1287 
1288   // Verify that the address is available to the host.
1289   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1290 
1291   // Check the alignment of `address`.
1292   if (AlignDown(address, access_size) != address) {
1293     VIXL_ALIGNMENT_EXCEPTION();
1294   }
1295 
1296   // The sp must be aligned to 16 bytes when it is accessed.
1297   if ((rn == 31) && (AlignDown(address, 16) != address)) {
1298     VIXL_ALIGNMENT_EXCEPTION();
1299   }
1300 
1301   if (is_load) {
1302     if (is_exclusive) {
1303       local_monitor_.MarkExclusive(address, access_size);
1304     } else {
1305       // Any non-exclusive load can clear the local monitor as a side effect. We
1306       // don't need to do this, but it is useful to stress the simulated code.
1307       local_monitor_.Clear();
1308     }
1309 
1310     // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
1311     // will print a more detailed log.
1312     switch (op) {
1313       case LDXRB_w:
1314       case LDAXRB_w:
1315       case LDARB_w:
1316         set_wreg(rt, Read<uint8_t>(address), NoRegLog);
1317         break;
1318       case LDXRH_w:
1319       case LDAXRH_w:
1320       case LDARH_w:
1321         set_wreg(rt, Read<uint16_t>(address), NoRegLog);
1322         break;
1323       case LDXR_w:
1324       case LDAXR_w:
1325       case LDAR_w:
1326         set_wreg(rt, Read<uint32_t>(address), NoRegLog);
1327         break;
1328       case LDXR_x:
1329       case LDAXR_x:
1330       case LDAR_x:
1331         set_xreg(rt, Read<uint64_t>(address), NoRegLog);
1332         break;
1333       case LDXP_w:
1334       case LDAXP_w:
1335         set_wreg(rt, Read<uint32_t>(address), NoRegLog);
1336         set_wreg(rt2, Read<uint32_t>(address + element_size), NoRegLog);
1337         break;
1338       case LDXP_x:
1339       case LDAXP_x:
1340         set_xreg(rt, Read<uint64_t>(address), NoRegLog);
1341         set_xreg(rt2, Read<uint64_t>(address + element_size), NoRegLog);
1342         break;
1343       default:
1344         VIXL_UNREACHABLE();
1345     }
1346 
1347     if (is_acquire_release) {
1348       // Approximate load-acquire by issuing a full barrier after the load.
1349       js::jit::AtomicOperations::fenceSeqCst();
1350     }
1351 
1352     LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1353     if (is_pair) {
1354       LogRead(address + element_size, rt2,
1355               GetPrintRegisterFormatForSize(element_size));
1356     }
1357   } else {
1358     if (is_acquire_release) {
1359       // Approximate store-release by issuing a full barrier before the store.
1360       js::jit::AtomicOperations::fenceSeqCst();
1361     }
1362 
1363     bool do_store = true;
1364     if (is_exclusive) {
1365       do_store = local_monitor_.IsExclusive(address, access_size) &&
1366                  global_monitor_.IsExclusive(address, access_size);
1367       set_wreg(rs, do_store ? 0 : 1);
1368 
1369       //  - All exclusive stores explicitly clear the local monitor.
1370       local_monitor_.Clear();
1371     } else {
1372       //  - Any other store can clear the local monitor as a side effect.
1373       local_monitor_.MaybeClear();
1374     }
1375 
1376     if (do_store) {
1377       switch (op) {
1378         case STXRB_w:
1379         case STLXRB_w:
1380         case STLRB_w:
1381           Write<uint8_t>(address, wreg(rt));
1382           break;
1383         case STXRH_w:
1384         case STLXRH_w:
1385         case STLRH_w:
1386           Write<uint16_t>(address, wreg(rt));
1387           break;
1388         case STXR_w:
1389         case STLXR_w:
1390         case STLR_w:
1391           Write<uint32_t>(address, wreg(rt));
1392           break;
1393         case STXR_x:
1394         case STLXR_x:
1395         case STLR_x:
1396           Write<uint64_t>(address, xreg(rt));
1397           break;
1398         case STXP_w:
1399         case STLXP_w:
1400           Write<uint32_t>(address, wreg(rt));
1401           Write<uint32_t>(address + element_size, wreg(rt2));
1402           break;
1403         case STXP_x:
1404         case STLXP_x:
1405           Write<uint64_t>(address, xreg(rt));
1406           Write<uint64_t>(address + element_size, xreg(rt2));
1407           break;
1408         default:
1409           VIXL_UNREACHABLE();
1410       }
1411 
1412       LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1413       if (is_pair) {
1414         LogWrite(address + element_size, rt2,
1415                  GetPrintRegisterFormatForSize(element_size));
1416       }
1417     }
1418   }
1419 }
1420 
1421 
VisitLoadLiteral(const Instruction * instr)1422 void Simulator::VisitLoadLiteral(const Instruction* instr) {
1423   unsigned rt = instr->Rt();
1424   uint64_t address = instr->LiteralAddress<uint64_t>();
1425 
1426   // Verify that the calculated address is available to the host.
1427   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1428 
1429   switch (instr->Mask(LoadLiteralMask)) {
1430     // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
1431     // print a more detailed log.
1432     case LDR_w_lit:
1433       set_wreg(rt, Read<uint32_t>(address), NoRegLog);
1434       LogRead(address, rt, kPrintWReg);
1435       break;
1436     case LDR_x_lit:
1437       set_xreg(rt, Read<uint64_t>(address), NoRegLog);
1438       LogRead(address, rt, kPrintXReg);
1439       break;
1440     case LDR_s_lit:
1441       set_sreg(rt, Read<float>(address), NoRegLog);
1442       LogVRead(address, rt, kPrintSReg);
1443       break;
1444     case LDR_d_lit:
1445       set_dreg(rt, Read<double>(address), NoRegLog);
1446       LogVRead(address, rt, kPrintDReg);
1447       break;
1448     case LDR_q_lit:
1449       set_qreg(rt, Read<qreg_t>(address), NoRegLog);
1450       LogVRead(address, rt, kPrintReg1Q);
1451       break;
1452     case LDRSW_x_lit:
1453       set_xreg(rt, Read<int32_t>(address), NoRegLog);
1454       LogRead(address, rt, kPrintWReg);
1455       break;
1456 
1457     // Ignore prfm hint instructions.
1458     case PRFM_lit: break;
1459 
1460     default: VIXL_UNREACHABLE();
1461   }
1462 
1463   local_monitor_.MaybeClear();
1464 }
1465 
1466 
AddressModeHelper(unsigned addr_reg,int64_t offset,AddrMode addrmode)1467 uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
1468                                        int64_t offset,
1469                                        AddrMode addrmode) {
1470   uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1471 
1472   if ((addr_reg == 31) && ((address % 16) != 0)) {
1473     // When the base register is SP the stack pointer is required to be
1474     // quadword aligned prior to the address calculation and write-backs.
1475     // Misalignment will cause a stack alignment fault.
1476     VIXL_ALIGNMENT_EXCEPTION();
1477   }
1478 
1479   if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1480     VIXL_ASSERT(offset != 0);
1481     // Only preindex should log the register update here. For Postindex, the
1482     // update will be printed automatically by LogWrittenRegisters _after_ the
1483     // memory access itself is logged.
1484     RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
1485     set_xreg(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
1486   }
1487 
1488   if ((addrmode == Offset) || (addrmode == PreIndex)) {
1489     address += offset;
1490   }
1491 
1492   // Verify that the calculated address is available to the host.
1493   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1494 
1495   return static_cast<uintptr_t>(address);
1496 }
1497 
1498 
VisitMoveWideImmediate(const Instruction * instr)1499 void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
1500   MoveWideImmediateOp mov_op =
1501     static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1502   int64_t new_xn_val = 0;
1503 
1504   bool is_64_bits = instr->SixtyFourBits() == 1;
1505   // Shift is limited for W operations.
1506   VIXL_ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
1507 
1508   // Get the shifted immediate.
1509   int64_t shift = instr->ShiftMoveWide() * 16;
1510   int64_t shifted_imm16 = static_cast<int64_t>(instr->ImmMoveWide()) << shift;
1511 
1512   // Compute the new value.
1513   switch (mov_op) {
1514     case MOVN_w:
1515     case MOVN_x: {
1516         new_xn_val = ~shifted_imm16;
1517         if (!is_64_bits) new_xn_val &= kWRegMask;
1518       break;
1519     }
1520     case MOVK_w:
1521     case MOVK_x: {
1522         unsigned reg_code = instr->Rd();
1523         int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1524                                          : wreg(reg_code);
1525         new_xn_val =
1526             (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
1527       break;
1528     }
1529     case MOVZ_w:
1530     case MOVZ_x: {
1531         new_xn_val = shifted_imm16;
1532       break;
1533     }
1534     default:
1535       VIXL_UNREACHABLE();
1536   }
1537 
1538   // Update the destination register.
1539   set_xreg(instr->Rd(), new_xn_val);
1540 }
1541 
1542 
VisitConditionalSelect(const Instruction * instr)1543 void Simulator::VisitConditionalSelect(const Instruction* instr) {
1544   uint64_t new_val = xreg(instr->Rn());
1545 
1546   if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1547     new_val = xreg(instr->Rm());
1548     switch (instr->Mask(ConditionalSelectMask)) {
1549       case CSEL_w:
1550       case CSEL_x: break;
1551       case CSINC_w:
1552       case CSINC_x: new_val++; break;
1553       case CSINV_w:
1554       case CSINV_x: new_val = ~new_val; break;
1555       case CSNEG_w:
1556       case CSNEG_x: new_val = -new_val; break;
1557       default: VIXL_UNIMPLEMENTED();
1558     }
1559   }
1560   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1561   set_reg(reg_size, instr->Rd(), new_val);
1562 }
1563 
1564 
VisitDataProcessing1Source(const Instruction * instr)1565 void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
1566   unsigned dst = instr->Rd();
1567   unsigned src = instr->Rn();
1568 
1569   switch (instr->Mask(DataProcessing1SourceMask)) {
1570     case RBIT_w: set_wreg(dst, ReverseBits(wreg(src))); break;
1571     case RBIT_x: set_xreg(dst, ReverseBits(xreg(src))); break;
1572     case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), 1)); break;
1573     case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), 1)); break;
1574     case REV_w: set_wreg(dst, ReverseBytes(wreg(src), 2)); break;
1575     case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), 2)); break;
1576     case REV_x: set_xreg(dst, ReverseBytes(xreg(src), 3)); break;
1577     case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src))); break;
1578     case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src))); break;
1579     case CLS_w: {
1580       set_wreg(dst, CountLeadingSignBits(wreg(src)));
1581       break;
1582     }
1583     case CLS_x: {
1584       set_xreg(dst, CountLeadingSignBits(xreg(src)));
1585       break;
1586     }
1587     default: VIXL_UNIMPLEMENTED();
1588   }
1589 }
1590 
1591 
Poly32Mod2(unsigned n,uint64_t data,uint32_t poly)1592 uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
1593   VIXL_ASSERT((n > 32) && (n <= 64));
1594   for (unsigned i = (n - 1); i >= 32; i--) {
1595     if (((data >> i) & 1) != 0) {
1596       uint64_t polysh32 = (uint64_t)poly << (i - 32);
1597       uint64_t mask = (UINT64_C(1) << i) - 1;
1598       data = ((data & mask) ^ polysh32);
1599     }
1600   }
1601   return data & 0xffffffff;
1602 }
1603 
1604 
1605 template <typename T>
Crc32Checksum(uint32_t acc,T val,uint32_t poly)1606 uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
1607   unsigned size = sizeof(val) * 8;  // Number of bits in type T.
1608   VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
1609   uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
1610   uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
1611   return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
1612 }
1613 
1614 
Crc32Checksum(uint32_t acc,uint64_t val,uint32_t poly)1615 uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
1616   // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
1617   // the CRC of each 32-bit word sequentially.
1618   acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
1619   return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
1620 }
1621 
1622 
VisitDataProcessing2Source(const Instruction * instr)1623 void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
1624   Shift shift_op = NO_SHIFT;
1625   int64_t result = 0;
1626   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1627 
1628   switch (instr->Mask(DataProcessing2SourceMask)) {
1629     case SDIV_w: {
1630       int32_t rn = wreg(instr->Rn());
1631       int32_t rm = wreg(instr->Rm());
1632       if ((rn == kWMinInt) && (rm == -1)) {
1633         result = kWMinInt;
1634       } else if (rm == 0) {
1635         // Division by zero can be trapped, but not on A-class processors.
1636         result = 0;
1637       } else {
1638         result = rn / rm;
1639       }
1640       break;
1641     }
1642     case SDIV_x: {
1643       int64_t rn = xreg(instr->Rn());
1644       int64_t rm = xreg(instr->Rm());
1645       if ((rn == kXMinInt) && (rm == -1)) {
1646         result = kXMinInt;
1647       } else if (rm == 0) {
1648         // Division by zero can be trapped, but not on A-class processors.
1649         result = 0;
1650       } else {
1651         result = rn / rm;
1652       }
1653       break;
1654     }
1655     case UDIV_w: {
1656       uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
1657       uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
1658       if (rm == 0) {
1659         // Division by zero can be trapped, but not on A-class processors.
1660         result = 0;
1661       } else {
1662         result = rn / rm;
1663       }
1664       break;
1665     }
1666     case UDIV_x: {
1667       uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
1668       uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
1669       if (rm == 0) {
1670         // Division by zero can be trapped, but not on A-class processors.
1671         result = 0;
1672       } else {
1673         result = rn / rm;
1674       }
1675       break;
1676     }
1677     case LSLV_w:
1678     case LSLV_x: shift_op = LSL; break;
1679     case LSRV_w:
1680     case LSRV_x: shift_op = LSR; break;
1681     case ASRV_w:
1682     case ASRV_x: shift_op = ASR; break;
1683     case RORV_w:
1684     case RORV_x: shift_op = ROR; break;
1685     case CRC32B: {
1686       uint32_t acc = reg<uint32_t>(instr->Rn());
1687       uint8_t  val = reg<uint8_t>(instr->Rm());
1688       result = Crc32Checksum(acc, val, CRC32_POLY);
1689       break;
1690     }
1691     case CRC32H: {
1692       uint32_t acc = reg<uint32_t>(instr->Rn());
1693       uint16_t val = reg<uint16_t>(instr->Rm());
1694       result = Crc32Checksum(acc, val, CRC32_POLY);
1695       break;
1696     }
1697     case CRC32W: {
1698       uint32_t acc = reg<uint32_t>(instr->Rn());
1699       uint32_t val = reg<uint32_t>(instr->Rm());
1700       result = Crc32Checksum(acc, val, CRC32_POLY);
1701       break;
1702     }
1703     case CRC32X: {
1704       uint32_t acc = reg<uint32_t>(instr->Rn());
1705       uint64_t val = reg<uint64_t>(instr->Rm());
1706       result = Crc32Checksum(acc, val, CRC32_POLY);
1707       reg_size = kWRegSize;
1708       break;
1709     }
1710     case CRC32CB: {
1711       uint32_t acc = reg<uint32_t>(instr->Rn());
1712       uint8_t  val = reg<uint8_t>(instr->Rm());
1713       result = Crc32Checksum(acc, val, CRC32C_POLY);
1714       break;
1715     }
1716     case CRC32CH: {
1717       uint32_t acc = reg<uint32_t>(instr->Rn());
1718       uint16_t val = reg<uint16_t>(instr->Rm());
1719       result = Crc32Checksum(acc, val, CRC32C_POLY);
1720       break;
1721     }
1722     case CRC32CW: {
1723       uint32_t acc = reg<uint32_t>(instr->Rn());
1724       uint32_t val = reg<uint32_t>(instr->Rm());
1725       result = Crc32Checksum(acc, val, CRC32C_POLY);
1726       break;
1727     }
1728     case CRC32CX: {
1729       uint32_t acc = reg<uint32_t>(instr->Rn());
1730       uint64_t val = reg<uint64_t>(instr->Rm());
1731       result = Crc32Checksum(acc, val, CRC32C_POLY);
1732       reg_size = kWRegSize;
1733       break;
1734     }
1735     default: VIXL_UNIMPLEMENTED();
1736   }
1737 
1738   if (shift_op != NO_SHIFT) {
1739     // Shift distance encoded in the least-significant five/six bits of the
1740     // register.
1741     int mask = (instr->SixtyFourBits() == 1) ? 0x3f : 0x1f;
1742     unsigned shift = wreg(instr->Rm()) & mask;
1743     result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
1744                           shift);
1745   }
1746   set_reg(reg_size, instr->Rd(), result);
1747 }
1748 
1749 
1750 // The algorithm used is adapted from the one described in section 8.2 of
1751 //   Hacker's Delight, by Henry S. Warren, Jr.
1752 // It assumes that a right shift on a signed integer is an arithmetic shift.
1753 // Type T must be either uint64_t or int64_t.
1754 template <typename T>
MultiplyHigh(T u,T v)1755 static T MultiplyHigh(T u, T v) {
1756   uint64_t u0, v0, w0;
1757   T u1, v1, w1, w2, t;
1758 
1759   VIXL_ASSERT(sizeof(u) == sizeof(u0));
1760 
1761   u0 = u & 0xffffffff;
1762   u1 = u >> 32;
1763   v0 = v & 0xffffffff;
1764   v1 = v >> 32;
1765 
1766   w0 = u0 * v0;
1767   t = u1 * v0 + (w0 >> 32);
1768   w1 = t & 0xffffffff;
1769   w2 = t >> 32;
1770   w1 = u0 * v1 + w1;
1771 
1772   return u1 * v1 + w2 + (w1 >> 32);
1773 }
1774 
1775 
VisitDataProcessing3Source(const Instruction * instr)1776 void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
1777   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1778 
1779   int64_t result = 0;
1780   // Extract and sign- or zero-extend 32-bit arguments for widening operations.
1781   uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
1782   uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
1783   int64_t rn_s32 = reg<int32_t>(instr->Rn());
1784   int64_t rm_s32 = reg<int32_t>(instr->Rm());
1785   switch (instr->Mask(DataProcessing3SourceMask)) {
1786     case MADD_w:
1787     case MADD_x:
1788       result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
1789       break;
1790     case MSUB_w:
1791     case MSUB_x:
1792       result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
1793       break;
1794     case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
1795     case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
1796     case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
1797     case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
1798     case UMULH_x:
1799       result = MultiplyHigh(reg<uint64_t>(instr->Rn()),
1800                             reg<uint64_t>(instr->Rm()));
1801       break;
1802     case SMULH_x:
1803       result = MultiplyHigh(xreg(instr->Rn()), xreg(instr->Rm()));
1804       break;
1805     default: VIXL_UNIMPLEMENTED();
1806   }
1807   set_reg(reg_size, instr->Rd(), result);
1808 }
1809 
1810 
VisitBitfield(const Instruction * instr)1811 void Simulator::VisitBitfield(const Instruction* instr) {
1812   unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1813   int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
1814   int64_t R = instr->ImmR();
1815   int64_t S = instr->ImmS();
1816   int64_t diff = S - R;
1817   int64_t mask;
1818   if (diff >= 0) {
1819     mask = (diff < (reg_size - 1)) ? (INT64_C(1) << (diff + 1)) - 1
1820                                    : reg_mask;
1821   } else {
1822     mask = (INT64_C(1) << (S + 1)) - 1;
1823     mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
1824     diff += reg_size;
1825   }
1826 
1827   // inzero indicates if the extracted bitfield is inserted into the
1828   // destination register value or in zero.
1829   // If extend is true, extend the sign of the extracted bitfield.
1830   bool inzero = false;
1831   bool extend = false;
1832   switch (instr->Mask(BitfieldMask)) {
1833     case BFM_x:
1834     case BFM_w:
1835       break;
1836     case SBFM_x:
1837     case SBFM_w:
1838       inzero = true;
1839       extend = true;
1840       break;
1841     case UBFM_x:
1842     case UBFM_w:
1843       inzero = true;
1844       break;
1845     default:
1846       VIXL_UNIMPLEMENTED();
1847   }
1848 
1849   int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
1850   int64_t src = reg(reg_size, instr->Rn());
1851   // Rotate source bitfield into place.
1852   int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
1853   // Determine the sign extension.
1854   int64_t topbits = ((INT64_C(1) << (reg_size - diff - 1)) - 1) << (diff + 1);
1855   int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
1856 
1857   // Merge sign extension, dest/zero and bitfield.
1858   result = signbits | (result & mask) | (dst & ~mask);
1859 
1860   set_reg(reg_size, instr->Rd(), result);
1861 }
1862 
1863 
VisitExtract(const Instruction * instr)1864 void Simulator::VisitExtract(const Instruction* instr) {
1865   unsigned lsb = instr->ImmS();
1866   unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
1867                                                     : kWRegSize;
1868   uint64_t low_res = static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb;
1869   uint64_t high_res =
1870       (lsb == 0) ? 0 : reg(reg_size, instr->Rn()) << (reg_size - lsb);
1871   set_reg(reg_size, instr->Rd(), low_res | high_res);
1872 }
1873 
1874 
VisitFPImmediate(const Instruction * instr)1875 void Simulator::VisitFPImmediate(const Instruction* instr) {
1876   AssertSupportedFPCR();
1877 
1878   unsigned dest = instr->Rd();
1879   switch (instr->Mask(FPImmediateMask)) {
1880     case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
1881     case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
1882     default: VIXL_UNREACHABLE();
1883   }
1884 }
1885 
1886 
VisitFPIntegerConvert(const Instruction * instr)1887 void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
1888   AssertSupportedFPCR();
1889 
1890   unsigned dst = instr->Rd();
1891   unsigned src = instr->Rn();
1892 
1893   FPRounding round = RMode();
1894 
1895   switch (instr->Mask(FPIntegerConvertMask)) {
1896     case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
1897     case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
1898     case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
1899     case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
1900     case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
1901     case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
1902     case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
1903     case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
1904     case FCVTMS_ws:
1905       set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
1906       break;
1907     case FCVTMS_xs:
1908       set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
1909       break;
1910     case FCVTMS_wd:
1911       set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
1912       break;
1913     case FCVTMS_xd:
1914       set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
1915       break;
1916     case FCVTMU_ws:
1917       set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
1918       break;
1919     case FCVTMU_xs:
1920       set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
1921       break;
1922     case FCVTMU_wd:
1923       set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
1924       break;
1925     case FCVTMU_xd:
1926       set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
1927       break;
1928     case FCVTPS_ws:
1929       set_wreg(dst, FPToInt32(sreg(src), FPPositiveInfinity));
1930       break;
1931     case FCVTPS_xs:
1932       set_xreg(dst, FPToInt64(sreg(src), FPPositiveInfinity));
1933       break;
1934     case FCVTPS_wd:
1935       set_wreg(dst, FPToInt32(dreg(src), FPPositiveInfinity));
1936       break;
1937     case FCVTPS_xd:
1938       set_xreg(dst, FPToInt64(dreg(src), FPPositiveInfinity));
1939       break;
1940     case FCVTPU_ws:
1941       set_wreg(dst, FPToUInt32(sreg(src), FPPositiveInfinity));
1942       break;
1943     case FCVTPU_xs:
1944       set_xreg(dst, FPToUInt64(sreg(src), FPPositiveInfinity));
1945       break;
1946     case FCVTPU_wd:
1947       set_wreg(dst, FPToUInt32(dreg(src), FPPositiveInfinity));
1948       break;
1949     case FCVTPU_xd:
1950       set_xreg(dst, FPToUInt64(dreg(src), FPPositiveInfinity));
1951       break;
1952     case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
1953     case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
1954     case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
1955     case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
1956     case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
1957     case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
1958     case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
1959     case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
1960     case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
1961     case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
1962     case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
1963     case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
1964     case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
1965     case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
1966     case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
1967     case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
1968     case FJCVTZS: set_wreg(dst, FPToFixedJS(dreg(src))); break;
1969     case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
1970     case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
1971     case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
1972     case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
1973     case FMOV_d1_x:
1974       LogicVRegister(vreg(dst)).SetUint(kFormatD, 1, xreg(src));
1975       break;
1976     case FMOV_x_d1:
1977       set_xreg(dst, LogicVRegister(vreg(src)).Uint(kFormatD, 1));
1978       break;
1979 
1980     // A 32-bit input can be handled in the same way as a 64-bit input, since
1981     // the sign- or zero-extension will not affect the conversion.
1982     case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
1983     case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
1984     case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
1985     case UCVTF_dw: {
1986       set_dreg(dst, UFixedToDouble(static_cast<uint32_t>(wreg(src)), 0, round));
1987       break;
1988     }
1989     case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
1990     case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
1991     case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
1992     case UCVTF_sw: {
1993       set_sreg(dst, UFixedToFloat(static_cast<uint32_t>(wreg(src)), 0, round));
1994       break;
1995     }
1996 
1997     default: VIXL_UNREACHABLE();
1998   }
1999 }
2000 
2001 
VisitFPFixedPointConvert(const Instruction * instr)2002 void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
2003   AssertSupportedFPCR();
2004 
2005   unsigned dst = instr->Rd();
2006   unsigned src = instr->Rn();
2007   int fbits = 64 - instr->FPScale();
2008 
2009   FPRounding round = RMode();
2010 
2011   switch (instr->Mask(FPFixedPointConvertMask)) {
2012     // A 32-bit input can be handled in the same way as a 64-bit input, since
2013     // the sign- or zero-extension will not affect the conversion.
2014     case SCVTF_dx_fixed:
2015       set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2016       break;
2017     case SCVTF_dw_fixed:
2018       set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2019       break;
2020     case UCVTF_dx_fixed:
2021       set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2022       break;
2023     case UCVTF_dw_fixed: {
2024       set_dreg(dst,
2025                UFixedToDouble(static_cast<uint32_t>(wreg(src)), fbits, round));
2026       break;
2027     }
2028     case SCVTF_sx_fixed:
2029       set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2030       break;
2031     case SCVTF_sw_fixed:
2032       set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2033       break;
2034     case UCVTF_sx_fixed:
2035       set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2036       break;
2037     case UCVTF_sw_fixed: {
2038       set_sreg(dst,
2039                UFixedToFloat(static_cast<uint32_t>(wreg(src)), fbits, round));
2040       break;
2041     }
2042     case FCVTZS_xd_fixed:
2043       set_xreg(dst, FPToInt64(dreg(src) * std::pow(2.0, fbits), FPZero));
2044       break;
2045     case FCVTZS_wd_fixed:
2046       set_wreg(dst, FPToInt32(dreg(src) * std::pow(2.0, fbits), FPZero));
2047       break;
2048     case FCVTZU_xd_fixed:
2049       set_xreg(dst, FPToUInt64(dreg(src) * std::pow(2.0, fbits), FPZero));
2050       break;
2051     case FCVTZU_wd_fixed:
2052       set_wreg(dst, FPToUInt32(dreg(src) * std::pow(2.0, fbits), FPZero));
2053       break;
2054     case FCVTZS_xs_fixed:
2055       set_xreg(dst, FPToInt64(sreg(src) * std::pow(2.0f, fbits), FPZero));
2056       break;
2057     case FCVTZS_ws_fixed:
2058       set_wreg(dst, FPToInt32(sreg(src) * std::pow(2.0f, fbits), FPZero));
2059       break;
2060     case FCVTZU_xs_fixed:
2061       set_xreg(dst, FPToUInt64(sreg(src) * std::pow(2.0f, fbits), FPZero));
2062       break;
2063     case FCVTZU_ws_fixed:
2064       set_wreg(dst, FPToUInt32(sreg(src) * std::pow(2.0f, fbits), FPZero));
2065       break;
2066     default: VIXL_UNREACHABLE();
2067   }
2068 }
2069 
2070 
VisitFPCompare(const Instruction * instr)2071 void Simulator::VisitFPCompare(const Instruction* instr) {
2072   AssertSupportedFPCR();
2073 
2074   FPTrapFlags trap = DisableTrap;
2075   switch (instr->Mask(FPCompareMask)) {
2076     case FCMPE_s: trap = EnableTrap; VIXL_FALLTHROUGH();
2077     case FCMP_s: FPCompare(sreg(instr->Rn()), sreg(instr->Rm()), trap); break;
2078     case FCMPE_d: trap = EnableTrap; VIXL_FALLTHROUGH();
2079     case FCMP_d: FPCompare(dreg(instr->Rn()), dreg(instr->Rm()), trap); break;
2080     case FCMPE_s_zero: trap = EnableTrap; VIXL_FALLTHROUGH();
2081     case FCMP_s_zero: FPCompare(sreg(instr->Rn()), 0.0f, trap); break;
2082     case FCMPE_d_zero: trap = EnableTrap; VIXL_FALLTHROUGH();
2083     case FCMP_d_zero: FPCompare(dreg(instr->Rn()), 0.0, trap); break;
2084     default: VIXL_UNIMPLEMENTED();
2085   }
2086 }
2087 
2088 
VisitFPConditionalCompare(const Instruction * instr)2089 void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
2090   AssertSupportedFPCR();
2091 
2092   FPTrapFlags trap = DisableTrap;
2093   switch (instr->Mask(FPConditionalCompareMask)) {
2094     case FCCMPE_s: trap = EnableTrap;
2095       VIXL_FALLTHROUGH();
2096     case FCCMP_s:
2097       if (ConditionPassed(instr->Condition())) {
2098         FPCompare(sreg(instr->Rn()), sreg(instr->Rm()), trap);
2099       } else {
2100         nzcv().SetFlags(instr->Nzcv());
2101         LogSystemRegister(NZCV);
2102       }
2103       break;
2104     case FCCMPE_d: trap = EnableTrap;
2105       VIXL_FALLTHROUGH();
2106     case FCCMP_d:
2107       if (ConditionPassed(instr->Condition())) {
2108         FPCompare(dreg(instr->Rn()), dreg(instr->Rm()), trap);
2109       } else {
2110         nzcv().SetFlags(instr->Nzcv());
2111         LogSystemRegister(NZCV);
2112       }
2113       break;
2114     default: VIXL_UNIMPLEMENTED();
2115   }
2116 }
2117 
2118 
VisitFPConditionalSelect(const Instruction * instr)2119 void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
2120   AssertSupportedFPCR();
2121 
2122   Instr selected;
2123   if (ConditionPassed(instr->Condition())) {
2124     selected = instr->Rn();
2125   } else {
2126     selected = instr->Rm();
2127   }
2128 
2129   switch (instr->Mask(FPConditionalSelectMask)) {
2130     case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2131     case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2132     default: VIXL_UNIMPLEMENTED();
2133   }
2134 }
2135 
2136 
VisitFPDataProcessing1Source(const Instruction * instr)2137 void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
2138   AssertSupportedFPCR();
2139 
2140   FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
2141   VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2142   SimVRegister& rd = vreg(instr->Rd());
2143   SimVRegister& rn = vreg(instr->Rn());
2144   bool inexact_exception = false;
2145 
2146   unsigned fd = instr->Rd();
2147   unsigned fn = instr->Rn();
2148 
2149   switch (instr->Mask(FPDataProcessing1SourceMask)) {
2150     case FMOV_s: set_sreg(fd, sreg(fn)); return;
2151     case FMOV_d: set_dreg(fd, dreg(fn)); return;
2152     case FABS_s: fabs_(kFormatS, vreg(fd), vreg(fn)); return;
2153     case FABS_d: fabs_(kFormatD, vreg(fd), vreg(fn)); return;
2154     case FNEG_s: fneg(kFormatS, vreg(fd), vreg(fn)); return;
2155     case FNEG_d: fneg(kFormatD, vreg(fd), vreg(fn)); return;
2156     case FCVT_ds:
2157       set_dreg(fd, FPToDouble(sreg(fn), ReadDN()));
2158       return;
2159     case FCVT_sd:
2160       set_sreg(fd, FPToFloat(dreg(fn), FPTieEven, ReadDN()));
2161       return;
2162     case FCVT_hs:
2163       set_hreg(fd, Float16ToRawbits(FPToFloat16(sreg(fn), FPTieEven, ReadDN())));
2164       return;
2165     case FCVT_sh:
2166       set_sreg(fd, FPToFloat(RawbitsToFloat16(hreg(fn)), ReadDN()));
2167       return;
2168     case FCVT_dh:
2169       set_dreg(fd, FPToDouble(hreg(fn), ReadDN()));
2170       return;
2171     case FCVT_hd:
2172       set_hreg(fd, Float16ToRawbits(FPToFloat16(dreg(fn), FPTieEven, ReadDN())));
2173       return;
2174     case FSQRT_s:
2175     case FSQRT_d: fsqrt(vform, rd, rn); return;
2176     case FRINTI_s:
2177     case FRINTI_d: break;  // Use FPCR rounding mode.
2178     case FRINTX_s:
2179     case FRINTX_d: inexact_exception = true; break;
2180     case FRINTA_s:
2181     case FRINTA_d: fpcr_rounding = FPTieAway; break;
2182     case FRINTM_s:
2183     case FRINTM_d: fpcr_rounding = FPNegativeInfinity; break;
2184     case FRINTN_s:
2185     case FRINTN_d: fpcr_rounding = FPTieEven; break;
2186     case FRINTP_s:
2187     case FRINTP_d: fpcr_rounding = FPPositiveInfinity; break;
2188     case FRINTZ_s:
2189     case FRINTZ_d: fpcr_rounding = FPZero; break;
2190     default: VIXL_UNIMPLEMENTED();
2191   }
2192 
2193   // Only FRINT* instructions fall through the switch above.
2194   frint(vform, rd, rn, fpcr_rounding, inexact_exception);
2195 }
2196 
2197 
VisitFPDataProcessing2Source(const Instruction * instr)2198 void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
2199   AssertSupportedFPCR();
2200 
2201   VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2202   SimVRegister& rd = vreg(instr->Rd());
2203   SimVRegister& rn = vreg(instr->Rn());
2204   SimVRegister& rm = vreg(instr->Rm());
2205 
2206   switch (instr->Mask(FPDataProcessing2SourceMask)) {
2207     case FADD_s:
2208     case FADD_d: fadd(vform, rd, rn, rm); break;
2209     case FSUB_s:
2210     case FSUB_d: fsub(vform, rd, rn, rm); break;
2211     case FMUL_s:
2212     case FMUL_d: fmul(vform, rd, rn, rm); break;
2213     case FNMUL_s:
2214     case FNMUL_d: fnmul(vform, rd, rn, rm); break;
2215     case FDIV_s:
2216     case FDIV_d: fdiv(vform, rd, rn, rm); break;
2217     case FMAX_s:
2218     case FMAX_d: fmax(vform, rd, rn, rm); break;
2219     case FMIN_s:
2220     case FMIN_d: fmin(vform, rd, rn, rm); break;
2221     case FMAXNM_s:
2222     case FMAXNM_d: fmaxnm(vform, rd, rn, rm); break;
2223     case FMINNM_s:
2224     case FMINNM_d: fminnm(vform, rd, rn, rm); break;
2225     default:
2226       VIXL_UNREACHABLE();
2227   }
2228 }
2229 
2230 
VisitFPDataProcessing3Source(const Instruction * instr)2231 void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
2232   AssertSupportedFPCR();
2233 
2234   unsigned fd = instr->Rd();
2235   unsigned fn = instr->Rn();
2236   unsigned fm = instr->Rm();
2237   unsigned fa = instr->Ra();
2238 
2239   switch (instr->Mask(FPDataProcessing3SourceMask)) {
2240     // fd = fa +/- (fn * fm)
2241     case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
2242     case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
2243     case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
2244     case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
2245     // Negated variants of the above.
2246     case FNMADD_s:
2247       set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2248       break;
2249     case FNMSUB_s:
2250       set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2251       break;
2252     case FNMADD_d:
2253       set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2254       break;
2255     case FNMSUB_d:
2256       set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2257       break;
2258     default: VIXL_UNIMPLEMENTED();
2259   }
2260 }
2261 
2262 
FPProcessNaNs(const Instruction * instr)2263 bool Simulator::FPProcessNaNs(const Instruction* instr) {
2264   unsigned fd = instr->Rd();
2265   unsigned fn = instr->Rn();
2266   unsigned fm = instr->Rm();
2267   bool done = false;
2268 
2269   if (instr->Mask(FP64) == FP64) {
2270     double result = FPProcessNaNs(dreg(fn), dreg(fm));
2271     if (std::isnan(result)) {
2272       set_dreg(fd, result);
2273       done = true;
2274     }
2275   } else {
2276     float result = FPProcessNaNs(sreg(fn), sreg(fm));
2277     if (std::isnan(result)) {
2278       set_sreg(fd, result);
2279       done = true;
2280     }
2281   }
2282 
2283   return done;
2284 }
2285 
2286 
SysOp_W(int op,int64_t val)2287 void Simulator::SysOp_W(int op, int64_t val) {
2288   switch (op) {
2289     case IVAU:
2290     case CVAC:
2291     case CVAU:
2292     case CIVAC: {
2293       // Perform a dummy memory access to ensure that we have read access
2294       // to the specified address.
2295       volatile uint8_t y = Read<uint8_t>(val);
2296       USE(y);
2297       // TODO: Implement "case ZVA:".
2298       break;
2299     }
2300     default:
2301       VIXL_UNIMPLEMENTED();
2302   }
2303 }
2304 
2305 
VisitSystem(const Instruction * instr)2306 void Simulator::VisitSystem(const Instruction* instr) {
2307   // Some system instructions hijack their Op and Cp fields to represent a
2308   // range of immediates instead of indicating a different instruction. This
2309   // makes the decoding tricky.
2310   if (instr->Mask(SystemExclusiveMonitorFMask) == SystemExclusiveMonitorFixed) {
2311     VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
2312     switch (instr->Mask(SystemExclusiveMonitorMask)) {
2313       case CLREX: {
2314         PrintExclusiveAccessWarning();
2315         ClearLocalMonitor();
2316         break;
2317       }
2318     }
2319   } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2320     switch (instr->Mask(SystemSysRegMask)) {
2321       case MRS: {
2322         switch (instr->ImmSystemRegister()) {
2323           case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
2324           case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
2325           default: VIXL_UNIMPLEMENTED();
2326         }
2327         break;
2328       }
2329       case MSR: {
2330         switch (instr->ImmSystemRegister()) {
2331           case NZCV:
2332             nzcv().SetRawValue(wreg(instr->Rt()));
2333             LogSystemRegister(NZCV);
2334             break;
2335           case FPCR:
2336             fpcr().SetRawValue(wreg(instr->Rt()));
2337             LogSystemRegister(FPCR);
2338             break;
2339           default: VIXL_UNIMPLEMENTED();
2340         }
2341         break;
2342       }
2343     }
2344   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
2345     VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
2346     switch (instr->ImmHint()) {
2347       case NOP: break;
2348       case CSDB: break;
2349       default: VIXL_UNIMPLEMENTED();
2350     }
2351   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2352     js::jit::AtomicOperations::fenceSeqCst();
2353   } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
2354     switch (instr->Mask(SystemSysMask)) {
2355       case SYS: SysOp_W(instr->SysOp(), xreg(instr->Rt())); break;
2356       default: VIXL_UNIMPLEMENTED();
2357     }
2358   } else {
2359     VIXL_UNIMPLEMENTED();
2360   }
2361 }
2362 
2363 
VisitCrypto2RegSHA(const Instruction * instr)2364 void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
2365   VisitUnimplemented(instr);
2366 }
2367 
2368 
VisitCrypto3RegSHA(const Instruction * instr)2369 void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
2370   VisitUnimplemented(instr);
2371 }
2372 
2373 
VisitCryptoAES(const Instruction * instr)2374 void Simulator::VisitCryptoAES(const Instruction* instr) {
2375   VisitUnimplemented(instr);
2376 }
2377 
2378 
VisitNEON2RegMisc(const Instruction * instr)2379 void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
2380   NEONFormatDecoder nfd(instr);
2381   VectorFormat vf = nfd.GetVectorFormat();
2382 
2383   static const NEONFormatMap map_lp = {
2384     {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}
2385   };
2386   VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
2387 
2388   static const NEONFormatMap map_fcvtl = {
2389     {22}, {NF_4S, NF_2D}
2390   };
2391   VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
2392 
2393   static const NEONFormatMap map_fcvtn = {
2394     {22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S}
2395   };
2396   VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
2397 
2398   SimVRegister& rd = vreg(instr->Rd());
2399   SimVRegister& rn = vreg(instr->Rn());
2400 
2401   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
2402     // These instructions all use a two bit size field, except NOT and RBIT,
2403     // which use the field to encode the operation.
2404     switch (instr->Mask(NEON2RegMiscMask)) {
2405       case NEON_REV64:     rev64(vf, rd, rn); break;
2406       case NEON_REV32:     rev32(vf, rd, rn); break;
2407       case NEON_REV16:     rev16(vf, rd, rn); break;
2408       case NEON_SUQADD:    suqadd(vf, rd, rn); break;
2409       case NEON_USQADD:    usqadd(vf, rd, rn); break;
2410       case NEON_CLS:       cls(vf, rd, rn); break;
2411       case NEON_CLZ:       clz(vf, rd, rn); break;
2412       case NEON_CNT:       cnt(vf, rd, rn); break;
2413       case NEON_SQABS:     abs(vf, rd, rn).SignedSaturate(vf); break;
2414       case NEON_SQNEG:     neg(vf, rd, rn).SignedSaturate(vf); break;
2415       case NEON_CMGT_zero: cmp(vf, rd, rn, 0, gt); break;
2416       case NEON_CMGE_zero: cmp(vf, rd, rn, 0, ge); break;
2417       case NEON_CMEQ_zero: cmp(vf, rd, rn, 0, eq); break;
2418       case NEON_CMLE_zero: cmp(vf, rd, rn, 0, le); break;
2419       case NEON_CMLT_zero: cmp(vf, rd, rn, 0, lt); break;
2420       case NEON_ABS:       abs(vf, rd, rn); break;
2421       case NEON_NEG:       neg(vf, rd, rn); break;
2422       case NEON_SADDLP:    saddlp(vf_lp, rd, rn); break;
2423       case NEON_UADDLP:    uaddlp(vf_lp, rd, rn); break;
2424       case NEON_SADALP:    sadalp(vf_lp, rd, rn); break;
2425       case NEON_UADALP:    uadalp(vf_lp, rd, rn); break;
2426       case NEON_RBIT_NOT:
2427         vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
2428         switch (instr->FPType()) {
2429           case 0: not_(vf, rd, rn); break;
2430           case 1: rbit(vf, rd, rn);; break;
2431           default:
2432             VIXL_UNIMPLEMENTED();
2433         }
2434         break;
2435     }
2436   } else {
2437     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
2438     FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
2439     bool inexact_exception = false;
2440 
2441     // These instructions all use a one bit size field, except XTN, SQXTUN,
2442     // SHLL, SQXTN and UQXTN, which use a two bit size field.
2443     switch (instr->Mask(NEON2RegMiscFPMask)) {
2444       case NEON_FABS:   fabs_(fpf, rd, rn); return;
2445       case NEON_FNEG:   fneg(fpf, rd, rn); return;
2446       case NEON_FSQRT:  fsqrt(fpf, rd, rn); return;
2447       case NEON_FCVTL:
2448         if (instr->Mask(NEON_Q)) {
2449           fcvtl2(vf_fcvtl, rd, rn);
2450         } else {
2451           fcvtl(vf_fcvtl, rd, rn);
2452         }
2453         return;
2454       case NEON_FCVTN:
2455         if (instr->Mask(NEON_Q)) {
2456           fcvtn2(vf_fcvtn, rd, rn);
2457         } else {
2458           fcvtn(vf_fcvtn, rd, rn);
2459         }
2460         return;
2461       case NEON_FCVTXN:
2462         if (instr->Mask(NEON_Q)) {
2463           fcvtxn2(vf_fcvtn, rd, rn);
2464         } else {
2465           fcvtxn(vf_fcvtn, rd, rn);
2466         }
2467         return;
2468 
2469       // The following instructions break from the switch statement, rather
2470       // than return.
2471       case NEON_FRINTI:     break;  // Use FPCR rounding mode.
2472       case NEON_FRINTX:     inexact_exception = true; break;
2473       case NEON_FRINTA:     fpcr_rounding = FPTieAway; break;
2474       case NEON_FRINTM:     fpcr_rounding = FPNegativeInfinity; break;
2475       case NEON_FRINTN:     fpcr_rounding = FPTieEven; break;
2476       case NEON_FRINTP:     fpcr_rounding = FPPositiveInfinity; break;
2477       case NEON_FRINTZ:     fpcr_rounding = FPZero; break;
2478 
2479       case NEON_FCVTNS:     fcvts(fpf, rd, rn, FPTieEven); return;
2480       case NEON_FCVTNU:     fcvtu(fpf, rd, rn, FPTieEven); return;
2481       case NEON_FCVTPS:     fcvts(fpf, rd, rn, FPPositiveInfinity); return;
2482       case NEON_FCVTPU:     fcvtu(fpf, rd, rn, FPPositiveInfinity); return;
2483       case NEON_FCVTMS:     fcvts(fpf, rd, rn, FPNegativeInfinity); return;
2484       case NEON_FCVTMU:     fcvtu(fpf, rd, rn, FPNegativeInfinity); return;
2485       case NEON_FCVTZS:     fcvts(fpf, rd, rn, FPZero); return;
2486       case NEON_FCVTZU:     fcvtu(fpf, rd, rn, FPZero); return;
2487       case NEON_FCVTAS:     fcvts(fpf, rd, rn, FPTieAway); return;
2488       case NEON_FCVTAU:     fcvtu(fpf, rd, rn, FPTieAway); return;
2489       case NEON_SCVTF:      scvtf(fpf, rd, rn, 0, fpcr_rounding); return;
2490       case NEON_UCVTF:      ucvtf(fpf, rd, rn, 0, fpcr_rounding); return;
2491       case NEON_URSQRTE:    ursqrte(fpf, rd, rn); return;
2492       case NEON_URECPE:     urecpe(fpf, rd, rn); return;
2493       case NEON_FRSQRTE:    frsqrte(fpf, rd, rn); return;
2494       case NEON_FRECPE:     frecpe(fpf, rd, rn, fpcr_rounding); return;
2495       case NEON_FCMGT_zero: fcmp_zero(fpf, rd, rn, gt); return;
2496       case NEON_FCMGE_zero: fcmp_zero(fpf, rd, rn, ge); return;
2497       case NEON_FCMEQ_zero: fcmp_zero(fpf, rd, rn, eq); return;
2498       case NEON_FCMLE_zero: fcmp_zero(fpf, rd, rn, le); return;
2499       case NEON_FCMLT_zero: fcmp_zero(fpf, rd, rn, lt); return;
2500       default:
2501         if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
2502             (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
2503           switch (instr->Mask(NEON2RegMiscMask)) {
2504             case NEON_XTN: xtn(vf, rd, rn); return;
2505             case NEON_SQXTN: sqxtn(vf, rd, rn); return;
2506             case NEON_UQXTN: uqxtn(vf, rd, rn); return;
2507             case NEON_SQXTUN: sqxtun(vf, rd, rn); return;
2508             case NEON_SHLL:
2509               vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
2510               if (instr->Mask(NEON_Q)) {
2511                 shll2(vf, rd, rn);
2512               } else {
2513                 shll(vf, rd, rn);
2514               }
2515               return;
2516             default:
2517               VIXL_UNIMPLEMENTED();
2518           }
2519         } else {
2520           VIXL_UNIMPLEMENTED();
2521         }
2522     }
2523 
2524     // Only FRINT* instructions fall through the switch above.
2525     frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
2526   }
2527 }
2528 
2529 
VisitNEON3Same(const Instruction * instr)2530 void Simulator::VisitNEON3Same(const Instruction* instr) {
2531   NEONFormatDecoder nfd(instr);
2532   SimVRegister& rd = vreg(instr->Rd());
2533   SimVRegister& rn = vreg(instr->Rn());
2534   SimVRegister& rm = vreg(instr->Rm());
2535 
2536   if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
2537     VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
2538     switch (instr->Mask(NEON3SameLogicalMask)) {
2539       case NEON_AND: and_(vf, rd, rn, rm); break;
2540       case NEON_ORR: orr(vf, rd, rn, rm); break;
2541       case NEON_ORN: orn(vf, rd, rn, rm); break;
2542       case NEON_EOR: eor(vf, rd, rn, rm); break;
2543       case NEON_BIC: bic(vf, rd, rn, rm); break;
2544       case NEON_BIF: bif(vf, rd, rn, rm); break;
2545       case NEON_BIT: bit(vf, rd, rn, rm); break;
2546       case NEON_BSL: bsl(vf, rd, rn, rm); break;
2547       default:
2548         VIXL_UNIMPLEMENTED();
2549     }
2550   } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
2551     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
2552     switch (instr->Mask(NEON3SameFPMask)) {
2553       case NEON_FADD:    fadd(vf, rd, rn, rm); break;
2554       case NEON_FSUB:    fsub(vf, rd, rn, rm); break;
2555       case NEON_FMUL:    fmul(vf, rd, rn, rm); break;
2556       case NEON_FDIV:    fdiv(vf, rd, rn, rm); break;
2557       case NEON_FMAX:    fmax(vf, rd, rn, rm); break;
2558       case NEON_FMIN:    fmin(vf, rd, rn, rm); break;
2559       case NEON_FMAXNM:  fmaxnm(vf, rd, rn, rm); break;
2560       case NEON_FMINNM:  fminnm(vf, rd, rn, rm); break;
2561       case NEON_FMLA:    fmla(vf, rd, rn, rm); break;
2562       case NEON_FMLS:    fmls(vf, rd, rn, rm); break;
2563       case NEON_FMULX:   fmulx(vf, rd, rn, rm); break;
2564       case NEON_FACGE:   fabscmp(vf, rd, rn, rm, ge); break;
2565       case NEON_FACGT:   fabscmp(vf, rd, rn, rm, gt); break;
2566       case NEON_FCMEQ:   fcmp(vf, rd, rn, rm, eq); break;
2567       case NEON_FCMGE:   fcmp(vf, rd, rn, rm, ge); break;
2568       case NEON_FCMGT:   fcmp(vf, rd, rn, rm, gt); break;
2569       case NEON_FRECPS:  frecps(vf, rd, rn, rm); break;
2570       case NEON_FRSQRTS: frsqrts(vf, rd, rn, rm); break;
2571       case NEON_FABD:    fabd(vf, rd, rn, rm); break;
2572       case NEON_FADDP:   faddp(vf, rd, rn, rm); break;
2573       case NEON_FMAXP:   fmaxp(vf, rd, rn, rm); break;
2574       case NEON_FMAXNMP: fmaxnmp(vf, rd, rn, rm); break;
2575       case NEON_FMINP:   fminp(vf, rd, rn, rm); break;
2576       case NEON_FMINNMP: fminnmp(vf, rd, rn, rm); break;
2577       default:
2578         VIXL_UNIMPLEMENTED();
2579     }
2580   } else {
2581     VectorFormat vf = nfd.GetVectorFormat();
2582     switch (instr->Mask(NEON3SameMask)) {
2583       case NEON_ADD:   add(vf, rd, rn, rm);  break;
2584       case NEON_ADDP:  addp(vf, rd, rn, rm); break;
2585       case NEON_CMEQ:  cmp(vf, rd, rn, rm, eq); break;
2586       case NEON_CMGE:  cmp(vf, rd, rn, rm, ge); break;
2587       case NEON_CMGT:  cmp(vf, rd, rn, rm, gt); break;
2588       case NEON_CMHI:  cmp(vf, rd, rn, rm, hi); break;
2589       case NEON_CMHS:  cmp(vf, rd, rn, rm, hs); break;
2590       case NEON_CMTST: cmptst(vf, rd, rn, rm); break;
2591       case NEON_MLS:   mls(vf, rd, rn, rm); break;
2592       case NEON_MLA:   mla(vf, rd, rn, rm); break;
2593       case NEON_MUL:   mul(vf, rd, rn, rm); break;
2594       case NEON_PMUL:  pmul(vf, rd, rn, rm); break;
2595       case NEON_SMAX:  smax(vf, rd, rn, rm); break;
2596       case NEON_SMAXP: smaxp(vf, rd, rn, rm); break;
2597       case NEON_SMIN:  smin(vf, rd, rn, rm); break;
2598       case NEON_SMINP: sminp(vf, rd, rn, rm); break;
2599       case NEON_SUB:   sub(vf, rd, rn, rm);  break;
2600       case NEON_UMAX:  umax(vf, rd, rn, rm); break;
2601       case NEON_UMAXP: umaxp(vf, rd, rn, rm); break;
2602       case NEON_UMIN:  umin(vf, rd, rn, rm); break;
2603       case NEON_UMINP: uminp(vf, rd, rn, rm); break;
2604       case NEON_SSHL:  sshl(vf, rd, rn, rm); break;
2605       case NEON_USHL:  ushl(vf, rd, rn, rm); break;
2606       case NEON_SABD:  absdiff(vf, rd, rn, rm, true); break;
2607       case NEON_UABD:  absdiff(vf, rd, rn, rm, false); break;
2608       case NEON_SABA:  saba(vf, rd, rn, rm); break;
2609       case NEON_UABA:  uaba(vf, rd, rn, rm); break;
2610       case NEON_UQADD: add(vf, rd, rn, rm).UnsignedSaturate(vf); break;
2611       case NEON_SQADD: add(vf, rd, rn, rm).SignedSaturate(vf); break;
2612       case NEON_UQSUB: sub(vf, rd, rn, rm).UnsignedSaturate(vf); break;
2613       case NEON_SQSUB: sub(vf, rd, rn, rm).SignedSaturate(vf); break;
2614       case NEON_SQDMULH:  sqdmulh(vf, rd, rn, rm); break;
2615       case NEON_SQRDMULH: sqrdmulh(vf, rd, rn, rm); break;
2616       case NEON_UQSHL: ushl(vf, rd, rn, rm).UnsignedSaturate(vf); break;
2617       case NEON_SQSHL: sshl(vf, rd, rn, rm).SignedSaturate(vf); break;
2618       case NEON_URSHL: ushl(vf, rd, rn, rm).Round(vf); break;
2619       case NEON_SRSHL: sshl(vf, rd, rn, rm).Round(vf); break;
2620       case NEON_UQRSHL:
2621         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
2622         break;
2623       case NEON_SQRSHL:
2624         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
2625         break;
2626       case NEON_UHADD:
2627         add(vf, rd, rn, rm).Uhalve(vf);
2628         break;
2629       case NEON_URHADD:
2630         add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
2631         break;
2632       case NEON_SHADD:
2633         add(vf, rd, rn, rm).Halve(vf);
2634         break;
2635       case NEON_SRHADD:
2636         add(vf, rd, rn, rm).Halve(vf).Round(vf);
2637         break;
2638       case NEON_UHSUB:
2639         sub(vf, rd, rn, rm).Uhalve(vf);
2640         break;
2641       case NEON_SHSUB:
2642         sub(vf, rd, rn, rm).Halve(vf);
2643         break;
2644       default:
2645         VIXL_UNIMPLEMENTED();
2646     }
2647   }
2648 }
2649 
2650 
VisitNEON3Different(const Instruction * instr)2651 void Simulator::VisitNEON3Different(const Instruction* instr) {
2652   NEONFormatDecoder nfd(instr);
2653   VectorFormat vf = nfd.GetVectorFormat();
2654   VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
2655 
2656   SimVRegister& rd = vreg(instr->Rd());
2657   SimVRegister& rn = vreg(instr->Rn());
2658   SimVRegister& rm = vreg(instr->Rm());
2659 
2660   switch (instr->Mask(NEON3DifferentMask)) {
2661     case NEON_PMULL:    pmull(vf_l, rd, rn, rm); break;
2662     case NEON_PMULL2:   pmull2(vf_l, rd, rn, rm); break;
2663     case NEON_UADDL:    uaddl(vf_l, rd, rn, rm); break;
2664     case NEON_UADDL2:   uaddl2(vf_l, rd, rn, rm); break;
2665     case NEON_SADDL:    saddl(vf_l, rd, rn, rm); break;
2666     case NEON_SADDL2:   saddl2(vf_l, rd, rn, rm); break;
2667     case NEON_USUBL:    usubl(vf_l, rd, rn, rm); break;
2668     case NEON_USUBL2:   usubl2(vf_l, rd, rn, rm); break;
2669     case NEON_SSUBL:    ssubl(vf_l, rd, rn, rm); break;
2670     case NEON_SSUBL2:   ssubl2(vf_l, rd, rn, rm); break;
2671     case NEON_SABAL:    sabal(vf_l, rd, rn, rm); break;
2672     case NEON_SABAL2:   sabal2(vf_l, rd, rn, rm); break;
2673     case NEON_UABAL:    uabal(vf_l, rd, rn, rm); break;
2674     case NEON_UABAL2:   uabal2(vf_l, rd, rn, rm); break;
2675     case NEON_SABDL:    sabdl(vf_l, rd, rn, rm); break;
2676     case NEON_SABDL2:   sabdl2(vf_l, rd, rn, rm); break;
2677     case NEON_UABDL:    uabdl(vf_l, rd, rn, rm); break;
2678     case NEON_UABDL2:   uabdl2(vf_l, rd, rn, rm); break;
2679     case NEON_SMLAL:    smlal(vf_l, rd, rn, rm); break;
2680     case NEON_SMLAL2:   smlal2(vf_l, rd, rn, rm); break;
2681     case NEON_UMLAL:    umlal(vf_l, rd, rn, rm); break;
2682     case NEON_UMLAL2:   umlal2(vf_l, rd, rn, rm); break;
2683     case NEON_SMLSL:    smlsl(vf_l, rd, rn, rm); break;
2684     case NEON_SMLSL2:   smlsl2(vf_l, rd, rn, rm); break;
2685     case NEON_UMLSL:    umlsl(vf_l, rd, rn, rm); break;
2686     case NEON_UMLSL2:   umlsl2(vf_l, rd, rn, rm); break;
2687     case NEON_SMULL:    smull(vf_l, rd, rn, rm); break;
2688     case NEON_SMULL2:   smull2(vf_l, rd, rn, rm); break;
2689     case NEON_UMULL:    umull(vf_l, rd, rn, rm); break;
2690     case NEON_UMULL2:   umull2(vf_l, rd, rn, rm); break;
2691     case NEON_SQDMLAL:  sqdmlal(vf_l, rd, rn, rm); break;
2692     case NEON_SQDMLAL2: sqdmlal2(vf_l, rd, rn, rm); break;
2693     case NEON_SQDMLSL:  sqdmlsl(vf_l, rd, rn, rm); break;
2694     case NEON_SQDMLSL2: sqdmlsl2(vf_l, rd, rn, rm); break;
2695     case NEON_SQDMULL:  sqdmull(vf_l, rd, rn, rm); break;
2696     case NEON_SQDMULL2: sqdmull2(vf_l, rd, rn, rm); break;
2697     case NEON_UADDW:    uaddw(vf_l, rd, rn, rm); break;
2698     case NEON_UADDW2:   uaddw2(vf_l, rd, rn, rm); break;
2699     case NEON_SADDW:    saddw(vf_l, rd, rn, rm); break;
2700     case NEON_SADDW2:   saddw2(vf_l, rd, rn, rm); break;
2701     case NEON_USUBW:    usubw(vf_l, rd, rn, rm); break;
2702     case NEON_USUBW2:   usubw2(vf_l, rd, rn, rm); break;
2703     case NEON_SSUBW:    ssubw(vf_l, rd, rn, rm); break;
2704     case NEON_SSUBW2:   ssubw2(vf_l, rd, rn, rm); break;
2705     case NEON_ADDHN:    addhn(vf, rd, rn, rm); break;
2706     case NEON_ADDHN2:   addhn2(vf, rd, rn, rm); break;
2707     case NEON_RADDHN:   raddhn(vf, rd, rn, rm); break;
2708     case NEON_RADDHN2:  raddhn2(vf, rd, rn, rm); break;
2709     case NEON_SUBHN:    subhn(vf, rd, rn, rm); break;
2710     case NEON_SUBHN2:   subhn2(vf, rd, rn, rm); break;
2711     case NEON_RSUBHN:   rsubhn(vf, rd, rn, rm); break;
2712     case NEON_RSUBHN2:  rsubhn2(vf, rd, rn, rm); break;
2713     default:
2714       VIXL_UNIMPLEMENTED();
2715   }
2716 }
2717 
2718 
VisitNEONAcrossLanes(const Instruction * instr)2719 void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
2720   NEONFormatDecoder nfd(instr);
2721 
2722   SimVRegister& rd = vreg(instr->Rd());
2723   SimVRegister& rn = vreg(instr->Rn());
2724 
2725   // The input operand's VectorFormat is passed for these instructions.
2726   if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
2727     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
2728 
2729     switch (instr->Mask(NEONAcrossLanesFPMask)) {
2730       case NEON_FMAXV: fmaxv(vf, rd, rn); break;
2731       case NEON_FMINV: fminv(vf, rd, rn); break;
2732       case NEON_FMAXNMV: fmaxnmv(vf, rd, rn); break;
2733       case NEON_FMINNMV: fminnmv(vf, rd, rn); break;
2734       default:
2735         VIXL_UNIMPLEMENTED();
2736     }
2737   } else {
2738     VectorFormat vf = nfd.GetVectorFormat();
2739 
2740     switch (instr->Mask(NEONAcrossLanesMask)) {
2741       case NEON_ADDV:   addv(vf, rd, rn); break;
2742       case NEON_SMAXV:  smaxv(vf, rd, rn); break;
2743       case NEON_SMINV:  sminv(vf, rd, rn); break;
2744       case NEON_UMAXV:  umaxv(vf, rd, rn); break;
2745       case NEON_UMINV:  uminv(vf, rd, rn); break;
2746       case NEON_SADDLV: saddlv(vf, rd, rn); break;
2747       case NEON_UADDLV: uaddlv(vf, rd, rn); break;
2748       default:
2749         VIXL_UNIMPLEMENTED();
2750     }
2751   }
2752 }
2753 
2754 
VisitNEONByIndexedElement(const Instruction * instr)2755 void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
2756   NEONFormatDecoder nfd(instr);
2757   VectorFormat vf_r = nfd.GetVectorFormat();
2758   VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
2759 
2760   SimVRegister& rd = vreg(instr->Rd());
2761   SimVRegister& rn = vreg(instr->Rn());
2762 
2763   ByElementOp Op = NULL;
2764 
2765   int rm_reg = instr->Rm();
2766   int index = (instr->NEONH() << 1) | instr->NEONL();
2767   if (instr->NEONSize() == 1) {
2768     rm_reg &= 0xf;
2769     index = (index << 1) | instr->NEONM();
2770   }
2771 
2772   switch (instr->Mask(NEONByIndexedElementMask)) {
2773     case NEON_MUL_byelement: Op = &Simulator::mul; vf = vf_r; break;
2774     case NEON_MLA_byelement: Op = &Simulator::mla; vf = vf_r; break;
2775     case NEON_MLS_byelement: Op = &Simulator::mls; vf = vf_r; break;
2776     case NEON_SQDMULH_byelement: Op = &Simulator::sqdmulh; vf = vf_r; break;
2777     case NEON_SQRDMULH_byelement: Op = &Simulator::sqrdmulh; vf = vf_r; break;
2778     case NEON_SMULL_byelement:
2779       if (instr->Mask(NEON_Q)) {
2780         Op = &Simulator::smull2;
2781       } else {
2782         Op = &Simulator::smull;
2783       }
2784       break;
2785     case NEON_UMULL_byelement:
2786       if (instr->Mask(NEON_Q)) {
2787         Op = &Simulator::umull2;
2788       } else {
2789         Op = &Simulator::umull;
2790       }
2791       break;
2792     case NEON_SMLAL_byelement:
2793       if (instr->Mask(NEON_Q)) {
2794         Op = &Simulator::smlal2;
2795       } else {
2796         Op = &Simulator::smlal;
2797       }
2798       break;
2799     case NEON_UMLAL_byelement:
2800       if (instr->Mask(NEON_Q)) {
2801         Op = &Simulator::umlal2;
2802       } else {
2803         Op = &Simulator::umlal;
2804       }
2805       break;
2806     case NEON_SMLSL_byelement:
2807       if (instr->Mask(NEON_Q)) {
2808         Op = &Simulator::smlsl2;
2809       } else {
2810         Op = &Simulator::smlsl;
2811       }
2812       break;
2813     case NEON_UMLSL_byelement:
2814       if (instr->Mask(NEON_Q)) {
2815         Op = &Simulator::umlsl2;
2816       } else {
2817         Op = &Simulator::umlsl;
2818       }
2819       break;
2820     case NEON_SQDMULL_byelement:
2821       if (instr->Mask(NEON_Q)) {
2822         Op = &Simulator::sqdmull2;
2823       } else {
2824         Op = &Simulator::sqdmull;
2825       }
2826       break;
2827     case NEON_SQDMLAL_byelement:
2828       if (instr->Mask(NEON_Q)) {
2829         Op = &Simulator::sqdmlal2;
2830       } else {
2831         Op = &Simulator::sqdmlal;
2832       }
2833       break;
2834     case NEON_SQDMLSL_byelement:
2835       if (instr->Mask(NEON_Q)) {
2836         Op = &Simulator::sqdmlsl2;
2837       } else {
2838         Op = &Simulator::sqdmlsl;
2839       }
2840       break;
2841     default:
2842       index = instr->NEONH();
2843       if ((instr->FPType() & 1) == 0) {
2844         index = (index << 1) | instr->NEONL();
2845       }
2846 
2847       vf = nfd.GetVectorFormat(nfd.FPFormatMap());
2848 
2849       switch (instr->Mask(NEONByIndexedElementFPMask)) {
2850         case NEON_FMUL_byelement: Op = &Simulator::fmul; break;
2851         case NEON_FMLA_byelement: Op = &Simulator::fmla; break;
2852         case NEON_FMLS_byelement: Op = &Simulator::fmls; break;
2853         case NEON_FMULX_byelement: Op = &Simulator::fmulx; break;
2854         default: VIXL_UNIMPLEMENTED();
2855       }
2856   }
2857 
2858   (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
2859 }
2860 
2861 
VisitNEONCopy(const Instruction * instr)2862 void Simulator::VisitNEONCopy(const Instruction* instr) {
2863   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
2864   VectorFormat vf = nfd.GetVectorFormat();
2865 
2866   SimVRegister& rd = vreg(instr->Rd());
2867   SimVRegister& rn = vreg(instr->Rn());
2868   int imm5 = instr->ImmNEON5();
2869   int tz = CountTrailingZeros(imm5, 32);
2870   int reg_index = imm5 >> (tz + 1);
2871 
2872   if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
2873     int imm4 = instr->ImmNEON4();
2874     int rn_index = imm4 >> tz;
2875     ins_element(vf, rd, reg_index, rn, rn_index);
2876   } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
2877     ins_immediate(vf, rd, reg_index, xreg(instr->Rn()));
2878   } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
2879     uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
2880     value &= MaxUintFromFormat(vf);
2881     set_xreg(instr->Rd(), value);
2882   } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
2883     int64_t value = LogicVRegister(rn).Int(vf, reg_index);
2884     if (instr->NEONQ()) {
2885       set_xreg(instr->Rd(), value);
2886     } else {
2887       set_wreg(instr->Rd(), (int32_t)value);
2888     }
2889   } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
2890     dup_element(vf, rd, rn, reg_index);
2891   } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
2892     dup_immediate(vf, rd, xreg(instr->Rn()));
2893   } else {
2894     VIXL_UNIMPLEMENTED();
2895   }
2896 }
2897 
2898 
VisitNEONExtract(const Instruction * instr)2899 void Simulator::VisitNEONExtract(const Instruction* instr) {
2900   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
2901   VectorFormat vf = nfd.GetVectorFormat();
2902   SimVRegister& rd = vreg(instr->Rd());
2903   SimVRegister& rn = vreg(instr->Rn());
2904   SimVRegister& rm = vreg(instr->Rm());
2905   if (instr->Mask(NEONExtractMask) == NEON_EXT) {
2906     int index = instr->ImmNEONExt();
2907     ext(vf, rd, rn, rm, index);
2908   } else {
2909     VIXL_UNIMPLEMENTED();
2910   }
2911 }
2912 
2913 
NEONLoadStoreMultiStructHelper(const Instruction * instr,AddrMode addr_mode)2914 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
2915                                                AddrMode addr_mode) {
2916   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2917   VectorFormat vf = nfd.GetVectorFormat();
2918 
2919   uint64_t addr_base = xreg(instr->Rn(), Reg31IsStackPointer);
2920   int reg_size = RegisterSizeInBytesFromFormat(vf);
2921 
2922   int reg[4];
2923   uint64_t addr[4];
2924   for (int i = 0; i < 4; i++) {
2925     reg[i] = (instr->Rt() + i) % kNumberOfVRegisters;
2926     addr[i] = addr_base + (i * reg_size);
2927   }
2928   int count = 1;
2929   bool log_read = true;
2930 
2931   Instr itype = instr->Mask(NEONLoadStoreMultiStructMask);
2932   if (((itype == NEON_LD1_1v) || (itype == NEON_LD1_2v) ||
2933        (itype == NEON_LD1_3v) || (itype == NEON_LD1_4v) ||
2934        (itype == NEON_ST1_1v) || (itype == NEON_ST1_2v) ||
2935        (itype == NEON_ST1_3v) || (itype == NEON_ST1_4v)) &&
2936       (instr->Bits(20, 16) != 0)) {
2937     VIXL_UNREACHABLE();
2938   }
2939 
2940   // We use the PostIndex mask here, as it works in this case for both Offset
2941   // and PostIndex addressing.
2942   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2943     case NEON_LD1_4v:
2944     case NEON_LD1_4v_post: ld1(vf, vreg(reg[3]), addr[3]); count++;
2945       VIXL_FALLTHROUGH();
2946     case NEON_LD1_3v:
2947     case NEON_LD1_3v_post: ld1(vf, vreg(reg[2]), addr[2]); count++;
2948       VIXL_FALLTHROUGH();
2949     case NEON_LD1_2v:
2950     case NEON_LD1_2v_post: ld1(vf, vreg(reg[1]), addr[1]); count++;
2951       VIXL_FALLTHROUGH();
2952     case NEON_LD1_1v:
2953     case NEON_LD1_1v_post:
2954       ld1(vf, vreg(reg[0]), addr[0]);
2955       log_read = true;
2956       break;
2957     case NEON_ST1_4v:
2958     case NEON_ST1_4v_post: st1(vf, vreg(reg[3]), addr[3]); count++;
2959       VIXL_FALLTHROUGH();
2960     case NEON_ST1_3v:
2961     case NEON_ST1_3v_post: st1(vf, vreg(reg[2]), addr[2]); count++;
2962       VIXL_FALLTHROUGH();
2963     case NEON_ST1_2v:
2964     case NEON_ST1_2v_post: st1(vf, vreg(reg[1]), addr[1]); count++;
2965       VIXL_FALLTHROUGH();
2966     case NEON_ST1_1v:
2967     case NEON_ST1_1v_post:
2968       st1(vf, vreg(reg[0]), addr[0]);
2969       log_read = false;
2970       break;
2971     case NEON_LD2_post:
2972     case NEON_LD2:
2973       ld2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
2974       count = 2;
2975       break;
2976     case NEON_ST2:
2977     case NEON_ST2_post:
2978       st2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
2979       count = 2;
2980       break;
2981     case NEON_LD3_post:
2982     case NEON_LD3:
2983       ld3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
2984       count = 3;
2985       break;
2986     case NEON_ST3:
2987     case NEON_ST3_post:
2988       st3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
2989       count = 3;
2990       break;
2991     case NEON_ST4:
2992     case NEON_ST4_post:
2993       st4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]),
2994           addr[0]);
2995       count = 4;
2996       break;
2997     case NEON_LD4_post:
2998     case NEON_LD4:
2999       ld4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]),
3000           addr[0]);
3001       count = 4;
3002       break;
3003     default: VIXL_UNIMPLEMENTED();
3004   }
3005 
3006   // Explicitly log the register update whilst we have type information.
3007   for (int i = 0; i < count; i++) {
3008     // For de-interleaving loads, only print the base address.
3009     int lane_size = LaneSizeInBytesFromFormat(vf);
3010     PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
3011         GetPrintRegisterFormatForSize(reg_size, lane_size));
3012     if (log_read) {
3013       LogVRead(addr_base, reg[i], format);
3014     } else {
3015       LogVWrite(addr_base, reg[i], format);
3016     }
3017   }
3018 
3019   if (addr_mode == PostIndex) {
3020     int rm = instr->Rm();
3021     // The immediate post index addressing mode is indicated by rm = 31.
3022     // The immediate is implied by the number of vector registers used.
3023     addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
3024                             : xreg(rm);
3025     set_xreg(instr->Rn(), addr_base);
3026   } else {
3027     VIXL_ASSERT(addr_mode == Offset);
3028   }
3029 }
3030 
3031 
VisitNEONLoadStoreMultiStruct(const Instruction * instr)3032 void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
3033   NEONLoadStoreMultiStructHelper(instr, Offset);
3034 }
3035 
3036 
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)3037 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
3038     const Instruction* instr) {
3039   NEONLoadStoreMultiStructHelper(instr, PostIndex);
3040 }
3041 
3042 
NEONLoadStoreSingleStructHelper(const Instruction * instr,AddrMode addr_mode)3043 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
3044                                                 AddrMode addr_mode) {
3045   uint64_t addr = xreg(instr->Rn(), Reg31IsStackPointer);
3046   int rt = instr->Rt();
3047 
3048   Instr itype = instr->Mask(NEONLoadStoreSingleStructMask);
3049   if (((itype == NEON_LD1_b) || (itype == NEON_LD1_h) ||
3050        (itype == NEON_LD1_s) || (itype == NEON_LD1_d)) &&
3051       (instr->Bits(20, 16) != 0)) {
3052     VIXL_UNREACHABLE();
3053   }
3054 
3055   // We use the PostIndex mask here, as it works in this case for both Offset
3056   // and PostIndex addressing.
3057   bool do_load = false;
3058 
3059   bool replicating = false;
3060 
3061   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3062   VectorFormat vf_t = nfd.GetVectorFormat();
3063 
3064   VectorFormat vf = kFormat16B;
3065   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3066     case NEON_LD1_b:
3067     case NEON_LD1_b_post:
3068     case NEON_LD2_b:
3069     case NEON_LD2_b_post:
3070     case NEON_LD3_b:
3071     case NEON_LD3_b_post:
3072     case NEON_LD4_b:
3073     case NEON_LD4_b_post: do_load = true;
3074       VIXL_FALLTHROUGH();
3075     case NEON_ST1_b:
3076     case NEON_ST1_b_post:
3077     case NEON_ST2_b:
3078     case NEON_ST2_b_post:
3079     case NEON_ST3_b:
3080     case NEON_ST3_b_post:
3081     case NEON_ST4_b:
3082     case NEON_ST4_b_post: break;
3083 
3084     case NEON_LD1_h:
3085     case NEON_LD1_h_post:
3086     case NEON_LD2_h:
3087     case NEON_LD2_h_post:
3088     case NEON_LD3_h:
3089     case NEON_LD3_h_post:
3090     case NEON_LD4_h:
3091     case NEON_LD4_h_post: do_load = true;
3092       VIXL_FALLTHROUGH();
3093     case NEON_ST1_h:
3094     case NEON_ST1_h_post:
3095     case NEON_ST2_h:
3096     case NEON_ST2_h_post:
3097     case NEON_ST3_h:
3098     case NEON_ST3_h_post:
3099     case NEON_ST4_h:
3100     case NEON_ST4_h_post: vf = kFormat8H; break;
3101     case NEON_LD1_s:
3102     case NEON_LD1_s_post:
3103     case NEON_LD2_s:
3104     case NEON_LD2_s_post:
3105     case NEON_LD3_s:
3106     case NEON_LD3_s_post:
3107     case NEON_LD4_s:
3108     case NEON_LD4_s_post: do_load = true;
3109       VIXL_FALLTHROUGH();
3110     case NEON_ST1_s:
3111     case NEON_ST1_s_post:
3112     case NEON_ST2_s:
3113     case NEON_ST2_s_post:
3114     case NEON_ST3_s:
3115     case NEON_ST3_s_post:
3116     case NEON_ST4_s:
3117     case NEON_ST4_s_post: {
3118       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3119       VIXL_STATIC_ASSERT(
3120           (NEON_LD1_s_post | (1 << NEONLSSize_offset)) == NEON_LD1_d_post);
3121       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3122       VIXL_STATIC_ASSERT(
3123           (NEON_ST1_s_post | (1 << NEONLSSize_offset)) == NEON_ST1_d_post);
3124       vf = ((instr->NEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
3125       break;
3126     }
3127 
3128     case NEON_LD1R:
3129     case NEON_LD1R_post:
3130     case NEON_LD2R:
3131     case NEON_LD2R_post:
3132     case NEON_LD3R:
3133     case NEON_LD3R_post:
3134     case NEON_LD4R:
3135     case NEON_LD4R_post: {
3136       vf = vf_t;
3137       do_load = true;
3138       replicating = true;
3139       break;
3140     }
3141     default: VIXL_UNIMPLEMENTED();
3142   }
3143 
3144   PrintRegisterFormat print_format =
3145       GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
3146   // Make sure that the print_format only includes a single lane.
3147   print_format =
3148       static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
3149 
3150   int esize = LaneSizeInBytesFromFormat(vf);
3151   int index_shift = LaneSizeInBytesLog2FromFormat(vf);
3152   int lane = instr->NEONLSIndex(index_shift);
3153   int scale = 0;
3154   int rt2 = (rt + 1) % kNumberOfVRegisters;
3155   int rt3 = (rt2 + 1) % kNumberOfVRegisters;
3156   int rt4 = (rt3 + 1) % kNumberOfVRegisters;
3157   switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
3158     case NEONLoadStoreSingle1:
3159       scale = 1;
3160       if (do_load) {
3161         if (replicating) {
3162           ld1r(vf, vreg(rt), addr);
3163         } else  {
3164           ld1(vf, vreg(rt), lane, addr);
3165         }
3166         LogVRead(addr, rt, print_format, lane);
3167       } else {
3168         st1(vf, vreg(rt), lane, addr);
3169         LogVWrite(addr, rt, print_format, lane);
3170       }
3171       break;
3172     case NEONLoadStoreSingle2:
3173       scale = 2;
3174       if (do_load) {
3175         if (replicating) {
3176           ld2r(vf, vreg(rt), vreg(rt2), addr);
3177         } else {
3178           ld2(vf, vreg(rt), vreg(rt2), lane, addr);
3179         }
3180         LogVRead(addr, rt, print_format, lane);
3181         LogVRead(addr + esize, rt2, print_format, lane);
3182       } else {
3183         st2(vf, vreg(rt), vreg(rt2), lane, addr);
3184         LogVWrite(addr, rt, print_format, lane);
3185         LogVWrite(addr + esize, rt2, print_format, lane);
3186       }
3187       break;
3188     case NEONLoadStoreSingle3:
3189       scale = 3;
3190       if (do_load) {
3191         if (replicating) {
3192           ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
3193         } else {
3194           ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
3195         }
3196         LogVRead(addr, rt, print_format, lane);
3197         LogVRead(addr + esize, rt2, print_format, lane);
3198         LogVRead(addr + (2 * esize), rt3, print_format, lane);
3199       } else {
3200         st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
3201         LogVWrite(addr, rt, print_format, lane);
3202         LogVWrite(addr + esize, rt2, print_format, lane);
3203         LogVWrite(addr + (2 * esize), rt3, print_format, lane);
3204       }
3205       break;
3206     case NEONLoadStoreSingle4:
3207       scale = 4;
3208       if (do_load) {
3209         if (replicating) {
3210           ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
3211         } else {
3212           ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
3213         }
3214         LogVRead(addr, rt, print_format, lane);
3215         LogVRead(addr + esize, rt2, print_format, lane);
3216         LogVRead(addr + (2 * esize), rt3, print_format, lane);
3217         LogVRead(addr + (3 * esize), rt4, print_format, lane);
3218       } else {
3219         st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
3220         LogVWrite(addr, rt, print_format, lane);
3221         LogVWrite(addr + esize, rt2, print_format, lane);
3222         LogVWrite(addr + (2 * esize), rt3, print_format, lane);
3223         LogVWrite(addr + (3 * esize), rt4, print_format, lane);
3224       }
3225       break;
3226     default: VIXL_UNIMPLEMENTED();
3227   }
3228 
3229   if (addr_mode == PostIndex) {
3230     int rm = instr->Rm();
3231     int lane_size = LaneSizeInBytesFromFormat(vf);
3232     set_xreg(instr->Rn(), addr + ((rm == 31) ? (scale * lane_size) : xreg(rm)));
3233   }
3234 }
3235 
3236 
VisitNEONLoadStoreSingleStruct(const Instruction * instr)3237 void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
3238   NEONLoadStoreSingleStructHelper(instr, Offset);
3239 }
3240 
3241 
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)3242 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
3243     const Instruction* instr) {
3244   NEONLoadStoreSingleStructHelper(instr, PostIndex);
3245 }
3246 
3247 
VisitNEONModifiedImmediate(const Instruction * instr)3248 void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
3249   SimVRegister& rd = vreg(instr->Rd());
3250   int cmode = instr->NEONCmode();
3251   int cmode_3_1 = (cmode >> 1) & 7;
3252   int cmode_3 = (cmode >> 3) & 1;
3253   int cmode_2 = (cmode >> 2) & 1;
3254   int cmode_1 = (cmode >> 1) & 1;
3255   int cmode_0 = cmode & 1;
3256   int q = instr->NEONQ();
3257   int op_bit = instr->NEONModImmOp();
3258   uint64_t imm8  = instr->ImmNEONabcdefgh();
3259 
3260   // Find the format and immediate value
3261   uint64_t imm = 0;
3262   VectorFormat vform = kFormatUndefined;
3263   switch (cmode_3_1) {
3264     case 0x0:
3265     case 0x1:
3266     case 0x2:
3267     case 0x3:
3268       vform = (q == 1) ? kFormat4S : kFormat2S;
3269       imm = imm8 << (8 * cmode_3_1);
3270       break;
3271     case 0x4:
3272     case 0x5:
3273       vform = (q == 1) ? kFormat8H : kFormat4H;
3274       imm = imm8 << (8 * cmode_1);
3275       break;
3276     case 0x6:
3277       vform = (q == 1) ? kFormat4S : kFormat2S;
3278       if (cmode_0 == 0) {
3279         imm = imm8 << 8  | 0x000000ff;
3280       } else {
3281         imm = imm8 << 16 | 0x0000ffff;
3282       }
3283       break;
3284     case 0x7:
3285       if (cmode_0 == 0 && op_bit == 0) {
3286         vform = q ? kFormat16B : kFormat8B;
3287         imm = imm8;
3288       } else if (cmode_0 == 0 && op_bit == 1) {
3289         vform = q ? kFormat2D : kFormat1D;
3290         imm = 0;
3291         for (int i = 0; i < 8; ++i) {
3292           if (imm8 & (1ULL << i)) {
3293             imm |= (UINT64_C(0xff) << (8 * i));
3294           }
3295         }
3296       } else {  // cmode_0 == 1, cmode == 0xf.
3297         if (op_bit == 0) {
3298           vform = q ? kFormat4S : kFormat2S;
3299           imm = FloatToRawbits(instr->ImmNEONFP32());
3300         } else if (q == 1) {
3301           vform = kFormat2D;
3302           imm = DoubleToRawbits(instr->ImmNEONFP64());
3303         } else {
3304           VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
3305           VisitUnallocated(instr);
3306         }
3307       }
3308       break;
3309     default: VIXL_UNREACHABLE(); break;
3310   }
3311 
3312   // Find the operation
3313   NEONModifiedImmediateOp op;
3314   if (cmode_3 == 0) {
3315     if (cmode_0 == 0) {
3316       op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
3317     } else {  // cmode<0> == '1'
3318       op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
3319     }
3320   } else {  // cmode<3> == '1'
3321     if (cmode_2 == 0) {
3322       if (cmode_0 == 0) {
3323         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
3324       } else {  // cmode<0> == '1'
3325         op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
3326       }
3327     } else {  // cmode<2> == '1'
3328        if (cmode_1 == 0) {
3329          op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
3330        } else {  // cmode<1> == '1'
3331          if (cmode_0 == 0) {
3332            op = NEONModifiedImmediate_MOVI;
3333          } else {  // cmode<0> == '1'
3334            op = NEONModifiedImmediate_MOVI;
3335          }
3336        }
3337     }
3338   }
3339 
3340   // Call the logic function
3341   if (op == NEONModifiedImmediate_ORR) {
3342     orr(vform, rd, rd, imm);
3343   } else if (op == NEONModifiedImmediate_BIC) {
3344     bic(vform, rd, rd, imm);
3345   } else  if (op == NEONModifiedImmediate_MOVI) {
3346     movi(vform, rd, imm);
3347   } else if (op == NEONModifiedImmediate_MVNI) {
3348     mvni(vform, rd, imm);
3349   } else {
3350     VisitUnimplemented(instr);
3351   }
3352 }
3353 
3354 
VisitNEONScalar2RegMisc(const Instruction * instr)3355 void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
3356   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
3357   VectorFormat vf = nfd.GetVectorFormat();
3358 
3359   SimVRegister& rd = vreg(instr->Rd());
3360   SimVRegister& rn = vreg(instr->Rn());
3361 
3362   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
3363     // These instructions all use a two bit size field, except NOT and RBIT,
3364     // which use the field to encode the operation.
3365     switch (instr->Mask(NEONScalar2RegMiscMask)) {
3366       case NEON_CMEQ_zero_scalar: cmp(vf, rd, rn, 0, eq); break;
3367       case NEON_CMGE_zero_scalar: cmp(vf, rd, rn, 0, ge); break;
3368       case NEON_CMGT_zero_scalar: cmp(vf, rd, rn, 0, gt); break;
3369       case NEON_CMLT_zero_scalar: cmp(vf, rd, rn, 0, lt); break;
3370       case NEON_CMLE_zero_scalar: cmp(vf, rd, rn, 0, le); break;
3371       case NEON_ABS_scalar:       abs(vf, rd, rn); break;
3372       case NEON_SQABS_scalar:     abs(vf, rd, rn).SignedSaturate(vf); break;
3373       case NEON_NEG_scalar:       neg(vf, rd, rn); break;
3374       case NEON_SQNEG_scalar:     neg(vf, rd, rn).SignedSaturate(vf); break;
3375       case NEON_SUQADD_scalar:    suqadd(vf, rd, rn); break;
3376       case NEON_USQADD_scalar:    usqadd(vf, rd, rn); break;
3377       default: VIXL_UNIMPLEMENTED(); break;
3378     }
3379   } else {
3380     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
3381     FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3382 
3383     // These instructions all use a one bit size field, except SQXTUN, SQXTN
3384     // and UQXTN, which use a two bit size field.
3385     switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
3386       case NEON_FRECPE_scalar:     frecpe(fpf, rd, rn, fpcr_rounding); break;
3387       case NEON_FRECPX_scalar:     frecpx(fpf, rd, rn); break;
3388       case NEON_FRSQRTE_scalar:    frsqrte(fpf, rd, rn); break;
3389       case NEON_FCMGT_zero_scalar: fcmp_zero(fpf, rd, rn, gt); break;
3390       case NEON_FCMGE_zero_scalar: fcmp_zero(fpf, rd, rn, ge); break;
3391       case NEON_FCMEQ_zero_scalar: fcmp_zero(fpf, rd, rn, eq); break;
3392       case NEON_FCMLE_zero_scalar: fcmp_zero(fpf, rd, rn, le); break;
3393       case NEON_FCMLT_zero_scalar: fcmp_zero(fpf, rd, rn, lt); break;
3394       case NEON_SCVTF_scalar:      scvtf(fpf, rd, rn, 0, fpcr_rounding); break;
3395       case NEON_UCVTF_scalar:      ucvtf(fpf, rd, rn, 0, fpcr_rounding); break;
3396       case NEON_FCVTNS_scalar: fcvts(fpf, rd, rn, FPTieEven); break;
3397       case NEON_FCVTNU_scalar: fcvtu(fpf, rd, rn, FPTieEven); break;
3398       case NEON_FCVTPS_scalar: fcvts(fpf, rd, rn, FPPositiveInfinity); break;
3399       case NEON_FCVTPU_scalar: fcvtu(fpf, rd, rn, FPPositiveInfinity); break;
3400       case NEON_FCVTMS_scalar: fcvts(fpf, rd, rn, FPNegativeInfinity); break;
3401       case NEON_FCVTMU_scalar: fcvtu(fpf, rd, rn, FPNegativeInfinity); break;
3402       case NEON_FCVTZS_scalar: fcvts(fpf, rd, rn, FPZero); break;
3403       case NEON_FCVTZU_scalar: fcvtu(fpf, rd, rn, FPZero); break;
3404       case NEON_FCVTAS_scalar: fcvts(fpf, rd, rn, FPTieAway); break;
3405       case NEON_FCVTAU_scalar: fcvtu(fpf, rd, rn, FPTieAway); break;
3406       case NEON_FCVTXN_scalar:
3407         // Unlike all of the other FP instructions above, fcvtxn encodes dest
3408         // size S as size<0>=1. There's only one case, so we ignore the form.
3409         VIXL_ASSERT(instr->Bit(22) == 1);
3410         fcvtxn(kFormatS, rd, rn);
3411         break;
3412       default:
3413         switch (instr->Mask(NEONScalar2RegMiscMask)) {
3414           case NEON_SQXTN_scalar:  sqxtn(vf, rd, rn); break;
3415           case NEON_UQXTN_scalar:  uqxtn(vf, rd, rn); break;
3416           case NEON_SQXTUN_scalar: sqxtun(vf, rd, rn); break;
3417           default:
3418             VIXL_UNIMPLEMENTED();
3419         }
3420     }
3421   }
3422 }
3423 
3424 
VisitNEONScalar3Diff(const Instruction * instr)3425 void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
3426   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
3427   VectorFormat vf = nfd.GetVectorFormat();
3428 
3429   SimVRegister& rd = vreg(instr->Rd());
3430   SimVRegister& rn = vreg(instr->Rn());
3431   SimVRegister& rm = vreg(instr->Rm());
3432   switch (instr->Mask(NEONScalar3DiffMask)) {
3433     case NEON_SQDMLAL_scalar: sqdmlal(vf, rd, rn, rm); break;
3434     case NEON_SQDMLSL_scalar: sqdmlsl(vf, rd, rn, rm); break;
3435     case NEON_SQDMULL_scalar: sqdmull(vf, rd, rn, rm); break;
3436     default:
3437       VIXL_UNIMPLEMENTED();
3438   }
3439 }
3440 
3441 
VisitNEONScalar3Same(const Instruction * instr)3442 void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
3443   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
3444   VectorFormat vf = nfd.GetVectorFormat();
3445 
3446   SimVRegister& rd = vreg(instr->Rd());
3447   SimVRegister& rn = vreg(instr->Rn());
3448   SimVRegister& rm = vreg(instr->Rm());
3449 
3450   if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
3451     vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
3452     switch (instr->Mask(NEONScalar3SameFPMask)) {
3453       case NEON_FMULX_scalar:   fmulx(vf, rd, rn, rm); break;
3454       case NEON_FACGE_scalar:   fabscmp(vf, rd, rn, rm, ge); break;
3455       case NEON_FACGT_scalar:   fabscmp(vf, rd, rn, rm, gt); break;
3456       case NEON_FCMEQ_scalar:   fcmp(vf, rd, rn, rm, eq); break;
3457       case NEON_FCMGE_scalar:   fcmp(vf, rd, rn, rm, ge); break;
3458       case NEON_FCMGT_scalar:   fcmp(vf, rd, rn, rm, gt); break;
3459       case NEON_FRECPS_scalar:  frecps(vf, rd, rn, rm); break;
3460       case NEON_FRSQRTS_scalar: frsqrts(vf, rd, rn, rm); break;
3461       case NEON_FABD_scalar:    fabd(vf, rd, rn, rm); break;
3462       default:
3463         VIXL_UNIMPLEMENTED();
3464     }
3465   } else {
3466     switch (instr->Mask(NEONScalar3SameMask)) {
3467       case NEON_ADD_scalar:      add(vf, rd, rn, rm); break;
3468       case NEON_SUB_scalar:      sub(vf, rd, rn, rm); break;
3469       case NEON_CMEQ_scalar:     cmp(vf, rd, rn, rm, eq); break;
3470       case NEON_CMGE_scalar:     cmp(vf, rd, rn, rm, ge); break;
3471       case NEON_CMGT_scalar:     cmp(vf, rd, rn, rm, gt); break;
3472       case NEON_CMHI_scalar:     cmp(vf, rd, rn, rm, hi); break;
3473       case NEON_CMHS_scalar:     cmp(vf, rd, rn, rm, hs); break;
3474       case NEON_CMTST_scalar:    cmptst(vf, rd, rn, rm); break;
3475       case NEON_USHL_scalar:     ushl(vf, rd, rn, rm); break;
3476       case NEON_SSHL_scalar:     sshl(vf, rd, rn, rm); break;
3477       case NEON_SQDMULH_scalar:  sqdmulh(vf, rd, rn, rm); break;
3478       case NEON_SQRDMULH_scalar: sqrdmulh(vf, rd, rn, rm); break;
3479       case NEON_UQADD_scalar:
3480         add(vf, rd, rn, rm).UnsignedSaturate(vf);
3481         break;
3482       case NEON_SQADD_scalar:
3483         add(vf, rd, rn, rm).SignedSaturate(vf);
3484         break;
3485       case NEON_UQSUB_scalar:
3486         sub(vf, rd, rn, rm).UnsignedSaturate(vf);
3487         break;
3488       case NEON_SQSUB_scalar:
3489         sub(vf, rd, rn, rm).SignedSaturate(vf);
3490         break;
3491       case NEON_UQSHL_scalar:
3492         ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
3493         break;
3494       case NEON_SQSHL_scalar:
3495         sshl(vf, rd, rn, rm).SignedSaturate(vf);
3496         break;
3497       case NEON_URSHL_scalar:
3498         ushl(vf, rd, rn, rm).Round(vf);
3499         break;
3500       case NEON_SRSHL_scalar:
3501         sshl(vf, rd, rn, rm).Round(vf);
3502         break;
3503       case NEON_UQRSHL_scalar:
3504         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
3505         break;
3506       case NEON_SQRSHL_scalar:
3507         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
3508         break;
3509       default:
3510         VIXL_UNIMPLEMENTED();
3511     }
3512   }
3513 }
3514 
3515 
VisitNEONScalarByIndexedElement(const Instruction * instr)3516 void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
3517   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
3518   VectorFormat vf = nfd.GetVectorFormat();
3519   VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
3520 
3521   SimVRegister& rd = vreg(instr->Rd());
3522   SimVRegister& rn = vreg(instr->Rn());
3523   ByElementOp Op = NULL;
3524 
3525   int rm_reg = instr->Rm();
3526   int index = (instr->NEONH() << 1) | instr->NEONL();
3527   if (instr->NEONSize() == 1) {
3528     rm_reg &= 0xf;
3529     index = (index << 1) | instr->NEONM();
3530   }
3531 
3532   switch (instr->Mask(NEONScalarByIndexedElementMask)) {
3533     case NEON_SQDMULL_byelement_scalar: Op = &Simulator::sqdmull; break;
3534     case NEON_SQDMLAL_byelement_scalar: Op = &Simulator::sqdmlal; break;
3535     case NEON_SQDMLSL_byelement_scalar: Op = &Simulator::sqdmlsl; break;
3536     case NEON_SQDMULH_byelement_scalar:
3537       Op = &Simulator::sqdmulh;
3538       vf = vf_r;
3539       break;
3540     case NEON_SQRDMULH_byelement_scalar:
3541       Op = &Simulator::sqrdmulh;
3542       vf = vf_r;
3543       break;
3544     default:
3545       vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
3546       index = instr->NEONH();
3547       if ((instr->FPType() & 1) == 0) {
3548         index = (index << 1) | instr->NEONL();
3549       }
3550       switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
3551         case NEON_FMUL_byelement_scalar: Op = &Simulator::fmul; break;
3552         case NEON_FMLA_byelement_scalar: Op = &Simulator::fmla; break;
3553         case NEON_FMLS_byelement_scalar: Op = &Simulator::fmls; break;
3554         case NEON_FMULX_byelement_scalar: Op = &Simulator::fmulx; break;
3555         default: VIXL_UNIMPLEMENTED();
3556       }
3557   }
3558 
3559   (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
3560 }
3561 
3562 
VisitNEONScalarCopy(const Instruction * instr)3563 void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
3564   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
3565   VectorFormat vf = nfd.GetVectorFormat();
3566 
3567   SimVRegister& rd = vreg(instr->Rd());
3568   SimVRegister& rn = vreg(instr->Rn());
3569 
3570   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
3571     int imm5 = instr->ImmNEON5();
3572     int tz = CountTrailingZeros(imm5, 32);
3573     int rn_index = imm5 >> (tz + 1);
3574     dup_element(vf, rd, rn, rn_index);
3575   } else {
3576     VIXL_UNIMPLEMENTED();
3577   }
3578 }
3579 
3580 
VisitNEONScalarPairwise(const Instruction * instr)3581 void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
3582   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
3583   VectorFormat vf = nfd.GetVectorFormat();
3584 
3585   SimVRegister& rd = vreg(instr->Rd());
3586   SimVRegister& rn = vreg(instr->Rn());
3587   switch (instr->Mask(NEONScalarPairwiseMask)) {
3588     case NEON_ADDP_scalar:    addp(vf, rd, rn); break;
3589     case NEON_FADDP_scalar:   faddp(vf, rd, rn); break;
3590     case NEON_FMAXP_scalar:   fmaxp(vf, rd, rn); break;
3591     case NEON_FMAXNMP_scalar: fmaxnmp(vf, rd, rn); break;
3592     case NEON_FMINP_scalar:   fminp(vf, rd, rn); break;
3593     case NEON_FMINNMP_scalar: fminnmp(vf, rd, rn); break;
3594     default:
3595       VIXL_UNIMPLEMENTED();
3596   }
3597 }
3598 
3599 
VisitNEONScalarShiftImmediate(const Instruction * instr)3600 void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
3601   SimVRegister& rd = vreg(instr->Rd());
3602   SimVRegister& rn = vreg(instr->Rn());
3603   FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3604 
3605   static const NEONFormatMap map = {
3606     {22, 21, 20, 19},
3607     {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S,
3608      NF_D,     NF_D, NF_D, NF_D, NF_D, NF_D, NF_D, NF_D}
3609   };
3610   NEONFormatDecoder nfd(instr, &map);
3611   VectorFormat vf = nfd.GetVectorFormat();
3612 
3613   int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
3614   int immhimmb = instr->ImmNEONImmhImmb();
3615   int right_shift = (16 << highestSetBit) - immhimmb;
3616   int left_shift = immhimmb - (8 << highestSetBit);
3617   switch (instr->Mask(NEONScalarShiftImmediateMask)) {
3618     case NEON_SHL_scalar:       shl(vf, rd, rn, left_shift); break;
3619     case NEON_SLI_scalar:       sli(vf, rd, rn, left_shift); break;
3620     case NEON_SQSHL_imm_scalar: sqshl(vf, rd, rn, left_shift); break;
3621     case NEON_UQSHL_imm_scalar: uqshl(vf, rd, rn, left_shift); break;
3622     case NEON_SQSHLU_scalar:    sqshlu(vf, rd, rn, left_shift); break;
3623     case NEON_SRI_scalar:       sri(vf, rd, rn, right_shift); break;
3624     case NEON_SSHR_scalar:      sshr(vf, rd, rn, right_shift); break;
3625     case NEON_USHR_scalar:      ushr(vf, rd, rn, right_shift); break;
3626     case NEON_SRSHR_scalar:     sshr(vf, rd, rn, right_shift).Round(vf); break;
3627     case NEON_URSHR_scalar:     ushr(vf, rd, rn, right_shift).Round(vf); break;
3628     case NEON_SSRA_scalar:      ssra(vf, rd, rn, right_shift); break;
3629     case NEON_USRA_scalar:      usra(vf, rd, rn, right_shift); break;
3630     case NEON_SRSRA_scalar:     srsra(vf, rd, rn, right_shift); break;
3631     case NEON_URSRA_scalar:     ursra(vf, rd, rn, right_shift); break;
3632     case NEON_UQSHRN_scalar:    uqshrn(vf, rd, rn, right_shift); break;
3633     case NEON_UQRSHRN_scalar:   uqrshrn(vf, rd, rn, right_shift); break;
3634     case NEON_SQSHRN_scalar:    sqshrn(vf, rd, rn, right_shift); break;
3635     case NEON_SQRSHRN_scalar:   sqrshrn(vf, rd, rn, right_shift); break;
3636     case NEON_SQSHRUN_scalar:   sqshrun(vf, rd, rn, right_shift); break;
3637     case NEON_SQRSHRUN_scalar:  sqrshrun(vf, rd, rn, right_shift); break;
3638     case NEON_FCVTZS_imm_scalar: fcvts(vf, rd, rn, FPZero, right_shift); break;
3639     case NEON_FCVTZU_imm_scalar: fcvtu(vf, rd, rn, FPZero, right_shift); break;
3640     case NEON_SCVTF_imm_scalar:
3641       scvtf(vf, rd, rn, right_shift, fpcr_rounding);
3642       break;
3643     case NEON_UCVTF_imm_scalar:
3644       ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
3645       break;
3646     default:
3647       VIXL_UNIMPLEMENTED();
3648   }
3649 }
3650 
3651 
VisitNEONShiftImmediate(const Instruction * instr)3652 void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
3653   SimVRegister& rd = vreg(instr->Rd());
3654   SimVRegister& rn = vreg(instr->Rn());
3655   FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3656 
3657   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
3658   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
3659   static const NEONFormatMap map = {
3660     {22, 21, 20, 19, 30},
3661     {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B, NF_4H,    NF_8H, NF_4H,    NF_8H,
3662      NF_2S,    NF_4S,    NF_2S,    NF_4S,  NF_2S,    NF_4S, NF_2S,    NF_4S,
3663      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
3664      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}
3665   };
3666   NEONFormatDecoder nfd(instr, &map);
3667   VectorFormat vf = nfd.GetVectorFormat();
3668 
3669   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
3670   static const NEONFormatMap map_l = {
3671     {22, 21, 20, 19},
3672     {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}
3673   };
3674   VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
3675 
3676   int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
3677   int immhimmb = instr->ImmNEONImmhImmb();
3678   int right_shift = (16 << highestSetBit) - immhimmb;
3679   int left_shift = immhimmb - (8 << highestSetBit);
3680 
3681   switch (instr->Mask(NEONShiftImmediateMask)) {
3682     case NEON_SHL:    shl(vf, rd, rn, left_shift); break;
3683     case NEON_SLI:    sli(vf, rd, rn, left_shift); break;
3684     case NEON_SQSHLU: sqshlu(vf, rd, rn, left_shift); break;
3685     case NEON_SRI:    sri(vf, rd, rn, right_shift); break;
3686     case NEON_SSHR:   sshr(vf, rd, rn, right_shift); break;
3687     case NEON_USHR:   ushr(vf, rd, rn, right_shift); break;
3688     case NEON_SRSHR:  sshr(vf, rd, rn, right_shift).Round(vf); break;
3689     case NEON_URSHR:  ushr(vf, rd, rn, right_shift).Round(vf); break;
3690     case NEON_SSRA:   ssra(vf, rd, rn, right_shift); break;
3691     case NEON_USRA:   usra(vf, rd, rn, right_shift); break;
3692     case NEON_SRSRA:  srsra(vf, rd, rn, right_shift); break;
3693     case NEON_URSRA:  ursra(vf, rd, rn, right_shift); break;
3694     case NEON_SQSHL_imm: sqshl(vf, rd, rn, left_shift); break;
3695     case NEON_UQSHL_imm: uqshl(vf, rd, rn, left_shift); break;
3696     case NEON_SCVTF_imm: scvtf(vf, rd, rn, right_shift, fpcr_rounding); break;
3697     case NEON_UCVTF_imm: ucvtf(vf, rd, rn, right_shift, fpcr_rounding); break;
3698     case NEON_FCVTZS_imm: fcvts(vf, rd, rn, FPZero, right_shift); break;
3699     case NEON_FCVTZU_imm: fcvtu(vf, rd, rn, FPZero, right_shift); break;
3700     case NEON_SSHLL:
3701       vf = vf_l;
3702       if (instr->Mask(NEON_Q)) {
3703         sshll2(vf, rd, rn, left_shift);
3704       } else {
3705         sshll(vf, rd, rn, left_shift);
3706       }
3707       break;
3708     case NEON_USHLL:
3709       vf = vf_l;
3710       if (instr->Mask(NEON_Q)) {
3711         ushll2(vf, rd, rn, left_shift);
3712       } else {
3713         ushll(vf, rd, rn, left_shift);
3714       }
3715       break;
3716     case NEON_SHRN:
3717       if (instr->Mask(NEON_Q)) {
3718         shrn2(vf, rd, rn, right_shift);
3719       } else {
3720         shrn(vf, rd, rn, right_shift);
3721       }
3722       break;
3723     case NEON_RSHRN:
3724       if (instr->Mask(NEON_Q)) {
3725         rshrn2(vf, rd, rn, right_shift);
3726       } else {
3727         rshrn(vf, rd, rn, right_shift);
3728       }
3729       break;
3730     case NEON_UQSHRN:
3731       if (instr->Mask(NEON_Q)) {
3732         uqshrn2(vf, rd, rn, right_shift);
3733       } else {
3734         uqshrn(vf, rd, rn, right_shift);
3735       }
3736       break;
3737     case NEON_UQRSHRN:
3738       if (instr->Mask(NEON_Q)) {
3739         uqrshrn2(vf, rd, rn, right_shift);
3740       } else {
3741         uqrshrn(vf, rd, rn, right_shift);
3742       }
3743       break;
3744     case NEON_SQSHRN:
3745       if (instr->Mask(NEON_Q)) {
3746         sqshrn2(vf, rd, rn, right_shift);
3747       } else {
3748         sqshrn(vf, rd, rn, right_shift);
3749       }
3750       break;
3751     case NEON_SQRSHRN:
3752       if (instr->Mask(NEON_Q)) {
3753         sqrshrn2(vf, rd, rn, right_shift);
3754       } else {
3755         sqrshrn(vf, rd, rn, right_shift);
3756       }
3757       break;
3758     case NEON_SQSHRUN:
3759       if (instr->Mask(NEON_Q)) {
3760         sqshrun2(vf, rd, rn, right_shift);
3761       } else {
3762         sqshrun(vf, rd, rn, right_shift);
3763       }
3764       break;
3765     case NEON_SQRSHRUN:
3766       if (instr->Mask(NEON_Q)) {
3767         sqrshrun2(vf, rd, rn, right_shift);
3768       } else {
3769         sqrshrun(vf, rd, rn, right_shift);
3770       }
3771       break;
3772     default:
3773       VIXL_UNIMPLEMENTED();
3774   }
3775 }
3776 
3777 
VisitNEONTable(const Instruction * instr)3778 void Simulator::VisitNEONTable(const Instruction* instr) {
3779   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3780   VectorFormat vf = nfd.GetVectorFormat();
3781 
3782   SimVRegister& rd = vreg(instr->Rd());
3783   SimVRegister& rn = vreg(instr->Rn());
3784   SimVRegister& rn2 = vreg((instr->Rn() + 1) % kNumberOfVRegisters);
3785   SimVRegister& rn3 = vreg((instr->Rn() + 2) % kNumberOfVRegisters);
3786   SimVRegister& rn4 = vreg((instr->Rn() + 3) % kNumberOfVRegisters);
3787   SimVRegister& rm = vreg(instr->Rm());
3788 
3789   switch (instr->Mask(NEONTableMask)) {
3790     case NEON_TBL_1v: tbl(vf, rd, rn, rm); break;
3791     case NEON_TBL_2v: tbl(vf, rd, rn, rn2, rm); break;
3792     case NEON_TBL_3v: tbl(vf, rd, rn, rn2, rn3, rm); break;
3793     case NEON_TBL_4v: tbl(vf, rd, rn, rn2, rn3, rn4, rm); break;
3794     case NEON_TBX_1v: tbx(vf, rd, rn, rm); break;
3795     case NEON_TBX_2v: tbx(vf, rd, rn, rn2, rm); break;
3796     case NEON_TBX_3v: tbx(vf, rd, rn, rn2, rn3, rm); break;
3797     case NEON_TBX_4v: tbx(vf, rd, rn, rn2, rn3, rn4, rm); break;
3798     default:
3799       VIXL_UNIMPLEMENTED();
3800   }
3801 }
3802 
3803 
VisitNEONPerm(const Instruction * instr)3804 void Simulator::VisitNEONPerm(const Instruction* instr) {
3805   NEONFormatDecoder nfd(instr);
3806   VectorFormat vf = nfd.GetVectorFormat();
3807 
3808   SimVRegister& rd = vreg(instr->Rd());
3809   SimVRegister& rn = vreg(instr->Rn());
3810   SimVRegister& rm = vreg(instr->Rm());
3811 
3812   switch (instr->Mask(NEONPermMask)) {
3813     case NEON_TRN1: trn1(vf, rd, rn, rm); break;
3814     case NEON_TRN2: trn2(vf, rd, rn, rm); break;
3815     case NEON_UZP1: uzp1(vf, rd, rn, rm); break;
3816     case NEON_UZP2: uzp2(vf, rd, rn, rm); break;
3817     case NEON_ZIP1: zip1(vf, rd, rn, rm); break;
3818     case NEON_ZIP2: zip2(vf, rd, rn, rm); break;
3819     default:
3820       VIXL_UNIMPLEMENTED();
3821   }
3822 }
3823 
3824 
DoUnreachable(const Instruction * instr)3825 void Simulator::DoUnreachable(const Instruction* instr) {
3826   VIXL_ASSERT(instr->InstructionBits() == UNDEFINED_INST_PATTERN);
3827 
3828   fprintf(stream_, "Hit UNREACHABLE marker at pc=%p.\n",
3829           reinterpret_cast<const void*>(instr));
3830   abort();
3831 }
3832 
3833 
DoTrace(const Instruction * instr)3834 void Simulator::DoTrace(const Instruction* instr) {
3835   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3836               (instr->ImmException() == kTraceOpcode));
3837 
3838   // Read the arguments encoded inline in the instruction stream.
3839   uint32_t parameters;
3840   uint32_t command;
3841 
3842   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
3843   memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
3844   memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
3845 
3846   switch (command) {
3847     case TRACE_ENABLE:
3848       set_trace_parameters(trace_parameters() | parameters);
3849       break;
3850     case TRACE_DISABLE:
3851       set_trace_parameters(trace_parameters() & ~parameters);
3852       break;
3853     default:
3854       VIXL_UNREACHABLE();
3855   }
3856 
3857   set_pc(instr->InstructionAtOffset(kTraceLength));
3858 }
3859 
3860 
DoLog(const Instruction * instr)3861 void Simulator::DoLog(const Instruction* instr) {
3862   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3863               (instr->ImmException() == kLogOpcode));
3864 
3865   // Read the arguments encoded inline in the instruction stream.
3866   uint32_t parameters;
3867 
3868   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
3869   memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
3870 
3871   // We don't support a one-shot LOG_DISASM.
3872   VIXL_ASSERT((parameters & LOG_DISASM) == 0);
3873   // Print the requested information.
3874   if (parameters & LOG_SYSREGS) PrintSystemRegisters();
3875   if (parameters & LOG_REGS) PrintRegisters();
3876   if (parameters & LOG_VREGS) PrintVRegisters();
3877 
3878   set_pc(instr->InstructionAtOffset(kLogLength));
3879 }
3880 
3881 
DoPrintf(const Instruction * instr)3882 void Simulator::DoPrintf(const Instruction* instr) {
3883   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3884               (instr->ImmException() == kPrintfOpcode));
3885 
3886   // Read the arguments encoded inline in the instruction stream.
3887   uint32_t arg_count;
3888   uint32_t arg_pattern_list;
3889   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
3890   memcpy(&arg_count,
3891          instr + kPrintfArgCountOffset,
3892          sizeof(arg_count));
3893   memcpy(&arg_pattern_list,
3894          instr + kPrintfArgPatternListOffset,
3895          sizeof(arg_pattern_list));
3896 
3897   VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
3898   VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
3899 
3900   // We need to call the host printf function with a set of arguments defined by
3901   // arg_pattern_list. Because we don't know the types and sizes of the
3902   // arguments, this is very difficult to do in a robust and portable way. To
3903   // work around the problem, we pick apart the format string, and print one
3904   // format placeholder at a time.
3905 
3906   // Allocate space for the format string. We take a copy, so we can modify it.
3907   // Leave enough space for one extra character per expected argument (plus the
3908   // '\0' termination).
3909   const char * format_base = reg<const char *>(0);
3910   VIXL_ASSERT(format_base != NULL);
3911   size_t length = strlen(format_base) + 1;
3912   char * const format = (char *)js_calloc(length + arg_count);
3913 
3914   // A list of chunks, each with exactly one format placeholder.
3915   const char * chunks[kPrintfMaxArgCount];
3916 
3917   // Copy the format string and search for format placeholders.
3918   uint32_t placeholder_count = 0;
3919   char * format_scratch = format;
3920   for (size_t i = 0; i < length; i++) {
3921     if (format_base[i] != '%') {
3922       *format_scratch++ = format_base[i];
3923     } else {
3924       if (format_base[i + 1] == '%') {
3925         // Ignore explicit "%%" sequences.
3926         *format_scratch++ = format_base[i];
3927         i++;
3928         // Chunks after the first are passed as format strings to printf, so we
3929         // need to escape '%' characters in those chunks.
3930         if (placeholder_count > 0) *format_scratch++ = format_base[i];
3931       } else {
3932         VIXL_CHECK(placeholder_count < arg_count);
3933         // Insert '\0' before placeholders, and store their locations.
3934         *format_scratch++ = '\0';
3935         chunks[placeholder_count++] = format_scratch;
3936         *format_scratch++ = format_base[i];
3937       }
3938     }
3939   }
3940   VIXL_CHECK(placeholder_count == arg_count);
3941 
3942   // Finally, call printf with each chunk, passing the appropriate register
3943   // argument. Normally, printf returns the number of bytes transmitted, so we
3944   // can emulate a single printf call by adding the result from each chunk. If
3945   // any call returns a negative (error) value, though, just return that value.
3946 
3947   printf("%s", clr_printf);
3948 
3949   // Because '\0' is inserted before each placeholder, the first string in
3950   // 'format' contains no format placeholders and should be printed literally.
3951   int result = printf("%s", format);
3952   int pcs_r = 1;      // Start at x1. x0 holds the format string.
3953   int pcs_f = 0;      // Start at d0.
3954   if (result >= 0) {
3955     for (uint32_t i = 0; i < placeholder_count; i++) {
3956       int part_result = -1;
3957 
3958       uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
3959       arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
3960       switch (arg_pattern) {
3961         case kPrintfArgW: part_result = printf(chunks[i], wreg(pcs_r++)); break;
3962         case kPrintfArgX: part_result = printf(chunks[i], xreg(pcs_r++)); break;
3963         case kPrintfArgD: part_result = printf(chunks[i], dreg(pcs_f++)); break;
3964         default: VIXL_UNREACHABLE();
3965       }
3966 
3967       if (part_result < 0) {
3968         // Handle error values.
3969         result = part_result;
3970         break;
3971       }
3972 
3973       result += part_result;
3974     }
3975   }
3976 
3977   printf("%s", clr_normal);
3978 
3979   // Printf returns its result in x0 (just like the C library's printf).
3980   set_xreg(0, result);
3981 
3982   // The printf parameters are inlined in the code, so skip them.
3983   set_pc(instr->InstructionAtOffset(kPrintfLength));
3984 
3985   // Set LR as if we'd just called a native printf function.
3986   set_lr(pc());
3987 
3988   js_free(format);
3989 }
3990 
3991 }  // namespace vixl
3992 
3993 #endif  // JS_SIMULATOR_ARM64
3994