• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015, VIXL authors
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 VIXL_INCLUDE_SIMULATOR_AARCH64
28 
29 #include <cmath>
30 #include <cstring>
31 #include <limits>
32 
33 #include "simulator-aarch64.h"
34 
35 namespace vixl {
36 namespace aarch64 {
37 
38 using vixl::internal::SimFloat16;
39 
40 const Instruction* Simulator::kEndOfSimAddress = NULL;
41 
SetBits(int msb,int lsb,uint32_t bits)42 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
43   int width = msb - lsb + 1;
44   VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
45 
46   bits <<= lsb;
47   uint32_t mask = ((1 << width) - 1) << lsb;
48   VIXL_ASSERT((mask & write_ignore_mask_) == 0);
49 
50   value_ = (value_ & ~mask) | (bits & mask);
51 }
52 
53 
DefaultValueFor(SystemRegister id)54 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
55   switch (id) {
56     case NZCV:
57       return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
58     case FPCR:
59       return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
60     default:
61       VIXL_UNREACHABLE();
62       return SimSystemRegister();
63   }
64 }
65 
66 
Simulator(Decoder * decoder,FILE * stream)67 Simulator::Simulator(Decoder* decoder, FILE* stream)
68     : cpu_features_auditor_(decoder, CPUFeatures::All()) {
69   // Ensure that shift operations act as the simulator expects.
70   VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
71   VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
72 
73   instruction_stats_ = false;
74 
75   // Set up the decoder.
76   decoder_ = decoder;
77   decoder_->AppendVisitor(this);
78 
79   stream_ = stream;
80 
81   print_disasm_ = new PrintDisassembler(stream_);
82   // The Simulator and Disassembler share the same available list, held by the
83   // auditor. The Disassembler only annotates instructions with features that
84   // are _not_ available, so registering the auditor should have no effect
85   // unless the simulator is about to abort (due to missing features). In
86   // practice, this means that with trace enabled, the simulator will crash just
87   // after the disassembler prints the instruction, with the missing features
88   // enumerated.
89   print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
90 
91   SetColouredTrace(false);
92   trace_parameters_ = LOG_NONE;
93 
94   ResetState();
95 
96   // Allocate and set up the simulator stack.
97   stack_ = new byte[stack_size_];
98   stack_limit_ = stack_ + stack_protection_size_;
99   // Configure the starting stack pointer.
100   //  - Find the top of the stack.
101   byte* tos = stack_ + stack_size_;
102   //  - There's a protection region at both ends of the stack.
103   tos -= stack_protection_size_;
104   //  - The stack pointer must be 16-byte aligned.
105   tos = AlignDown(tos, 16);
106   WriteSp(tos);
107 
108   instrumentation_ = NULL;
109 
110   // Print a warning about exclusive-access instructions, but only the first
111   // time they are encountered. This warning can be silenced using
112   // SilenceExclusiveAccessWarning().
113   print_exclusive_access_warning_ = true;
114 
115   guard_pages_ = false;
116 
117   // Initialize the common state of RNDR and RNDRRS.
118   uint16_t seed[3] = {11, 22, 33};
119   VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rndr_state_));
120   memcpy(rndr_state_, seed, sizeof(rndr_state_));
121 }
122 
123 
ResetState()124 void Simulator::ResetState() {
125   // Reset the system registers.
126   nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
127   fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
128 
129   // Reset registers to 0.
130   pc_ = NULL;
131   pc_modified_ = false;
132   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
133     WriteXRegister(i, 0xbadbeef);
134   }
135   // Set FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
136   uint64_t nan_bits[] = {
137       UINT64_C(0x7ff00cab7f8ba9e1), UINT64_C(0x7ff0dead7f8beef1),
138   };
139   VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits[0] & kDRegMask)));
140   VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits[0] & kSRegMask)));
141 
142   qreg_t q_bits;
143   VIXL_ASSERT(sizeof(q_bits) == sizeof(nan_bits));
144   memcpy(&q_bits, nan_bits, sizeof(nan_bits));
145 
146   for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
147     WriteQRegister(i, q_bits);
148   }
149   // Returning to address 0 exits the Simulator.
150   WriteLr(kEndOfSimAddress);
151 
152   btype_ = DefaultBType;
153   next_btype_ = DefaultBType;
154 }
155 
156 
~Simulator()157 Simulator::~Simulator() {
158   delete[] stack_;
159   // The decoder may outlive the simulator.
160   decoder_->RemoveVisitor(print_disasm_);
161   delete print_disasm_;
162 
163   decoder_->RemoveVisitor(instrumentation_);
164   delete instrumentation_;
165 }
166 
167 
Run()168 void Simulator::Run() {
169   // Flush any written registers before executing anything, so that
170   // manually-set registers are logged _before_ the first instruction.
171   LogAllWrittenRegisters();
172 
173   while (pc_ != kEndOfSimAddress) {
174     ExecuteInstruction();
175   }
176 }
177 
178 
RunFrom(const Instruction * first)179 void Simulator::RunFrom(const Instruction* first) {
180   WritePc(first, NoBranchLog);
181   Run();
182 }
183 
184 
185 const char* Simulator::xreg_names[] = {"x0",  "x1",  "x2",  "x3",  "x4",  "x5",
186                                        "x6",  "x7",  "x8",  "x9",  "x10", "x11",
187                                        "x12", "x13", "x14", "x15", "x16", "x17",
188                                        "x18", "x19", "x20", "x21", "x22", "x23",
189                                        "x24", "x25", "x26", "x27", "x28", "x29",
190                                        "lr",  "xzr", "sp"};
191 
192 const char* Simulator::wreg_names[] = {"w0",  "w1",  "w2",  "w3",  "w4",  "w5",
193                                        "w6",  "w7",  "w8",  "w9",  "w10", "w11",
194                                        "w12", "w13", "w14", "w15", "w16", "w17",
195                                        "w18", "w19", "w20", "w21", "w22", "w23",
196                                        "w24", "w25", "w26", "w27", "w28", "w29",
197                                        "w30", "wzr", "wsp"};
198 
199 const char* Simulator::hreg_names[] = {"h0",  "h1",  "h2",  "h3",  "h4",  "h5",
200                                        "h6",  "h7",  "h8",  "h9",  "h10", "h11",
201                                        "h12", "h13", "h14", "h15", "h16", "h17",
202                                        "h18", "h19", "h20", "h21", "h22", "h23",
203                                        "h24", "h25", "h26", "h27", "h28", "h29",
204                                        "h30", "h31"};
205 
206 const char* Simulator::sreg_names[] = {"s0",  "s1",  "s2",  "s3",  "s4",  "s5",
207                                        "s6",  "s7",  "s8",  "s9",  "s10", "s11",
208                                        "s12", "s13", "s14", "s15", "s16", "s17",
209                                        "s18", "s19", "s20", "s21", "s22", "s23",
210                                        "s24", "s25", "s26", "s27", "s28", "s29",
211                                        "s30", "s31"};
212 
213 const char* Simulator::dreg_names[] = {"d0",  "d1",  "d2",  "d3",  "d4",  "d5",
214                                        "d6",  "d7",  "d8",  "d9",  "d10", "d11",
215                                        "d12", "d13", "d14", "d15", "d16", "d17",
216                                        "d18", "d19", "d20", "d21", "d22", "d23",
217                                        "d24", "d25", "d26", "d27", "d28", "d29",
218                                        "d30", "d31"};
219 
220 const char* Simulator::vreg_names[] = {"v0",  "v1",  "v2",  "v3",  "v4",  "v5",
221                                        "v6",  "v7",  "v8",  "v9",  "v10", "v11",
222                                        "v12", "v13", "v14", "v15", "v16", "v17",
223                                        "v18", "v19", "v20", "v21", "v22", "v23",
224                                        "v24", "v25", "v26", "v27", "v28", "v29",
225                                        "v30", "v31"};
226 
227 
WRegNameForCode(unsigned code,Reg31Mode mode)228 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
229   VIXL_ASSERT(code < kNumberOfRegisters);
230   // If the code represents the stack pointer, index the name after zr.
231   if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
232     code = kZeroRegCode + 1;
233   }
234   return wreg_names[code];
235 }
236 
237 
XRegNameForCode(unsigned code,Reg31Mode mode)238 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
239   VIXL_ASSERT(code < kNumberOfRegisters);
240   // If the code represents the stack pointer, index the name after zr.
241   if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
242     code = kZeroRegCode + 1;
243   }
244   return xreg_names[code];
245 }
246 
247 
HRegNameForCode(unsigned code)248 const char* Simulator::HRegNameForCode(unsigned code) {
249   VIXL_ASSERT(code < kNumberOfVRegisters);
250   return hreg_names[code];
251 }
252 
253 
SRegNameForCode(unsigned code)254 const char* Simulator::SRegNameForCode(unsigned code) {
255   VIXL_ASSERT(code < kNumberOfVRegisters);
256   return sreg_names[code];
257 }
258 
259 
DRegNameForCode(unsigned code)260 const char* Simulator::DRegNameForCode(unsigned code) {
261   VIXL_ASSERT(code < kNumberOfVRegisters);
262   return dreg_names[code];
263 }
264 
265 
VRegNameForCode(unsigned code)266 const char* Simulator::VRegNameForCode(unsigned code) {
267   VIXL_ASSERT(code < kNumberOfVRegisters);
268   return vreg_names[code];
269 }
270 
271 
272 #define COLOUR(colour_code) "\033[0;" colour_code "m"
273 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
274 #define COLOUR_HIGHLIGHT "\033[43m"
275 #define NORMAL ""
276 #define GREY "30"
277 #define RED "31"
278 #define GREEN "32"
279 #define YELLOW "33"
280 #define BLUE "34"
281 #define MAGENTA "35"
282 #define CYAN "36"
283 #define WHITE "37"
SetColouredTrace(bool value)284 void Simulator::SetColouredTrace(bool value) {
285   coloured_trace_ = value;
286 
287   clr_normal = value ? COLOUR(NORMAL) : "";
288   clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
289   clr_flag_value = value ? COLOUR(NORMAL) : "";
290   clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
291   clr_reg_value = value ? COLOUR(CYAN) : "";
292   clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
293   clr_vreg_value = value ? COLOUR(MAGENTA) : "";
294   clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
295   clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
296   clr_warning_message = value ? COLOUR(YELLOW) : "";
297   clr_printf = value ? COLOUR(GREEN) : "";
298   clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
299 
300   if (value) {
301     print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
302     print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
303   } else {
304     print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
305     print_disasm_->SetCPUFeaturesSuffix("");
306   }
307 }
308 
309 
SetTraceParameters(int parameters)310 void Simulator::SetTraceParameters(int parameters) {
311   bool disasm_before = trace_parameters_ & LOG_DISASM;
312   trace_parameters_ = parameters;
313   bool disasm_after = trace_parameters_ & LOG_DISASM;
314 
315   if (disasm_before != disasm_after) {
316     if (disasm_after) {
317       decoder_->InsertVisitorBefore(print_disasm_, this);
318     } else {
319       decoder_->RemoveVisitor(print_disasm_);
320     }
321   }
322 }
323 
324 
SetInstructionStats(bool value)325 void Simulator::SetInstructionStats(bool value) {
326   if (value != instruction_stats_) {
327     if (value) {
328       if (instrumentation_ == NULL) {
329         // Set the sample period to 10, as the VIXL examples and tests are
330         // short.
331         instrumentation_ = new Instrument("vixl_stats.csv", 10);
332       }
333       decoder_->AppendVisitor(instrumentation_);
334     } else if (instrumentation_ != NULL) {
335       decoder_->RemoveVisitor(instrumentation_);
336     }
337     instruction_stats_ = value;
338   }
339 }
340 
341 // Helpers ---------------------------------------------------------------------
AddWithCarry(unsigned reg_size,bool set_flags,uint64_t left,uint64_t right,int carry_in)342 uint64_t Simulator::AddWithCarry(unsigned reg_size,
343                                  bool set_flags,
344                                  uint64_t left,
345                                  uint64_t right,
346                                  int carry_in) {
347   VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
348   VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
349 
350   uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
351   uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
352   uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
353 
354   left &= reg_mask;
355   right &= reg_mask;
356   uint64_t result = (left + right + carry_in) & reg_mask;
357 
358   if (set_flags) {
359     ReadNzcv().SetN(CalcNFlag(result, reg_size));
360     ReadNzcv().SetZ(CalcZFlag(result));
361 
362     // Compute the C flag by comparing the result to the max unsigned integer.
363     uint64_t max_uint_2op = max_uint - carry_in;
364     bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
365     ReadNzcv().SetC(C ? 1 : 0);
366 
367     // Overflow iff the sign bit is the same for the two inputs and different
368     // for the result.
369     uint64_t left_sign = left & sign_mask;
370     uint64_t right_sign = right & sign_mask;
371     uint64_t result_sign = result & sign_mask;
372     bool V = (left_sign == right_sign) && (left_sign != result_sign);
373     ReadNzcv().SetV(V ? 1 : 0);
374 
375     LogSystemRegister(NZCV);
376   }
377   return result;
378 }
379 
380 
ShiftOperand(unsigned reg_size,int64_t value,Shift shift_type,unsigned amount) const381 int64_t Simulator::ShiftOperand(unsigned reg_size,
382                                 int64_t value,
383                                 Shift shift_type,
384                                 unsigned amount) const {
385   VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
386   if (amount == 0) {
387     return value;
388   }
389   uint64_t uvalue = static_cast<uint64_t>(value);
390   uint64_t mask = kWRegMask;
391   bool is_negative = (uvalue & kWSignMask) != 0;
392   if (reg_size == kXRegSize) {
393     mask = kXRegMask;
394     is_negative = (uvalue & kXSignMask) != 0;
395   }
396 
397   switch (shift_type) {
398     case LSL:
399       uvalue <<= amount;
400       break;
401     case LSR:
402       uvalue >>= amount;
403       break;
404     case ASR:
405       uvalue >>= amount;
406       if (is_negative) {
407         // Simulate sign-extension to 64 bits.
408         uvalue |= ~UINT64_C(0) << (reg_size - amount);
409       }
410       break;
411     case ROR: {
412       uvalue = RotateRight(uvalue, amount, reg_size);
413       break;
414     }
415     default:
416       VIXL_UNIMPLEMENTED();
417       return 0;
418   }
419   uvalue &= mask;
420 
421   int64_t result;
422   memcpy(&result, &uvalue, sizeof(result));
423   return result;
424 }
425 
426 
ExtendValue(unsigned reg_size,int64_t value,Extend extend_type,unsigned left_shift) const427 int64_t Simulator::ExtendValue(unsigned reg_size,
428                                int64_t value,
429                                Extend extend_type,
430                                unsigned left_shift) const {
431   switch (extend_type) {
432     case UXTB:
433       value &= kByteMask;
434       break;
435     case UXTH:
436       value &= kHalfWordMask;
437       break;
438     case UXTW:
439       value &= kWordMask;
440       break;
441     case SXTB:
442       value &= kByteMask;
443       if ((value & 0x80) != 0) {
444         value |= ~UINT64_C(0) << 8;
445       }
446       break;
447     case SXTH:
448       value &= kHalfWordMask;
449       if ((value & 0x8000) != 0) {
450         value |= ~UINT64_C(0) << 16;
451       }
452       break;
453     case SXTW:
454       value &= kWordMask;
455       if ((value & 0x80000000) != 0) {
456         value |= ~UINT64_C(0) << 32;
457       }
458       break;
459     case UXTX:
460     case SXTX:
461       break;
462     default:
463       VIXL_UNREACHABLE();
464   }
465   return ShiftOperand(reg_size, value, LSL, left_shift);
466 }
467 
468 
FPCompare(double val0,double val1,FPTrapFlags trap)469 void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
470   AssertSupportedFPCR();
471 
472   // TODO: This assumes that the C++ implementation handles comparisons in the
473   // way that we expect (as per AssertSupportedFPCR()).
474   bool process_exception = false;
475   if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
476     ReadNzcv().SetRawValue(FPUnorderedFlag);
477     if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
478         (trap == EnableTrap)) {
479       process_exception = true;
480     }
481   } else if (val0 < val1) {
482     ReadNzcv().SetRawValue(FPLessThanFlag);
483   } else if (val0 > val1) {
484     ReadNzcv().SetRawValue(FPGreaterThanFlag);
485   } else if (val0 == val1) {
486     ReadNzcv().SetRawValue(FPEqualFlag);
487   } else {
488     VIXL_UNREACHABLE();
489   }
490   LogSystemRegister(NZCV);
491   if (process_exception) FPProcessException();
492 }
493 
494 
ComputeMemOperandAddress(const MemOperand & mem_op) const495 uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
496   VIXL_ASSERT(mem_op.IsValid());
497   int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
498   if (mem_op.IsImmediateOffset()) {
499     return base + mem_op.GetOffset();
500   } else {
501     VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
502     int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
503     unsigned shift_amount = mem_op.GetShiftAmount();
504     if (mem_op.GetShift() != NO_SHIFT) {
505       offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
506     }
507     if (mem_op.GetExtend() != NO_EXTEND) {
508       offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
509     }
510     return static_cast<uint64_t>(base + offset);
511   }
512 }
513 
514 
GetPrintRegisterFormatForSize(unsigned reg_size,unsigned lane_size)515 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
516     unsigned reg_size, unsigned lane_size) {
517   VIXL_ASSERT(reg_size >= lane_size);
518 
519   uint32_t format = 0;
520   if (reg_size != lane_size) {
521     switch (reg_size) {
522       default:
523         VIXL_UNREACHABLE();
524         break;
525       case kQRegSizeInBytes:
526         format = kPrintRegAsQVector;
527         break;
528       case kDRegSizeInBytes:
529         format = kPrintRegAsDVector;
530         break;
531     }
532   }
533 
534   switch (lane_size) {
535     default:
536       VIXL_UNREACHABLE();
537       break;
538     case kQRegSizeInBytes:
539       format |= kPrintReg1Q;
540       break;
541     case kDRegSizeInBytes:
542       format |= kPrintReg1D;
543       break;
544     case kSRegSizeInBytes:
545       format |= kPrintReg1S;
546       break;
547     case kHRegSizeInBytes:
548       format |= kPrintReg1H;
549       break;
550     case kBRegSizeInBytes:
551       format |= kPrintReg1B;
552       break;
553   }
554   // These sizes would be duplicate case labels.
555   VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
556   VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
557   VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
558   VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
559 
560   return static_cast<PrintRegisterFormat>(format);
561 }
562 
563 
GetPrintRegisterFormat(VectorFormat vform)564 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
565     VectorFormat vform) {
566   switch (vform) {
567     default:
568       VIXL_UNREACHABLE();
569       return kPrintReg16B;
570     case kFormat16B:
571       return kPrintReg16B;
572     case kFormat8B:
573       return kPrintReg8B;
574     case kFormat8H:
575       return kPrintReg8H;
576     case kFormat4H:
577       return kPrintReg4H;
578     case kFormat4S:
579       return kPrintReg4S;
580     case kFormat2S:
581       return kPrintReg2S;
582     case kFormat2D:
583       return kPrintReg2D;
584     case kFormat1D:
585       return kPrintReg1D;
586 
587     case kFormatB:
588       return kPrintReg1B;
589     case kFormatH:
590       return kPrintReg1H;
591     case kFormatS:
592       return kPrintReg1S;
593     case kFormatD:
594       return kPrintReg1D;
595   }
596 }
597 
598 
GetPrintRegisterFormatFP(VectorFormat vform)599 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
600     VectorFormat vform) {
601   switch (vform) {
602     default:
603       VIXL_UNREACHABLE();
604       return kPrintReg16B;
605     case kFormat8H:
606       return kPrintReg8HFP;
607     case kFormat4H:
608       return kPrintReg4HFP;
609     case kFormat4S:
610       return kPrintReg4SFP;
611     case kFormat2S:
612       return kPrintReg2SFP;
613     case kFormat2D:
614       return kPrintReg2DFP;
615     case kFormat1D:
616       return kPrintReg1DFP;
617     case kFormatH:
618       return kPrintReg1HFP;
619     case kFormatS:
620       return kPrintReg1SFP;
621     case kFormatD:
622       return kPrintReg1DFP;
623   }
624 }
625 
626 
PrintWrittenRegisters()627 void Simulator::PrintWrittenRegisters() {
628   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
629     if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
630   }
631 }
632 
633 
PrintWrittenVRegisters()634 void Simulator::PrintWrittenVRegisters() {
635   for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
636     // At this point there is no type information, so print as a raw 1Q.
637     if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
638   }
639 }
640 
641 
PrintSystemRegisters()642 void Simulator::PrintSystemRegisters() {
643   PrintSystemRegister(NZCV);
644   PrintSystemRegister(FPCR);
645 }
646 
647 
PrintRegisters()648 void Simulator::PrintRegisters() {
649   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
650     PrintRegister(i);
651   }
652 }
653 
654 
PrintVRegisters()655 void Simulator::PrintVRegisters() {
656   for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
657     // At this point there is no type information, so print as a raw 1Q.
658     PrintVRegister(i, kPrintReg1Q);
659   }
660 }
661 
662 
663 // Print a register's name and raw value.
664 //
665 // Only the least-significant `size_in_bytes` bytes of the register are printed,
666 // but the value is aligned as if the whole register had been printed.
667 //
668 // For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
669 // -- the default -- so that the whole register is printed. Other values of
670 // size_in_bytes are intended for use when the register hasn't actually been
671 // updated (such as in PrintWrite).
672 //
673 // No newline is printed. This allows the caller to print more details (such as
674 // a memory access annotation).
PrintRegisterRawHelper(unsigned code,Reg31Mode r31mode,int size_in_bytes)675 void Simulator::PrintRegisterRawHelper(unsigned code,
676                                        Reg31Mode r31mode,
677                                        int size_in_bytes) {
678   // The template for all supported sizes.
679   //   "# x{code}: 0xffeeddccbbaa9988"
680   //   "# w{code}:         0xbbaa9988"
681   //   "# w{code}<15:0>:       0x9988"
682   //   "# w{code}<7:0>:          0x88"
683   unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
684 
685   const char* name = "";
686   const char* suffix = "";
687   switch (size_in_bytes) {
688     case kXRegSizeInBytes:
689       name = XRegNameForCode(code, r31mode);
690       break;
691     case kWRegSizeInBytes:
692       name = WRegNameForCode(code, r31mode);
693       break;
694     case 2:
695       name = WRegNameForCode(code, r31mode);
696       suffix = "<15:0>";
697       padding_chars -= strlen(suffix);
698       break;
699     case 1:
700       name = WRegNameForCode(code, r31mode);
701       suffix = "<7:0>";
702       padding_chars -= strlen(suffix);
703       break;
704     default:
705       VIXL_UNREACHABLE();
706   }
707   fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
708 
709   // Print leading padding spaces.
710   VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
711   for (unsigned i = 0; i < padding_chars; i++) {
712     putc(' ', stream_);
713   }
714 
715   // Print the specified bits in hexadecimal format.
716   uint64_t bits = ReadRegister<uint64_t>(code, r31mode);
717   bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
718   VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
719 
720   int chars = size_in_bytes * 2;
721   fprintf(stream_,
722           "%s0x%0*" PRIx64 "%s",
723           clr_reg_value,
724           chars,
725           bits,
726           clr_normal);
727 }
728 
729 
PrintRegister(unsigned code,Reg31Mode r31mode)730 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
731   registers_[code].NotifyRegisterLogged();
732 
733   // Don't print writes into xzr.
734   if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
735     return;
736   }
737 
738   // The template for all x and w registers:
739   //   "# x{code}: 0x{value}"
740   //   "# w{code}: 0x{value}"
741 
742   PrintRegisterRawHelper(code, r31mode);
743   fprintf(stream_, "\n");
744 }
745 
746 
747 // Print a register's name and raw value.
748 //
749 // The `bytes` and `lsb` arguments can be used to limit the bytes that are
750 // printed. These arguments are intended for use in cases where register hasn't
751 // actually been updated (such as in PrintVWrite).
752 //
753 // No newline is printed. This allows the caller to print more details (such as
754 // a floating-point interpretation or a memory access annotation).
PrintVRegisterRawHelper(unsigned code,int bytes,int lsb)755 void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
756   // The template for vector types:
757   //   "# v{code}: 0xffeeddccbbaa99887766554433221100".
758   // An example with bytes=4 and lsb=8:
759   //   "# v{code}:         0xbbaa9988                ".
760   fprintf(stream_,
761           "# %s%5s: %s",
762           clr_vreg_name,
763           VRegNameForCode(code),
764           clr_vreg_value);
765 
766   int msb = lsb + bytes - 1;
767   int byte = kQRegSizeInBytes - 1;
768 
769   // Print leading padding spaces. (Two spaces per byte.)
770   while (byte > msb) {
771     fprintf(stream_, "  ");
772     byte--;
773   }
774 
775   // Print the specified part of the value, byte by byte.
776   qreg_t rawbits = ReadQRegister(code);
777   fprintf(stream_, "0x");
778   while (byte >= lsb) {
779     fprintf(stream_, "%02x", rawbits.val[byte]);
780     byte--;
781   }
782 
783   // Print trailing padding spaces.
784   while (byte >= 0) {
785     fprintf(stream_, "  ");
786     byte--;
787   }
788   fprintf(stream_, "%s", clr_normal);
789 }
790 
791 
792 // Print each of the specified lanes of a register as a float or double value.
793 //
794 // The `lane_count` and `lslane` arguments can be used to limit the lanes that
795 // are printed. These arguments are intended for use in cases where register
796 // hasn't actually been updated (such as in PrintVWrite).
797 //
798 // No newline is printed. This allows the caller to print more details (such as
799 // a memory access annotation).
PrintVRegisterFPHelper(unsigned code,unsigned lane_size_in_bytes,int lane_count,int rightmost_lane)800 void Simulator::PrintVRegisterFPHelper(unsigned code,
801                                        unsigned lane_size_in_bytes,
802                                        int lane_count,
803                                        int rightmost_lane) {
804   VIXL_ASSERT((lane_size_in_bytes == kHRegSizeInBytes) ||
805               (lane_size_in_bytes == kSRegSizeInBytes) ||
806               (lane_size_in_bytes == kDRegSizeInBytes));
807 
808   unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
809   VIXL_ASSERT(msb <= kQRegSizeInBytes);
810 
811   // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
812   // name is used:
813   //   " (h{code}: {value})"
814   //   " (s{code}: {value})"
815   //   " (d{code}: {value})"
816   // For vector types, "..." is used to represent one or more omitted lanes.
817   //   " (..., {value}, {value}, ...)"
818   if (lane_size_in_bytes == kHRegSizeInBytes) {
819     // TODO: Trace tests will fail until we regenerate them.
820     return;
821   }
822   if ((lane_count == 1) && (rightmost_lane == 0)) {
823     const char* name;
824     switch (lane_size_in_bytes) {
825       case kHRegSizeInBytes:
826         name = HRegNameForCode(code);
827         break;
828       case kSRegSizeInBytes:
829         name = SRegNameForCode(code);
830         break;
831       case kDRegSizeInBytes:
832         name = DRegNameForCode(code);
833         break;
834       default:
835         name = NULL;
836         VIXL_UNREACHABLE();
837     }
838     fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
839   } else {
840     if (msb < (kQRegSizeInBytes - 1)) {
841       fprintf(stream_, " (..., ");
842     } else {
843       fprintf(stream_, " (");
844     }
845   }
846 
847   // Print the list of values.
848   const char* separator = "";
849   int leftmost_lane = rightmost_lane + lane_count - 1;
850   for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
851     double value;
852     switch (lane_size_in_bytes) {
853       case kHRegSizeInBytes:
854         value = ReadVRegister(code).GetLane<uint16_t>(lane);
855         break;
856       case kSRegSizeInBytes:
857         value = ReadVRegister(code).GetLane<float>(lane);
858         break;
859       case kDRegSizeInBytes:
860         value = ReadVRegister(code).GetLane<double>(lane);
861         break;
862       default:
863         value = 0.0;
864         VIXL_UNREACHABLE();
865     }
866     if (IsNaN(value)) {
867       // The output for NaNs is implementation defined. Always print `nan`, so
868       // that traces are coherent across different implementations.
869       fprintf(stream_, "%s%snan%s", separator, clr_vreg_value, clr_normal);
870     } else {
871       fprintf(stream_,
872               "%s%s%#g%s",
873               separator,
874               clr_vreg_value,
875               value,
876               clr_normal);
877     }
878     separator = ", ";
879   }
880 
881   if (rightmost_lane > 0) {
882     fprintf(stream_, ", ...");
883   }
884   fprintf(stream_, ")");
885 }
886 
887 
PrintVRegister(unsigned code,PrintRegisterFormat format)888 void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
889   vregisters_[code].NotifyRegisterLogged();
890 
891   int lane_size_log2 = format & kPrintRegLaneSizeMask;
892 
893   int reg_size_log2;
894   if (format & kPrintRegAsQVector) {
895     reg_size_log2 = kQRegSizeInBytesLog2;
896   } else if (format & kPrintRegAsDVector) {
897     reg_size_log2 = kDRegSizeInBytesLog2;
898   } else {
899     // Scalar types.
900     reg_size_log2 = lane_size_log2;
901   }
902 
903   int lane_count = 1 << (reg_size_log2 - lane_size_log2);
904   int lane_size = 1 << lane_size_log2;
905 
906   // The template for vector types:
907   //   "# v{code}: 0x{rawbits} (..., {value}, ...)".
908   // The template for scalar types:
909   //   "# v{code}: 0x{rawbits} ({reg}:{value})".
910   // The values in parentheses after the bit representations are floating-point
911   // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
912 
913   PrintVRegisterRawHelper(code);
914   if (format & kPrintRegAsFP) {
915     PrintVRegisterFPHelper(code, lane_size, lane_count);
916   }
917 
918   fprintf(stream_, "\n");
919 }
920 
921 
PrintSystemRegister(SystemRegister id)922 void Simulator::PrintSystemRegister(SystemRegister id) {
923   switch (id) {
924     case NZCV:
925       fprintf(stream_,
926               "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
927               clr_flag_name,
928               clr_flag_value,
929               ReadNzcv().GetN(),
930               ReadNzcv().GetZ(),
931               ReadNzcv().GetC(),
932               ReadNzcv().GetV(),
933               clr_normal);
934       break;
935     case FPCR: {
936       static const char* rmode[] = {"0b00 (Round to Nearest)",
937                                     "0b01 (Round towards Plus Infinity)",
938                                     "0b10 (Round towards Minus Infinity)",
939                                     "0b11 (Round towards Zero)"};
940       VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
941       fprintf(stream_,
942               "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
943               clr_flag_name,
944               clr_flag_value,
945               ReadFpcr().GetAHP(),
946               ReadFpcr().GetDN(),
947               ReadFpcr().GetFZ(),
948               rmode[ReadFpcr().GetRMode()],
949               clr_normal);
950       break;
951     }
952     default:
953       VIXL_UNREACHABLE();
954   }
955 }
956 
957 
PrintRead(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)958 void Simulator::PrintRead(uintptr_t address,
959                           unsigned reg_code,
960                           PrintRegisterFormat format) {
961   registers_[reg_code].NotifyRegisterLogged();
962 
963   USE(format);
964 
965   // The template is "# {reg}: 0x{value} <- {address}".
966   PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
967   fprintf(stream_,
968           " <- %s0x%016" PRIxPTR "%s\n",
969           clr_memory_address,
970           address,
971           clr_normal);
972 }
973 
974 
PrintVRead(uintptr_t address,unsigned reg_code,PrintRegisterFormat format,unsigned lane)975 void Simulator::PrintVRead(uintptr_t address,
976                            unsigned reg_code,
977                            PrintRegisterFormat format,
978                            unsigned lane) {
979   vregisters_[reg_code].NotifyRegisterLogged();
980 
981   // The template is "# v{code}: 0x{rawbits} <- address".
982   PrintVRegisterRawHelper(reg_code);
983   if (format & kPrintRegAsFP) {
984     PrintVRegisterFPHelper(reg_code,
985                            GetPrintRegLaneSizeInBytes(format),
986                            GetPrintRegLaneCount(format),
987                            lane);
988   }
989   fprintf(stream_,
990           " <- %s0x%016" PRIxPTR "%s\n",
991           clr_memory_address,
992           address,
993           clr_normal);
994 }
995 
996 
PrintWrite(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)997 void Simulator::PrintWrite(uintptr_t address,
998                            unsigned reg_code,
999                            PrintRegisterFormat format) {
1000   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1001 
1002   // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
1003   // and readable, the value is aligned with the values in the register trace.
1004   PrintRegisterRawHelper(reg_code,
1005                          Reg31IsZeroRegister,
1006                          GetPrintRegSizeInBytes(format));
1007   fprintf(stream_,
1008           " -> %s0x%016" PRIxPTR "%s\n",
1009           clr_memory_address,
1010           address,
1011           clr_normal);
1012 }
1013 
1014 
PrintVWrite(uintptr_t address,unsigned reg_code,PrintRegisterFormat format,unsigned lane)1015 void Simulator::PrintVWrite(uintptr_t address,
1016                             unsigned reg_code,
1017                             PrintRegisterFormat format,
1018                             unsigned lane) {
1019   // The templates:
1020   //   "# v{code}: 0x{rawbits} -> {address}"
1021   //   "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
1022   //   "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
1023   // Because this trace doesn't represent a change to the source register's
1024   // value, only the relevant part of the value is printed. To keep the trace
1025   // tidy and readable, the raw value is aligned with the other values in the
1026   // register trace.
1027   int lane_count = GetPrintRegLaneCount(format);
1028   int lane_size = GetPrintRegLaneSizeInBytes(format);
1029   int reg_size = GetPrintRegSizeInBytes(format);
1030   PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1031   if (format & kPrintRegAsFP) {
1032     PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1033   }
1034   fprintf(stream_,
1035           " -> %s0x%016" PRIxPTR "%s\n",
1036           clr_memory_address,
1037           address,
1038           clr_normal);
1039 }
1040 
1041 
PrintTakenBranch(const Instruction * target)1042 void Simulator::PrintTakenBranch(const Instruction* target) {
1043   fprintf(stream_,
1044           "# %sBranch%s to 0x%016" PRIx64 ".\n",
1045           clr_branch_marker,
1046           clr_normal,
1047           reinterpret_cast<uint64_t>(target));
1048 }
1049 
1050 
1051 // Visitors---------------------------------------------------------------------
1052 
1053 
VisitReserved(const Instruction * instr)1054 void Simulator::VisitReserved(const Instruction* instr) {
1055   // UDF is the only instruction in this group, and the Decoder is precise here.
1056   VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1057 
1058   printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1059          reinterpret_cast<const void*>(instr),
1060          instr->GetInstructionBits());
1061   VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1062 }
1063 
1064 
VisitUnimplemented(const Instruction * instr)1065 void Simulator::VisitUnimplemented(const Instruction* instr) {
1066   printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1067          reinterpret_cast<const void*>(instr),
1068          instr->GetInstructionBits());
1069   VIXL_UNIMPLEMENTED();
1070 }
1071 
1072 
VisitUnallocated(const Instruction * instr)1073 void Simulator::VisitUnallocated(const Instruction* instr) {
1074   printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1075          reinterpret_cast<const void*>(instr),
1076          instr->GetInstructionBits());
1077   VIXL_UNIMPLEMENTED();
1078 }
1079 
1080 
VisitPCRelAddressing(const Instruction * instr)1081 void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1082   VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1083               (instr->Mask(PCRelAddressingMask) == ADRP));
1084 
1085   WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1086 }
1087 
1088 
VisitUnconditionalBranch(const Instruction * instr)1089 void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1090   switch (instr->Mask(UnconditionalBranchMask)) {
1091     case BL:
1092       WriteLr(instr->GetNextInstruction());
1093       VIXL_FALLTHROUGH();
1094     case B:
1095       WritePc(instr->GetImmPCOffsetTarget());
1096       break;
1097     default:
1098       VIXL_UNREACHABLE();
1099   }
1100 }
1101 
1102 
VisitConditionalBranch(const Instruction * instr)1103 void Simulator::VisitConditionalBranch(const Instruction* instr) {
1104   VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1105   if (ConditionPassed(instr->GetConditionBranch())) {
1106     WritePc(instr->GetImmPCOffsetTarget());
1107   }
1108 }
1109 
GetBTypeFromInstruction(const Instruction * instr) const1110 BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1111   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1112     case BLR:
1113     case BLRAA:
1114     case BLRAB:
1115     case BLRAAZ:
1116     case BLRABZ:
1117       return BranchAndLink;
1118     case BR:
1119     case BRAA:
1120     case BRAB:
1121     case BRAAZ:
1122     case BRABZ:
1123       if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1124           !PcIsInGuardedPage()) {
1125         return BranchFromUnguardedOrToIP;
1126       }
1127       return BranchFromGuardedNotToIP;
1128   }
1129   return DefaultBType;
1130 }
1131 
VisitUnconditionalBranchToRegister(const Instruction * instr)1132 void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
1133   bool authenticate = false;
1134   bool link = false;
1135   uint64_t addr = ReadXRegister(instr->GetRn());
1136   uint64_t context = 0;
1137 
1138   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1139     case BLR:
1140       link = true;
1141       VIXL_FALLTHROUGH();
1142     case BR:
1143     case RET:
1144       break;
1145 
1146     case BLRAAZ:
1147     case BLRABZ:
1148       link = true;
1149       VIXL_FALLTHROUGH();
1150     case BRAAZ:
1151     case BRABZ:
1152       authenticate = true;
1153       break;
1154 
1155     case BLRAA:
1156     case BLRAB:
1157       link = true;
1158       VIXL_FALLTHROUGH();
1159     case BRAA:
1160     case BRAB:
1161       authenticate = true;
1162       context = ReadXRegister(instr->GetRd());
1163       break;
1164 
1165     case RETAA:
1166     case RETAB:
1167       authenticate = true;
1168       addr = ReadXRegister(kLinkRegCode);
1169       context = ReadXRegister(31, Reg31IsStackPointer);
1170       break;
1171     default:
1172       VIXL_UNREACHABLE();
1173   }
1174 
1175   if (link) {
1176     WriteLr(instr->GetNextInstruction());
1177   }
1178 
1179   if (authenticate) {
1180     PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1181     addr = AuthPAC(addr, context, key, kInstructionPointer);
1182 
1183     int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1184     if (((addr >> error_lsb) & 0x3) != 0x0) {
1185       VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1186     }
1187   }
1188 
1189   WritePc(Instruction::Cast(addr));
1190   WriteNextBType(GetBTypeFromInstruction(instr));
1191 }
1192 
1193 
VisitTestBranch(const Instruction * instr)1194 void Simulator::VisitTestBranch(const Instruction* instr) {
1195   unsigned bit_pos =
1196       (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1197   bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1198   bool take_branch = false;
1199   switch (instr->Mask(TestBranchMask)) {
1200     case TBZ:
1201       take_branch = bit_zero;
1202       break;
1203     case TBNZ:
1204       take_branch = !bit_zero;
1205       break;
1206     default:
1207       VIXL_UNIMPLEMENTED();
1208   }
1209   if (take_branch) {
1210     WritePc(instr->GetImmPCOffsetTarget());
1211   }
1212 }
1213 
1214 
VisitCompareBranch(const Instruction * instr)1215 void Simulator::VisitCompareBranch(const Instruction* instr) {
1216   unsigned rt = instr->GetRt();
1217   bool take_branch = false;
1218   switch (instr->Mask(CompareBranchMask)) {
1219     case CBZ_w:
1220       take_branch = (ReadWRegister(rt) == 0);
1221       break;
1222     case CBZ_x:
1223       take_branch = (ReadXRegister(rt) == 0);
1224       break;
1225     case CBNZ_w:
1226       take_branch = (ReadWRegister(rt) != 0);
1227       break;
1228     case CBNZ_x:
1229       take_branch = (ReadXRegister(rt) != 0);
1230       break;
1231     default:
1232       VIXL_UNIMPLEMENTED();
1233   }
1234   if (take_branch) {
1235     WritePc(instr->GetImmPCOffsetTarget());
1236   }
1237 }
1238 
1239 
AddSubHelper(const Instruction * instr,int64_t op2)1240 void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1241   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1242   bool set_flags = instr->GetFlagsUpdate();
1243   int64_t new_val = 0;
1244   Instr operation = instr->Mask(AddSubOpMask);
1245 
1246   switch (operation) {
1247     case ADD:
1248     case ADDS: {
1249       new_val = AddWithCarry(reg_size,
1250                              set_flags,
1251                              ReadRegister(reg_size,
1252                                           instr->GetRn(),
1253                                           instr->GetRnMode()),
1254                              op2);
1255       break;
1256     }
1257     case SUB:
1258     case SUBS: {
1259       new_val = AddWithCarry(reg_size,
1260                              set_flags,
1261                              ReadRegister(reg_size,
1262                                           instr->GetRn(),
1263                                           instr->GetRnMode()),
1264                              ~op2,
1265                              1);
1266       break;
1267     }
1268     default:
1269       VIXL_UNREACHABLE();
1270   }
1271 
1272   WriteRegister(reg_size,
1273                 instr->GetRd(),
1274                 new_val,
1275                 LogRegWrites,
1276                 instr->GetRdMode());
1277 }
1278 
1279 
VisitAddSubShifted(const Instruction * instr)1280 void Simulator::VisitAddSubShifted(const Instruction* instr) {
1281   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1282   int64_t op2 = ShiftOperand(reg_size,
1283                              ReadRegister(reg_size, instr->GetRm()),
1284                              static_cast<Shift>(instr->GetShiftDP()),
1285                              instr->GetImmDPShift());
1286   AddSubHelper(instr, op2);
1287 }
1288 
1289 
VisitAddSubImmediate(const Instruction * instr)1290 void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1291   int64_t op2 = instr->GetImmAddSub()
1292                 << ((instr->GetShiftAddSub() == 1) ? 12 : 0);
1293   AddSubHelper(instr, op2);
1294 }
1295 
1296 
VisitAddSubExtended(const Instruction * instr)1297 void Simulator::VisitAddSubExtended(const Instruction* instr) {
1298   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1299   int64_t op2 = ExtendValue(reg_size,
1300                             ReadRegister(reg_size, instr->GetRm()),
1301                             static_cast<Extend>(instr->GetExtendMode()),
1302                             instr->GetImmExtendShift());
1303   AddSubHelper(instr, op2);
1304 }
1305 
1306 
VisitAddSubWithCarry(const Instruction * instr)1307 void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1308   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1309   int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1310   int64_t new_val;
1311 
1312   if ((instr->Mask(AddSubOpMask) == SUB) ||
1313       (instr->Mask(AddSubOpMask) == SUBS)) {
1314     op2 = ~op2;
1315   }
1316 
1317   new_val = AddWithCarry(reg_size,
1318                          instr->GetFlagsUpdate(),
1319                          ReadRegister(reg_size, instr->GetRn()),
1320                          op2,
1321                          ReadC());
1322 
1323   WriteRegister(reg_size, instr->GetRd(), new_val);
1324 }
1325 
1326 
VisitRotateRightIntoFlags(const Instruction * instr)1327 void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1328   switch (instr->Mask(RotateRightIntoFlagsMask)) {
1329     case RMIF: {
1330       uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1331       unsigned shift = instr->GetImmRMIFRotation();
1332       unsigned mask = instr->GetNzcv();
1333       uint64_t rotated = RotateRight(value, shift, kXRegSize);
1334 
1335       ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1336       break;
1337     }
1338   }
1339 }
1340 
1341 
VisitEvaluateIntoFlags(const Instruction * instr)1342 void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1343   uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1344   unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1345 
1346   unsigned sign_bit = (value >> msb) & 1;
1347   unsigned overflow_bit = (value >> (msb + 1)) & 1;
1348   ReadNzcv().SetN(sign_bit);
1349   ReadNzcv().SetZ((value << (31 - msb)) == 0);
1350   ReadNzcv().SetV(sign_bit ^ overflow_bit);
1351 }
1352 
1353 
VisitLogicalShifted(const Instruction * instr)1354 void Simulator::VisitLogicalShifted(const Instruction* instr) {
1355   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1356   Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1357   unsigned shift_amount = instr->GetImmDPShift();
1358   int64_t op2 = ShiftOperand(reg_size,
1359                              ReadRegister(reg_size, instr->GetRm()),
1360                              shift_type,
1361                              shift_amount);
1362   if (instr->Mask(NOT) == NOT) {
1363     op2 = ~op2;
1364   }
1365   LogicalHelper(instr, op2);
1366 }
1367 
1368 
VisitLogicalImmediate(const Instruction * instr)1369 void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1370   LogicalHelper(instr, instr->GetImmLogical());
1371 }
1372 
1373 
LogicalHelper(const Instruction * instr,int64_t op2)1374 void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1375   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1376   int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1377   int64_t result = 0;
1378   bool update_flags = false;
1379 
1380   // Switch on the logical operation, stripping out the NOT bit, as it has a
1381   // different meaning for logical immediate instructions.
1382   switch (instr->Mask(LogicalOpMask & ~NOT)) {
1383     case ANDS:
1384       update_flags = true;
1385       VIXL_FALLTHROUGH();
1386     case AND:
1387       result = op1 & op2;
1388       break;
1389     case ORR:
1390       result = op1 | op2;
1391       break;
1392     case EOR:
1393       result = op1 ^ op2;
1394       break;
1395     default:
1396       VIXL_UNIMPLEMENTED();
1397   }
1398 
1399   if (update_flags) {
1400     ReadNzcv().SetN(CalcNFlag(result, reg_size));
1401     ReadNzcv().SetZ(CalcZFlag(result));
1402     ReadNzcv().SetC(0);
1403     ReadNzcv().SetV(0);
1404     LogSystemRegister(NZCV);
1405   }
1406 
1407   WriteRegister(reg_size,
1408                 instr->GetRd(),
1409                 result,
1410                 LogRegWrites,
1411                 instr->GetRdMode());
1412 }
1413 
1414 
VisitConditionalCompareRegister(const Instruction * instr)1415 void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1416   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1417   ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1418 }
1419 
1420 
VisitConditionalCompareImmediate(const Instruction * instr)1421 void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1422   ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1423 }
1424 
1425 
ConditionalCompareHelper(const Instruction * instr,int64_t op2)1426 void Simulator::ConditionalCompareHelper(const Instruction* instr,
1427                                          int64_t op2) {
1428   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1429   int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1430 
1431   if (ConditionPassed(instr->GetCondition())) {
1432     // If the condition passes, set the status flags to the result of comparing
1433     // the operands.
1434     if (instr->Mask(ConditionalCompareMask) == CCMP) {
1435       AddWithCarry(reg_size, true, op1, ~op2, 1);
1436     } else {
1437       VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1438       AddWithCarry(reg_size, true, op1, op2, 0);
1439     }
1440   } else {
1441     // If the condition fails, set the status flags to the nzcv immediate.
1442     ReadNzcv().SetFlags(instr->GetNzcv());
1443     LogSystemRegister(NZCV);
1444   }
1445 }
1446 
1447 
VisitLoadStoreUnsignedOffset(const Instruction * instr)1448 void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1449   int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1450   LoadStoreHelper(instr, offset, Offset);
1451 }
1452 
1453 
VisitLoadStoreUnscaledOffset(const Instruction * instr)1454 void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1455   LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1456 }
1457 
1458 
VisitLoadStorePreIndex(const Instruction * instr)1459 void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1460   LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1461 }
1462 
1463 
VisitLoadStorePostIndex(const Instruction * instr)1464 void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1465   LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1466 }
1467 
1468 
1469 template <typename T1, typename T2>
LoadAcquireRCpcUnscaledOffsetHelper(const Instruction * instr)1470 void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1471   unsigned rt = instr->GetRt();
1472   unsigned rn = instr->GetRn();
1473 
1474   unsigned element_size = sizeof(T2);
1475   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1476   int offset = instr->GetImmLS();
1477   address += offset;
1478 
1479   // Verify that the address is available to the host.
1480   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1481 
1482   // Check the alignment of `address`.
1483   if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1484     VIXL_ALIGNMENT_EXCEPTION();
1485   }
1486 
1487   WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
1488 
1489   // Approximate load-acquire by issuing a full barrier after the load.
1490   __sync_synchronize();
1491 
1492   LogRead(address, rt, GetPrintRegisterFormat(element_size));
1493 }
1494 
1495 
1496 template <typename T>
StoreReleaseUnscaledOffsetHelper(const Instruction * instr)1497 void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
1498   unsigned rt = instr->GetRt();
1499   unsigned rn = instr->GetRn();
1500 
1501   unsigned element_size = sizeof(T);
1502   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1503   int offset = instr->GetImmLS();
1504   address += offset;
1505 
1506   // Verify that the address is available to the host.
1507   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1508 
1509   // Check the alignment of `address`.
1510   if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1511     VIXL_ALIGNMENT_EXCEPTION();
1512   }
1513 
1514   // Approximate store-release by issuing a full barrier after the load.
1515   __sync_synchronize();
1516 
1517   Memory::Write<T>(address, ReadRegister<T>(rt));
1518 
1519   LogWrite(address, rt, GetPrintRegisterFormat(element_size));
1520 }
1521 
1522 
VisitLoadStoreRCpcUnscaledOffset(const Instruction * instr)1523 void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
1524   switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
1525     case LDAPURB:
1526       LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
1527       break;
1528     case LDAPURH:
1529       LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
1530       break;
1531     case LDAPUR_w:
1532       LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
1533       break;
1534     case LDAPUR_x:
1535       LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
1536       break;
1537     case LDAPURSB_w:
1538       LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
1539       break;
1540     case LDAPURSB_x:
1541       LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
1542       break;
1543     case LDAPURSH_w:
1544       LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
1545       break;
1546     case LDAPURSH_x:
1547       LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
1548       break;
1549     case LDAPURSW:
1550       LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
1551       break;
1552     case STLURB:
1553       StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
1554       break;
1555     case STLURH:
1556       StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
1557       break;
1558     case STLUR_w:
1559       StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
1560       break;
1561     case STLUR_x:
1562       StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
1563       break;
1564   }
1565 }
1566 
1567 
VisitLoadStorePAC(const Instruction * instr)1568 void Simulator::VisitLoadStorePAC(const Instruction* instr) {
1569   unsigned dst = instr->GetRt();
1570   unsigned addr_reg = instr->GetRn();
1571 
1572   uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
1573 
1574   PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
1575   address = AuthPAC(address, 0, key, kDataPointer);
1576 
1577   int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
1578   if (((address >> error_lsb) & 0x3) != 0x0) {
1579     VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1580   }
1581 
1582 
1583   if ((addr_reg == 31) && ((address % 16) != 0)) {
1584     // When the base register is SP the stack pointer is required to be
1585     // quadword aligned prior to the address calculation and write-backs.
1586     // Misalignment will cause a stack alignment fault.
1587     VIXL_ALIGNMENT_EXCEPTION();
1588   }
1589 
1590   int64_t offset = instr->GetImmLSPAC();
1591   address += offset;
1592 
1593   if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
1594     // Pre-index mode.
1595     VIXL_ASSERT(offset != 0);
1596     WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
1597   }
1598 
1599   uintptr_t addr_ptr = static_cast<uintptr_t>(address);
1600 
1601   // Verify that the calculated address is available to the host.
1602   VIXL_ASSERT(address == addr_ptr);
1603 
1604   WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
1605   unsigned access_size = 1 << 3;
1606   LogRead(addr_ptr, dst, GetPrintRegisterFormatForSize(access_size));
1607 }
1608 
1609 
VisitLoadStoreRegisterOffset(const Instruction * instr)1610 void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
1611   Extend ext = static_cast<Extend>(instr->GetExtendMode());
1612   VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1613   unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
1614 
1615   int64_t offset =
1616       ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
1617   LoadStoreHelper(instr, offset, Offset);
1618 }
1619 
1620 
LoadStoreHelper(const Instruction * instr,int64_t offset,AddrMode addrmode)1621 void Simulator::LoadStoreHelper(const Instruction* instr,
1622                                 int64_t offset,
1623                                 AddrMode addrmode) {
1624   unsigned srcdst = instr->GetRt();
1625   uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
1626 
1627   LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
1628   switch (op) {
1629     case LDRB_w:
1630       WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
1631       break;
1632     case LDRH_w:
1633       WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
1634       break;
1635     case LDR_w:
1636       WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
1637       break;
1638     case LDR_x:
1639       WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
1640       break;
1641     case LDRSB_w:
1642       WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
1643       break;
1644     case LDRSH_w:
1645       WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
1646       break;
1647     case LDRSB_x:
1648       WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
1649       break;
1650     case LDRSH_x:
1651       WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
1652       break;
1653     case LDRSW_x:
1654       WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
1655       break;
1656     case LDR_b:
1657       WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
1658       break;
1659     case LDR_h:
1660       WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
1661       break;
1662     case LDR_s:
1663       WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
1664       break;
1665     case LDR_d:
1666       WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
1667       break;
1668     case LDR_q:
1669       WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
1670       break;
1671 
1672     case STRB_w:
1673       Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
1674       break;
1675     case STRH_w:
1676       Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
1677       break;
1678     case STR_w:
1679       Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
1680       break;
1681     case STR_x:
1682       Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
1683       break;
1684     case STR_b:
1685       Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
1686       break;
1687     case STR_h:
1688       Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
1689       break;
1690     case STR_s:
1691       Memory::Write<float>(address, ReadSRegister(srcdst));
1692       break;
1693     case STR_d:
1694       Memory::Write<double>(address, ReadDRegister(srcdst));
1695       break;
1696     case STR_q:
1697       Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
1698       break;
1699 
1700     // Ignore prfm hint instructions.
1701     case PRFM:
1702       break;
1703 
1704     default:
1705       VIXL_UNIMPLEMENTED();
1706   }
1707 
1708   unsigned access_size = 1 << instr->GetSizeLS();
1709   if (instr->IsLoad()) {
1710     if ((op == LDR_s) || (op == LDR_d)) {
1711       LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1712     } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1713       LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1714     } else {
1715       LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1716     }
1717   } else if (instr->IsStore()) {
1718     if ((op == STR_s) || (op == STR_d)) {
1719       LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1720     } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1721       LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1722     } else {
1723       LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1724     }
1725   } else {
1726     VIXL_ASSERT(op == PRFM);
1727   }
1728 
1729   local_monitor_.MaybeClear();
1730 }
1731 
1732 
VisitLoadStorePairOffset(const Instruction * instr)1733 void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
1734   LoadStorePairHelper(instr, Offset);
1735 }
1736 
1737 
VisitLoadStorePairPreIndex(const Instruction * instr)1738 void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
1739   LoadStorePairHelper(instr, PreIndex);
1740 }
1741 
1742 
VisitLoadStorePairPostIndex(const Instruction * instr)1743 void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
1744   LoadStorePairHelper(instr, PostIndex);
1745 }
1746 
1747 
VisitLoadStorePairNonTemporal(const Instruction * instr)1748 void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
1749   LoadStorePairHelper(instr, Offset);
1750 }
1751 
1752 
LoadStorePairHelper(const Instruction * instr,AddrMode addrmode)1753 void Simulator::LoadStorePairHelper(const Instruction* instr,
1754                                     AddrMode addrmode) {
1755   unsigned rt = instr->GetRt();
1756   unsigned rt2 = instr->GetRt2();
1757   int element_size = 1 << instr->GetSizeLSPair();
1758   int64_t offset = instr->GetImmLSPair() * element_size;
1759   uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
1760   uintptr_t address2 = address + element_size;
1761 
1762   LoadStorePairOp op =
1763       static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1764 
1765   // 'rt' and 'rt2' can only be aliased for stores.
1766   VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1767 
1768   switch (op) {
1769     // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
1770     // will print a more detailed log.
1771     case LDP_w: {
1772       WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
1773       WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
1774       break;
1775     }
1776     case LDP_s: {
1777       WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
1778       WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
1779       break;
1780     }
1781     case LDP_x: {
1782       WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
1783       WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
1784       break;
1785     }
1786     case LDP_d: {
1787       WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
1788       WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
1789       break;
1790     }
1791     case LDP_q: {
1792       WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
1793       WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
1794       break;
1795     }
1796     case LDPSW_x: {
1797       WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
1798       WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
1799       break;
1800     }
1801     case STP_w: {
1802       Memory::Write<uint32_t>(address, ReadWRegister(rt));
1803       Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
1804       break;
1805     }
1806     case STP_s: {
1807       Memory::Write<float>(address, ReadSRegister(rt));
1808       Memory::Write<float>(address2, ReadSRegister(rt2));
1809       break;
1810     }
1811     case STP_x: {
1812       Memory::Write<uint64_t>(address, ReadXRegister(rt));
1813       Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
1814       break;
1815     }
1816     case STP_d: {
1817       Memory::Write<double>(address, ReadDRegister(rt));
1818       Memory::Write<double>(address2, ReadDRegister(rt2));
1819       break;
1820     }
1821     case STP_q: {
1822       Memory::Write<qreg_t>(address, ReadQRegister(rt));
1823       Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
1824       break;
1825     }
1826     default:
1827       VIXL_UNREACHABLE();
1828   }
1829 
1830   // Print a detailed trace (including the memory address) instead of the basic
1831   // register:value trace generated by set_*reg().
1832   if (instr->IsLoad()) {
1833     if ((op == LDP_s) || (op == LDP_d)) {
1834       LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1835       LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1836     } else if (op == LDP_q) {
1837       LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1838       LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1839     } else {
1840       LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1841       LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1842     }
1843   } else {
1844     if ((op == STP_s) || (op == STP_d)) {
1845       LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1846       LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1847     } else if (op == STP_q) {
1848       LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1849       LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1850     } else {
1851       LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1852       LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1853     }
1854   }
1855 
1856   local_monitor_.MaybeClear();
1857 }
1858 
1859 
1860 template <typename T>
CompareAndSwapHelper(const Instruction * instr)1861 void Simulator::CompareAndSwapHelper(const Instruction* instr) {
1862   unsigned rs = instr->GetRs();
1863   unsigned rt = instr->GetRt();
1864   unsigned rn = instr->GetRn();
1865 
1866   unsigned element_size = sizeof(T);
1867   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1868 
1869   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
1870 
1871   bool is_acquire = instr->ExtractBit(22) == 1;
1872   bool is_release = instr->ExtractBit(15) == 1;
1873 
1874   T comparevalue = ReadRegister<T>(rs);
1875   T newvalue = ReadRegister<T>(rt);
1876 
1877   // The architecture permits that the data read clears any exclusive monitors
1878   // associated with that location, even if the compare subsequently fails.
1879   local_monitor_.Clear();
1880 
1881   T data = Memory::Read<T>(address);
1882   if (is_acquire) {
1883     // Approximate load-acquire by issuing a full barrier after the load.
1884     __sync_synchronize();
1885   }
1886 
1887   if (data == comparevalue) {
1888     if (is_release) {
1889       // Approximate store-release by issuing a full barrier before the store.
1890       __sync_synchronize();
1891     }
1892     Memory::Write<T>(address, newvalue);
1893     LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1894   }
1895   WriteRegister<T>(rs, data);
1896   LogRead(address, rs, GetPrintRegisterFormatForSize(element_size));
1897 }
1898 
1899 
1900 template <typename T>
CompareAndSwapPairHelper(const Instruction * instr)1901 void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
1902   VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
1903   unsigned rs = instr->GetRs();
1904   unsigned rt = instr->GetRt();
1905   unsigned rn = instr->GetRn();
1906 
1907   VIXL_ASSERT((rs % 2 == 0) && (rs % 2 == 0));
1908 
1909   unsigned element_size = sizeof(T);
1910   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1911 
1912   CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
1913 
1914   uint64_t address2 = address + element_size;
1915 
1916   bool is_acquire = instr->ExtractBit(22) == 1;
1917   bool is_release = instr->ExtractBit(15) == 1;
1918 
1919   T comparevalue_high = ReadRegister<T>(rs + 1);
1920   T comparevalue_low = ReadRegister<T>(rs);
1921   T newvalue_high = ReadRegister<T>(rt + 1);
1922   T newvalue_low = ReadRegister<T>(rt);
1923 
1924   // The architecture permits that the data read clears any exclusive monitors
1925   // associated with that location, even if the compare subsequently fails.
1926   local_monitor_.Clear();
1927 
1928   T data_high = Memory::Read<T>(address);
1929   T data_low = Memory::Read<T>(address2);
1930 
1931   if (is_acquire) {
1932     // Approximate load-acquire by issuing a full barrier after the load.
1933     __sync_synchronize();
1934   }
1935 
1936   bool same =
1937       (data_high == comparevalue_high) && (data_low == comparevalue_low);
1938   if (same) {
1939     if (is_release) {
1940       // Approximate store-release by issuing a full barrier before the store.
1941       __sync_synchronize();
1942     }
1943 
1944     Memory::Write<T>(address, newvalue_high);
1945     Memory::Write<T>(address2, newvalue_low);
1946   }
1947 
1948   WriteRegister<T>(rs + 1, data_high);
1949   WriteRegister<T>(rs, data_low);
1950 
1951   LogRead(address, rs + 1, GetPrintRegisterFormatForSize(element_size));
1952   LogRead(address2, rs, GetPrintRegisterFormatForSize(element_size));
1953 
1954   if (same) {
1955     LogWrite(address, rt + 1, GetPrintRegisterFormatForSize(element_size));
1956     LogWrite(address2, rt, GetPrintRegisterFormatForSize(element_size));
1957   }
1958 }
1959 
1960 
PrintExclusiveAccessWarning()1961 void Simulator::PrintExclusiveAccessWarning() {
1962   if (print_exclusive_access_warning_) {
1963     fprintf(stderr,
1964             "%sWARNING:%s VIXL simulator support for "
1965             "load-/store-/clear-exclusive "
1966             "instructions is limited. Refer to the README for details.%s\n",
1967             clr_warning,
1968             clr_warning_message,
1969             clr_normal);
1970     print_exclusive_access_warning_ = false;
1971   }
1972 }
1973 
1974 
VisitLoadStoreExclusive(const Instruction * instr)1975 void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
1976   LoadStoreExclusive op =
1977       static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
1978 
1979   switch (op) {
1980     case CAS_w:
1981     case CASA_w:
1982     case CASL_w:
1983     case CASAL_w:
1984       CompareAndSwapHelper<uint32_t>(instr);
1985       break;
1986     case CAS_x:
1987     case CASA_x:
1988     case CASL_x:
1989     case CASAL_x:
1990       CompareAndSwapHelper<uint64_t>(instr);
1991       break;
1992     case CASB:
1993     case CASAB:
1994     case CASLB:
1995     case CASALB:
1996       CompareAndSwapHelper<uint8_t>(instr);
1997       break;
1998     case CASH:
1999     case CASAH:
2000     case CASLH:
2001     case CASALH:
2002       CompareAndSwapHelper<uint16_t>(instr);
2003       break;
2004     case CASP_w:
2005     case CASPA_w:
2006     case CASPL_w:
2007     case CASPAL_w:
2008       CompareAndSwapPairHelper<uint32_t>(instr);
2009       break;
2010     case CASP_x:
2011     case CASPA_x:
2012     case CASPL_x:
2013     case CASPAL_x:
2014       CompareAndSwapPairHelper<uint64_t>(instr);
2015       break;
2016     default:
2017       PrintExclusiveAccessWarning();
2018 
2019       unsigned rs = instr->GetRs();
2020       unsigned rt = instr->GetRt();
2021       unsigned rt2 = instr->GetRt2();
2022       unsigned rn = instr->GetRn();
2023 
2024       bool is_exclusive = !instr->GetLdStXNotExclusive();
2025       bool is_acquire_release =
2026           !is_exclusive || instr->GetLdStXAcquireRelease();
2027       bool is_load = instr->GetLdStXLoad();
2028       bool is_pair = instr->GetLdStXPair();
2029 
2030       unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2031       unsigned access_size = is_pair ? element_size * 2 : element_size;
2032       uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2033 
2034       CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2035 
2036       if (is_load) {
2037         if (is_exclusive) {
2038           local_monitor_.MarkExclusive(address, access_size);
2039         } else {
2040           // Any non-exclusive load can clear the local monitor as a side
2041           // effect. We don't need to do this, but it is useful to stress the
2042           // simulated code.
2043           local_monitor_.Clear();
2044         }
2045 
2046         // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2047         // We will print a more detailed log.
2048         switch (op) {
2049           case LDXRB_w:
2050           case LDAXRB_w:
2051           case LDARB_w:
2052           case LDLARB:
2053             WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
2054             break;
2055           case LDXRH_w:
2056           case LDAXRH_w:
2057           case LDARH_w:
2058           case LDLARH:
2059             WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
2060             break;
2061           case LDXR_w:
2062           case LDAXR_w:
2063           case LDAR_w:
2064           case LDLAR_w:
2065             WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2066             break;
2067           case LDXR_x:
2068           case LDAXR_x:
2069           case LDAR_x:
2070           case LDLAR_x:
2071             WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2072             break;
2073           case LDXP_w:
2074           case LDAXP_w:
2075             WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2076             WriteWRegister(rt2,
2077                            Memory::Read<uint32_t>(address + element_size),
2078                            NoRegLog);
2079             break;
2080           case LDXP_x:
2081           case LDAXP_x:
2082             WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2083             WriteXRegister(rt2,
2084                            Memory::Read<uint64_t>(address + element_size),
2085                            NoRegLog);
2086             break;
2087           default:
2088             VIXL_UNREACHABLE();
2089         }
2090 
2091         if (is_acquire_release) {
2092           // Approximate load-acquire by issuing a full barrier after the load.
2093           __sync_synchronize();
2094         }
2095 
2096         LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2097         if (is_pair) {
2098           LogRead(address + element_size,
2099                   rt2,
2100                   GetPrintRegisterFormatForSize(element_size));
2101         }
2102       } else {
2103         if (is_acquire_release) {
2104           // Approximate store-release by issuing a full barrier before the
2105           // store.
2106           __sync_synchronize();
2107         }
2108 
2109         bool do_store = true;
2110         if (is_exclusive) {
2111           do_store = local_monitor_.IsExclusive(address, access_size) &&
2112                      global_monitor_.IsExclusive(address, access_size);
2113           WriteWRegister(rs, do_store ? 0 : 1);
2114 
2115           //  - All exclusive stores explicitly clear the local monitor.
2116           local_monitor_.Clear();
2117         } else {
2118           //  - Any other store can clear the local monitor as a side effect.
2119           local_monitor_.MaybeClear();
2120         }
2121 
2122         if (do_store) {
2123           switch (op) {
2124             case STXRB_w:
2125             case STLXRB_w:
2126             case STLRB_w:
2127             case STLLRB:
2128               Memory::Write<uint8_t>(address, ReadWRegister(rt));
2129               break;
2130             case STXRH_w:
2131             case STLXRH_w:
2132             case STLRH_w:
2133             case STLLRH:
2134               Memory::Write<uint16_t>(address, ReadWRegister(rt));
2135               break;
2136             case STXR_w:
2137             case STLXR_w:
2138             case STLR_w:
2139             case STLLR_w:
2140               Memory::Write<uint32_t>(address, ReadWRegister(rt));
2141               break;
2142             case STXR_x:
2143             case STLXR_x:
2144             case STLR_x:
2145             case STLLR_x:
2146               Memory::Write<uint64_t>(address, ReadXRegister(rt));
2147               break;
2148             case STXP_w:
2149             case STLXP_w:
2150               Memory::Write<uint32_t>(address, ReadWRegister(rt));
2151               Memory::Write<uint32_t>(address + element_size,
2152                                       ReadWRegister(rt2));
2153               break;
2154             case STXP_x:
2155             case STLXP_x:
2156               Memory::Write<uint64_t>(address, ReadXRegister(rt));
2157               Memory::Write<uint64_t>(address + element_size,
2158                                       ReadXRegister(rt2));
2159               break;
2160             default:
2161               VIXL_UNREACHABLE();
2162           }
2163 
2164           LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2165           if (is_pair) {
2166             LogWrite(address + element_size,
2167                      rt2,
2168                      GetPrintRegisterFormatForSize(element_size));
2169           }
2170         }
2171       }
2172   }
2173 }
2174 
2175 template <typename T>
AtomicMemorySimpleHelper(const Instruction * instr)2176 void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2177   unsigned rs = instr->GetRs();
2178   unsigned rt = instr->GetRt();
2179   unsigned rn = instr->GetRn();
2180 
2181   bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2182   bool is_release = instr->ExtractBit(22) == 1;
2183 
2184   unsigned element_size = sizeof(T);
2185   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2186 
2187   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2188 
2189   T value = ReadRegister<T>(rs);
2190 
2191   T data = Memory::Read<T>(address);
2192 
2193   if (is_acquire) {
2194     // Approximate load-acquire by issuing a full barrier after the load.
2195     __sync_synchronize();
2196   }
2197 
2198   T result = 0;
2199   switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2200     case LDADDOp:
2201       result = data + value;
2202       break;
2203     case LDCLROp:
2204       VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2205       result = data & ~value;
2206       break;
2207     case LDEOROp:
2208       VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2209       result = data ^ value;
2210       break;
2211     case LDSETOp:
2212       VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2213       result = data | value;
2214       break;
2215 
2216     // Signed/Unsigned difference is done via the templated type T.
2217     case LDSMAXOp:
2218     case LDUMAXOp:
2219       result = (data > value) ? data : value;
2220       break;
2221     case LDSMINOp:
2222     case LDUMINOp:
2223       result = (data > value) ? value : data;
2224       break;
2225   }
2226 
2227   if (is_release) {
2228     // Approximate store-release by issuing a full barrier before the store.
2229     __sync_synchronize();
2230   }
2231 
2232   Memory::Write<T>(address, result);
2233   WriteRegister<T>(rt, data, NoRegLog);
2234 
2235   LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2236   LogWrite(address, rs, GetPrintRegisterFormatForSize(element_size));
2237 }
2238 
2239 template <typename T>
AtomicMemorySwapHelper(const Instruction * instr)2240 void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2241   unsigned rs = instr->GetRs();
2242   unsigned rt = instr->GetRt();
2243   unsigned rn = instr->GetRn();
2244 
2245   bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2246   bool is_release = instr->ExtractBit(22) == 1;
2247 
2248   unsigned element_size = sizeof(T);
2249   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2250 
2251   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2252 
2253   T data = Memory::Read<T>(address);
2254   if (is_acquire) {
2255     // Approximate load-acquire by issuing a full barrier after the load.
2256     __sync_synchronize();
2257   }
2258 
2259   if (is_release) {
2260     // Approximate store-release by issuing a full barrier before the store.
2261     __sync_synchronize();
2262   }
2263   Memory::Write<T>(address, ReadRegister<T>(rs));
2264 
2265   WriteRegister<T>(rt, data);
2266 
2267   LogRead(address, rt, GetPrintRegisterFormat(element_size));
2268   LogWrite(address, rs, GetPrintRegisterFormat(element_size));
2269 }
2270 
2271 template <typename T>
LoadAcquireRCpcHelper(const Instruction * instr)2272 void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2273   unsigned rt = instr->GetRt();
2274   unsigned rn = instr->GetRn();
2275 
2276   unsigned element_size = sizeof(T);
2277   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2278 
2279   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2280 
2281   WriteRegister<T>(rt, Memory::Read<T>(address));
2282 
2283   // Approximate load-acquire by issuing a full barrier after the load.
2284   __sync_synchronize();
2285 
2286   LogRead(address, rt, GetPrintRegisterFormat(element_size));
2287 }
2288 
2289 #define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2290   V(LDADD)                                \
2291   V(LDCLR)                                \
2292   V(LDEOR)                                \
2293   V(LDSET)                                \
2294   V(LDUMAX)                               \
2295   V(LDUMIN)
2296 
2297 #define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2298   V(LDSMAX)                              \
2299   V(LDSMIN)
2300 
VisitAtomicMemory(const Instruction * instr)2301 void Simulator::VisitAtomicMemory(const Instruction* instr) {
2302   switch (instr->Mask(AtomicMemoryMask)) {
2303 // clang-format off
2304 #define SIM_FUNC_B(A) \
2305     case A##B:        \
2306     case A##AB:       \
2307     case A##LB:       \
2308     case A##ALB:
2309 #define SIM_FUNC_H(A) \
2310     case A##H:        \
2311     case A##AH:       \
2312     case A##LH:       \
2313     case A##ALH:
2314 #define SIM_FUNC_w(A) \
2315     case A##_w:       \
2316     case A##A_w:      \
2317     case A##L_w:      \
2318     case A##AL_w:
2319 #define SIM_FUNC_x(A) \
2320     case A##_x:       \
2321     case A##A_x:      \
2322     case A##L_x:      \
2323     case A##AL_x:
2324 
2325     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2326       AtomicMemorySimpleHelper<uint8_t>(instr);
2327       break;
2328     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2329       AtomicMemorySimpleHelper<int8_t>(instr);
2330       break;
2331     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2332       AtomicMemorySimpleHelper<uint16_t>(instr);
2333       break;
2334     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2335       AtomicMemorySimpleHelper<int16_t>(instr);
2336       break;
2337     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2338       AtomicMemorySimpleHelper<uint32_t>(instr);
2339       break;
2340     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2341       AtomicMemorySimpleHelper<int32_t>(instr);
2342       break;
2343     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2344       AtomicMemorySimpleHelper<uint64_t>(instr);
2345       break;
2346     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2347       AtomicMemorySimpleHelper<int64_t>(instr);
2348       break;
2349     // clang-format on
2350 
2351     case SWPB:
2352     case SWPAB:
2353     case SWPLB:
2354     case SWPALB:
2355       AtomicMemorySwapHelper<uint8_t>(instr);
2356       break;
2357     case SWPH:
2358     case SWPAH:
2359     case SWPLH:
2360     case SWPALH:
2361       AtomicMemorySwapHelper<uint16_t>(instr);
2362       break;
2363     case SWP_w:
2364     case SWPA_w:
2365     case SWPL_w:
2366     case SWPAL_w:
2367       AtomicMemorySwapHelper<uint32_t>(instr);
2368       break;
2369     case SWP_x:
2370     case SWPA_x:
2371     case SWPL_x:
2372     case SWPAL_x:
2373       AtomicMemorySwapHelper<uint64_t>(instr);
2374       break;
2375     case LDAPRB:
2376       LoadAcquireRCpcHelper<uint8_t>(instr);
2377       break;
2378     case LDAPRH:
2379       LoadAcquireRCpcHelper<uint16_t>(instr);
2380       break;
2381     case LDAPR_w:
2382       LoadAcquireRCpcHelper<uint32_t>(instr);
2383       break;
2384     case LDAPR_x:
2385       LoadAcquireRCpcHelper<uint64_t>(instr);
2386       break;
2387   }
2388 }
2389 
2390 
VisitLoadLiteral(const Instruction * instr)2391 void Simulator::VisitLoadLiteral(const Instruction* instr) {
2392   unsigned rt = instr->GetRt();
2393   uint64_t address = instr->GetLiteralAddress<uint64_t>();
2394 
2395   // Verify that the calculated address is available to the host.
2396   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2397 
2398   switch (instr->Mask(LoadLiteralMask)) {
2399     // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
2400     // print a more detailed log.
2401     case LDR_w_lit:
2402       WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2403       LogRead(address, rt, kPrintWReg);
2404       break;
2405     case LDR_x_lit:
2406       WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2407       LogRead(address, rt, kPrintXReg);
2408       break;
2409     case LDR_s_lit:
2410       WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2411       LogVRead(address, rt, kPrintSReg);
2412       break;
2413     case LDR_d_lit:
2414       WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2415       LogVRead(address, rt, kPrintDReg);
2416       break;
2417     case LDR_q_lit:
2418       WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2419       LogVRead(address, rt, kPrintReg1Q);
2420       break;
2421     case LDRSW_x_lit:
2422       WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2423       LogRead(address, rt, kPrintWReg);
2424       break;
2425 
2426     // Ignore prfm hint instructions.
2427     case PRFM_lit:
2428       break;
2429 
2430     default:
2431       VIXL_UNREACHABLE();
2432   }
2433 
2434   local_monitor_.MaybeClear();
2435 }
2436 
2437 
AddressModeHelper(unsigned addr_reg,int64_t offset,AddrMode addrmode)2438 uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
2439                                        int64_t offset,
2440                                        AddrMode addrmode) {
2441   uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2442 
2443   if ((addr_reg == 31) && ((address % 16) != 0)) {
2444     // When the base register is SP the stack pointer is required to be
2445     // quadword aligned prior to the address calculation and write-backs.
2446     // Misalignment will cause a stack alignment fault.
2447     VIXL_ALIGNMENT_EXCEPTION();
2448   }
2449 
2450   if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
2451     VIXL_ASSERT(offset != 0);
2452     // Only preindex should log the register update here. For Postindex, the
2453     // update will be printed automatically by LogWrittenRegisters _after_ the
2454     // memory access itself is logged.
2455     RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
2456     WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
2457   }
2458 
2459   if ((addrmode == Offset) || (addrmode == PreIndex)) {
2460     address += offset;
2461   }
2462 
2463   // Verify that the calculated address is available to the host.
2464   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2465 
2466   return static_cast<uintptr_t>(address);
2467 }
2468 
2469 
VisitMoveWideImmediate(const Instruction * instr)2470 void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
2471   MoveWideImmediateOp mov_op =
2472       static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
2473   int64_t new_xn_val = 0;
2474 
2475   bool is_64_bits = instr->GetSixtyFourBits() == 1;
2476   // Shift is limited for W operations.
2477   VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
2478 
2479   // Get the shifted immediate.
2480   int64_t shift = instr->GetShiftMoveWide() * 16;
2481   int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
2482                           << shift;
2483 
2484   // Compute the new value.
2485   switch (mov_op) {
2486     case MOVN_w:
2487     case MOVN_x: {
2488       new_xn_val = ~shifted_imm16;
2489       if (!is_64_bits) new_xn_val &= kWRegMask;
2490       break;
2491     }
2492     case MOVK_w:
2493     case MOVK_x: {
2494       unsigned reg_code = instr->GetRd();
2495       int64_t prev_xn_val =
2496           is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
2497       new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
2498       break;
2499     }
2500     case MOVZ_w:
2501     case MOVZ_x: {
2502       new_xn_val = shifted_imm16;
2503       break;
2504     }
2505     default:
2506       VIXL_UNREACHABLE();
2507   }
2508 
2509   // Update the destination register.
2510   WriteXRegister(instr->GetRd(), new_xn_val);
2511 }
2512 
2513 
VisitConditionalSelect(const Instruction * instr)2514 void Simulator::VisitConditionalSelect(const Instruction* instr) {
2515   uint64_t new_val = ReadXRegister(instr->GetRn());
2516 
2517   if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
2518     new_val = ReadXRegister(instr->GetRm());
2519     switch (instr->Mask(ConditionalSelectMask)) {
2520       case CSEL_w:
2521       case CSEL_x:
2522         break;
2523       case CSINC_w:
2524       case CSINC_x:
2525         new_val++;
2526         break;
2527       case CSINV_w:
2528       case CSINV_x:
2529         new_val = ~new_val;
2530         break;
2531       case CSNEG_w:
2532       case CSNEG_x:
2533         new_val = -new_val;
2534         break;
2535       default:
2536         VIXL_UNIMPLEMENTED();
2537     }
2538   }
2539   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2540   WriteRegister(reg_size, instr->GetRd(), new_val);
2541 }
2542 
2543 
2544 // clang-format off
2545 #define PAUTH_MODES(V)                                       \
2546   V(IA,  ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
2547   V(IB,  ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
2548   V(IZA, 0x00000000,         kPACKeyIA, kInstructionPointer) \
2549   V(IZB, 0x00000000,         kPACKeyIB, kInstructionPointer) \
2550   V(DA,  ReadXRegister(src), kPACKeyDA, kDataPointer)        \
2551   V(DB,  ReadXRegister(src), kPACKeyDB, kDataPointer)        \
2552   V(DZA, 0x00000000,         kPACKeyDA, kDataPointer)        \
2553   V(DZB, 0x00000000,         kPACKeyDB, kDataPointer)
2554 // clang-format on
2555 
VisitDataProcessing1Source(const Instruction * instr)2556 void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
2557   unsigned dst = instr->GetRd();
2558   unsigned src = instr->GetRn();
2559 
2560   switch (instr->Mask(DataProcessing1SourceMask)) {
2561 #define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D)     \
2562   case PAC##SUFFIX: {                               \
2563     uint64_t ptr = ReadXRegister(dst);              \
2564     WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D));  \
2565     break;                                          \
2566   }                                                 \
2567   case AUT##SUFFIX: {                               \
2568     uint64_t ptr = ReadXRegister(dst);              \
2569     WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
2570     break;                                          \
2571   }
2572 
2573     PAUTH_MODES(DEFINE_PAUTH_FUNCS)
2574 #undef DEFINE_PAUTH_FUNCS
2575 
2576     case XPACI:
2577       WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
2578       break;
2579     case XPACD:
2580       WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
2581       break;
2582     case RBIT_w:
2583       WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
2584       break;
2585     case RBIT_x:
2586       WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
2587       break;
2588     case REV16_w:
2589       WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
2590       break;
2591     case REV16_x:
2592       WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
2593       break;
2594     case REV_w:
2595       WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
2596       break;
2597     case REV32_x:
2598       WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
2599       break;
2600     case REV_x:
2601       WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
2602       break;
2603     case CLZ_w:
2604       WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
2605       break;
2606     case CLZ_x:
2607       WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
2608       break;
2609     case CLS_w:
2610       WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
2611       break;
2612     case CLS_x:
2613       WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
2614       break;
2615     default:
2616       VIXL_UNIMPLEMENTED();
2617   }
2618 }
2619 
2620 
Poly32Mod2(unsigned n,uint64_t data,uint32_t poly)2621 uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
2622   VIXL_ASSERT((n > 32) && (n <= 64));
2623   for (unsigned i = (n - 1); i >= 32; i--) {
2624     if (((data >> i) & 1) != 0) {
2625       uint64_t polysh32 = (uint64_t)poly << (i - 32);
2626       uint64_t mask = (UINT64_C(1) << i) - 1;
2627       data = ((data & mask) ^ polysh32);
2628     }
2629   }
2630   return data & 0xffffffff;
2631 }
2632 
2633 
2634 template <typename T>
Crc32Checksum(uint32_t acc,T val,uint32_t poly)2635 uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
2636   unsigned size = sizeof(val) * 8;  // Number of bits in type T.
2637   VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
2638   uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
2639   uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
2640   return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
2641 }
2642 
2643 
Crc32Checksum(uint32_t acc,uint64_t val,uint32_t poly)2644 uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
2645   // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
2646   // the CRC of each 32-bit word sequentially.
2647   acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
2648   return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
2649 }
2650 
2651 
VisitDataProcessing2Source(const Instruction * instr)2652 void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
2653   Shift shift_op = NO_SHIFT;
2654   int64_t result = 0;
2655   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2656 
2657   switch (instr->Mask(DataProcessing2SourceMask)) {
2658     case SDIV_w: {
2659       int32_t rn = ReadWRegister(instr->GetRn());
2660       int32_t rm = ReadWRegister(instr->GetRm());
2661       if ((rn == kWMinInt) && (rm == -1)) {
2662         result = kWMinInt;
2663       } else if (rm == 0) {
2664         // Division by zero can be trapped, but not on A-class processors.
2665         result = 0;
2666       } else {
2667         result = rn / rm;
2668       }
2669       break;
2670     }
2671     case SDIV_x: {
2672       int64_t rn = ReadXRegister(instr->GetRn());
2673       int64_t rm = ReadXRegister(instr->GetRm());
2674       if ((rn == kXMinInt) && (rm == -1)) {
2675         result = kXMinInt;
2676       } else if (rm == 0) {
2677         // Division by zero can be trapped, but not on A-class processors.
2678         result = 0;
2679       } else {
2680         result = rn / rm;
2681       }
2682       break;
2683     }
2684     case UDIV_w: {
2685       uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
2686       uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
2687       if (rm == 0) {
2688         // Division by zero can be trapped, but not on A-class processors.
2689         result = 0;
2690       } else {
2691         result = rn / rm;
2692       }
2693       break;
2694     }
2695     case UDIV_x: {
2696       uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
2697       uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
2698       if (rm == 0) {
2699         // Division by zero can be trapped, but not on A-class processors.
2700         result = 0;
2701       } else {
2702         result = rn / rm;
2703       }
2704       break;
2705     }
2706     case LSLV_w:
2707     case LSLV_x:
2708       shift_op = LSL;
2709       break;
2710     case LSRV_w:
2711     case LSRV_x:
2712       shift_op = LSR;
2713       break;
2714     case ASRV_w:
2715     case ASRV_x:
2716       shift_op = ASR;
2717       break;
2718     case RORV_w:
2719     case RORV_x:
2720       shift_op = ROR;
2721       break;
2722     case PACGA: {
2723       uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
2724       uint64_t src = static_cast<uint64_t>(
2725           ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
2726       uint64_t code = ComputePAC(dst, src, kPACKeyGA);
2727       result = code & 0xffffffff00000000;
2728       break;
2729     }
2730     case CRC32B: {
2731       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2732       uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
2733       result = Crc32Checksum(acc, val, CRC32_POLY);
2734       break;
2735     }
2736     case CRC32H: {
2737       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2738       uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
2739       result = Crc32Checksum(acc, val, CRC32_POLY);
2740       break;
2741     }
2742     case CRC32W: {
2743       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2744       uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
2745       result = Crc32Checksum(acc, val, CRC32_POLY);
2746       break;
2747     }
2748     case CRC32X: {
2749       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2750       uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
2751       result = Crc32Checksum(acc, val, CRC32_POLY);
2752       reg_size = kWRegSize;
2753       break;
2754     }
2755     case CRC32CB: {
2756       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2757       uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
2758       result = Crc32Checksum(acc, val, CRC32C_POLY);
2759       break;
2760     }
2761     case CRC32CH: {
2762       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2763       uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
2764       result = Crc32Checksum(acc, val, CRC32C_POLY);
2765       break;
2766     }
2767     case CRC32CW: {
2768       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2769       uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
2770       result = Crc32Checksum(acc, val, CRC32C_POLY);
2771       break;
2772     }
2773     case CRC32CX: {
2774       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2775       uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
2776       result = Crc32Checksum(acc, val, CRC32C_POLY);
2777       reg_size = kWRegSize;
2778       break;
2779     }
2780     default:
2781       VIXL_UNIMPLEMENTED();
2782   }
2783 
2784   if (shift_op != NO_SHIFT) {
2785     // Shift distance encoded in the least-significant five/six bits of the
2786     // register.
2787     int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
2788     unsigned shift = ReadWRegister(instr->GetRm()) & mask;
2789     result = ShiftOperand(reg_size,
2790                           ReadRegister(reg_size, instr->GetRn()),
2791                           shift_op,
2792                           shift);
2793   }
2794   WriteRegister(reg_size, instr->GetRd(), result);
2795 }
2796 
2797 
2798 // The algorithm used is adapted from the one described in section 8.2 of
2799 //   Hacker's Delight, by Henry S. Warren, Jr.
2800 template <typename T>
MultiplyHigh(T u,T v)2801 static int64_t MultiplyHigh(T u, T v) {
2802   uint64_t u0, v0, w0, u1, v1, w1, w2, t;
2803   uint64_t sign_mask = UINT64_C(0x8000000000000000);
2804   uint64_t sign_ext = 0;
2805   if (std::numeric_limits<T>::is_signed) {
2806     sign_ext = UINT64_C(0xffffffff00000000);
2807   }
2808 
2809   VIXL_ASSERT(sizeof(u) == sizeof(uint64_t));
2810   VIXL_ASSERT(sizeof(u) == sizeof(u0));
2811 
2812   u0 = u & 0xffffffff;
2813   u1 = u >> 32 | (((u & sign_mask) != 0) ? sign_ext : 0);
2814   v0 = v & 0xffffffff;
2815   v1 = v >> 32 | (((v & sign_mask) != 0) ? sign_ext : 0);
2816 
2817   w0 = u0 * v0;
2818   t = u1 * v0 + (w0 >> 32);
2819 
2820   w1 = t & 0xffffffff;
2821   w2 = t >> 32 | (((t & sign_mask) != 0) ? sign_ext : 0);
2822   w1 = u0 * v1 + w1;
2823   w1 = w1 >> 32 | (((w1 & sign_mask) != 0) ? sign_ext : 0);
2824 
2825   uint64_t value = u1 * v1 + w2 + w1;
2826   int64_t result;
2827   memcpy(&result, &value, sizeof(result));
2828   return result;
2829 }
2830 
2831 
VisitDataProcessing3Source(const Instruction * instr)2832 void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
2833   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2834 
2835   uint64_t result = 0;
2836   // Extract and sign- or zero-extend 32-bit arguments for widening operations.
2837   uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
2838   uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
2839   int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
2840   int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
2841   uint64_t rn_u64 = ReadXRegister(instr->GetRn());
2842   uint64_t rm_u64 = ReadXRegister(instr->GetRm());
2843   switch (instr->Mask(DataProcessing3SourceMask)) {
2844     case MADD_w:
2845     case MADD_x:
2846       result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
2847       break;
2848     case MSUB_w:
2849     case MSUB_x:
2850       result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
2851       break;
2852     case SMADDL_x:
2853       result = ReadXRegister(instr->GetRa()) +
2854                static_cast<uint64_t>(rn_s32 * rm_s32);
2855       break;
2856     case SMSUBL_x:
2857       result = ReadXRegister(instr->GetRa()) -
2858                static_cast<uint64_t>(rn_s32 * rm_s32);
2859       break;
2860     case UMADDL_x:
2861       result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
2862       break;
2863     case UMSUBL_x:
2864       result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
2865       break;
2866     case UMULH_x:
2867       result = MultiplyHigh(ReadRegister<uint64_t>(instr->GetRn()),
2868                             ReadRegister<uint64_t>(instr->GetRm()));
2869       break;
2870     case SMULH_x:
2871       result = MultiplyHigh(ReadXRegister(instr->GetRn()),
2872                             ReadXRegister(instr->GetRm()));
2873       break;
2874     default:
2875       VIXL_UNIMPLEMENTED();
2876   }
2877   WriteRegister(reg_size, instr->GetRd(), result);
2878 }
2879 
2880 
VisitBitfield(const Instruction * instr)2881 void Simulator::VisitBitfield(const Instruction* instr) {
2882   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2883   int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
2884   int R = instr->GetImmR();
2885   int S = instr->GetImmS();
2886   int diff = S - R;
2887   uint64_t mask;
2888   if (diff >= 0) {
2889     mask = ~UINT64_C(0) >> (64 - (diff + 1));
2890     mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
2891   } else {
2892     mask = ~UINT64_C(0) >> (64 - (S + 1));
2893     mask = RotateRight(mask, R, reg_size);
2894     diff += reg_size;
2895   }
2896 
2897   // inzero indicates if the extracted bitfield is inserted into the
2898   // destination register value or in zero.
2899   // If extend is true, extend the sign of the extracted bitfield.
2900   bool inzero = false;
2901   bool extend = false;
2902   switch (instr->Mask(BitfieldMask)) {
2903     case BFM_x:
2904     case BFM_w:
2905       break;
2906     case SBFM_x:
2907     case SBFM_w:
2908       inzero = true;
2909       extend = true;
2910       break;
2911     case UBFM_x:
2912     case UBFM_w:
2913       inzero = true;
2914       break;
2915     default:
2916       VIXL_UNIMPLEMENTED();
2917   }
2918 
2919   uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
2920   uint64_t src = ReadRegister(reg_size, instr->GetRn());
2921   // Rotate source bitfield into place.
2922   uint64_t result = RotateRight(src, R, reg_size);
2923   // Determine the sign extension.
2924   uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
2925   uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
2926 
2927   // Merge sign extension, dest/zero and bitfield.
2928   result = signbits | (result & mask) | (dst & ~mask);
2929 
2930   WriteRegister(reg_size, instr->GetRd(), result);
2931 }
2932 
2933 
VisitExtract(const Instruction * instr)2934 void Simulator::VisitExtract(const Instruction* instr) {
2935   unsigned lsb = instr->GetImmS();
2936   unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
2937   uint64_t low_res =
2938       static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
2939   uint64_t high_res =
2940       (lsb == 0) ? 0 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
2941                            << (reg_size - lsb);
2942   WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
2943 }
2944 
2945 
VisitFPImmediate(const Instruction * instr)2946 void Simulator::VisitFPImmediate(const Instruction* instr) {
2947   AssertSupportedFPCR();
2948   unsigned dest = instr->GetRd();
2949   switch (instr->Mask(FPImmediateMask)) {
2950     case FMOV_h_imm:
2951       WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
2952       break;
2953     case FMOV_s_imm:
2954       WriteSRegister(dest, instr->GetImmFP32());
2955       break;
2956     case FMOV_d_imm:
2957       WriteDRegister(dest, instr->GetImmFP64());
2958       break;
2959     default:
2960       VIXL_UNREACHABLE();
2961   }
2962 }
2963 
2964 
VisitFPIntegerConvert(const Instruction * instr)2965 void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
2966   AssertSupportedFPCR();
2967 
2968   unsigned dst = instr->GetRd();
2969   unsigned src = instr->GetRn();
2970 
2971   FPRounding round = ReadRMode();
2972 
2973   switch (instr->Mask(FPIntegerConvertMask)) {
2974     case FCVTAS_wh:
2975       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
2976       break;
2977     case FCVTAS_xh:
2978       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
2979       break;
2980     case FCVTAS_ws:
2981       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
2982       break;
2983     case FCVTAS_xs:
2984       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
2985       break;
2986     case FCVTAS_wd:
2987       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
2988       break;
2989     case FCVTAS_xd:
2990       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
2991       break;
2992     case FCVTAU_wh:
2993       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
2994       break;
2995     case FCVTAU_xh:
2996       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
2997       break;
2998     case FCVTAU_ws:
2999       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3000       break;
3001     case FCVTAU_xs:
3002       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3003       break;
3004     case FCVTAU_wd:
3005       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3006       break;
3007     case FCVTAU_xd:
3008       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3009       break;
3010     case FCVTMS_wh:
3011       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3012       break;
3013     case FCVTMS_xh:
3014       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3015       break;
3016     case FCVTMS_ws:
3017       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3018       break;
3019     case FCVTMS_xs:
3020       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3021       break;
3022     case FCVTMS_wd:
3023       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3024       break;
3025     case FCVTMS_xd:
3026       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3027       break;
3028     case FCVTMU_wh:
3029       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3030       break;
3031     case FCVTMU_xh:
3032       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3033       break;
3034     case FCVTMU_ws:
3035       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3036       break;
3037     case FCVTMU_xs:
3038       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3039       break;
3040     case FCVTMU_wd:
3041       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3042       break;
3043     case FCVTMU_xd:
3044       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3045       break;
3046     case FCVTPS_wh:
3047       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3048       break;
3049     case FCVTPS_xh:
3050       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3051       break;
3052     case FCVTPS_ws:
3053       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3054       break;
3055     case FCVTPS_xs:
3056       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3057       break;
3058     case FCVTPS_wd:
3059       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3060       break;
3061     case FCVTPS_xd:
3062       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3063       break;
3064     case FCVTPU_wh:
3065       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3066       break;
3067     case FCVTPU_xh:
3068       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3069       break;
3070     case FCVTPU_ws:
3071       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3072       break;
3073     case FCVTPU_xs:
3074       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3075       break;
3076     case FCVTPU_wd:
3077       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3078       break;
3079     case FCVTPU_xd:
3080       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3081       break;
3082     case FCVTNS_wh:
3083       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3084       break;
3085     case FCVTNS_xh:
3086       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3087       break;
3088     case FCVTNS_ws:
3089       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3090       break;
3091     case FCVTNS_xs:
3092       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3093       break;
3094     case FCVTNS_wd:
3095       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3096       break;
3097     case FCVTNS_xd:
3098       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3099       break;
3100     case FCVTNU_wh:
3101       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3102       break;
3103     case FCVTNU_xh:
3104       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3105       break;
3106     case FCVTNU_ws:
3107       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3108       break;
3109     case FCVTNU_xs:
3110       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3111       break;
3112     case FCVTNU_wd:
3113       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3114       break;
3115     case FCVTNU_xd:
3116       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3117       break;
3118     case FCVTZS_wh:
3119       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3120       break;
3121     case FCVTZS_xh:
3122       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3123       break;
3124     case FCVTZS_ws:
3125       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3126       break;
3127     case FCVTZS_xs:
3128       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3129       break;
3130     case FCVTZS_wd:
3131       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3132       break;
3133     case FCVTZS_xd:
3134       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3135       break;
3136     case FCVTZU_wh:
3137       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3138       break;
3139     case FCVTZU_xh:
3140       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3141       break;
3142     case FCVTZU_ws:
3143       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3144       break;
3145     case FCVTZU_xs:
3146       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3147       break;
3148     case FCVTZU_wd:
3149       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3150       break;
3151     case FCVTZU_xd:
3152       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3153       break;
3154     case FJCVTZS:
3155       WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3156       break;
3157     case FMOV_hw:
3158       WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3159       break;
3160     case FMOV_wh:
3161       WriteWRegister(dst, ReadHRegisterBits(src));
3162       break;
3163     case FMOV_xh:
3164       WriteXRegister(dst, ReadHRegisterBits(src));
3165       break;
3166     case FMOV_hx:
3167       WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3168       break;
3169     case FMOV_ws:
3170       WriteWRegister(dst, ReadSRegisterBits(src));
3171       break;
3172     case FMOV_xd:
3173       WriteXRegister(dst, ReadDRegisterBits(src));
3174       break;
3175     case FMOV_sw:
3176       WriteSRegisterBits(dst, ReadWRegister(src));
3177       break;
3178     case FMOV_dx:
3179       WriteDRegisterBits(dst, ReadXRegister(src));
3180       break;
3181     case FMOV_d1_x:
3182       LogicVRegister(ReadVRegister(dst))
3183           .SetUint(kFormatD, 1, ReadXRegister(src));
3184       break;
3185     case FMOV_x_d1:
3186       WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3187       break;
3188 
3189     // A 32-bit input can be handled in the same way as a 64-bit input, since
3190     // the sign- or zero-extension will not affect the conversion.
3191     case SCVTF_dx:
3192       WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3193       break;
3194     case SCVTF_dw:
3195       WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3196       break;
3197     case UCVTF_dx:
3198       WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3199       break;
3200     case UCVTF_dw: {
3201       WriteDRegister(dst,
3202                      UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
3203       break;
3204     }
3205     case SCVTF_sx:
3206       WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3207       break;
3208     case SCVTF_sw:
3209       WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3210       break;
3211     case UCVTF_sx:
3212       WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3213       break;
3214     case UCVTF_sw: {
3215       WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3216       break;
3217     }
3218     case SCVTF_hx:
3219       WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3220       break;
3221     case SCVTF_hw:
3222       WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3223       break;
3224     case UCVTF_hx:
3225       WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3226       break;
3227     case UCVTF_hw: {
3228       WriteHRegister(dst,
3229                      UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
3230       break;
3231     }
3232 
3233     default:
3234       VIXL_UNREACHABLE();
3235   }
3236 }
3237 
3238 
VisitFPFixedPointConvert(const Instruction * instr)3239 void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3240   AssertSupportedFPCR();
3241 
3242   unsigned dst = instr->GetRd();
3243   unsigned src = instr->GetRn();
3244   int fbits = 64 - instr->GetFPScale();
3245 
3246   FPRounding round = ReadRMode();
3247 
3248   switch (instr->Mask(FPFixedPointConvertMask)) {
3249     // A 32-bit input can be handled in the same way as a 64-bit input, since
3250     // the sign- or zero-extension will not affect the conversion.
3251     case SCVTF_dx_fixed:
3252       WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3253       break;
3254     case SCVTF_dw_fixed:
3255       WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3256       break;
3257     case UCVTF_dx_fixed:
3258       WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3259       break;
3260     case UCVTF_dw_fixed: {
3261       WriteDRegister(dst,
3262                      UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
3263       break;
3264     }
3265     case SCVTF_sx_fixed:
3266       WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3267       break;
3268     case SCVTF_sw_fixed:
3269       WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3270       break;
3271     case UCVTF_sx_fixed:
3272       WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3273       break;
3274     case UCVTF_sw_fixed: {
3275       WriteSRegister(dst,
3276                      UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3277       break;
3278     }
3279     case SCVTF_hx_fixed:
3280       WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3281       break;
3282     case SCVTF_hw_fixed:
3283       WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3284       break;
3285     case UCVTF_hx_fixed:
3286       WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3287       break;
3288     case UCVTF_hw_fixed: {
3289       WriteHRegister(dst,
3290                      UFixedToFloat16(ReadRegister<uint32_t>(src),
3291                                      fbits,
3292                                      round));
3293       break;
3294     }
3295     case FCVTZS_xd_fixed:
3296       WriteXRegister(dst,
3297                      FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3298                                FPZero));
3299       break;
3300     case FCVTZS_wd_fixed:
3301       WriteWRegister(dst,
3302                      FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3303                                FPZero));
3304       break;
3305     case FCVTZU_xd_fixed:
3306       WriteXRegister(dst,
3307                      FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3308                                 FPZero));
3309       break;
3310     case FCVTZU_wd_fixed:
3311       WriteWRegister(dst,
3312                      FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3313                                 FPZero));
3314       break;
3315     case FCVTZS_xs_fixed:
3316       WriteXRegister(dst,
3317                      FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3318                                FPZero));
3319       break;
3320     case FCVTZS_ws_fixed:
3321       WriteWRegister(dst,
3322                      FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3323                                FPZero));
3324       break;
3325     case FCVTZU_xs_fixed:
3326       WriteXRegister(dst,
3327                      FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3328                                 FPZero));
3329       break;
3330     case FCVTZU_ws_fixed:
3331       WriteWRegister(dst,
3332                      FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3333                                 FPZero));
3334       break;
3335     case FCVTZS_xh_fixed: {
3336       double output =
3337           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3338       WriteXRegister(dst, FPToInt64(output, FPZero));
3339       break;
3340     }
3341     case FCVTZS_wh_fixed: {
3342       double output =
3343           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3344       WriteWRegister(dst, FPToInt32(output, FPZero));
3345       break;
3346     }
3347     case FCVTZU_xh_fixed: {
3348       double output =
3349           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3350       WriteXRegister(dst, FPToUInt64(output, FPZero));
3351       break;
3352     }
3353     case FCVTZU_wh_fixed: {
3354       double output =
3355           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3356       WriteWRegister(dst, FPToUInt32(output, FPZero));
3357       break;
3358     }
3359     default:
3360       VIXL_UNREACHABLE();
3361   }
3362 }
3363 
3364 
VisitFPCompare(const Instruction * instr)3365 void Simulator::VisitFPCompare(const Instruction* instr) {
3366   AssertSupportedFPCR();
3367 
3368   FPTrapFlags trap = DisableTrap;
3369   switch (instr->Mask(FPCompareMask)) {
3370     case FCMPE_h:
3371       trap = EnableTrap;
3372       VIXL_FALLTHROUGH();
3373     case FCMP_h:
3374       FPCompare(ReadHRegister(instr->GetRn()),
3375                 ReadHRegister(instr->GetRm()),
3376                 trap);
3377       break;
3378     case FCMPE_s:
3379       trap = EnableTrap;
3380       VIXL_FALLTHROUGH();
3381     case FCMP_s:
3382       FPCompare(ReadSRegister(instr->GetRn()),
3383                 ReadSRegister(instr->GetRm()),
3384                 trap);
3385       break;
3386     case FCMPE_d:
3387       trap = EnableTrap;
3388       VIXL_FALLTHROUGH();
3389     case FCMP_d:
3390       FPCompare(ReadDRegister(instr->GetRn()),
3391                 ReadDRegister(instr->GetRm()),
3392                 trap);
3393       break;
3394     case FCMPE_h_zero:
3395       trap = EnableTrap;
3396       VIXL_FALLTHROUGH();
3397     case FCMP_h_zero:
3398       FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3399       break;
3400     case FCMPE_s_zero:
3401       trap = EnableTrap;
3402       VIXL_FALLTHROUGH();
3403     case FCMP_s_zero:
3404       FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3405       break;
3406     case FCMPE_d_zero:
3407       trap = EnableTrap;
3408       VIXL_FALLTHROUGH();
3409     case FCMP_d_zero:
3410       FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
3411       break;
3412     default:
3413       VIXL_UNIMPLEMENTED();
3414   }
3415 }
3416 
3417 
VisitFPConditionalCompare(const Instruction * instr)3418 void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
3419   AssertSupportedFPCR();
3420 
3421   FPTrapFlags trap = DisableTrap;
3422   switch (instr->Mask(FPConditionalCompareMask)) {
3423     case FCCMPE_h:
3424       trap = EnableTrap;
3425       VIXL_FALLTHROUGH();
3426     case FCCMP_h:
3427       if (ConditionPassed(instr->GetCondition())) {
3428         FPCompare(ReadHRegister(instr->GetRn()),
3429                   ReadHRegister(instr->GetRm()),
3430                   trap);
3431       } else {
3432         ReadNzcv().SetFlags(instr->GetNzcv());
3433         LogSystemRegister(NZCV);
3434       }
3435       break;
3436     case FCCMPE_s:
3437       trap = EnableTrap;
3438       VIXL_FALLTHROUGH();
3439     case FCCMP_s:
3440       if (ConditionPassed(instr->GetCondition())) {
3441         FPCompare(ReadSRegister(instr->GetRn()),
3442                   ReadSRegister(instr->GetRm()),
3443                   trap);
3444       } else {
3445         ReadNzcv().SetFlags(instr->GetNzcv());
3446         LogSystemRegister(NZCV);
3447       }
3448       break;
3449     case FCCMPE_d:
3450       trap = EnableTrap;
3451       VIXL_FALLTHROUGH();
3452     case FCCMP_d:
3453       if (ConditionPassed(instr->GetCondition())) {
3454         FPCompare(ReadDRegister(instr->GetRn()),
3455                   ReadDRegister(instr->GetRm()),
3456                   trap);
3457       } else {
3458         ReadNzcv().SetFlags(instr->GetNzcv());
3459         LogSystemRegister(NZCV);
3460       }
3461       break;
3462     default:
3463       VIXL_UNIMPLEMENTED();
3464   }
3465 }
3466 
3467 
VisitFPConditionalSelect(const Instruction * instr)3468 void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
3469   AssertSupportedFPCR();
3470 
3471   Instr selected;
3472   if (ConditionPassed(instr->GetCondition())) {
3473     selected = instr->GetRn();
3474   } else {
3475     selected = instr->GetRm();
3476   }
3477 
3478   switch (instr->Mask(FPConditionalSelectMask)) {
3479     case FCSEL_h:
3480       WriteHRegister(instr->GetRd(), ReadHRegister(selected));
3481       break;
3482     case FCSEL_s:
3483       WriteSRegister(instr->GetRd(), ReadSRegister(selected));
3484       break;
3485     case FCSEL_d:
3486       WriteDRegister(instr->GetRd(), ReadDRegister(selected));
3487       break;
3488     default:
3489       VIXL_UNIMPLEMENTED();
3490   }
3491 }
3492 
3493 
VisitFPDataProcessing1Source(const Instruction * instr)3494 void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
3495   AssertSupportedFPCR();
3496 
3497   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
3498   VectorFormat vform;
3499   switch (instr->Mask(FPTypeMask)) {
3500     default:
3501       VIXL_UNREACHABLE_OR_FALLTHROUGH();
3502     case FP64:
3503       vform = kFormatD;
3504       break;
3505     case FP32:
3506       vform = kFormatS;
3507       break;
3508     case FP16:
3509       vform = kFormatH;
3510       break;
3511   }
3512 
3513   SimVRegister& rd = ReadVRegister(instr->GetRd());
3514   SimVRegister& rn = ReadVRegister(instr->GetRn());
3515   bool inexact_exception = false;
3516   FrintMode frint_mode = kFrintToInteger;
3517 
3518   unsigned fd = instr->GetRd();
3519   unsigned fn = instr->GetRn();
3520 
3521   switch (instr->Mask(FPDataProcessing1SourceMask)) {
3522     case FMOV_h:
3523       WriteHRegister(fd, ReadHRegister(fn));
3524       return;
3525     case FMOV_s:
3526       WriteSRegister(fd, ReadSRegister(fn));
3527       return;
3528     case FMOV_d:
3529       WriteDRegister(fd, ReadDRegister(fn));
3530       return;
3531     case FABS_h:
3532     case FABS_s:
3533     case FABS_d:
3534       fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
3535       // Explicitly log the register update whilst we have type information.
3536       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3537       return;
3538     case FNEG_h:
3539     case FNEG_s:
3540     case FNEG_d:
3541       fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
3542       // Explicitly log the register update whilst we have type information.
3543       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3544       return;
3545     case FCVT_ds:
3546       WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
3547       return;
3548     case FCVT_sd:
3549       WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
3550       return;
3551     case FCVT_hs:
3552       WriteHRegister(fd,
3553                      Float16ToRawbits(
3554                          FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
3555       return;
3556     case FCVT_sh:
3557       WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
3558       return;
3559     case FCVT_dh:
3560       WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
3561       return;
3562     case FCVT_hd:
3563       WriteHRegister(fd,
3564                      Float16ToRawbits(
3565                          FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
3566       return;
3567     case FSQRT_h:
3568     case FSQRT_s:
3569     case FSQRT_d:
3570       fsqrt(vform, rd, rn);
3571       // Explicitly log the register update whilst we have type information.
3572       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3573       return;
3574     case FRINT32X_s:
3575     case FRINT32X_d:
3576       inexact_exception = true;
3577       frint_mode = kFrintToInt32;
3578       break;  // Use FPCR rounding mode.
3579     case FRINT64X_s:
3580     case FRINT64X_d:
3581       inexact_exception = true;
3582       frint_mode = kFrintToInt64;
3583       break;  // Use FPCR rounding mode.
3584     case FRINT32Z_s:
3585     case FRINT32Z_d:
3586       inexact_exception = true;
3587       frint_mode = kFrintToInt32;
3588       fpcr_rounding = FPZero;
3589       break;
3590     case FRINT64Z_s:
3591     case FRINT64Z_d:
3592       inexact_exception = true;
3593       frint_mode = kFrintToInt64;
3594       fpcr_rounding = FPZero;
3595       break;
3596     case FRINTI_h:
3597     case FRINTI_s:
3598     case FRINTI_d:
3599       break;  // Use FPCR rounding mode.
3600     case FRINTX_h:
3601     case FRINTX_s:
3602     case FRINTX_d:
3603       inexact_exception = true;
3604       break;
3605     case FRINTA_h:
3606     case FRINTA_s:
3607     case FRINTA_d:
3608       fpcr_rounding = FPTieAway;
3609       break;
3610     case FRINTM_h:
3611     case FRINTM_s:
3612     case FRINTM_d:
3613       fpcr_rounding = FPNegativeInfinity;
3614       break;
3615     case FRINTN_h:
3616     case FRINTN_s:
3617     case FRINTN_d:
3618       fpcr_rounding = FPTieEven;
3619       break;
3620     case FRINTP_h:
3621     case FRINTP_s:
3622     case FRINTP_d:
3623       fpcr_rounding = FPPositiveInfinity;
3624       break;
3625     case FRINTZ_h:
3626     case FRINTZ_s:
3627     case FRINTZ_d:
3628       fpcr_rounding = FPZero;
3629       break;
3630     default:
3631       VIXL_UNIMPLEMENTED();
3632   }
3633 
3634   // Only FRINT* instructions fall through the switch above.
3635   frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
3636   // Explicitly log the register update whilst we have type information.
3637   LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3638 }
3639 
3640 
VisitFPDataProcessing2Source(const Instruction * instr)3641 void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
3642   AssertSupportedFPCR();
3643 
3644   VectorFormat vform;
3645   switch (instr->Mask(FPTypeMask)) {
3646     default:
3647       VIXL_UNREACHABLE_OR_FALLTHROUGH();
3648     case FP64:
3649       vform = kFormatD;
3650       break;
3651     case FP32:
3652       vform = kFormatS;
3653       break;
3654     case FP16:
3655       vform = kFormatH;
3656       break;
3657   }
3658   SimVRegister& rd = ReadVRegister(instr->GetRd());
3659   SimVRegister& rn = ReadVRegister(instr->GetRn());
3660   SimVRegister& rm = ReadVRegister(instr->GetRm());
3661 
3662   switch (instr->Mask(FPDataProcessing2SourceMask)) {
3663     case FADD_h:
3664     case FADD_s:
3665     case FADD_d:
3666       fadd(vform, rd, rn, rm);
3667       break;
3668     case FSUB_h:
3669     case FSUB_s:
3670     case FSUB_d:
3671       fsub(vform, rd, rn, rm);
3672       break;
3673     case FMUL_h:
3674     case FMUL_s:
3675     case FMUL_d:
3676       fmul(vform, rd, rn, rm);
3677       break;
3678     case FNMUL_h:
3679     case FNMUL_s:
3680     case FNMUL_d:
3681       fnmul(vform, rd, rn, rm);
3682       break;
3683     case FDIV_h:
3684     case FDIV_s:
3685     case FDIV_d:
3686       fdiv(vform, rd, rn, rm);
3687       break;
3688     case FMAX_h:
3689     case FMAX_s:
3690     case FMAX_d:
3691       fmax(vform, rd, rn, rm);
3692       break;
3693     case FMIN_h:
3694     case FMIN_s:
3695     case FMIN_d:
3696       fmin(vform, rd, rn, rm);
3697       break;
3698     case FMAXNM_h:
3699     case FMAXNM_s:
3700     case FMAXNM_d:
3701       fmaxnm(vform, rd, rn, rm);
3702       break;
3703     case FMINNM_h:
3704     case FMINNM_s:
3705     case FMINNM_d:
3706       fminnm(vform, rd, rn, rm);
3707       break;
3708     default:
3709       VIXL_UNREACHABLE();
3710   }
3711   // Explicitly log the register update whilst we have type information.
3712   LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
3713 }
3714 
3715 
VisitFPDataProcessing3Source(const Instruction * instr)3716 void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
3717   AssertSupportedFPCR();
3718 
3719   unsigned fd = instr->GetRd();
3720   unsigned fn = instr->GetRn();
3721   unsigned fm = instr->GetRm();
3722   unsigned fa = instr->GetRa();
3723 
3724   switch (instr->Mask(FPDataProcessing3SourceMask)) {
3725     // fd = fa +/- (fn * fm)
3726     case FMADD_h:
3727       WriteHRegister(fd,
3728                      FPMulAdd(ReadHRegister(fa),
3729                               ReadHRegister(fn),
3730                               ReadHRegister(fm)));
3731       break;
3732     case FMSUB_h:
3733       WriteHRegister(fd,
3734                      FPMulAdd(ReadHRegister(fa),
3735                               -ReadHRegister(fn),
3736                               ReadHRegister(fm)));
3737       break;
3738     case FMADD_s:
3739       WriteSRegister(fd,
3740                      FPMulAdd(ReadSRegister(fa),
3741                               ReadSRegister(fn),
3742                               ReadSRegister(fm)));
3743       break;
3744     case FMSUB_s:
3745       WriteSRegister(fd,
3746                      FPMulAdd(ReadSRegister(fa),
3747                               -ReadSRegister(fn),
3748                               ReadSRegister(fm)));
3749       break;
3750     case FMADD_d:
3751       WriteDRegister(fd,
3752                      FPMulAdd(ReadDRegister(fa),
3753                               ReadDRegister(fn),
3754                               ReadDRegister(fm)));
3755       break;
3756     case FMSUB_d:
3757       WriteDRegister(fd,
3758                      FPMulAdd(ReadDRegister(fa),
3759                               -ReadDRegister(fn),
3760                               ReadDRegister(fm)));
3761       break;
3762     // Negated variants of the above.
3763     case FNMADD_h:
3764       WriteHRegister(fd,
3765                      FPMulAdd(-ReadHRegister(fa),
3766                               -ReadHRegister(fn),
3767                               ReadHRegister(fm)));
3768       break;
3769     case FNMSUB_h:
3770       WriteHRegister(fd,
3771                      FPMulAdd(-ReadHRegister(fa),
3772                               ReadHRegister(fn),
3773                               ReadHRegister(fm)));
3774       break;
3775     case FNMADD_s:
3776       WriteSRegister(fd,
3777                      FPMulAdd(-ReadSRegister(fa),
3778                               -ReadSRegister(fn),
3779                               ReadSRegister(fm)));
3780       break;
3781     case FNMSUB_s:
3782       WriteSRegister(fd,
3783                      FPMulAdd(-ReadSRegister(fa),
3784                               ReadSRegister(fn),
3785                               ReadSRegister(fm)));
3786       break;
3787     case FNMADD_d:
3788       WriteDRegister(fd,
3789                      FPMulAdd(-ReadDRegister(fa),
3790                               -ReadDRegister(fn),
3791                               ReadDRegister(fm)));
3792       break;
3793     case FNMSUB_d:
3794       WriteDRegister(fd,
3795                      FPMulAdd(-ReadDRegister(fa),
3796                               ReadDRegister(fn),
3797                               ReadDRegister(fm)));
3798       break;
3799     default:
3800       VIXL_UNIMPLEMENTED();
3801   }
3802 }
3803 
3804 
FPProcessNaNs(const Instruction * instr)3805 bool Simulator::FPProcessNaNs(const Instruction* instr) {
3806   unsigned fd = instr->GetRd();
3807   unsigned fn = instr->GetRn();
3808   unsigned fm = instr->GetRm();
3809   bool done = false;
3810 
3811   if (instr->Mask(FP64) == FP64) {
3812     double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
3813     if (IsNaN(result)) {
3814       WriteDRegister(fd, result);
3815       done = true;
3816     }
3817   } else if (instr->Mask(FP32) == FP32) {
3818     float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
3819     if (IsNaN(result)) {
3820       WriteSRegister(fd, result);
3821       done = true;
3822     }
3823   } else {
3824     VIXL_ASSERT(instr->Mask(FP16) == FP16);
3825     VIXL_UNIMPLEMENTED();
3826   }
3827 
3828   return done;
3829 }
3830 
3831 
SysOp_W(int op,int64_t val)3832 void Simulator::SysOp_W(int op, int64_t val) {
3833   switch (op) {
3834     case IVAU:
3835     case CVAC:
3836     case CVAU:
3837     case CVAP:
3838     case CVADP:
3839     case CIVAC: {
3840       // Perform a dummy memory access to ensure that we have read access
3841       // to the specified address.
3842       volatile uint8_t y = Memory::Read<uint8_t>(val);
3843       USE(y);
3844       // TODO: Implement "case ZVA:".
3845       break;
3846     }
3847     default:
3848       VIXL_UNIMPLEMENTED();
3849   }
3850 }
3851 
3852 
3853 // clang-format off
3854 #define PAUTH_SYSTEM_MODES(V)                                     \
3855   V(A1716, 17, ReadXRegister(16),                      kPACKeyIA) \
3856   V(B1716, 17, ReadXRegister(16),                      kPACKeyIB) \
3857   V(AZ,    30, 0x00000000,                             kPACKeyIA) \
3858   V(BZ,    30, 0x00000000,                             kPACKeyIB) \
3859   V(ASP,   30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
3860   V(BSP,   30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
3861 // clang-format on
3862 
3863 
VisitSystem(const Instruction * instr)3864 void Simulator::VisitSystem(const Instruction* instr) {
3865   // Some system instructions hijack their Op and Cp fields to represent a
3866   // range of immediates instead of indicating a different instruction. This
3867   // makes the decoding tricky.
3868   if (instr->GetInstructionBits() == XPACLRI) {
3869     WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
3870   } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
3871     switch (instr->Mask(SystemPStateMask)) {
3872       case CFINV:
3873         ReadNzcv().SetC(!ReadC());
3874         break;
3875       case AXFLAG:
3876         ReadNzcv().SetN(0);
3877         ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
3878         ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
3879         ReadNzcv().SetV(0);
3880         break;
3881       case XAFLAG: {
3882         // Can't set the flags in place due to the logical dependencies.
3883         uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
3884         uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
3885         uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
3886         uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
3887         ReadNzcv().SetN(n);
3888         ReadNzcv().SetZ(z);
3889         ReadNzcv().SetC(c);
3890         ReadNzcv().SetV(v);
3891         break;
3892       }
3893     }
3894   } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
3895     // Check BType allows PACI[AB]SP instructions.
3896     if (PcIsInGuardedPage()) {
3897       Instr i = instr->Mask(SystemPAuthMask);
3898       if ((i == PACIASP) || (i == PACIBSP)) {
3899         switch (ReadBType()) {
3900           case BranchFromGuardedNotToIP:
3901           // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
3902           // assume here to be zero. This allows execution of PACI[AB]SP when
3903           // BTYPE is BranchFromGuardedNotToIP (0b11).
3904           case DefaultBType:
3905           case BranchFromUnguardedOrToIP:
3906           case BranchAndLink:
3907             break;
3908         }
3909       }
3910     }
3911 
3912     switch (instr->Mask(SystemPAuthMask)) {
3913 #define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY)                              \
3914   case PACI##SUFFIX:                                                           \
3915     WriteXRegister(DST,                                                        \
3916                    AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
3917     break;                                                                     \
3918   case AUTI##SUFFIX:                                                           \
3919     WriteXRegister(DST,                                                        \
3920                    AuthPAC(ReadXRegister(DST),                                 \
3921                            MOD,                                                \
3922                            KEY,                                                \
3923                            kInstructionPointer));                              \
3924     break;
3925 
3926       PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
3927 #undef DEFINE_PAUTH_FUNCS
3928     }
3929   } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
3930              SystemExclusiveMonitorFixed) {
3931     VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
3932     switch (instr->Mask(SystemExclusiveMonitorMask)) {
3933       case CLREX: {
3934         PrintExclusiveAccessWarning();
3935         ClearLocalMonitor();
3936         break;
3937       }
3938     }
3939   } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
3940     switch (instr->Mask(SystemSysRegMask)) {
3941       case MRS: {
3942         switch (instr->GetImmSystemRegister()) {
3943           case NZCV:
3944             WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
3945             break;
3946           case FPCR:
3947             WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
3948             break;
3949           case RNDR:
3950           case RNDRRS: {
3951             uint64_t high = jrand48(rndr_state_);
3952             uint64_t low = jrand48(rndr_state_);
3953             uint64_t rand_num = (high << 32) | (low & 0xffffffff);
3954             WriteXRegister(instr->GetRt(), rand_num);
3955             // Simulate successful random number generation.
3956             // TODO: Return failure occasionally as a random number cannot be
3957             // returned in a period of time.
3958             ReadNzcv().SetRawValue(NoFlag);
3959             LogSystemRegister(NZCV);
3960             break;
3961           }
3962           default:
3963             VIXL_UNIMPLEMENTED();
3964         }
3965         break;
3966       }
3967       case MSR: {
3968         switch (instr->GetImmSystemRegister()) {
3969           case NZCV:
3970             ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
3971             LogSystemRegister(NZCV);
3972             break;
3973           case FPCR:
3974             ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
3975             LogSystemRegister(FPCR);
3976             break;
3977           default:
3978             VIXL_UNIMPLEMENTED();
3979         }
3980         break;
3981       }
3982     }
3983   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
3984     VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
3985     switch (instr->GetImmHint()) {
3986       case NOP:
3987       case ESB:
3988       case CSDB:
3989       case BTI_jc:
3990         break;
3991       case BTI:
3992         if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
3993           VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
3994         }
3995         break;
3996       case BTI_c:
3997         if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
3998           VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
3999         }
4000         break;
4001       case BTI_j:
4002         if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4003           VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4004         }
4005         break;
4006       default:
4007         VIXL_UNIMPLEMENTED();
4008     }
4009   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4010     __sync_synchronize();
4011   } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4012     switch (instr->Mask(SystemSysMask)) {
4013       case SYS:
4014         SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4015         break;
4016       default:
4017         VIXL_UNIMPLEMENTED();
4018     }
4019   } else {
4020     VIXL_UNIMPLEMENTED();
4021   }
4022 }
4023 
4024 
VisitException(const Instruction * instr)4025 void Simulator::VisitException(const Instruction* instr) {
4026   switch (instr->Mask(ExceptionMask)) {
4027     case HLT:
4028       switch (instr->GetImmException()) {
4029         case kUnreachableOpcode:
4030           DoUnreachable(instr);
4031           return;
4032         case kTraceOpcode:
4033           DoTrace(instr);
4034           return;
4035         case kLogOpcode:
4036           DoLog(instr);
4037           return;
4038         case kPrintfOpcode:
4039           DoPrintf(instr);
4040           return;
4041         case kRuntimeCallOpcode:
4042           DoRuntimeCall(instr);
4043           return;
4044         case kSetCPUFeaturesOpcode:
4045         case kEnableCPUFeaturesOpcode:
4046         case kDisableCPUFeaturesOpcode:
4047           DoConfigureCPUFeatures(instr);
4048           return;
4049         case kSaveCPUFeaturesOpcode:
4050           DoSaveCPUFeatures(instr);
4051           return;
4052         case kRestoreCPUFeaturesOpcode:
4053           DoRestoreCPUFeatures(instr);
4054           return;
4055         default:
4056           HostBreakpoint();
4057           return;
4058       }
4059     case BRK:
4060       HostBreakpoint();
4061       return;
4062     default:
4063       VIXL_UNIMPLEMENTED();
4064   }
4065 }
4066 
4067 
VisitCrypto2RegSHA(const Instruction * instr)4068 void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4069   VisitUnimplemented(instr);
4070 }
4071 
4072 
VisitCrypto3RegSHA(const Instruction * instr)4073 void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4074   VisitUnimplemented(instr);
4075 }
4076 
4077 
VisitCryptoAES(const Instruction * instr)4078 void Simulator::VisitCryptoAES(const Instruction* instr) {
4079   VisitUnimplemented(instr);
4080 }
4081 
4082 
VisitNEON2RegMisc(const Instruction * instr)4083 void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4084   NEONFormatDecoder nfd(instr);
4085   VectorFormat vf = nfd.GetVectorFormat();
4086 
4087   static const NEONFormatMap map_lp =
4088       {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4089   VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4090 
4091   static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4092   VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4093 
4094   static const NEONFormatMap map_fcvtn = {{22, 30},
4095                                           {NF_4H, NF_8H, NF_2S, NF_4S}};
4096   VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4097 
4098   SimVRegister& rd = ReadVRegister(instr->GetRd());
4099   SimVRegister& rn = ReadVRegister(instr->GetRn());
4100 
4101   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4102     // These instructions all use a two bit size field, except NOT and RBIT,
4103     // which use the field to encode the operation.
4104     switch (instr->Mask(NEON2RegMiscMask)) {
4105       case NEON_REV64:
4106         rev64(vf, rd, rn);
4107         break;
4108       case NEON_REV32:
4109         rev32(vf, rd, rn);
4110         break;
4111       case NEON_REV16:
4112         rev16(vf, rd, rn);
4113         break;
4114       case NEON_SUQADD:
4115         suqadd(vf, rd, rn);
4116         break;
4117       case NEON_USQADD:
4118         usqadd(vf, rd, rn);
4119         break;
4120       case NEON_CLS:
4121         cls(vf, rd, rn);
4122         break;
4123       case NEON_CLZ:
4124         clz(vf, rd, rn);
4125         break;
4126       case NEON_CNT:
4127         cnt(vf, rd, rn);
4128         break;
4129       case NEON_SQABS:
4130         abs(vf, rd, rn).SignedSaturate(vf);
4131         break;
4132       case NEON_SQNEG:
4133         neg(vf, rd, rn).SignedSaturate(vf);
4134         break;
4135       case NEON_CMGT_zero:
4136         cmp(vf, rd, rn, 0, gt);
4137         break;
4138       case NEON_CMGE_zero:
4139         cmp(vf, rd, rn, 0, ge);
4140         break;
4141       case NEON_CMEQ_zero:
4142         cmp(vf, rd, rn, 0, eq);
4143         break;
4144       case NEON_CMLE_zero:
4145         cmp(vf, rd, rn, 0, le);
4146         break;
4147       case NEON_CMLT_zero:
4148         cmp(vf, rd, rn, 0, lt);
4149         break;
4150       case NEON_ABS:
4151         abs(vf, rd, rn);
4152         break;
4153       case NEON_NEG:
4154         neg(vf, rd, rn);
4155         break;
4156       case NEON_SADDLP:
4157         saddlp(vf_lp, rd, rn);
4158         break;
4159       case NEON_UADDLP:
4160         uaddlp(vf_lp, rd, rn);
4161         break;
4162       case NEON_SADALP:
4163         sadalp(vf_lp, rd, rn);
4164         break;
4165       case NEON_UADALP:
4166         uadalp(vf_lp, rd, rn);
4167         break;
4168       case NEON_RBIT_NOT:
4169         vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4170         switch (instr->GetFPType()) {
4171           case 0:
4172             not_(vf, rd, rn);
4173             break;
4174           case 1:
4175             rbit(vf, rd, rn);
4176             break;
4177           default:
4178             VIXL_UNIMPLEMENTED();
4179         }
4180         break;
4181     }
4182   } else {
4183     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4184     FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4185     bool inexact_exception = false;
4186     FrintMode frint_mode = kFrintToInteger;
4187 
4188     // These instructions all use a one bit size field, except XTN, SQXTUN,
4189     // SHLL, SQXTN and UQXTN, which use a two bit size field.
4190     switch (instr->Mask(NEON2RegMiscFPMask)) {
4191       case NEON_FABS:
4192         fabs_(fpf, rd, rn);
4193         return;
4194       case NEON_FNEG:
4195         fneg(fpf, rd, rn);
4196         return;
4197       case NEON_FSQRT:
4198         fsqrt(fpf, rd, rn);
4199         return;
4200       case NEON_FCVTL:
4201         if (instr->Mask(NEON_Q)) {
4202           fcvtl2(vf_fcvtl, rd, rn);
4203         } else {
4204           fcvtl(vf_fcvtl, rd, rn);
4205         }
4206         return;
4207       case NEON_FCVTN:
4208         if (instr->Mask(NEON_Q)) {
4209           fcvtn2(vf_fcvtn, rd, rn);
4210         } else {
4211           fcvtn(vf_fcvtn, rd, rn);
4212         }
4213         return;
4214       case NEON_FCVTXN:
4215         if (instr->Mask(NEON_Q)) {
4216           fcvtxn2(vf_fcvtn, rd, rn);
4217         } else {
4218           fcvtxn(vf_fcvtn, rd, rn);
4219         }
4220         return;
4221 
4222       // The following instructions break from the switch statement, rather
4223       // than return.
4224       case NEON_FRINT32X:
4225         inexact_exception = true;
4226         frint_mode = kFrintToInt32;
4227         break;  // Use FPCR rounding mode.
4228       case NEON_FRINT32Z:
4229         inexact_exception = true;
4230         frint_mode = kFrintToInt32;
4231         fpcr_rounding = FPZero;
4232         break;
4233       case NEON_FRINT64X:
4234         inexact_exception = true;
4235         frint_mode = kFrintToInt64;
4236         break;  // Use FPCR rounding mode.
4237       case NEON_FRINT64Z:
4238         inexact_exception = true;
4239         frint_mode = kFrintToInt64;
4240         fpcr_rounding = FPZero;
4241         break;
4242       case NEON_FRINTI:
4243         break;  // Use FPCR rounding mode.
4244       case NEON_FRINTX:
4245         inexact_exception = true;
4246         break;
4247       case NEON_FRINTA:
4248         fpcr_rounding = FPTieAway;
4249         break;
4250       case NEON_FRINTM:
4251         fpcr_rounding = FPNegativeInfinity;
4252         break;
4253       case NEON_FRINTN:
4254         fpcr_rounding = FPTieEven;
4255         break;
4256       case NEON_FRINTP:
4257         fpcr_rounding = FPPositiveInfinity;
4258         break;
4259       case NEON_FRINTZ:
4260         fpcr_rounding = FPZero;
4261         break;
4262 
4263       case NEON_FCVTNS:
4264         fcvts(fpf, rd, rn, FPTieEven);
4265         return;
4266       case NEON_FCVTNU:
4267         fcvtu(fpf, rd, rn, FPTieEven);
4268         return;
4269       case NEON_FCVTPS:
4270         fcvts(fpf, rd, rn, FPPositiveInfinity);
4271         return;
4272       case NEON_FCVTPU:
4273         fcvtu(fpf, rd, rn, FPPositiveInfinity);
4274         return;
4275       case NEON_FCVTMS:
4276         fcvts(fpf, rd, rn, FPNegativeInfinity);
4277         return;
4278       case NEON_FCVTMU:
4279         fcvtu(fpf, rd, rn, FPNegativeInfinity);
4280         return;
4281       case NEON_FCVTZS:
4282         fcvts(fpf, rd, rn, FPZero);
4283         return;
4284       case NEON_FCVTZU:
4285         fcvtu(fpf, rd, rn, FPZero);
4286         return;
4287       case NEON_FCVTAS:
4288         fcvts(fpf, rd, rn, FPTieAway);
4289         return;
4290       case NEON_FCVTAU:
4291         fcvtu(fpf, rd, rn, FPTieAway);
4292         return;
4293       case NEON_SCVTF:
4294         scvtf(fpf, rd, rn, 0, fpcr_rounding);
4295         return;
4296       case NEON_UCVTF:
4297         ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4298         return;
4299       case NEON_URSQRTE:
4300         ursqrte(fpf, rd, rn);
4301         return;
4302       case NEON_URECPE:
4303         urecpe(fpf, rd, rn);
4304         return;
4305       case NEON_FRSQRTE:
4306         frsqrte(fpf, rd, rn);
4307         return;
4308       case NEON_FRECPE:
4309         frecpe(fpf, rd, rn, fpcr_rounding);
4310         return;
4311       case NEON_FCMGT_zero:
4312         fcmp_zero(fpf, rd, rn, gt);
4313         return;
4314       case NEON_FCMGE_zero:
4315         fcmp_zero(fpf, rd, rn, ge);
4316         return;
4317       case NEON_FCMEQ_zero:
4318         fcmp_zero(fpf, rd, rn, eq);
4319         return;
4320       case NEON_FCMLE_zero:
4321         fcmp_zero(fpf, rd, rn, le);
4322         return;
4323       case NEON_FCMLT_zero:
4324         fcmp_zero(fpf, rd, rn, lt);
4325         return;
4326       default:
4327         if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4328             (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4329           switch (instr->Mask(NEON2RegMiscMask)) {
4330             case NEON_XTN:
4331               xtn(vf, rd, rn);
4332               return;
4333             case NEON_SQXTN:
4334               sqxtn(vf, rd, rn);
4335               return;
4336             case NEON_UQXTN:
4337               uqxtn(vf, rd, rn);
4338               return;
4339             case NEON_SQXTUN:
4340               sqxtun(vf, rd, rn);
4341               return;
4342             case NEON_SHLL:
4343               vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4344               if (instr->Mask(NEON_Q)) {
4345                 shll2(vf, rd, rn);
4346               } else {
4347                 shll(vf, rd, rn);
4348               }
4349               return;
4350             default:
4351               VIXL_UNIMPLEMENTED();
4352           }
4353         } else {
4354           VIXL_UNIMPLEMENTED();
4355         }
4356     }
4357 
4358     // Only FRINT* instructions fall through the switch above.
4359     frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
4360   }
4361 }
4362 
4363 
VisitNEON2RegMiscFP16(const Instruction * instr)4364 void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4365   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4366   NEONFormatDecoder nfd(instr);
4367   VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4368 
4369   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4370 
4371   SimVRegister& rd = ReadVRegister(instr->GetRd());
4372   SimVRegister& rn = ReadVRegister(instr->GetRn());
4373 
4374   switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4375     case NEON_SCVTF_H:
4376       scvtf(fpf, rd, rn, 0, fpcr_rounding);
4377       return;
4378     case NEON_UCVTF_H:
4379       ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4380       return;
4381     case NEON_FCVTNS_H:
4382       fcvts(fpf, rd, rn, FPTieEven);
4383       return;
4384     case NEON_FCVTNU_H:
4385       fcvtu(fpf, rd, rn, FPTieEven);
4386       return;
4387     case NEON_FCVTPS_H:
4388       fcvts(fpf, rd, rn, FPPositiveInfinity);
4389       return;
4390     case NEON_FCVTPU_H:
4391       fcvtu(fpf, rd, rn, FPPositiveInfinity);
4392       return;
4393     case NEON_FCVTMS_H:
4394       fcvts(fpf, rd, rn, FPNegativeInfinity);
4395       return;
4396     case NEON_FCVTMU_H:
4397       fcvtu(fpf, rd, rn, FPNegativeInfinity);
4398       return;
4399     case NEON_FCVTZS_H:
4400       fcvts(fpf, rd, rn, FPZero);
4401       return;
4402     case NEON_FCVTZU_H:
4403       fcvtu(fpf, rd, rn, FPZero);
4404       return;
4405     case NEON_FCVTAS_H:
4406       fcvts(fpf, rd, rn, FPTieAway);
4407       return;
4408     case NEON_FCVTAU_H:
4409       fcvtu(fpf, rd, rn, FPTieAway);
4410       return;
4411     case NEON_FRINTI_H:
4412       frint(fpf, rd, rn, fpcr_rounding, false);
4413       return;
4414     case NEON_FRINTX_H:
4415       frint(fpf, rd, rn, fpcr_rounding, true);
4416       return;
4417     case NEON_FRINTA_H:
4418       frint(fpf, rd, rn, FPTieAway, false);
4419       return;
4420     case NEON_FRINTM_H:
4421       frint(fpf, rd, rn, FPNegativeInfinity, false);
4422       return;
4423     case NEON_FRINTN_H:
4424       frint(fpf, rd, rn, FPTieEven, false);
4425       return;
4426     case NEON_FRINTP_H:
4427       frint(fpf, rd, rn, FPPositiveInfinity, false);
4428       return;
4429     case NEON_FRINTZ_H:
4430       frint(fpf, rd, rn, FPZero, false);
4431       return;
4432     case NEON_FABS_H:
4433       fabs_(fpf, rd, rn);
4434       return;
4435     case NEON_FNEG_H:
4436       fneg(fpf, rd, rn);
4437       return;
4438     case NEON_FSQRT_H:
4439       fsqrt(fpf, rd, rn);
4440       return;
4441     case NEON_FRSQRTE_H:
4442       frsqrte(fpf, rd, rn);
4443       return;
4444     case NEON_FRECPE_H:
4445       frecpe(fpf, rd, rn, fpcr_rounding);
4446       return;
4447     case NEON_FCMGT_H_zero:
4448       fcmp_zero(fpf, rd, rn, gt);
4449       return;
4450     case NEON_FCMGE_H_zero:
4451       fcmp_zero(fpf, rd, rn, ge);
4452       return;
4453     case NEON_FCMEQ_H_zero:
4454       fcmp_zero(fpf, rd, rn, eq);
4455       return;
4456     case NEON_FCMLE_H_zero:
4457       fcmp_zero(fpf, rd, rn, le);
4458       return;
4459     case NEON_FCMLT_H_zero:
4460       fcmp_zero(fpf, rd, rn, lt);
4461       return;
4462     default:
4463       VIXL_UNIMPLEMENTED();
4464       return;
4465   }
4466 }
4467 
4468 
VisitNEON3Same(const Instruction * instr)4469 void Simulator::VisitNEON3Same(const Instruction* instr) {
4470   NEONFormatDecoder nfd(instr);
4471   SimVRegister& rd = ReadVRegister(instr->GetRd());
4472   SimVRegister& rn = ReadVRegister(instr->GetRn());
4473   SimVRegister& rm = ReadVRegister(instr->GetRm());
4474 
4475   if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
4476     VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4477     switch (instr->Mask(NEON3SameLogicalMask)) {
4478       case NEON_AND:
4479         and_(vf, rd, rn, rm);
4480         break;
4481       case NEON_ORR:
4482         orr(vf, rd, rn, rm);
4483         break;
4484       case NEON_ORN:
4485         orn(vf, rd, rn, rm);
4486         break;
4487       case NEON_EOR:
4488         eor(vf, rd, rn, rm);
4489         break;
4490       case NEON_BIC:
4491         bic(vf, rd, rn, rm);
4492         break;
4493       case NEON_BIF:
4494         bif(vf, rd, rn, rm);
4495         break;
4496       case NEON_BIT:
4497         bit(vf, rd, rn, rm);
4498         break;
4499       case NEON_BSL:
4500         bsl(vf, rd, rn, rm);
4501         break;
4502       default:
4503         VIXL_UNIMPLEMENTED();
4504     }
4505   } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
4506     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4507     switch (instr->Mask(NEON3SameFPMask)) {
4508       case NEON_FADD:
4509         fadd(vf, rd, rn, rm);
4510         break;
4511       case NEON_FSUB:
4512         fsub(vf, rd, rn, rm);
4513         break;
4514       case NEON_FMUL:
4515         fmul(vf, rd, rn, rm);
4516         break;
4517       case NEON_FDIV:
4518         fdiv(vf, rd, rn, rm);
4519         break;
4520       case NEON_FMAX:
4521         fmax(vf, rd, rn, rm);
4522         break;
4523       case NEON_FMIN:
4524         fmin(vf, rd, rn, rm);
4525         break;
4526       case NEON_FMAXNM:
4527         fmaxnm(vf, rd, rn, rm);
4528         break;
4529       case NEON_FMINNM:
4530         fminnm(vf, rd, rn, rm);
4531         break;
4532       case NEON_FMLA:
4533         fmla(vf, rd, rn, rm);
4534         break;
4535       case NEON_FMLS:
4536         fmls(vf, rd, rn, rm);
4537         break;
4538       case NEON_FMULX:
4539         fmulx(vf, rd, rn, rm);
4540         break;
4541       case NEON_FACGE:
4542         fabscmp(vf, rd, rn, rm, ge);
4543         break;
4544       case NEON_FACGT:
4545         fabscmp(vf, rd, rn, rm, gt);
4546         break;
4547       case NEON_FCMEQ:
4548         fcmp(vf, rd, rn, rm, eq);
4549         break;
4550       case NEON_FCMGE:
4551         fcmp(vf, rd, rn, rm, ge);
4552         break;
4553       case NEON_FCMGT:
4554         fcmp(vf, rd, rn, rm, gt);
4555         break;
4556       case NEON_FRECPS:
4557         frecps(vf, rd, rn, rm);
4558         break;
4559       case NEON_FRSQRTS:
4560         frsqrts(vf, rd, rn, rm);
4561         break;
4562       case NEON_FABD:
4563         fabd(vf, rd, rn, rm);
4564         break;
4565       case NEON_FADDP:
4566         faddp(vf, rd, rn, rm);
4567         break;
4568       case NEON_FMAXP:
4569         fmaxp(vf, rd, rn, rm);
4570         break;
4571       case NEON_FMAXNMP:
4572         fmaxnmp(vf, rd, rn, rm);
4573         break;
4574       case NEON_FMINP:
4575         fminp(vf, rd, rn, rm);
4576         break;
4577       case NEON_FMINNMP:
4578         fminnmp(vf, rd, rn, rm);
4579         break;
4580       default:
4581         // FMLAL{2} and FMLSL{2} have special-case encodings.
4582         switch (instr->Mask(NEON3SameFHMMask)) {
4583           case NEON_FMLAL:
4584             fmlal(vf, rd, rn, rm);
4585             break;
4586           case NEON_FMLAL2:
4587             fmlal2(vf, rd, rn, rm);
4588             break;
4589           case NEON_FMLSL:
4590             fmlsl(vf, rd, rn, rm);
4591             break;
4592           case NEON_FMLSL2:
4593             fmlsl2(vf, rd, rn, rm);
4594             break;
4595           default:
4596             VIXL_UNIMPLEMENTED();
4597         }
4598     }
4599   } else {
4600     VectorFormat vf = nfd.GetVectorFormat();
4601     switch (instr->Mask(NEON3SameMask)) {
4602       case NEON_ADD:
4603         add(vf, rd, rn, rm);
4604         break;
4605       case NEON_ADDP:
4606         addp(vf, rd, rn, rm);
4607         break;
4608       case NEON_CMEQ:
4609         cmp(vf, rd, rn, rm, eq);
4610         break;
4611       case NEON_CMGE:
4612         cmp(vf, rd, rn, rm, ge);
4613         break;
4614       case NEON_CMGT:
4615         cmp(vf, rd, rn, rm, gt);
4616         break;
4617       case NEON_CMHI:
4618         cmp(vf, rd, rn, rm, hi);
4619         break;
4620       case NEON_CMHS:
4621         cmp(vf, rd, rn, rm, hs);
4622         break;
4623       case NEON_CMTST:
4624         cmptst(vf, rd, rn, rm);
4625         break;
4626       case NEON_MLS:
4627         mls(vf, rd, rn, rm);
4628         break;
4629       case NEON_MLA:
4630         mla(vf, rd, rn, rm);
4631         break;
4632       case NEON_MUL:
4633         mul(vf, rd, rn, rm);
4634         break;
4635       case NEON_PMUL:
4636         pmul(vf, rd, rn, rm);
4637         break;
4638       case NEON_SMAX:
4639         smax(vf, rd, rn, rm);
4640         break;
4641       case NEON_SMAXP:
4642         smaxp(vf, rd, rn, rm);
4643         break;
4644       case NEON_SMIN:
4645         smin(vf, rd, rn, rm);
4646         break;
4647       case NEON_SMINP:
4648         sminp(vf, rd, rn, rm);
4649         break;
4650       case NEON_SUB:
4651         sub(vf, rd, rn, rm);
4652         break;
4653       case NEON_UMAX:
4654         umax(vf, rd, rn, rm);
4655         break;
4656       case NEON_UMAXP:
4657         umaxp(vf, rd, rn, rm);
4658         break;
4659       case NEON_UMIN:
4660         umin(vf, rd, rn, rm);
4661         break;
4662       case NEON_UMINP:
4663         uminp(vf, rd, rn, rm);
4664         break;
4665       case NEON_SSHL:
4666         sshl(vf, rd, rn, rm);
4667         break;
4668       case NEON_USHL:
4669         ushl(vf, rd, rn, rm);
4670         break;
4671       case NEON_SABD:
4672         absdiff(vf, rd, rn, rm, true);
4673         break;
4674       case NEON_UABD:
4675         absdiff(vf, rd, rn, rm, false);
4676         break;
4677       case NEON_SABA:
4678         saba(vf, rd, rn, rm);
4679         break;
4680       case NEON_UABA:
4681         uaba(vf, rd, rn, rm);
4682         break;
4683       case NEON_UQADD:
4684         add(vf, rd, rn, rm).UnsignedSaturate(vf);
4685         break;
4686       case NEON_SQADD:
4687         add(vf, rd, rn, rm).SignedSaturate(vf);
4688         break;
4689       case NEON_UQSUB:
4690         sub(vf, rd, rn, rm).UnsignedSaturate(vf);
4691         break;
4692       case NEON_SQSUB:
4693         sub(vf, rd, rn, rm).SignedSaturate(vf);
4694         break;
4695       case NEON_SQDMULH:
4696         sqdmulh(vf, rd, rn, rm);
4697         break;
4698       case NEON_SQRDMULH:
4699         sqrdmulh(vf, rd, rn, rm);
4700         break;
4701       case NEON_UQSHL:
4702         ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
4703         break;
4704       case NEON_SQSHL:
4705         sshl(vf, rd, rn, rm).SignedSaturate(vf);
4706         break;
4707       case NEON_URSHL:
4708         ushl(vf, rd, rn, rm).Round(vf);
4709         break;
4710       case NEON_SRSHL:
4711         sshl(vf, rd, rn, rm).Round(vf);
4712         break;
4713       case NEON_UQRSHL:
4714         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
4715         break;
4716       case NEON_SQRSHL:
4717         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
4718         break;
4719       case NEON_UHADD:
4720         add(vf, rd, rn, rm).Uhalve(vf);
4721         break;
4722       case NEON_URHADD:
4723         add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
4724         break;
4725       case NEON_SHADD:
4726         add(vf, rd, rn, rm).Halve(vf);
4727         break;
4728       case NEON_SRHADD:
4729         add(vf, rd, rn, rm).Halve(vf).Round(vf);
4730         break;
4731       case NEON_UHSUB:
4732         sub(vf, rd, rn, rm).Uhalve(vf);
4733         break;
4734       case NEON_SHSUB:
4735         sub(vf, rd, rn, rm).Halve(vf);
4736         break;
4737       default:
4738         VIXL_UNIMPLEMENTED();
4739     }
4740   }
4741 }
4742 
4743 
VisitNEON3SameFP16(const Instruction * instr)4744 void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
4745   NEONFormatDecoder nfd(instr);
4746   SimVRegister& rd = ReadVRegister(instr->GetRd());
4747   SimVRegister& rn = ReadVRegister(instr->GetRn());
4748   SimVRegister& rm = ReadVRegister(instr->GetRm());
4749 
4750   VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
4751   switch (instr->Mask(NEON3SameFP16Mask)) {
4752 #define SIM_FUNC(A, B) \
4753   case NEON_##A##_H:   \
4754     B(vf, rd, rn, rm); \
4755     break;
4756     SIM_FUNC(FMAXNM, fmaxnm);
4757     SIM_FUNC(FMLA, fmla);
4758     SIM_FUNC(FADD, fadd);
4759     SIM_FUNC(FMULX, fmulx);
4760     SIM_FUNC(FMAX, fmax);
4761     SIM_FUNC(FRECPS, frecps);
4762     SIM_FUNC(FMINNM, fminnm);
4763     SIM_FUNC(FMLS, fmls);
4764     SIM_FUNC(FSUB, fsub);
4765     SIM_FUNC(FMIN, fmin);
4766     SIM_FUNC(FRSQRTS, frsqrts);
4767     SIM_FUNC(FMAXNMP, fmaxnmp);
4768     SIM_FUNC(FADDP, faddp);
4769     SIM_FUNC(FMUL, fmul);
4770     SIM_FUNC(FMAXP, fmaxp);
4771     SIM_FUNC(FDIV, fdiv);
4772     SIM_FUNC(FMINNMP, fminnmp);
4773     SIM_FUNC(FABD, fabd);
4774     SIM_FUNC(FMINP, fminp);
4775 #undef SIM_FUNC
4776     case NEON_FCMEQ_H:
4777       fcmp(vf, rd, rn, rm, eq);
4778       break;
4779     case NEON_FCMGE_H:
4780       fcmp(vf, rd, rn, rm, ge);
4781       break;
4782     case NEON_FACGE_H:
4783       fabscmp(vf, rd, rn, rm, ge);
4784       break;
4785     case NEON_FCMGT_H:
4786       fcmp(vf, rd, rn, rm, gt);
4787       break;
4788     case NEON_FACGT_H:
4789       fabscmp(vf, rd, rn, rm, gt);
4790       break;
4791     default:
4792       VIXL_UNIMPLEMENTED();
4793       break;
4794   }
4795 }
4796 
VisitNEON3SameExtra(const Instruction * instr)4797 void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
4798   NEONFormatDecoder nfd(instr);
4799   SimVRegister& rd = ReadVRegister(instr->GetRd());
4800   SimVRegister& rn = ReadVRegister(instr->GetRn());
4801   SimVRegister& rm = ReadVRegister(instr->GetRm());
4802   int rot = 0;
4803   VectorFormat vf = nfd.GetVectorFormat();
4804   if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
4805     rot = instr->GetImmRotFcmlaVec();
4806     fcmla(vf, rd, rn, rm, rot);
4807   } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
4808     rot = instr->GetImmRotFcadd();
4809     fcadd(vf, rd, rn, rm, rot);
4810   } else {
4811     switch (instr->Mask(NEON3SameExtraMask)) {
4812       case NEON_SDOT:
4813         sdot(vf, rd, rn, rm);
4814         break;
4815       case NEON_SQRDMLAH:
4816         sqrdmlah(vf, rd, rn, rm);
4817         break;
4818       case NEON_UDOT:
4819         udot(vf, rd, rn, rm);
4820         break;
4821       case NEON_SQRDMLSH:
4822         sqrdmlsh(vf, rd, rn, rm);
4823         break;
4824       default:
4825         VIXL_UNIMPLEMENTED();
4826         break;
4827     }
4828   }
4829 }
4830 
4831 
VisitNEON3Different(const Instruction * instr)4832 void Simulator::VisitNEON3Different(const Instruction* instr) {
4833   NEONFormatDecoder nfd(instr);
4834   VectorFormat vf = nfd.GetVectorFormat();
4835   VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4836 
4837   SimVRegister& rd = ReadVRegister(instr->GetRd());
4838   SimVRegister& rn = ReadVRegister(instr->GetRn());
4839   SimVRegister& rm = ReadVRegister(instr->GetRm());
4840 
4841   switch (instr->Mask(NEON3DifferentMask)) {
4842     case NEON_PMULL:
4843       pmull(vf_l, rd, rn, rm);
4844       break;
4845     case NEON_PMULL2:
4846       pmull2(vf_l, rd, rn, rm);
4847       break;
4848     case NEON_UADDL:
4849       uaddl(vf_l, rd, rn, rm);
4850       break;
4851     case NEON_UADDL2:
4852       uaddl2(vf_l, rd, rn, rm);
4853       break;
4854     case NEON_SADDL:
4855       saddl(vf_l, rd, rn, rm);
4856       break;
4857     case NEON_SADDL2:
4858       saddl2(vf_l, rd, rn, rm);
4859       break;
4860     case NEON_USUBL:
4861       usubl(vf_l, rd, rn, rm);
4862       break;
4863     case NEON_USUBL2:
4864       usubl2(vf_l, rd, rn, rm);
4865       break;
4866     case NEON_SSUBL:
4867       ssubl(vf_l, rd, rn, rm);
4868       break;
4869     case NEON_SSUBL2:
4870       ssubl2(vf_l, rd, rn, rm);
4871       break;
4872     case NEON_SABAL:
4873       sabal(vf_l, rd, rn, rm);
4874       break;
4875     case NEON_SABAL2:
4876       sabal2(vf_l, rd, rn, rm);
4877       break;
4878     case NEON_UABAL:
4879       uabal(vf_l, rd, rn, rm);
4880       break;
4881     case NEON_UABAL2:
4882       uabal2(vf_l, rd, rn, rm);
4883       break;
4884     case NEON_SABDL:
4885       sabdl(vf_l, rd, rn, rm);
4886       break;
4887     case NEON_SABDL2:
4888       sabdl2(vf_l, rd, rn, rm);
4889       break;
4890     case NEON_UABDL:
4891       uabdl(vf_l, rd, rn, rm);
4892       break;
4893     case NEON_UABDL2:
4894       uabdl2(vf_l, rd, rn, rm);
4895       break;
4896     case NEON_SMLAL:
4897       smlal(vf_l, rd, rn, rm);
4898       break;
4899     case NEON_SMLAL2:
4900       smlal2(vf_l, rd, rn, rm);
4901       break;
4902     case NEON_UMLAL:
4903       umlal(vf_l, rd, rn, rm);
4904       break;
4905     case NEON_UMLAL2:
4906       umlal2(vf_l, rd, rn, rm);
4907       break;
4908     case NEON_SMLSL:
4909       smlsl(vf_l, rd, rn, rm);
4910       break;
4911     case NEON_SMLSL2:
4912       smlsl2(vf_l, rd, rn, rm);
4913       break;
4914     case NEON_UMLSL:
4915       umlsl(vf_l, rd, rn, rm);
4916       break;
4917     case NEON_UMLSL2:
4918       umlsl2(vf_l, rd, rn, rm);
4919       break;
4920     case NEON_SMULL:
4921       smull(vf_l, rd, rn, rm);
4922       break;
4923     case NEON_SMULL2:
4924       smull2(vf_l, rd, rn, rm);
4925       break;
4926     case NEON_UMULL:
4927       umull(vf_l, rd, rn, rm);
4928       break;
4929     case NEON_UMULL2:
4930       umull2(vf_l, rd, rn, rm);
4931       break;
4932     case NEON_SQDMLAL:
4933       sqdmlal(vf_l, rd, rn, rm);
4934       break;
4935     case NEON_SQDMLAL2:
4936       sqdmlal2(vf_l, rd, rn, rm);
4937       break;
4938     case NEON_SQDMLSL:
4939       sqdmlsl(vf_l, rd, rn, rm);
4940       break;
4941     case NEON_SQDMLSL2:
4942       sqdmlsl2(vf_l, rd, rn, rm);
4943       break;
4944     case NEON_SQDMULL:
4945       sqdmull(vf_l, rd, rn, rm);
4946       break;
4947     case NEON_SQDMULL2:
4948       sqdmull2(vf_l, rd, rn, rm);
4949       break;
4950     case NEON_UADDW:
4951       uaddw(vf_l, rd, rn, rm);
4952       break;
4953     case NEON_UADDW2:
4954       uaddw2(vf_l, rd, rn, rm);
4955       break;
4956     case NEON_SADDW:
4957       saddw(vf_l, rd, rn, rm);
4958       break;
4959     case NEON_SADDW2:
4960       saddw2(vf_l, rd, rn, rm);
4961       break;
4962     case NEON_USUBW:
4963       usubw(vf_l, rd, rn, rm);
4964       break;
4965     case NEON_USUBW2:
4966       usubw2(vf_l, rd, rn, rm);
4967       break;
4968     case NEON_SSUBW:
4969       ssubw(vf_l, rd, rn, rm);
4970       break;
4971     case NEON_SSUBW2:
4972       ssubw2(vf_l, rd, rn, rm);
4973       break;
4974     case NEON_ADDHN:
4975       addhn(vf, rd, rn, rm);
4976       break;
4977     case NEON_ADDHN2:
4978       addhn2(vf, rd, rn, rm);
4979       break;
4980     case NEON_RADDHN:
4981       raddhn(vf, rd, rn, rm);
4982       break;
4983     case NEON_RADDHN2:
4984       raddhn2(vf, rd, rn, rm);
4985       break;
4986     case NEON_SUBHN:
4987       subhn(vf, rd, rn, rm);
4988       break;
4989     case NEON_SUBHN2:
4990       subhn2(vf, rd, rn, rm);
4991       break;
4992     case NEON_RSUBHN:
4993       rsubhn(vf, rd, rn, rm);
4994       break;
4995     case NEON_RSUBHN2:
4996       rsubhn2(vf, rd, rn, rm);
4997       break;
4998     default:
4999       VIXL_UNIMPLEMENTED();
5000   }
5001 }
5002 
5003 
VisitNEONAcrossLanes(const Instruction * instr)5004 void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5005   NEONFormatDecoder nfd(instr);
5006 
5007   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5008 
5009   SimVRegister& rd = ReadVRegister(instr->GetRd());
5010   SimVRegister& rn = ReadVRegister(instr->GetRn());
5011 
5012   if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5013     VectorFormat vf = nfd.GetVectorFormat(&map_half);
5014     switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5015       case NEON_FMAXV_H:
5016         fmaxv(vf, rd, rn);
5017         break;
5018       case NEON_FMINV_H:
5019         fminv(vf, rd, rn);
5020         break;
5021       case NEON_FMAXNMV_H:
5022         fmaxnmv(vf, rd, rn);
5023         break;
5024       case NEON_FMINNMV_H:
5025         fminnmv(vf, rd, rn);
5026         break;
5027       default:
5028         VIXL_UNIMPLEMENTED();
5029     }
5030   } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5031     // The input operand's VectorFormat is passed for these instructions.
5032     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5033 
5034     switch (instr->Mask(NEONAcrossLanesFPMask)) {
5035       case NEON_FMAXV:
5036         fmaxv(vf, rd, rn);
5037         break;
5038       case NEON_FMINV:
5039         fminv(vf, rd, rn);
5040         break;
5041       case NEON_FMAXNMV:
5042         fmaxnmv(vf, rd, rn);
5043         break;
5044       case NEON_FMINNMV:
5045         fminnmv(vf, rd, rn);
5046         break;
5047       default:
5048         VIXL_UNIMPLEMENTED();
5049     }
5050   } else {
5051     VectorFormat vf = nfd.GetVectorFormat();
5052 
5053     switch (instr->Mask(NEONAcrossLanesMask)) {
5054       case NEON_ADDV:
5055         addv(vf, rd, rn);
5056         break;
5057       case NEON_SMAXV:
5058         smaxv(vf, rd, rn);
5059         break;
5060       case NEON_SMINV:
5061         sminv(vf, rd, rn);
5062         break;
5063       case NEON_UMAXV:
5064         umaxv(vf, rd, rn);
5065         break;
5066       case NEON_UMINV:
5067         uminv(vf, rd, rn);
5068         break;
5069       case NEON_SADDLV:
5070         saddlv(vf, rd, rn);
5071         break;
5072       case NEON_UADDLV:
5073         uaddlv(vf, rd, rn);
5074         break;
5075       default:
5076         VIXL_UNIMPLEMENTED();
5077     }
5078   }
5079 }
5080 
5081 
VisitNEONByIndexedElement(const Instruction * instr)5082 void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5083   NEONFormatDecoder nfd(instr);
5084   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5085   VectorFormat vf_r = nfd.GetVectorFormat();
5086   VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
5087   VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5088 
5089   SimVRegister& rd = ReadVRegister(instr->GetRd());
5090   SimVRegister& rn = ReadVRegister(instr->GetRn());
5091 
5092   ByElementOp Op = NULL;
5093 
5094   int rm_reg = instr->GetRm();
5095   int rm_low_reg = instr->GetRmLow16();
5096   int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
5097   int index_hlm = (index << 1) | instr->GetNEONM();
5098 
5099   switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5100     // These are oddballs and are best handled as special cases.
5101     // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5102     // - The index is always H:L:M.
5103     case NEON_FMLAL_H_byelement:
5104       fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5105       return;
5106     case NEON_FMLAL2_H_byelement:
5107       fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5108       return;
5109     case NEON_FMLSL_H_byelement:
5110       fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5111       return;
5112     case NEON_FMLSL2_H_byelement:
5113       fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5114       return;
5115   }
5116 
5117   if (instr->GetNEONSize() == 1) {
5118     rm_reg = rm_low_reg;
5119     index = index_hlm;
5120   }
5121 
5122   switch (instr->Mask(NEONByIndexedElementMask)) {
5123     case NEON_MUL_byelement:
5124       Op = &Simulator::mul;
5125       vf = vf_r;
5126       break;
5127     case NEON_MLA_byelement:
5128       Op = &Simulator::mla;
5129       vf = vf_r;
5130       break;
5131     case NEON_MLS_byelement:
5132       Op = &Simulator::mls;
5133       vf = vf_r;
5134       break;
5135     case NEON_SQDMULH_byelement:
5136       Op = &Simulator::sqdmulh;
5137       vf = vf_r;
5138       break;
5139     case NEON_SQRDMULH_byelement:
5140       Op = &Simulator::sqrdmulh;
5141       vf = vf_r;
5142       break;
5143     case NEON_SDOT_byelement:
5144       Op = &Simulator::sdot;
5145       vf = vf_r;
5146       break;
5147     case NEON_SQRDMLAH_byelement:
5148       Op = &Simulator::sqrdmlah;
5149       vf = vf_r;
5150       break;
5151     case NEON_UDOT_byelement:
5152       Op = &Simulator::udot;
5153       vf = vf_r;
5154       break;
5155     case NEON_SQRDMLSH_byelement:
5156       Op = &Simulator::sqrdmlsh;
5157       vf = vf_r;
5158       break;
5159     case NEON_SMULL_byelement:
5160       if (instr->Mask(NEON_Q)) {
5161         Op = &Simulator::smull2;
5162       } else {
5163         Op = &Simulator::smull;
5164       }
5165       break;
5166     case NEON_UMULL_byelement:
5167       if (instr->Mask(NEON_Q)) {
5168         Op = &Simulator::umull2;
5169       } else {
5170         Op = &Simulator::umull;
5171       }
5172       break;
5173     case NEON_SMLAL_byelement:
5174       if (instr->Mask(NEON_Q)) {
5175         Op = &Simulator::smlal2;
5176       } else {
5177         Op = &Simulator::smlal;
5178       }
5179       break;
5180     case NEON_UMLAL_byelement:
5181       if (instr->Mask(NEON_Q)) {
5182         Op = &Simulator::umlal2;
5183       } else {
5184         Op = &Simulator::umlal;
5185       }
5186       break;
5187     case NEON_SMLSL_byelement:
5188       if (instr->Mask(NEON_Q)) {
5189         Op = &Simulator::smlsl2;
5190       } else {
5191         Op = &Simulator::smlsl;
5192       }
5193       break;
5194     case NEON_UMLSL_byelement:
5195       if (instr->Mask(NEON_Q)) {
5196         Op = &Simulator::umlsl2;
5197       } else {
5198         Op = &Simulator::umlsl;
5199       }
5200       break;
5201     case NEON_SQDMULL_byelement:
5202       if (instr->Mask(NEON_Q)) {
5203         Op = &Simulator::sqdmull2;
5204       } else {
5205         Op = &Simulator::sqdmull;
5206       }
5207       break;
5208     case NEON_SQDMLAL_byelement:
5209       if (instr->Mask(NEON_Q)) {
5210         Op = &Simulator::sqdmlal2;
5211       } else {
5212         Op = &Simulator::sqdmlal;
5213       }
5214       break;
5215     case NEON_SQDMLSL_byelement:
5216       if (instr->Mask(NEON_Q)) {
5217         Op = &Simulator::sqdmlsl2;
5218       } else {
5219         Op = &Simulator::sqdmlsl;
5220       }
5221       break;
5222     default:
5223       index = instr->GetNEONH();
5224       if (instr->GetFPType() == 0) {
5225         rm_reg &= 0xf;
5226         index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5227       } else if ((instr->GetFPType() & 1) == 0) {
5228         index = (index << 1) | instr->GetNEONL();
5229       }
5230 
5231       vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5232 
5233       switch (instr->Mask(NEONByIndexedElementFPMask)) {
5234         case NEON_FMUL_H_byelement:
5235           vf = vf_half;
5236           VIXL_FALLTHROUGH();
5237         case NEON_FMUL_byelement:
5238           Op = &Simulator::fmul;
5239           break;
5240         case NEON_FMLA_H_byelement:
5241           vf = vf_half;
5242           VIXL_FALLTHROUGH();
5243         case NEON_FMLA_byelement:
5244           Op = &Simulator::fmla;
5245           break;
5246         case NEON_FMLS_H_byelement:
5247           vf = vf_half;
5248           VIXL_FALLTHROUGH();
5249         case NEON_FMLS_byelement:
5250           Op = &Simulator::fmls;
5251           break;
5252         case NEON_FMULX_H_byelement:
5253           vf = vf_half;
5254           VIXL_FALLTHROUGH();
5255         case NEON_FMULX_byelement:
5256           Op = &Simulator::fmulx;
5257           break;
5258         default:
5259           if (instr->GetNEONSize() == 2) {
5260             index = instr->GetNEONH();
5261           } else {
5262             index = (instr->GetNEONH() << 1) | instr->GetNEONL();
5263           }
5264           switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5265             case NEON_FCMLA_byelement:
5266               vf = vf_r;
5267               fcmla(vf,
5268                     rd,
5269                     rn,
5270                     ReadVRegister(instr->GetRm()),
5271                     index,
5272                     instr->GetImmRotFcmlaSca());
5273               return;
5274             default:
5275               VIXL_UNIMPLEMENTED();
5276           }
5277       }
5278   }
5279 
5280   (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5281 }
5282 
5283 
VisitNEONCopy(const Instruction * instr)5284 void Simulator::VisitNEONCopy(const Instruction* instr) {
5285   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5286   VectorFormat vf = nfd.GetVectorFormat();
5287 
5288   SimVRegister& rd = ReadVRegister(instr->GetRd());
5289   SimVRegister& rn = ReadVRegister(instr->GetRn());
5290   int imm5 = instr->GetImmNEON5();
5291   int tz = CountTrailingZeros(imm5, 32);
5292   int reg_index = imm5 >> (tz + 1);
5293 
5294   if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5295     int imm4 = instr->GetImmNEON4();
5296     int rn_index = imm4 >> tz;
5297     ins_element(vf, rd, reg_index, rn, rn_index);
5298   } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5299     ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5300   } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5301     uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5302     value &= MaxUintFromFormat(vf);
5303     WriteXRegister(instr->GetRd(), value);
5304   } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5305     int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5306     if (instr->GetNEONQ()) {
5307       WriteXRegister(instr->GetRd(), value);
5308     } else {
5309       WriteWRegister(instr->GetRd(), (int32_t)value);
5310     }
5311   } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5312     dup_element(vf, rd, rn, reg_index);
5313   } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5314     dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5315   } else {
5316     VIXL_UNIMPLEMENTED();
5317   }
5318 }
5319 
5320 
VisitNEONExtract(const Instruction * instr)5321 void Simulator::VisitNEONExtract(const Instruction* instr) {
5322   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5323   VectorFormat vf = nfd.GetVectorFormat();
5324   SimVRegister& rd = ReadVRegister(instr->GetRd());
5325   SimVRegister& rn = ReadVRegister(instr->GetRn());
5326   SimVRegister& rm = ReadVRegister(instr->GetRm());
5327   if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5328     int index = instr->GetImmNEONExt();
5329     ext(vf, rd, rn, rm, index);
5330   } else {
5331     VIXL_UNIMPLEMENTED();
5332   }
5333 }
5334 
5335 
NEONLoadStoreMultiStructHelper(const Instruction * instr,AddrMode addr_mode)5336 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5337                                                AddrMode addr_mode) {
5338   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5339   VectorFormat vf = nfd.GetVectorFormat();
5340 
5341   uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5342   int reg_size = RegisterSizeInBytesFromFormat(vf);
5343 
5344   int reg[4];
5345   uint64_t addr[4];
5346   for (int i = 0; i < 4; i++) {
5347     reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5348     addr[i] = addr_base + (i * reg_size);
5349   }
5350   int count = 1;
5351   bool log_read = true;
5352 
5353   // Bit 23 determines whether this is an offset or post-index addressing mode.
5354   // In offset mode, bits 20 to 16 should be zero; these bits encode the
5355   // register or immediate in post-index mode.
5356   if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
5357     VIXL_UNREACHABLE();
5358   }
5359 
5360   // We use the PostIndex mask here, as it works in this case for both Offset
5361   // and PostIndex addressing.
5362   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5363     case NEON_LD1_4v:
5364     case NEON_LD1_4v_post:
5365       ld1(vf, ReadVRegister(reg[3]), addr[3]);
5366       count++;
5367       VIXL_FALLTHROUGH();
5368     case NEON_LD1_3v:
5369     case NEON_LD1_3v_post:
5370       ld1(vf, ReadVRegister(reg[2]), addr[2]);
5371       count++;
5372       VIXL_FALLTHROUGH();
5373     case NEON_LD1_2v:
5374     case NEON_LD1_2v_post:
5375       ld1(vf, ReadVRegister(reg[1]), addr[1]);
5376       count++;
5377       VIXL_FALLTHROUGH();
5378     case NEON_LD1_1v:
5379     case NEON_LD1_1v_post:
5380       ld1(vf, ReadVRegister(reg[0]), addr[0]);
5381       break;
5382     case NEON_ST1_4v:
5383     case NEON_ST1_4v_post:
5384       st1(vf, ReadVRegister(reg[3]), addr[3]);
5385       count++;
5386       VIXL_FALLTHROUGH();
5387     case NEON_ST1_3v:
5388     case NEON_ST1_3v_post:
5389       st1(vf, ReadVRegister(reg[2]), addr[2]);
5390       count++;
5391       VIXL_FALLTHROUGH();
5392     case NEON_ST1_2v:
5393     case NEON_ST1_2v_post:
5394       st1(vf, ReadVRegister(reg[1]), addr[1]);
5395       count++;
5396       VIXL_FALLTHROUGH();
5397     case NEON_ST1_1v:
5398     case NEON_ST1_1v_post:
5399       st1(vf, ReadVRegister(reg[0]), addr[0]);
5400       log_read = false;
5401       break;
5402     case NEON_LD2_post:
5403     case NEON_LD2:
5404       ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5405       count = 2;
5406       break;
5407     case NEON_ST2:
5408     case NEON_ST2_post:
5409       st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5410       count = 2;
5411       log_read = false;
5412       break;
5413     case NEON_LD3_post:
5414     case NEON_LD3:
5415       ld3(vf,
5416           ReadVRegister(reg[0]),
5417           ReadVRegister(reg[1]),
5418           ReadVRegister(reg[2]),
5419           addr[0]);
5420       count = 3;
5421       break;
5422     case NEON_ST3:
5423     case NEON_ST3_post:
5424       st3(vf,
5425           ReadVRegister(reg[0]),
5426           ReadVRegister(reg[1]),
5427           ReadVRegister(reg[2]),
5428           addr[0]);
5429       count = 3;
5430       log_read = false;
5431       break;
5432     case NEON_ST4:
5433     case NEON_ST4_post:
5434       st4(vf,
5435           ReadVRegister(reg[0]),
5436           ReadVRegister(reg[1]),
5437           ReadVRegister(reg[2]),
5438           ReadVRegister(reg[3]),
5439           addr[0]);
5440       count = 4;
5441       log_read = false;
5442       break;
5443     case NEON_LD4_post:
5444     case NEON_LD4:
5445       ld4(vf,
5446           ReadVRegister(reg[0]),
5447           ReadVRegister(reg[1]),
5448           ReadVRegister(reg[2]),
5449           ReadVRegister(reg[3]),
5450           addr[0]);
5451       count = 4;
5452       break;
5453     default:
5454       VIXL_UNIMPLEMENTED();
5455   }
5456 
5457   // Explicitly log the register update whilst we have type information.
5458   for (int i = 0; i < count; i++) {
5459     // For de-interleaving loads, only print the base address.
5460     int lane_size = LaneSizeInBytesFromFormat(vf);
5461     PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
5462         GetPrintRegisterFormatForSize(reg_size, lane_size));
5463     if (log_read) {
5464       LogVRead(addr_base, reg[i], format);
5465     } else {
5466       LogVWrite(addr_base, reg[i], format);
5467     }
5468   }
5469 
5470   if (addr_mode == PostIndex) {
5471     int rm = instr->GetRm();
5472     // The immediate post index addressing mode is indicated by rm = 31.
5473     // The immediate is implied by the number of vector registers used.
5474     addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
5475                             : ReadXRegister(rm);
5476     WriteXRegister(instr->GetRn(), addr_base);
5477   } else {
5478     VIXL_ASSERT(addr_mode == Offset);
5479   }
5480 }
5481 
5482 
VisitNEONLoadStoreMultiStruct(const Instruction * instr)5483 void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
5484   NEONLoadStoreMultiStructHelper(instr, Offset);
5485 }
5486 
5487 
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)5488 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
5489     const Instruction* instr) {
5490   NEONLoadStoreMultiStructHelper(instr, PostIndex);
5491 }
5492 
5493 
NEONLoadStoreSingleStructHelper(const Instruction * instr,AddrMode addr_mode)5494 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
5495                                                 AddrMode addr_mode) {
5496   uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5497   int rt = instr->GetRt();
5498 
5499   // Bit 23 determines whether this is an offset or post-index addressing mode.
5500   // In offset mode, bits 20 to 16 should be zero; these bits encode the
5501   // register or immediate in post-index mode.
5502   if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
5503     VIXL_UNREACHABLE();
5504   }
5505 
5506   // We use the PostIndex mask here, as it works in this case for both Offset
5507   // and PostIndex addressing.
5508   bool do_load = false;
5509 
5510   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5511   VectorFormat vf_t = nfd.GetVectorFormat();
5512 
5513   VectorFormat vf = kFormat16B;
5514   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
5515     case NEON_LD1_b:
5516     case NEON_LD1_b_post:
5517     case NEON_LD2_b:
5518     case NEON_LD2_b_post:
5519     case NEON_LD3_b:
5520     case NEON_LD3_b_post:
5521     case NEON_LD4_b:
5522     case NEON_LD4_b_post:
5523       do_load = true;
5524       VIXL_FALLTHROUGH();
5525     case NEON_ST1_b:
5526     case NEON_ST1_b_post:
5527     case NEON_ST2_b:
5528     case NEON_ST2_b_post:
5529     case NEON_ST3_b:
5530     case NEON_ST3_b_post:
5531     case NEON_ST4_b:
5532     case NEON_ST4_b_post:
5533       break;
5534 
5535     case NEON_LD1_h:
5536     case NEON_LD1_h_post:
5537     case NEON_LD2_h:
5538     case NEON_LD2_h_post:
5539     case NEON_LD3_h:
5540     case NEON_LD3_h_post:
5541     case NEON_LD4_h:
5542     case NEON_LD4_h_post:
5543       do_load = true;
5544       VIXL_FALLTHROUGH();
5545     case NEON_ST1_h:
5546     case NEON_ST1_h_post:
5547     case NEON_ST2_h:
5548     case NEON_ST2_h_post:
5549     case NEON_ST3_h:
5550     case NEON_ST3_h_post:
5551     case NEON_ST4_h:
5552     case NEON_ST4_h_post:
5553       vf = kFormat8H;
5554       break;
5555     case NEON_LD1_s:
5556     case NEON_LD1_s_post:
5557     case NEON_LD2_s:
5558     case NEON_LD2_s_post:
5559     case NEON_LD3_s:
5560     case NEON_LD3_s_post:
5561     case NEON_LD4_s:
5562     case NEON_LD4_s_post:
5563       do_load = true;
5564       VIXL_FALLTHROUGH();
5565     case NEON_ST1_s:
5566     case NEON_ST1_s_post:
5567     case NEON_ST2_s:
5568     case NEON_ST2_s_post:
5569     case NEON_ST3_s:
5570     case NEON_ST3_s_post:
5571     case NEON_ST4_s:
5572     case NEON_ST4_s_post: {
5573       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
5574       VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
5575                          NEON_LD1_d_post);
5576       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
5577       VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
5578                          NEON_ST1_d_post);
5579       vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
5580       break;
5581     }
5582 
5583     case NEON_LD1R:
5584     case NEON_LD1R_post: {
5585       vf = vf_t;
5586       ld1r(vf, ReadVRegister(rt), addr);
5587       do_load = true;
5588       break;
5589     }
5590 
5591     case NEON_LD2R:
5592     case NEON_LD2R_post: {
5593       vf = vf_t;
5594       int rt2 = (rt + 1) % kNumberOfVRegisters;
5595       ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
5596       do_load = true;
5597       break;
5598     }
5599 
5600     case NEON_LD3R:
5601     case NEON_LD3R_post: {
5602       vf = vf_t;
5603       int rt2 = (rt + 1) % kNumberOfVRegisters;
5604       int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5605       ld3r(vf, ReadVRegister(rt), ReadVRegister(rt2), ReadVRegister(rt3), addr);
5606       do_load = true;
5607       break;
5608     }
5609 
5610     case NEON_LD4R:
5611     case NEON_LD4R_post: {
5612       vf = vf_t;
5613       int rt2 = (rt + 1) % kNumberOfVRegisters;
5614       int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5615       int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5616       ld4r(vf,
5617            ReadVRegister(rt),
5618            ReadVRegister(rt2),
5619            ReadVRegister(rt3),
5620            ReadVRegister(rt4),
5621            addr);
5622       do_load = true;
5623       break;
5624     }
5625     default:
5626       VIXL_UNIMPLEMENTED();
5627   }
5628 
5629   PrintRegisterFormat print_format =
5630       GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
5631   // Make sure that the print_format only includes a single lane.
5632   print_format =
5633       static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
5634 
5635   int esize = LaneSizeInBytesFromFormat(vf);
5636   int index_shift = LaneSizeInBytesLog2FromFormat(vf);
5637   int lane = instr->GetNEONLSIndex(index_shift);
5638   int scale = 0;
5639   int rt2 = (rt + 1) % kNumberOfVRegisters;
5640   int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5641   int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5642   switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
5643     case NEONLoadStoreSingle1:
5644       scale = 1;
5645       if (do_load) {
5646         ld1(vf, ReadVRegister(rt), lane, addr);
5647         LogVRead(addr, rt, print_format, lane);
5648       } else {
5649         st1(vf, ReadVRegister(rt), lane, addr);
5650         LogVWrite(addr, rt, print_format, lane);
5651       }
5652       break;
5653     case NEONLoadStoreSingle2:
5654       scale = 2;
5655       if (do_load) {
5656         ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
5657         LogVRead(addr, rt, print_format, lane);
5658         LogVRead(addr + esize, rt2, print_format, lane);
5659       } else {
5660         st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
5661         LogVWrite(addr, rt, print_format, lane);
5662         LogVWrite(addr + esize, rt2, print_format, lane);
5663       }
5664       break;
5665     case NEONLoadStoreSingle3:
5666       scale = 3;
5667       if (do_load) {
5668         ld3(vf,
5669             ReadVRegister(rt),
5670             ReadVRegister(rt2),
5671             ReadVRegister(rt3),
5672             lane,
5673             addr);
5674         LogVRead(addr, rt, print_format, lane);
5675         LogVRead(addr + esize, rt2, print_format, lane);
5676         LogVRead(addr + (2 * esize), rt3, print_format, lane);
5677       } else {
5678         st3(vf,
5679             ReadVRegister(rt),
5680             ReadVRegister(rt2),
5681             ReadVRegister(rt3),
5682             lane,
5683             addr);
5684         LogVWrite(addr, rt, print_format, lane);
5685         LogVWrite(addr + esize, rt2, print_format, lane);
5686         LogVWrite(addr + (2 * esize), rt3, print_format, lane);
5687       }
5688       break;
5689     case NEONLoadStoreSingle4:
5690       scale = 4;
5691       if (do_load) {
5692         ld4(vf,
5693             ReadVRegister(rt),
5694             ReadVRegister(rt2),
5695             ReadVRegister(rt3),
5696             ReadVRegister(rt4),
5697             lane,
5698             addr);
5699         LogVRead(addr, rt, print_format, lane);
5700         LogVRead(addr + esize, rt2, print_format, lane);
5701         LogVRead(addr + (2 * esize), rt3, print_format, lane);
5702         LogVRead(addr + (3 * esize), rt4, print_format, lane);
5703       } else {
5704         st4(vf,
5705             ReadVRegister(rt),
5706             ReadVRegister(rt2),
5707             ReadVRegister(rt3),
5708             ReadVRegister(rt4),
5709             lane,
5710             addr);
5711         LogVWrite(addr, rt, print_format, lane);
5712         LogVWrite(addr + esize, rt2, print_format, lane);
5713         LogVWrite(addr + (2 * esize), rt3, print_format, lane);
5714         LogVWrite(addr + (3 * esize), rt4, print_format, lane);
5715       }
5716       break;
5717     default:
5718       VIXL_UNIMPLEMENTED();
5719   }
5720 
5721   if (addr_mode == PostIndex) {
5722     int rm = instr->GetRm();
5723     int lane_size = LaneSizeInBytesFromFormat(vf);
5724     WriteXRegister(instr->GetRn(),
5725                    addr +
5726                        ((rm == 31) ? (scale * lane_size) : ReadXRegister(rm)));
5727   }
5728 }
5729 
5730 
VisitNEONLoadStoreSingleStruct(const Instruction * instr)5731 void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
5732   NEONLoadStoreSingleStructHelper(instr, Offset);
5733 }
5734 
5735 
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)5736 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
5737     const Instruction* instr) {
5738   NEONLoadStoreSingleStructHelper(instr, PostIndex);
5739 }
5740 
5741 
VisitNEONModifiedImmediate(const Instruction * instr)5742 void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
5743   SimVRegister& rd = ReadVRegister(instr->GetRd());
5744   int cmode = instr->GetNEONCmode();
5745   int cmode_3_1 = (cmode >> 1) & 7;
5746   int cmode_3 = (cmode >> 3) & 1;
5747   int cmode_2 = (cmode >> 2) & 1;
5748   int cmode_1 = (cmode >> 1) & 1;
5749   int cmode_0 = cmode & 1;
5750   int half_enc = instr->ExtractBit(11);
5751   int q = instr->GetNEONQ();
5752   int op_bit = instr->GetNEONModImmOp();
5753   uint64_t imm8 = instr->GetImmNEONabcdefgh();
5754   // Find the format and immediate value
5755   uint64_t imm = 0;
5756   VectorFormat vform = kFormatUndefined;
5757   switch (cmode_3_1) {
5758     case 0x0:
5759     case 0x1:
5760     case 0x2:
5761     case 0x3:
5762       vform = (q == 1) ? kFormat4S : kFormat2S;
5763       imm = imm8 << (8 * cmode_3_1);
5764       break;
5765     case 0x4:
5766     case 0x5:
5767       vform = (q == 1) ? kFormat8H : kFormat4H;
5768       imm = imm8 << (8 * cmode_1);
5769       break;
5770     case 0x6:
5771       vform = (q == 1) ? kFormat4S : kFormat2S;
5772       if (cmode_0 == 0) {
5773         imm = imm8 << 8 | 0x000000ff;
5774       } else {
5775         imm = imm8 << 16 | 0x0000ffff;
5776       }
5777       break;
5778     case 0x7:
5779       if (cmode_0 == 0 && op_bit == 0) {
5780         vform = q ? kFormat16B : kFormat8B;
5781         imm = imm8;
5782       } else if (cmode_0 == 0 && op_bit == 1) {
5783         vform = q ? kFormat2D : kFormat1D;
5784         imm = 0;
5785         for (int i = 0; i < 8; ++i) {
5786           if (imm8 & (1 << i)) {
5787             imm |= (UINT64_C(0xff) << (8 * i));
5788           }
5789         }
5790       } else {  // cmode_0 == 1, cmode == 0xf.
5791         if (half_enc == 1) {
5792           vform = q ? kFormat8H : kFormat4H;
5793           imm = Float16ToRawbits(instr->GetImmNEONFP16());
5794         } else if (op_bit == 0) {
5795           vform = q ? kFormat4S : kFormat2S;
5796           imm = FloatToRawbits(instr->GetImmNEONFP32());
5797         } else if (q == 1) {
5798           vform = kFormat2D;
5799           imm = DoubleToRawbits(instr->GetImmNEONFP64());
5800         } else {
5801           VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
5802           VisitUnallocated(instr);
5803         }
5804       }
5805       break;
5806     default:
5807       VIXL_UNREACHABLE();
5808       break;
5809   }
5810 
5811   // Find the operation
5812   NEONModifiedImmediateOp op;
5813   if (cmode_3 == 0) {
5814     if (cmode_0 == 0) {
5815       op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
5816     } else {  // cmode<0> == '1'
5817       op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
5818     }
5819   } else {  // cmode<3> == '1'
5820     if (cmode_2 == 0) {
5821       if (cmode_0 == 0) {
5822         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
5823       } else {  // cmode<0> == '1'
5824         op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
5825       }
5826     } else {  // cmode<2> == '1'
5827       if (cmode_1 == 0) {
5828         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
5829       } else {  // cmode<1> == '1'
5830         if (cmode_0 == 0) {
5831           op = NEONModifiedImmediate_MOVI;
5832         } else {  // cmode<0> == '1'
5833           op = NEONModifiedImmediate_MOVI;
5834         }
5835       }
5836     }
5837   }
5838 
5839   // Call the logic function
5840   if (op == NEONModifiedImmediate_ORR) {
5841     orr(vform, rd, rd, imm);
5842   } else if (op == NEONModifiedImmediate_BIC) {
5843     bic(vform, rd, rd, imm);
5844   } else if (op == NEONModifiedImmediate_MOVI) {
5845     movi(vform, rd, imm);
5846   } else if (op == NEONModifiedImmediate_MVNI) {
5847     mvni(vform, rd, imm);
5848   } else {
5849     VisitUnimplemented(instr);
5850   }
5851 }
5852 
5853 
VisitNEONScalar2RegMisc(const Instruction * instr)5854 void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
5855   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
5856   VectorFormat vf = nfd.GetVectorFormat();
5857 
5858   SimVRegister& rd = ReadVRegister(instr->GetRd());
5859   SimVRegister& rn = ReadVRegister(instr->GetRn());
5860 
5861   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
5862     // These instructions all use a two bit size field, except NOT and RBIT,
5863     // which use the field to encode the operation.
5864     switch (instr->Mask(NEONScalar2RegMiscMask)) {
5865       case NEON_CMEQ_zero_scalar:
5866         cmp(vf, rd, rn, 0, eq);
5867         break;
5868       case NEON_CMGE_zero_scalar:
5869         cmp(vf, rd, rn, 0, ge);
5870         break;
5871       case NEON_CMGT_zero_scalar:
5872         cmp(vf, rd, rn, 0, gt);
5873         break;
5874       case NEON_CMLT_zero_scalar:
5875         cmp(vf, rd, rn, 0, lt);
5876         break;
5877       case NEON_CMLE_zero_scalar:
5878         cmp(vf, rd, rn, 0, le);
5879         break;
5880       case NEON_ABS_scalar:
5881         abs(vf, rd, rn);
5882         break;
5883       case NEON_SQABS_scalar:
5884         abs(vf, rd, rn).SignedSaturate(vf);
5885         break;
5886       case NEON_NEG_scalar:
5887         neg(vf, rd, rn);
5888         break;
5889       case NEON_SQNEG_scalar:
5890         neg(vf, rd, rn).SignedSaturate(vf);
5891         break;
5892       case NEON_SUQADD_scalar:
5893         suqadd(vf, rd, rn);
5894         break;
5895       case NEON_USQADD_scalar:
5896         usqadd(vf, rd, rn);
5897         break;
5898       default:
5899         VIXL_UNIMPLEMENTED();
5900         break;
5901     }
5902   } else {
5903     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5904     FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
5905 
5906     // These instructions all use a one bit size field, except SQXTUN, SQXTN
5907     // and UQXTN, which use a two bit size field.
5908     switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
5909       case NEON_FRECPE_scalar:
5910         frecpe(fpf, rd, rn, fpcr_rounding);
5911         break;
5912       case NEON_FRECPX_scalar:
5913         frecpx(fpf, rd, rn);
5914         break;
5915       case NEON_FRSQRTE_scalar:
5916         frsqrte(fpf, rd, rn);
5917         break;
5918       case NEON_FCMGT_zero_scalar:
5919         fcmp_zero(fpf, rd, rn, gt);
5920         break;
5921       case NEON_FCMGE_zero_scalar:
5922         fcmp_zero(fpf, rd, rn, ge);
5923         break;
5924       case NEON_FCMEQ_zero_scalar:
5925         fcmp_zero(fpf, rd, rn, eq);
5926         break;
5927       case NEON_FCMLE_zero_scalar:
5928         fcmp_zero(fpf, rd, rn, le);
5929         break;
5930       case NEON_FCMLT_zero_scalar:
5931         fcmp_zero(fpf, rd, rn, lt);
5932         break;
5933       case NEON_SCVTF_scalar:
5934         scvtf(fpf, rd, rn, 0, fpcr_rounding);
5935         break;
5936       case NEON_UCVTF_scalar:
5937         ucvtf(fpf, rd, rn, 0, fpcr_rounding);
5938         break;
5939       case NEON_FCVTNS_scalar:
5940         fcvts(fpf, rd, rn, FPTieEven);
5941         break;
5942       case NEON_FCVTNU_scalar:
5943         fcvtu(fpf, rd, rn, FPTieEven);
5944         break;
5945       case NEON_FCVTPS_scalar:
5946         fcvts(fpf, rd, rn, FPPositiveInfinity);
5947         break;
5948       case NEON_FCVTPU_scalar:
5949         fcvtu(fpf, rd, rn, FPPositiveInfinity);
5950         break;
5951       case NEON_FCVTMS_scalar:
5952         fcvts(fpf, rd, rn, FPNegativeInfinity);
5953         break;
5954       case NEON_FCVTMU_scalar:
5955         fcvtu(fpf, rd, rn, FPNegativeInfinity);
5956         break;
5957       case NEON_FCVTZS_scalar:
5958         fcvts(fpf, rd, rn, FPZero);
5959         break;
5960       case NEON_FCVTZU_scalar:
5961         fcvtu(fpf, rd, rn, FPZero);
5962         break;
5963       case NEON_FCVTAS_scalar:
5964         fcvts(fpf, rd, rn, FPTieAway);
5965         break;
5966       case NEON_FCVTAU_scalar:
5967         fcvtu(fpf, rd, rn, FPTieAway);
5968         break;
5969       case NEON_FCVTXN_scalar:
5970         // Unlike all of the other FP instructions above, fcvtxn encodes dest
5971         // size S as size<0>=1. There's only one case, so we ignore the form.
5972         VIXL_ASSERT(instr->ExtractBit(22) == 1);
5973         fcvtxn(kFormatS, rd, rn);
5974         break;
5975       default:
5976         switch (instr->Mask(NEONScalar2RegMiscMask)) {
5977           case NEON_SQXTN_scalar:
5978             sqxtn(vf, rd, rn);
5979             break;
5980           case NEON_UQXTN_scalar:
5981             uqxtn(vf, rd, rn);
5982             break;
5983           case NEON_SQXTUN_scalar:
5984             sqxtun(vf, rd, rn);
5985             break;
5986           default:
5987             VIXL_UNIMPLEMENTED();
5988         }
5989     }
5990   }
5991 }
5992 
5993 
VisitNEONScalar2RegMiscFP16(const Instruction * instr)5994 void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
5995   VectorFormat fpf = kFormatH;
5996   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
5997 
5998   SimVRegister& rd = ReadVRegister(instr->GetRd());
5999   SimVRegister& rn = ReadVRegister(instr->GetRn());
6000 
6001   switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6002     case NEON_FRECPE_H_scalar:
6003       frecpe(fpf, rd, rn, fpcr_rounding);
6004       break;
6005     case NEON_FRECPX_H_scalar:
6006       frecpx(fpf, rd, rn);
6007       break;
6008     case NEON_FRSQRTE_H_scalar:
6009       frsqrte(fpf, rd, rn);
6010       break;
6011     case NEON_FCMGT_H_zero_scalar:
6012       fcmp_zero(fpf, rd, rn, gt);
6013       break;
6014     case NEON_FCMGE_H_zero_scalar:
6015       fcmp_zero(fpf, rd, rn, ge);
6016       break;
6017     case NEON_FCMEQ_H_zero_scalar:
6018       fcmp_zero(fpf, rd, rn, eq);
6019       break;
6020     case NEON_FCMLE_H_zero_scalar:
6021       fcmp_zero(fpf, rd, rn, le);
6022       break;
6023     case NEON_FCMLT_H_zero_scalar:
6024       fcmp_zero(fpf, rd, rn, lt);
6025       break;
6026     case NEON_SCVTF_H_scalar:
6027       scvtf(fpf, rd, rn, 0, fpcr_rounding);
6028       break;
6029     case NEON_UCVTF_H_scalar:
6030       ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6031       break;
6032     case NEON_FCVTNS_H_scalar:
6033       fcvts(fpf, rd, rn, FPTieEven);
6034       break;
6035     case NEON_FCVTNU_H_scalar:
6036       fcvtu(fpf, rd, rn, FPTieEven);
6037       break;
6038     case NEON_FCVTPS_H_scalar:
6039       fcvts(fpf, rd, rn, FPPositiveInfinity);
6040       break;
6041     case NEON_FCVTPU_H_scalar:
6042       fcvtu(fpf, rd, rn, FPPositiveInfinity);
6043       break;
6044     case NEON_FCVTMS_H_scalar:
6045       fcvts(fpf, rd, rn, FPNegativeInfinity);
6046       break;
6047     case NEON_FCVTMU_H_scalar:
6048       fcvtu(fpf, rd, rn, FPNegativeInfinity);
6049       break;
6050     case NEON_FCVTZS_H_scalar:
6051       fcvts(fpf, rd, rn, FPZero);
6052       break;
6053     case NEON_FCVTZU_H_scalar:
6054       fcvtu(fpf, rd, rn, FPZero);
6055       break;
6056     case NEON_FCVTAS_H_scalar:
6057       fcvts(fpf, rd, rn, FPTieAway);
6058       break;
6059     case NEON_FCVTAU_H_scalar:
6060       fcvtu(fpf, rd, rn, FPTieAway);
6061       break;
6062   }
6063 }
6064 
6065 
VisitNEONScalar3Diff(const Instruction * instr)6066 void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6067   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6068   VectorFormat vf = nfd.GetVectorFormat();
6069 
6070   SimVRegister& rd = ReadVRegister(instr->GetRd());
6071   SimVRegister& rn = ReadVRegister(instr->GetRn());
6072   SimVRegister& rm = ReadVRegister(instr->GetRm());
6073   switch (instr->Mask(NEONScalar3DiffMask)) {
6074     case NEON_SQDMLAL_scalar:
6075       sqdmlal(vf, rd, rn, rm);
6076       break;
6077     case NEON_SQDMLSL_scalar:
6078       sqdmlsl(vf, rd, rn, rm);
6079       break;
6080     case NEON_SQDMULL_scalar:
6081       sqdmull(vf, rd, rn, rm);
6082       break;
6083     default:
6084       VIXL_UNIMPLEMENTED();
6085   }
6086 }
6087 
6088 
VisitNEONScalar3Same(const Instruction * instr)6089 void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6090   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6091   VectorFormat vf = nfd.GetVectorFormat();
6092 
6093   SimVRegister& rd = ReadVRegister(instr->GetRd());
6094   SimVRegister& rn = ReadVRegister(instr->GetRn());
6095   SimVRegister& rm = ReadVRegister(instr->GetRm());
6096 
6097   if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6098     vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6099     switch (instr->Mask(NEONScalar3SameFPMask)) {
6100       case NEON_FMULX_scalar:
6101         fmulx(vf, rd, rn, rm);
6102         break;
6103       case NEON_FACGE_scalar:
6104         fabscmp(vf, rd, rn, rm, ge);
6105         break;
6106       case NEON_FACGT_scalar:
6107         fabscmp(vf, rd, rn, rm, gt);
6108         break;
6109       case NEON_FCMEQ_scalar:
6110         fcmp(vf, rd, rn, rm, eq);
6111         break;
6112       case NEON_FCMGE_scalar:
6113         fcmp(vf, rd, rn, rm, ge);
6114         break;
6115       case NEON_FCMGT_scalar:
6116         fcmp(vf, rd, rn, rm, gt);
6117         break;
6118       case NEON_FRECPS_scalar:
6119         frecps(vf, rd, rn, rm);
6120         break;
6121       case NEON_FRSQRTS_scalar:
6122         frsqrts(vf, rd, rn, rm);
6123         break;
6124       case NEON_FABD_scalar:
6125         fabd(vf, rd, rn, rm);
6126         break;
6127       default:
6128         VIXL_UNIMPLEMENTED();
6129     }
6130   } else {
6131     switch (instr->Mask(NEONScalar3SameMask)) {
6132       case NEON_ADD_scalar:
6133         add(vf, rd, rn, rm);
6134         break;
6135       case NEON_SUB_scalar:
6136         sub(vf, rd, rn, rm);
6137         break;
6138       case NEON_CMEQ_scalar:
6139         cmp(vf, rd, rn, rm, eq);
6140         break;
6141       case NEON_CMGE_scalar:
6142         cmp(vf, rd, rn, rm, ge);
6143         break;
6144       case NEON_CMGT_scalar:
6145         cmp(vf, rd, rn, rm, gt);
6146         break;
6147       case NEON_CMHI_scalar:
6148         cmp(vf, rd, rn, rm, hi);
6149         break;
6150       case NEON_CMHS_scalar:
6151         cmp(vf, rd, rn, rm, hs);
6152         break;
6153       case NEON_CMTST_scalar:
6154         cmptst(vf, rd, rn, rm);
6155         break;
6156       case NEON_USHL_scalar:
6157         ushl(vf, rd, rn, rm);
6158         break;
6159       case NEON_SSHL_scalar:
6160         sshl(vf, rd, rn, rm);
6161         break;
6162       case NEON_SQDMULH_scalar:
6163         sqdmulh(vf, rd, rn, rm);
6164         break;
6165       case NEON_SQRDMULH_scalar:
6166         sqrdmulh(vf, rd, rn, rm);
6167         break;
6168       case NEON_UQADD_scalar:
6169         add(vf, rd, rn, rm).UnsignedSaturate(vf);
6170         break;
6171       case NEON_SQADD_scalar:
6172         add(vf, rd, rn, rm).SignedSaturate(vf);
6173         break;
6174       case NEON_UQSUB_scalar:
6175         sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6176         break;
6177       case NEON_SQSUB_scalar:
6178         sub(vf, rd, rn, rm).SignedSaturate(vf);
6179         break;
6180       case NEON_UQSHL_scalar:
6181         ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6182         break;
6183       case NEON_SQSHL_scalar:
6184         sshl(vf, rd, rn, rm).SignedSaturate(vf);
6185         break;
6186       case NEON_URSHL_scalar:
6187         ushl(vf, rd, rn, rm).Round(vf);
6188         break;
6189       case NEON_SRSHL_scalar:
6190         sshl(vf, rd, rn, rm).Round(vf);
6191         break;
6192       case NEON_UQRSHL_scalar:
6193         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6194         break;
6195       case NEON_SQRSHL_scalar:
6196         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6197         break;
6198       default:
6199         VIXL_UNIMPLEMENTED();
6200     }
6201   }
6202 }
6203 
VisitNEONScalar3SameFP16(const Instruction * instr)6204 void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6205   SimVRegister& rd = ReadVRegister(instr->GetRd());
6206   SimVRegister& rn = ReadVRegister(instr->GetRn());
6207   SimVRegister& rm = ReadVRegister(instr->GetRm());
6208 
6209   switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6210     case NEON_FABD_H_scalar:
6211       fabd(kFormatH, rd, rn, rm);
6212       break;
6213     case NEON_FMULX_H_scalar:
6214       fmulx(kFormatH, rd, rn, rm);
6215       break;
6216     case NEON_FCMEQ_H_scalar:
6217       fcmp(kFormatH, rd, rn, rm, eq);
6218       break;
6219     case NEON_FCMGE_H_scalar:
6220       fcmp(kFormatH, rd, rn, rm, ge);
6221       break;
6222     case NEON_FCMGT_H_scalar:
6223       fcmp(kFormatH, rd, rn, rm, gt);
6224       break;
6225     case NEON_FACGE_H_scalar:
6226       fabscmp(kFormatH, rd, rn, rm, ge);
6227       break;
6228     case NEON_FACGT_H_scalar:
6229       fabscmp(kFormatH, rd, rn, rm, gt);
6230       break;
6231     case NEON_FRECPS_H_scalar:
6232       frecps(kFormatH, rd, rn, rm);
6233       break;
6234     case NEON_FRSQRTS_H_scalar:
6235       frsqrts(kFormatH, rd, rn, rm);
6236       break;
6237     default:
6238       VIXL_UNREACHABLE();
6239   }
6240 }
6241 
6242 
VisitNEONScalar3SameExtra(const Instruction * instr)6243 void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6244   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6245   VectorFormat vf = nfd.GetVectorFormat();
6246 
6247   SimVRegister& rd = ReadVRegister(instr->GetRd());
6248   SimVRegister& rn = ReadVRegister(instr->GetRn());
6249   SimVRegister& rm = ReadVRegister(instr->GetRm());
6250 
6251   switch (instr->Mask(NEONScalar3SameExtraMask)) {
6252     case NEON_SQRDMLAH_scalar:
6253       sqrdmlah(vf, rd, rn, rm);
6254       break;
6255     case NEON_SQRDMLSH_scalar:
6256       sqrdmlsh(vf, rd, rn, rm);
6257       break;
6258     default:
6259       VIXL_UNIMPLEMENTED();
6260   }
6261 }
6262 
VisitNEONScalarByIndexedElement(const Instruction * instr)6263 void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6264   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6265   VectorFormat vf = nfd.GetVectorFormat();
6266   VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6267 
6268   SimVRegister& rd = ReadVRegister(instr->GetRd());
6269   SimVRegister& rn = ReadVRegister(instr->GetRn());
6270   ByElementOp Op = NULL;
6271 
6272   int rm_reg = instr->GetRm();
6273   int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6274   if (instr->GetNEONSize() == 1) {
6275     rm_reg &= 0xf;
6276     index = (index << 1) | instr->GetNEONM();
6277   }
6278 
6279   switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6280     case NEON_SQDMULL_byelement_scalar:
6281       Op = &Simulator::sqdmull;
6282       break;
6283     case NEON_SQDMLAL_byelement_scalar:
6284       Op = &Simulator::sqdmlal;
6285       break;
6286     case NEON_SQDMLSL_byelement_scalar:
6287       Op = &Simulator::sqdmlsl;
6288       break;
6289     case NEON_SQDMULH_byelement_scalar:
6290       Op = &Simulator::sqdmulh;
6291       vf = vf_r;
6292       break;
6293     case NEON_SQRDMULH_byelement_scalar:
6294       Op = &Simulator::sqrdmulh;
6295       vf = vf_r;
6296       break;
6297     case NEON_SQRDMLAH_byelement_scalar:
6298       Op = &Simulator::sqrdmlah;
6299       vf = vf_r;
6300       break;
6301     case NEON_SQRDMLSH_byelement_scalar:
6302       Op = &Simulator::sqrdmlsh;
6303       vf = vf_r;
6304       break;
6305     default:
6306       vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6307       index = instr->GetNEONH();
6308       if (instr->GetFPType() == 0) {
6309         index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6310         rm_reg &= 0xf;
6311         vf = kFormatH;
6312       } else if ((instr->GetFPType() & 1) == 0) {
6313         index = (index << 1) | instr->GetNEONL();
6314       }
6315       switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
6316         case NEON_FMUL_H_byelement_scalar:
6317         case NEON_FMUL_byelement_scalar:
6318           Op = &Simulator::fmul;
6319           break;
6320         case NEON_FMLA_H_byelement_scalar:
6321         case NEON_FMLA_byelement_scalar:
6322           Op = &Simulator::fmla;
6323           break;
6324         case NEON_FMLS_H_byelement_scalar:
6325         case NEON_FMLS_byelement_scalar:
6326           Op = &Simulator::fmls;
6327           break;
6328         case NEON_FMULX_H_byelement_scalar:
6329         case NEON_FMULX_byelement_scalar:
6330           Op = &Simulator::fmulx;
6331           break;
6332         default:
6333           VIXL_UNIMPLEMENTED();
6334       }
6335   }
6336 
6337   (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6338 }
6339 
6340 
VisitNEONScalarCopy(const Instruction * instr)6341 void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6342   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6343   VectorFormat vf = nfd.GetVectorFormat();
6344 
6345   SimVRegister& rd = ReadVRegister(instr->GetRd());
6346   SimVRegister& rn = ReadVRegister(instr->GetRn());
6347 
6348   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6349     int imm5 = instr->GetImmNEON5();
6350     int tz = CountTrailingZeros(imm5, 32);
6351     int rn_index = imm5 >> (tz + 1);
6352     dup_element(vf, rd, rn, rn_index);
6353   } else {
6354     VIXL_UNIMPLEMENTED();
6355   }
6356 }
6357 
6358 
VisitNEONScalarPairwise(const Instruction * instr)6359 void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
6360   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
6361   VectorFormat vf = nfd.GetVectorFormat();
6362 
6363   SimVRegister& rd = ReadVRegister(instr->GetRd());
6364   SimVRegister& rn = ReadVRegister(instr->GetRn());
6365   switch (instr->Mask(NEONScalarPairwiseMask)) {
6366     case NEON_ADDP_scalar: {
6367       // All pairwise operations except ADDP use bit U to differentiate FP16
6368       // from FP32/FP64 variations.
6369       NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6370       addp(nfd_addp.GetVectorFormat(), rd, rn);
6371       break;
6372     }
6373     case NEON_FADDP_h_scalar:
6374     case NEON_FADDP_scalar:
6375       faddp(vf, rd, rn);
6376       break;
6377     case NEON_FMAXP_h_scalar:
6378     case NEON_FMAXP_scalar:
6379       fmaxp(vf, rd, rn);
6380       break;
6381     case NEON_FMAXNMP_h_scalar:
6382     case NEON_FMAXNMP_scalar:
6383       fmaxnmp(vf, rd, rn);
6384       break;
6385     case NEON_FMINP_h_scalar:
6386     case NEON_FMINP_scalar:
6387       fminp(vf, rd, rn);
6388       break;
6389     case NEON_FMINNMP_h_scalar:
6390     case NEON_FMINNMP_scalar:
6391       fminnmp(vf, rd, rn);
6392       break;
6393     default:
6394       VIXL_UNIMPLEMENTED();
6395   }
6396 }
6397 
6398 
VisitNEONScalarShiftImmediate(const Instruction * instr)6399 void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6400   SimVRegister& rd = ReadVRegister(instr->GetRd());
6401   SimVRegister& rn = ReadVRegister(instr->GetRn());
6402   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6403 
6404   static const NEONFormatMap map = {{22, 21, 20, 19},
6405                                     {NF_UNDEF,
6406                                      NF_B,
6407                                      NF_H,
6408                                      NF_H,
6409                                      NF_S,
6410                                      NF_S,
6411                                      NF_S,
6412                                      NF_S,
6413                                      NF_D,
6414                                      NF_D,
6415                                      NF_D,
6416                                      NF_D,
6417                                      NF_D,
6418                                      NF_D,
6419                                      NF_D,
6420                                      NF_D}};
6421   NEONFormatDecoder nfd(instr, &map);
6422   VectorFormat vf = nfd.GetVectorFormat();
6423 
6424   int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6425   int immhimmb = instr->GetImmNEONImmhImmb();
6426   int right_shift = (16 << highestSetBit) - immhimmb;
6427   int left_shift = immhimmb - (8 << highestSetBit);
6428   switch (instr->Mask(NEONScalarShiftImmediateMask)) {
6429     case NEON_SHL_scalar:
6430       shl(vf, rd, rn, left_shift);
6431       break;
6432     case NEON_SLI_scalar:
6433       sli(vf, rd, rn, left_shift);
6434       break;
6435     case NEON_SQSHL_imm_scalar:
6436       sqshl(vf, rd, rn, left_shift);
6437       break;
6438     case NEON_UQSHL_imm_scalar:
6439       uqshl(vf, rd, rn, left_shift);
6440       break;
6441     case NEON_SQSHLU_scalar:
6442       sqshlu(vf, rd, rn, left_shift);
6443       break;
6444     case NEON_SRI_scalar:
6445       sri(vf, rd, rn, right_shift);
6446       break;
6447     case NEON_SSHR_scalar:
6448       sshr(vf, rd, rn, right_shift);
6449       break;
6450     case NEON_USHR_scalar:
6451       ushr(vf, rd, rn, right_shift);
6452       break;
6453     case NEON_SRSHR_scalar:
6454       sshr(vf, rd, rn, right_shift).Round(vf);
6455       break;
6456     case NEON_URSHR_scalar:
6457       ushr(vf, rd, rn, right_shift).Round(vf);
6458       break;
6459     case NEON_SSRA_scalar:
6460       ssra(vf, rd, rn, right_shift);
6461       break;
6462     case NEON_USRA_scalar:
6463       usra(vf, rd, rn, right_shift);
6464       break;
6465     case NEON_SRSRA_scalar:
6466       srsra(vf, rd, rn, right_shift);
6467       break;
6468     case NEON_URSRA_scalar:
6469       ursra(vf, rd, rn, right_shift);
6470       break;
6471     case NEON_UQSHRN_scalar:
6472       uqshrn(vf, rd, rn, right_shift);
6473       break;
6474     case NEON_UQRSHRN_scalar:
6475       uqrshrn(vf, rd, rn, right_shift);
6476       break;
6477     case NEON_SQSHRN_scalar:
6478       sqshrn(vf, rd, rn, right_shift);
6479       break;
6480     case NEON_SQRSHRN_scalar:
6481       sqrshrn(vf, rd, rn, right_shift);
6482       break;
6483     case NEON_SQSHRUN_scalar:
6484       sqshrun(vf, rd, rn, right_shift);
6485       break;
6486     case NEON_SQRSHRUN_scalar:
6487       sqrshrun(vf, rd, rn, right_shift);
6488       break;
6489     case NEON_FCVTZS_imm_scalar:
6490       fcvts(vf, rd, rn, FPZero, right_shift);
6491       break;
6492     case NEON_FCVTZU_imm_scalar:
6493       fcvtu(vf, rd, rn, FPZero, right_shift);
6494       break;
6495     case NEON_SCVTF_imm_scalar:
6496       scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6497       break;
6498     case NEON_UCVTF_imm_scalar:
6499       ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6500       break;
6501     default:
6502       VIXL_UNIMPLEMENTED();
6503   }
6504 }
6505 
6506 
VisitNEONShiftImmediate(const Instruction * instr)6507 void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
6508   SimVRegister& rd = ReadVRegister(instr->GetRd());
6509   SimVRegister& rn = ReadVRegister(instr->GetRn());
6510   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6511 
6512   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
6513   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
6514   static const NEONFormatMap map = {{22, 21, 20, 19, 30},
6515                                     {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B,
6516                                      NF_4H,    NF_8H,    NF_4H,    NF_8H,
6517                                      NF_2S,    NF_4S,    NF_2S,    NF_4S,
6518                                      NF_2S,    NF_4S,    NF_2S,    NF_4S,
6519                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
6520                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
6521                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
6522                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D}};
6523   NEONFormatDecoder nfd(instr, &map);
6524   VectorFormat vf = nfd.GetVectorFormat();
6525 
6526   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
6527   static const NEONFormatMap map_l =
6528       {{22, 21, 20, 19},
6529        {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
6530   VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
6531 
6532   int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6533   int immhimmb = instr->GetImmNEONImmhImmb();
6534   int right_shift = (16 << highestSetBit) - immhimmb;
6535   int left_shift = immhimmb - (8 << highestSetBit);
6536 
6537   switch (instr->Mask(NEONShiftImmediateMask)) {
6538     case NEON_SHL:
6539       shl(vf, rd, rn, left_shift);
6540       break;
6541     case NEON_SLI:
6542       sli(vf, rd, rn, left_shift);
6543       break;
6544     case NEON_SQSHLU:
6545       sqshlu(vf, rd, rn, left_shift);
6546       break;
6547     case NEON_SRI:
6548       sri(vf, rd, rn, right_shift);
6549       break;
6550     case NEON_SSHR:
6551       sshr(vf, rd, rn, right_shift);
6552       break;
6553     case NEON_USHR:
6554       ushr(vf, rd, rn, right_shift);
6555       break;
6556     case NEON_SRSHR:
6557       sshr(vf, rd, rn, right_shift).Round(vf);
6558       break;
6559     case NEON_URSHR:
6560       ushr(vf, rd, rn, right_shift).Round(vf);
6561       break;
6562     case NEON_SSRA:
6563       ssra(vf, rd, rn, right_shift);
6564       break;
6565     case NEON_USRA:
6566       usra(vf, rd, rn, right_shift);
6567       break;
6568     case NEON_SRSRA:
6569       srsra(vf, rd, rn, right_shift);
6570       break;
6571     case NEON_URSRA:
6572       ursra(vf, rd, rn, right_shift);
6573       break;
6574     case NEON_SQSHL_imm:
6575       sqshl(vf, rd, rn, left_shift);
6576       break;
6577     case NEON_UQSHL_imm:
6578       uqshl(vf, rd, rn, left_shift);
6579       break;
6580     case NEON_SCVTF_imm:
6581       scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6582       break;
6583     case NEON_UCVTF_imm:
6584       ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6585       break;
6586     case NEON_FCVTZS_imm:
6587       fcvts(vf, rd, rn, FPZero, right_shift);
6588       break;
6589     case NEON_FCVTZU_imm:
6590       fcvtu(vf, rd, rn, FPZero, right_shift);
6591       break;
6592     case NEON_SSHLL:
6593       vf = vf_l;
6594       if (instr->Mask(NEON_Q)) {
6595         sshll2(vf, rd, rn, left_shift);
6596       } else {
6597         sshll(vf, rd, rn, left_shift);
6598       }
6599       break;
6600     case NEON_USHLL:
6601       vf = vf_l;
6602       if (instr->Mask(NEON_Q)) {
6603         ushll2(vf, rd, rn, left_shift);
6604       } else {
6605         ushll(vf, rd, rn, left_shift);
6606       }
6607       break;
6608     case NEON_SHRN:
6609       if (instr->Mask(NEON_Q)) {
6610         shrn2(vf, rd, rn, right_shift);
6611       } else {
6612         shrn(vf, rd, rn, right_shift);
6613       }
6614       break;
6615     case NEON_RSHRN:
6616       if (instr->Mask(NEON_Q)) {
6617         rshrn2(vf, rd, rn, right_shift);
6618       } else {
6619         rshrn(vf, rd, rn, right_shift);
6620       }
6621       break;
6622     case NEON_UQSHRN:
6623       if (instr->Mask(NEON_Q)) {
6624         uqshrn2(vf, rd, rn, right_shift);
6625       } else {
6626         uqshrn(vf, rd, rn, right_shift);
6627       }
6628       break;
6629     case NEON_UQRSHRN:
6630       if (instr->Mask(NEON_Q)) {
6631         uqrshrn2(vf, rd, rn, right_shift);
6632       } else {
6633         uqrshrn(vf, rd, rn, right_shift);
6634       }
6635       break;
6636     case NEON_SQSHRN:
6637       if (instr->Mask(NEON_Q)) {
6638         sqshrn2(vf, rd, rn, right_shift);
6639       } else {
6640         sqshrn(vf, rd, rn, right_shift);
6641       }
6642       break;
6643     case NEON_SQRSHRN:
6644       if (instr->Mask(NEON_Q)) {
6645         sqrshrn2(vf, rd, rn, right_shift);
6646       } else {
6647         sqrshrn(vf, rd, rn, right_shift);
6648       }
6649       break;
6650     case NEON_SQSHRUN:
6651       if (instr->Mask(NEON_Q)) {
6652         sqshrun2(vf, rd, rn, right_shift);
6653       } else {
6654         sqshrun(vf, rd, rn, right_shift);
6655       }
6656       break;
6657     case NEON_SQRSHRUN:
6658       if (instr->Mask(NEON_Q)) {
6659         sqrshrun2(vf, rd, rn, right_shift);
6660       } else {
6661         sqrshrun(vf, rd, rn, right_shift);
6662       }
6663       break;
6664     default:
6665       VIXL_UNIMPLEMENTED();
6666   }
6667 }
6668 
6669 
VisitNEONTable(const Instruction * instr)6670 void Simulator::VisitNEONTable(const Instruction* instr) {
6671   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
6672   VectorFormat vf = nfd.GetVectorFormat();
6673 
6674   SimVRegister& rd = ReadVRegister(instr->GetRd());
6675   SimVRegister& rn = ReadVRegister(instr->GetRn());
6676   SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
6677   SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
6678   SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
6679   SimVRegister& rm = ReadVRegister(instr->GetRm());
6680 
6681   switch (instr->Mask(NEONTableMask)) {
6682     case NEON_TBL_1v:
6683       tbl(vf, rd, rn, rm);
6684       break;
6685     case NEON_TBL_2v:
6686       tbl(vf, rd, rn, rn2, rm);
6687       break;
6688     case NEON_TBL_3v:
6689       tbl(vf, rd, rn, rn2, rn3, rm);
6690       break;
6691     case NEON_TBL_4v:
6692       tbl(vf, rd, rn, rn2, rn3, rn4, rm);
6693       break;
6694     case NEON_TBX_1v:
6695       tbx(vf, rd, rn, rm);
6696       break;
6697     case NEON_TBX_2v:
6698       tbx(vf, rd, rn, rn2, rm);
6699       break;
6700     case NEON_TBX_3v:
6701       tbx(vf, rd, rn, rn2, rn3, rm);
6702       break;
6703     case NEON_TBX_4v:
6704       tbx(vf, rd, rn, rn2, rn3, rn4, rm);
6705       break;
6706     default:
6707       VIXL_UNIMPLEMENTED();
6708   }
6709 }
6710 
6711 
VisitNEONPerm(const Instruction * instr)6712 void Simulator::VisitNEONPerm(const Instruction* instr) {
6713   NEONFormatDecoder nfd(instr);
6714   VectorFormat vf = nfd.GetVectorFormat();
6715 
6716   SimVRegister& rd = ReadVRegister(instr->GetRd());
6717   SimVRegister& rn = ReadVRegister(instr->GetRn());
6718   SimVRegister& rm = ReadVRegister(instr->GetRm());
6719 
6720   switch (instr->Mask(NEONPermMask)) {
6721     case NEON_TRN1:
6722       trn1(vf, rd, rn, rm);
6723       break;
6724     case NEON_TRN2:
6725       trn2(vf, rd, rn, rm);
6726       break;
6727     case NEON_UZP1:
6728       uzp1(vf, rd, rn, rm);
6729       break;
6730     case NEON_UZP2:
6731       uzp2(vf, rd, rn, rm);
6732       break;
6733     case NEON_ZIP1:
6734       zip1(vf, rd, rn, rm);
6735       break;
6736     case NEON_ZIP2:
6737       zip2(vf, rd, rn, rm);
6738       break;
6739     default:
6740       VIXL_UNIMPLEMENTED();
6741   }
6742 }
6743 
6744 
DoUnreachable(const Instruction * instr)6745 void Simulator::DoUnreachable(const Instruction* instr) {
6746   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
6747               (instr->GetImmException() == kUnreachableOpcode));
6748 
6749   fprintf(stream_,
6750           "Hit UNREACHABLE marker at pc=%p.\n",
6751           reinterpret_cast<const void*>(instr));
6752   abort();
6753 }
6754 
6755 
DoTrace(const Instruction * instr)6756 void Simulator::DoTrace(const Instruction* instr) {
6757   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
6758               (instr->GetImmException() == kTraceOpcode));
6759 
6760   // Read the arguments encoded inline in the instruction stream.
6761   uint32_t parameters;
6762   uint32_t command;
6763 
6764   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
6765   memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
6766   memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
6767 
6768   switch (command) {
6769     case TRACE_ENABLE:
6770       SetTraceParameters(GetTraceParameters() | parameters);
6771       break;
6772     case TRACE_DISABLE:
6773       SetTraceParameters(GetTraceParameters() & ~parameters);
6774       break;
6775     default:
6776       VIXL_UNREACHABLE();
6777   }
6778 
6779   WritePc(instr->GetInstructionAtOffset(kTraceLength));
6780 }
6781 
6782 
DoLog(const Instruction * instr)6783 void Simulator::DoLog(const Instruction* instr) {
6784   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
6785               (instr->GetImmException() == kLogOpcode));
6786 
6787   // Read the arguments encoded inline in the instruction stream.
6788   uint32_t parameters;
6789 
6790   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
6791   memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
6792 
6793   // We don't support a one-shot LOG_DISASM.
6794   VIXL_ASSERT((parameters & LOG_DISASM) == 0);
6795   // Print the requested information.
6796   if (parameters & LOG_SYSREGS) PrintSystemRegisters();
6797   if (parameters & LOG_REGS) PrintRegisters();
6798   if (parameters & LOG_VREGS) PrintVRegisters();
6799 
6800   WritePc(instr->GetInstructionAtOffset(kLogLength));
6801 }
6802 
6803 
DoPrintf(const Instruction * instr)6804 void Simulator::DoPrintf(const Instruction* instr) {
6805   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
6806               (instr->GetImmException() == kPrintfOpcode));
6807 
6808   // Read the arguments encoded inline in the instruction stream.
6809   uint32_t arg_count;
6810   uint32_t arg_pattern_list;
6811   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
6812   memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
6813   memcpy(&arg_pattern_list,
6814          instr + kPrintfArgPatternListOffset,
6815          sizeof(arg_pattern_list));
6816 
6817   VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
6818   VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
6819 
6820   // We need to call the host printf function with a set of arguments defined by
6821   // arg_pattern_list. Because we don't know the types and sizes of the
6822   // arguments, this is very difficult to do in a robust and portable way. To
6823   // work around the problem, we pick apart the format string, and print one
6824   // format placeholder at a time.
6825 
6826   // Allocate space for the format string. We take a copy, so we can modify it.
6827   // Leave enough space for one extra character per expected argument (plus the
6828   // '\0' termination).
6829   const char* format_base = ReadRegister<const char*>(0);
6830   VIXL_ASSERT(format_base != NULL);
6831   size_t length = strlen(format_base) + 1;
6832   char* const format = new char[length + arg_count];
6833 
6834   // A list of chunks, each with exactly one format placeholder.
6835   const char* chunks[kPrintfMaxArgCount];
6836 
6837   // Copy the format string and search for format placeholders.
6838   uint32_t placeholder_count = 0;
6839   char* format_scratch = format;
6840   for (size_t i = 0; i < length; i++) {
6841     if (format_base[i] != '%') {
6842       *format_scratch++ = format_base[i];
6843     } else {
6844       if (format_base[i + 1] == '%') {
6845         // Ignore explicit "%%" sequences.
6846         *format_scratch++ = format_base[i];
6847         i++;
6848         // Chunks after the first are passed as format strings to printf, so we
6849         // need to escape '%' characters in those chunks.
6850         if (placeholder_count > 0) *format_scratch++ = format_base[i];
6851       } else {
6852         VIXL_CHECK(placeholder_count < arg_count);
6853         // Insert '\0' before placeholders, and store their locations.
6854         *format_scratch++ = '\0';
6855         chunks[placeholder_count++] = format_scratch;
6856         *format_scratch++ = format_base[i];
6857       }
6858     }
6859   }
6860   VIXL_CHECK(placeholder_count == arg_count);
6861 
6862   // Finally, call printf with each chunk, passing the appropriate register
6863   // argument. Normally, printf returns the number of bytes transmitted, so we
6864   // can emulate a single printf call by adding the result from each chunk. If
6865   // any call returns a negative (error) value, though, just return that value.
6866 
6867   printf("%s", clr_printf);
6868 
6869   // Because '\0' is inserted before each placeholder, the first string in
6870   // 'format' contains no format placeholders and should be printed literally.
6871   int result = printf("%s", format);
6872   int pcs_r = 1;  // Start at x1. x0 holds the format string.
6873   int pcs_f = 0;  // Start at d0.
6874   if (result >= 0) {
6875     for (uint32_t i = 0; i < placeholder_count; i++) {
6876       int part_result = -1;
6877 
6878       uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
6879       arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
6880       switch (arg_pattern) {
6881         case kPrintfArgW:
6882           part_result = printf(chunks[i], ReadWRegister(pcs_r++));
6883           break;
6884         case kPrintfArgX:
6885           part_result = printf(chunks[i], ReadXRegister(pcs_r++));
6886           break;
6887         case kPrintfArgD:
6888           part_result = printf(chunks[i], ReadDRegister(pcs_f++));
6889           break;
6890         default:
6891           VIXL_UNREACHABLE();
6892       }
6893 
6894       if (part_result < 0) {
6895         // Handle error values.
6896         result = part_result;
6897         break;
6898       }
6899 
6900       result += part_result;
6901     }
6902   }
6903 
6904   printf("%s", clr_normal);
6905 
6906   // Printf returns its result in x0 (just like the C library's printf).
6907   WriteXRegister(0, result);
6908 
6909   // The printf parameters are inlined in the code, so skip them.
6910   WritePc(instr->GetInstructionAtOffset(kPrintfLength));
6911 
6912   // Set LR as if we'd just called a native printf function.
6913   WriteLr(ReadPc());
6914 
6915   delete[] format;
6916 }
6917 
6918 
6919 #ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
DoRuntimeCall(const Instruction * instr)6920 void Simulator::DoRuntimeCall(const Instruction* instr) {
6921   VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
6922   // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
6923   // to call are passed inlined in the assembly.
6924   uintptr_t call_wrapper_address =
6925       Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
6926   uintptr_t function_address =
6927       Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
6928   RuntimeCallType call_type = static_cast<RuntimeCallType>(
6929       Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
6930   auto runtime_call_wrapper =
6931       reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
6932 
6933   if (call_type == kCallRuntime) {
6934     WriteRegister(kLinkRegCode,
6935                   instr->GetInstructionAtOffset(kRuntimeCallLength));
6936   }
6937   runtime_call_wrapper(this, function_address);
6938   // Read the return address from `lr` and write it into `pc`.
6939   WritePc(ReadRegister<Instruction*>(kLinkRegCode));
6940 }
6941 #else
DoRuntimeCall(const Instruction * instr)6942 void Simulator::DoRuntimeCall(const Instruction* instr) {
6943   USE(instr);
6944   VIXL_UNREACHABLE();
6945 }
6946 #endif
6947 
6948 
DoConfigureCPUFeatures(const Instruction * instr)6949 void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
6950   VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
6951 
6952   typedef ConfigureCPUFeaturesElementType ElementType;
6953   VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
6954               std::numeric_limits<ElementType>::max());
6955 
6956   // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
6957 
6958   size_t element_size = sizeof(ElementType);
6959   size_t offset = kConfigureCPUFeaturesListOffset;
6960 
6961   // Read the kNone-terminated list of features.
6962   CPUFeatures parameters;
6963   while (true) {
6964     ElementType feature = Memory::Read<ElementType>(instr + offset);
6965     offset += element_size;
6966     if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
6967     parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
6968   }
6969 
6970   switch (instr->GetImmException()) {
6971     case kSetCPUFeaturesOpcode:
6972       SetCPUFeatures(parameters);
6973       break;
6974     case kEnableCPUFeaturesOpcode:
6975       GetCPUFeatures()->Combine(parameters);
6976       break;
6977     case kDisableCPUFeaturesOpcode:
6978       GetCPUFeatures()->Remove(parameters);
6979       break;
6980     default:
6981       VIXL_UNREACHABLE();
6982       break;
6983   }
6984 
6985   WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
6986 }
6987 
6988 
DoSaveCPUFeatures(const Instruction * instr)6989 void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
6990   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
6991               (instr->GetImmException() == kSaveCPUFeaturesOpcode));
6992   USE(instr);
6993 
6994   saved_cpu_features_.push_back(*GetCPUFeatures());
6995 }
6996 
6997 
DoRestoreCPUFeatures(const Instruction * instr)6998 void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
6999   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
7000               (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
7001   USE(instr);
7002 
7003   SetCPUFeatures(saved_cpu_features_.back());
7004   saved_cpu_features_.pop_back();
7005 }
7006 
7007 
7008 }  // namespace aarch64
7009 }  // namespace vixl
7010 
7011 #endif  // VIXL_INCLUDE_SIMULATOR_AARCH64
7012