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