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