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