1ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Copyright 2013, ARM Limited
2ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// All rights reserved.
3ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
4ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Redistribution and use in source and binary forms, with or without
5ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// modification, are permitted provided that the following conditions are met:
6ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
7ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions of source code must retain the above copyright notice,
8ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer.
9ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions in binary form must reproduce the above copyright notice,
10ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer in the documentation
11ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     and/or other materials provided with the distribution.
12ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
13ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     used to endorse or promote products derived from this software without
14ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     specific prior written permission.
15ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
16ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#ifdef USE_SIMULATOR
281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
29ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl#include <string.h>
30e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers#include <cmath>
31ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#include "a64/simulator-a64.h"
32ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
33ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
34ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
35ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst Instruction* Simulator::kEndOfSimAddress = NULL;
36ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
37578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
38578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  int width = msb - lsb + 1;
391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(is_uintn(width, bits) || is_intn(width, bits));
40578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
41578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  bits <<= lsb;
42578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  uint32_t mask = ((1 << width) - 1) << lsb;
431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((mask & write_ignore_mask_) == 0);
44578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
45578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  value_ = (value_ & ~mask) | (bits & mask);
46578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
47578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
48578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
49578645f14e122d2b87d907e298cda7e7d0babf1farmvixlSimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
50578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  switch (id) {
51578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case NZCV:
52578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
53578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FPCR:
54578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
55578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    default:
561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
57578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return SimSystemRegister();
58578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
59578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
60578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
61578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
62ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlSimulator::Simulator(Decoder* decoder, FILE* stream) {
63f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // Ensure that shift operations act as the simulator expects.
641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7FFFFFFF);
66ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
67f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // Set up the decoder.
68ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  decoder_ = decoder;
69ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  decoder_->AppendVisitor(this);
70ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
71ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ResetState();
72ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
73f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // Allocate and set up the simulator stack.
74f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  stack_ = new byte[stack_size_];
75ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stack_limit_ = stack_ + stack_protection_size_;
76f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // Configure the starting stack pointer.
77f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  //  - Find the top of the stack.
781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  byte * tos = stack_ + stack_size_;
79f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  //  - There's a protection region at both ends of the stack.
80f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  tos -= stack_protection_size_;
81f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  //  - The stack pointer must be 16-byte aligned.
821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  tos = AlignDown(tos, 16);
83f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  set_sp(tos);
84ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
85ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stream_ = stream;
86ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  print_disasm_ = new PrintDisassembler(stream_);
87ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  set_coloured_trace(false);
88ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  disasm_trace_ = false;
89578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
90578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Set the sample period to 10, as the VIXL examples and tests are short.
91578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  instrumentation_ = new Instrument("vixl_stats.csv", 10);
92ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
93ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
94ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
95ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::ResetState() {
96578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Reset the system registers.
97578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
98578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
99ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Reset registers to 0.
101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  pc_ = NULL;
102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  pc_modified_ = false;
103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    set_xreg(i, 0xbadbeef);
105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
1081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    set_dreg(i, kFP64SignallingNaN);
109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Returning to address 0 exits the Simulator.
111f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  set_lr(kEndOfSimAddress);
112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlSimulator::~Simulator() {
116f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  delete [] stack_;
117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The decoder may outlive the simulator.
118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  decoder_->RemoveVisitor(print_disasm_);
119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  delete print_disasm_;
120578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
121578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  decoder_->RemoveVisitor(instrumentation_);
122578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  delete instrumentation_;
123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::Run() {
127f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  pc_modified_ = false;
128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (pc_ != kEndOfSimAddress) {
129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    ExecuteInstruction();
130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::RunFrom(Instruction* first) {
135f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  set_pc(first);
136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Run();
137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::xreg_names[] = {
141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"x24", "x25", "x26", "x27", "x28", "x29", "lr",  "xzr", "sp"};
145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::wreg_names[] = {
148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"w0",  "w1",  "w2",  "w3",  "w4",  "w5",  "w6",  "w7",
149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"w8",  "w9",  "w10", "w11", "w12", "w13", "w14", "w15",
150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr", "wsp"};
152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::sreg_names[] = {
154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::dreg_names[] = {
160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::vreg_names[] = {
166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
1741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(code < kNumberOfRegisters);
175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If the code represents the stack pointer, index the name after zr.
176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    code = kZeroRegCode + 1;
178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return wreg_names[code];
180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
1841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(code < kNumberOfRegisters);
185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If the code represents the stack pointer, index the name after zr.
186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    code = kZeroRegCode + 1;
188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return xreg_names[code];
190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::SRegNameForCode(unsigned code) {
1941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(code < kNumberOfFPRegisters);
195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return sreg_names[code];
196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::DRegNameForCode(unsigned code) {
2001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(code < kNumberOfFPRegisters);
201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return dreg_names[code];
202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlconst char* Simulator::VRegNameForCode(unsigned code) {
2061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(code < kNumberOfFPRegisters);
207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return vreg_names[code];
208ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
210ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define COLOUR(colour_code)  "\033[" colour_code "m"
2121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define BOLD(colour_code)    "1;" colour_code
2131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define NORMAL ""
2141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define GREY   "30"
2151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define GREEN  "32"
2161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define ORANGE "33"
2171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define BLUE   "34"
2181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define PURPLE "35"
2191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define INDIGO "36"
2201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#define WHITE  "37"
2211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlvoid Simulator::set_coloured_trace(bool value) {
2221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  coloured_trace_ = value;
223ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
224ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_normal         = value ? COLOUR(NORMAL)       : "";
225ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_flag_name      = value ? COLOUR(BOLD(GREY))   : "";
226ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_flag_value     = value ? COLOUR(BOLD(WHITE))  : "";
227ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_reg_name       = value ? COLOUR(BOLD(BLUE))   : "";
228ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_reg_value      = value ? COLOUR(BOLD(INDIGO)) : "";
229ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_fpreg_name     = value ? COLOUR(BOLD(ORANGE)) : "";
230ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_fpreg_value    = value ? COLOUR(BOLD(PURPLE)) : "";
231ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_memory_value   = value ? COLOUR(BOLD(GREEN))  : "";
232ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_memory_address = value ? COLOUR(GREEN)        : "";
233ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_debug_number   = value ? COLOUR(BOLD(ORANGE)) : "";
234ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_debug_message  = value ? COLOUR(ORANGE)       : "";
235ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  clr_printf         = value ? COLOUR(GREEN)        : "";
2361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
2371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
239ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Helpers ---------------------------------------------------------------------
240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint64_t Simulator::AddWithCarry(unsigned reg_size,
241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                bool set_flags,
242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                int64_t src1,
243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                int64_t src2,
244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                int64_t carry_in) {
2451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
2461123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint64_t u1, u2;
249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t result;
250ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t signed_sum = src1 + src2 + carry_in;
251ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
252ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint32_t N, Z, C, V;
253ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (reg_size == kWRegSize) {
255ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    u1 = static_cast<uint64_t>(src1) & kWRegMask;
256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    u2 = static_cast<uint64_t>(src2) & kWRegMask;
257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    result = signed_sum & kWRegMask;
259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Compute the C flag by comparing the sum to the max unsigned integer.
260578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    C = ((kWMaxUInt - u1) < (u2 + carry_in)) ||
261578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        ((kWMaxUInt - u1 - carry_in) < u2);
262ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Overflow iff the sign bit is the same for the two inputs and different
263ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // for the result.
264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int64_t s_src1 = src1 << (kXRegSize - kWRegSize);
265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int64_t s_src2 = src2 << (kXRegSize - kWRegSize);
266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    int64_t s_result = result << (kXRegSize - kWRegSize);
267578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0);
268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    u1 = static_cast<uint64_t>(src1);
271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    u2 = static_cast<uint64_t>(src2);
272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
273ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    result = signed_sum;
274ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Compute the C flag by comparing the sum to the max unsigned integer.
275578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    C = ((kXMaxUInt - u1) < (u2 + carry_in)) ||
276578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        ((kXMaxUInt - u1 - carry_in) < u2);
277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Overflow iff the sign bit is the same for the two inputs and different
278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // for the result.
279578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
282ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  N = CalcNFlag(result, reg_size);
283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Z = CalcZFlag(result);
284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
285578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (set_flags) {
286578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetN(N);
287578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetZ(Z);
288578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetC(C);
289578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetV(V);
290578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return result;
292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint64_t Simulator::ShiftOperand(unsigned reg_size,
296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                int64_t value,
297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                Shift shift_type,
298ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                unsigned amount) {
299ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (amount == 0) {
300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return value;
301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
303ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (shift_type) {
304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LSL:
305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return (value << amount) & mask;
306ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LSR:
307ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return static_cast<uint64_t>(value) >> amount;
308ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ASR: {
309ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Shift used to restore the sign.
310ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      unsigned s_shift = kXRegSize - reg_size;
311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Value with its sign restored.
312ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      int64_t s_value = (value << s_shift) >> s_shift;
313ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return (s_value >> amount) & mask;
314ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
315ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ROR: {
316ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (reg_size == kWRegSize) {
317ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        value &= kWRegMask;
318ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
319ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return (static_cast<uint64_t>(value) >> amount) |
3201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl             ((value & ((INT64_C(1) << amount) - 1)) <<
3211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              (reg_size - amount));
322ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
323ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
3241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNIMPLEMENTED();
325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      return 0;
326ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
327ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
328ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
329ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint64_t Simulator::ExtendValue(unsigned reg_size,
331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               int64_t value,
332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               Extend extend_type,
333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               unsigned left_shift) {
334ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (extend_type) {
335ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UXTB:
336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      value &= kByteMask;
337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
338ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UXTH:
339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      value &= kHalfWordMask;
340ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
341ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UXTW:
342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      value &= kWordMask;
343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SXTB:
345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      value = (value << 56) >> 56;
346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
347ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SXTH:
348ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      value = (value << 48) >> 48;
349ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
350ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SXTW:
351ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      value = (value << 32) >> 32;
352ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UXTX:
354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SXTX:
355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
356ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
3571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
359ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
360ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return (value << left_shift) & mask;
361ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
362ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
363ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
3641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate<> double Simulator::FPDefaultNaN<double>() const {
3651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return kFP64DefaultNaN;
3661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
3671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate<> float Simulator::FPDefaultNaN<float>() const {
3701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return kFP32DefaultNaN;
3711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
3721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
3731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::FPCompare(double val0, double val1) {
375578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
377578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // TODO: This assumes that the C++ implementation handles comparisons in the
378578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // way that we expect (as per AssertSupportedFPCR()).
379e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
380578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetRawValue(FPUnorderedFlag);
381578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else if (val0 < val1) {
382578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetRawValue(FPLessThanFlag);
383578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else if (val0 > val1) {
384578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetRawValue(FPGreaterThanFlag);
385578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else if (val0 == val1) {
386578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetRawValue(FPEqualFlag);
387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
3881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_UNREACHABLE();
389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
393578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid Simulator::PrintSystemRegisters(bool print_all) {
394ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  static bool first_run = true;
395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
396578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  static SimSystemRegister last_nzcv;
397578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) {
398578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n",
399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            clr_flag_name,
400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            clr_flag_value,
401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            N(), Z(), C(), V(),
402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl            clr_normal);
403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
404578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  last_nzcv = nzcv();
405578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
406578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  static SimSystemRegister last_fpcr;
407578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (print_all || first_run || (last_fpcr.RawValue() != fpcr().RawValue())) {
408578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    static const char * rmode[] = {
409578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      "0b00 (Round to Nearest)",
410578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      "0b01 (Round towards Plus Infinity)",
411578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      "0b10 (Round towards Minus Infinity)",
412578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      "0b11 (Round towards Zero)"
413578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    };
4141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(fpcr().RMode() <= (sizeof(rmode) / sizeof(rmode[0])));
415578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    fprintf(stream_, "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
416578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            clr_flag_name,
417578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            clr_flag_value,
418578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
419578645f14e122d2b87d907e298cda7e7d0babf1farmvixl            clr_normal);
420578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
421578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  last_fpcr = fpcr();
422578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  first_run = false;
424ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
427ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::PrintRegisters(bool print_all_regs) {
428ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  static bool first_run = true;
429ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  static int64_t last_regs[kNumberOfRegisters];
430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
431ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfRegisters; i++) {
432f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (print_all_regs || first_run ||
433f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        (last_regs[i] != xreg(i, Reg31IsStackPointer))) {
434ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      fprintf(stream_,
435ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              "# %s%4s:%s 0x%016" PRIx64 "%s\n",
436ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              clr_reg_name,
437ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              XRegNameForCode(i, Reg31IsStackPointer),
438ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              clr_reg_value,
439f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl              xreg(i, Reg31IsStackPointer),
440ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              clr_normal);
441ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Cache the new register value so the next run can detect any changes.
443f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    last_regs[i] = xreg(i, Reg31IsStackPointer);
444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  first_run = false;
446ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
447ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
448ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
449ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::PrintFPRegisters(bool print_all_regs) {
450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  static bool first_run = true;
451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  static uint64_t last_regs[kNumberOfFPRegisters];
452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Print as many rows of registers as necessary, keeping each individual
454ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // register in the same column each time (to make it easy to visually scan
455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // for changes).
456ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
457f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (print_all_regs || first_run || (last_regs[i] != dreg_bits(i))) {
458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      fprintf(stream_,
459ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl              "# %s%4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
4601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              clr_fpreg_name,
461ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              VRegNameForCode(i),
4621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              clr_fpreg_value,
463f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl              dreg_bits(i),
464ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              clr_normal,
4651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              clr_fpreg_name,
466ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              DRegNameForCode(i),
4671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              clr_fpreg_value,
468f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl              dreg(i),
4691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              clr_fpreg_name,
470ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              SRegNameForCode(i),
4711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl              clr_fpreg_value,
472f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl              sreg(i),
473ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              clr_normal);
474ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
475ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Cache the new register value so the next run can detect any changes.
476f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    last_regs[i] = dreg_bits(i);
477ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  first_run = false;
479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
481ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
482ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::PrintProcessorState() {
483578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  PrintSystemRegisters();
484ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrintRegisters();
485ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrintFPRegisters();
486ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
487ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
488ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
489ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Visitors---------------------------------------------------------------------
490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
491578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid Simulator::VisitUnimplemented(Instruction* instr) {
492578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  printf("Unimplemented instruction at 0x%p: 0x%08" PRIx32 "\n",
493578645f14e122d2b87d907e298cda7e7d0babf1farmvixl         reinterpret_cast<void*>(instr), instr->InstructionBits());
4941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_UNIMPLEMENTED();
495578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
496578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
497578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
498578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid Simulator::VisitUnallocated(Instruction* instr) {
499578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  printf("Unallocated instruction at 0x%p: 0x%08" PRIx32 "\n",
500ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl         reinterpret_cast<void*>(instr), instr->InstructionBits());
5011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_UNIMPLEMENTED();
502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
504ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
505ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitPCRelAddressing(Instruction* instr) {
506ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(PCRelAddressingMask)) {
507ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADR:
508ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_reg(kXRegSize,
509ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              instr->Rd(),
510ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl              reinterpret_cast<int64_t>(instr->ImmPCOffsetTarget()));
511ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
512ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADRP:  // Not implemented in the assembler.
5131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNIMPLEMENTED();
514ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
515ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
5161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
520ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitUnconditionalBranch(Instruction* instr) {
522ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(UnconditionalBranchMask)) {
523ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BL:
524f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      set_lr(instr->NextInstruction());
525ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Fall through.
526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case B:
527ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_pc(instr->ImmPCOffsetTarget());
528ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
5291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
530ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
531ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
532ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
533ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
534ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitConditionalBranch(Instruction* instr) {
5351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
536ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) {
537ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    set_pc(instr->ImmPCOffsetTarget());
538ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
539ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
540ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
541ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
542ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
543ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Instruction* target = Instruction::Cast(xreg(instr->Rn()));
544ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
545ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
546ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BLR:
547f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      set_lr(instr->NextInstruction());
548ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Fall through.
549ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BR:
550ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case RET: set_pc(target); break;
5511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
552ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
553ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
554ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
555ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
556ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitTestBranch(Instruction* instr) {
557ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
558ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                     instr->ImmTestBranchBit40();
5591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  bool bit_zero = ((xreg(instr->Rt()) >> bit_pos) & 1) == 0;
5601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  bool take_branch = false;
561ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(TestBranchMask)) {
5621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case TBZ: take_branch = bit_zero; break;
5631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case TBNZ: take_branch = !bit_zero; break;
5641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
565ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
566ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (take_branch) {
567ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    set_pc(instr->ImmPCOffsetTarget());
568ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
569ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
570ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
571ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
572ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitCompareBranch(Instruction* instr) {
573ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned rt = instr->Rt();
574ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool take_branch = false;
575ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(CompareBranchMask)) {
576ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBZ_w: take_branch = (wreg(rt) == 0); break;
577ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBZ_x: take_branch = (xreg(rt) == 0); break;
578ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBNZ_w: take_branch = (wreg(rt) != 0); break;
579ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CBNZ_x: take_branch = (xreg(rt) != 0); break;
5801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
581ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
582ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (take_branch) {
583ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    set_pc(instr->ImmPCOffsetTarget());
584ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
585ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
586ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
587ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
588ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::AddSubHelper(Instruction* instr, int64_t op2) {
589ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
590ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool set_flags = instr->FlagsUpdate();
591ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t new_val = 0;
592ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Instr operation = instr->Mask(AddSubOpMask);
593ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
594ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (operation) {
595ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADD:
596ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ADDS: {
597ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      new_val = AddWithCarry(reg_size,
598ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             set_flags,
599ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             reg(reg_size, instr->Rn(), instr->RnMode()),
600ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             op2);
601ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
602ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
603ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUB:
604ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SUBS: {
605ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      new_val = AddWithCarry(reg_size,
606ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             set_flags,
607ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             reg(reg_size, instr->Rn(), instr->RnMode()),
608ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             ~op2,
609ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             1);
610ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
611ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
6121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
613ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
614ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
615ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size, instr->Rd(), new_val, instr->RdMode());
616ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
617ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
618ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
619ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitAddSubShifted(Instruction* instr) {
620ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
621ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t op2 = ShiftOperand(reg_size,
622ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             reg(reg_size, instr->Rm()),
623ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             static_cast<Shift>(instr->ShiftDP()),
624ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             instr->ImmDPShift());
625ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  AddSubHelper(instr, op2);
626ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
627ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
628ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
629ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitAddSubImmediate(Instruction* instr) {
630ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
631ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  AddSubHelper(instr, op2);
632ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
633ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
634ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
635ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitAddSubExtended(Instruction* instr) {
636ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
637ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t op2 = ExtendValue(reg_size,
638ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                            reg(reg_size, instr->Rm()),
639ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                            static_cast<Extend>(instr->ExtendMode()),
640ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                            instr->ImmExtendShift());
641ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  AddSubHelper(instr, op2);
642ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
643ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
644ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
645ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitAddSubWithCarry(Instruction* instr) {
646ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
647ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t op2 = reg(reg_size, instr->Rm());
648ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t new_val;
649ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
650ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
651ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    op2 = ~op2;
652ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
653ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
654ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  new_val = AddWithCarry(reg_size,
655ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         instr->FlagsUpdate(),
656ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         reg(reg_size, instr->Rn()),
657ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         op2,
658ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         C());
659ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
660ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size, instr->Rd(), new_val);
661ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
662ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
663ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
664ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLogicalShifted(Instruction* instr) {
665ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
666ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Shift shift_type = static_cast<Shift>(instr->ShiftDP());
667ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned shift_amount = instr->ImmDPShift();
668ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
669ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                             shift_amount);
670ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (instr->Mask(NOT) == NOT) {
671ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    op2 = ~op2;
672ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
673ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalHelper(instr, op2);
674ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
675ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
676ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
677ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLogicalImmediate(Instruction* instr) {
678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalHelper(instr, instr->ImmLogical());
679ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
680ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
681ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
682ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::LogicalHelper(Instruction* instr, int64_t op2) {
683ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
684ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t op1 = reg(reg_size, instr->Rn());
685ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t result = 0;
686ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool update_flags = false;
687ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
688ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Switch on the logical operation, stripping out the NOT bit, as it has a
689ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // different meaning for logical immediate instructions.
690ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LogicalOpMask & ~NOT)) {
691ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ANDS: update_flags = true;  // Fall through.
692ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case AND: result = op1 & op2; break;
693ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ORR: result = op1 | op2; break;
694ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case EOR: result = op1 ^ op2; break;
695ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
6961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNIMPLEMENTED();
697ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
698ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
699ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (update_flags) {
700578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetN(CalcNFlag(result, reg_size));
701578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetZ(CalcZFlag(result));
702578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetC(0);
703578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetV(0);
704ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
705ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
706ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size, instr->Rd(), result, instr->RdMode());
707ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
708ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
709ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
710ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitConditionalCompareRegister(Instruction* instr) {
711ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
712ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
713ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
714ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
715ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
716ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
717ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ConditionalCompareHelper(instr, instr->ImmCondCmp());
718ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
719ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
720ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::ConditionalCompareHelper(Instruction* instr, int64_t op2) {
722ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t op1 = reg(reg_size, instr->Rn());
724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
725ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
726ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the condition passes, set the status flags to the result of comparing
727ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the operands.
728ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (instr->Mask(ConditionalCompareMask) == CCMP) {
729ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AddWithCarry(reg_size, true, op1, ~op2, 1);
730ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
7311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
732ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      AddWithCarry(reg_size, true, op1, op2, 0);
733ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
734ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
735ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the condition fails, set the status flags to the nzcv immediate.
736578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    nzcv().SetFlags(instr->Nzcv());
737ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
738ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
739ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
741ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) {
742ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int offset = instr->ImmLSUnsigned() << instr->SizeLS();
743ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStoreHelper(instr, offset, Offset);
744ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
745ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
746ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
747ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) {
748ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStoreHelper(instr, instr->ImmLS(), Offset);
749ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
750ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
751ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
752ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStorePreIndex(Instruction* instr) {
753ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
754ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
755ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
756ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
757ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStorePostIndex(Instruction* instr) {
758ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
759ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
761ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
762ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) {
763ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Extend ext = static_cast<Extend>(instr->ExtendMode());
7641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
765ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
766ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
767ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
768ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               shift_amount);
769ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStoreHelper(instr, offset, Offset);
770ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
771ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
772ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
773ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::LoadStoreHelper(Instruction* instr,
774ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                int64_t offset,
775ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                AddrMode addrmode) {
776ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned srcdst = instr->Rt();
777ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode);
778ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int num_bytes = 1 << instr->SizeLS();
779ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
780ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
781ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (op) {
782ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDRB_w:
783ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDRH_w:
784ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_w:
785ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break;
786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STRB_w:
787ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STRH_w:
788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STR_w:
789ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break;
790ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDRSB_w: {
791ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead8(address), SXTB));
792ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
793ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
794ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDRSB_x: {
795ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead8(address), SXTB));
796ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
797ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
798ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDRSH_w: {
799ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(srcdst, ExtendValue(kWRegSize, MemoryRead16(address), SXTH));
800ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
801ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
802ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDRSH_x: {
803ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead16(address), SXTH));
804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
806ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDRSW_x: {
807ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
808ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
809ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
810ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break;
811ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break;
812ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break;
813ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break;
8141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
815ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
816ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
817ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
818ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStorePairOffset(Instruction* instr) {
820ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStorePairHelper(instr, Offset);
821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
822ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
823ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
824ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
825ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStorePairHelper(instr, PreIndex);
826ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
827ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
828ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
829ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
830ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStorePairHelper(instr, PostIndex);
831ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
832ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) {
835ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStorePairHelper(instr, Offset);
836ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
837ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
838ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
839ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::LoadStorePairHelper(Instruction* instr,
840ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    AddrMode addrmode) {
841ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned rt = instr->Rt();
842ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned rt2 = instr->Rt2();
843ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int offset = instr->ImmLSPair() << instr->SizeLSPair();
844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode);
845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
846ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LoadStorePairOp op =
847ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
848ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // 'rt' and 'rt2' can only be aliased for stores.
8501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
852ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (op) {
853ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDP_w: {
854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(rt, MemoryRead32(address));
855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(rt2, MemoryRead32(address + kWRegSizeInBytes));
856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
858ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDP_s: {
859ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_sreg(rt, MemoryReadFP32(address));
860ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_sreg(rt2, MemoryReadFP32(address + kSRegSizeInBytes));
861ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
862ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDP_x: {
864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(rt, MemoryRead64(address));
865ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(rt2, MemoryRead64(address + kXRegSizeInBytes));
866ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
868ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDP_d: {
869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_dreg(rt, MemoryReadFP64(address));
870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_dreg(rt2, MemoryReadFP64(address + kDRegSizeInBytes));
871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
872ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
873ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDPSW_x: {
874ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(rt, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
875ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(rt2, ExtendValue(kXRegSize,
876ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl               MemoryRead32(address + kWRegSizeInBytes), SXTW));
877ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
878ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
879ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STP_w: {
880ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWrite32(address, wreg(rt));
881ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWrite32(address + kWRegSizeInBytes, wreg(rt2));
882ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
883ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
884ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STP_s: {
885ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWriteFP32(address, sreg(rt));
886ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWriteFP32(address + kSRegSizeInBytes, sreg(rt2));
887ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
888ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
889ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STP_x: {
890ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWrite64(address, xreg(rt));
891ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWrite64(address + kXRegSizeInBytes, xreg(rt2));
892ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
893ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
894ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case STP_d: {
895ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWriteFP64(address, dreg(rt));
896ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      MemoryWriteFP64(address + kDRegSizeInBytes, dreg(rt2));
897ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
898ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
8991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
900ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
901ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
902ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
903ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
904ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitLoadLiteral(Instruction* instr) {
905ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint8_t* address = instr->LiteralAddress();
906ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned rt = instr->Rt();
907ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
908ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(LoadLiteralMask)) {
909ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_w_lit: set_wreg(rt, MemoryRead32(address));  break;
910ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_x_lit: set_xreg(rt, MemoryRead64(address));  break;
911ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address));  break;
912ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address));  break;
9131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
914ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
915ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
916ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
917ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
918ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint8_t* Simulator::AddressModeHelper(unsigned addr_reg,
919ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      int64_t offset,
920ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      AddrMode addrmode) {
921ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
9221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
923ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((addr_reg == 31) && ((address % 16) != 0)) {
924ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // When the base register is SP the stack pointer is required to be
925ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // quadword aligned prior to the address calculation and write-backs.
926ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Misalignment will cause a stack alignment fault.
9271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ALIGNMENT_EXCEPTION();
928ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
9291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
930ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
9311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(offset != 0);
932ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    set_xreg(addr_reg, address + offset, Reg31IsStackPointer);
933ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
934ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
935ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((addrmode == Offset) || (addrmode == PreIndex)) {
936ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    address += offset;
937ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
938ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
9391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Verify that the calculated address is available to the host.
9401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(address == static_cast<uintptr_t>(address));
9411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
942ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return reinterpret_cast<uint8_t*>(address);
943ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
944ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
945ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
946ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint64_t Simulator::MemoryRead(const uint8_t* address, unsigned num_bytes) {
9471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(address != NULL);
9481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
949ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint64_t read = 0;
950ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  memcpy(&read, address, num_bytes);
951ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return read;
952ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
953ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
954ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
955ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint8_t Simulator::MemoryRead8(uint8_t* address) {
956ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return MemoryRead(address, sizeof(uint8_t));
957ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
958ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
959ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
960ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint16_t Simulator::MemoryRead16(uint8_t* address) {
961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return MemoryRead(address, sizeof(uint16_t));
962ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
963ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
964ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
965ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint32_t Simulator::MemoryRead32(uint8_t* address) {
966ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return MemoryRead(address, sizeof(uint32_t));
967ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
968ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
969ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
970ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlfloat Simulator::MemoryReadFP32(uint8_t* address) {
971ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return rawbits_to_float(MemoryRead32(address));
972ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
973ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
974ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
975ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint64_t Simulator::MemoryRead64(uint8_t* address) {
976ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return MemoryRead(address, sizeof(uint64_t));
977ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
978ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
979ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
980ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixldouble Simulator::MemoryReadFP64(uint8_t* address) {
981ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return rawbits_to_double(MemoryRead64(address));
982ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
983ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
984ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
985ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::MemoryWrite(uint8_t* address,
986ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                            uint64_t value,
987ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                            unsigned num_bytes) {
9881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(address != NULL);
9891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
990ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  memcpy(address, &value, num_bytes);
991ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
992ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
993ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
994ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::MemoryWrite32(uint8_t* address, uint32_t value) {
995ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemoryWrite(address, value, sizeof(uint32_t));
996ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
997ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
998ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
999ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::MemoryWriteFP32(uint8_t* address, float value) {
1000ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemoryWrite32(address, float_to_rawbits(value));
1001ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1002ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1003ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1004ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::MemoryWrite64(uint8_t* address, uint64_t value) {
1005ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemoryWrite(address, value, sizeof(uint64_t));
1006ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1007ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1008ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1009ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::MemoryWriteFP64(uint8_t* address, double value) {
1010ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemoryWrite64(address, double_to_rawbits(value));
1011ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1012ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1013ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1014ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitMoveWideImmediate(Instruction* instr) {
1015ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MoveWideImmediateOp mov_op =
1016ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1017ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t new_xn_val = 0;
1018ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
10197f2db39dffaca523429c67a71054bb19c108f31fAndreas Gampe  bool is_64_bits = instr->SixtyFourBits() != 0;
1020ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Shift is limited for W operations.
10211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
1022ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1023ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Get the shifted immediate.
1024ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t shift = instr->ShiftMoveWide() * 16;
1025ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t shifted_imm16 = instr->ImmMoveWide() << shift;
1026ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1027ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Compute the new value.
1028ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (mov_op) {
1029ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVN_w:
1030ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVN_x: {
1031ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        new_xn_val = ~shifted_imm16;
1032ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        if (!is_64_bits) new_xn_val &= kWRegMask;
1033ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1034ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1035ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVK_w:
1036ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVK_x: {
1037ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        unsigned reg_code = instr->Rd();
1038ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1039ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                         : wreg(reg_code);
10401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        new_xn_val =
10411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl            (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
1042ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1043ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1044ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVZ_w:
1045ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MOVZ_x: {
1046ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        new_xn_val = shifted_imm16;
1047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1049ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
10501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
1051ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1052ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1053ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Update the destination register.
1054ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_xreg(instr->Rd(), new_xn_val);
1055ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1056ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1057ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1058ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitConditionalSelect(Instruction* instr) {
1059ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint64_t new_val = xreg(instr->Rn());
1060ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1061ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1062ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    new_val = xreg(instr->Rm());
1063ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    switch (instr->Mask(ConditionalSelectMask)) {
1064ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSEL_w:
1065ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSEL_x: break;
1066ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSINC_w:
1067ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSINC_x: new_val++; break;
1068ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSINV_w:
1069ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSINV_x: new_val = ~new_val; break;
1070ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSNEG_w:
1071ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case CSNEG_x: new_val = -new_val; break;
10721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      default: VIXL_UNIMPLEMENTED();
1073ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1075ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1076ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size, instr->Rd(), new_val);
1077ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1078ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1079ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1080ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitDataProcessing1Source(Instruction* instr) {
1081ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned dst = instr->Rd();
1082ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned src = instr->Rn();
1083ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1084ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(DataProcessing1SourceMask)) {
1085ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSize)); break;
1086ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSize)); break;
1087ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break;
1088ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break;
1089ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break;
1090ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break;
1091ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break;
1092ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSize)); break;
1093ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSize)); break;
1094ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CLS_w: {
1095ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSize));
1096ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1097ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1098ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case CLS_x: {
1099ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSize));
1100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
11021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) {
11081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((num_bits == kWRegSize) || (num_bits == kXRegSize));
1109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint64_t result = 0;
1110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (unsigned i = 0; i < num_bits; i++) {
1111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    result = (result << 1) | (value & 1);
1112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    value >>= 1;
1113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return result;
1115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) {
1119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Split the 64-bit value into an 8-bit array, where b[0] is the least
1120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // significant byte, and b[7] is the most significant.
1121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint8_t bytes[8];
1122e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  uint64_t mask = UINT64_C(0xff00000000000000);
1123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (int i = 7; i >= 0; i--) {
1124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    bytes[i] = (value & mask) >> (i * 8);
1125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mask >>= 8;
1126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Permutation tables for REV instructions.
1129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //  permute_table[Reverse16] is used by REV16_x, REV16_w
1130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //  permute_table[Reverse32] is used by REV32_x, REV_w
1131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //  permute_table[Reverse64] is used by REV_x
11321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_STATIC_ASSERT((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2));
1133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1},
1134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                               {4, 5, 6, 7, 0, 1, 2, 3},
1135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                               {0, 1, 2, 3, 4, 5, 6, 7} };
1136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint64_t result = 0;
1137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  for (int i = 0; i < 8; i++) {
1138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    result <<= 8;
1139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    result |= bytes[permute_table[mode][i]];
1140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return result;
1142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitDataProcessing2Source(Instruction* instr) {
1146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Shift shift_op = NO_SHIFT;
1147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t result = 0;
1148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(DataProcessing2SourceMask)) {
1149f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case SDIV_w: {
1150f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      int32_t rn = wreg(instr->Rn());
1151f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      int32_t rm = wreg(instr->Rm());
1152f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      if ((rn == kWMinInt) && (rm == -1)) {
1153f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = kWMinInt;
1154f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      } else if (rm == 0) {
1155f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        // Division by zero can be trapped, but not on A-class processors.
1156f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = 0;
1157f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      } else {
1158f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = rn / rm;
1159f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1160f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      break;
1161f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    }
1162f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case SDIV_x: {
1163f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      int64_t rn = xreg(instr->Rn());
1164f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      int64_t rm = xreg(instr->Rm());
1165f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      if ((rn == kXMinInt) && (rm == -1)) {
1166f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = kXMinInt;
1167f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      } else if (rm == 0) {
1168f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        // Division by zero can be trapped, but not on A-class processors.
1169f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = 0;
1170f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      } else {
1171f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = rn / rm;
1172f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1173f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      break;
1174f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    }
1175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UDIV_w: {
1176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
1177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
1178f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      if (rm == 0) {
1179f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        // Division by zero can be trapped, but not on A-class processors.
1180f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = 0;
1181f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      } else {
1182f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = rn / rm;
1183f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UDIV_x: {
1187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
1188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
1189f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      if (rm == 0) {
1190f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        // Division by zero can be trapped, but not on A-class processors.
1191f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = 0;
1192f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      } else {
1193f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        result = rn / rm;
1194f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LSLV_w:
1198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LSLV_x: shift_op = LSL; break;
1199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LSRV_w:
1200ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case LSRV_x: shift_op = LSR; break;
1201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ASRV_w:
1202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case ASRV_x: shift_op = ASR; break;
1203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case RORV_w:
1204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case RORV_x: shift_op = ROR; break;
12051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1208ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (shift_op != NO_SHIFT) {
1210ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Shift distance encoded in the least-significant five/six bits of the
1211ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // register.
12127f2db39dffaca523429c67a71054bb19c108f31fAndreas Gampe    int mask = (instr->SixtyFourBits() != 0) ? 0x3f : 0x1f;
1213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    unsigned shift = wreg(instr->Rm()) & mask;
1214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
1215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          shift);
1216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1217ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size, instr->Rd(), result);
1218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1220ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// The algorithm used is adapted from the one described in section 8.2 of
1222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   Hacker's Delight, by Henry S. Warren, Jr.
1223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// It assumes that a right shift on a signed integer is an arithmetic shift.
1224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlstatic int64_t MultiplyHighSigned(int64_t u, int64_t v) {
1225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  uint64_t u0, v0, w0;
1226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t u1, v1, w1, w2, t;
1227ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
12281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  u0 = u & 0xffffffff;
1229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  u1 = u >> 32;
12301123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  v0 = v & 0xffffffff;
1231ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  v1 = v >> 32;
1232ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1233ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  w0 = u0 * v0;
1234ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  t = u1 * v0 + (w0 >> 32);
12351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  w1 = t & 0xffffffff;
1236ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  w2 = t >> 32;
1237ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  w1 = u0 * v1 + w1;
1238ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1239ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return u1 * v1 + w2 + (w1 >> 32);
1240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitDataProcessing3Source(Instruction* instr) {
1244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t result = 0;
1247f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  // Extract and sign- or zero-extend 32-bit arguments for widening operations.
1248f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
1249f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
1250f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  int64_t rn_s32 = reg<int32_t>(instr->Rn());
1251f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  int64_t rm_s32 = reg<int32_t>(instr->Rm());
1252ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(DataProcessing3SourceMask)) {
1253ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MADD_w:
1254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MADD_x:
1255ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
1256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MSUB_w:
1258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case MSUB_x:
1259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
1260ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1261f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
1262f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
1263f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
1264f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
1265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SMULH_x:
1266ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm()));
1267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
12681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size, instr->Rd(), result);
1271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1273ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1274ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitBitfield(Instruction* instr) {
1275ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1276ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
1277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t R = instr->ImmR();
1278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t S = instr->ImmS();
1279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t diff = S - R;
1280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t mask;
1281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (diff >= 0) {
12821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    mask = (diff < (reg_size - 1)) ? (INT64_C(1) << (diff + 1)) - 1
12831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl                                   : reg_mask;
1284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
12851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    mask = (INT64_C(1) << (S + 1)) - 1;
1286ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
1287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    diff += reg_size;
1288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // inzero indicates if the extracted bitfield is inserted into the
1291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // destination register value or in zero.
1292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If extend is true, extend the sign of the extracted bitfield.
1293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool inzero = false;
1294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  bool extend = false;
1295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(BitfieldMask)) {
1296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BFM_x:
1297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BFM_w:
1298ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1299ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBFM_x:
1300ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case SBFM_w:
1301ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      inzero = true;
1302ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      extend = true;
1303ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1304ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UBFM_x:
1305ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UBFM_w:
1306ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      inzero = true;
1307ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1308ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
13091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNIMPLEMENTED();
1310ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1311ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1312ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
1313ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t src = reg(reg_size, instr->Rn());
1314ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Rotate source bitfield into place.
1315ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
1316ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Determine the sign extension.
13171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  int64_t topbits = ((INT64_C(1) << (reg_size - diff - 1)) - 1) << (diff + 1);
1318ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
1319ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1320ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Merge sign extension, dest/zero and bitfield.
1321ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  result = signbits | (result & mask) | (dst & ~mask);
1322ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1323ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size, instr->Rd(), result);
1324ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1325ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1326ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1327ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitExtract(Instruction* instr) {
1328ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned lsb = instr->ImmS();
13297f2db39dffaca523429c67a71054bb19c108f31fAndreas Gampe  unsigned reg_size = (instr->SixtyFourBits() != 0) ? kXRegSize
1330ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                                    : kWRegSize;
1331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_reg(reg_size,
1332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          instr->Rd(),
1333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          (static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb) |
1334ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          (reg(reg_size, instr->Rn()) << (reg_size - lsb)));
1335ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1338ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPImmediate(Instruction* instr) {
1339578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
1340578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1341ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned dest = instr->Rd();
1342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPImmediateMask)) {
1343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
1344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
13451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1347ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1348ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1349ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1350ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPIntegerConvert(Instruction* instr) {
1351578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
1352578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned dst = instr->Rd();
1354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned src = instr->Rn();
1355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1356578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  FPRounding round = RMode();
1357578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPIntegerConvertMask)) {
1359f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
1360f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
1361f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
1362f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
1363f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
1364f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
1365f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
1366f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
1367ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_ws:
1368ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
1369ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1370ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_xs:
1371ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
1372ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_wd:
1374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
1375ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMS_xd:
1377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
1378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_ws:
1380ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
1381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_xs:
1383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
1384ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1385ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_wd:
1386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
1387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTMU_xd:
1389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
1390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
1392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
1393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
1394ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
1395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
1396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
1397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
1398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
1399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
1400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
1401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
1402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
1403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
1404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
1405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
1406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
1407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
1408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
1409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
1410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
1411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1412578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // A 32-bit input can be handled in the same way as a 64-bit input, since
1413578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // the sign- or zero-extension will not affect the conversion.
1414578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
1415578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
1416578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
1417ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case UCVTF_dw: {
1418578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_dreg(dst, UFixedToDouble(static_cast<uint32_t>(wreg(src)), 0, round));
1419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1420ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1421578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
1422578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
1423578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
1424578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_sw: {
1425578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_sreg(dst, UFixedToFloat(static_cast<uint32_t>(wreg(src)), 0, round));
1426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1427ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1428578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
14291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1431ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1432ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1433ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1434ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPFixedPointConvert(Instruction* instr) {
1435578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
1436578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1437ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned dst = instr->Rd();
1438ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned src = instr->Rn();
1439ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int fbits = 64 - instr->FPScale();
1440ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1441578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  FPRounding round = RMode();
1442578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1443ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPFixedPointConvertMask)) {
1444578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // A 32-bit input can be handled in the same way as a 64-bit input, since
1445578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // the sign- or zero-extension will not affect the conversion.
1446578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_dx_fixed:
1447578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
1448578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
1449578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_dw_fixed:
1450578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
1451578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
1452578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_dx_fixed:
1453578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
1454578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
1455578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_dw_fixed: {
1456578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_dreg(dst,
1457578645f14e122d2b87d907e298cda7e7d0babf1farmvixl               UFixedToDouble(static_cast<uint32_t>(wreg(src)), fbits, round));
1458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1459ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1460578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_sx_fixed:
1461578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
1462578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
1463578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case SCVTF_sw_fixed:
1464578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
1465578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
1466578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_sx_fixed:
1467578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
1468578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      break;
1469578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case UCVTF_sw_fixed: {
1470578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      set_sreg(dst,
1471578645f14e122d2b87d907e298cda7e7d0babf1farmvixl               UFixedToFloat(static_cast<uint32_t>(wreg(src)), fbits, round));
1472ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1473ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
14741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNREACHABLE();
1475ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1476ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1477ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint32_t Simulator::FPToInt32(double value, FPRounding rmode) {
1480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  value = FPRoundInt(value, rmode);
1481ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (value >= kWMaxInt) {
1482ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return kWMaxInt;
1483ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (value < kWMinInt) {
1484ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return kWMinInt;
1485ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1486e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  return std::isnan(value) ? 0 : static_cast<int32_t>(value);
1487ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1488ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1489ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlint64_t Simulator::FPToInt64(double value, FPRounding rmode) {
1491ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  value = FPRoundInt(value, rmode);
1492ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (value >= kXMaxInt) {
1493ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return kXMaxInt;
1494ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (value < kXMinInt) {
1495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return kXMinInt;
1496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1497e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  return std::isnan(value) ? 0 : static_cast<int64_t>(value);
1498ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1499ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1500ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1501ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
1502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  value = FPRoundInt(value, rmode);
1503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (value >= kWMaxUInt) {
1504ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return kWMaxUInt;
1505ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (value < 0.0) {
1506ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return 0;
1507ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1508e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
1509ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1510ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1511ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1512ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixluint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
1513ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  value = FPRoundInt(value, rmode);
1514ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (value >= kXMaxUInt) {
1515ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return kXMaxUInt;
1516ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (value < 0.0) {
1517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return 0;
1518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1519e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
1520ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1522ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1523ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPCompare(Instruction* instr) {
1524578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
1525578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
15261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSize : kSRegSize;
1527ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  double fn_val = fpreg(reg_size, instr->Rn());
1528ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1529ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPCompareMask)) {
1530ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_s:
1531ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break;
1532ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_s_zero:
1533ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCMP_d_zero: FPCompare(fn_val, 0.0); break;
15341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1535ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1536ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1537ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1538ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1539ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPConditionalCompare(Instruction* instr) {
1540578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
1541578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1542ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPConditionalCompareMask)) {
1543ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCCMP_s:
1544ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FCCMP_d: {
1545ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1546ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // If the condition passes, set the status flags to the result of
1547ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // comparing the operands.
15481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSize : kSRegSize;
1549ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
1550ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
1551ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // If the condition fails, set the status flags to the nzcv immediate.
1552578645f14e122d2b87d907e298cda7e7d0babf1farmvixl        nzcv().SetFlags(instr->Nzcv());
1553ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1554ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1555ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
15561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1557ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1558ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1559ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1560ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1561ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPConditionalSelect(Instruction* instr) {
1562578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
1563578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1564f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Instr selected;
1565ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1566f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    selected = instr->Rn();
1567ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1568f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    selected = instr->Rm();
1569ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1570ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1571ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPConditionalSelectMask)) {
1572f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
1573f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
15741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1575ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1576ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1577ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1578ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1579ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
1580578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
1581578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1582ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fd = instr->Rd();
1583ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fn = instr->Rn();
1584ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1585ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPDataProcessing1SourceMask)) {
1586ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_s: set_sreg(fd, sreg(fn)); break;
1587ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMOV_d: set_dreg(fd, dreg(fn)); break;
15881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FABS_s: set_sreg(fd, fabsf(sreg(fn))); break;
1589ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FABS_d: set_dreg(fd, fabs(dreg(fn))); break;
1590ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FNEG_s: set_sreg(fd, -sreg(fn)); break;
1591ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FNEG_d: set_dreg(fd, -dreg(fn)); break;
15921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break;
15931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break;
1594f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break;
1595f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break;
1596ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    case FRINTM_s:
1597ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break;
1598ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    case FRINTM_d:
1599ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break;
1600ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break;
1601ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break;
1602ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
1603ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
1604578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
1605578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
16061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1607ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1608ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1609ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1610ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1611578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// Assemble the specified IEEE-754 components into the target type and apply
1612578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// appropriate rounding.
1613578645f14e122d2b87d907e298cda7e7d0babf1farmvixl//  sign:     0 = positive, 1 = negative
1614578645f14e122d2b87d907e298cda7e7d0babf1farmvixl//  exponent: Unbiased IEEE-754 exponent.
1615578645f14e122d2b87d907e298cda7e7d0babf1farmvixl//  mantissa: The mantissa of the input. The top bit (which is not encoded for
1616578645f14e122d2b87d907e298cda7e7d0babf1farmvixl//            normal IEEE-754 values) must not be omitted. This bit has the
1617578645f14e122d2b87d907e298cda7e7d0babf1farmvixl//            value 'pow(2, exponent)'.
1618578645f14e122d2b87d907e298cda7e7d0babf1farmvixl//
1619578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// The input value is assumed to be a normalized value. That is, the input may
1620578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// not be infinity or NaN. If the source value is subnormal, it must be
1621578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// normalized before calling this function such that the highest set bit in the
1622578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// mantissa has the value 'pow(2, exponent)'.
1623578645f14e122d2b87d907e298cda7e7d0babf1farmvixl//
1624578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
1625578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// calling a templated FPRound.
1626578645f14e122d2b87d907e298cda7e7d0babf1farmvixltemplate <class T, int ebits, int mbits>
1627578645f14e122d2b87d907e298cda7e7d0babf1farmvixlstatic T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
1628578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                 FPRounding round_mode) {
16291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((sign == 0) || (sign == 1));
1630578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1631578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Only the FPTieEven rounding mode is implemented.
16321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(round_mode == FPTieEven);
1633578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  USE(round_mode);
1634578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1635578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Rounding can promote subnormals to normals, and normals to infinities. For
1636578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
1637578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // encodable as a float, but rounding based on the low-order mantissa bits
1638578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // could make it overflow. With ties-to-even rounding, this value would become
1639578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // an infinity.
1640578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1641578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // ---- Rounding Method ----
1642578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //
1643578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // The exponent is irrelevant in the rounding operation, so we treat the
1644578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // lowest-order bit that will fit into the result ('onebit') as having
1645578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // the value '1'. Similarly, the highest-order bit that won't fit into
1646578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // the result ('halfbit') has the value '0.5'. The 'point' sits between
1647578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // 'onebit' and 'halfbit':
1648578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //
1649578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //            These bits fit into the result.
1650578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //               |---------------------|
1651578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1652578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //                                     ||
1653578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //                                    / |
1654578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //                                   /  halfbit
1655578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //                               onebit
1656578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //
1657578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // For subnormal outputs, the range of representable bits is smaller and
1658578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // the position of onebit and halfbit depends on the exponent of the
1659578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // input, but the method is otherwise similar.
1660578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //
1661578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //   onebit(frac)
1662578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //     |
1663578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //     | halfbit(frac)          halfbit(adjusted)
1664578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //     | /                      /
1665578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //     | |                      |
1666578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b00.0 (exact)      -> 0b00.0 (exact)                    -> 0b00
1667578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b00.0...           -> 0b00.0...                         -> 0b00
1668578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b00.1 (exact)      -> 0b00.0111..111                    -> 0b00
1669578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b00.1...           -> 0b00.1...                         -> 0b01
1670578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b01.0 (exact)      -> 0b01.0 (exact)                    -> 0b01
1671578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b01.0...           -> 0b01.0...                         -> 0b01
1672578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b01.1 (exact)      -> 0b01.1 (exact)                    -> 0b10
1673578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b01.1...           -> 0b01.1...                         -> 0b10
1674578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b10.0 (exact)      -> 0b10.0 (exact)                    -> 0b10
1675578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b10.0...           -> 0b10.0...                         -> 0b10
1676578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b10.1 (exact)      -> 0b10.0111..111                    -> 0b10
1677578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b10.1...           -> 0b10.1...                         -> 0b11
1678578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  0b11.0 (exact)      -> 0b11.0 (exact)                    -> 0b11
1679578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //  ...                   /             |                      /   |
1680578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //                       /              |                     /    |
1681578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //                                                           /     |
1682578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // adjusted = frac - (halfbit(mantissa) & ~onebit(frac));   /      |
1683578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //
1684578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  //                   mantissa = (mantissa >> shift) + halfbit(adjusted);
1685578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1686578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  static const int mantissa_offset = 0;
1687578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  static const int exponent_offset = mantissa_offset + mbits;
1688578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  static const int sign_offset = exponent_offset + ebits;
16891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(sign_offset == (sizeof(T) * 8 - 1));
1690578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1691578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Bail out early for zero inputs.
1692578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (mantissa == 0) {
1693578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return sign << sign_offset;
1694578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1695578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1696578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // If all bits in the exponent are set, the value is infinite or NaN.
1697578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // This is true for all binary IEEE-754 formats.
1698578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  static const int infinite_exponent = (1 << ebits) - 1;
1699578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  static const int max_normal_exponent = infinite_exponent - 1;
1700578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1701578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Apply the exponent bias to encode it for the result. Doing this early makes
1702578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // it easy to detect values that will be infinite or subnormal.
1703578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  exponent += max_normal_exponent >> 1;
1704578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1705578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (exponent > max_normal_exponent) {
1706578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // Overflow: The input is too large for the result type to represent. The
1707578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // FPTieEven rounding mode handles overflows using infinities.
1708578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    exponent = infinite_exponent;
1709578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    mantissa = 0;
1710578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return (sign << sign_offset) |
1711578645f14e122d2b87d907e298cda7e7d0babf1farmvixl           (exponent << exponent_offset) |
1712578645f14e122d2b87d907e298cda7e7d0babf1farmvixl           (mantissa << mantissa_offset);
1713578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1714578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1715578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Calculate the shift required to move the top mantissa bit to the proper
1716578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // place in the destination type.
1717578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
1718578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  int shift = highest_significant_bit - mbits;
1719578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1720578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (exponent <= 0) {
1721578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // The output will be subnormal (before rounding).
1722578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1723578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // For subnormal outputs, the shift must be adjusted by the exponent. The +1
1724578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // is necessary because the exponent of a subnormal value (encoded as 0) is
1725578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // the same as the exponent of the smallest normal value (encoded as 1).
1726578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    shift += -exponent + 1;
1727578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1728578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // Handle inputs that would produce a zero output.
1729578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    //
1730578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // Shifts higher than highest_significant_bit+1 will always produce a zero
1731578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // result. A shift of exactly highest_significant_bit+1 might produce a
1732578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // non-zero result after rounding.
1733578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    if (shift > (highest_significant_bit + 1)) {
1734578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // The result will always be +/-0.0.
1735578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return sign << sign_offset;
1736578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
1737578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1738578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // Properly encode the exponent for a subnormal output.
1739578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    exponent = 0;
1740578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
1741578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
1742578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // normal values.
17431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    mantissa &= ~(UINT64_C(1) << highest_significant_bit);
1744578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1745578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1746578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (shift > 0) {
1747578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // We have to shift the mantissa to the right. Some precision is lost, so we
1748578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // need to apply rounding.
1749578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
1750578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
1751578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
1752578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
1753578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1754578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    T result = (sign << sign_offset) |
1755578645f14e122d2b87d907e298cda7e7d0babf1farmvixl               (exponent << exponent_offset) |
1756578645f14e122d2b87d907e298cda7e7d0babf1farmvixl               ((mantissa >> shift) << mantissa_offset);
1757578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1758578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // A very large mantissa can overflow during rounding. If this happens, the
1759578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // exponent should be incremented and the mantissa set to 1.0 (encoded as
1760578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // 0). Applying halfbit_adjusted after assembling the float has the nice
1761578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // side-effect that this case is handled for free.
1762578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    //
1763578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // This also handles cases where a very large finite value overflows to
1764578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // infinity, or where a very large subnormal value overflows to become
1765578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // normal.
1766578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return result + halfbit_adjusted;
1767578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
1768578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // We have to shift the mantissa to the left (or not at all). The input
1769578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // mantissa is exactly representable in the output mantissa, so apply no
1770578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // rounding correction.
1771578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return (sign << sign_offset) |
1772578645f14e122d2b87d907e298cda7e7d0babf1farmvixl           (exponent << exponent_offset) |
1773578645f14e122d2b87d907e298cda7e7d0babf1farmvixl           ((mantissa << -shift) << mantissa_offset);
1774578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1775578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1776578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1777578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1778578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// See FPRound for a description of this function.
1779578645f14e122d2b87d907e298cda7e7d0babf1farmvixlstatic inline double FPRoundToDouble(int64_t sign, int64_t exponent,
1780578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                     uint64_t mantissa, FPRounding round_mode) {
1781578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  int64_t bits =
1782578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
1783578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                                                 exponent,
1784578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                                                 mantissa,
1785578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                                                 round_mode);
1786578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return rawbits_to_double(bits);
1787578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1788578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1789578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1790578645f14e122d2b87d907e298cda7e7d0babf1farmvixl// See FPRound for a description of this function.
1791578645f14e122d2b87d907e298cda7e7d0babf1farmvixlstatic inline float FPRoundToFloat(int64_t sign, int64_t exponent,
1792578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                   uint64_t mantissa, FPRounding round_mode) {
1793578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  int32_t bits =
1794578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
1795578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                                               exponent,
1796578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                                               mantissa,
1797578645f14e122d2b87d907e298cda7e7d0babf1farmvixl                                                               round_mode);
1798578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return rawbits_to_float(bits);
1799578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1800578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1801578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1802578645f14e122d2b87d907e298cda7e7d0babf1farmvixldouble Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
1803578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (src >= 0) {
1804578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return UFixedToDouble(src, fbits, round);
1805578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
1806578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // This works for all negative values, including INT64_MIN.
1807578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return -UFixedToDouble(-src, fbits, round);
1808578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1809578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1810578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1811578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1812578645f14e122d2b87d907e298cda7e7d0babf1farmvixldouble Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
1813578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // An input of 0 is a special case because the result is effectively
1814578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
1815578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (src == 0) {
1816578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return 0.0;
1817578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1818578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1819578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Calculate the exponent. The highest significant bit will have the value
1820578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // 2^exponent.
1821578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
1822578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const int64_t exponent = highest_significant_bit - fbits;
1823578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1824578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return FPRoundToDouble(0, exponent, src, round);
1825578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1826578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1827578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1828578645f14e122d2b87d907e298cda7e7d0babf1farmvixlfloat Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
1829578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (src >= 0) {
1830578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return UFixedToFloat(src, fbits, round);
1831578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  } else {
1832578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    // This works for all negative values, including INT64_MIN.
1833578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return -UFixedToFloat(-src, fbits, round);
1834578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1835578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1836578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1837578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1838578645f14e122d2b87d907e298cda7e7d0babf1farmvixlfloat Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
1839578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // An input of 0 is a special case because the result is effectively
1840578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
1841578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  if (src == 0) {
1842578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    return 0.0f;
1843578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1844578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1845578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Calculate the exponent. The highest significant bit will have the value
1846578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // 2^exponent.
1847578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
1848578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  const int32_t exponent = highest_significant_bit - fbits;
1849578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1850578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return FPRoundToFloat(0, exponent, src, round);
1851578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1852578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1853578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixldouble Simulator::FPRoundInt(double value, FPRounding round_mode) {
1855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
18561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      (value == kFP64NegativeInfinity)) {
1857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return value;
1858e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  } else if (std::isnan(value)) {
18591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(value);
1860ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1861ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1862ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  double int_result = floor(value);
1863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  double error = value - int_result;
1864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (round_mode) {
1865f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    case FPTieAway: {
1866ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // Take care of correctly handling the range ]-0.5, -0.0], which must
1867ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // yield -0.0.
1868ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if ((-0.5 < value) && (value < 0.0)) {
1869ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        int_result = -0.0;
1870ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1871ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
1872ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        // If the error is greater than 0.5, or is equal to 0.5 and the integer
1873ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        // result is positive, round up.
1874f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl        int_result++;
1875f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      }
1876f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      break;
1877f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    }
1878ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FPTieEven: {
1879ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // Take care of correctly handling the range [-0.5, -0.0], which must
1880ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      // yield -0.0.
1881ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if ((-0.5 <= value) && (value < 0.0)) {
1882ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        int_result = -0.0;
1883ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
1884ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // If the error is greater than 0.5, or is equal to 0.5 and the integer
1885ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // result is odd, round up.
1886ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      } else if ((error > 0.5) ||
1887ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          ((error == 0.5) && (fmod(int_result, 2) != 0))) {
1888ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        int_result++;
1889ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1890ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1891ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1892ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FPZero: {
1893ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // If value>0 then we take floor(value)
1894ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // otherwise, ceil(value).
1895ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (value < 0) {
1896ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl         int_result = ceil(value);
1897ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
1898ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1899ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1900ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FPNegativeInfinity: {
1901ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // We always use floor(value).
1902ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1903ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
19041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
1905ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1906ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  return int_result;
1907ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1908ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1909ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1910578645f14e122d2b87d907e298cda7e7d0babf1farmvixldouble Simulator::FPToDouble(float value) {
1911e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  switch (std::fpclassify(value)) {
1912578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_NAN: {
19131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      if (DN()) return kFP64DefaultNaN;
19141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
19151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      // Convert NaNs as the processor would:
1916578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //  - The sign is propagated.
1917578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //  - The payload (mantissa) is transferred entirely, except that the top
1918578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //    bit is forced to '1', making the result a quiet NaN. The unused
1919578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //    (low-order) payload bits are set to 0.
1920578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint32_t raw = float_to_rawbits(value);
1921578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1922578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint64_t sign = raw >> 31;
1923578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint64_t exponent = (1 << 11) - 1;
1924578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint64_t payload = unsigned_bitextract_64(21, 0, raw);
1925578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      payload <<= (52 - 23);  // The unused low-order bits should be 0.
19261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      payload |= (UINT64_C(1) << 51);  // Force a quiet NaN.
1927578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1928578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
1929578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
1930578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1931578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_ZERO:
1932578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_NORMAL:
1933578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_SUBNORMAL:
1934578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_INFINITE: {
1935578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // All other inputs are preserved in a standard cast, because every value
1936578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // representable using an IEEE-754 float is also representable using an
1937578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // IEEE-754 double.
1938578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return static_cast<double>(value);
1939578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
1940578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1941578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
19421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_UNREACHABLE();
1943578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return static_cast<double>(value);
1944578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1945578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1946578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1947578645f14e122d2b87d907e298cda7e7d0babf1farmvixlfloat Simulator::FPToFloat(double value, FPRounding round_mode) {
1948578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // Only the FPTieEven rounding mode is implemented.
19491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT(round_mode == FPTieEven);
1950578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  USE(round_mode);
1951578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1952e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  switch (std::fpclassify(value)) {
1953578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_NAN: {
19541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      if (DN()) return kFP32DefaultNaN;
19551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
19561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      // Convert NaNs as the processor would:
1957578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //  - The sign is propagated.
1958578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //  - The payload (mantissa) is transferred as much as possible, except
1959578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      //    that the top bit is forced to '1', making the result a quiet NaN.
1960578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint64_t raw = double_to_rawbits(value);
1961578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1962578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint32_t sign = raw >> 63;
1963578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint32_t exponent = (1 << 8) - 1;
1964578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw);
1965578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      payload |= (1 << 22);   // Force a quiet NaN.
1966578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1967578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
1968578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
1969578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1970578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_ZERO:
1971578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_INFINITE: {
1972578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // In a C++ cast, any value representable in the target type will be
1973578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // unchanged. This is always the case for +/-0.0 and infinities.
1974578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return static_cast<float>(value);
1975578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
1976578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1977578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_NORMAL:
1978578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    case FP_SUBNORMAL: {
1979578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // Convert double-to-float as the processor would, assuming that FPCR.FZ
1980578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // (flush-to-zero) is not set.
1981578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint64_t raw = double_to_rawbits(value);
1982578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // Extract the IEEE-754 double components.
1983578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint32_t sign = raw >> 63;
1984578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // Extract the exponent and remove the IEEE-754 encoding bias.
1985578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023;
1986578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      // Extract the mantissa and add the implicit '1' bit.
1987578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
1988e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers      if (std::fpclassify(value) == FP_NORMAL) {
19891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl        mantissa |= (UINT64_C(1) << 52);
1990578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      }
1991578645f14e122d2b87d907e298cda7e7d0babf1farmvixl      return FPRoundToFloat(sign, exponent, mantissa, round_mode);
1992578645f14e122d2b87d907e298cda7e7d0babf1farmvixl    }
1993578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  }
1994578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
19951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_UNREACHABLE();
1996578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  return value;
1997578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
1998578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
1999578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2000ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2001578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
2002578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2003ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fd = instr->Rd();
2004ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fn = instr->Rn();
2005ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fm = instr->Rm();
2006ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
20071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Fmaxnm and Fminnm have special NaN handling.
20081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  switch (instr->Mask(FPDataProcessing2SourceMask)) {
20091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return;
20101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return;
20111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return;
20121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return;
20131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default:
20141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      break;    // Fall through.
20151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
20161123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
20171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (FPProcessNaNs(instr)) return;
20181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2019ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPDataProcessing2SourceMask)) {
20201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break;
20211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break;
20221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break;
20231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break;
20241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break;
20251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break;
20261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break;
20271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break;
2028ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break;
2029ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break;
2030ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break;
2031ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break;
20321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMAXNM_s:
20331123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMAXNM_d:
20341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMINNM_s:
20351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMINNM_d:
20361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      // These were handled before the standard FPProcessNaNs() stage.
20371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNREACHABLE();
20381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
2039ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2040ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2041ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2042ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2043ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2044578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  AssertSupportedFPCR();
2045578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2046ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fd = instr->Rd();
2047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fn = instr->Rn();
2048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fm = instr->Rm();
2049ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  unsigned fa = instr->Ra();
2050ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2051ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(FPDataProcessing3SourceMask)) {
2052f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // fd = fa +/- (fn * fm)
20531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
20541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
20551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
20561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
20571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Negated variants of the above.
20581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FNMADD_s:
20591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
20601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      break;
20611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FNMSUB_s:
20621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
20631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      break;
20641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FNMADD_d:
20651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
20661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      break;
20671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    case FNMSUB_d:
20681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
20691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      break;
20701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    default: VIXL_UNIMPLEMENTED();
2071ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2072ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2073ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2075f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixltemplate <typename T>
20761123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPAdd(T op1, T op2) {
20771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // NaNs should be handled elsewhere.
2078e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(!std::isnan(op1) && !std::isnan(op2));
20791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2080e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) {
20811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // inf + -inf returns the default NaN.
20821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPProcessException();
20831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPDefaultNaN<T>();
20841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
20851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Other cases should be handled by standard arithmetic.
20861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return op1 + op2;
2087ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
20881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
20891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
20901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
20911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
20921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPDiv(T op1, T op2) {
20931123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // NaNs should be handled elsewhere.
2094e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(!std::isnan(op1) && !std::isnan(op2));
20951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2096e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
20971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // inf / inf and 0.0 / 0.0 return the default NaN.
20981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPProcessException();
20991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPDefaultNaN<T>();
21001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
21011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (op2 == 0.0) FPProcessException();
21021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Other cases should be handled by standard arithmetic.
21041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return op1 / op2;
21051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
21061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
21071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
21101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPMax(T a, T b) {
21111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // NaNs should be handled elsewhere.
2112e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(!std::isnan(a) && !std::isnan(b));
2113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((a == 0.0) && (b == 0.0) &&
2115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (copysign(1.0, a) != copysign(1.0, b))) {
2116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // a and b are zero, and the sign differs: return +0.0.
2117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return 0.0;
2118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
2119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return (a > b) ? a : b;
2120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2124f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixltemplate <typename T>
2125f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlT Simulator::FPMaxNM(T a, T b) {
2126f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (IsQuietNaN(a) && !IsQuietNaN(b)) {
2127f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    a = kFP64NegativeInfinity;
2128f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
2129f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    b = kFP64NegativeInfinity;
2130f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
21311123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  T result = FPProcessNaNs(a, b);
2133e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  return std::isnan(result) ? result : FPMax(a, b);
2134f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
2135f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2136f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2137f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixltemplate <typename T>
2138f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlT Simulator::FPMin(T a, T b) {
21391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // NaNs should be handled elsewhere.
2140e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(!std::isnan(a) && !std::isnan(b));
2141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if ((a == 0.0) && (b == 0.0) &&
2143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      (copysign(1.0, a) != copysign(1.0, b))) {
2144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // a and b are zero, and the sign differs: return -0.0.
2145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return -0.0;
2146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
2147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    return (a < b) ? a : b;
2148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
21511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2152f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixltemplate <typename T>
2153f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlT Simulator::FPMinNM(T a, T b) {
2154f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (IsQuietNaN(a) && !IsQuietNaN(b)) {
2155f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    a = kFP64PositiveInfinity;
2156f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
2157f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    b = kFP64PositiveInfinity;
2158f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
21591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  T result = FPProcessNaNs(a, b);
2161e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  return std::isnan(result) ? result : FPMin(a, b);
21621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
21631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
21661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPMul(T op1, T op2) {
21671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // NaNs should be handled elsewhere.
2168e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(!std::isnan(op1) && !std::isnan(op2));
21691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2170e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
21711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // inf * 0.0 returns the default NaN.
21721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPProcessException();
21731123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPDefaultNaN<T>();
21741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
21751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Other cases should be handled by standard arithmetic.
21761123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return op1 * op2;
21771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
21781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
21791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate<typename T>
21821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPMulAdd(T a, T op1, T op2) {
21831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  T result = FPProcessNaNs3(a, op1, op2);
21841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
21851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  T sign_a = copysign(1.0, a);
21861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
2187e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  bool isinf_prod = std::isinf(op1) || std::isinf(op2);
21881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  bool operation_generates_nan =
2189e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers      (std::isinf(op1) && (op2 == 0.0)) ||                     // inf * 0.0
2190e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers      (std::isinf(op2) && (op1 == 0.0)) ||                     // 0.0 * inf
2191e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers      (std::isinf(a) && isinf_prod && (sign_a != sign_prod));  // inf - inf
21921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2193e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  if (std::isnan(result)) {
21941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Generated NaNs override quiet NaNs propagated from a.
21951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    if (operation_generates_nan && IsQuietNaN(a)) {
21961123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      FPProcessException();
21971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      return FPDefaultNaN<T>();
21981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    } else {
21991123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      return result;
22001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
22011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // If the operation would produce a NaN, return the default NaN.
22041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (operation_generates_nan) {
22051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPProcessException();
22061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPDefaultNaN<T>();
22071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Work around broken fma implementations for exact zero results: The sign of
22101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // exact 0.0 results is positive unless both a and op1 * op2 are negative.
22111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) {
22121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0;
22131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  result = FusedMultiplyAdd(op1, op2, a);
2216e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(!std::isnan(result));
22171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // Work around broken fma implementations for rounded zero results: If a is
22191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // 0.0, the sign of the result is the sign of op1 * op2 before rounding.
22201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if ((a == 0.0) && (result == 0.0)) {
22211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return copysign(0.0, sign_prod);
22221123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return result;
22251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
22261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
22291123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPSub(T op1, T op2) {
22301123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  // NaNs should be handled elsewhere.
2231e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(!std::isnan(op1) && !std::isnan(op2));
22321123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
2233e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) {
22341123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // inf - inf returns the default NaN.
22351123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPProcessException();
22361123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPDefaultNaN<T>();
22371123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
22381123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    // Other cases should be handled by standard arithmetic.
22391123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return op1 - op2;
22401123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22411123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
22421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22431123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22441123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
22451123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPSqrt(T op) {
2246e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  if (std::isnan(op)) {
22471123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op);
22481123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else if (op < 0.0) {
22491123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPProcessException();
22501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPDefaultNaN<T>();
22511123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
22521123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return sqrt(op);
22531123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22541123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
22551123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22571123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
22581123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPProcessNaN(T op) {
2259e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  VIXL_ASSERT(std::isnan(op));
22601123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (IsSignallingNaN(op)) {
22611123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    FPProcessException();
22621123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22631123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
22641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
22651123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22661123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22671123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
22681123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPProcessNaNs(T op1, T op2) {
22691123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (IsSignallingNaN(op1)) {
22701123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op1);
22711123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else if (IsSignallingNaN(op2)) {
22721123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op2);
2273e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  } else if (std::isnan(op1)) {
22741123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsQuietNaN(op1));
22751123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op1);
2276e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  } else if (std::isnan(op2)) {
22771123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsQuietNaN(op2));
22781123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op2);
22791123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
22801123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return 0.0;
22811123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
22821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
22831123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22841123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
22851123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixltemplate <typename T>
22861123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlT Simulator::FPProcessNaNs3(T op1, T op2, T op3) {
22871123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (IsSignallingNaN(op1)) {
22881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op1);
22891123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else if (IsSignallingNaN(op2)) {
22901123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op2);
22911123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else if (IsSignallingNaN(op3)) {
22921123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op3);
2293e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  } else if (std::isnan(op1)) {
22941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsQuietNaN(op1));
22951123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op1);
2296e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  } else if (std::isnan(op2)) {
22971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsQuietNaN(op2));
22981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op2);
2299e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers  } else if (std::isnan(op3)) {
23001123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(IsQuietNaN(op3));
23011123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return FPProcessNaN(op3);
23021123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
23031123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    return 0.0;
23041123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
23051123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl}
23061123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
23071123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
23081123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixlbool Simulator::FPProcessNaNs(Instruction* instr) {
23091123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  unsigned fd = instr->Rd();
23101123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  unsigned fn = instr->Rn();
23111123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  unsigned fm = instr->Rm();
23121123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  bool done = false;
23131123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
23141123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  if (instr->Mask(FP64) == FP64) {
23151123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    double result = FPProcessNaNs(dreg(fn), dreg(fm));
2316e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers    if (std::isnan(result)) {
23171123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      set_dreg(fd, result);
23181123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      done = true;
23191123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
23201123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  } else {
23211123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    float result = FPProcessNaNs(sreg(fn), sreg(fm));
2322e6feb7aa71ed0d2318558000aaeb46220890ad9aIan Rogers    if (std::isnan(result)) {
23231123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      set_sreg(fd, result);
23241123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      done = true;
23251123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    }
23261123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  }
23271123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
23281123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  return done;
2329f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
2330f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2331ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitSystem(Instruction* instr) {
2333ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Some system instructions hijack their Op and Cp fields to represent a
2334ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // range of immediates instead of indicating a different instruction. This
2335ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // makes the decoding tricky.
2336ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2337ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    switch (instr->Mask(SystemSysRegMask)) {
2338ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case MRS: {
2339ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        switch (instr->ImmSystemRegister()) {
2340578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
2341578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
23421123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          default: VIXL_UNIMPLEMENTED();
2343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
2344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        break;
2345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
2346ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case MSR: {
2347ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        switch (instr->ImmSystemRegister()) {
2348578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break;
2349578645f14e122d2b87d907e298cda7e7d0babf1farmvixl          case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break;
23501123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl          default: VIXL_UNIMPLEMENTED();
2351ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        }
2352ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        break;
2353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
2354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
23561123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
2357ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    switch (instr->ImmHint()) {
2358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      case NOP: break;
23591123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      default: VIXL_UNIMPLEMENTED();
2360ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2361f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2362f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    __sync_synchronize();
2363ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
23641123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl    VIXL_UNIMPLEMENTED();
2365ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2367ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2368ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2369ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::VisitException(Instruction* instr) {
2370ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (instr->Mask(ExceptionMask)) {
2371ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case BRK: HostBreakpoint(); break;
2372ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case HLT:
2373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // The Printf pseudo instruction is so useful, we include it in the
2374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // default simulator.
2375ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (instr->ImmException() == kPrintfOpcode) {
2376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        DoPrintf(instr);
2377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
2378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        HostBreakpoint();
2379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
2380ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
23821123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl      VIXL_UNIMPLEMENTED();
2383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2384ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2385ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid Simulator::DoPrintf(Instruction* instr) {
23881123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
2389ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl              (instr->ImmException() == kPrintfOpcode));
2390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2391ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Read the arguments encoded inline in the instruction stream.
2392ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  uint32_t arg_count;
2393ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  uint32_t arg_pattern_list;
23941123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl  VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
2395ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  memcpy(&arg_count,
2396ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl         instr + kPrintfArgCountOffset,
2397ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl         sizeof(arg_count));
2398ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  memcpy(&arg_pattern_list,
2399ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl         instr + kPrintfArgPatternListOffset,
2400ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl         sizeof(arg_pattern_list));
2401ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2402ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
2403ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
2404ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2405ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // We need to call the host printf function with a set of arguments defined by
2406ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // arg_pattern_list. Because we don't know the types and sizes of the
2407ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // arguments, this is very difficult to do in a robust and portable way. To
2408ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // work around the problem, we pick apart the format string, and print one
2409ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // format placeholder at a time.
2410ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2411ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Allocate space for the format string. We take a copy, so we can modify it.
2412ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Leave enough space for one extra character per expected argument (plus the
2413ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // '\0' termination).
2414ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const char * format_base = reg<const char *>(0);
2415ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_ASSERT(format_base != NULL);
2416ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  size_t length = strlen(format_base) + 1;
2417ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  char * const format = new char[length + arg_count];
2418ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2419ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // A list of chunks, each with exactly one format placeholder.
2420ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  const char * chunks[kPrintfMaxArgCount];
2421ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2422ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Copy the format string and search for format placeholders.
2423ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  uint32_t placeholder_count = 0;
2424ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  char * format_scratch = format;
2425ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  for (size_t i = 0; i < length; i++) {
2426ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    if (format_base[i] != '%') {
2427ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      *format_scratch++ = format_base[i];
2428ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    } else {
2429ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (format_base[i + 1] == '%') {
2430ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        // Ignore explicit "%%" sequences.
2431ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        *format_scratch++ = format_base[i];
2432ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        i++;
2433ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        // Chunks after the first are passed as format strings to printf, so we
2434ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        // need to escape '%' characters in those chunks.
2435ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        if (placeholder_count > 0) *format_scratch++ = format_base[i];
2436ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      } else {
2437ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        VIXL_CHECK(placeholder_count < arg_count);
2438ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        // Insert '\0' before placeholders, and store their locations.
2439ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        *format_scratch++ = '\0';
2440ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        chunks[placeholder_count++] = format_scratch;
2441ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        *format_scratch++ = format_base[i];
2442ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
2443ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
2444ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  }
2445ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  VIXL_CHECK(placeholder_count == arg_count);
2446ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2447ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Finally, call printf with each chunk, passing the appropriate register
2448ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // argument. Normally, printf returns the number of bytes transmitted, so we
2449ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // can emulate a single printf call by adding the result from each chunk. If
2450ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // any call returns a negative (error) value, though, just return that value.
2451ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2452ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  printf("%s", clr_printf);
2453ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2454ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Because '\0' is inserted before each placeholder, the first string in
2455ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // 'format' contains no format placeholders and should be printed literally.
2456ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  int result = printf("%s", format);
2457ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  int pcs_r = 1;      // Start at x1. x0 holds the format string.
2458ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  int pcs_f = 0;      // Start at d0.
2459ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  if (result >= 0) {
2460ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    for (uint32_t i = 0; i < placeholder_count; i++) {
2461ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      int part_result = -1;
2462ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2463ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
2464ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
2465ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      switch (arg_pattern) {
2466ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        case kPrintfArgW: part_result = printf(chunks[i], wreg(pcs_r++)); break;
2467ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        case kPrintfArgX: part_result = printf(chunks[i], xreg(pcs_r++)); break;
2468ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        case kPrintfArgD: part_result = printf(chunks[i], dreg(pcs_f++)); break;
2469ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        default: VIXL_UNREACHABLE();
2470ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
2471ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2472ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      if (part_result < 0) {
2473ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        // Handle error values.
2474ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        result = part_result;
2475ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl        break;
2476ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      }
2477ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2478ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl      result += part_result;
2479ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl    }
2480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2481ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2482ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  printf("%s", clr_normal);
2483ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2484ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  // Printf returns its result in x0 (just like the C library's printf).
2485ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  set_xreg(0, result);
2486ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2487ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // The printf parameters are inlined in the code, so skip them.
2488ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  set_pc(instr->InstructionAtOffset(kPrintfLength));
2489ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Set LR as if we'd just called a native printf function.
2491f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  set_lr(pc());
2492ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl
2493ae093bfb93c7d6b6cc143546a4211995a9db4ebfarmvixl  delete[] format;
2494ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
24971123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl
24981123fee00a9cef7f1b448eab3c2ca333dbd426d7armvixl#endif  // USE_SIMULATOR
2499