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