10cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Copyright 2015, ARM Limited
20cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// All rights reserved.
30cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
40cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Redistribution and use in source and binary forms, with or without
50cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// modification, are permitted provided that the following conditions are met:
60cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
70cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//   * Redistributions of source code must retain the above copyright notice,
80cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//     this list of conditions and the following disclaimer.
90cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//   * Redistributions in binary form must reproduce the above copyright notice,
100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//     this list of conditions and the following disclaimer in the documentation
110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//     and/or other materials provided with the distribution.
120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//     used to endorse or promote products derived from this software without
140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//     specific prior written permission.
150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
279795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang#ifdef VIXL_INCLUDE_SIMULATOR
280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#include <string.h>
300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#include <cmath>
310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#include "vixl/a64/simulator-a64.h"
320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
330cc8b6ece4b3e757e11a906a81ece292437713abarmvixlnamespace vixl {
340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
350cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst Instruction* Simulator::kEndOfSimAddress = NULL;
360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
370cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int width = msb - lsb + 1;
390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(is_uintn(width, bits) || is_intn(width, bits));
400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bits <<= lsb;
420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t mask = ((1 << width) - 1) << lsb;
430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((mask & write_ignore_mask_) == 0);
440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  value_ = (value_ & ~mask) | (bits & mask);
460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
490cc8b6ece4b3e757e11a906a81ece292437713abarmvixlSimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (id) {
510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NZCV:
520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FPCR:
540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNREACHABLE();
570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return SimSystemRegister();
580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
620cc8b6ece4b3e757e11a906a81ece292437713abarmvixlSimulator::Simulator(Decoder* decoder, FILE* stream) {
630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Ensure that shift operations act as the simulator expects.
640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
67f83765e26812f0d09307defe5dcbabb19632ab45Serban Constantinescu  instruction_stats_ = false;
68f83765e26812f0d09307defe5dcbabb19632ab45Serban Constantinescu
690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Set up the decoder.
700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  decoder_ = decoder;
710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  decoder_->AppendVisitor(this);
720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  stream_ = stream;
740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  print_disasm_ = new PrintDisassembler(stream_);
750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_coloured_trace(false);
760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  trace_parameters_ = LOG_NONE;
770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  ResetState();
790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Allocate and set up the simulator stack.
810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  stack_ = new byte[stack_size_];
820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  stack_limit_ = stack_ + stack_protection_size_;
830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Configure the starting stack pointer.
840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //  - Find the top of the stack.
850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  byte * tos = stack_ + stack_size_;
860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //  - There's a protection region at both ends of the stack.
870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  tos -= stack_protection_size_;
880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //  - The stack pointer must be 16-byte aligned.
890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  tos = AlignDown(tos, 16);
900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_sp(tos);
910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Set the sample period to 10, as the VIXL examples and tests are short.
930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  instrumentation_ = new Instrument("vixl_stats.csv", 10);
940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print a warning about exclusive-access instructions, but only the first
960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // time they are encountered. This warning can be silenced using
970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // SilenceExclusiveAccessWarning().
980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  print_exclusive_access_warning_ = true;
990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
1000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1020cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::ResetState() {
1030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Reset the system registers.
1040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
1050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
1060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Reset registers to 0.
1080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  pc_ = NULL;
1090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  pc_modified_ = false;
1100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_xreg(i, 0xbadbeef);
1120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
1130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Set FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
1140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t nan_bits = UINT64_C(0x7ff0dead7f8beef1);
1150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(IsSignallingNaN(rawbits_to_double(nan_bits & kDRegMask)));
1160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(IsSignallingNaN(rawbits_to_float(nan_bits & kSRegMask)));
1170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
1180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_dreg_bits(i, nan_bits);
1190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
1200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Returning to address 0 exits the Simulator.
1210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_lr(kEndOfSimAddress);
1220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
1230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1250cc8b6ece4b3e757e11a906a81ece292437713abarmvixlSimulator::~Simulator() {
126f83765e26812f0d09307defe5dcbabb19632ab45Serban Constantinescu  delete[] stack_;
1270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The decoder may outlive the simulator.
1280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  decoder_->RemoveVisitor(print_disasm_);
1290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  delete print_disasm_;
1300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  decoder_->RemoveVisitor(instrumentation_);
1320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  delete instrumentation_;
1330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
1340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1360cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::Run() {
1370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  pc_modified_ = false;
1380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  while (pc_ != kEndOfSimAddress) {
1390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    ExecuteInstruction();
1400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    LogAllWrittenRegisters();
1410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
1420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
1430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1450cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::RunFrom(const Instruction* first) {
1460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_pc(first);
1470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Run();
1480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
1490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1510cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::xreg_names[] = {
1520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
1530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
1540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
1550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"x24", "x25", "x26", "x27", "x28", "x29", "lr",  "xzr", "sp"};
1560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1570cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::wreg_names[] = {
1580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"w0",  "w1",  "w2",  "w3",  "w4",  "w5",  "w6",  "w7",
1590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"w8",  "w9",  "w10", "w11", "w12", "w13", "w14", "w15",
1600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
1610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr", "wsp"};
1620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1630cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::sreg_names[] = {
1640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
1650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
1660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
1670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
1680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1690cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::dreg_names[] = {
1700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
1710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
1720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
1730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
1740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1750cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::vreg_names[] = {
1760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
1770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
1780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
1790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
1800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1830cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
1840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(code < kNumberOfRegisters);
1850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // If the code represents the stack pointer, index the name after zr.
1860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
1870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    code = kZeroRegCode + 1;
1880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
1890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return wreg_names[code];
1900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
1910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
1930cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
1940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(code < kNumberOfRegisters);
1950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // If the code represents the stack pointer, index the name after zr.
1960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
1970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    code = kZeroRegCode + 1;
1980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
1990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return xreg_names[code];
2000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
2010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2030cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::SRegNameForCode(unsigned code) {
2040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(code < kNumberOfFPRegisters);
2050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return sreg_names[code];
2060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
2070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2090cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::DRegNameForCode(unsigned code) {
2100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(code < kNumberOfFPRegisters);
2110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return dreg_names[code];
2120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
2130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2150cc8b6ece4b3e757e11a906a81ece292437713abarmvixlconst char* Simulator::VRegNameForCode(unsigned code) {
2160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(code < kNumberOfVRegisters);
2170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return vreg_names[code];
2180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
2190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define COLOUR(colour_code)       "\033[0;" colour_code "m"
2220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define COLOUR_BOLD(colour_code)  "\033[1;" colour_code "m"
2230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define NORMAL  ""
2240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define GREY    "30"
2250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define RED     "31"
2260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define GREEN   "32"
2270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define YELLOW  "33"
2280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define BLUE    "34"
2290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define MAGENTA "35"
2300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define CYAN    "36"
2310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl#define WHITE   "37"
2320cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::set_coloured_trace(bool value) {
2330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  coloured_trace_ = value;
2340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_normal          = value ? COLOUR(NORMAL)        : "";
2360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_flag_name       = value ? COLOUR_BOLD(WHITE)    : "";
2370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_flag_value      = value ? COLOUR(NORMAL)        : "";
2380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_reg_name        = value ? COLOUR_BOLD(CYAN)     : "";
2390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_reg_value       = value ? COLOUR(CYAN)          : "";
2400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_vreg_name       = value ? COLOUR_BOLD(MAGENTA)  : "";
2410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_vreg_value      = value ? COLOUR(MAGENTA)       : "";
2420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_memory_address  = value ? COLOUR_BOLD(BLUE)     : "";
2430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_warning         = value ? COLOUR_BOLD(YELLOW)   : "";
2440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_warning_message = value ? COLOUR(YELLOW)        : "";
2450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  clr_printf          = value ? COLOUR(GREEN)         : "";
2460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
2470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2490cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::set_trace_parameters(int parameters) {
2500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool disasm_before = trace_parameters_ & LOG_DISASM;
2510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  trace_parameters_ = parameters;
2520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool disasm_after = trace_parameters_ & LOG_DISASM;
2530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (disasm_before != disasm_after) {
2550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (disasm_after) {
2560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      decoder_->InsertVisitorBefore(print_disasm_, this);
2570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
2580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      decoder_->RemoveVisitor(print_disasm_);
2590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
2600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
2610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
2620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2640cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::set_instruction_stats(bool value) {
2650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (value != instruction_stats_) {
2660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (value) {
2670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      decoder_->AppendVisitor(instrumentation_);
2680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
2690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      decoder_->RemoveVisitor(instrumentation_);
2700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
2710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    instruction_stats_ = value;
2720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
2730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
2740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Helpers ---------------------------------------------------------------------
2769795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wanguint64_t Simulator::AddWithCarry(unsigned reg_size,
2779795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang                                 bool set_flags,
2789795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang                                 uint64_t left,
2799795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang                                 uint64_t right,
2809795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang                                 int carry_in) {
2810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
2820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
2830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2849795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang  uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
2859795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang  uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
2869795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang  uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
2870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2889795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang  left &= reg_mask;
2899795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang  right &= reg_mask;
2909795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang  uint64_t result = (left + right + carry_in) & reg_mask;
2910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2929795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang  if (set_flags) {
2939795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    nzcv().SetN(CalcNFlag(result, reg_size));
2949795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    nzcv().SetZ(CalcZFlag(result));
2950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
2969795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    // Compute the C flag by comparing the result to the max unsigned integer.
2979795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    uint64_t max_uint_2op = max_uint - carry_in;
2989795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
2999795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    nzcv().SetC(C ? 1 : 0);
3000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Overflow iff the sign bit is the same for the two inputs and different
3020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // for the result.
3039795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    uint64_t left_sign = left & sign_mask;
3049795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    uint64_t right_sign = right & sign_mask;
3059795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    uint64_t result_sign = result & sign_mask;
3069795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    bool V = (left_sign == right_sign) && (left_sign != result_sign);
3079795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang    nzcv().SetV(V ? 1 : 0);
3080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    LogSystemRegister(NZCV);
3100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
3110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return result;
3120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
3130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3150cc8b6ece4b3e757e11a906a81ece292437713abarmvixlint64_t Simulator::ShiftOperand(unsigned reg_size,
3160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                int64_t value,
3170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                Shift shift_type,
3180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                unsigned amount) {
3190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (amount == 0) {
3200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    return value;
3210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
3220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
3230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (shift_type) {
3240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LSL:
3250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return (value << amount) & mask;
3260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LSR:
3270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return static_cast<uint64_t>(value) >> amount;
3280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ASR: {
3290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // Shift used to restore the sign.
3300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      unsigned s_shift = kXRegSize - reg_size;
3310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // Value with its sign restored.
3320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int64_t s_value = (value << s_shift) >> s_shift;
3330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return (s_value >> amount) & mask;
3340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
3350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ROR: {
3360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (reg_size == kWRegSize) {
3370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        value &= kWRegMask;
3380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
3390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return (static_cast<uint64_t>(value) >> amount) |
3400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl             ((value & ((INT64_C(1) << amount) - 1)) <<
3410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              (reg_size - amount));
3420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
3430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
3440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
3450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return 0;
3460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
3470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
3480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3500cc8b6ece4b3e757e11a906a81ece292437713abarmvixlint64_t Simulator::ExtendValue(unsigned reg_size,
3510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                               int64_t value,
3520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                               Extend extend_type,
3530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                               unsigned left_shift) {
3540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (extend_type) {
3550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UXTB:
3560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      value &= kByteMask;
3570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
3580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UXTH:
3590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      value &= kHalfWordMask;
3600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
3610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UXTW:
3620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      value &= kWordMask;
3630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
3640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SXTB:
3650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      value = (value << 56) >> 56;
3660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
3670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SXTH:
3680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      value = (value << 48) >> 48;
3690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
3700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SXTW:
3710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      value = (value << 32) >> 32;
3720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
3730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UXTX:
3740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SXTX:
3750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
3760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
3770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNREACHABLE();
3780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
3790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
3800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return (value << left_shift) & mask;
3810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
3820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3840cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
3850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
3860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
3870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // TODO: This assumes that the C++ implementation handles comparisons in the
3880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // way that we expect (as per AssertSupportedFPCR()).
3890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool process_exception = false;
3900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
3910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetRawValue(FPUnorderedFlag);
3920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
3930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        (trap == EnableTrap)) {
3940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      process_exception = true;
3950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
3960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (val0 < val1) {
3970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetRawValue(FPLessThanFlag);
3980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (val0 > val1) {
3990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetRawValue(FPGreaterThanFlag);
4000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (val0 == val1) {
4010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetRawValue(FPEqualFlag);
4020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
4030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_UNREACHABLE();
4040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LogSystemRegister(NZCV);
4060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (process_exception) FPProcessException();
4070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4100cc8b6ece4b3e757e11a906a81ece292437713abarmvixlSimulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
4110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    unsigned reg_size, unsigned lane_size) {
4120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(reg_size >= lane_size);
4130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t format = 0;
4150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (reg_size != lane_size) {
4160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (reg_size) {
4170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default: VIXL_UNREACHABLE(); break;
4180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case kQRegSizeInBytes: format = kPrintRegAsQVector; break;
4190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case kDRegSizeInBytes: format = kPrintRegAsDVector; break;
4200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
4210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (lane_size) {
4240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE(); break;
4250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kQRegSizeInBytes: format |= kPrintReg1Q; break;
4260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kDRegSizeInBytes: format |= kPrintReg1D; break;
4270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kSRegSizeInBytes: format |= kPrintReg1S; break;
4280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kHRegSizeInBytes: format |= kPrintReg1H; break;
4290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kBRegSizeInBytes: format |= kPrintReg1B; break;
4300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // These sizes would be duplicate case labels.
4320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
4330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
4340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
4350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
4360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return static_cast<PrintRegisterFormat>(format);
4380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4410cc8b6ece4b3e757e11a906a81ece292437713abarmvixlSimulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
4420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat vform) {
4430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (vform) {
4440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE(); return kPrintReg16B;
4450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat16B: return kPrintReg16B;
4460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat8B: return kPrintReg8B;
4470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat8H: return kPrintReg8H;
4480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat4H: return kPrintReg4H;
4490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat4S: return kPrintReg4S;
4500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat2S: return kPrintReg2S;
4510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat2D: return kPrintReg2D;
4520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kFormat1D: return kPrintReg1D;
4530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4570cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintWrittenRegisters() {
4580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
4590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
4600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4640cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintWrittenVRegisters() {
4650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
4660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // At this point there is no type information, so print as a raw 1Q.
4670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
4680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4720cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintSystemRegisters() {
4730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintSystemRegister(NZCV);
4740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintSystemRegister(FPCR);
4750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4780cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintRegisters() {
4790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
4800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    PrintRegister(i);
4810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4850cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintVRegisters() {
4860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
4870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // At this point there is no type information, so print as a raw 1Q.
4880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    PrintVRegister(i, kPrintReg1Q);
4890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
4900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
4910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
4930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Print a register's name and raw value.
4940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
4950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Only the least-significant `size_in_bytes` bytes of the register are printed,
4960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// but the value is aligned as if the whole register had been printed.
4970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
4980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
4990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// -- the default -- so that the whole register is printed. Other values of
5000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// size_in_bytes are intended for use when the register hasn't actually been
5010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// updated (such as in PrintWrite).
5020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
5030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// No newline is printed. This allows the caller to print more details (such as
5040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// a memory access annotation).
5050cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
5060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                       int size_in_bytes) {
5070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template for all supported sizes.
5080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# x{code}: 0xffeeddccbbaa9988"
5090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# w{code}:         0xbbaa9988"
5100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# w{code}<15:0>:       0x9988"
5110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# w{code}<7:0>:          0x88"
5120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
5130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  const char * name = "";
5150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  const char * suffix = "";
5160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (size_in_bytes) {
5170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kXRegSizeInBytes: name = XRegNameForCode(code, r31mode); break;
5180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case kWRegSizeInBytes: name = WRegNameForCode(code, r31mode); break;
5190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 2:
5200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      name = WRegNameForCode(code, r31mode);
5210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      suffix = "<15:0>";
5220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      padding_chars -= strlen(suffix);
5230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
5240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 1:
5250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      name = WRegNameForCode(code, r31mode);
5260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      suffix = "<7:0>";
5270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      padding_chars -= strlen(suffix);
5280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
5290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
5300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNREACHABLE();
5310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
5320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
5330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print leading padding spaces.
5350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
5360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = 0; i < padding_chars; i++) {
5370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    putc(' ', stream_);
5380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
5390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print the specified bits in hexadecimal format.
5410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t bits = reg<uint64_t>(code, r31mode);
5420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
5430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
5440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int chars = size_in_bytes * 2;
5460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "%s0x%0*" PRIx64 "%s",
5470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          clr_reg_value, chars, bits, clr_normal);
5480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
5490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5510cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
5520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  registers_[code].NotifyRegisterLogged();
5530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Don't print writes into xzr.
5550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
5560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    return;
5570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
5580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template for all x and w registers:
5600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# x{code}: 0x{value}"
5610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# w{code}: 0x{value}"
5620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintRegisterRawHelper(code, r31mode);
5640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "\n");
5650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
5660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Print a register's name and raw value.
5690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
5700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// The `bytes` and `lsb` arguments can be used to limit the bytes that are
5710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// printed. These arguments are intended for use in cases where register hasn't
5720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// actually been updated (such as in PrintVWrite).
5730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
5740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// No newline is printed. This allows the caller to print more details (such as
5750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// a floating-point interpretation or a memory access annotation).
5760cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
5770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template for vector types:
5780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# v{code}: 0xffeeddccbbaa99887766554433221100".
5790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // An example with bytes=4 and lsb=8:
5800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# v{code}:         0xbbaa9988                ".
5810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "# %s%5s: %s",
5820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          clr_vreg_name, VRegNameForCode(code), clr_vreg_value);
5830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int msb = lsb + bytes - 1;
5850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int byte = kQRegSizeInBytes - 1;
5860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print leading padding spaces. (Two spaces per byte.)
5880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  while (byte > msb) {
5890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    fprintf(stream_, "  ");
5900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    byte--;
5910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
5920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
5930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print the specified part of the value, byte by byte.
5940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  qreg_t rawbits = qreg(code);
5950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "0x");
5960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  while (byte >= lsb) {
5970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    fprintf(stream_, "%02x", rawbits.val[byte]);
5980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    byte--;
5990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
6000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print trailing padding spaces.
6020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  while (byte >= 0) {
6030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    fprintf(stream_, "  ");
6040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    byte--;
6050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
6060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "%s", clr_normal);
6070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
6080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Print each of the specified lanes of a register as a float or double value.
6110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
6120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// The `lane_count` and `lslane` arguments can be used to limit the lanes that
6130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// are printed. These arguments are intended for use in cases where register
6140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// hasn't actually been updated (such as in PrintVWrite).
6150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//
6160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// No newline is printed. This allows the caller to print more details (such as
6170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// a memory access annotation).
6180cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintVRegisterFPHelper(unsigned code,
6190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                       unsigned lane_size_in_bytes,
6200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                       int lane_count,
6210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                       int rightmost_lane) {
6220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((lane_size_in_bytes == kSRegSizeInBytes) ||
6230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              (lane_size_in_bytes == kDRegSizeInBytes));
6240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
6260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(msb <= kQRegSizeInBytes);
6270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
6290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // name is used:
6300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   " (s{code}: {value})"
6310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   " (d{code}: {value})"
6320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // For vector types, "..." is used to represent one or more omitted lanes.
6330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   " (..., {value}, {value}, ...)"
6340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((lane_count == 1) && (rightmost_lane == 0)) {
6350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    const char * name =
6360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        (lane_size_in_bytes == kSRegSizeInBytes) ? SRegNameForCode(code)
6370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                                 : DRegNameForCode(code);
6380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
6390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
6400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (msb < (kQRegSizeInBytes - 1)) {
6410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      fprintf(stream_, " (..., ");
6420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
6430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      fprintf(stream_, " (");
6440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
6450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
6460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print the list of values.
6480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  const char * separator = "";
6490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int leftmost_lane = rightmost_lane + lane_count - 1;
6500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
6510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    double value =
6520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        (lane_size_in_bytes == kSRegSizeInBytes) ? vreg(code).Get<float>(lane)
6530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                                 : vreg(code).Get<double>(lane);
6540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    fprintf(stream_, "%s%s%#g%s", separator, clr_vreg_value, value, clr_normal);
6550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    separator = ", ";
6560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
6570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (rightmost_lane > 0) {
6590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    fprintf(stream_, ", ...");
6600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
6610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, ")");
6620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
6630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6650cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
6660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  vregisters_[code].NotifyRegisterLogged();
6670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int lane_size_log2 = format & kPrintRegLaneSizeMask;
6690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int reg_size_log2;
6710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (format & kPrintRegAsQVector) {
6720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    reg_size_log2 = kQRegSizeInBytesLog2;
6730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (format & kPrintRegAsDVector) {
6740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    reg_size_log2 = kDRegSizeInBytesLog2;
6750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
6760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Scalar types.
6770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    reg_size_log2 = lane_size_log2;
6780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
6790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int lane_count = 1 << (reg_size_log2 - lane_size_log2);
6810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int lane_size = 1 << lane_size_log2;
6820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template for vector types:
6840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# v{code}: 0x{rawbits} (..., {value}, ...)".
6850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template for scalar types:
6860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# v{code}: 0x{rawbits} ({reg}:{value})".
6870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The values in parentheses after the bit representations are floating-point
6880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
6890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintVRegisterRawHelper(code);
6910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (format & kPrintRegAsFP) {
6920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    PrintVRegisterFPHelper(code, lane_size, lane_count);
6930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
6940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "\n");
6960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
6970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
6990cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintSystemRegister(SystemRegister id) {
7000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (id) {
7010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NZCV:
7020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
7030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              clr_flag_name, clr_flag_value,
7040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
7050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              clr_normal);
7060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
7070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FPCR: {
7080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      static const char * rmode[] = {
7090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        "0b00 (Round to Nearest)",
7100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        "0b01 (Round towards Plus Infinity)",
7110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        "0b10 (Round towards Minus Infinity)",
7120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        "0b11 (Round towards Zero)"
7130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      };
7140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_ASSERT(fpcr().RMode() < (sizeof(rmode) / sizeof(rmode[0])));
7150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      fprintf(stream_,
7160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
7170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              clr_flag_name, clr_flag_value,
7180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
7190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              clr_normal);
7200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
7210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
7220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
7230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNREACHABLE();
7240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
7250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
7260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7280cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintRead(uintptr_t address,
7290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                          unsigned reg_code,
7300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                          PrintRegisterFormat format) {
7310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  registers_[reg_code].NotifyRegisterLogged();
7320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  USE(format);
7340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template is "# {reg}: 0x{value} <- {address}".
7360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
7370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
7380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          clr_memory_address, address, clr_normal);
7390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
7400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7420cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintVRead(uintptr_t address,
7430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                           unsigned reg_code,
7440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                           PrintRegisterFormat format,
7450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                           unsigned lane) {
7460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  vregisters_[reg_code].NotifyRegisterLogged();
7470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template is "# v{code}: 0x{rawbits} <- address".
7490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintVRegisterRawHelper(reg_code);
7500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (format & kPrintRegAsFP) {
7510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    PrintVRegisterFPHelper(reg_code, GetPrintRegLaneSizeInBytes(format),
7520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                           GetPrintRegLaneCount(format), lane);
7530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
7540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
7550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          clr_memory_address, address, clr_normal);
7560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
7570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7590cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintWrite(uintptr_t address,
7600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                           unsigned reg_code,
7610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                           PrintRegisterFormat format) {
7620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
7630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
7650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // and readable, the value is aligned with the values in the register trace.
7660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister,
7670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                         GetPrintRegSizeInBytes(format));
7680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
7690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          clr_memory_address, address, clr_normal);
7700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
7710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7730cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintVWrite(uintptr_t address,
7740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            unsigned reg_code,
7750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            PrintRegisterFormat format,
7760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            unsigned lane) {
7770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The templates:
7780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# v{code}: 0x{rawbits} -> {address}"
7790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
7800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  //   "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
7810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Because this trace doesn't represent a change to the source register's
7820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // value, only the relevant part of the value is printed. To keep the trace
7830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // tidy and readable, the raw value is aligned with the other values in the
7840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // register trace.
7850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int lane_count = GetPrintRegLaneCount(format);
7860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int lane_size = GetPrintRegLaneSizeInBytes(format);
7870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int reg_size = GetPrintRegSizeInBytes(format);
7880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
7890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (format & kPrintRegAsFP) {
7900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
7910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
7920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
7930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          clr_memory_address, address, clr_normal);
7940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
7950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Visitors---------------------------------------------------------------------
7980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
7990cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitUnimplemented(const Instruction* instr) {
8000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
8010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         reinterpret_cast<const void*>(instr), instr->InstructionBits());
8020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_UNIMPLEMENTED();
8030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8060cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitUnallocated(const Instruction* instr) {
8070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
8080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         reinterpret_cast<const void*>(instr), instr->InstructionBits());
8090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_UNIMPLEMENTED();
8100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8130cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitPCRelAddressing(const Instruction* instr) {
8140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
8150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              (instr->Mask(PCRelAddressingMask) == ADRP));
8160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
8180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8210cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitUnconditionalBranch(const Instruction* instr) {
8220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(UnconditionalBranchMask)) {
8230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case BL:
8240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_lr(instr->NextInstruction());
8250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
8260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case B:
8270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_pc(instr->ImmPCOffsetTarget());
8280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
8290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
8300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
8310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8340cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitConditionalBranch(const Instruction* instr) {
8350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
8360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (ConditionPassed(instr->ConditionBranch())) {
8370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_pc(instr->ImmPCOffsetTarget());
8380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
8390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8420cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
8430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  const Instruction* target = Instruction::Cast(xreg(instr->Rn()));
8440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
8460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case BLR:
8470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_lr(instr->NextInstruction());
8480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
8490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case BR:
8500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case RET: set_pc(target); break;
8510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
8520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
8530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8560cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitTestBranch(const Instruction* instr) {
8570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
8580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                     instr->ImmTestBranchBit40();
8590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool bit_zero = ((xreg(instr->Rt()) >> bit_pos) & 1) == 0;
8600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool take_branch = false;
8610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(TestBranchMask)) {
8620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case TBZ: take_branch = bit_zero; break;
8630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case TBNZ: take_branch = !bit_zero; break;
8640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
8650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
8660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (take_branch) {
8670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_pc(instr->ImmPCOffsetTarget());
8680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
8690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8720cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitCompareBranch(const Instruction* instr) {
8730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rt = instr->Rt();
8740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool take_branch = false;
8750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(CompareBranchMask)) {
8760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CBZ_w: take_branch = (wreg(rt) == 0); break;
8770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CBZ_x: take_branch = (xreg(rt) == 0); break;
8780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CBNZ_w: take_branch = (wreg(rt) != 0); break;
8790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CBNZ_x: take_branch = (xreg(rt) != 0); break;
8800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
8810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
8820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (take_branch) {
8830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_pc(instr->ImmPCOffsetTarget());
8840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
8850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
8860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8880cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
8890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
8900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool set_flags = instr->FlagsUpdate();
8910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t new_val = 0;
8920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Instr operation = instr->Mask(AddSubOpMask);
8930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
8940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (operation) {
8950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ADD:
8960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ADDS: {
8970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      new_val = AddWithCarry(reg_size,
8980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             set_flags,
8990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             reg(reg_size, instr->Rn(), instr->RnMode()),
9000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             op2);
9010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
9020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
9030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SUB:
9040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SUBS: {
9050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      new_val = AddWithCarry(reg_size,
9060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             set_flags,
9070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             reg(reg_size, instr->Rn(), instr->RnMode()),
9080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             ~op2,
9090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             1);
9100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
9110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
9120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
9130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
9140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), new_val, LogRegWrites, instr->RdMode());
9160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
9170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9190cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitAddSubShifted(const Instruction* instr) {
9200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
9210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t op2 = ShiftOperand(reg_size,
9220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             reg(reg_size, instr->Rm()),
9230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             static_cast<Shift>(instr->ShiftDP()),
9240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             instr->ImmDPShift());
9250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AddSubHelper(instr, op2);
9260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
9270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9290cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitAddSubImmediate(const Instruction* instr) {
9300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
9310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AddSubHelper(instr, op2);
9320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
9330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9350cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitAddSubExtended(const Instruction* instr) {
9360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
9370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t op2 = ExtendValue(reg_size,
9380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            reg(reg_size, instr->Rm()),
9390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            static_cast<Extend>(instr->ExtendMode()),
9400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            instr->ImmExtendShift());
9410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AddSubHelper(instr, op2);
9420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
9430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9450cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitAddSubWithCarry(const Instruction* instr) {
9460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
9470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t op2 = reg(reg_size, instr->Rm());
9480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t new_val;
9490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
9510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    op2 = ~op2;
9520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
9530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  new_val = AddWithCarry(reg_size,
9550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                         instr->FlagsUpdate(),
9560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                         reg(reg_size, instr->Rn()),
9570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                         op2,
9580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                         C());
9590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), new_val);
9610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
9620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9640cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLogicalShifted(const Instruction* instr) {
9650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
9660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Shift shift_type = static_cast<Shift>(instr->ShiftDP());
9670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned shift_amount = instr->ImmDPShift();
9680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
9690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                             shift_amount);
9700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NOT) == NOT) {
9710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    op2 = ~op2;
9720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
9730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LogicalHelper(instr, op2);
9740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
9750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9770cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLogicalImmediate(const Instruction* instr) {
9780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LogicalHelper(instr, instr->ImmLogical());
9790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
9800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9820cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
9830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
9840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t op1 = reg(reg_size, instr->Rn());
9850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t result = 0;
9860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool update_flags = false;
9870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Switch on the logical operation, stripping out the NOT bit, as it has a
9890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // different meaning for logical immediate instructions.
9900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(LogicalOpMask & ~NOT)) {
9910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ANDS: update_flags = true; VIXL_FALLTHROUGH();
9920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case AND: result = op1 & op2; break;
9930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ORR: result = op1 | op2; break;
9940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case EOR: result = op1 ^ op2; break;
9950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
9960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
9970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
9980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
9990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (update_flags) {
10000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetN(CalcNFlag(result, reg_size));
10010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetZ(CalcZFlag(result));
10020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetC(0);
10030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetV(0);
10040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    LogSystemRegister(NZCV);
10050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
10060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), result, LogRegWrites, instr->RdMode());
10080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10110cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
10120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
10130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
10140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10170cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
10180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  ConditionalCompareHelper(instr, instr->ImmCondCmp());
10190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10220cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::ConditionalCompareHelper(const Instruction* instr,
10230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                         int64_t op2) {
10240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
10250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t op1 = reg(reg_size, instr->Rn());
10260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (ConditionPassed(instr->Condition())) {
10280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // If the condition passes, set the status flags to the result of comparing
10290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // the operands.
10300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (instr->Mask(ConditionalCompareMask) == CCMP) {
10310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      AddWithCarry(reg_size, true, op1, ~op2, 1);
10320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
10330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
10340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      AddWithCarry(reg_size, true, op1, op2, 0);
10350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
10360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
10370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // If the condition fails, set the status flags to the nzcv immediate.
10380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    nzcv().SetFlags(instr->Nzcv());
10390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    LogSystemRegister(NZCV);
10400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
10410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10440cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
10450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int offset = instr->ImmLSUnsigned() << instr->SizeLS();
10460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStoreHelper(instr, offset, Offset);
10470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10500cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
10510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStoreHelper(instr, instr->ImmLS(), Offset);
10520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10550cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
10560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
10570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10600cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
10610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
10620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10650cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
10660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Extend ext = static_cast<Extend>(instr->ExtendMode());
10670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
10680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
10690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
10710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                               shift_amount);
10720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStoreHelper(instr, offset, Offset);
10730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
10740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10770cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::LoadStoreHelper(const Instruction* instr,
10780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                int64_t offset,
10790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                AddrMode addrmode) {
10800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned srcdst = instr->Rt();
10810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uintptr_t address = AddressModeHelper(instr->Rn(), offset, addrmode);
10820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
10830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
10840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (op) {
10850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRB_w:
10860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(srcdst, Memory::Read<uint8_t>(address), NoRegLog); break;
10870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRH_w:
10880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(srcdst, Memory::Read<uint16_t>(address), NoRegLog); break;
10890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_w:
10900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(srcdst, Memory::Read<uint32_t>(address), NoRegLog); break;
10910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_x:
10920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(srcdst, Memory::Read<uint64_t>(address), NoRegLog); break;
10930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRSB_w:
10940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(srcdst, Memory::Read<int8_t>(address), NoRegLog); break;
10950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRSH_w:
10960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(srcdst, Memory::Read<int16_t>(address), NoRegLog); break;
10970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRSB_x:
10980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(srcdst, Memory::Read<int8_t>(address), NoRegLog); break;
10990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRSH_x:
11000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(srcdst, Memory::Read<int16_t>(address), NoRegLog); break;
11010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRSW_x:
11020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(srcdst, Memory::Read<int32_t>(address), NoRegLog); break;
11030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_b:
11040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_breg(srcdst, Memory::Read<uint8_t>(address), NoRegLog); break;
11050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_h:
11060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_hreg(srcdst, Memory::Read<uint16_t>(address), NoRegLog); break;
11070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_s:
11080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(srcdst, Memory::Read<float>(address), NoRegLog); break;
11090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_d:
11100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(srcdst, Memory::Read<double>(address), NoRegLog); break;
11110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_q:
11120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_qreg(srcdst, Memory::Read<qreg_t>(address), NoRegLog); break;
11130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STRB_w:  Memory::Write<uint8_t>(address, wreg(srcdst)); break;
11150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STRH_w:  Memory::Write<uint16_t>(address, wreg(srcdst)); break;
11160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STR_w:   Memory::Write<uint32_t>(address, wreg(srcdst)); break;
11170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STR_x:   Memory::Write<uint64_t>(address, xreg(srcdst)); break;
11180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STR_b:   Memory::Write<uint8_t>(address, breg(srcdst)); break;
11190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STR_h:   Memory::Write<uint16_t>(address, hreg(srcdst)); break;
11200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STR_s:   Memory::Write<float>(address, sreg(srcdst)); break;
11210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STR_d:   Memory::Write<double>(address, dreg(srcdst)); break;
11220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STR_q:   Memory::Write<qreg_t>(address, qreg(srcdst)); break;
11230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Ignore prfm hint instructions.
11250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case PRFM: break;
11260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
11280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
11290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11305ee436a3a51863de7b5dc9326cf02895248050c2armvixl  unsigned access_size = 1 << instr->SizeLS();
11310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->IsLoad()) {
11320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if ((op == LDR_s) || (op == LDR_d)) {
11330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
11340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
11350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
11360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
11370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
11380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
11390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
11400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if ((op == STR_s) || (op == STR_d)) {
11410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
11420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
11430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
11440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
11450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
11460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
11470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
11480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  local_monitor_.MaybeClear();
11500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
11510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11530cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
11540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStorePairHelper(instr, Offset);
11550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
11560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11580cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
11590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStorePairHelper(instr, PreIndex);
11600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
11610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11630cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
11640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStorePairHelper(instr, PostIndex);
11650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
11660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11680cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
11690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStorePairHelper(instr, Offset);
11700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
11710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11730cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::LoadStorePairHelper(const Instruction* instr,
11740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                    AddrMode addrmode) {
11750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rt = instr->Rt();
11760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rt2 = instr->Rt2();
11775ee436a3a51863de7b5dc9326cf02895248050c2armvixl  int element_size = 1 << instr->SizeLSPair();
11780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t offset = instr->ImmLSPair() * element_size;
11790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uintptr_t address = AddressModeHelper(instr->Rn(), offset, addrmode);
11800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uintptr_t address2 = address + element_size;
11810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStorePairOp op =
11830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
11840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // 'rt' and 'rt2' can only be aliased for stores.
11860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
11870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
11880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (op) {
11890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
11900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // will print a more detailed log.
11910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDP_w: {
11920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
11930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
11940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
11950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
11960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDP_s: {
11970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(rt, Memory::Read<float>(address), NoRegLog);
11980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(rt2, Memory::Read<float>(address2), NoRegLog);
11990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDP_x: {
12020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
12030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
12040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDP_d: {
12070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(rt, Memory::Read<double>(address), NoRegLog);
12080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(rt2, Memory::Read<double>(address2), NoRegLog);
12090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDP_q: {
12120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_qreg(rt, Memory::Read<qreg_t>(address), NoRegLog);
12130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_qreg(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
12140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDPSW_x: {
12170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(rt, Memory::Read<int32_t>(address), NoRegLog);
12180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(rt2, Memory::Read<int32_t>(address2), NoRegLog);
12190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STP_w: {
12220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<uint32_t>(address, wreg(rt));
12230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<uint32_t>(address2, wreg(rt2));
12240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STP_s: {
12270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<float>(address, sreg(rt));
12280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<float>(address2, sreg(rt2));
12290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STP_x: {
12320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<uint64_t>(address, xreg(rt));
12330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<uint64_t>(address2, xreg(rt2));
12340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STP_d: {
12370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<double>(address, dreg(rt));
12380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<double>(address2, dreg(rt2));
12390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case STP_q: {
12420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<qreg_t>(address, qreg(rt));
12430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Memory::Write<qreg_t>(address2, qreg(rt2));
12440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
12450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
12470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
12480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print a detailed trace (including the memory address) instead of the basic
12500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // register:value trace generated by set_*reg().
12510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->IsLoad()) {
12520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if ((op == LDP_s) || (op == LDP_d)) {
12530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
12540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
12550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else if (op == LDP_q) {
12560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
12570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
12580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
12590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
12600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
12610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
12630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if ((op == STP_s) || (op == STP_d)) {
12640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
12650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
12660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else if (op == STP_q) {
12670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
12680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
12690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
12700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
12710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
12720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
12730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
12740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  local_monitor_.MaybeClear();
12760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
12770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12790cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::PrintExclusiveAccessWarning() {
12800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (print_exclusive_access_warning_) {
12810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    fprintf(
12820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        stderr,
12830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        "%sWARNING:%s VIXL simulator support for load-/store-/clear-exclusive "
12840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        "instructions is limited. Refer to the README for details.%s\n",
12850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        clr_warning, clr_warning_message, clr_normal);
12860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    print_exclusive_access_warning_ = false;
12870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
12880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
12890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12910cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
12920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintExclusiveAccessWarning();
12930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rs = instr->Rs();
12950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rt = instr->Rt();
12960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rt2 = instr->Rt2();
12970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rn = instr->Rn();
12980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
12990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  LoadStoreExclusive op =
13000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
13010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool is_acquire_release = instr->LdStXAcquireRelease();
13030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool is_exclusive = !instr->LdStXNotExclusive();
13040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool is_load = instr->LdStXLoad();
13050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool is_pair = instr->LdStXPair();
13060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13075ee436a3a51863de7b5dc9326cf02895248050c2armvixl  unsigned element_size = 1 << instr->LdStXSizeLog2();
13085ee436a3a51863de7b5dc9326cf02895248050c2armvixl  unsigned access_size = is_pair ? element_size * 2 : element_size;
13090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t address = reg<uint64_t>(rn, Reg31IsStackPointer);
13100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Verify that the address is available to the host.
13120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(address == static_cast<uintptr_t>(address));
13130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Check the alignment of `address`.
13150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (AlignDown(address, access_size) != address) {
13160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_ALIGNMENT_EXCEPTION();
13170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
13180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The sp must be aligned to 16 bytes when it is accessed.
13200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((rn == 31) && (AlignDown(address, 16) != address)) {
13210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_ALIGNMENT_EXCEPTION();
13220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
13230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (is_load) {
13250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (is_exclusive) {
13260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      local_monitor_.MarkExclusive(address, access_size);
13270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
13280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // Any non-exclusive load can clear the local monitor as a side effect. We
13290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // don't need to do this, but it is useful to stress the simulated code.
13300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      local_monitor_.Clear();
13310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
13320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
13340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // will print a more detailed log.
13350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (op) {
13360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDXRB_w:
13370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAXRB_w:
13380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDARB_w:
13390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_wreg(rt, Memory::Read<uint8_t>(address), NoRegLog);
13400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
13410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDXRH_w:
13420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAXRH_w:
13430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDARH_w:
13440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_wreg(rt, Memory::Read<uint16_t>(address), NoRegLog);
13450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
13460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDXR_w:
13470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAXR_w:
13480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAR_w:
13490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
13500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
13510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDXR_x:
13520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAXR_x:
13530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAR_x:
13540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
13550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
13560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDXP_w:
13570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAXP_w:
13580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
13590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_wreg(rt2, Memory::Read<uint32_t>(address + element_size), NoRegLog);
13600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
13610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDXP_x:
13620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case LDAXP_x:
13630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
13640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        set_xreg(rt2, Memory::Read<uint64_t>(address + element_size), NoRegLog);
13650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
13660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
13670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNREACHABLE();
13680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
13690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (is_acquire_release) {
13710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // Approximate load-acquire by issuing a full barrier after the load.
13720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      __sync_synchronize();
13730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
13740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
13760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (is_pair) {
13770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogRead(address + element_size, rt2,
13780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              GetPrintRegisterFormatForSize(element_size));
13790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
13800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
13810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (is_acquire_release) {
13820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // Approximate store-release by issuing a full barrier before the store.
13830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      __sync_synchronize();
13840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
13850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    bool do_store = true;
13870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (is_exclusive) {
13880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      do_store = local_monitor_.IsExclusive(address, access_size) &&
13890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                 global_monitor_.IsExclusive(address, access_size);
13900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(rs, do_store ? 0 : 1);
13910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      //  - All exclusive stores explicitly clear the local monitor.
13930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      local_monitor_.Clear();
13940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
13950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      //  - Any other store can clear the local monitor as a side effect.
13960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      local_monitor_.MaybeClear();
13970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
13980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
13990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (do_store) {
14000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      switch (op) {
14010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STXRB_w:
14020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLXRB_w:
14030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLRB_w:
14040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint8_t>(address, wreg(rt));
14050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          break;
14060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STXRH_w:
14070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLXRH_w:
14080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLRH_w:
14090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint16_t>(address, wreg(rt));
14100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          break;
14110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STXR_w:
14120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLXR_w:
14130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLR_w:
14140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint32_t>(address, wreg(rt));
14150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          break;
14160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STXR_x:
14170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLXR_x:
14180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLR_x:
14190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint64_t>(address, xreg(rt));
14200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          break;
14210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STXP_w:
14220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLXP_w:
14230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint32_t>(address, wreg(rt));
14240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint32_t>(address + element_size, wreg(rt2));
14250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          break;
14260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STXP_x:
14270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case STLXP_x:
14280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint64_t>(address, xreg(rt));
14290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          Memory::Write<uint64_t>(address + element_size, xreg(rt2));
14300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          break;
14310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        default:
14320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VIXL_UNREACHABLE();
14330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
14340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
14360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (is_pair) {
14370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogWrite(address + element_size, rt2,
14380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                 GetPrintRegisterFormatForSize(element_size));
14390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
14400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
14410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
14420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
14430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14450cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitLoadLiteral(const Instruction* instr) {
14460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned rt = instr->Rt();
14470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t address = instr->LiteralAddress<uint64_t>();
14480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Verify that the calculated address is available to the host.
14500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(address == static_cast<uintptr_t>(address));
14510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(LoadLiteralMask)) {
14530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
14540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // print a more detailed log.
14550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_w_lit:
14560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
14570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogRead(address, rt, kPrintWReg);
14580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
14590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_x_lit:
14600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
14610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogRead(address, rt, kPrintXReg);
14620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
14630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_s_lit:
14640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(rt, Memory::Read<float>(address), NoRegLog);
14650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address, rt, kPrintSReg);
14660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
14670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_d_lit:
14680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(rt, Memory::Read<double>(address), NoRegLog);
14690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address, rt, kPrintDReg);
14700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
14710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDR_q_lit:
14720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_qreg(rt, Memory::Read<qreg_t>(address), NoRegLog);
14730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(address, rt, kPrintReg1Q);
14740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
14750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LDRSW_x_lit:
14760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(rt, Memory::Read<int32_t>(address), NoRegLog);
14770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogRead(address, rt, kPrintWReg);
14780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
14790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Ignore prfm hint instructions.
14810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case PRFM_lit: break;
14820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
14840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
14850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  local_monitor_.MaybeClear();
14870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
14880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14900cc8b6ece4b3e757e11a906a81ece292437713abarmvixluintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
14910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                       int64_t offset,
14920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                       AddrMode addrmode) {
14930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
14940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
14950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((addr_reg == 31) && ((address % 16) != 0)) {
14960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // When the base register is SP the stack pointer is required to be
14970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // quadword aligned prior to the address calculation and write-backs.
14980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Misalignment will cause a stack alignment fault.
14990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_ALIGNMENT_EXCEPTION();
15000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
15010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
15030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_ASSERT(offset != 0);
15040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Only preindex should log the register update here. For Postindex, the
15050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // update will be printed automatically by LogWrittenRegisters _after_ the
15060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // memory access itself is logged.
15070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
15080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_xreg(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
15090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
15100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if ((addrmode == Offset) || (addrmode == PreIndex)) {
15120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    address += offset;
15130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
15140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Verify that the calculated address is available to the host.
15160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(address == static_cast<uintptr_t>(address));
15170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return static_cast<uintptr_t>(address);
15190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
15200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15220cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitMoveWideImmediate(const Instruction* instr) {
15230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  MoveWideImmediateOp mov_op =
15240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
15250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t new_xn_val = 0;
15260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool is_64_bits = instr->SixtyFourBits() == 1;
15280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Shift is limited for W operations.
15290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
15300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Get the shifted immediate.
15320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t shift = instr->ShiftMoveWide() * 16;
15335ee436a3a51863de7b5dc9326cf02895248050c2armvixl  int64_t shifted_imm16 = static_cast<int64_t>(instr->ImmMoveWide()) << shift;
15340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Compute the new value.
15360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (mov_op) {
15370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MOVN_w:
15380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MOVN_x: {
15390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        new_xn_val = ~shifted_imm16;
15400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (!is_64_bits) new_xn_val &= kWRegMask;
15410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
15420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
15430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MOVK_w:
15440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MOVK_x: {
15450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        unsigned reg_code = instr->Rd();
15460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
15470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                         : wreg(reg_code);
15480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        new_xn_val =
15490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
15500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
15510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
15520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MOVZ_w:
15530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MOVZ_x: {
15540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        new_xn_val = shifted_imm16;
15550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
15560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
15570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
15580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNREACHABLE();
15590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
15600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Update the destination register.
15620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_xreg(instr->Rd(), new_xn_val);
15630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
15640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15660cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitConditionalSelect(const Instruction* instr) {
15670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t new_val = xreg(instr->Rn());
15680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
15700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    new_val = xreg(instr->Rm());
15710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(ConditionalSelectMask)) {
15720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSEL_w:
15730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSEL_x: break;
15740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSINC_w:
15750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSINC_x: new_val++; break;
15760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSINV_w:
15770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSINV_x: new_val = ~new_val; break;
15780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSNEG_w:
15790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CSNEG_x: new_val = -new_val; break;
15800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default: VIXL_UNIMPLEMENTED();
15810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
15820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
15830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
15840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), new_val);
15850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
15860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15880cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitDataProcessing1Source(const Instruction* instr) {
15890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned dst = instr->Rd();
15900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned src = instr->Rn();
15910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
15920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(DataProcessing1SourceMask)) {
15935ee436a3a51863de7b5dc9326cf02895248050c2armvixl    case RBIT_w: set_wreg(dst, ReverseBits(wreg(src))); break;
15945ee436a3a51863de7b5dc9326cf02895248050c2armvixl    case RBIT_x: set_xreg(dst, ReverseBits(xreg(src))); break;
15955ee436a3a51863de7b5dc9326cf02895248050c2armvixl    case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), 1)); break;
15965ee436a3a51863de7b5dc9326cf02895248050c2armvixl    case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), 1)); break;
15975ee436a3a51863de7b5dc9326cf02895248050c2armvixl    case REV_w: set_wreg(dst, ReverseBytes(wreg(src), 2)); break;
15985ee436a3a51863de7b5dc9326cf02895248050c2armvixl    case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), 2)); break;
15995ee436a3a51863de7b5dc9326cf02895248050c2armvixl    case REV_x: set_xreg(dst, ReverseBytes(xreg(src), 3)); break;
16000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src))); break;
16010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src))); break;
16020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CLS_w: {
16030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, CountLeadingSignBits(wreg(src)));
16040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
16050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
16060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CLS_x: {
16070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, CountLeadingSignBits(xreg(src)));
16080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
16090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
16100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
16110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
16120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
16130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16150cc8b6ece4b3e757e11a906a81ece292437713abarmvixluint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
16160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((n > 32) && (n <= 64));
16170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (unsigned i = (n - 1); i >= 32; i--) {
16180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (((data >> i) & 1) != 0) {
16190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint64_t polysh32 = (uint64_t)poly << (i - 32);
16200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint64_t mask = (UINT64_C(1) << i) - 1;
16210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      data = ((data & mask) ^ polysh32);
16220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
16230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
16240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return data & 0xffffffff;
16250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
16260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16280cc8b6ece4b3e757e11a906a81ece292437713abarmvixltemplate <typename T>
16290cc8b6ece4b3e757e11a906a81ece292437713abarmvixluint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
16305ee436a3a51863de7b5dc9326cf02895248050c2armvixl  unsigned size = sizeof(val) * 8;  // Number of bits in type T.
16310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
16325ee436a3a51863de7b5dc9326cf02895248050c2armvixl  uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
16335ee436a3a51863de7b5dc9326cf02895248050c2armvixl  uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
16345ee436a3a51863de7b5dc9326cf02895248050c2armvixl  return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
16350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
16360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16380cc8b6ece4b3e757e11a906a81ece292437713abarmvixluint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
16390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
16400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // the CRC of each 32-bit word sequentially.
16410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
16420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
16430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
16440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16460cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitDataProcessing2Source(const Instruction* instr) {
16470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Shift shift_op = NO_SHIFT;
16480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t result = 0;
16490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
16500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
16510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(DataProcessing2SourceMask)) {
16520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SDIV_w: {
16530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int32_t rn = wreg(instr->Rn());
16540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int32_t rm = wreg(instr->Rm());
16550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if ((rn == kWMinInt) && (rm == -1)) {
16560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = kWMinInt;
16570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else if (rm == 0) {
16580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Division by zero can be trapped, but not on A-class processors.
16590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = 0;
16600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
16610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = rn / rm;
16620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
16630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
16640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
16650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SDIV_x: {
16660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int64_t rn = xreg(instr->Rn());
16670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int64_t rm = xreg(instr->Rm());
16680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if ((rn == kXMinInt) && (rm == -1)) {
16690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = kXMinInt;
16700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else if (rm == 0) {
16710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Division by zero can be trapped, but not on A-class processors.
16720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = 0;
16730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
16740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = rn / rm;
16750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
16760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
16770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
16780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UDIV_w: {
16790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
16800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
16810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (rm == 0) {
16820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Division by zero can be trapped, but not on A-class processors.
16830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = 0;
16840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
16850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = rn / rm;
16860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
16870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
16880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
16890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UDIV_x: {
16900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
16910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
16920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (rm == 0) {
16930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Division by zero can be trapped, but not on A-class processors.
16940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = 0;
16950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
16960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = rn / rm;
16970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
16980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
16990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LSLV_w:
17010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LSLV_x: shift_op = LSL; break;
17020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LSRV_w:
17030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case LSRV_x: shift_op = LSR; break;
17040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ASRV_w:
17050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case ASRV_x: shift_op = ASR; break;
17060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case RORV_w:
17070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case RORV_x: shift_op = ROR; break;
17080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32B: {
17090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint8_t  val = reg<uint8_t>(instr->Rm());
17110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32_POLY);
17120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32H: {
17150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint16_t val = reg<uint16_t>(instr->Rm());
17170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32_POLY);
17180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32W: {
17210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t val = reg<uint32_t>(instr->Rm());
17230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32_POLY);
17240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32X: {
17270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint64_t val = reg<uint64_t>(instr->Rm());
17290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32_POLY);
17300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      reg_size = kWRegSize;
17310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32CB: {
17340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint8_t  val = reg<uint8_t>(instr->Rm());
17360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32C_POLY);
17370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32CH: {
17400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint16_t val = reg<uint16_t>(instr->Rm());
17420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32C_POLY);
17430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32CW: {
17460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t val = reg<uint32_t>(instr->Rm());
17480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32C_POLY);
17490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CRC32CX: {
17520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t acc = reg<uint32_t>(instr->Rn());
17530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint64_t val = reg<uint64_t>(instr->Rm());
17540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = Crc32Checksum(acc, val, CRC32C_POLY);
17550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      reg_size = kWRegSize;
17560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
17570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
17580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
17590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
17600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (shift_op != NO_SHIFT) {
17620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Shift distance encoded in the least-significant five/six bits of the
17630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // register.
17640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int mask = (instr->SixtyFourBits() == 1) ? 0x3f : 0x1f;
17650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    unsigned shift = wreg(instr->Rm()) & mask;
17660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
17670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                          shift);
17680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
17690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), result);
17700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
17710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// The algorithm used is adapted from the one described in section 8.2 of
17740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl//   Hacker's Delight, by Henry S. Warren, Jr.
17750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// It assumes that a right shift on a signed integer is an arithmetic shift.
17760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl// Type T must be either uint64_t or int64_t.
17770cc8b6ece4b3e757e11a906a81ece292437713abarmvixltemplate <typename T>
17780cc8b6ece4b3e757e11a906a81ece292437713abarmvixlstatic T MultiplyHigh(T u, T v) {
17790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t u0, v0, w0;
17800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  T u1, v1, w1, w2, t;
17810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(sizeof(u) == sizeof(u0));
17830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  u0 = u & 0xffffffff;
17850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  u1 = u >> 32;
17860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  v0 = v & 0xffffffff;
17870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  v1 = v >> 32;
17880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  w0 = u0 * v0;
17900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  t = u1 * v0 + (w0 >> 32);
17910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  w1 = t & 0xffffffff;
17920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  w2 = t >> 32;
17930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  w1 = u0 * v1 + w1;
17940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return u1 * v1 + w2 + (w1 >> 32);
17960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
17970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
17990cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitDataProcessing3Source(const Instruction* instr) {
18000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
18010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t result = 0;
18030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Extract and sign- or zero-extend 32-bit arguments for widening operations.
18040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
18050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
18060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t rn_s32 = reg<int32_t>(instr->Rn());
18070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t rm_s32 = reg<int32_t>(instr->Rm());
18080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(DataProcessing3SourceMask)) {
18090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MADD_w:
18100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MADD_x:
18110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
18120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
18130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MSUB_w:
18140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case MSUB_x:
18150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
18160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
18170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
18180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
18190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
18200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
18210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UMULH_x:
18220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = MultiplyHigh(reg<uint64_t>(instr->Rn()),
18230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            reg<uint64_t>(instr->Rm()));
18240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
18250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SMULH_x:
18260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result = MultiplyHigh(xreg(instr->Rn()), xreg(instr->Rm()));
18270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
18280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
18290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
18300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), result);
18310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
18320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18340cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitBitfield(const Instruction* instr) {
18350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
18360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
18370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t R = instr->ImmR();
18380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t S = instr->ImmS();
18390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t diff = S - R;
18400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t mask;
18410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (diff >= 0) {
18420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    mask = (diff < (reg_size - 1)) ? (INT64_C(1) << (diff + 1)) - 1
18430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                   : reg_mask;
18440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
18450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    mask = (INT64_C(1) << (S + 1)) - 1;
18460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
18470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    diff += reg_size;
18480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
18490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // inzero indicates if the extracted bitfield is inserted into the
18510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // destination register value or in zero.
18520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // If extend is true, extend the sign of the extracted bitfield.
18530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool inzero = false;
18540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool extend = false;
18550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(BitfieldMask)) {
18560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case BFM_x:
18570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case BFM_w:
18580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
18590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SBFM_x:
18600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SBFM_w:
18610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      inzero = true;
18620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      extend = true;
18630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
18640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UBFM_x:
18650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UBFM_w:
18660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      inzero = true;
18670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
18680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
18690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
18700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
18710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
18730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t src = reg(reg_size, instr->Rn());
18740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Rotate source bitfield into place.
18750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
18760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Determine the sign extension.
18770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t topbits = ((INT64_C(1) << (reg_size - diff - 1)) - 1) << (diff + 1);
18780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
18790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Merge sign extension, dest/zero and bitfield.
18810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  result = signbits | (result & mask) | (dst & ~mask);
18820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), result);
18840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
18850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18870cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitExtract(const Instruction* instr) {
18880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned lsb = instr->ImmS();
18890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
18900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                                    : kWRegSize;
18910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t low_res = static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb;
18920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t high_res =
18930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      (lsb == 0) ? 0 : reg(reg_size, instr->Rn()) << (reg_size - lsb);
18940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_reg(reg_size, instr->Rd(), low_res | high_res);
18950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
18960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
18980cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPImmediate(const Instruction* instr) {
18990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
19000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
19010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned dest = instr->Rd();
19020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPImmediateMask)) {
19030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
19040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
19050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
19060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
19070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
19080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
19090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
19100cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPIntegerConvert(const Instruction* instr) {
19110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
19120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
19130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned dst = instr->Rd();
19140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned src = instr->Rn();
19150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
19160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  FPRounding round = RMode();
19170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
19180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPIntegerConvertMask)) {
19190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
19200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
19210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
19220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
19230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
19240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
19250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
19260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
19270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMS_ws:
19280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
19290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMS_xs:
19310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
19320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMS_wd:
19340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
19350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMS_xd:
19370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
19380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMU_ws:
19400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
19410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMU_xs:
19430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
19440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMU_wd:
19460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
19470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTMU_xd:
19490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
19500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPS_ws:
19520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToInt32(sreg(src), FPPositiveInfinity));
19530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPS_xs:
19550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToInt64(sreg(src), FPPositiveInfinity));
19560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPS_wd:
19580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToInt32(dreg(src), FPPositiveInfinity));
19590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPS_xd:
19610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToInt64(dreg(src), FPPositiveInfinity));
19620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPU_ws:
19640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToUInt32(sreg(src), FPPositiveInfinity));
19650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPU_xs:
19670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToUInt64(sreg(src), FPPositiveInfinity));
19680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPU_wd:
19700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToUInt32(dreg(src), FPPositiveInfinity));
19710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTPU_xd:
19730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToUInt64(dreg(src), FPPositiveInfinity));
19740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
19760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
19770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
19780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
19790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
19800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
19810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
19820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
19830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
19840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
19850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
19860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
19870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
19880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
19890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
19900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
19910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
19920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
19930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
19940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
19950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_d1_x:
19960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogicVRegister(vreg(dst)).SetUint(kFormatD, 1, xreg(src));
19970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
19980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_x_d1:
19990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, LogicVRegister(vreg(src)).Uint(kFormatD, 1));
20000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // A 32-bit input can be handled in the same way as a 64-bit input, since
20030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // the sign- or zero-extension will not affect the conversion.
20040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
20050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
20060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
20070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_dw: {
20080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(dst, UFixedToDouble(static_cast<uint32_t>(wreg(src)), 0, round));
20090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
20110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
20120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
20130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
20140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_sw: {
20150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(dst, UFixedToFloat(static_cast<uint32_t>(wreg(src)), 0, round));
20160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
20180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
20200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
20210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
20220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20240cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
20250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
20260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned dst = instr->Rd();
20280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned src = instr->Rn();
20290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int fbits = 64 - instr->FPScale();
20300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  FPRounding round = RMode();
20320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPFixedPointConvertMask)) {
20340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // A 32-bit input can be handled in the same way as a 64-bit input, since
20350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // the sign- or zero-extension will not affect the conversion.
20360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_dx_fixed:
20370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
20380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_dw_fixed:
20400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
20410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_dx_fixed:
20430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
20440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_dw_fixed: {
20460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(dst,
20470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl               UFixedToDouble(static_cast<uint32_t>(wreg(src)), fbits, round));
20480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
20500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_sx_fixed:
20510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
20520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case SCVTF_sw_fixed:
20540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
20550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_sx_fixed:
20570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
20580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case UCVTF_sw_fixed: {
20600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(dst,
20610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl               UFixedToFloat(static_cast<uint32_t>(wreg(src)), fbits, round));
20620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
20640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_xd_fixed:
20650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToInt64(dreg(src) * std::pow(2.0, fbits), FPZero));
20660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_wd_fixed:
20680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToInt32(dreg(src) * std::pow(2.0, fbits), FPZero));
20690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_xd_fixed:
20710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToUInt64(dreg(src) * std::pow(2.0, fbits), FPZero));
20720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_wd_fixed:
20740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToUInt32(dreg(src) * std::pow(2.0, fbits), FPZero));
20750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_xs_fixed:
20770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToInt64(sreg(src) * std::pow(2.0f, fbits), FPZero));
20780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZS_ws_fixed:
20800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToInt32(sreg(src) * std::pow(2.0f, fbits), FPZero));
20810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_xs_fixed:
20830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(dst, FPToUInt64(sreg(src) * std::pow(2.0f, fbits), FPZero));
20840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVTZU_ws_fixed:
20860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(dst, FPToUInt32(sreg(src) * std::pow(2.0f, fbits), FPZero));
20870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
20880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE();
20890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
20900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
20910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20930cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPCompare(const Instruction* instr) {
20940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
20950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
20960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  FPTrapFlags trap = DisableTrap;
20970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPCompareMask)) {
20980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMPE_s: trap = EnableTrap; VIXL_FALLTHROUGH();
20990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMP_s: FPCompare(sreg(instr->Rn()), sreg(instr->Rm()), trap); break;
21000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMPE_d: trap = EnableTrap; VIXL_FALLTHROUGH();
21010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMP_d: FPCompare(dreg(instr->Rn()), dreg(instr->Rm()), trap); break;
21020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMPE_s_zero: trap = EnableTrap; VIXL_FALLTHROUGH();
21030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMP_s_zero: FPCompare(sreg(instr->Rn()), 0.0f, trap); break;
21040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMPE_d_zero: trap = EnableTrap; VIXL_FALLTHROUGH();
21050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCMP_d_zero: FPCompare(dreg(instr->Rn()), 0.0, trap); break;
21060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
21070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
21080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
21090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21110cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPConditionalCompare(const Instruction* instr) {
21120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
21130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  FPTrapFlags trap = DisableTrap;
21150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPConditionalCompareMask)) {
21160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCCMPE_s: trap = EnableTrap;
21170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
21180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCCMP_s:
21190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (ConditionPassed(instr->Condition())) {
21200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        FPCompare(sreg(instr->Rn()), sreg(instr->Rm()), trap);
21210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
21220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        nzcv().SetFlags(instr->Nzcv());
21230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogSystemRegister(NZCV);
21240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
21250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
21260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCCMPE_d: trap = EnableTrap;
21270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
21280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCCMP_d:
21290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (ConditionPassed(instr->Condition())) {
21300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        FPCompare(dreg(instr->Rn()), dreg(instr->Rm()), trap);
21310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
21320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        nzcv().SetFlags(instr->Nzcv());
21330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogSystemRegister(NZCV);
21340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
21350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
21360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
21370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
21380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
21390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21410cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPConditionalSelect(const Instruction* instr) {
21420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
21430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Instr selected;
21450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (ConditionPassed(instr->Condition())) {
21460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    selected = instr->Rn();
21470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
21480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    selected = instr->Rm();
21490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
21500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPConditionalSelectMask)) {
21520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
21530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
21540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
21550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
21560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
21570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21590cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
21600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
21610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
21630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
21640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
21650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
21660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool inexact_exception = false;
21670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fd = instr->Rd();
21690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fn = instr->Rn();
21700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
21710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPDataProcessing1SourceMask)) {
21720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_s: set_sreg(fd, sreg(fn)); return;
21730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMOV_d: set_dreg(fd, dreg(fn)); return;
21740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FABS_s: fabs_(kFormatS, vreg(fd), vreg(fn)); return;
21750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FABS_d: fabs_(kFormatD, vreg(fd), vreg(fn)); return;
21760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNEG_s: fneg(kFormatS, vreg(fd), vreg(fn)); return;
21770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNEG_d: fneg(kFormatD, vreg(fd), vreg(fn)); return;
21780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); return;
21790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); return;
21800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVT_hs: set_hreg(fd, FPToFloat16(sreg(fn), FPTieEven)); return;
21810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVT_sh: set_sreg(fd, FPToFloat(hreg(fn))); return;
21820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVT_dh: set_dreg(fd, FPToDouble(FPToFloat(hreg(fn)))); return;
21830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FCVT_hd: set_hreg(fd, FPToFloat16(dreg(fn), FPTieEven)); return;
21840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FSQRT_s:
21850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FSQRT_d: fsqrt(vform, rd, rn); return;
21860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTI_s:
21870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTI_d: break;  // Use FPCR rounding mode.
21880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTX_s:
21890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTX_d: inexact_exception = true; break;
21900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTA_s:
21910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTA_d: fpcr_rounding = FPTieAway; break;
21920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTM_s:
21930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTM_d: fpcr_rounding = FPNegativeInfinity; break;
21940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTN_s:
21950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTN_d: fpcr_rounding = FPTieEven; break;
21960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTP_s:
21970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTP_d: fpcr_rounding = FPPositiveInfinity; break;
21980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTZ_s:
21990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FRINTZ_d: fpcr_rounding = FPZero; break;
22000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
22010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
22020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Only FRINT* instructions fall through the switch above.
22040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  frint(vform, rd, rn, fpcr_rounding, inexact_exception);
22050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
22060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22080cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
22090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
22100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
22120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
22130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
22140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
22150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPDataProcessing2SourceMask)) {
22170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FADD_s:
22180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FADD_d: fadd(vform, rd, rn, rm); break;
22190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FSUB_s:
22200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FSUB_d: fsub(vform, rd, rn, rm); break;
22210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMUL_s:
22220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMUL_d: fmul(vform, rd, rn, rm); break;
22230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNMUL_s:
22240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNMUL_d: fnmul(vform, rd, rn, rm); break;
22250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FDIV_s:
22260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FDIV_d: fdiv(vform, rd, rn, rm); break;
22270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMAX_s:
22280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMAX_d: fmax(vform, rd, rn, rm); break;
22290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMIN_s:
22300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMIN_d: fmin(vform, rd, rn, rm); break;
22310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMAXNM_s:
22320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMAXNM_d: fmaxnm(vform, rd, rn, rm); break;
22330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMINNM_s:
22340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMINNM_d: fminnm(vform, rd, rn, rm); break;
22350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
22360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNREACHABLE();
22370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
22380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
22390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22410cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
22420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  AssertSupportedFPCR();
22430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fd = instr->Rd();
22450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fn = instr->Rn();
22460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fm = instr->Rm();
22470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fa = instr->Ra();
22480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(FPDataProcessing3SourceMask)) {
22500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // fd = fa +/- (fn * fm)
22510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
22520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
22530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
22540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
22550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Negated variants of the above.
22560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNMADD_s:
22570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
22580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
22590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNMSUB_s:
22600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
22610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
22620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNMADD_d:
22630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
22640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
22650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case FNMSUB_d:
22660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
22670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
22680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
22690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
22700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
22710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22730cc8b6ece4b3e757e11a906a81ece292437713abarmvixlbool Simulator::FPProcessNaNs(const Instruction* instr) {
22740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fd = instr->Rd();
22750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fn = instr->Rn();
22760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  unsigned fm = instr->Rm();
22770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool done = false;
22780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(FP64) == FP64) {
22800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    double result = FPProcessNaNs(dreg(fn), dreg(fm));
22810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (std::isnan(result)) {
22820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_dreg(fd, result);
22830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      done = true;
22840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
22850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
22860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    float result = FPProcessNaNs(sreg(fn), sreg(fm));
22870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (std::isnan(result)) {
22880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_sreg(fd, result);
22890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      done = true;
22900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
22910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
22920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  return done;
22940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
22950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
22970cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::SysOp_W(int op, int64_t val) {
22980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (op) {
22990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case IVAU:
23000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CVAC:
23010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CVAU:
23020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case CIVAC: {
23030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // Perform a dummy memory access to ensure that we have read access
23040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // to the specified address.
23050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      volatile uint8_t y = Memory::Read<uint8_t>(val);
23060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      USE(y);
23070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // TODO: Implement "case ZVA:".
23080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
23090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
23100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
23110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
23120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
23130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
23140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
23150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
23160cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitSystem(const Instruction* instr) {
23170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Some system instructions hijack their Op and Cp fields to represent a
23180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // range of immediates instead of indicating a different instruction. This
23190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // makes the decoding tricky.
23200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(SystemExclusiveMonitorFMask) == SystemExclusiveMonitorFixed) {
23210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
23220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(SystemExclusiveMonitorMask)) {
23230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case CLREX: {
23240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        PrintExclusiveAccessWarning();
23250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ClearLocalMonitor();
23260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
23270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
23280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
23290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
23300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(SystemSysRegMask)) {
23310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case MRS: {
23320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        switch (instr->ImmSystemRegister()) {
23330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
23340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
23350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          default: VIXL_UNIMPLEMENTED();
23360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
23370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
23380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
23390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case MSR: {
23400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        switch (instr->ImmSystemRegister()) {
23410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case NZCV:
23425ee436a3a51863de7b5dc9326cf02895248050c2armvixl            nzcv().SetRawValue(wreg(instr->Rt()));
23430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            LogSystemRegister(NZCV);
23440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            break;
23450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case FPCR:
23465ee436a3a51863de7b5dc9326cf02895248050c2armvixl            fpcr().SetRawValue(wreg(instr->Rt()));
23470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            LogSystemRegister(FPCR);
23480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            break;
23490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          default: VIXL_UNIMPLEMENTED();
23500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
23510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
23520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
23530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
23540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
23550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
23560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->ImmHint()) {
23570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NOP: break;
23580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default: VIXL_UNIMPLEMENTED();
23590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
23600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
23610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    __sync_synchronize();
23620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
23630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(SystemSysMask)) {
23640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case SYS: SysOp_W(instr->SysOp(), xreg(instr->Rt())); break;
23650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default: VIXL_UNIMPLEMENTED();
23660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
23670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
23680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_UNIMPLEMENTED();
23690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
23700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
23710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
23720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
23730cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitException(const Instruction* instr) {
23740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(ExceptionMask)) {
23750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case HLT:
23760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      switch (instr->ImmException()) {
23770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case kUnreachableOpcode:
23780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          DoUnreachable(instr);
23790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          return;
23800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case kTraceOpcode:
23810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          DoTrace(instr);
23820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          return;
23830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case kLogOpcode:
23840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          DoLog(instr);
23850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          return;
23860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case kPrintfOpcode:
23870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          DoPrintf(instr);
23880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          return;
23890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        default:
23900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          HostBreakpoint();
23910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          return;
23920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
23930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case BRK:
23940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      HostBreakpoint();
23950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      return;
23960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
23970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
23980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
23990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
24000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24020cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
24030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VisitUnimplemented(instr);
24040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
24050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24070cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
24080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VisitUnimplemented(instr);
24090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
24100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24120cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitCryptoAES(const Instruction* instr) {
24130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VisitUnimplemented(instr);
24140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
24150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24170cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEON2RegMisc(const Instruction* instr) {
24180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr);
24190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
24200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  static const NEONFormatMap map_lp = {
24220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}
24230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  };
24240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
24250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  static const NEONFormatMap map_fcvtl = {
24270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {22}, {NF_4S, NF_2D}
24280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  };
24290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
24300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  static const NEONFormatMap map_fcvtn = {
24320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S}
24330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  };
24340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
24350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
24370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
24380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
24400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // These instructions all use a two bit size field, except NOT and RBIT,
24410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // which use the field to encode the operation.
24420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEON2RegMiscMask)) {
24430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_REV64:     rev64(vf, rd, rn); break;
24440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_REV32:     rev32(vf, rd, rn); break;
24450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_REV16:     rev16(vf, rd, rn); break;
24460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SUQADD:    suqadd(vf, rd, rn); break;
24470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_USQADD:    usqadd(vf, rd, rn); break;
24480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CLS:       cls(vf, rd, rn); break;
24490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CLZ:       clz(vf, rd, rn); break;
24500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CNT:       cnt(vf, rd, rn); break;
24510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQABS:     abs(vf, rd, rn).SignedSaturate(vf); break;
24520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQNEG:     neg(vf, rd, rn).SignedSaturate(vf); break;
24530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGT_zero: cmp(vf, rd, rn, 0, gt); break;
24540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGE_zero: cmp(vf, rd, rn, 0, ge); break;
24550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMEQ_zero: cmp(vf, rd, rn, 0, eq); break;
24560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMLE_zero: cmp(vf, rd, rn, 0, le); break;
24570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMLT_zero: cmp(vf, rd, rn, 0, lt); break;
24580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ABS:       abs(vf, rd, rn); break;
24590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_NEG:       neg(vf, rd, rn); break;
24600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SADDLP:    saddlp(vf_lp, rd, rn); break;
24610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UADDLP:    uaddlp(vf_lp, rd, rn); break;
24620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SADALP:    sadalp(vf_lp, rd, rn); break;
24630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UADALP:    uadalp(vf_lp, rd, rn); break;
24640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_RBIT_NOT:
24650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
24660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        switch (instr->FPType()) {
24670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case 0: not_(vf, rd, rn); break;
24680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case 1: rbit(vf, rd, rn);; break;
24690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          default:
24700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VIXL_UNIMPLEMENTED();
24710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
24720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
24730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
24740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
24750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
24760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
24770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    bool inexact_exception = false;
24780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
24790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // These instructions all use a one bit size field, except XTN, SQXTUN,
24800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // SHLL, SQXTN and UQXTN, which use a two bit size field.
24810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEON2RegMiscFPMask)) {
24820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FABS:   fabs_(fpf, rd, rn); return;
24830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FNEG:   fneg(fpf, rd, rn); return;
24840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FSQRT:  fsqrt(fpf, rd, rn); return;
24850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTL:
24860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Mask(NEON_Q)) {
24870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          fcvtl2(vf_fcvtl, rd, rn);
24880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
24890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          fcvtl(vf_fcvtl, rd, rn);
24900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
24910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        return;
24920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTN:
24930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Mask(NEON_Q)) {
24940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          fcvtn2(vf_fcvtn, rd, rn);
24950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
24960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          fcvtn(vf_fcvtn, rd, rn);
24970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
24980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        return;
24990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTXN:
25000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (instr->Mask(NEON_Q)) {
25010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          fcvtxn2(vf_fcvtn, rd, rn);
25020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
25030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          fcvtxn(vf_fcvtn, rd, rn);
25040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
25050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        return;
25060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
25070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // The following instructions break from the switch statement, rather
25080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      // than return.
25090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRINTI:     break;  // Use FPCR rounding mode.
25100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRINTX:     inexact_exception = true; break;
25110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRINTA:     fpcr_rounding = FPTieAway; break;
25120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRINTM:     fpcr_rounding = FPNegativeInfinity; break;
25130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRINTN:     fpcr_rounding = FPTieEven; break;
25140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRINTP:     fpcr_rounding = FPPositiveInfinity; break;
25150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRINTZ:     fpcr_rounding = FPZero; break;
25160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
25170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTNS:     fcvts(fpf, rd, rn, FPTieEven); return;
25180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTNU:     fcvtu(fpf, rd, rn, FPTieEven); return;
25190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTPS:     fcvts(fpf, rd, rn, FPPositiveInfinity); return;
25200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTPU:     fcvtu(fpf, rd, rn, FPPositiveInfinity); return;
25210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTMS:     fcvts(fpf, rd, rn, FPNegativeInfinity); return;
25220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTMU:     fcvtu(fpf, rd, rn, FPNegativeInfinity); return;
25230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTZS:     fcvts(fpf, rd, rn, FPZero); return;
25240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTZU:     fcvtu(fpf, rd, rn, FPZero); return;
25250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTAS:     fcvts(fpf, rd, rn, FPTieAway); return;
25260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTAU:     fcvtu(fpf, rd, rn, FPTieAway); return;
25270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SCVTF:      scvtf(fpf, rd, rn, 0, fpcr_rounding); return;
25280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UCVTF:      ucvtf(fpf, rd, rn, 0, fpcr_rounding); return;
25290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_URSQRTE:    ursqrte(fpf, rd, rn); return;
25300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_URECPE:     urecpe(fpf, rd, rn); return;
25310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRSQRTE:    frsqrte(fpf, rd, rn); return;
25320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRECPE:     frecpe(fpf, rd, rn, fpcr_rounding); return;
25330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGT_zero: fcmp_zero(fpf, rd, rn, gt); return;
25340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGE_zero: fcmp_zero(fpf, rd, rn, ge); return;
25350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMEQ_zero: fcmp_zero(fpf, rd, rn, eq); return;
25360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMLE_zero: fcmp_zero(fpf, rd, rn, le); return;
25370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMLT_zero: fcmp_zero(fpf, rd, rn, lt); return;
25380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
25390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
25400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
25410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          switch (instr->Mask(NEON2RegMiscMask)) {
25420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            case NEON_XTN: xtn(vf, rd, rn); return;
25430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            case NEON_SQXTN: sqxtn(vf, rd, rn); return;
25440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            case NEON_UQXTN: uqxtn(vf, rd, rn); return;
25450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            case NEON_SQXTUN: sqxtun(vf, rd, rn); return;
25460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            case NEON_SHLL:
25470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
25480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              if (instr->Mask(NEON_Q)) {
25490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                shll2(vf, rd, rn);
25500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              } else {
25510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                shll(vf, rd, rn);
25520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              }
25530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              return;
25540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            default:
25550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              VIXL_UNIMPLEMENTED();
25560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
25570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
25580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VIXL_UNIMPLEMENTED();
25590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
25600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
25610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
25620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // Only FRINT* instructions fall through the switch above.
25630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
25640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
25650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
25660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
25670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
25680cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEON3Same(const Instruction* instr) {
25690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr);
25700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
25710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
25720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
25730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
25740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
25750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
25760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEON3SameLogicalMask)) {
25770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_AND: and_(vf, rd, rn, rm); break;
25780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ORR: orr(vf, rd, rn, rm); break;
25790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ORN: orn(vf, rd, rn, rm); break;
25800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_EOR: eor(vf, rd, rn, rm); break;
25810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_BIC: bic(vf, rd, rn, rm); break;
25820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_BIF: bif(vf, rd, rn, rm); break;
25830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_BIT: bit(vf, rd, rn, rm); break;
25840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_BSL: bsl(vf, rd, rn, rm); break;
25850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
25860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNIMPLEMENTED();
25870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
25880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
25890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
25900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEON3SameFPMask)) {
25910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FADD:    fadd(vf, rd, rn, rm); break;
25920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FSUB:    fsub(vf, rd, rn, rm); break;
25930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMUL:    fmul(vf, rd, rn, rm); break;
25940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FDIV:    fdiv(vf, rd, rn, rm); break;
25950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMAX:    fmax(vf, rd, rn, rm); break;
25960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMIN:    fmin(vf, rd, rn, rm); break;
25970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMAXNM:  fmaxnm(vf, rd, rn, rm); break;
25980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMINNM:  fminnm(vf, rd, rn, rm); break;
25990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMLA:    fmla(vf, rd, rn, rm); break;
26000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMLS:    fmls(vf, rd, rn, rm); break;
26010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMULX:   fmulx(vf, rd, rn, rm); break;
26020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FACGE:   fabscmp(vf, rd, rn, rm, ge); break;
26030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FACGT:   fabscmp(vf, rd, rn, rm, gt); break;
26040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMEQ:   fcmp(vf, rd, rn, rm, eq); break;
26050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGE:   fcmp(vf, rd, rn, rm, ge); break;
26060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGT:   fcmp(vf, rd, rn, rm, gt); break;
26070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRECPS:  frecps(vf, rd, rn, rm); break;
26080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRSQRTS: frsqrts(vf, rd, rn, rm); break;
26090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FABD:    fabd(vf, rd, rn, rm); break;
26100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FADDP:   faddp(vf, rd, rn, rm); break;
26110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMAXP:   fmaxp(vf, rd, rn, rm); break;
26120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMAXNMP: fmaxnmp(vf, rd, rn, rm); break;
26130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMINP:   fminp(vf, rd, rn, rm); break;
26140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMINNMP: fminnmp(vf, rd, rn, rm); break;
26150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
26160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNIMPLEMENTED();
26170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
26180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
26190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat vf = nfd.GetVectorFormat();
26200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEON3SameMask)) {
26210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ADD:   add(vf, rd, rn, rm);  break;
26220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ADDP:  addp(vf, rd, rn, rm); break;
26230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMEQ:  cmp(vf, rd, rn, rm, eq); break;
26240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGE:  cmp(vf, rd, rn, rm, ge); break;
26250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGT:  cmp(vf, rd, rn, rm, gt); break;
26260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMHI:  cmp(vf, rd, rn, rm, hi); break;
26270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMHS:  cmp(vf, rd, rn, rm, hs); break;
26280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMTST: cmptst(vf, rd, rn, rm); break;
26290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_MLS:   mls(vf, rd, rn, rm); break;
26300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_MLA:   mla(vf, rd, rn, rm); break;
26310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_MUL:   mul(vf, rd, rn, rm); break;
26320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_PMUL:  pmul(vf, rd, rn, rm); break;
26330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SMAX:  smax(vf, rd, rn, rm); break;
26340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SMAXP: smaxp(vf, rd, rn, rm); break;
26350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SMIN:  smin(vf, rd, rn, rm); break;
26360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SMINP: sminp(vf, rd, rn, rm); break;
26370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SUB:   sub(vf, rd, rn, rm);  break;
26380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UMAX:  umax(vf, rd, rn, rm); break;
26390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UMAXP: umaxp(vf, rd, rn, rm); break;
26400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UMIN:  umin(vf, rd, rn, rm); break;
26410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UMINP: uminp(vf, rd, rn, rm); break;
26420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SSHL:  sshl(vf, rd, rn, rm); break;
26430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_USHL:  ushl(vf, rd, rn, rm); break;
26440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SABD:  absdiff(vf, rd, rn, rm, true); break;
26450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UABD:  absdiff(vf, rd, rn, rm, false); break;
26460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SABA:  saba(vf, rd, rn, rm); break;
26470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UABA:  uaba(vf, rd, rn, rm); break;
26480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQADD: add(vf, rd, rn, rm).UnsignedSaturate(vf); break;
26490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQADD: add(vf, rd, rn, rm).SignedSaturate(vf); break;
26500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQSUB: sub(vf, rd, rn, rm).UnsignedSaturate(vf); break;
26510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQSUB: sub(vf, rd, rn, rm).SignedSaturate(vf); break;
26520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQDMULH:  sqdmulh(vf, rd, rn, rm); break;
26530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQRDMULH: sqrdmulh(vf, rd, rn, rm); break;
26540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQSHL: ushl(vf, rd, rn, rm).UnsignedSaturate(vf); break;
26550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQSHL: sshl(vf, rd, rn, rm).SignedSaturate(vf); break;
26560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_URSHL: ushl(vf, rd, rn, rm).Round(vf); break;
26570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SRSHL: sshl(vf, rd, rn, rm).Round(vf); break;
26580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQRSHL:
26590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
26600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQRSHL:
26620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
26630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UHADD:
26650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        add(vf, rd, rn, rm).Uhalve(vf);
26660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_URHADD:
26680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
26690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SHADD:
26710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        add(vf, rd, rn, rm).Halve(vf);
26720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SRHADD:
26740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        add(vf, rd, rn, rm).Halve(vf).Round(vf);
26750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UHSUB:
26770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sub(vf, rd, rn, rm).Uhalve(vf);
26780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SHSUB:
26800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sub(vf, rd, rn, rm).Halve(vf);
26810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
26820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
26830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNIMPLEMENTED();
26840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
26850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
26860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
26870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
26880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
26890cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEON3Different(const Instruction* instr) {
26900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr);
26910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
26920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
26930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
26940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
26950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
26960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
26970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
26980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEON3DifferentMask)) {
26990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_PMULL:    pmull(vf_l, rd, rn, rm); break;
27000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_PMULL2:   pmull2(vf_l, rd, rn, rm); break;
27010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UADDL:    uaddl(vf_l, rd, rn, rm); break;
27020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UADDL2:   uaddl2(vf_l, rd, rn, rm); break;
27030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SADDL:    saddl(vf_l, rd, rn, rm); break;
27040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SADDL2:   saddl2(vf_l, rd, rn, rm); break;
27050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USUBL:    usubl(vf_l, rd, rn, rm); break;
27060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USUBL2:   usubl2(vf_l, rd, rn, rm); break;
27070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSUBL:    ssubl(vf_l, rd, rn, rm); break;
27080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSUBL2:   ssubl2(vf_l, rd, rn, rm); break;
27090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SABAL:    sabal(vf_l, rd, rn, rm); break;
27100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SABAL2:   sabal2(vf_l, rd, rn, rm); break;
27110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UABAL:    uabal(vf_l, rd, rn, rm); break;
27120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UABAL2:   uabal2(vf_l, rd, rn, rm); break;
27130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SABDL:    sabdl(vf_l, rd, rn, rm); break;
27140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SABDL2:   sabdl2(vf_l, rd, rn, rm); break;
27150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UABDL:    uabdl(vf_l, rd, rn, rm); break;
27160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UABDL2:   uabdl2(vf_l, rd, rn, rm); break;
27170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMLAL:    smlal(vf_l, rd, rn, rm); break;
27180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMLAL2:   smlal2(vf_l, rd, rn, rm); break;
27190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMLAL:    umlal(vf_l, rd, rn, rm); break;
27200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMLAL2:   umlal2(vf_l, rd, rn, rm); break;
27210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMLSL:    smlsl(vf_l, rd, rn, rm); break;
27220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMLSL2:   smlsl2(vf_l, rd, rn, rm); break;
27230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMLSL:    umlsl(vf_l, rd, rn, rm); break;
27240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMLSL2:   umlsl2(vf_l, rd, rn, rm); break;
27250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMULL:    smull(vf_l, rd, rn, rm); break;
27260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMULL2:   smull2(vf_l, rd, rn, rm); break;
27270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMULL:    umull(vf_l, rd, rn, rm); break;
27280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMULL2:   umull2(vf_l, rd, rn, rm); break;
27290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLAL:  sqdmlal(vf_l, rd, rn, rm); break;
27300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLAL2: sqdmlal2(vf_l, rd, rn, rm); break;
27310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLSL:  sqdmlsl(vf_l, rd, rn, rm); break;
27320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLSL2: sqdmlsl2(vf_l, rd, rn, rm); break;
27330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMULL:  sqdmull(vf_l, rd, rn, rm); break;
27340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMULL2: sqdmull2(vf_l, rd, rn, rm); break;
27350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UADDW:    uaddw(vf_l, rd, rn, rm); break;
27360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UADDW2:   uaddw2(vf_l, rd, rn, rm); break;
27370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SADDW:    saddw(vf_l, rd, rn, rm); break;
27380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SADDW2:   saddw2(vf_l, rd, rn, rm); break;
27390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USUBW:    usubw(vf_l, rd, rn, rm); break;
27400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USUBW2:   usubw2(vf_l, rd, rn, rm); break;
27410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSUBW:    ssubw(vf_l, rd, rn, rm); break;
27420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSUBW2:   ssubw2(vf_l, rd, rn, rm); break;
27430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ADDHN:    addhn(vf, rd, rn, rm); break;
27440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ADDHN2:   addhn2(vf, rd, rn, rm); break;
27450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_RADDHN:   raddhn(vf, rd, rn, rm); break;
27460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_RADDHN2:  raddhn2(vf, rd, rn, rm); break;
27470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SUBHN:    subhn(vf, rd, rn, rm); break;
27480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SUBHN2:   subhn2(vf, rd, rn, rm); break;
27490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_RSUBHN:   rsubhn(vf, rd, rn, rm); break;
27500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_RSUBHN2:  rsubhn2(vf, rd, rn, rm); break;
27510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
27520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
27530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
27540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
27550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27570cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
27580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr);
27590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
27610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
27620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The input operand's VectorFormat is passed for these instructions.
27640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
27650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
27660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEONAcrossLanesFPMask)) {
27680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMAXV: fmaxv(vf, rd, rn); break;
27690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMINV: fminv(vf, rd, rn); break;
27700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMAXNMV: fmaxnmv(vf, rd, rn); break;
27710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMINNMV: fminnmv(vf, rd, rn); break;
27720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
27730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNIMPLEMENTED();
27740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
27750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
27760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat vf = nfd.GetVectorFormat();
27770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEONAcrossLanesMask)) {
27790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ADDV:   addv(vf, rd, rn); break;
27800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SMAXV:  smaxv(vf, rd, rn); break;
27810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SMINV:  sminv(vf, rd, rn); break;
27820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UMAXV:  umaxv(vf, rd, rn); break;
27830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UMINV:  uminv(vf, rd, rn); break;
27840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SADDLV: saddlv(vf, rd, rn); break;
27850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UADDLV: uaddlv(vf, rd, rn); break;
27860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
27870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNIMPLEMENTED();
27880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
27890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
27900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
27910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27930cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
27940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr);
27950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_r = nfd.GetVectorFormat();
27960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
27970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
27980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
27990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
28000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
28010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  ByElementOp Op = NULL;
28020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
28030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int rm_reg = instr->Rm();
28040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int index = (instr->NEONH() << 1) | instr->NEONL();
28050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->NEONSize() == 1) {
28060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    rm_reg &= 0xf;
28070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    index = (index << 1) | instr->NEONM();
28080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
28090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
28100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONByIndexedElementMask)) {
28110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_MUL_byelement: Op = &Simulator::mul; vf = vf_r; break;
28120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_MLA_byelement: Op = &Simulator::mla; vf = vf_r; break;
28130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_MLS_byelement: Op = &Simulator::mls; vf = vf_r; break;
28140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMULH_byelement: Op = &Simulator::sqdmulh; vf = vf_r; break;
28150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQRDMULH_byelement: Op = &Simulator::sqrdmulh; vf = vf_r; break;
28160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMULL_byelement:
28170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::smull2;
28190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::smull;
28210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMULL_byelement:
28240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::umull2;
28260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::umull;
28280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMLAL_byelement:
28310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::smlal2;
28330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::smlal;
28350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMLAL_byelement:
28380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::umlal2;
28400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::umlal;
28420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SMLSL_byelement:
28450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::smlsl2;
28470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::smlsl;
28490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UMLSL_byelement:
28520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::umlsl2;
28540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::umlsl;
28560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMULL_byelement:
28590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::sqdmull2;
28610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::sqdmull;
28630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLAL_byelement:
28660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::sqdmlal2;
28680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::sqdmlal;
28700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLSL_byelement:
28730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
28740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::sqdmlsl2;
28750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
28760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        Op = &Simulator::sqdmlsl;
28770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
28790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
28800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      index = instr->NEONH();
28810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if ((instr->FPType() & 1) == 0) {
28820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        index = (index << 1) | instr->NEONL();
28830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
28850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = nfd.GetVectorFormat(nfd.FPFormatMap());
28860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
28870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      switch (instr->Mask(NEONByIndexedElementFPMask)) {
28880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMUL_byelement: Op = &Simulator::fmul; break;
28890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMLA_byelement: Op = &Simulator::fmla; break;
28900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMLS_byelement: Op = &Simulator::fmls; break;
28910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMULX_byelement: Op = &Simulator::fmulx; break;
28920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        default: VIXL_UNIMPLEMENTED();
28930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
28940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
28950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
28960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
28970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
28980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
28990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29000cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONCopy(const Instruction* instr) {
29010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
29020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
29030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
29050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
29060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int imm5 = instr->ImmNEON5();
29070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int tz = CountTrailingZeros(imm5, 32);
29080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int reg_index = imm5 >> (tz + 1);
29090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
29110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int imm4 = instr->ImmNEON4();
29120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int rn_index = imm4 >> tz;
29130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    ins_element(vf, rd, reg_index, rn, rn_index);
29140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
29150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    ins_immediate(vf, rd, reg_index, xreg(instr->Rn()));
29160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
29170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
29180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    value &= MaxUintFromFormat(vf);
29190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_xreg(instr->Rd(), value);
29200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
29210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int64_t value = LogicVRegister(rn).Int(vf, reg_index);
29220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (instr->NEONQ()) {
29230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_xreg(instr->Rd(), value);
29240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
29250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_wreg(instr->Rd(), (int32_t)value);
29260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
29270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
29280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    dup_element(vf, rd, rn, reg_index);
29290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
29300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    dup_immediate(vf, rd, xreg(instr->Rn()));
29310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
29320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_UNIMPLEMENTED();
29330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
29340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
29350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29370cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONExtract(const Instruction* instr) {
29380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
29390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
29400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
29410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
29420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
29430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEONExtractMask) == NEON_EXT) {
29440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int index = instr->ImmNEONExt();
29450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    ext(vf, rd, rn, rm, index);
29460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
29470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_UNIMPLEMENTED();
29480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
29490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
29500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29520cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
29530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                               AddrMode addr_mode) {
29540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
29550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
29560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t addr_base = xreg(instr->Rn(), Reg31IsStackPointer);
29585ee436a3a51863de7b5dc9326cf02895248050c2armvixl  int reg_size = RegisterSizeInBytesFromFormat(vf);
29590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int reg[4];
29610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t addr[4];
29620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (int i = 0; i < 4; i++) {
29630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    reg[i] = (instr->Rt() + i) % kNumberOfVRegisters;
29640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    addr[i] = addr_base + (i * reg_size);
29650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
29660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int count = 1;
29670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool log_read = true;
29680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Instr itype = instr->Mask(NEONLoadStoreMultiStructMask);
29700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (((itype == NEON_LD1_1v) || (itype == NEON_LD1_2v) ||
29710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl       (itype == NEON_LD1_3v) || (itype == NEON_LD1_4v) ||
29720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl       (itype == NEON_ST1_1v) || (itype == NEON_ST1_2v) ||
29730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl       (itype == NEON_ST1_3v) || (itype == NEON_ST1_4v)) &&
29740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      (instr->Bits(20, 16) != 0)) {
29750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_UNREACHABLE();
29760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
29770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
29780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // We use the PostIndex mask here, as it works in this case for both Offset
29790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // and PostIndex addressing.
29800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
29810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_4v:
29820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_4v_post: ld1(vf, vreg(reg[3]), addr[3]); count++;
29830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
29840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_3v:
29850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_3v_post: ld1(vf, vreg(reg[2]), addr[2]); count++;
29860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
29870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_2v:
29880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_2v_post: ld1(vf, vreg(reg[1]), addr[1]); count++;
29890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
29900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_1v:
29910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_1v_post:
29920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld1(vf, vreg(reg[0]), addr[0]);
29930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      log_read = true;
29940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
29950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_4v:
29960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_4v_post: st1(vf, vreg(reg[3]), addr[3]); count++;
29970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
29980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_3v:
29990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_3v_post: st1(vf, vreg(reg[2]), addr[2]); count++;
30000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
30010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_2v:
30020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_2v_post: st1(vf, vreg(reg[1]), addr[1]); count++;
30030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
30040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_1v:
30050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_1v_post:
30060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      st1(vf, vreg(reg[0]), addr[0]);
30070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      log_read = false;
30080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
30090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2_post:
30100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2:
30110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
30120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      count = 2;
30130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
30140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2:
30150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2_post:
30160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      st2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
30170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      count = 2;
30180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
30190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3_post:
30200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3:
30210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
30220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      count = 3;
30230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
30240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3:
30250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3_post:
30260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      st3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
30270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      count = 3;
30280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
30290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4:
30300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4_post:
30310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      st4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]),
30320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          addr[0]);
30330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      count = 4;
30340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
30350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4_post:
30360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4:
30370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]),
30380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          addr[0]);
30390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      count = 4;
30400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
30410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
30420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
30430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Explicitly log the register update whilst we have type information.
30450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (int i = 0; i < count; i++) {
30460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // For de-interleaving loads, only print the base address.
30470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int lane_size = LaneSizeInBytesFromFormat(vf);
30480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
30490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        GetPrintRegisterFormatForSize(reg_size, lane_size));
30500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (log_read) {
30510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVRead(addr_base, reg[i], format);
30520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
30530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      LogVWrite(addr_base, reg[i], format);
30540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
30550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
30560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (addr_mode == PostIndex) {
30580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int rm = instr->Rm();
30590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // The immediate post index addressing mode is indicated by rm = 31.
30600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // The immediate is implied by the number of vector registers used.
30610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
30620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                            : xreg(rm);
30630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_xreg(instr->Rn(), addr_base);
30640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
30650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_ASSERT(addr_mode == Offset);
30660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
30670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
30680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30700cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
30710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONLoadStoreMultiStructHelper(instr, Offset);
30720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
30730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30750cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONLoadStoreMultiStructPostIndex(
30760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    const Instruction* instr) {
30770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONLoadStoreMultiStructHelper(instr, PostIndex);
30780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
30790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30810cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
30820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl                                                AddrMode addr_mode) {
30830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t addr = xreg(instr->Rn(), Reg31IsStackPointer);
30840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int rt = instr->Rt();
30850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  Instr itype = instr->Mask(NEONLoadStoreSingleStructMask);
30870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (((itype == NEON_LD1_b) || (itype == NEON_LD1_h) ||
30880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl       (itype == NEON_LD1_s) || (itype == NEON_LD1_d)) &&
30890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      (instr->Bits(20, 16) != 0)) {
30900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_UNREACHABLE();
30910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
30920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // We use the PostIndex mask here, as it works in this case for both Offset
30940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // and PostIndex addressing.
30950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  bool do_load = false;
30960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
30970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
30980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_t = nfd.GetVectorFormat();
30990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
31000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = kFormat16B;
31010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
31020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_b:
31030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_b_post:
31040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2_b:
31050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2_b_post:
31060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3_b:
31070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3_b_post:
31080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4_b:
31090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4_b_post: do_load = true;
31100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
31110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_b:
31120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_b_post:
31130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2_b:
31140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2_b_post:
31150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3_b:
31160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3_b_post:
31170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4_b:
31180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4_b_post: break;
31190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
31200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_h:
31210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_h_post:
31220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2_h:
31230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2_h_post:
31240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3_h:
31250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3_h_post:
31260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4_h:
31270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4_h_post: do_load = true;
31280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
31290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_h:
31300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_h_post:
31310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2_h:
31320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2_h_post:
31330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3_h:
31340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3_h_post:
31350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4_h:
31360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4_h_post: vf = kFormat8H; break;
31370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_s:
31380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1_s_post:
31390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2_s:
31400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2_s_post:
31410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3_s:
31420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3_s_post:
31430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4_s:
31440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4_s_post: do_load = true;
31450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_FALLTHROUGH();
31460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_s:
31470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST1_s_post:
31480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2_s:
31490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST2_s_post:
31500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3_s:
31510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST3_s_post:
31520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4_s:
31530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ST4_s_post: {
31540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
31550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_STATIC_ASSERT(
31560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          (NEON_LD1_s_post | (1 << NEONLSSize_offset)) == NEON_LD1_d_post);
31570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
31580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_STATIC_ASSERT(
31590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          (NEON_ST1_s_post | (1 << NEONLSSize_offset)) == NEON_ST1_d_post);
31600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = ((instr->NEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
31610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
31620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
31630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
31640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1R:
31650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD1R_post: {
31660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_t;
31670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld1r(vf, vreg(rt), addr);
31680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      do_load = true;
31690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
31700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
31710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
31720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2R:
31730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD2R_post: {
31740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_t;
31750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int rt2 = (rt + 1) % kNumberOfVRegisters;
31760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld2r(vf, vreg(rt), vreg(rt2), addr);
31770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      do_load = true;
31780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
31790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
31800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
31810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3R:
31820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD3R_post: {
31830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_t;
31840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int rt2 = (rt + 1) % kNumberOfVRegisters;
31850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int rt3 = (rt2 + 1) % kNumberOfVRegisters;
31860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
31870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      do_load = true;
31880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
31890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
31900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
31910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4R:
31920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_LD4R_post: {
31930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_t;
31940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int rt2 = (rt + 1) % kNumberOfVRegisters;
31950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int rt3 = (rt2 + 1) % kNumberOfVRegisters;
31960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int rt4 = (rt3 + 1) % kNumberOfVRegisters;
31970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
31980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      do_load = true;
31990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
32000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
32010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
32020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
32030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  PrintRegisterFormat print_format =
32050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
32060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Make sure that the print_format only includes a single lane.
32070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  print_format =
32080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
32090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int esize = LaneSizeInBytesFromFormat(vf);
32110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int index_shift = LaneSizeInBytesLog2FromFormat(vf);
32120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int lane = instr->NEONLSIndex(index_shift);
32130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int scale = 0;
32140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int rt2 = (rt + 1) % kNumberOfVRegisters;
32150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int rt3 = (rt2 + 1) % kNumberOfVRegisters;
32160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int rt4 = (rt3 + 1) % kNumberOfVRegisters;
32170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
32180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEONLoadStoreSingle1:
32190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      scale = 1;
32200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (do_load) {
32210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ld1(vf, vreg(rt), lane, addr);
32220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr, rt, print_format, lane);
32230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
32240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        st1(vf, vreg(rt), lane, addr);
32250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr, rt, print_format, lane);
32260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
32270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
32280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEONLoadStoreSingle2:
32290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      scale = 2;
32300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (do_load) {
32310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ld2(vf, vreg(rt), vreg(rt2), lane, addr);
32320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr, rt, print_format, lane);
32330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr + esize, rt2, print_format, lane);
32340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
32350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        st2(vf, vreg(rt), vreg(rt2), lane, addr);
32360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr, rt, print_format, lane);
32370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr + esize, rt2, print_format, lane);
32380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
32390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
32400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEONLoadStoreSingle3:
32410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      scale = 3;
32420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (do_load) {
32430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
32440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr, rt, print_format, lane);
32450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr + esize, rt2, print_format, lane);
32460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr + (2 * esize), rt3, print_format, lane);
32470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
32480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
32490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr, rt, print_format, lane);
32500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr + esize, rt2, print_format, lane);
32510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr + (2 * esize), rt3, print_format, lane);
32520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
32530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
32540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEONLoadStoreSingle4:
32550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      scale = 4;
32560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (do_load) {
32570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
32580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr, rt, print_format, lane);
32590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr + esize, rt2, print_format, lane);
32600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr + (2 * esize), rt3, print_format, lane);
32610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVRead(addr + (3 * esize), rt4, print_format, lane);
32620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
32630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
32640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr, rt, print_format, lane);
32650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr + esize, rt2, print_format, lane);
32660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr + (2 * esize), rt3, print_format, lane);
32670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        LogVWrite(addr + (3 * esize), rt4, print_format, lane);
32680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
32690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
32700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNIMPLEMENTED();
32710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
32720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (addr_mode == PostIndex) {
32740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int rm = instr->Rm();
32750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int lane_size = LaneSizeInBytesFromFormat(vf);
32760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    set_xreg(instr->Rn(), addr + ((rm == 31) ? (scale * lane_size) : xreg(rm)));
32770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
32780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
32790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32810cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
32820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONLoadStoreSingleStructHelper(instr, Offset);
32830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
32840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32860cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONLoadStoreSingleStructPostIndex(
32870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    const Instruction* instr) {
32880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONLoadStoreSingleStructHelper(instr, PostIndex);
32890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
32900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
32920cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
32930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
32940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int cmode = instr->NEONCmode();
32950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int cmode_3_1 = (cmode >> 1) & 7;
32960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int cmode_3 = (cmode >> 3) & 1;
32970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int cmode_2 = (cmode >> 2) & 1;
32980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int cmode_1 = (cmode >> 1) & 1;
32990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int cmode_0 = cmode & 1;
33000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int q = instr->NEONQ();
33010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int op_bit = instr->NEONModImmOp();
33020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t imm8  = instr->ImmNEONabcdefgh();
33030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
33040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Find the format and immediate value
33050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint64_t imm = 0;
33060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vform = kFormatUndefined;
33070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (cmode_3_1) {
33080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x0:
33090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x1:
33100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x2:
33110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x3:
33120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vform = (q == 1) ? kFormat4S : kFormat2S;
33130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      imm = imm8 << (8 * cmode_3_1);
33140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
33150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x4:
33160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x5:
33170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vform = (q == 1) ? kFormat8H : kFormat4H;
33180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      imm = imm8 << (8 * cmode_1);
33190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
33200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x6:
33210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vform = (q == 1) ? kFormat4S : kFormat2S;
33220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (cmode_0 == 0) {
33230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        imm = imm8 << 8  | 0x000000ff;
33240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
33250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        imm = imm8 << 16 | 0x0000ffff;
33260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
33270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
33280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case 0x7:
33290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (cmode_0 == 0 && op_bit == 0) {
33300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        vform = q ? kFormat16B : kFormat8B;
33310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        imm = imm8;
33320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else if (cmode_0 == 0 && op_bit == 1) {
33330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        vform = q ? kFormat2D : kFormat1D;
33340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        imm = 0;
33350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        for (int i = 0; i < 8; ++i) {
33360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          if (imm8 & (1 << i)) {
33370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            imm |= (UINT64_C(0xff) << (8 * i));
33380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          }
33390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
33400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {  // cmode_0 == 1, cmode == 0xf.
33410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (op_bit == 0) {
33420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          vform = q ? kFormat4S : kFormat2S;
33430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          imm = float_to_rawbits(instr->ImmNEONFP32());
33440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else if (q == 1) {
33450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          vform = kFormat2D;
33460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          imm = double_to_rawbits(instr->ImmNEONFP64());
33470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        } else {
33480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
33490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          VisitUnallocated(instr);
33500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
33510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
33520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
33530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default: VIXL_UNREACHABLE(); break;
33540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
33550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
33560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Find the operation
33570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONModifiedImmediateOp op;
33580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (cmode_3 == 0) {
33590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (cmode_0 == 0) {
33600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
33610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {  // cmode<0> == '1'
33620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
33630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
33640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {  // cmode<3> == '1'
33650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (cmode_2 == 0) {
33660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (cmode_0 == 0) {
33670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
33680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {  // cmode<0> == '1'
33690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
33700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
33710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {  // cmode<2> == '1'
33720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl       if (cmode_1 == 0) {
33730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
33740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl       } else {  // cmode<1> == '1'
33750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         if (cmode_0 == 0) {
33760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl           op = NEONModifiedImmediate_MOVI;
33770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         } else {  // cmode<0> == '1'
33780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl           op = NEONModifiedImmediate_MOVI;
33790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         }
33800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl       }
33810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
33820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
33830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
33840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Call the logic function
33850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (op == NEONModifiedImmediate_ORR) {
33860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    orr(vform, rd, rd, imm);
33870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (op == NEONModifiedImmediate_BIC) {
33880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    bic(vform, rd, rd, imm);
33890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else  if (op == NEONModifiedImmediate_MOVI) {
33900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    movi(vform, rd, imm);
33910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else if (op == NEONModifiedImmediate_MVNI) {
33920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    mvni(vform, rd, imm);
33930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
33940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VisitUnimplemented(instr);
33950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
33960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
33970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
33980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
33990cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
34000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
34010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
34020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
34040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
34050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
34070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // These instructions all use a two bit size field, except NOT and RBIT,
34080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // which use the field to encode the operation.
34090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEONScalar2RegMiscMask)) {
34100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMEQ_zero_scalar: cmp(vf, rd, rn, 0, eq); break;
34110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGE_zero_scalar: cmp(vf, rd, rn, 0, ge); break;
34120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGT_zero_scalar: cmp(vf, rd, rn, 0, gt); break;
34130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMLT_zero_scalar: cmp(vf, rd, rn, 0, lt); break;
34140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMLE_zero_scalar: cmp(vf, rd, rn, 0, le); break;
34150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ABS_scalar:       abs(vf, rd, rn); break;
34160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQABS_scalar:     abs(vf, rd, rn).SignedSaturate(vf); break;
34170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_NEG_scalar:       neg(vf, rd, rn); break;
34180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQNEG_scalar:     neg(vf, rd, rn).SignedSaturate(vf); break;
34190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SUQADD_scalar:    suqadd(vf, rd, rn); break;
34200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_USQADD_scalar:    usqadd(vf, rd, rn); break;
34210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default: VIXL_UNIMPLEMENTED(); break;
34220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
34230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
34240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
34250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
34260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // These instructions all use a one bit size field, except SQXTUN, SQXTN
34280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    // and UQXTN, which use a two bit size field.
34290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
34300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRECPE_scalar:     frecpe(fpf, rd, rn, fpcr_rounding); break;
34310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRECPX_scalar:     frecpx(fpf, rd, rn); break;
34320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRSQRTE_scalar:    frsqrte(fpf, rd, rn); break;
34330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGT_zero_scalar: fcmp_zero(fpf, rd, rn, gt); break;
34340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGE_zero_scalar: fcmp_zero(fpf, rd, rn, ge); break;
34350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMEQ_zero_scalar: fcmp_zero(fpf, rd, rn, eq); break;
34360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMLE_zero_scalar: fcmp_zero(fpf, rd, rn, le); break;
34370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMLT_zero_scalar: fcmp_zero(fpf, rd, rn, lt); break;
34380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SCVTF_scalar:      scvtf(fpf, rd, rn, 0, fpcr_rounding); break;
34390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UCVTF_scalar:      ucvtf(fpf, rd, rn, 0, fpcr_rounding); break;
34400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTNS_scalar: fcvts(fpf, rd, rn, FPTieEven); break;
34410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTNU_scalar: fcvtu(fpf, rd, rn, FPTieEven); break;
34420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTPS_scalar: fcvts(fpf, rd, rn, FPPositiveInfinity); break;
34430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTPU_scalar: fcvtu(fpf, rd, rn, FPPositiveInfinity); break;
34440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTMS_scalar: fcvts(fpf, rd, rn, FPNegativeInfinity); break;
34450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTMU_scalar: fcvtu(fpf, rd, rn, FPNegativeInfinity); break;
34460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTZS_scalar: fcvts(fpf, rd, rn, FPZero); break;
34470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTZU_scalar: fcvtu(fpf, rd, rn, FPZero); break;
34480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTAS_scalar: fcvts(fpf, rd, rn, FPTieAway); break;
34490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTAU_scalar: fcvtu(fpf, rd, rn, FPTieAway); break;
34500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCVTXN_scalar:
34510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Unlike all of the other FP instructions above, fcvtxn encodes dest
34520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // size S as size<0>=1. There's only one case, so we ignore the form.
34530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_ASSERT(instr->Bit(22) == 1);
34540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        fcvtxn(kFormatS, rd, rn);
34550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
34560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
34570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        switch (instr->Mask(NEONScalar2RegMiscMask)) {
34580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case NEON_SQXTN_scalar:  sqxtn(vf, rd, rn); break;
34590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case NEON_UQXTN_scalar:  uqxtn(vf, rd, rn); break;
34600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          case NEON_SQXTUN_scalar: sqxtun(vf, rd, rn); break;
34610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          default:
34620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl            VIXL_UNIMPLEMENTED();
34630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        }
34640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
34650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
34660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
34670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34690cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
34700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
34710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
34720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
34740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
34750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
34760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONScalar3DiffMask)) {
34770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLAL_scalar: sqdmlal(vf, rd, rn, rm); break;
34780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLSL_scalar: sqdmlsl(vf, rd, rn, rm); break;
34790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMULL_scalar: sqdmull(vf, rd, rn, rm); break;
34800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
34810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
34820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
34830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
34840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34860cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONScalar3Same(const Instruction* instr) {
34870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
34880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
34890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
34910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
34920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
34930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
34940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
34950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
34960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEONScalar3SameFPMask)) {
34970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FMULX_scalar:   fmulx(vf, rd, rn, rm); break;
34980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FACGE_scalar:   fabscmp(vf, rd, rn, rm, ge); break;
34990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FACGT_scalar:   fabscmp(vf, rd, rn, rm, gt); break;
35000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMEQ_scalar:   fcmp(vf, rd, rn, rm, eq); break;
35010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGE_scalar:   fcmp(vf, rd, rn, rm, ge); break;
35020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FCMGT_scalar:   fcmp(vf, rd, rn, rm, gt); break;
35030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRECPS_scalar:  frecps(vf, rd, rn, rm); break;
35040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FRSQRTS_scalar: frsqrts(vf, rd, rn, rm); break;
35050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_FABD_scalar:    fabd(vf, rd, rn, rm); break;
35060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
35070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNIMPLEMENTED();
35080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
35090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
35100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    switch (instr->Mask(NEONScalar3SameMask)) {
35110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_ADD_scalar:      add(vf, rd, rn, rm); break;
35120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SUB_scalar:      sub(vf, rd, rn, rm); break;
35130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMEQ_scalar:     cmp(vf, rd, rn, rm, eq); break;
35140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGE_scalar:     cmp(vf, rd, rn, rm, ge); break;
35150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMGT_scalar:     cmp(vf, rd, rn, rm, gt); break;
35160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMHI_scalar:     cmp(vf, rd, rn, rm, hi); break;
35170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMHS_scalar:     cmp(vf, rd, rn, rm, hs); break;
35180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_CMTST_scalar:    cmptst(vf, rd, rn, rm); break;
35190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_USHL_scalar:     ushl(vf, rd, rn, rm); break;
35200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SSHL_scalar:     sshl(vf, rd, rn, rm); break;
35210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQDMULH_scalar:  sqdmulh(vf, rd, rn, rm); break;
35220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQRDMULH_scalar: sqrdmulh(vf, rd, rn, rm); break;
35230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQADD_scalar:
35240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        add(vf, rd, rn, rm).UnsignedSaturate(vf);
35250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQADD_scalar:
35270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        add(vf, rd, rn, rm).SignedSaturate(vf);
35280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQSUB_scalar:
35300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sub(vf, rd, rn, rm).UnsignedSaturate(vf);
35310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQSUB_scalar:
35330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sub(vf, rd, rn, rm).SignedSaturate(vf);
35340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQSHL_scalar:
35360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
35370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQSHL_scalar:
35390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sshl(vf, rd, rn, rm).SignedSaturate(vf);
35400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_URSHL_scalar:
35420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ushl(vf, rd, rn, rm).Round(vf);
35430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SRSHL_scalar:
35450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sshl(vf, rd, rn, rm).Round(vf);
35460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_UQRSHL_scalar:
35480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
35490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      case NEON_SQRSHL_scalar:
35510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
35520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
35530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      default:
35540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_UNIMPLEMENTED();
35550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
35560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
35570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
35580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
35590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
35600cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
35610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
35620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
35630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
35640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
35650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
35660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
35670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  ByElementOp Op = NULL;
35680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
35690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int rm_reg = instr->Rm();
35700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int index = (instr->NEONH() << 1) | instr->NEONL();
35710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->NEONSize() == 1) {
35720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    rm_reg &= 0xf;
35730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    index = (index << 1) | instr->NEONM();
35740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
35750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
35760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONScalarByIndexedElementMask)) {
35770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMULL_byelement_scalar: Op = &Simulator::sqdmull; break;
35780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLAL_byelement_scalar: Op = &Simulator::sqdmlal; break;
35790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMLSL_byelement_scalar: Op = &Simulator::sqdmlsl; break;
35800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQDMULH_byelement_scalar:
35810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Op = &Simulator::sqdmulh;
35820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_r;
35830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
35840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQRDMULH_byelement_scalar:
35850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      Op = &Simulator::sqrdmulh;
35860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_r;
35870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
35880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
35890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
35900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      index = instr->NEONH();
35910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if ((instr->FPType() & 1) == 0) {
35920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        index = (index << 1) | instr->NEONL();
35930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
35940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
35950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMUL_byelement_scalar: Op = &Simulator::fmul; break;
35960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMLA_byelement_scalar: Op = &Simulator::fmla; break;
35970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMLS_byelement_scalar: Op = &Simulator::fmls; break;
35980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case NEON_FMULX_byelement_scalar: Op = &Simulator::fmulx; break;
35990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        default: VIXL_UNIMPLEMENTED();
36000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
36010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
36020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
36040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
36050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36070cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONScalarCopy(const Instruction* instr) {
36080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
36090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
36100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
36120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
36130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
36150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int imm5 = instr->ImmNEON5();
36160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int tz = CountTrailingZeros(imm5, 32);
36170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    int rn_index = imm5 >> (tz + 1);
36180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    dup_element(vf, rd, rn, rn_index);
36190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  } else {
36200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    VIXL_UNIMPLEMENTED();
36210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
36220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
36230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36250cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
36260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
36270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
36280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
36300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
36310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONScalarPairwiseMask)) {
36320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ADDP_scalar:    addp(vf, rd, rn); break;
36330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FADDP_scalar:   faddp(vf, rd, rn); break;
36340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FMAXP_scalar:   fmaxp(vf, rd, rn); break;
36350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FMAXNMP_scalar: fmaxnmp(vf, rd, rn); break;
36360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FMINP_scalar:   fminp(vf, rd, rn); break;
36370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FMINNMP_scalar: fminnmp(vf, rd, rn); break;
36380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
36390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
36400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
36410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
36420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36440cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
36450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
36460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
36470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
36480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  static const NEONFormatMap map = {
36500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {22, 21, 20, 19},
36510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S,
36520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl     NF_D,     NF_D, NF_D, NF_D, NF_D, NF_D, NF_D, NF_D}
36530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  };
36540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, &map);
36550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
36560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
36580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int immhimmb = instr->ImmNEONImmhImmb();
36590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int right_shift = (16 << highestSetBit) - immhimmb;
36600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int left_shift = immhimmb - (8 << highestSetBit);
36610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONScalarShiftImmediateMask)) {
36620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SHL_scalar:       shl(vf, rd, rn, left_shift); break;
36630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SLI_scalar:       sli(vf, rd, rn, left_shift); break;
36640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHL_imm_scalar: sqshl(vf, rd, rn, left_shift); break;
36650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UQSHL_imm_scalar: uqshl(vf, rd, rn, left_shift); break;
36660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHLU_scalar:    sqshlu(vf, rd, rn, left_shift); break;
36670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SRI_scalar:       sri(vf, rd, rn, right_shift); break;
36680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSHR_scalar:      sshr(vf, rd, rn, right_shift); break;
36690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USHR_scalar:      ushr(vf, rd, rn, right_shift); break;
36700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SRSHR_scalar:     sshr(vf, rd, rn, right_shift).Round(vf); break;
36710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_URSHR_scalar:     ushr(vf, rd, rn, right_shift).Round(vf); break;
36720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSRA_scalar:      ssra(vf, rd, rn, right_shift); break;
36730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USRA_scalar:      usra(vf, rd, rn, right_shift); break;
36740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SRSRA_scalar:     srsra(vf, rd, rn, right_shift); break;
36750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_URSRA_scalar:     ursra(vf, rd, rn, right_shift); break;
36760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UQSHRN_scalar:    uqshrn(vf, rd, rn, right_shift); break;
36770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UQRSHRN_scalar:   uqrshrn(vf, rd, rn, right_shift); break;
36780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHRN_scalar:    sqshrn(vf, rd, rn, right_shift); break;
36790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQRSHRN_scalar:   sqrshrn(vf, rd, rn, right_shift); break;
36800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHRUN_scalar:   sqshrun(vf, rd, rn, right_shift); break;
36810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQRSHRUN_scalar:  sqrshrun(vf, rd, rn, right_shift); break;
36820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FCVTZS_imm_scalar: fcvts(vf, rd, rn, FPZero, right_shift); break;
36830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FCVTZU_imm_scalar: fcvtu(vf, rd, rn, FPZero, right_shift); break;
36840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SCVTF_imm_scalar:
36850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      scvtf(vf, rd, rn, right_shift, fpcr_rounding);
36860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
36870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UCVTF_imm_scalar:
36880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
36890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
36900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
36910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
36920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
36930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
36940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
36960cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
36970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
36980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
36990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
37000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
37010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
37020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
37030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  static const NEONFormatMap map = {
37040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {22, 21, 20, 19, 30},
37050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B, NF_4H,    NF_8H, NF_4H,    NF_8H,
37060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl     NF_2S,    NF_4S,    NF_2S,    NF_4S,  NF_2S,    NF_4S, NF_2S,    NF_4S,
37070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl     NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
37080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl     NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,  NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}
37090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  };
37100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, &map);
37110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
37120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
37130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
37140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  static const NEONFormatMap map_l = {
37150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {22, 21, 20, 19},
37160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}
37170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  };
37180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
37190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
37200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
37210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int immhimmb = instr->ImmNEONImmhImmb();
37220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int right_shift = (16 << highestSetBit) - immhimmb;
37230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int left_shift = immhimmb - (8 << highestSetBit);
37240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
37250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONShiftImmediateMask)) {
37260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SHL:    shl(vf, rd, rn, left_shift); break;
37270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SLI:    sli(vf, rd, rn, left_shift); break;
37280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHLU: sqshlu(vf, rd, rn, left_shift); break;
37290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SRI:    sri(vf, rd, rn, right_shift); break;
37300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSHR:   sshr(vf, rd, rn, right_shift); break;
37310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USHR:   ushr(vf, rd, rn, right_shift); break;
37320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SRSHR:  sshr(vf, rd, rn, right_shift).Round(vf); break;
37330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_URSHR:  ushr(vf, rd, rn, right_shift).Round(vf); break;
37340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSRA:   ssra(vf, rd, rn, right_shift); break;
37350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USRA:   usra(vf, rd, rn, right_shift); break;
37360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SRSRA:  srsra(vf, rd, rn, right_shift); break;
37370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_URSRA:  ursra(vf, rd, rn, right_shift); break;
37380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHL_imm: sqshl(vf, rd, rn, left_shift); break;
37390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UQSHL_imm: uqshl(vf, rd, rn, left_shift); break;
37400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SCVTF_imm: scvtf(vf, rd, rn, right_shift, fpcr_rounding); break;
37410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UCVTF_imm: ucvtf(vf, rd, rn, right_shift, fpcr_rounding); break;
37420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FCVTZS_imm: fcvts(vf, rd, rn, FPZero, right_shift); break;
37430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_FCVTZU_imm: fcvtu(vf, rd, rn, FPZero, right_shift); break;
37440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SSHLL:
37450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_l;
37460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sshll2(vf, rd, rn, left_shift);
37480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sshll(vf, rd, rn, left_shift);
37500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
37510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
37520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_USHLL:
37530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      vf = vf_l;
37540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ushll2(vf, rd, rn, left_shift);
37560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        ushll(vf, rd, rn, left_shift);
37580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
37590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
37600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SHRN:
37610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        shrn2(vf, rd, rn, right_shift);
37630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        shrn(vf, rd, rn, right_shift);
37650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
37660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
37670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_RSHRN:
37680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        rshrn2(vf, rd, rn, right_shift);
37700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        rshrn(vf, rd, rn, right_shift);
37720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
37730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
37740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UQSHRN:
37750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        uqshrn2(vf, rd, rn, right_shift);
37770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        uqshrn(vf, rd, rn, right_shift);
37790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
37800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
37810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UQRSHRN:
37820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        uqrshrn2(vf, rd, rn, right_shift);
37840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        uqrshrn(vf, rd, rn, right_shift);
37860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
37870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
37880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHRN:
37890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqshrn2(vf, rd, rn, right_shift);
37910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqshrn(vf, rd, rn, right_shift);
37930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
37940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
37950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQRSHRN:
37960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
37970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqrshrn2(vf, rd, rn, right_shift);
37980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
37990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqrshrn(vf, rd, rn, right_shift);
38000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
38010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
38020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQSHRUN:
38030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
38040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqshrun2(vf, rd, rn, right_shift);
38050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
38060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqshrun(vf, rd, rn, right_shift);
38070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
38080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
38090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_SQRSHRUN:
38100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (instr->Mask(NEON_Q)) {
38110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqrshrun2(vf, rd, rn, right_shift);
38120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
38130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        sqrshrun(vf, rd, rn, right_shift);
38140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
38150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
38160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
38170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
38180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
38190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
38200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38220cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONTable(const Instruction* instr) {
38230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
38240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
38250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
38270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
38280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn2 = vreg((instr->Rn() + 1) % kNumberOfVRegisters);
38290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn3 = vreg((instr->Rn() + 2) % kNumberOfVRegisters);
38300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn4 = vreg((instr->Rn() + 3) % kNumberOfVRegisters);
38310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
38320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONTableMask)) {
38340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBL_1v: tbl(vf, rd, rn, rm); break;
38350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBL_2v: tbl(vf, rd, rn, rn2, rm); break;
38360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBL_3v: tbl(vf, rd, rn, rn2, rn3, rm); break;
38370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBL_4v: tbl(vf, rd, rn, rn2, rn3, rn4, rm); break;
38380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBX_1v: tbx(vf, rd, rn, rm); break;
38390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBX_2v: tbx(vf, rd, rn, rn2, rm); break;
38400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBX_3v: tbx(vf, rd, rn, rn2, rn3, rm); break;
38410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TBX_4v: tbx(vf, rd, rn, rn2, rn3, rn4, rm); break;
38420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
38430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
38440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
38450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
38460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38480cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::VisitNEONPerm(const Instruction* instr) {
38490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  NEONFormatDecoder nfd(instr);
38500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VectorFormat vf = nfd.GetVectorFormat();
38510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rd = vreg(instr->Rd());
38530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rn = vreg(instr->Rn());
38540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  SimVRegister& rm = vreg(instr->Rm());
38550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (instr->Mask(NEONPermMask)) {
38570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TRN1: trn1(vf, rd, rn, rm); break;
38580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_TRN2: trn2(vf, rd, rn, rm); break;
38590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UZP1: uzp1(vf, rd, rn, rm); break;
38600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_UZP2: uzp2(vf, rd, rn, rm); break;
38610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ZIP1: zip1(vf, rd, rn, rm); break;
38620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case NEON_ZIP2: zip2(vf, rd, rn, rm); break;
38630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
38640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNIMPLEMENTED();
38650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
38660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
38670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38690cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::DoUnreachable(const Instruction* instr) {
38700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
38710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              (instr->ImmException() == kUnreachableOpcode));
38720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  fprintf(stream_, "Hit UNREACHABLE marker at pc=%p.\n",
38740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl          reinterpret_cast<const void*>(instr));
38750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  abort();
38760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
38770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38790cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::DoTrace(const Instruction* instr) {
38800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
38810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              (instr->ImmException() == kTraceOpcode));
38820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Read the arguments encoded inline in the instruction stream.
38840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t parameters;
38850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t command;
38860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
38880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
38890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
38900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
38910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  switch (command) {
38920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case TRACE_ENABLE:
38930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_trace_parameters(trace_parameters() | parameters);
38940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
38950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    case TRACE_DISABLE:
38960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      set_trace_parameters(trace_parameters() & ~parameters);
38970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      break;
38980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    default:
38990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      VIXL_UNREACHABLE();
39000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
39010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_pc(instr->InstructionAtOffset(kTraceLength));
39030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
39040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39060cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::DoLog(const Instruction* instr) {
39070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
39080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              (instr->ImmException() == kLogOpcode));
39090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Read the arguments encoded inline in the instruction stream.
39110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t parameters;
39120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
39140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
39150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // We don't support a one-shot LOG_DISASM.
39170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((parameters & LOG_DISASM) == 0);
39180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Print the requested information.
39190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (parameters & LOG_SYSREGS) PrintSystemRegisters();
39200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (parameters & LOG_REGS) PrintRegisters();
39210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (parameters & LOG_VREGS) PrintVRegisters();
39220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_pc(instr->InstructionAtOffset(kLogLength));
39240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
39250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39270cc8b6ece4b3e757e11a906a81ece292437713abarmvixlvoid Simulator::DoPrintf(const Instruction* instr) {
39280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
39290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl              (instr->ImmException() == kPrintfOpcode));
39300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Read the arguments encoded inline in the instruction stream.
39320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t arg_count;
39330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t arg_pattern_list;
39340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
39350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  memcpy(&arg_count,
39360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         instr + kPrintfArgCountOffset,
39370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         sizeof(arg_count));
39380cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  memcpy(&arg_pattern_list,
39390cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         instr + kPrintfArgPatternListOffset,
39400cc8b6ece4b3e757e11a906a81ece292437713abarmvixl         sizeof(arg_pattern_list));
39410cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39420cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
39430cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
39440cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39450cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // We need to call the host printf function with a set of arguments defined by
39460cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // arg_pattern_list. Because we don't know the types and sizes of the
39470cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // arguments, this is very difficult to do in a robust and portable way. To
39480cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // work around the problem, we pick apart the format string, and print one
39490cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // format placeholder at a time.
39500cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39510cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Allocate space for the format string. We take a copy, so we can modify it.
39520cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Leave enough space for one extra character per expected argument (plus the
39530cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // '\0' termination).
39540cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  const char * format_base = reg<const char *>(0);
39550cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_ASSERT(format_base != NULL);
39560cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  size_t length = strlen(format_base) + 1;
39570cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  char * const format = new char[length + arg_count];
39580cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39590cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // A list of chunks, each with exactly one format placeholder.
39600cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  const char * chunks[kPrintfMaxArgCount];
39610cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39620cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Copy the format string and search for format placeholders.
39630cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  uint32_t placeholder_count = 0;
39640cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  char * format_scratch = format;
39650cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  for (size_t i = 0; i < length; i++) {
39660cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    if (format_base[i] != '%') {
39670cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      *format_scratch++ = format_base[i];
39680cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    } else {
39690cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (format_base[i + 1] == '%') {
39700cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Ignore explicit "%%" sequences.
39710cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        *format_scratch++ = format_base[i];
39720cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        i++;
39730cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Chunks after the first are passed as format strings to printf, so we
39740cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // need to escape '%' characters in those chunks.
39750cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        if (placeholder_count > 0) *format_scratch++ = format_base[i];
39760cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      } else {
39770cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        VIXL_CHECK(placeholder_count < arg_count);
39780cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Insert '\0' before placeholders, and store their locations.
39790cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        *format_scratch++ = '\0';
39800cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        chunks[placeholder_count++] = format_scratch;
39810cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        *format_scratch++ = format_base[i];
39820cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
39830cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
39840cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
39850cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  VIXL_CHECK(placeholder_count == arg_count);
39860cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39870cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Finally, call printf with each chunk, passing the appropriate register
39880cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // argument. Normally, printf returns the number of bytes transmitted, so we
39890cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // can emulate a single printf call by adding the result from each chunk. If
39900cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // any call returns a negative (error) value, though, just return that value.
39910cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39920cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  printf("%s", clr_printf);
39930cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
39940cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Because '\0' is inserted before each placeholder, the first string in
39950cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // 'format' contains no format placeholders and should be printed literally.
39960cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int result = printf("%s", format);
39970cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int pcs_r = 1;      // Start at x1. x0 holds the format string.
39980cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  int pcs_f = 0;      // Start at d0.
39990cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  if (result >= 0) {
40000cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    for (uint32_t i = 0; i < placeholder_count; i++) {
40010cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      int part_result = -1;
40020cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40030cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
40040cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
40050cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      switch (arg_pattern) {
40060cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case kPrintfArgW: part_result = printf(chunks[i], wreg(pcs_r++)); break;
40070cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case kPrintfArgX: part_result = printf(chunks[i], xreg(pcs_r++)); break;
40080cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        case kPrintfArgD: part_result = printf(chunks[i], dreg(pcs_f++)); break;
40090cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        default: VIXL_UNREACHABLE();
40100cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
40110cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40120cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      if (part_result < 0) {
40130cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        // Handle error values.
40140cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        result = part_result;
40150cc8b6ece4b3e757e11a906a81ece292437713abarmvixl        break;
40160cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      }
40170cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40180cc8b6ece4b3e757e11a906a81ece292437713abarmvixl      result += part_result;
40190cc8b6ece4b3e757e11a906a81ece292437713abarmvixl    }
40200cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  }
40210cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40220cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  printf("%s", clr_normal);
40230cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40240cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Printf returns its result in x0 (just like the C library's printf).
40250cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_xreg(0, result);
40260cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40270cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // The printf parameters are inlined in the code, so skip them.
40280cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_pc(instr->InstructionAtOffset(kPrintfLength));
40290cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40300cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  // Set LR as if we'd just called a native printf function.
40310cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  set_lr(pc());
40320cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40330cc8b6ece4b3e757e11a906a81ece292437713abarmvixl  delete[] format;
40340cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}
40350cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40360cc8b6ece4b3e757e11a906a81ece292437713abarmvixl}  // namespace vixl
40370cc8b6ece4b3e757e11a906a81ece292437713abarmvixl
40389795cffa6b242fddee25847d17136a8da5b5c2d7Phil Wang#endif  // VIXL_INCLUDE_SIMULATOR
4039