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