blob: 43b6f74bc7e47d554befabbc1bbe5eaf1dc7a34c [file] [log] [blame]
Alexandre Ramesd3832962016-07-04 15:03:43 +01001// Copyright 2015, VIXL authors
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// * Neither the name of ARM Limited nor the names of its contributors may be
13// used to endorse or promote products derived from this software without
14// specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010027#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
Alexandre Ramesd3832962016-07-04 15:03:43 +010028
Alexandre Ramesd3832962016-07-04 15:03:43 +010029#include <cmath>
Pierre Langlois1bce0072017-06-06 17:58:58 +010030#include <cstring>
Martyn Capewell5b24fb32016-11-02 18:52:55 +000031#include <limits>
Alexandre Ramesd3832962016-07-04 15:03:43 +010032
Alexandre Ramesb49bdb72016-09-26 12:08:57 +010033#include "simulator-aarch64.h"
Alexandre Ramesd3832962016-07-04 15:03:43 +010034
35namespace vixl {
36namespace aarch64 {
37
Jacob Bramleyca789742018-09-13 14:25:46 +010038using vixl::internal::SimFloat16;
39
Alexandre Ramesd3832962016-07-04 15:03:43 +010040const Instruction* Simulator::kEndOfSimAddress = NULL;
41
42void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
43 int width = msb - lsb + 1;
44 VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
45
46 bits <<= lsb;
47 uint32_t mask = ((1 << width) - 1) << lsb;
48 VIXL_ASSERT((mask & write_ignore_mask_) == 0);
49
50 value_ = (value_ & ~mask) | (bits & mask);
51}
52
53
54SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
55 switch (id) {
56 case NZCV:
57 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
58 case FPCR:
59 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
60 default:
61 VIXL_UNREACHABLE();
62 return SimSystemRegister();
63 }
64}
65
66
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010067Simulator::Simulator(Decoder* decoder, FILE* stream)
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010068 : movprfx_(NULL), cpu_features_auditor_(decoder, CPUFeatures::All()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010069 // Ensure that shift operations act as the simulator expects.
70 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
71 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
72
73 instruction_stats_ = false;
74
75 // Set up the decoder.
76 decoder_ = decoder;
77 decoder_->AppendVisitor(this);
78
79 stream_ = stream;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010080
Alexandre Ramesd3832962016-07-04 15:03:43 +010081 print_disasm_ = new PrintDisassembler(stream_);
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010082 // The Simulator and Disassembler share the same available list, held by the
83 // auditor. The Disassembler only annotates instructions with features that
84 // are _not_ available, so registering the auditor should have no effect
85 // unless the simulator is about to abort (due to missing features). In
86 // practice, this means that with trace enabled, the simulator will crash just
87 // after the disassembler prints the instruction, with the missing features
88 // enumerated.
89 print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
90
Alexandre Ramesd3832962016-07-04 15:03:43 +010091 SetColouredTrace(false);
92 trace_parameters_ = LOG_NONE;
93
Jacob Bramley9d06c4d2019-05-13 18:15:06 +010094 // We have to configure the SVE vector register length before calling
95 // ResetState().
96 SetVectorLengthInBits(kZRegMinSize);
97
Alexandre Ramesd3832962016-07-04 15:03:43 +010098 ResetState();
99
100 // Allocate and set up the simulator stack.
101 stack_ = new byte[stack_size_];
102 stack_limit_ = stack_ + stack_protection_size_;
103 // Configure the starting stack pointer.
104 // - Find the top of the stack.
105 byte* tos = stack_ + stack_size_;
106 // - There's a protection region at both ends of the stack.
107 tos -= stack_protection_size_;
108 // - The stack pointer must be 16-byte aligned.
109 tos = AlignDown(tos, 16);
110 WriteSp(tos);
111
112 instrumentation_ = NULL;
113
114 // Print a warning about exclusive-access instructions, but only the first
115 // time they are encountered. This warning can be silenced using
116 // SilenceExclusiveAccessWarning().
117 print_exclusive_access_warning_ = true;
Martyn Capewellcb963f72018-10-22 15:25:28 +0100118
119 guard_pages_ = false;
TatWai Chong04edf682018-12-27 16:01:02 -0800120
121 // Initialize the common state of RNDR and RNDRRS.
122 uint16_t seed[3] = {11, 22, 33};
123 VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rndr_state_));
124 memcpy(rndr_state_, seed, sizeof(rndr_state_));
TatWai Chongb2d8d1f2019-10-21 15:19:31 -0700125
126 // Initialize all bits of pseudo predicate register to true.
127 LogicPRegister ones(pregister_all_true_);
128 ones.SetAllBits();
Alexandre Ramesd3832962016-07-04 15:03:43 +0100129}
130
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100131void Simulator::ResetSystemRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100132 // Reset the system registers.
133 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
134 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
TatWai Chong4023d7a2019-11-18 14:16:28 -0800135 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100136}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100137
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100138void Simulator::ResetRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100139 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
140 WriteXRegister(i, 0xbadbeef);
141 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100142 // Returning to address 0 exits the Simulator.
143 WriteLr(kEndOfSimAddress);
144}
Pierre Langlois23703a72016-08-15 17:23:39 +0100145
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100146void Simulator::ResetVRegisters() {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800147 // Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100148 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
149 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
TatWai Chonge3d059b2019-02-27 15:04:51 -0800150 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100151 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100152 vregisters_[i].NotifyAccessAsZ();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100153 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800154 // Encode the register number and (D-sized) lane into each NaN, to
155 // make them easier to trace.
156 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
157 (0x0000000000000001 * lane);
158 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
159 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100160 vregisters_[i].Insert(lane, nan_bits);
TatWai Chonge3d059b2019-02-27 15:04:51 -0800161 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100162 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100163}
TatWai Chonge3d059b2019-02-27 15:04:51 -0800164
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100165void Simulator::ResetPRegisters() {
166 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
167 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
168 // Ensure the register configuration fits in this bit encoding.
169 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
170 VIXL_ASSERT(lane_count <= UINT8_MAX);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700171 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100172 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
173 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge0590cc2019-03-18 16:23:59 -0700174 // Encode the register number and (H-sized) lane into each lane slot.
175 uint16_t bits = (0x0100 * lane) | i;
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100176 pregisters_[i].Insert(lane, bits);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700177 }
178 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100179}
TatWai Chonge0590cc2019-03-18 16:23:59 -0700180
TatWai Chong4023d7a2019-11-18 14:16:28 -0800181void Simulator::ResetFFR() {
182 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
183 int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
184 ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
185}
186
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100187void Simulator::ResetState() {
188 ResetSystemRegisters();
189 ResetRegisters();
190 ResetVRegisters();
191 ResetPRegisters();
Martyn Capewellcb963f72018-10-22 15:25:28 +0100192
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100193 pc_ = NULL;
194 pc_modified_ = false;
195
196 // BTI state.
Martyn Capewellcb963f72018-10-22 15:25:28 +0100197 btype_ = DefaultBType;
198 next_btype_ = DefaultBType;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100199}
200
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100201void Simulator::SetVectorLengthInBits(unsigned vector_length) {
202 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
203 (vector_length <= kZRegMaxSize));
204 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
205 vector_length_ = vector_length;
206
207 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
208 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
209 }
210 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
211 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
212 }
213
TatWai Chong4023d7a2019-11-18 14:16:28 -0800214 ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
215
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100216 ResetVRegisters();
217 ResetPRegisters();
TatWai Chong4023d7a2019-11-18 14:16:28 -0800218 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100219}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100220
221Simulator::~Simulator() {
222 delete[] stack_;
223 // The decoder may outlive the simulator.
224 decoder_->RemoveVisitor(print_disasm_);
225 delete print_disasm_;
226
227 decoder_->RemoveVisitor(instrumentation_);
228 delete instrumentation_;
229}
230
231
232void Simulator::Run() {
233 // Flush any written registers before executing anything, so that
234 // manually-set registers are logged _before_ the first instruction.
235 LogAllWrittenRegisters();
236
237 while (pc_ != kEndOfSimAddress) {
238 ExecuteInstruction();
239 }
240}
241
242
243void Simulator::RunFrom(const Instruction* first) {
Jacob Bramleye79723a2016-06-07 17:50:47 +0100244 WritePc(first, NoBranchLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100245 Run();
246}
247
248
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100249// clang-format off
Alexandre Ramesd3832962016-07-04 15:03:43 +0100250const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
251 "x6", "x7", "x8", "x9", "x10", "x11",
252 "x12", "x13", "x14", "x15", "x16", "x17",
253 "x18", "x19", "x20", "x21", "x22", "x23",
254 "x24", "x25", "x26", "x27", "x28", "x29",
255 "lr", "xzr", "sp"};
256
257const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
258 "w6", "w7", "w8", "w9", "w10", "w11",
259 "w12", "w13", "w14", "w15", "w16", "w17",
260 "w18", "w19", "w20", "w21", "w22", "w23",
261 "w24", "w25", "w26", "w27", "w28", "w29",
262 "w30", "wzr", "wsp"};
263
Jacob Bramley423e5422019-11-13 19:15:55 +0000264const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",
265 "b6", "b7", "b8", "b9", "b10", "b11",
266 "b12", "b13", "b14", "b15", "b16", "b17",
267 "b18", "b19", "b20", "b21", "b22", "b23",
268 "b24", "b25", "b26", "b27", "b28", "b29",
269 "b30", "b31"};
270
Carey Williamsd8bb3572018-04-10 11:58:07 +0100271const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
272 "h6", "h7", "h8", "h9", "h10", "h11",
273 "h12", "h13", "h14", "h15", "h16", "h17",
274 "h18", "h19", "h20", "h21", "h22", "h23",
275 "h24", "h25", "h26", "h27", "h28", "h29",
276 "h30", "h31"};
277
Alexandre Ramesd3832962016-07-04 15:03:43 +0100278const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
279 "s6", "s7", "s8", "s9", "s10", "s11",
280 "s12", "s13", "s14", "s15", "s16", "s17",
281 "s18", "s19", "s20", "s21", "s22", "s23",
282 "s24", "s25", "s26", "s27", "s28", "s29",
283 "s30", "s31"};
284
285const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
286 "d6", "d7", "d8", "d9", "d10", "d11",
287 "d12", "d13", "d14", "d15", "d16", "d17",
288 "d18", "d19", "d20", "d21", "d22", "d23",
289 "d24", "d25", "d26", "d27", "d28", "d29",
290 "d30", "d31"};
291
292const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
293 "v6", "v7", "v8", "v9", "v10", "v11",
294 "v12", "v13", "v14", "v15", "v16", "v17",
295 "v18", "v19", "v20", "v21", "v22", "v23",
296 "v24", "v25", "v26", "v27", "v28", "v29",
297 "v30", "v31"};
298
TatWai Chong72d2e562019-05-16 11:22:22 -0700299const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
300 "z6", "z7", "z8", "z9", "z10", "z11",
301 "z12", "z13", "z14", "z15", "z16", "z17",
302 "z18", "z19", "z20", "z21", "z22", "z23",
303 "z24", "z25", "z26", "z27", "z28", "z29",
304 "z30", "z31"};
305
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100306const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
307 "p6", "p7", "p8", "p9", "p10", "p11",
308 "p12", "p13", "p14", "p15"};
309// clang-format on
310
Alexandre Ramesd3832962016-07-04 15:03:43 +0100311
312const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100313 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000314 if ((code == kSPRegInternalCode) ||
315 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100316 code = kZeroRegCode + 1;
317 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000318 VIXL_ASSERT(code < ArrayLength(wreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100319 return wreg_names[code];
320}
321
322
323const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100324 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000325 if ((code == kSPRegInternalCode) ||
326 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100327 code = kZeroRegCode + 1;
328 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000329 VIXL_ASSERT(code < ArrayLength(xreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100330 return xreg_names[code];
331}
332
333
Jacob Bramley423e5422019-11-13 19:15:55 +0000334const char* Simulator::BRegNameForCode(unsigned code) {
335 VIXL_ASSERT(code < kNumberOfVRegisters);
336 return breg_names[code];
337}
338
339
Carey Williamsd8bb3572018-04-10 11:58:07 +0100340const char* Simulator::HRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100341 VIXL_ASSERT(code < kNumberOfVRegisters);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100342 return hreg_names[code];
343}
344
345
Alexandre Ramesd3832962016-07-04 15:03:43 +0100346const char* Simulator::SRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100347 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100348 return sreg_names[code];
349}
350
351
352const char* Simulator::DRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100353 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100354 return dreg_names[code];
355}
356
357
358const char* Simulator::VRegNameForCode(unsigned code) {
359 VIXL_ASSERT(code < kNumberOfVRegisters);
360 return vreg_names[code];
361}
362
363
TatWai Chong72d2e562019-05-16 11:22:22 -0700364const char* Simulator::ZRegNameForCode(unsigned code) {
365 VIXL_ASSERT(code < kNumberOfZRegisters);
366 return zreg_names[code];
367}
368
369
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100370const char* Simulator::PRegNameForCode(unsigned code) {
371 VIXL_ASSERT(code < kNumberOfPRegisters);
372 return preg_names[code];
373}
374
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000375SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
376 SimVRegister ones, result;
377 dup_immediate(kFormatVnB, ones, 0xff);
378 mov_zeroing(kFormatVnB, result, pg, ones);
379 return result;
380}
381
382void Simulator::ExtractFromSimVRegister(SimPRegister& pd, SimVRegister vreg) {
383 SimVRegister zero;
384 dup_immediate(kFormatVnB, zero, 0);
385 SVEIntCompareVectorsHelper(ne,
386 kFormatVnB,
387 pd,
388 GetPTrue(),
389 vreg,
390 zero,
391 false,
392 LeaveFlags);
393}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100394
Alexandre Ramesd3832962016-07-04 15:03:43 +0100395#define COLOUR(colour_code) "\033[0;" colour_code "m"
396#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
Jacob Bramleye79723a2016-06-07 17:50:47 +0100397#define COLOUR_HIGHLIGHT "\033[43m"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100398#define NORMAL ""
399#define GREY "30"
400#define RED "31"
401#define GREEN "32"
402#define YELLOW "33"
403#define BLUE "34"
404#define MAGENTA "35"
405#define CYAN "36"
406#define WHITE "37"
407void Simulator::SetColouredTrace(bool value) {
408 coloured_trace_ = value;
409
410 clr_normal = value ? COLOUR(NORMAL) : "";
411 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
412 clr_flag_value = value ? COLOUR(NORMAL) : "";
413 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
414 clr_reg_value = value ? COLOUR(CYAN) : "";
415 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
416 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100417 clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
418 clr_preg_value = value ? COLOUR(GREEN) : "";
Alexandre Ramesd3832962016-07-04 15:03:43 +0100419 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
420 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
421 clr_warning_message = value ? COLOUR(YELLOW) : "";
422 clr_printf = value ? COLOUR(GREEN) : "";
Jacob Bramleye79723a2016-06-07 17:50:47 +0100423 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100424
425 if (value) {
426 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
427 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
428 } else {
429 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
430 print_disasm_->SetCPUFeaturesSuffix("");
431 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100432}
433
434
435void Simulator::SetTraceParameters(int parameters) {
436 bool disasm_before = trace_parameters_ & LOG_DISASM;
437 trace_parameters_ = parameters;
438 bool disasm_after = trace_parameters_ & LOG_DISASM;
439
440 if (disasm_before != disasm_after) {
441 if (disasm_after) {
442 decoder_->InsertVisitorBefore(print_disasm_, this);
443 } else {
444 decoder_->RemoveVisitor(print_disasm_);
445 }
446 }
447}
448
449
450void Simulator::SetInstructionStats(bool value) {
451 if (value != instruction_stats_) {
452 if (value) {
453 if (instrumentation_ == NULL) {
454 // Set the sample period to 10, as the VIXL examples and tests are
455 // short.
456 instrumentation_ = new Instrument("vixl_stats.csv", 10);
457 }
458 decoder_->AppendVisitor(instrumentation_);
459 } else if (instrumentation_ != NULL) {
460 decoder_->RemoveVisitor(instrumentation_);
461 }
462 instruction_stats_ = value;
463 }
464}
465
466// Helpers ---------------------------------------------------------------------
467uint64_t Simulator::AddWithCarry(unsigned reg_size,
468 bool set_flags,
469 uint64_t left,
470 uint64_t right,
471 int carry_in) {
472 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
473 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
474
475 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
476 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
477 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
478
479 left &= reg_mask;
480 right &= reg_mask;
481 uint64_t result = (left + right + carry_in) & reg_mask;
482
483 if (set_flags) {
484 ReadNzcv().SetN(CalcNFlag(result, reg_size));
485 ReadNzcv().SetZ(CalcZFlag(result));
486
487 // Compute the C flag by comparing the result to the max unsigned integer.
488 uint64_t max_uint_2op = max_uint - carry_in;
489 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
490 ReadNzcv().SetC(C ? 1 : 0);
491
492 // Overflow iff the sign bit is the same for the two inputs and different
493 // for the result.
494 uint64_t left_sign = left & sign_mask;
495 uint64_t right_sign = right & sign_mask;
496 uint64_t result_sign = result & sign_mask;
497 bool V = (left_sign == right_sign) && (left_sign != result_sign);
498 ReadNzcv().SetV(V ? 1 : 0);
499
500 LogSystemRegister(NZCV);
501 }
502 return result;
503}
504
505
506int64_t Simulator::ShiftOperand(unsigned reg_size,
507 int64_t value,
508 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100509 unsigned amount) const {
TatWai Chong29a0c432019-11-06 22:20:44 -0800510 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
511 (reg_size == kSRegSize) || (reg_size == kDRegSize));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100512 if (amount == 0) {
513 return value;
514 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000515
TatWai Chong29a0c432019-11-06 22:20:44 -0800516 uint64_t uvalue = static_cast<uint64_t>(value);
517 uint64_t mask = GetUintMask(reg_size);
518 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
519 // The behavior is undefined in c++ if the shift amount greater than or equal
520 // to the register lane size. Work out the shifted result based on
521 // architectural behavior before performing the c++ type shfit operations.
Alexandre Ramesd3832962016-07-04 15:03:43 +0100522 switch (shift_type) {
523 case LSL:
TatWai Chong29a0c432019-11-06 22:20:44 -0800524 if (amount >= reg_size) {
525 return UINT64_C(0);
526 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000527 uvalue <<= amount;
528 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100529 case LSR:
TatWai Chong29a0c432019-11-06 22:20:44 -0800530 if (amount >= reg_size) {
531 return UINT64_C(0);
532 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000533 uvalue >>= amount;
534 break;
535 case ASR:
TatWai Chong29a0c432019-11-06 22:20:44 -0800536 if (amount >= reg_size) {
537 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
538 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000539 uvalue >>= amount;
540 if (is_negative) {
541 // Simulate sign-extension to 64 bits.
542 uvalue |= ~UINT64_C(0) << (reg_size - amount);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100543 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000544 break;
545 case ROR: {
Martyn Capewellfb8e3df2016-11-03 15:50:19 +0000546 uvalue = RotateRight(uvalue, amount, reg_size);
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000547 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100548 }
549 default:
550 VIXL_UNIMPLEMENTED();
551 return 0;
552 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000553 uvalue &= mask;
554
555 int64_t result;
556 memcpy(&result, &uvalue, sizeof(result));
557 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100558}
559
560
561int64_t Simulator::ExtendValue(unsigned reg_size,
562 int64_t value,
563 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100564 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100565 switch (extend_type) {
566 case UXTB:
567 value &= kByteMask;
568 break;
569 case UXTH:
570 value &= kHalfWordMask;
571 break;
572 case UXTW:
573 value &= kWordMask;
574 break;
575 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000576 value &= kByteMask;
577 if ((value & 0x80) != 0) {
578 value |= ~UINT64_C(0) << 8;
579 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100580 break;
581 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000582 value &= kHalfWordMask;
583 if ((value & 0x8000) != 0) {
584 value |= ~UINT64_C(0) << 16;
585 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100586 break;
587 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000588 value &= kWordMask;
589 if ((value & 0x80000000) != 0) {
590 value |= ~UINT64_C(0) << 32;
591 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100592 break;
593 case UXTX:
594 case SXTX:
595 break;
596 default:
597 VIXL_UNREACHABLE();
598 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000599 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100600}
601
602
603void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
604 AssertSupportedFPCR();
605
606 // TODO: This assumes that the C++ implementation handles comparisons in the
607 // way that we expect (as per AssertSupportedFPCR()).
608 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100609 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100610 ReadNzcv().SetRawValue(FPUnorderedFlag);
611 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
612 (trap == EnableTrap)) {
613 process_exception = true;
614 }
615 } else if (val0 < val1) {
616 ReadNzcv().SetRawValue(FPLessThanFlag);
617 } else if (val0 > val1) {
618 ReadNzcv().SetRawValue(FPGreaterThanFlag);
619 } else if (val0 == val1) {
620 ReadNzcv().SetRawValue(FPEqualFlag);
621 } else {
622 VIXL_UNREACHABLE();
623 }
624 LogSystemRegister(NZCV);
625 if (process_exception) FPProcessException();
626}
627
628
Alexandre Rames868bfc42016-07-19 17:10:48 +0100629uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
630 VIXL_ASSERT(mem_op.IsValid());
631 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
632 if (mem_op.IsImmediateOffset()) {
633 return base + mem_op.GetOffset();
634 } else {
635 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
636 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100637 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100638 if (mem_op.GetShift() != NO_SHIFT) {
639 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
640 }
641 if (mem_op.GetExtend() != NO_EXTEND) {
642 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
643 }
644 return static_cast<uint64_t>(base + offset);
645 }
646}
647
648
Alexandre Ramesd3832962016-07-04 15:03:43 +0100649Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
650 unsigned reg_size, unsigned lane_size) {
651 VIXL_ASSERT(reg_size >= lane_size);
652
653 uint32_t format = 0;
654 if (reg_size != lane_size) {
655 switch (reg_size) {
656 default:
657 VIXL_UNREACHABLE();
658 break;
659 case kQRegSizeInBytes:
660 format = kPrintRegAsQVector;
661 break;
662 case kDRegSizeInBytes:
663 format = kPrintRegAsDVector;
664 break;
665 }
666 }
667
668 switch (lane_size) {
669 default:
670 VIXL_UNREACHABLE();
671 break;
672 case kQRegSizeInBytes:
673 format |= kPrintReg1Q;
674 break;
675 case kDRegSizeInBytes:
676 format |= kPrintReg1D;
677 break;
678 case kSRegSizeInBytes:
679 format |= kPrintReg1S;
680 break;
681 case kHRegSizeInBytes:
682 format |= kPrintReg1H;
683 break;
684 case kBRegSizeInBytes:
685 format |= kPrintReg1B;
686 break;
687 }
688 // These sizes would be duplicate case labels.
689 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
690 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
691 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
692 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
693
694 return static_cast<PrintRegisterFormat>(format);
695}
696
697
698Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
699 VectorFormat vform) {
700 switch (vform) {
701 default:
702 VIXL_UNREACHABLE();
703 return kPrintReg16B;
704 case kFormat16B:
705 return kPrintReg16B;
706 case kFormat8B:
707 return kPrintReg8B;
708 case kFormat8H:
709 return kPrintReg8H;
710 case kFormat4H:
711 return kPrintReg4H;
712 case kFormat4S:
713 return kPrintReg4S;
714 case kFormat2S:
715 return kPrintReg2S;
716 case kFormat2D:
717 return kPrintReg2D;
718 case kFormat1D:
719 return kPrintReg1D;
720
721 case kFormatB:
722 return kPrintReg1B;
723 case kFormatH:
724 return kPrintReg1H;
725 case kFormatS:
726 return kPrintReg1S;
727 case kFormatD:
728 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +0100729
730 case kFormatVnB:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000731 return kPrintRegVnB;
Jacob Bramleye668b202019-08-14 17:57:34 +0100732 case kFormatVnH:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000733 return kPrintRegVnH;
Jacob Bramleye668b202019-08-14 17:57:34 +0100734 case kFormatVnS:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000735 return kPrintRegVnS;
Jacob Bramleye668b202019-08-14 17:57:34 +0100736 case kFormatVnD:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000737 return kPrintRegVnD;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100738 }
739}
740
741
742Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
743 VectorFormat vform) {
744 switch (vform) {
745 default:
746 VIXL_UNREACHABLE();
747 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100748 case kFormat8H:
749 return kPrintReg8HFP;
750 case kFormat4H:
751 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100752 case kFormat4S:
753 return kPrintReg4SFP;
754 case kFormat2S:
755 return kPrintReg2SFP;
756 case kFormat2D:
757 return kPrintReg2DFP;
758 case kFormat1D:
759 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100760 case kFormatH:
761 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100762 case kFormatS:
763 return kPrintReg1SFP;
764 case kFormatD:
765 return kPrintReg1DFP;
766 }
767}
768
Jacob Bramley423e5422019-11-13 19:15:55 +0000769void Simulator::PrintRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100770 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
Jacob Bramley423e5422019-11-13 19:15:55 +0000771 if (i == kSpRegCode) i = kSPRegInternalCode;
772 PrintRegister(i);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100773 }
774}
775
Jacob Bramley423e5422019-11-13 19:15:55 +0000776void Simulator::PrintVRegisters() {
777 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
778 PrintVRegister(i);
779 }
780}
781
782void Simulator::PrintZRegisters() {
783 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
784 PrintZRegister(i);
785 }
786}
787
788void Simulator::PrintWrittenRegisters() {
789 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
790 if (registers_[i].WrittenSinceLastLog()) {
791 if (i == kSpRegCode) i = kSPRegInternalCode;
792 PrintRegister(i);
793 }
794 }
795}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100796
797void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100798 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100799 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100800 if (vregisters_[i].WrittenSinceLastLog()) {
801 // Z registers are initialised in the constructor before the user can
802 // configure the CPU features, so we must also check for SVE here.
803 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
804 PrintZRegister(i);
805 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +0000806 PrintVRegister(i);
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100807 }
808 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100809 }
810}
811
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100812void Simulator::PrintWrittenPRegisters() {
813 // P registers are initialised in the constructor before the user can
814 // configure the CPU features, so we must check for SVE here.
815 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
816 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
817 if (pregisters_[i].WrittenSinceLastLog()) {
818 PrintPRegister(i);
819 }
820 }
821}
822
Alexandre Ramesd3832962016-07-04 15:03:43 +0100823void Simulator::PrintSystemRegisters() {
824 PrintSystemRegister(NZCV);
825 PrintSystemRegister(FPCR);
826}
827
Jacob Bramley423e5422019-11-13 19:15:55 +0000828void Simulator::PrintRegisterValue(const uint8_t* value,
829 int value_size,
830 PrintRegisterFormat format) {
831 int print_width = GetPrintRegSizeInBytes(format);
832 VIXL_ASSERT(print_width <= value_size);
833 for (int i = value_size - 1; i >= print_width; i--) {
834 // Pad with spaces so that values align vertically.
Alexandre Ramesd3832962016-07-04 15:03:43 +0100835 fprintf(stream_, " ");
Jacob Bramley423e5422019-11-13 19:15:55 +0000836 // If we aren't explicitly printing a partial value, ensure that the
837 // unprinted bits are zero.
838 VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100839 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100840 fprintf(stream_, "0x");
Jacob Bramley423e5422019-11-13 19:15:55 +0000841 for (int i = print_width - 1; i >= 0; i--) {
842 fprintf(stream_, "%02x", value[i]);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100843 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100844}
845
Jacob Bramley423e5422019-11-13 19:15:55 +0000846void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
847 uint16_t lane_mask,
848 PrintRegisterFormat format) {
849 VIXL_ASSERT((format & kPrintRegAsFP) != 0);
850 int lane_size = GetPrintRegLaneSizeInBytes(format);
851 fprintf(stream_, " (");
852 bool last_inactive = false;
853 const char* sep = "";
854 for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
855 bool access = (lane_mask & (1 << (i * lane_size))) != 0;
856 if (access) {
857 // Read the lane as a double, so we can format all FP types in the same
858 // way. We squash NaNs, and a double can exactly represent any other value
859 // that the smaller types can represent, so this is lossless.
860 double element;
861 switch (lane_size) {
862 case kHRegSizeInBytes: {
863 Float16 element_fp16;
864 VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
865 memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
866 element = FPToDouble(element_fp16, kUseDefaultNaN);
867 break;
868 }
869 case kSRegSizeInBytes: {
870 float element_fp32;
871 memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
872 element = static_cast<double>(element_fp32);
873 break;
874 }
875 case kDRegSizeInBytes: {
876 memcpy(&element, &value[i * lane_size], sizeof(element));
877 break;
878 }
879 default:
880 VIXL_UNREACHABLE();
881 fprintf(stream_, "{UnknownFPValue}");
882 continue;
883 }
884 if (IsNaN(element)) {
885 // The fprintf behaviour for NaNs is implementation-defined. Always
886 // print "nan", so that traces are consistent.
887 fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
888 } else {
889 fprintf(stream_,
890 "%s%s%#.4g%s",
891 sep,
892 clr_vreg_value,
893 element,
894 clr_normal);
895 }
896 last_inactive = false;
897 } else if (!last_inactive) {
898 // Replace each contiguous sequence of inactive lanes with "...".
899 fprintf(stream_, "%s...", sep);
900 last_inactive = true;
901 }
902 }
903 fprintf(stream_, ")");
904}
905
906void Simulator::PrintRegister(int code,
907 PrintRegisterFormat format,
908 const char* suffix) {
909 VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
910 (static_cast<unsigned>(code) == kSPRegInternalCode));
911 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
912 VIXL_ASSERT((format & kPrintRegAsFP) == 0);
913
914 SimRegister* reg;
915 SimRegister zero;
916 if (code == kZeroRegCode) {
917 reg = &zero;
918 } else {
919 // registers_[31] holds the SP.
920 VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
921 reg = &registers_[code % kNumberOfRegisters];
922 }
923
924 // We trace register writes as whole register values, implying that any
925 // unprinted bits are all zero:
926 // "# x{code}: 0x{-----value----}"
927 // "# w{code}: 0x{-value}"
928 // Stores trace partial register values, implying nothing about the unprinted
929 // bits:
930 // "# x{code}<63:0>: 0x{-----value----}"
931 // "# x{code}<31:0>: 0x{-value}"
932 // "# x{code}<15:0>: 0x{--}"
933 // "# x{code}<7:0>: 0x{}"
934
935 bool is_partial = (format & kPrintRegPartial) != 0;
936 unsigned print_reg_size = GetPrintRegSizeInBits(format);
937 std::stringstream name;
938 if (is_partial) {
939 name << XRegNameForCode(code) << GetPartialRegSuffix(format);
940 } else {
941 // Notify the register that it has been logged, but only if we're printing
942 // all of it.
943 reg->NotifyRegisterLogged();
944 switch (print_reg_size) {
945 case kWRegSize:
946 name << WRegNameForCode(code);
947 break;
948 case kXRegSize:
949 name << XRegNameForCode(code);
950 break;
951 default:
952 VIXL_UNREACHABLE();
953 return;
954 }
955 }
956
957 fprintf(stream_,
958 "# %s%*s: %s",
959 clr_reg_name,
960 kPrintRegisterNameFieldWidth,
961 name.str().c_str(),
962 clr_reg_value);
963 PrintRegisterValue(*reg, format);
964 fprintf(stream_, "%s%s", clr_normal, suffix);
965}
966
967void Simulator::PrintVRegister(int code,
968 PrintRegisterFormat format,
969 const char* suffix) {
970 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
971 VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
972 ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
973 ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
974
975 // We trace register writes as whole register values, implying that any
976 // unprinted bits are all zero:
977 // "# v{code}: 0x{-------------value------------}"
978 // "# d{code}: 0x{-----value----}"
979 // "# s{code}: 0x{-value}"
980 // "# h{code}: 0x{--}"
981 // "# b{code}: 0x{}"
982 // Stores trace partial register values, implying nothing about the unprinted
983 // bits:
984 // "# v{code}<127:0>: 0x{-------------value------------}"
985 // "# v{code}<63:0>: 0x{-----value----}"
986 // "# v{code}<31:0>: 0x{-value}"
987 // "# v{code}<15:0>: 0x{--}"
988 // "# v{code}<7:0>: 0x{}"
989
990 bool is_partial = ((format & kPrintRegPartial) != 0);
991 std::stringstream name;
992 unsigned print_reg_size = GetPrintRegSizeInBits(format);
993 if (is_partial) {
994 name << VRegNameForCode(code) << GetPartialRegSuffix(format);
995 } else {
996 // Notify the register that it has been logged, but only if we're printing
997 // all of it.
998 vregisters_[code].NotifyRegisterLogged();
999 switch (print_reg_size) {
1000 case kBRegSize:
1001 name << BRegNameForCode(code);
1002 break;
1003 case kHRegSize:
1004 name << HRegNameForCode(code);
1005 break;
1006 case kSRegSize:
1007 name << SRegNameForCode(code);
1008 break;
1009 case kDRegSize:
1010 name << DRegNameForCode(code);
1011 break;
1012 case kQRegSize:
1013 name << VRegNameForCode(code);
1014 break;
1015 default:
1016 VIXL_UNREACHABLE();
1017 return;
1018 }
1019 }
1020
1021 fprintf(stream_,
1022 "# %s%*s: %s",
1023 clr_vreg_name,
1024 kPrintRegisterNameFieldWidth,
1025 name.str().c_str(),
1026 clr_vreg_value);
1027 PrintRegisterValue(vregisters_[code], format);
1028 fprintf(stream_, "%s", clr_normal);
1029 if ((format & kPrintRegAsFP) != 0) {
1030 PrintRegisterValueFPAnnotations(vregisters_[code], format);
1031 }
1032 fprintf(stream_, "%s", suffix);
1033}
1034
1035void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1036 int reg_count,
1037 uint16_t focus_mask,
1038 PrintRegisterFormat format) {
1039 bool print_fp = (format & kPrintRegAsFP) != 0;
1040 // Suppress FP formatting, so we can specify the lanes we're interested in.
1041 PrintRegisterFormat format_no_fp =
1042 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1043
1044 for (int r = 0; r < reg_count; r++) {
1045 int code = (rt_code + r) % kNumberOfVRegisters;
1046 PrintVRegister(code, format_no_fp, "");
1047 if (print_fp) {
1048 PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1049 }
1050 fprintf(stream_, "\n");
1051 }
1052}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001053
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001054void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1055 int q_index,
1056 int reg_count,
1057 uint16_t focus_mask,
1058 PrintRegisterFormat format) {
1059 bool print_fp = (format & kPrintRegAsFP) != 0;
1060 // Suppress FP formatting, so we can specify the lanes we're interested in.
1061 PrintRegisterFormat format_no_fp =
1062 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
TatWai Chong72d2e562019-05-16 11:22:22 -07001063
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001064 PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
TatWai Chong72d2e562019-05-16 11:22:22 -07001065
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001066 const unsigned size = kQRegSizeInBytes;
1067 unsigned byte_index = q_index * size;
1068 const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1069 VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
TatWai Chong72d2e562019-05-16 11:22:22 -07001070
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001071 for (int r = 0; r < reg_count; r++) {
1072 int code = (rt_code + r) % kNumberOfZRegisters;
1073 PrintPartialZRegister(code, q_index, format_no_fp, "");
1074 if (print_fp) {
1075 PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
TatWai Chong72d2e562019-05-16 11:22:22 -07001076 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001077 fprintf(stream_, "\n");
TatWai Chong72d2e562019-05-16 11:22:22 -07001078 }
TatWai Chong72d2e562019-05-16 11:22:22 -07001079}
1080
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001081void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1082 // We're going to print the register in parts, so force a partial format.
1083 format = GetPrintRegPartial(format);
1084 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1085 int vl = GetVectorLengthInBits();
1086 VIXL_ASSERT((vl % kQRegSize) == 0);
1087 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1088 PrintPartialZRegister(code, i, format);
1089 }
1090 vregisters_[code].NotifyRegisterLogged();
1091}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001092
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001093void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1094 // We're going to print the register in parts, so force a partial format.
1095 format = GetPrintRegPartial(format);
1096 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1097 int vl = GetVectorLengthInBits();
1098 VIXL_ASSERT((vl % kQRegSize) == 0);
1099 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1100 PrintPartialPRegister(code, i, format);
1101 }
1102 pregisters_[code].NotifyRegisterLogged();
1103}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001104
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001105void Simulator::PrintPartialZRegister(int code,
1106 int q_index,
1107 PrintRegisterFormat format,
1108 const char* suffix) {
1109 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1110 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1111 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1112 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001113
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001114 // We _only_ trace partial Z register values in Q-sized chunks, because
1115 // they're often too large to reasonably fit on a single line. Each line
1116 // implies nothing about the unprinted bits.
1117 // "# z{code}<127:0>: 0x{-------------value------------}"
1118
1119 format = GetPrintRegAsQChunkOfSVE(format);
1120
1121 const unsigned size = kQRegSizeInBytes;
1122 unsigned byte_index = q_index * size;
1123 const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1124 VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1125
1126 int lsb = q_index * kQRegSize;
1127 int msb = lsb + kQRegSize - 1;
1128 std::stringstream name;
1129 name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001130
1131 fprintf(stream_,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001132 "# %s%*s: %s",
1133 clr_vreg_name,
1134 kPrintRegisterNameFieldWidth,
1135 name.str().c_str(),
1136 clr_vreg_value);
1137 PrintRegisterValue(value, size, format);
1138 fprintf(stream_, "%s", clr_normal);
1139 if ((format & kPrintRegAsFP) != 0) {
1140 PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1141 }
1142 fprintf(stream_, "%s", suffix);
1143}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001144
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001145void Simulator::PrintPartialPRegister(int code,
1146 int q_index,
1147 PrintRegisterFormat format,
1148 const char* suffix) {
1149 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1150 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1151 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1152 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1153
1154 // We don't currently use the format for anything here.
1155 USE(format);
1156
1157 // We _only_ trace partial P register values, because they're often too large
1158 // to reasonably fit on a single line. Each line implies nothing about the
1159 // unprinted bits.
1160 //
1161 // We print values in binary, with spaces between each bit, in order for the
1162 // bits to align with the Z register bytes that they predicate.
1163 // "# p{code}<15:0>: 0b{-------------value------------}"
1164
1165 int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1166 int lsb = q_index * print_size_in_bits;
1167 int msb = lsb + print_size_in_bits - 1;
1168 std::stringstream name;
1169 name << PRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
1170
1171 fprintf(stream_,
1172 "# %s%*s: %s0b",
1173 clr_preg_name,
1174 kPrintRegisterNameFieldWidth,
1175 name.str().c_str(),
1176 clr_preg_value);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001177 for (int i = msb; i >= lsb; i--) {
1178 fprintf(stream_, " %c", pregisters_[code].GetBit(i) ? '1' : '0');
1179 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001180 fprintf(stream_, "%s%s", clr_normal, suffix);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001181}
1182
Alexandre Ramesd3832962016-07-04 15:03:43 +01001183void Simulator::PrintSystemRegister(SystemRegister id) {
1184 switch (id) {
1185 case NZCV:
1186 fprintf(stream_,
1187 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1188 clr_flag_name,
1189 clr_flag_value,
1190 ReadNzcv().GetN(),
1191 ReadNzcv().GetZ(),
1192 ReadNzcv().GetC(),
1193 ReadNzcv().GetV(),
1194 clr_normal);
1195 break;
1196 case FPCR: {
1197 static const char* rmode[] = {"0b00 (Round to Nearest)",
1198 "0b01 (Round towards Plus Infinity)",
1199 "0b10 (Round towards Minus Infinity)",
1200 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001201 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001202 fprintf(stream_,
1203 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1204 clr_flag_name,
1205 clr_flag_value,
1206 ReadFpcr().GetAHP(),
1207 ReadFpcr().GetDN(),
1208 ReadFpcr().GetFZ(),
1209 rmode[ReadFpcr().GetRMode()],
1210 clr_normal);
1211 break;
1212 }
1213 default:
1214 VIXL_UNREACHABLE();
1215 }
1216}
1217
Jacob Bramley423e5422019-11-13 19:15:55 +00001218uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1219 uint16_t future_access_mask,
1220 int struct_element_count,
1221 int lane_size_in_bytes,
1222 const char* op,
1223 uintptr_t address,
1224 int reg_size_in_bytes) {
1225 // We want to assume that we'll access at least one lane.
1226 VIXL_ASSERT(access_mask != 0);
1227 VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1228 (reg_size_in_bytes == kQRegSizeInBytes));
1229 bool started_annotation = false;
1230 // Indent to match the register field, the fixed formatting, and the value
1231 // prefix ("0x"): "# {name}: 0x"
1232 fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1233 // First, annotate the lanes (byte by byte).
1234 for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1235 bool access = (access_mask & (1 << lane)) != 0;
1236 bool future = (future_access_mask & (1 << lane)) != 0;
1237 if (started_annotation) {
1238 // If we've started an annotation, draw a horizontal line in addition to
1239 // any other symbols.
1240 if (access) {
1241 fprintf(stream_, "─╨");
1242 } else if (future) {
1243 fprintf(stream_, "─║");
1244 } else {
1245 fprintf(stream_, "──");
1246 }
1247 } else {
1248 if (access) {
1249 started_annotation = true;
1250 fprintf(stream_, " â•™");
1251 } else if (future) {
1252 fprintf(stream_, " â•‘");
1253 } else {
1254 fprintf(stream_, " ");
1255 }
1256 }
1257 }
1258 VIXL_ASSERT(started_annotation);
1259 fprintf(stream_, "─ 0x");
1260 int lane_size_in_nibbles = lane_size_in_bytes * 2;
1261 // Print the most-significant struct element first.
1262 const char* sep = "";
1263 for (int i = struct_element_count - 1; i >= 0; i--) {
1264 int offset = lane_size_in_bytes * i;
1265 uint64_t nibble = Memory::Read(lane_size_in_bytes, address + offset);
1266 fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1267 sep = "'";
1268 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001269 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001270 " %s %s0x%016" PRIxPTR "%s\n",
1271 op,
1272 clr_memory_address,
1273 address,
1274 clr_normal);
1275 return future_access_mask & ~access_mask;
1276}
1277
1278void Simulator::PrintAccess(int code,
1279 PrintRegisterFormat format,
1280 const char* op,
1281 uintptr_t address) {
1282 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1283 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1284 if ((format & kPrintRegPartial) == 0) {
1285 registers_[code].NotifyRegisterLogged();
1286 }
1287 // Scalar-format accesses use a simple format:
1288 // "# {reg}: 0x{value} -> {address}"
1289
1290 // Suppress the newline, so the access annotation goes on the same line.
1291 PrintRegister(code, format, "");
1292 fprintf(stream_,
1293 " %s %s0x%016" PRIxPTR "%s\n",
1294 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001295 clr_memory_address,
1296 address,
1297 clr_normal);
1298}
1299
Jacob Bramley423e5422019-11-13 19:15:55 +00001300void Simulator::PrintVAccess(int code,
1301 PrintRegisterFormat format,
1302 const char* op,
1303 uintptr_t address) {
1304 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001305
Jacob Bramley423e5422019-11-13 19:15:55 +00001306 // Scalar-format accesses use a simple format:
1307 // "# v{code}: 0x{value} -> {address}"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001308
Jacob Bramley423e5422019-11-13 19:15:55 +00001309 // Suppress the newline, so the access annotation goes on the same line.
1310 PrintVRegister(code, format, "");
Alexandre Ramesd3832962016-07-04 15:03:43 +01001311 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001312 " %s %s0x%016" PRIxPTR "%s\n",
1313 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001314 clr_memory_address,
1315 address,
1316 clr_normal);
1317}
1318
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001319void Simulator::PrintVStructAccess(int rt_code,
Jacob Bramley423e5422019-11-13 19:15:55 +00001320 int reg_count,
1321 PrintRegisterFormat format,
1322 const char* op,
1323 uintptr_t address) {
1324 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1325
1326 // For example:
1327 // "# v{code}: 0x{value}"
1328 // "# ...: 0x{value}"
1329 // "# ║ ╙─ {struct_value} -> {lowest_address}"
1330 // "# ╙───── {struct_value} -> {highest_address}"
1331
1332 uint16_t lane_mask = GetPrintRegLaneMask(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001333 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
Jacob Bramley423e5422019-11-13 19:15:55 +00001334
1335 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1336 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1337 for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1338 uint16_t access_mask = 1 << i;
1339 VIXL_ASSERT((lane_mask & access_mask) != 0);
1340 lane_mask = PrintPartialAccess(access_mask,
1341 lane_mask,
1342 reg_count,
1343 lane_size_in_bytes,
1344 op,
1345 address + (i * reg_count));
1346 }
1347}
1348
1349void Simulator::PrintVSingleStructAccess(int rt_code,
1350 int reg_count,
1351 int lane,
1352 PrintRegisterFormat format,
1353 const char* op,
1354 uintptr_t address) {
1355 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1356
1357 // For example:
1358 // "# v{code}: 0x{value}"
1359 // "# ...: 0x{value}"
1360 // "# ╙───── {struct_value} -> {address}"
1361
1362 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1363 uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1364 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1365 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1366}
1367
1368void Simulator::PrintVReplicatingStructAccess(int rt_code,
1369 int reg_count,
1370 PrintRegisterFormat format,
1371 const char* op,
1372 uintptr_t address) {
1373 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1374
1375 // For example:
1376 // "# v{code}: 0x{value}"
1377 // "# ...: 0x{value}"
1378 // "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1379
1380 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1381 uint16_t lane_mask = GetPrintRegLaneMask(format);
1382 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1383 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1384}
1385
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001386void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1387 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1388
1389 // Scalar-format accesses are split into separate chunks, each of which uses a
1390 // simple format:
1391 // "# z{code}<127:0>: 0x{value} -> {address}"
1392 // "# z{code}<255:128>: 0x{value} -> {address + 16}"
1393 // "# z{code}<383:256>: 0x{value} -> {address + 32}"
1394 // etc
1395
1396 int vl = GetVectorLengthInBits();
1397 VIXL_ASSERT((vl % kQRegSize) == 0);
1398 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1399 // Suppress the newline, so the access annotation goes on the same line.
1400 PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1401 fprintf(stream_,
1402 " %s %s0x%016" PRIxPTR "%s\n",
1403 op,
1404 clr_memory_address,
1405 address,
1406 clr_normal);
1407 address += kQRegSizeInBytes;
1408 }
1409}
1410
1411void Simulator::PrintZStructAccess(int rt_code,
1412 int reg_count,
1413 const LogicPRegister& pg,
1414 PrintRegisterFormat format,
1415 int msize_in_bytes,
1416 const char* op,
1417 const LogicSVEAddressVector& addr) {
1418 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1419
1420 // For example:
1421 // "# z{code}<255:128>: 0x{value}"
1422 // "# ...<255:128>: 0x{value}"
1423 // "# ║ ╙─ {struct_value} -> {first_address}"
1424 // "# ╙───── {struct_value} -> {last_address}"
1425
1426 // We're going to print the register in parts, so force a partial format.
1427 bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1428 format = GetPrintRegPartial(format);
1429
1430 int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1431 int vl = GetVectorLengthInBits();
1432 VIXL_ASSERT((vl % kQRegSize) == 0);
1433 int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1434 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1435 uint16_t pred =
1436 pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1437 if ((pred == 0) && skip_inactive_chunks) continue;
1438
1439 PrintZRegistersForStructuredAccess(rt_code,
1440 q_index,
1441 reg_count,
1442 pred,
1443 format);
1444 if (pred == 0) {
1445 // This register chunk has no active lanes. The loop below would print
1446 // nothing, so leave a blank line to keep structures grouped together.
1447 fprintf(stream_, "#\n");
1448 continue;
1449 }
1450 for (int i = 0; i < lanes_per_q; i++) {
1451 uint16_t access = 1 << (i * esize_in_bytes);
1452 int lane = (q_index * lanes_per_q) + i;
1453 // Skip inactive lanes.
1454 if ((pred & access) == 0) continue;
1455 pred = PrintPartialAccess(access,
1456 pred,
1457 reg_count,
1458 msize_in_bytes,
1459 op,
1460 addr.GetStructAddress(lane));
1461 }
1462 }
1463
1464 // We print the whole register, even for stores.
1465 for (int i = 0; i < reg_count; i++) {
1466 vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1467 }
1468}
1469
1470void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1471 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1472
1473 // Scalar-format accesses are split into separate chunks, each of which uses a
1474 // simple format:
1475 // "# p{code}<15:0>: 0b{value} -> {address}"
1476 // "# p{code}<31:16>: 0b{value} -> {address + 2}"
1477 // "# p{code}<47:32>: 0b{value} -> {address + 4}"
1478 // etc
1479
1480 int vl = GetVectorLengthInBits();
1481 VIXL_ASSERT((vl % kQRegSize) == 0);
1482 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1483 // Suppress the newline, so the access annotation goes on the same line.
1484 PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1485 fprintf(stream_,
1486 " %s %s0x%016" PRIxPTR "%s\n",
1487 op,
1488 clr_memory_address,
1489 address,
1490 clr_normal);
1491 address += kQRegSizeInBytes;
1492 }
1493}
1494
Jacob Bramley423e5422019-11-13 19:15:55 +00001495void Simulator::PrintRead(int rt_code,
1496 PrintRegisterFormat format,
1497 uintptr_t address) {
1498 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1499 registers_[rt_code].NotifyRegisterLogged();
1500 PrintAccess(rt_code, format, "<-", address);
1501}
1502
1503void Simulator::PrintExtendingRead(int rt_code,
1504 PrintRegisterFormat format,
1505 int access_size_in_bytes,
1506 uintptr_t address) {
1507 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1508 if (access_size_in_bytes == reg_size_in_bytes) {
1509 // There is no extension here, so print a simple load.
1510 PrintRead(rt_code, format, address);
1511 return;
1512 }
1513 VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1514
1515 // For sign- and zero-extension, make it clear that the resulting register
1516 // value is different from what is loaded from memory.
1517 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1518 registers_[rt_code].NotifyRegisterLogged();
1519 PrintRegister(rt_code, format);
1520 PrintPartialAccess(1,
1521 0,
1522 1,
1523 access_size_in_bytes,
1524 "<-",
1525 address,
1526 kXRegSizeInBytes);
1527}
1528
1529void Simulator::PrintVRead(int rt_code,
1530 PrintRegisterFormat format,
1531 uintptr_t address) {
1532 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1533 vregisters_[rt_code].NotifyRegisterLogged();
1534 PrintVAccess(rt_code, format, "<-", address);
1535}
1536
Jacob Bramley423e5422019-11-13 19:15:55 +00001537void Simulator::PrintWrite(int rt_code,
1538 PrintRegisterFormat format,
1539 uintptr_t address) {
1540 // Because this trace doesn't represent a change to the source register's
1541 // value, only print the relevant part of the value.
1542 format = GetPrintRegPartial(format);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001543 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001544 registers_[rt_code].NotifyRegisterLogged();
1545 PrintAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001546}
1547
Jacob Bramley423e5422019-11-13 19:15:55 +00001548void Simulator::PrintVWrite(int rt_code,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001549 PrintRegisterFormat format,
Jacob Bramley423e5422019-11-13 19:15:55 +00001550 uintptr_t address) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001551 // Because this trace doesn't represent a change to the source register's
Jacob Bramley423e5422019-11-13 19:15:55 +00001552 // value, only print the relevant part of the value.
1553 format = GetPrintRegPartial(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001554 // It only makes sense to write scalar values here. Vectors are handled by
1555 // PrintVStructAccess.
Jacob Bramley423e5422019-11-13 19:15:55 +00001556 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001557 PrintVAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001558}
1559
Jacob Bramleye79723a2016-06-07 17:50:47 +01001560void Simulator::PrintTakenBranch(const Instruction* target) {
1561 fprintf(stream_,
1562 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1563 clr_branch_marker,
1564 clr_normal,
1565 reinterpret_cast<uint64_t>(target));
1566}
1567
Alexandre Ramesd3832962016-07-04 15:03:43 +01001568// Visitors---------------------------------------------------------------------
1569
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001570
1571void Simulator::VisitReserved(const Instruction* instr) {
1572 // UDF is the only instruction in this group, and the Decoder is precise here.
1573 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1574
1575 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1576 reinterpret_cast<const void*>(instr),
1577 instr->GetInstructionBits());
1578 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1579}
1580
1581
Alexandre Ramesd3832962016-07-04 15:03:43 +01001582void Simulator::VisitUnimplemented(const Instruction* instr) {
1583 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1584 reinterpret_cast<const void*>(instr),
1585 instr->GetInstructionBits());
1586 VIXL_UNIMPLEMENTED();
1587}
1588
1589
1590void Simulator::VisitUnallocated(const Instruction* instr) {
1591 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1592 reinterpret_cast<const void*>(instr),
1593 instr->GetInstructionBits());
1594 VIXL_UNIMPLEMENTED();
1595}
1596
1597
1598void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1599 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1600 (instr->Mask(PCRelAddressingMask) == ADRP));
1601
1602 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1603}
1604
1605
1606void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1607 switch (instr->Mask(UnconditionalBranchMask)) {
1608 case BL:
1609 WriteLr(instr->GetNextInstruction());
1610 VIXL_FALLTHROUGH();
1611 case B:
1612 WritePc(instr->GetImmPCOffsetTarget());
1613 break;
1614 default:
1615 VIXL_UNREACHABLE();
1616 }
1617}
1618
1619
1620void Simulator::VisitConditionalBranch(const Instruction* instr) {
1621 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1622 if (ConditionPassed(instr->GetConditionBranch())) {
1623 WritePc(instr->GetImmPCOffsetTarget());
1624 }
1625}
1626
Martyn Capewellcb963f72018-10-22 15:25:28 +01001627BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1628 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1629 case BLR:
1630 case BLRAA:
1631 case BLRAB:
1632 case BLRAAZ:
1633 case BLRABZ:
1634 return BranchAndLink;
1635 case BR:
1636 case BRAA:
1637 case BRAB:
1638 case BRAAZ:
1639 case BRABZ:
1640 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1641 !PcIsInGuardedPage()) {
1642 return BranchFromUnguardedOrToIP;
1643 }
1644 return BranchFromGuardedNotToIP;
1645 }
1646 return DefaultBType;
1647}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001648
1649void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01001650 bool authenticate = false;
1651 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01001652 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01001653 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001654
1655 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1656 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01001657 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001658 VIXL_FALLTHROUGH();
1659 case BR:
1660 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01001661 break;
1662
1663 case BLRAAZ:
1664 case BLRABZ:
1665 link = true;
1666 VIXL_FALLTHROUGH();
1667 case BRAAZ:
1668 case BRABZ:
1669 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001670 break;
1671
1672 case BLRAA:
1673 case BLRAB:
1674 link = true;
1675 VIXL_FALLTHROUGH();
1676 case BRAA:
1677 case BRAB:
1678 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001679 context = ReadXRegister(instr->GetRd());
1680 break;
1681
1682 case RETAA:
1683 case RETAB:
1684 authenticate = true;
1685 addr = ReadXRegister(kLinkRegCode);
1686 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001687 break;
1688 default:
1689 VIXL_UNREACHABLE();
1690 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001691
1692 if (link) {
1693 WriteLr(instr->GetNextInstruction());
1694 }
1695
1696 if (authenticate) {
1697 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1698 addr = AuthPAC(addr, context, key, kInstructionPointer);
1699
1700 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1701 if (((addr >> error_lsb) & 0x3) != 0x0) {
1702 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1703 }
1704 }
1705
Martyn Capewellcb963f72018-10-22 15:25:28 +01001706 WritePc(Instruction::Cast(addr));
1707 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001708}
1709
1710
1711void Simulator::VisitTestBranch(const Instruction* instr) {
1712 unsigned bit_pos =
1713 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1714 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1715 bool take_branch = false;
1716 switch (instr->Mask(TestBranchMask)) {
1717 case TBZ:
1718 take_branch = bit_zero;
1719 break;
1720 case TBNZ:
1721 take_branch = !bit_zero;
1722 break;
1723 default:
1724 VIXL_UNIMPLEMENTED();
1725 }
1726 if (take_branch) {
1727 WritePc(instr->GetImmPCOffsetTarget());
1728 }
1729}
1730
1731
1732void Simulator::VisitCompareBranch(const Instruction* instr) {
1733 unsigned rt = instr->GetRt();
1734 bool take_branch = false;
1735 switch (instr->Mask(CompareBranchMask)) {
1736 case CBZ_w:
1737 take_branch = (ReadWRegister(rt) == 0);
1738 break;
1739 case CBZ_x:
1740 take_branch = (ReadXRegister(rt) == 0);
1741 break;
1742 case CBNZ_w:
1743 take_branch = (ReadWRegister(rt) != 0);
1744 break;
1745 case CBNZ_x:
1746 take_branch = (ReadXRegister(rt) != 0);
1747 break;
1748 default:
1749 VIXL_UNIMPLEMENTED();
1750 }
1751 if (take_branch) {
1752 WritePc(instr->GetImmPCOffsetTarget());
1753 }
1754}
1755
1756
1757void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1758 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1759 bool set_flags = instr->GetFlagsUpdate();
1760 int64_t new_val = 0;
1761 Instr operation = instr->Mask(AddSubOpMask);
1762
1763 switch (operation) {
1764 case ADD:
1765 case ADDS: {
1766 new_val = AddWithCarry(reg_size,
1767 set_flags,
1768 ReadRegister(reg_size,
1769 instr->GetRn(),
1770 instr->GetRnMode()),
1771 op2);
1772 break;
1773 }
1774 case SUB:
1775 case SUBS: {
1776 new_val = AddWithCarry(reg_size,
1777 set_flags,
1778 ReadRegister(reg_size,
1779 instr->GetRn(),
1780 instr->GetRnMode()),
1781 ~op2,
1782 1);
1783 break;
1784 }
1785 default:
1786 VIXL_UNREACHABLE();
1787 }
1788
1789 WriteRegister(reg_size,
1790 instr->GetRd(),
1791 new_val,
1792 LogRegWrites,
1793 instr->GetRdMode());
1794}
1795
1796
1797void Simulator::VisitAddSubShifted(const Instruction* instr) {
1798 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1799 int64_t op2 = ShiftOperand(reg_size,
1800 ReadRegister(reg_size, instr->GetRm()),
1801 static_cast<Shift>(instr->GetShiftDP()),
1802 instr->GetImmDPShift());
1803 AddSubHelper(instr, op2);
1804}
1805
1806
1807void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1808 int64_t op2 = instr->GetImmAddSub()
1809 << ((instr->GetShiftAddSub() == 1) ? 12 : 0);
1810 AddSubHelper(instr, op2);
1811}
1812
1813
1814void Simulator::VisitAddSubExtended(const Instruction* instr) {
1815 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1816 int64_t op2 = ExtendValue(reg_size,
1817 ReadRegister(reg_size, instr->GetRm()),
1818 static_cast<Extend>(instr->GetExtendMode()),
1819 instr->GetImmExtendShift());
1820 AddSubHelper(instr, op2);
1821}
1822
1823
1824void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1825 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1826 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1827 int64_t new_val;
1828
1829 if ((instr->Mask(AddSubOpMask) == SUB) ||
1830 (instr->Mask(AddSubOpMask) == SUBS)) {
1831 op2 = ~op2;
1832 }
1833
1834 new_val = AddWithCarry(reg_size,
1835 instr->GetFlagsUpdate(),
1836 ReadRegister(reg_size, instr->GetRn()),
1837 op2,
1838 ReadC());
1839
1840 WriteRegister(reg_size, instr->GetRd(), new_val);
1841}
1842
1843
Alexander Gilday2487f142018-11-05 13:07:27 +00001844void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1845 switch (instr->Mask(RotateRightIntoFlagsMask)) {
1846 case RMIF: {
1847 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1848 unsigned shift = instr->GetImmRMIFRotation();
1849 unsigned mask = instr->GetNzcv();
1850 uint64_t rotated = RotateRight(value, shift, kXRegSize);
1851
1852 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1853 break;
1854 }
1855 }
1856}
1857
1858
1859void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1860 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1861 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1862
1863 unsigned sign_bit = (value >> msb) & 1;
1864 unsigned overflow_bit = (value >> (msb + 1)) & 1;
1865 ReadNzcv().SetN(sign_bit);
1866 ReadNzcv().SetZ((value << (31 - msb)) == 0);
1867 ReadNzcv().SetV(sign_bit ^ overflow_bit);
1868}
1869
1870
Alexandre Ramesd3832962016-07-04 15:03:43 +01001871void Simulator::VisitLogicalShifted(const Instruction* instr) {
1872 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1873 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1874 unsigned shift_amount = instr->GetImmDPShift();
1875 int64_t op2 = ShiftOperand(reg_size,
1876 ReadRegister(reg_size, instr->GetRm()),
1877 shift_type,
1878 shift_amount);
1879 if (instr->Mask(NOT) == NOT) {
1880 op2 = ~op2;
1881 }
1882 LogicalHelper(instr, op2);
1883}
1884
1885
1886void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1887 LogicalHelper(instr, instr->GetImmLogical());
1888}
1889
1890
1891void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1892 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1893 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1894 int64_t result = 0;
1895 bool update_flags = false;
1896
1897 // Switch on the logical operation, stripping out the NOT bit, as it has a
1898 // different meaning for logical immediate instructions.
1899 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1900 case ANDS:
1901 update_flags = true;
1902 VIXL_FALLTHROUGH();
1903 case AND:
1904 result = op1 & op2;
1905 break;
1906 case ORR:
1907 result = op1 | op2;
1908 break;
1909 case EOR:
1910 result = op1 ^ op2;
1911 break;
1912 default:
1913 VIXL_UNIMPLEMENTED();
1914 }
1915
1916 if (update_flags) {
1917 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1918 ReadNzcv().SetZ(CalcZFlag(result));
1919 ReadNzcv().SetC(0);
1920 ReadNzcv().SetV(0);
1921 LogSystemRegister(NZCV);
1922 }
1923
1924 WriteRegister(reg_size,
1925 instr->GetRd(),
1926 result,
1927 LogRegWrites,
1928 instr->GetRdMode());
1929}
1930
1931
1932void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1933 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1934 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1935}
1936
1937
1938void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1939 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1940}
1941
1942
1943void Simulator::ConditionalCompareHelper(const Instruction* instr,
1944 int64_t op2) {
1945 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1946 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1947
1948 if (ConditionPassed(instr->GetCondition())) {
1949 // If the condition passes, set the status flags to the result of comparing
1950 // the operands.
1951 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1952 AddWithCarry(reg_size, true, op1, ~op2, 1);
1953 } else {
1954 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1955 AddWithCarry(reg_size, true, op1, op2, 0);
1956 }
1957 } else {
1958 // If the condition fails, set the status flags to the nzcv immediate.
1959 ReadNzcv().SetFlags(instr->GetNzcv());
1960 LogSystemRegister(NZCV);
1961 }
1962}
1963
1964
1965void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1966 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1967 LoadStoreHelper(instr, offset, Offset);
1968}
1969
1970
1971void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1972 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1973}
1974
1975
1976void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1977 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1978}
1979
1980
1981void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1982 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1983}
1984
1985
Alexander Gilday311edf22018-10-29 13:41:41 +00001986template <typename T1, typename T2>
1987void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1988 unsigned rt = instr->GetRt();
1989 unsigned rn = instr->GetRn();
1990
1991 unsigned element_size = sizeof(T2);
1992 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1993 int offset = instr->GetImmLS();
1994 address += offset;
1995
1996 // Verify that the address is available to the host.
1997 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1998
1999 // Check the alignment of `address`.
2000 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2001 VIXL_ALIGNMENT_EXCEPTION();
2002 }
2003
2004 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
2005
2006 // Approximate load-acquire by issuing a full barrier after the load.
2007 __sync_synchronize();
2008
Jacob Bramley423e5422019-11-13 19:15:55 +00002009 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00002010}
2011
2012
2013template <typename T>
2014void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
2015 unsigned rt = instr->GetRt();
2016 unsigned rn = instr->GetRn();
2017
2018 unsigned element_size = sizeof(T);
2019 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2020 int offset = instr->GetImmLS();
2021 address += offset;
2022
2023 // Verify that the address is available to the host.
2024 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2025
2026 // Check the alignment of `address`.
2027 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2028 VIXL_ALIGNMENT_EXCEPTION();
2029 }
2030
2031 // Approximate store-release by issuing a full barrier after the load.
2032 __sync_synchronize();
2033
2034 Memory::Write<T>(address, ReadRegister<T>(rt));
2035
Jacob Bramley423e5422019-11-13 19:15:55 +00002036 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00002037}
2038
2039
2040void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
2041 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
2042 case LDAPURB:
2043 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
2044 break;
2045 case LDAPURH:
2046 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
2047 break;
2048 case LDAPUR_w:
2049 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
2050 break;
2051 case LDAPUR_x:
2052 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
2053 break;
2054 case LDAPURSB_w:
2055 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
2056 break;
2057 case LDAPURSB_x:
2058 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
2059 break;
2060 case LDAPURSH_w:
2061 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
2062 break;
2063 case LDAPURSH_x:
2064 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
2065 break;
2066 case LDAPURSW:
2067 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
2068 break;
2069 case STLURB:
2070 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
2071 break;
2072 case STLURH:
2073 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
2074 break;
2075 case STLUR_w:
2076 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
2077 break;
2078 case STLUR_x:
2079 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
2080 break;
2081 }
2082}
2083
2084
Alexander Gilday75605592018-11-01 09:30:29 +00002085void Simulator::VisitLoadStorePAC(const Instruction* instr) {
2086 unsigned dst = instr->GetRt();
2087 unsigned addr_reg = instr->GetRn();
2088
2089 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2090
2091 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
2092 address = AuthPAC(address, 0, key, kDataPointer);
2093
2094 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
2095 if (((address >> error_lsb) & 0x3) != 0x0) {
2096 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
2097 }
2098
2099
2100 if ((addr_reg == 31) && ((address % 16) != 0)) {
2101 // When the base register is SP the stack pointer is required to be
2102 // quadword aligned prior to the address calculation and write-backs.
2103 // Misalignment will cause a stack alignment fault.
2104 VIXL_ALIGNMENT_EXCEPTION();
2105 }
2106
2107 int64_t offset = instr->GetImmLSPAC();
2108 address += offset;
2109
2110 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
2111 // Pre-index mode.
2112 VIXL_ASSERT(offset != 0);
2113 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
2114 }
2115
2116 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
2117
2118 // Verify that the calculated address is available to the host.
2119 VIXL_ASSERT(address == addr_ptr);
2120
2121 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
2122 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00002123 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00002124}
2125
2126
Alexandre Ramesd3832962016-07-04 15:03:43 +01002127void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
2128 Extend ext = static_cast<Extend>(instr->GetExtendMode());
2129 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
2130 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
2131
2132 int64_t offset =
2133 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
2134 LoadStoreHelper(instr, offset, Offset);
2135}
2136
2137
2138void Simulator::LoadStoreHelper(const Instruction* instr,
2139 int64_t offset,
2140 AddrMode addrmode) {
2141 unsigned srcdst = instr->GetRt();
2142 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2143
Jacob Bramley423e5422019-11-13 19:15:55 +00002144 bool rt_is_vreg = false;
2145 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002146 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
2147 switch (op) {
2148 case LDRB_w:
2149 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002150 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002151 break;
2152 case LDRH_w:
2153 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002154 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002155 break;
2156 case LDR_w:
2157 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002158 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002159 break;
2160 case LDR_x:
2161 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002162 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002163 break;
2164 case LDRSB_w:
2165 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002166 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002167 break;
2168 case LDRSH_w:
2169 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002170 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002171 break;
2172 case LDRSB_x:
2173 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002174 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002175 break;
2176 case LDRSH_x:
2177 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002178 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002179 break;
2180 case LDRSW_x:
2181 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002182 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002183 break;
2184 case LDR_b:
2185 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002186 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002187 break;
2188 case LDR_h:
2189 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002190 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002191 break;
2192 case LDR_s:
2193 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002194 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002195 break;
2196 case LDR_d:
2197 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002198 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002199 break;
2200 case LDR_q:
2201 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002202 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002203 break;
2204
2205 case STRB_w:
2206 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
2207 break;
2208 case STRH_w:
2209 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
2210 break;
2211 case STR_w:
2212 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
2213 break;
2214 case STR_x:
2215 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
2216 break;
2217 case STR_b:
2218 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002219 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002220 break;
2221 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01002222 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002223 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002224 break;
2225 case STR_s:
2226 Memory::Write<float>(address, ReadSRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002227 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002228 break;
2229 case STR_d:
2230 Memory::Write<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002231 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002232 break;
2233 case STR_q:
2234 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002235 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002236 break;
2237
2238 // Ignore prfm hint instructions.
2239 case PRFM:
2240 break;
2241
2242 default:
2243 VIXL_UNIMPLEMENTED();
2244 }
2245
Jacob Bramley423e5422019-11-13 19:15:55 +00002246 // Print a detailed trace (including the memory address).
2247 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002248 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00002249 unsigned result_size = extend ? extend_to_size : access_size;
2250 PrintRegisterFormat print_format =
2251 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2252 : GetPrintRegisterFormatForSize(result_size);
2253
Alexandre Ramesd3832962016-07-04 15:03:43 +01002254 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002255 if (rt_is_vreg) {
2256 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002257 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002258 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002259 }
2260 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002261 if (rt_is_vreg) {
2262 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002263 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002264 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002265 }
2266 } else {
2267 VIXL_ASSERT(op == PRFM);
2268 }
2269
2270 local_monitor_.MaybeClear();
2271}
2272
2273
2274void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
2275 LoadStorePairHelper(instr, Offset);
2276}
2277
2278
2279void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
2280 LoadStorePairHelper(instr, PreIndex);
2281}
2282
2283
2284void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
2285 LoadStorePairHelper(instr, PostIndex);
2286}
2287
2288
2289void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
2290 LoadStorePairHelper(instr, Offset);
2291}
2292
2293
2294void Simulator::LoadStorePairHelper(const Instruction* instr,
2295 AddrMode addrmode) {
2296 unsigned rt = instr->GetRt();
2297 unsigned rt2 = instr->GetRt2();
2298 int element_size = 1 << instr->GetSizeLSPair();
2299 int64_t offset = instr->GetImmLSPair() * element_size;
2300 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2301 uintptr_t address2 = address + element_size;
2302
2303 LoadStorePairOp op =
2304 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
2305
2306 // 'rt' and 'rt2' can only be aliased for stores.
2307 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2308
Jacob Bramley423e5422019-11-13 19:15:55 +00002309 bool rt_is_vreg = false;
2310 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002311 switch (op) {
2312 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
2313 // will print a more detailed log.
2314 case LDP_w: {
2315 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2316 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
2317 break;
2318 }
2319 case LDP_s: {
2320 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2321 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002322 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002323 break;
2324 }
2325 case LDP_x: {
2326 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2327 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
2328 break;
2329 }
2330 case LDP_d: {
2331 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2332 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002333 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002334 break;
2335 }
2336 case LDP_q: {
2337 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2338 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002339 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002340 break;
2341 }
2342 case LDPSW_x: {
2343 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2344 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002345 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002346 break;
2347 }
2348 case STP_w: {
2349 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2350 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
2351 break;
2352 }
2353 case STP_s: {
2354 Memory::Write<float>(address, ReadSRegister(rt));
2355 Memory::Write<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002356 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002357 break;
2358 }
2359 case STP_x: {
2360 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2361 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
2362 break;
2363 }
2364 case STP_d: {
2365 Memory::Write<double>(address, ReadDRegister(rt));
2366 Memory::Write<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002367 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002368 break;
2369 }
2370 case STP_q: {
2371 Memory::Write<qreg_t>(address, ReadQRegister(rt));
2372 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002373 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002374 break;
2375 }
2376 default:
2377 VIXL_UNREACHABLE();
2378 }
2379
Jacob Bramley423e5422019-11-13 19:15:55 +00002380 // Print a detailed trace (including the memory address).
2381 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
2382 PrintRegisterFormat print_format =
2383 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2384 : GetPrintRegisterFormatForSize(result_size);
2385
Alexandre Ramesd3832962016-07-04 15:03:43 +01002386 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002387 if (rt_is_vreg) {
2388 LogVRead(rt, print_format, address);
2389 LogVRead(rt2, print_format, address2);
2390 } else if (sign_extend) {
2391 LogExtendingRead(rt, print_format, element_size, address);
2392 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002393 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002394 LogRead(rt, print_format, address);
2395 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002396 }
2397 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002398 if (rt_is_vreg) {
2399 LogVWrite(rt, print_format, address);
2400 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002401 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002402 LogWrite(rt, print_format, address);
2403 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002404 }
2405 }
2406
2407 local_monitor_.MaybeClear();
2408}
2409
2410
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002411template <typename T>
2412void Simulator::CompareAndSwapHelper(const Instruction* instr) {
2413 unsigned rs = instr->GetRs();
2414 unsigned rt = instr->GetRt();
2415 unsigned rn = instr->GetRn();
2416
2417 unsigned element_size = sizeof(T);
2418 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2419
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002420 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2421
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002422 bool is_acquire = instr->ExtractBit(22) == 1;
2423 bool is_release = instr->ExtractBit(15) == 1;
2424
2425 T comparevalue = ReadRegister<T>(rs);
2426 T newvalue = ReadRegister<T>(rt);
2427
2428 // The architecture permits that the data read clears any exclusive monitors
2429 // associated with that location, even if the compare subsequently fails.
2430 local_monitor_.Clear();
2431
2432 T data = Memory::Read<T>(address);
2433 if (is_acquire) {
2434 // Approximate load-acquire by issuing a full barrier after the load.
2435 __sync_synchronize();
2436 }
2437
2438 if (data == comparevalue) {
2439 if (is_release) {
2440 // Approximate store-release by issuing a full barrier before the store.
2441 __sync_synchronize();
2442 }
2443 Memory::Write<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00002444 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002445 }
2446 WriteRegister<T>(rs, data);
Jacob Bramley423e5422019-11-13 19:15:55 +00002447 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002448}
2449
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002450
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002451template <typename T>
2452void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
2453 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
2454 unsigned rs = instr->GetRs();
2455 unsigned rt = instr->GetRt();
2456 unsigned rn = instr->GetRn();
2457
2458 VIXL_ASSERT((rs % 2 == 0) && (rs % 2 == 0));
2459
2460 unsigned element_size = sizeof(T);
2461 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002462
2463 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
2464
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002465 uint64_t address2 = address + element_size;
2466
2467 bool is_acquire = instr->ExtractBit(22) == 1;
2468 bool is_release = instr->ExtractBit(15) == 1;
2469
2470 T comparevalue_high = ReadRegister<T>(rs + 1);
2471 T comparevalue_low = ReadRegister<T>(rs);
2472 T newvalue_high = ReadRegister<T>(rt + 1);
2473 T newvalue_low = ReadRegister<T>(rt);
2474
2475 // The architecture permits that the data read clears any exclusive monitors
2476 // associated with that location, even if the compare subsequently fails.
2477 local_monitor_.Clear();
2478
2479 T data_high = Memory::Read<T>(address);
2480 T data_low = Memory::Read<T>(address2);
2481
2482 if (is_acquire) {
2483 // Approximate load-acquire by issuing a full barrier after the load.
2484 __sync_synchronize();
2485 }
2486
2487 bool same =
2488 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2489 if (same) {
2490 if (is_release) {
2491 // Approximate store-release by issuing a full barrier before the store.
2492 __sync_synchronize();
2493 }
2494
2495 Memory::Write<T>(address, newvalue_high);
2496 Memory::Write<T>(address2, newvalue_low);
2497 }
2498
2499 WriteRegister<T>(rs + 1, data_high);
2500 WriteRegister<T>(rs, data_low);
2501
Jacob Bramley423e5422019-11-13 19:15:55 +00002502 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2503 LogRead(rs + 1, format, address);
2504 LogRead(rs, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002505
2506 if (same) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002507 LogWrite(rt + 1, format, address);
2508 LogWrite(rt, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002509 }
2510}
2511
Alexandre Ramesd3832962016-07-04 15:03:43 +01002512
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002513void Simulator::PrintExclusiveAccessWarning() {
2514 if (print_exclusive_access_warning_) {
2515 fprintf(stderr,
2516 "%sWARNING:%s VIXL simulator support for "
2517 "load-/store-/clear-exclusive "
2518 "instructions is limited. Refer to the README for details.%s\n",
2519 clr_warning,
2520 clr_warning_message,
2521 clr_normal);
2522 print_exclusive_access_warning_ = false;
2523 }
2524}
2525
2526
Alexandre Ramesd3832962016-07-04 15:03:43 +01002527void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002528 LoadStoreExclusive op =
2529 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
2530
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002531 switch (op) {
2532 case CAS_w:
2533 case CASA_w:
2534 case CASL_w:
2535 case CASAL_w:
2536 CompareAndSwapHelper<uint32_t>(instr);
2537 break;
2538 case CAS_x:
2539 case CASA_x:
2540 case CASL_x:
2541 case CASAL_x:
2542 CompareAndSwapHelper<uint64_t>(instr);
2543 break;
2544 case CASB:
2545 case CASAB:
2546 case CASLB:
2547 case CASALB:
2548 CompareAndSwapHelper<uint8_t>(instr);
2549 break;
2550 case CASH:
2551 case CASAH:
2552 case CASLH:
2553 case CASALH:
2554 CompareAndSwapHelper<uint16_t>(instr);
2555 break;
2556 case CASP_w:
2557 case CASPA_w:
2558 case CASPL_w:
2559 case CASPAL_w:
2560 CompareAndSwapPairHelper<uint32_t>(instr);
2561 break;
2562 case CASP_x:
2563 case CASPA_x:
2564 case CASPL_x:
2565 case CASPAL_x:
2566 CompareAndSwapPairHelper<uint64_t>(instr);
2567 break;
2568 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002569 PrintExclusiveAccessWarning();
2570
2571 unsigned rs = instr->GetRs();
2572 unsigned rt = instr->GetRt();
2573 unsigned rt2 = instr->GetRt2();
2574 unsigned rn = instr->GetRn();
2575
2576 bool is_exclusive = !instr->GetLdStXNotExclusive();
2577 bool is_acquire_release =
2578 !is_exclusive || instr->GetLdStXAcquireRelease();
2579 bool is_load = instr->GetLdStXLoad();
2580 bool is_pair = instr->GetLdStXPair();
2581
2582 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2583 unsigned access_size = is_pair ? element_size * 2 : element_size;
2584 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2585
2586 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2587
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002588 if (is_load) {
2589 if (is_exclusive) {
2590 local_monitor_.MarkExclusive(address, access_size);
2591 } else {
2592 // Any non-exclusive load can clear the local monitor as a side
2593 // effect. We don't need to do this, but it is useful to stress the
2594 // simulated code.
2595 local_monitor_.Clear();
2596 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002597
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002598 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2599 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00002600 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002601 switch (op) {
2602 case LDXRB_w:
2603 case LDAXRB_w:
2604 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002605 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002606 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002607 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002608 break;
2609 case LDXRH_w:
2610 case LDAXRH_w:
2611 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002612 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002613 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002614 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002615 break;
2616 case LDXR_w:
2617 case LDAXR_w:
2618 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002619 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002620 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002621 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002622 break;
2623 case LDXR_x:
2624 case LDAXR_x:
2625 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002626 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002627 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002628 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002629 break;
2630 case LDXP_w:
2631 case LDAXP_w:
2632 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2633 WriteWRegister(rt2,
2634 Memory::Read<uint32_t>(address + element_size),
2635 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002636 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002637 break;
2638 case LDXP_x:
2639 case LDAXP_x:
2640 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2641 WriteXRegister(rt2,
2642 Memory::Read<uint64_t>(address + element_size),
2643 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002644 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002645 break;
2646 default:
2647 VIXL_UNREACHABLE();
2648 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002649
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002650 if (is_acquire_release) {
2651 // Approximate load-acquire by issuing a full barrier after the load.
2652 __sync_synchronize();
2653 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002654
Jacob Bramley423e5422019-11-13 19:15:55 +00002655 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
2656 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002657 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002658 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002659 }
2660 } else {
2661 if (is_acquire_release) {
2662 // Approximate store-release by issuing a full barrier before the
2663 // store.
2664 __sync_synchronize();
2665 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002666
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002667 bool do_store = true;
2668 if (is_exclusive) {
2669 do_store = local_monitor_.IsExclusive(address, access_size) &&
2670 global_monitor_.IsExclusive(address, access_size);
2671 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002672
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002673 // - All exclusive stores explicitly clear the local monitor.
2674 local_monitor_.Clear();
2675 } else {
2676 // - Any other store can clear the local monitor as a side effect.
2677 local_monitor_.MaybeClear();
2678 }
2679
2680 if (do_store) {
2681 switch (op) {
2682 case STXRB_w:
2683 case STLXRB_w:
2684 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002685 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002686 Memory::Write<uint8_t>(address, ReadWRegister(rt));
2687 break;
2688 case STXRH_w:
2689 case STLXRH_w:
2690 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002691 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002692 Memory::Write<uint16_t>(address, ReadWRegister(rt));
2693 break;
2694 case STXR_w:
2695 case STLXR_w:
2696 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002697 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002698 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2699 break;
2700 case STXR_x:
2701 case STLXR_x:
2702 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002703 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002704 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2705 break;
2706 case STXP_w:
2707 case STLXP_w:
2708 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2709 Memory::Write<uint32_t>(address + element_size,
2710 ReadWRegister(rt2));
2711 break;
2712 case STXP_x:
2713 case STLXP_x:
2714 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2715 Memory::Write<uint64_t>(address + element_size,
2716 ReadXRegister(rt2));
2717 break;
2718 default:
2719 VIXL_UNREACHABLE();
2720 }
2721
Jacob Bramley423e5422019-11-13 19:15:55 +00002722 PrintRegisterFormat format =
2723 GetPrintRegisterFormatForSize(element_size);
2724 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002725 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002726 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002727 }
2728 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002729 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002730 }
2731}
2732
Jacob Bramleyca789742018-09-13 14:25:46 +01002733template <typename T>
2734void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2735 unsigned rs = instr->GetRs();
2736 unsigned rt = instr->GetRt();
2737 unsigned rn = instr->GetRn();
2738
2739 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2740 bool is_release = instr->ExtractBit(22) == 1;
2741
2742 unsigned element_size = sizeof(T);
2743 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2744
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002745 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002746
2747 T value = ReadRegister<T>(rs);
2748
2749 T data = Memory::Read<T>(address);
2750
2751 if (is_acquire) {
2752 // Approximate load-acquire by issuing a full barrier after the load.
2753 __sync_synchronize();
2754 }
2755
2756 T result = 0;
2757 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2758 case LDADDOp:
2759 result = data + value;
2760 break;
2761 case LDCLROp:
2762 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2763 result = data & ~value;
2764 break;
2765 case LDEOROp:
2766 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2767 result = data ^ value;
2768 break;
2769 case LDSETOp:
2770 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2771 result = data | value;
2772 break;
2773
2774 // Signed/Unsigned difference is done via the templated type T.
2775 case LDSMAXOp:
2776 case LDUMAXOp:
2777 result = (data > value) ? data : value;
2778 break;
2779 case LDSMINOp:
2780 case LDUMINOp:
2781 result = (data > value) ? value : data;
2782 break;
2783 }
2784
2785 if (is_release) {
2786 // Approximate store-release by issuing a full barrier before the store.
2787 __sync_synchronize();
2788 }
2789
2790 Memory::Write<T>(address, result);
2791 WriteRegister<T>(rt, data, NoRegLog);
2792
Jacob Bramley423e5422019-11-13 19:15:55 +00002793 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2794 LogRead(rt, format, address);
2795 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002796}
2797
2798template <typename T>
2799void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2800 unsigned rs = instr->GetRs();
2801 unsigned rt = instr->GetRt();
2802 unsigned rn = instr->GetRn();
2803
2804 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2805 bool is_release = instr->ExtractBit(22) == 1;
2806
2807 unsigned element_size = sizeof(T);
2808 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2809
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002810 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002811
2812 T data = Memory::Read<T>(address);
2813 if (is_acquire) {
2814 // Approximate load-acquire by issuing a full barrier after the load.
2815 __sync_synchronize();
2816 }
2817
2818 if (is_release) {
2819 // Approximate store-release by issuing a full barrier before the store.
2820 __sync_synchronize();
2821 }
2822 Memory::Write<T>(address, ReadRegister<T>(rs));
2823
2824 WriteRegister<T>(rt, data);
2825
Jacob Bramley423e5422019-11-13 19:15:55 +00002826 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2827 LogRead(rt, format, address);
2828 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002829}
2830
2831template <typename T>
2832void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2833 unsigned rt = instr->GetRt();
2834 unsigned rn = instr->GetRn();
2835
2836 unsigned element_size = sizeof(T);
2837 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2838
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002839 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2840
Jacob Bramleyca789742018-09-13 14:25:46 +01002841 WriteRegister<T>(rt, Memory::Read<T>(address));
2842
2843 // Approximate load-acquire by issuing a full barrier after the load.
2844 __sync_synchronize();
2845
Jacob Bramley423e5422019-11-13 19:15:55 +00002846 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002847}
2848
2849#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2850 V(LDADD) \
2851 V(LDCLR) \
2852 V(LDEOR) \
2853 V(LDSET) \
2854 V(LDUMAX) \
2855 V(LDUMIN)
2856
2857#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2858 V(LDSMAX) \
2859 V(LDSMIN)
2860
2861void Simulator::VisitAtomicMemory(const Instruction* instr) {
2862 switch (instr->Mask(AtomicMemoryMask)) {
2863// clang-format off
2864#define SIM_FUNC_B(A) \
2865 case A##B: \
2866 case A##AB: \
2867 case A##LB: \
2868 case A##ALB:
2869#define SIM_FUNC_H(A) \
2870 case A##H: \
2871 case A##AH: \
2872 case A##LH: \
2873 case A##ALH:
2874#define SIM_FUNC_w(A) \
2875 case A##_w: \
2876 case A##A_w: \
2877 case A##L_w: \
2878 case A##AL_w:
2879#define SIM_FUNC_x(A) \
2880 case A##_x: \
2881 case A##A_x: \
2882 case A##L_x: \
2883 case A##AL_x:
2884
2885 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2886 AtomicMemorySimpleHelper<uint8_t>(instr);
2887 break;
2888 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2889 AtomicMemorySimpleHelper<int8_t>(instr);
2890 break;
2891 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2892 AtomicMemorySimpleHelper<uint16_t>(instr);
2893 break;
2894 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2895 AtomicMemorySimpleHelper<int16_t>(instr);
2896 break;
2897 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2898 AtomicMemorySimpleHelper<uint32_t>(instr);
2899 break;
2900 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2901 AtomicMemorySimpleHelper<int32_t>(instr);
2902 break;
2903 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2904 AtomicMemorySimpleHelper<uint64_t>(instr);
2905 break;
2906 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2907 AtomicMemorySimpleHelper<int64_t>(instr);
2908 break;
2909 // clang-format on
2910
2911 case SWPB:
2912 case SWPAB:
2913 case SWPLB:
2914 case SWPALB:
2915 AtomicMemorySwapHelper<uint8_t>(instr);
2916 break;
2917 case SWPH:
2918 case SWPAH:
2919 case SWPLH:
2920 case SWPALH:
2921 AtomicMemorySwapHelper<uint16_t>(instr);
2922 break;
2923 case SWP_w:
2924 case SWPA_w:
2925 case SWPL_w:
2926 case SWPAL_w:
2927 AtomicMemorySwapHelper<uint32_t>(instr);
2928 break;
2929 case SWP_x:
2930 case SWPA_x:
2931 case SWPL_x:
2932 case SWPAL_x:
2933 AtomicMemorySwapHelper<uint64_t>(instr);
2934 break;
2935 case LDAPRB:
2936 LoadAcquireRCpcHelper<uint8_t>(instr);
2937 break;
2938 case LDAPRH:
2939 LoadAcquireRCpcHelper<uint16_t>(instr);
2940 break;
2941 case LDAPR_w:
2942 LoadAcquireRCpcHelper<uint32_t>(instr);
2943 break;
2944 case LDAPR_x:
2945 LoadAcquireRCpcHelper<uint64_t>(instr);
2946 break;
2947 }
2948}
2949
Alexandre Ramesd3832962016-07-04 15:03:43 +01002950
2951void Simulator::VisitLoadLiteral(const Instruction* instr) {
2952 unsigned rt = instr->GetRt();
2953 uint64_t address = instr->GetLiteralAddress<uint64_t>();
2954
2955 // Verify that the calculated address is available to the host.
2956 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2957
2958 switch (instr->Mask(LoadLiteralMask)) {
2959 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
2960 // print a more detailed log.
2961 case LDR_w_lit:
2962 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002963 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002964 break;
2965 case LDR_x_lit:
2966 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002967 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002968 break;
2969 case LDR_s_lit:
2970 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002971 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002972 break;
2973 case LDR_d_lit:
2974 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002975 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002976 break;
2977 case LDR_q_lit:
2978 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002979 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002980 break;
2981 case LDRSW_x_lit:
2982 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002983 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002984 break;
2985
2986 // Ignore prfm hint instructions.
2987 case PRFM_lit:
2988 break;
2989
2990 default:
2991 VIXL_UNREACHABLE();
2992 }
2993
2994 local_monitor_.MaybeClear();
2995}
2996
2997
2998uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
2999 int64_t offset,
3000 AddrMode addrmode) {
3001 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
3002
3003 if ((addr_reg == 31) && ((address % 16) != 0)) {
3004 // When the base register is SP the stack pointer is required to be
3005 // quadword aligned prior to the address calculation and write-backs.
3006 // Misalignment will cause a stack alignment fault.
3007 VIXL_ALIGNMENT_EXCEPTION();
3008 }
3009
3010 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
3011 VIXL_ASSERT(offset != 0);
3012 // Only preindex should log the register update here. For Postindex, the
3013 // update will be printed automatically by LogWrittenRegisters _after_ the
3014 // memory access itself is logged.
3015 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
3016 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
3017 }
3018
3019 if ((addrmode == Offset) || (addrmode == PreIndex)) {
3020 address += offset;
3021 }
3022
3023 // Verify that the calculated address is available to the host.
3024 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3025
3026 return static_cast<uintptr_t>(address);
3027}
3028
3029
3030void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
3031 MoveWideImmediateOp mov_op =
3032 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
3033 int64_t new_xn_val = 0;
3034
3035 bool is_64_bits = instr->GetSixtyFourBits() == 1;
3036 // Shift is limited for W operations.
3037 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
3038
3039 // Get the shifted immediate.
3040 int64_t shift = instr->GetShiftMoveWide() * 16;
3041 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
3042 << shift;
3043
3044 // Compute the new value.
3045 switch (mov_op) {
3046 case MOVN_w:
3047 case MOVN_x: {
3048 new_xn_val = ~shifted_imm16;
3049 if (!is_64_bits) new_xn_val &= kWRegMask;
3050 break;
3051 }
3052 case MOVK_w:
3053 case MOVK_x: {
3054 unsigned reg_code = instr->GetRd();
3055 int64_t prev_xn_val =
3056 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
3057 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
3058 break;
3059 }
3060 case MOVZ_w:
3061 case MOVZ_x: {
3062 new_xn_val = shifted_imm16;
3063 break;
3064 }
3065 default:
3066 VIXL_UNREACHABLE();
3067 }
3068
3069 // Update the destination register.
3070 WriteXRegister(instr->GetRd(), new_xn_val);
3071}
3072
3073
3074void Simulator::VisitConditionalSelect(const Instruction* instr) {
3075 uint64_t new_val = ReadXRegister(instr->GetRn());
3076
3077 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
3078 new_val = ReadXRegister(instr->GetRm());
3079 switch (instr->Mask(ConditionalSelectMask)) {
3080 case CSEL_w:
3081 case CSEL_x:
3082 break;
3083 case CSINC_w:
3084 case CSINC_x:
3085 new_val++;
3086 break;
3087 case CSINV_w:
3088 case CSINV_x:
3089 new_val = ~new_val;
3090 break;
3091 case CSNEG_w:
3092 case CSNEG_x:
3093 new_val = -new_val;
3094 break;
3095 default:
3096 VIXL_UNIMPLEMENTED();
3097 }
3098 }
3099 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3100 WriteRegister(reg_size, instr->GetRd(), new_val);
3101}
3102
3103
Jacob Bramleyca789742018-09-13 14:25:46 +01003104// clang-format off
3105#define PAUTH_MODES(V) \
3106 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
3107 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
3108 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
3109 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
3110 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
3111 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
3112 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
3113 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
3114// clang-format on
3115
Alexandre Ramesd3832962016-07-04 15:03:43 +01003116void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
3117 unsigned dst = instr->GetRd();
3118 unsigned src = instr->GetRn();
3119
3120 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003121#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
3122 case PAC##SUFFIX: { \
3123 uint64_t ptr = ReadXRegister(dst); \
3124 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
3125 break; \
3126 } \
3127 case AUT##SUFFIX: { \
3128 uint64_t ptr = ReadXRegister(dst); \
3129 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
3130 break; \
3131 }
3132
3133 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
3134#undef DEFINE_PAUTH_FUNCS
3135
3136 case XPACI:
3137 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
3138 break;
3139 case XPACD:
3140 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
3141 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003142 case RBIT_w:
3143 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
3144 break;
3145 case RBIT_x:
3146 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
3147 break;
3148 case REV16_w:
3149 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
3150 break;
3151 case REV16_x:
3152 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
3153 break;
3154 case REV_w:
3155 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
3156 break;
3157 case REV32_x:
3158 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
3159 break;
3160 case REV_x:
3161 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
3162 break;
3163 case CLZ_w:
3164 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
3165 break;
3166 case CLZ_x:
3167 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
3168 break;
3169 case CLS_w:
3170 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
3171 break;
3172 case CLS_x:
3173 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
3174 break;
3175 default:
3176 VIXL_UNIMPLEMENTED();
3177 }
3178}
3179
3180
3181uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
3182 VIXL_ASSERT((n > 32) && (n <= 64));
3183 for (unsigned i = (n - 1); i >= 32; i--) {
3184 if (((data >> i) & 1) != 0) {
3185 uint64_t polysh32 = (uint64_t)poly << (i - 32);
3186 uint64_t mask = (UINT64_C(1) << i) - 1;
3187 data = ((data & mask) ^ polysh32);
3188 }
3189 }
3190 return data & 0xffffffff;
3191}
3192
3193
3194template <typename T>
3195uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
3196 unsigned size = sizeof(val) * 8; // Number of bits in type T.
3197 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
3198 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
3199 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
3200 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
3201}
3202
3203
3204uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
3205 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
3206 // the CRC of each 32-bit word sequentially.
3207 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
3208 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
3209}
3210
3211
3212void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
3213 Shift shift_op = NO_SHIFT;
3214 int64_t result = 0;
3215 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3216
3217 switch (instr->Mask(DataProcessing2SourceMask)) {
3218 case SDIV_w: {
3219 int32_t rn = ReadWRegister(instr->GetRn());
3220 int32_t rm = ReadWRegister(instr->GetRm());
3221 if ((rn == kWMinInt) && (rm == -1)) {
3222 result = kWMinInt;
3223 } else if (rm == 0) {
3224 // Division by zero can be trapped, but not on A-class processors.
3225 result = 0;
3226 } else {
3227 result = rn / rm;
3228 }
3229 break;
3230 }
3231 case SDIV_x: {
3232 int64_t rn = ReadXRegister(instr->GetRn());
3233 int64_t rm = ReadXRegister(instr->GetRm());
3234 if ((rn == kXMinInt) && (rm == -1)) {
3235 result = kXMinInt;
3236 } else if (rm == 0) {
3237 // Division by zero can be trapped, but not on A-class processors.
3238 result = 0;
3239 } else {
3240 result = rn / rm;
3241 }
3242 break;
3243 }
3244 case UDIV_w: {
3245 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
3246 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
3247 if (rm == 0) {
3248 // Division by zero can be trapped, but not on A-class processors.
3249 result = 0;
3250 } else {
3251 result = rn / rm;
3252 }
3253 break;
3254 }
3255 case UDIV_x: {
3256 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3257 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
3258 if (rm == 0) {
3259 // Division by zero can be trapped, but not on A-class processors.
3260 result = 0;
3261 } else {
3262 result = rn / rm;
3263 }
3264 break;
3265 }
3266 case LSLV_w:
3267 case LSLV_x:
3268 shift_op = LSL;
3269 break;
3270 case LSRV_w:
3271 case LSRV_x:
3272 shift_op = LSR;
3273 break;
3274 case ASRV_w:
3275 case ASRV_x:
3276 shift_op = ASR;
3277 break;
3278 case RORV_w:
3279 case RORV_x:
3280 shift_op = ROR;
3281 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003282 case PACGA: {
3283 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3284 uint64_t src = static_cast<uint64_t>(
3285 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
3286 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
3287 result = code & 0xffffffff00000000;
3288 break;
3289 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003290 case CRC32B: {
3291 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3292 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3293 result = Crc32Checksum(acc, val, CRC32_POLY);
3294 break;
3295 }
3296 case CRC32H: {
3297 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3298 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3299 result = Crc32Checksum(acc, val, CRC32_POLY);
3300 break;
3301 }
3302 case CRC32W: {
3303 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3304 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3305 result = Crc32Checksum(acc, val, CRC32_POLY);
3306 break;
3307 }
3308 case CRC32X: {
3309 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3310 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3311 result = Crc32Checksum(acc, val, CRC32_POLY);
3312 reg_size = kWRegSize;
3313 break;
3314 }
3315 case CRC32CB: {
3316 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3317 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3318 result = Crc32Checksum(acc, val, CRC32C_POLY);
3319 break;
3320 }
3321 case CRC32CH: {
3322 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3323 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3324 result = Crc32Checksum(acc, val, CRC32C_POLY);
3325 break;
3326 }
3327 case CRC32CW: {
3328 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3329 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3330 result = Crc32Checksum(acc, val, CRC32C_POLY);
3331 break;
3332 }
3333 case CRC32CX: {
3334 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3335 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3336 result = Crc32Checksum(acc, val, CRC32C_POLY);
3337 reg_size = kWRegSize;
3338 break;
3339 }
3340 default:
3341 VIXL_UNIMPLEMENTED();
3342 }
3343
3344 if (shift_op != NO_SHIFT) {
3345 // Shift distance encoded in the least-significant five/six bits of the
3346 // register.
3347 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
3348 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
3349 result = ShiftOperand(reg_size,
3350 ReadRegister(reg_size, instr->GetRn()),
3351 shift_op,
3352 shift);
3353 }
3354 WriteRegister(reg_size, instr->GetRd(), result);
3355}
3356
3357
Alexandre Ramesd3832962016-07-04 15:03:43 +01003358void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
3359 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3360
3361 uint64_t result = 0;
3362 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
3363 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
3364 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
3365 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
3366 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003367 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
3368 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003369 switch (instr->Mask(DataProcessing3SourceMask)) {
3370 case MADD_w:
3371 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003372 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003373 break;
3374 case MSUB_w:
3375 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003376 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003377 break;
3378 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003379 result = ReadXRegister(instr->GetRa()) +
3380 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003381 break;
3382 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003383 result = ReadXRegister(instr->GetRa()) -
3384 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003385 break;
3386 case UMADDL_x:
3387 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
3388 break;
3389 case UMSUBL_x:
3390 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
3391 break;
3392 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003393 result =
3394 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
3395 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003396 break;
3397 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003398 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
3399 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003400 break;
3401 default:
3402 VIXL_UNIMPLEMENTED();
3403 }
3404 WriteRegister(reg_size, instr->GetRd(), result);
3405}
3406
3407
3408void Simulator::VisitBitfield(const Instruction* instr) {
3409 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3410 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003411 int R = instr->GetImmR();
3412 int S = instr->GetImmS();
3413 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003414 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003415 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003416 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003417 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003418 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003419 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003420 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003421 diff += reg_size;
3422 }
3423
3424 // inzero indicates if the extracted bitfield is inserted into the
3425 // destination register value or in zero.
3426 // If extend is true, extend the sign of the extracted bitfield.
3427 bool inzero = false;
3428 bool extend = false;
3429 switch (instr->Mask(BitfieldMask)) {
3430 case BFM_x:
3431 case BFM_w:
3432 break;
3433 case SBFM_x:
3434 case SBFM_w:
3435 inzero = true;
3436 extend = true;
3437 break;
3438 case UBFM_x:
3439 case UBFM_w:
3440 inzero = true;
3441 break;
3442 default:
3443 VIXL_UNIMPLEMENTED();
3444 }
3445
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003446 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
3447 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003448 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003449 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003450 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003451 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
3452 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003453
3454 // Merge sign extension, dest/zero and bitfield.
3455 result = signbits | (result & mask) | (dst & ~mask);
3456
3457 WriteRegister(reg_size, instr->GetRd(), result);
3458}
3459
3460
3461void Simulator::VisitExtract(const Instruction* instr) {
3462 unsigned lsb = instr->GetImmS();
3463 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3464 uint64_t low_res =
3465 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003466 uint64_t high_res =
3467 (lsb == 0) ? 0 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
3468 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003469 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
3470}
3471
3472
3473void Simulator::VisitFPImmediate(const Instruction* instr) {
3474 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01003475 unsigned dest = instr->GetRd();
3476 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003477 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01003478 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01003479 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003480 case FMOV_s_imm:
3481 WriteSRegister(dest, instr->GetImmFP32());
3482 break;
3483 case FMOV_d_imm:
3484 WriteDRegister(dest, instr->GetImmFP64());
3485 break;
3486 default:
3487 VIXL_UNREACHABLE();
3488 }
3489}
3490
3491
3492void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
3493 AssertSupportedFPCR();
3494
3495 unsigned dst = instr->GetRd();
3496 unsigned src = instr->GetRn();
3497
3498 FPRounding round = ReadRMode();
3499
3500 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003501 case FCVTAS_wh:
3502 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
3503 break;
3504 case FCVTAS_xh:
3505 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
3506 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003507 case FCVTAS_ws:
3508 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
3509 break;
3510 case FCVTAS_xs:
3511 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
3512 break;
3513 case FCVTAS_wd:
3514 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
3515 break;
3516 case FCVTAS_xd:
3517 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
3518 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003519 case FCVTAU_wh:
3520 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
3521 break;
3522 case FCVTAU_xh:
3523 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
3524 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003525 case FCVTAU_ws:
3526 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3527 break;
3528 case FCVTAU_xs:
3529 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3530 break;
3531 case FCVTAU_wd:
3532 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3533 break;
3534 case FCVTAU_xd:
3535 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3536 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003537 case FCVTMS_wh:
3538 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3539 break;
3540 case FCVTMS_xh:
3541 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3542 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003543 case FCVTMS_ws:
3544 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3545 break;
3546 case FCVTMS_xs:
3547 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3548 break;
3549 case FCVTMS_wd:
3550 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3551 break;
3552 case FCVTMS_xd:
3553 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3554 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003555 case FCVTMU_wh:
3556 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3557 break;
3558 case FCVTMU_xh:
3559 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3560 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003561 case FCVTMU_ws:
3562 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3563 break;
3564 case FCVTMU_xs:
3565 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3566 break;
3567 case FCVTMU_wd:
3568 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3569 break;
3570 case FCVTMU_xd:
3571 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3572 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003573 case FCVTPS_wh:
3574 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3575 break;
3576 case FCVTPS_xh:
3577 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3578 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003579 case FCVTPS_ws:
3580 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3581 break;
3582 case FCVTPS_xs:
3583 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3584 break;
3585 case FCVTPS_wd:
3586 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3587 break;
3588 case FCVTPS_xd:
3589 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3590 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003591 case FCVTPU_wh:
3592 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3593 break;
3594 case FCVTPU_xh:
3595 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3596 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003597 case FCVTPU_ws:
3598 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3599 break;
3600 case FCVTPU_xs:
3601 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3602 break;
3603 case FCVTPU_wd:
3604 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3605 break;
3606 case FCVTPU_xd:
3607 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3608 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003609 case FCVTNS_wh:
3610 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3611 break;
3612 case FCVTNS_xh:
3613 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3614 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003615 case FCVTNS_ws:
3616 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3617 break;
3618 case FCVTNS_xs:
3619 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3620 break;
3621 case FCVTNS_wd:
3622 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3623 break;
3624 case FCVTNS_xd:
3625 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3626 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003627 case FCVTNU_wh:
3628 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3629 break;
3630 case FCVTNU_xh:
3631 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3632 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003633 case FCVTNU_ws:
3634 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3635 break;
3636 case FCVTNU_xs:
3637 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3638 break;
3639 case FCVTNU_wd:
3640 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3641 break;
3642 case FCVTNU_xd:
3643 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3644 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003645 case FCVTZS_wh:
3646 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3647 break;
3648 case FCVTZS_xh:
3649 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3650 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003651 case FCVTZS_ws:
3652 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3653 break;
3654 case FCVTZS_xs:
3655 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3656 break;
3657 case FCVTZS_wd:
3658 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3659 break;
3660 case FCVTZS_xd:
3661 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3662 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003663 case FCVTZU_wh:
3664 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3665 break;
3666 case FCVTZU_xh:
3667 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3668 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003669 case FCVTZU_ws:
3670 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3671 break;
3672 case FCVTZU_xs:
3673 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3674 break;
3675 case FCVTZU_wd:
3676 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3677 break;
3678 case FCVTZU_xd:
3679 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3680 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003681 case FJCVTZS:
3682 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3683 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003684 case FMOV_hw:
3685 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3686 break;
3687 case FMOV_wh:
3688 WriteWRegister(dst, ReadHRegisterBits(src));
3689 break;
3690 case FMOV_xh:
3691 WriteXRegister(dst, ReadHRegisterBits(src));
3692 break;
3693 case FMOV_hx:
3694 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3695 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003696 case FMOV_ws:
3697 WriteWRegister(dst, ReadSRegisterBits(src));
3698 break;
3699 case FMOV_xd:
3700 WriteXRegister(dst, ReadDRegisterBits(src));
3701 break;
3702 case FMOV_sw:
3703 WriteSRegisterBits(dst, ReadWRegister(src));
3704 break;
3705 case FMOV_dx:
3706 WriteDRegisterBits(dst, ReadXRegister(src));
3707 break;
3708 case FMOV_d1_x:
3709 LogicVRegister(ReadVRegister(dst))
3710 .SetUint(kFormatD, 1, ReadXRegister(src));
3711 break;
3712 case FMOV_x_d1:
3713 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3714 break;
3715
3716 // A 32-bit input can be handled in the same way as a 64-bit input, since
3717 // the sign- or zero-extension will not affect the conversion.
3718 case SCVTF_dx:
3719 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3720 break;
3721 case SCVTF_dw:
3722 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3723 break;
3724 case UCVTF_dx:
3725 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3726 break;
3727 case UCVTF_dw: {
3728 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003729 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003730 break;
3731 }
3732 case SCVTF_sx:
3733 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3734 break;
3735 case SCVTF_sw:
3736 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3737 break;
3738 case UCVTF_sx:
3739 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3740 break;
3741 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01003742 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3743 break;
3744 }
3745 case SCVTF_hx:
3746 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3747 break;
3748 case SCVTF_hw:
3749 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3750 break;
3751 case UCVTF_hx:
3752 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3753 break;
3754 case UCVTF_hw: {
3755 WriteHRegister(dst,
3756 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003757 break;
3758 }
3759
3760 default:
3761 VIXL_UNREACHABLE();
3762 }
3763}
3764
3765
3766void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3767 AssertSupportedFPCR();
3768
3769 unsigned dst = instr->GetRd();
3770 unsigned src = instr->GetRn();
3771 int fbits = 64 - instr->GetFPScale();
3772
3773 FPRounding round = ReadRMode();
3774
3775 switch (instr->Mask(FPFixedPointConvertMask)) {
3776 // A 32-bit input can be handled in the same way as a 64-bit input, since
3777 // the sign- or zero-extension will not affect the conversion.
3778 case SCVTF_dx_fixed:
3779 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3780 break;
3781 case SCVTF_dw_fixed:
3782 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3783 break;
3784 case UCVTF_dx_fixed:
3785 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3786 break;
3787 case UCVTF_dw_fixed: {
3788 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003789 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003790 break;
3791 }
3792 case SCVTF_sx_fixed:
3793 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3794 break;
3795 case SCVTF_sw_fixed:
3796 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3797 break;
3798 case UCVTF_sx_fixed:
3799 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3800 break;
3801 case UCVTF_sw_fixed: {
3802 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003803 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3804 break;
3805 }
3806 case SCVTF_hx_fixed:
3807 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3808 break;
3809 case SCVTF_hw_fixed:
3810 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3811 break;
3812 case UCVTF_hx_fixed:
3813 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3814 break;
3815 case UCVTF_hw_fixed: {
3816 WriteHRegister(dst,
3817 UFixedToFloat16(ReadRegister<uint32_t>(src),
3818 fbits,
3819 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003820 break;
3821 }
3822 case FCVTZS_xd_fixed:
3823 WriteXRegister(dst,
3824 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3825 FPZero));
3826 break;
3827 case FCVTZS_wd_fixed:
3828 WriteWRegister(dst,
3829 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3830 FPZero));
3831 break;
3832 case FCVTZU_xd_fixed:
3833 WriteXRegister(dst,
3834 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3835 FPZero));
3836 break;
3837 case FCVTZU_wd_fixed:
3838 WriteWRegister(dst,
3839 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3840 FPZero));
3841 break;
3842 case FCVTZS_xs_fixed:
3843 WriteXRegister(dst,
3844 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3845 FPZero));
3846 break;
3847 case FCVTZS_ws_fixed:
3848 WriteWRegister(dst,
3849 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3850 FPZero));
3851 break;
3852 case FCVTZU_xs_fixed:
3853 WriteXRegister(dst,
3854 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3855 FPZero));
3856 break;
3857 case FCVTZU_ws_fixed:
3858 WriteWRegister(dst,
3859 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3860 FPZero));
3861 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003862 case FCVTZS_xh_fixed: {
3863 double output =
3864 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3865 WriteXRegister(dst, FPToInt64(output, FPZero));
3866 break;
3867 }
3868 case FCVTZS_wh_fixed: {
3869 double output =
3870 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3871 WriteWRegister(dst, FPToInt32(output, FPZero));
3872 break;
3873 }
3874 case FCVTZU_xh_fixed: {
3875 double output =
3876 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3877 WriteXRegister(dst, FPToUInt64(output, FPZero));
3878 break;
3879 }
3880 case FCVTZU_wh_fixed: {
3881 double output =
3882 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3883 WriteWRegister(dst, FPToUInt32(output, FPZero));
3884 break;
3885 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003886 default:
3887 VIXL_UNREACHABLE();
3888 }
3889}
3890
3891
3892void Simulator::VisitFPCompare(const Instruction* instr) {
3893 AssertSupportedFPCR();
3894
3895 FPTrapFlags trap = DisableTrap;
3896 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003897 case FCMPE_h:
3898 trap = EnableTrap;
3899 VIXL_FALLTHROUGH();
3900 case FCMP_h:
3901 FPCompare(ReadHRegister(instr->GetRn()),
3902 ReadHRegister(instr->GetRm()),
3903 trap);
3904 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003905 case FCMPE_s:
3906 trap = EnableTrap;
3907 VIXL_FALLTHROUGH();
3908 case FCMP_s:
3909 FPCompare(ReadSRegister(instr->GetRn()),
3910 ReadSRegister(instr->GetRm()),
3911 trap);
3912 break;
3913 case FCMPE_d:
3914 trap = EnableTrap;
3915 VIXL_FALLTHROUGH();
3916 case FCMP_d:
3917 FPCompare(ReadDRegister(instr->GetRn()),
3918 ReadDRegister(instr->GetRm()),
3919 trap);
3920 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003921 case FCMPE_h_zero:
3922 trap = EnableTrap;
3923 VIXL_FALLTHROUGH();
3924 case FCMP_h_zero:
3925 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3926 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003927 case FCMPE_s_zero:
3928 trap = EnableTrap;
3929 VIXL_FALLTHROUGH();
3930 case FCMP_s_zero:
3931 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3932 break;
3933 case FCMPE_d_zero:
3934 trap = EnableTrap;
3935 VIXL_FALLTHROUGH();
3936 case FCMP_d_zero:
3937 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
3938 break;
3939 default:
3940 VIXL_UNIMPLEMENTED();
3941 }
3942}
3943
3944
3945void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
3946 AssertSupportedFPCR();
3947
3948 FPTrapFlags trap = DisableTrap;
3949 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003950 case FCCMPE_h:
3951 trap = EnableTrap;
3952 VIXL_FALLTHROUGH();
3953 case FCCMP_h:
3954 if (ConditionPassed(instr->GetCondition())) {
3955 FPCompare(ReadHRegister(instr->GetRn()),
3956 ReadHRegister(instr->GetRm()),
3957 trap);
3958 } else {
3959 ReadNzcv().SetFlags(instr->GetNzcv());
3960 LogSystemRegister(NZCV);
3961 }
3962 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003963 case FCCMPE_s:
3964 trap = EnableTrap;
3965 VIXL_FALLTHROUGH();
3966 case FCCMP_s:
3967 if (ConditionPassed(instr->GetCondition())) {
3968 FPCompare(ReadSRegister(instr->GetRn()),
3969 ReadSRegister(instr->GetRm()),
3970 trap);
3971 } else {
3972 ReadNzcv().SetFlags(instr->GetNzcv());
3973 LogSystemRegister(NZCV);
3974 }
3975 break;
3976 case FCCMPE_d:
3977 trap = EnableTrap;
3978 VIXL_FALLTHROUGH();
3979 case FCCMP_d:
3980 if (ConditionPassed(instr->GetCondition())) {
3981 FPCompare(ReadDRegister(instr->GetRn()),
3982 ReadDRegister(instr->GetRm()),
3983 trap);
3984 } else {
3985 ReadNzcv().SetFlags(instr->GetNzcv());
3986 LogSystemRegister(NZCV);
3987 }
3988 break;
3989 default:
3990 VIXL_UNIMPLEMENTED();
3991 }
3992}
3993
3994
3995void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
3996 AssertSupportedFPCR();
3997
3998 Instr selected;
3999 if (ConditionPassed(instr->GetCondition())) {
4000 selected = instr->GetRn();
4001 } else {
4002 selected = instr->GetRm();
4003 }
4004
4005 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004006 case FCSEL_h:
4007 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
4008 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004009 case FCSEL_s:
4010 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
4011 break;
4012 case FCSEL_d:
4013 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
4014 break;
4015 default:
4016 VIXL_UNIMPLEMENTED();
4017 }
4018}
4019
4020
4021void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
4022 AssertSupportedFPCR();
4023
4024 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01004025 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01004026 switch (instr->Mask(FPTypeMask)) {
4027 default:
4028 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4029 case FP64:
4030 vform = kFormatD;
4031 break;
4032 case FP32:
4033 vform = kFormatS;
4034 break;
4035 case FP16:
4036 vform = kFormatH;
4037 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004038 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004039
Alexandre Ramesd3832962016-07-04 15:03:43 +01004040 SimVRegister& rd = ReadVRegister(instr->GetRd());
4041 SimVRegister& rn = ReadVRegister(instr->GetRn());
4042 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004043 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004044
4045 unsigned fd = instr->GetRd();
4046 unsigned fn = instr->GetRn();
4047
4048 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01004049 case FMOV_h:
4050 WriteHRegister(fd, ReadHRegister(fn));
4051 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004052 case FMOV_s:
4053 WriteSRegister(fd, ReadSRegister(fn));
4054 return;
4055 case FMOV_d:
4056 WriteDRegister(fd, ReadDRegister(fn));
4057 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004058 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004059 case FABS_s:
4060 case FABS_d:
4061 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
4062 // Explicitly log the register update whilst we have type information.
4063 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4064 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004065 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004066 case FNEG_s:
4067 case FNEG_d:
4068 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
4069 // Explicitly log the register update whilst we have type information.
4070 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4071 return;
4072 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01004073 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004074 return;
4075 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01004076 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004077 return;
4078 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01004079 WriteHRegister(fd,
4080 Float16ToRawbits(
4081 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004082 return;
4083 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01004084 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004085 return;
4086 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01004087 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004088 return;
4089 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01004090 WriteHRegister(fd,
4091 Float16ToRawbits(
4092 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004093 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004094 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004095 case FSQRT_s:
4096 case FSQRT_d:
4097 fsqrt(vform, rd, rn);
4098 // Explicitly log the register update whilst we have type information.
4099 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4100 return;
TatWai Chong04471812019-03-19 14:29:00 -07004101 case FRINT32X_s:
4102 case FRINT32X_d:
4103 inexact_exception = true;
4104 frint_mode = kFrintToInt32;
4105 break; // Use FPCR rounding mode.
4106 case FRINT64X_s:
4107 case FRINT64X_d:
4108 inexact_exception = true;
4109 frint_mode = kFrintToInt64;
4110 break; // Use FPCR rounding mode.
4111 case FRINT32Z_s:
4112 case FRINT32Z_d:
4113 inexact_exception = true;
4114 frint_mode = kFrintToInt32;
4115 fpcr_rounding = FPZero;
4116 break;
4117 case FRINT64Z_s:
4118 case FRINT64Z_d:
4119 inexact_exception = true;
4120 frint_mode = kFrintToInt64;
4121 fpcr_rounding = FPZero;
4122 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004123 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004124 case FRINTI_s:
4125 case FRINTI_d:
4126 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01004127 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004128 case FRINTX_s:
4129 case FRINTX_d:
4130 inexact_exception = true;
4131 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004132 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004133 case FRINTA_s:
4134 case FRINTA_d:
4135 fpcr_rounding = FPTieAway;
4136 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004137 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004138 case FRINTM_s:
4139 case FRINTM_d:
4140 fpcr_rounding = FPNegativeInfinity;
4141 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004142 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004143 case FRINTN_s:
4144 case FRINTN_d:
4145 fpcr_rounding = FPTieEven;
4146 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004147 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004148 case FRINTP_s:
4149 case FRINTP_d:
4150 fpcr_rounding = FPPositiveInfinity;
4151 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004152 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004153 case FRINTZ_s:
4154 case FRINTZ_d:
4155 fpcr_rounding = FPZero;
4156 break;
4157 default:
4158 VIXL_UNIMPLEMENTED();
4159 }
4160
4161 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004162 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004163 // Explicitly log the register update whilst we have type information.
4164 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4165}
4166
4167
4168void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
4169 AssertSupportedFPCR();
4170
Carey Williamsd8bb3572018-04-10 11:58:07 +01004171 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01004172 switch (instr->Mask(FPTypeMask)) {
4173 default:
4174 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4175 case FP64:
4176 vform = kFormatD;
4177 break;
4178 case FP32:
4179 vform = kFormatS;
4180 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004181 case FP16:
4182 vform = kFormatH;
4183 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004184 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004185 SimVRegister& rd = ReadVRegister(instr->GetRd());
4186 SimVRegister& rn = ReadVRegister(instr->GetRn());
4187 SimVRegister& rm = ReadVRegister(instr->GetRm());
4188
4189 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004190 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004191 case FADD_s:
4192 case FADD_d:
4193 fadd(vform, rd, rn, rm);
4194 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004195 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004196 case FSUB_s:
4197 case FSUB_d:
4198 fsub(vform, rd, rn, rm);
4199 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004200 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004201 case FMUL_s:
4202 case FMUL_d:
4203 fmul(vform, rd, rn, rm);
4204 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004205 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004206 case FNMUL_s:
4207 case FNMUL_d:
4208 fnmul(vform, rd, rn, rm);
4209 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004210 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004211 case FDIV_s:
4212 case FDIV_d:
4213 fdiv(vform, rd, rn, rm);
4214 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004215 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004216 case FMAX_s:
4217 case FMAX_d:
4218 fmax(vform, rd, rn, rm);
4219 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004220 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004221 case FMIN_s:
4222 case FMIN_d:
4223 fmin(vform, rd, rn, rm);
4224 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004225 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004226 case FMAXNM_s:
4227 case FMAXNM_d:
4228 fmaxnm(vform, rd, rn, rm);
4229 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004230 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004231 case FMINNM_s:
4232 case FMINNM_d:
4233 fminnm(vform, rd, rn, rm);
4234 break;
4235 default:
4236 VIXL_UNREACHABLE();
4237 }
4238 // Explicitly log the register update whilst we have type information.
4239 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
4240}
4241
4242
4243void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
4244 AssertSupportedFPCR();
4245
4246 unsigned fd = instr->GetRd();
4247 unsigned fn = instr->GetRn();
4248 unsigned fm = instr->GetRm();
4249 unsigned fa = instr->GetRa();
4250
4251 switch (instr->Mask(FPDataProcessing3SourceMask)) {
4252 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01004253 case FMADD_h:
4254 WriteHRegister(fd,
4255 FPMulAdd(ReadHRegister(fa),
4256 ReadHRegister(fn),
4257 ReadHRegister(fm)));
4258 break;
4259 case FMSUB_h:
4260 WriteHRegister(fd,
4261 FPMulAdd(ReadHRegister(fa),
4262 -ReadHRegister(fn),
4263 ReadHRegister(fm)));
4264 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004265 case FMADD_s:
4266 WriteSRegister(fd,
4267 FPMulAdd(ReadSRegister(fa),
4268 ReadSRegister(fn),
4269 ReadSRegister(fm)));
4270 break;
4271 case FMSUB_s:
4272 WriteSRegister(fd,
4273 FPMulAdd(ReadSRegister(fa),
4274 -ReadSRegister(fn),
4275 ReadSRegister(fm)));
4276 break;
4277 case FMADD_d:
4278 WriteDRegister(fd,
4279 FPMulAdd(ReadDRegister(fa),
4280 ReadDRegister(fn),
4281 ReadDRegister(fm)));
4282 break;
4283 case FMSUB_d:
4284 WriteDRegister(fd,
4285 FPMulAdd(ReadDRegister(fa),
4286 -ReadDRegister(fn),
4287 ReadDRegister(fm)));
4288 break;
4289 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01004290 case FNMADD_h:
4291 WriteHRegister(fd,
4292 FPMulAdd(-ReadHRegister(fa),
4293 -ReadHRegister(fn),
4294 ReadHRegister(fm)));
4295 break;
4296 case FNMSUB_h:
4297 WriteHRegister(fd,
4298 FPMulAdd(-ReadHRegister(fa),
4299 ReadHRegister(fn),
4300 ReadHRegister(fm)));
4301 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004302 case FNMADD_s:
4303 WriteSRegister(fd,
4304 FPMulAdd(-ReadSRegister(fa),
4305 -ReadSRegister(fn),
4306 ReadSRegister(fm)));
4307 break;
4308 case FNMSUB_s:
4309 WriteSRegister(fd,
4310 FPMulAdd(-ReadSRegister(fa),
4311 ReadSRegister(fn),
4312 ReadSRegister(fm)));
4313 break;
4314 case FNMADD_d:
4315 WriteDRegister(fd,
4316 FPMulAdd(-ReadDRegister(fa),
4317 -ReadDRegister(fn),
4318 ReadDRegister(fm)));
4319 break;
4320 case FNMSUB_d:
4321 WriteDRegister(fd,
4322 FPMulAdd(-ReadDRegister(fa),
4323 ReadDRegister(fn),
4324 ReadDRegister(fm)));
4325 break;
4326 default:
4327 VIXL_UNIMPLEMENTED();
4328 }
4329}
4330
4331
4332bool Simulator::FPProcessNaNs(const Instruction* instr) {
4333 unsigned fd = instr->GetRd();
4334 unsigned fn = instr->GetRn();
4335 unsigned fm = instr->GetRm();
4336 bool done = false;
4337
4338 if (instr->Mask(FP64) == FP64) {
4339 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004340 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004341 WriteDRegister(fd, result);
4342 done = true;
4343 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004344 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004345 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004346 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004347 WriteSRegister(fd, result);
4348 done = true;
4349 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004350 } else {
4351 VIXL_ASSERT(instr->Mask(FP16) == FP16);
4352 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01004353 }
4354
4355 return done;
4356}
4357
4358
4359void Simulator::SysOp_W(int op, int64_t val) {
4360 switch (op) {
4361 case IVAU:
4362 case CVAC:
4363 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01004364 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08004365 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004366 case CIVAC: {
4367 // Perform a dummy memory access to ensure that we have read access
4368 // to the specified address.
4369 volatile uint8_t y = Memory::Read<uint8_t>(val);
4370 USE(y);
4371 // TODO: Implement "case ZVA:".
4372 break;
4373 }
4374 default:
4375 VIXL_UNIMPLEMENTED();
4376 }
4377}
4378
4379
Jacob Bramleyca789742018-09-13 14:25:46 +01004380// clang-format off
4381#define PAUTH_SYSTEM_MODES(V) \
4382 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
4383 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
4384 V(AZ, 30, 0x00000000, kPACKeyIA) \
4385 V(BZ, 30, 0x00000000, kPACKeyIB) \
4386 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
4387 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
4388// clang-format on
4389
4390
Alexandre Ramesd3832962016-07-04 15:03:43 +01004391void Simulator::VisitSystem(const Instruction* instr) {
4392 // Some system instructions hijack their Op and Cp fields to represent a
4393 // range of immediates instead of indicating a different instruction. This
4394 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01004395 if (instr->GetInstructionBits() == XPACLRI) {
4396 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00004397 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
4398 switch (instr->Mask(SystemPStateMask)) {
4399 case CFINV:
4400 ReadNzcv().SetC(!ReadC());
4401 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00004402 case AXFLAG:
4403 ReadNzcv().SetN(0);
4404 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
4405 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
4406 ReadNzcv().SetV(0);
4407 break;
4408 case XAFLAG: {
4409 // Can't set the flags in place due to the logical dependencies.
4410 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
4411 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
4412 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
4413 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
4414 ReadNzcv().SetN(n);
4415 ReadNzcv().SetZ(z);
4416 ReadNzcv().SetC(c);
4417 ReadNzcv().SetV(v);
4418 break;
4419 }
Alexander Gilday2487f142018-11-05 13:07:27 +00004420 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004421 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004422 // Check BType allows PACI[AB]SP instructions.
4423 if (PcIsInGuardedPage()) {
4424 Instr i = instr->Mask(SystemPAuthMask);
4425 if ((i == PACIASP) || (i == PACIBSP)) {
4426 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004427 case BranchFromGuardedNotToIP:
4428 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
4429 // assume here to be zero. This allows execution of PACI[AB]SP when
4430 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00004431 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004432 case BranchFromUnguardedOrToIP:
4433 case BranchAndLink:
4434 break;
4435 }
4436 }
4437 }
4438
Jacob Bramleyca789742018-09-13 14:25:46 +01004439 switch (instr->Mask(SystemPAuthMask)) {
4440#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
4441 case PACI##SUFFIX: \
4442 WriteXRegister(DST, \
4443 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
4444 break; \
4445 case AUTI##SUFFIX: \
4446 WriteXRegister(DST, \
4447 AuthPAC(ReadXRegister(DST), \
4448 MOD, \
4449 KEY, \
4450 kInstructionPointer)); \
4451 break;
4452
4453 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
4454#undef DEFINE_PAUTH_FUNCS
4455 }
4456 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
4457 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004458 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
4459 switch (instr->Mask(SystemExclusiveMonitorMask)) {
4460 case CLREX: {
4461 PrintExclusiveAccessWarning();
4462 ClearLocalMonitor();
4463 break;
4464 }
4465 }
4466 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
4467 switch (instr->Mask(SystemSysRegMask)) {
4468 case MRS: {
4469 switch (instr->GetImmSystemRegister()) {
4470 case NZCV:
4471 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
4472 break;
4473 case FPCR:
4474 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
4475 break;
TatWai Chong04edf682018-12-27 16:01:02 -08004476 case RNDR:
4477 case RNDRRS: {
4478 uint64_t high = jrand48(rndr_state_);
4479 uint64_t low = jrand48(rndr_state_);
4480 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
4481 WriteXRegister(instr->GetRt(), rand_num);
4482 // Simulate successful random number generation.
4483 // TODO: Return failure occasionally as a random number cannot be
4484 // returned in a period of time.
4485 ReadNzcv().SetRawValue(NoFlag);
4486 LogSystemRegister(NZCV);
4487 break;
4488 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004489 default:
4490 VIXL_UNIMPLEMENTED();
4491 }
4492 break;
4493 }
4494 case MSR: {
4495 switch (instr->GetImmSystemRegister()) {
4496 case NZCV:
4497 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
4498 LogSystemRegister(NZCV);
4499 break;
4500 case FPCR:
4501 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
4502 LogSystemRegister(FPCR);
4503 break;
4504 default:
4505 VIXL_UNIMPLEMENTED();
4506 }
4507 break;
4508 }
4509 }
4510 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
4511 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
4512 switch (instr->GetImmHint()) {
4513 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01004514 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00004515 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004516 case BTI_jc:
4517 break;
4518 case BTI:
4519 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
4520 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
4521 }
4522 break;
4523 case BTI_c:
4524 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
4525 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
4526 }
4527 break;
4528 case BTI_j:
4529 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4530 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4531 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004532 break;
4533 default:
4534 VIXL_UNIMPLEMENTED();
4535 }
4536 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4537 __sync_synchronize();
4538 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4539 switch (instr->Mask(SystemSysMask)) {
4540 case SYS:
4541 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4542 break;
4543 default:
4544 VIXL_UNIMPLEMENTED();
4545 }
4546 } else {
4547 VIXL_UNIMPLEMENTED();
4548 }
4549}
4550
4551
4552void Simulator::VisitException(const Instruction* instr) {
4553 switch (instr->Mask(ExceptionMask)) {
4554 case HLT:
4555 switch (instr->GetImmException()) {
4556 case kUnreachableOpcode:
4557 DoUnreachable(instr);
4558 return;
4559 case kTraceOpcode:
4560 DoTrace(instr);
4561 return;
4562 case kLogOpcode:
4563 DoLog(instr);
4564 return;
4565 case kPrintfOpcode:
4566 DoPrintf(instr);
4567 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01004568 case kRuntimeCallOpcode:
4569 DoRuntimeCall(instr);
4570 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01004571 case kSetCPUFeaturesOpcode:
4572 case kEnableCPUFeaturesOpcode:
4573 case kDisableCPUFeaturesOpcode:
4574 DoConfigureCPUFeatures(instr);
4575 return;
4576 case kSaveCPUFeaturesOpcode:
4577 DoSaveCPUFeatures(instr);
4578 return;
4579 case kRestoreCPUFeaturesOpcode:
4580 DoRestoreCPUFeatures(instr);
4581 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004582 default:
4583 HostBreakpoint();
4584 return;
4585 }
4586 case BRK:
4587 HostBreakpoint();
4588 return;
4589 default:
4590 VIXL_UNIMPLEMENTED();
4591 }
4592}
4593
4594
4595void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4596 VisitUnimplemented(instr);
4597}
4598
4599
4600void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4601 VisitUnimplemented(instr);
4602}
4603
4604
4605void Simulator::VisitCryptoAES(const Instruction* instr) {
4606 VisitUnimplemented(instr);
4607}
4608
4609
4610void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4611 NEONFormatDecoder nfd(instr);
4612 VectorFormat vf = nfd.GetVectorFormat();
4613
4614 static const NEONFormatMap map_lp =
4615 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4616 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4617
4618 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4619 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4620
4621 static const NEONFormatMap map_fcvtn = {{22, 30},
4622 {NF_4H, NF_8H, NF_2S, NF_4S}};
4623 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4624
4625 SimVRegister& rd = ReadVRegister(instr->GetRd());
4626 SimVRegister& rn = ReadVRegister(instr->GetRn());
4627
4628 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4629 // These instructions all use a two bit size field, except NOT and RBIT,
4630 // which use the field to encode the operation.
4631 switch (instr->Mask(NEON2RegMiscMask)) {
4632 case NEON_REV64:
4633 rev64(vf, rd, rn);
4634 break;
4635 case NEON_REV32:
4636 rev32(vf, rd, rn);
4637 break;
4638 case NEON_REV16:
4639 rev16(vf, rd, rn);
4640 break;
4641 case NEON_SUQADD:
4642 suqadd(vf, rd, rn);
4643 break;
4644 case NEON_USQADD:
4645 usqadd(vf, rd, rn);
4646 break;
4647 case NEON_CLS:
4648 cls(vf, rd, rn);
4649 break;
4650 case NEON_CLZ:
4651 clz(vf, rd, rn);
4652 break;
4653 case NEON_CNT:
4654 cnt(vf, rd, rn);
4655 break;
4656 case NEON_SQABS:
4657 abs(vf, rd, rn).SignedSaturate(vf);
4658 break;
4659 case NEON_SQNEG:
4660 neg(vf, rd, rn).SignedSaturate(vf);
4661 break;
4662 case NEON_CMGT_zero:
4663 cmp(vf, rd, rn, 0, gt);
4664 break;
4665 case NEON_CMGE_zero:
4666 cmp(vf, rd, rn, 0, ge);
4667 break;
4668 case NEON_CMEQ_zero:
4669 cmp(vf, rd, rn, 0, eq);
4670 break;
4671 case NEON_CMLE_zero:
4672 cmp(vf, rd, rn, 0, le);
4673 break;
4674 case NEON_CMLT_zero:
4675 cmp(vf, rd, rn, 0, lt);
4676 break;
4677 case NEON_ABS:
4678 abs(vf, rd, rn);
4679 break;
4680 case NEON_NEG:
4681 neg(vf, rd, rn);
4682 break;
4683 case NEON_SADDLP:
4684 saddlp(vf_lp, rd, rn);
4685 break;
4686 case NEON_UADDLP:
4687 uaddlp(vf_lp, rd, rn);
4688 break;
4689 case NEON_SADALP:
4690 sadalp(vf_lp, rd, rn);
4691 break;
4692 case NEON_UADALP:
4693 uadalp(vf_lp, rd, rn);
4694 break;
4695 case NEON_RBIT_NOT:
4696 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4697 switch (instr->GetFPType()) {
4698 case 0:
4699 not_(vf, rd, rn);
4700 break;
4701 case 1:
4702 rbit(vf, rd, rn);
4703 break;
4704 default:
4705 VIXL_UNIMPLEMENTED();
4706 }
4707 break;
4708 }
4709 } else {
4710 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4711 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4712 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004713 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004714
4715 // These instructions all use a one bit size field, except XTN, SQXTUN,
4716 // SHLL, SQXTN and UQXTN, which use a two bit size field.
4717 switch (instr->Mask(NEON2RegMiscFPMask)) {
4718 case NEON_FABS:
4719 fabs_(fpf, rd, rn);
4720 return;
4721 case NEON_FNEG:
4722 fneg(fpf, rd, rn);
4723 return;
4724 case NEON_FSQRT:
4725 fsqrt(fpf, rd, rn);
4726 return;
4727 case NEON_FCVTL:
4728 if (instr->Mask(NEON_Q)) {
4729 fcvtl2(vf_fcvtl, rd, rn);
4730 } else {
4731 fcvtl(vf_fcvtl, rd, rn);
4732 }
4733 return;
4734 case NEON_FCVTN:
4735 if (instr->Mask(NEON_Q)) {
4736 fcvtn2(vf_fcvtn, rd, rn);
4737 } else {
4738 fcvtn(vf_fcvtn, rd, rn);
4739 }
4740 return;
4741 case NEON_FCVTXN:
4742 if (instr->Mask(NEON_Q)) {
4743 fcvtxn2(vf_fcvtn, rd, rn);
4744 } else {
4745 fcvtxn(vf_fcvtn, rd, rn);
4746 }
4747 return;
4748
4749 // The following instructions break from the switch statement, rather
4750 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07004751 case NEON_FRINT32X:
4752 inexact_exception = true;
4753 frint_mode = kFrintToInt32;
4754 break; // Use FPCR rounding mode.
4755 case NEON_FRINT32Z:
4756 inexact_exception = true;
4757 frint_mode = kFrintToInt32;
4758 fpcr_rounding = FPZero;
4759 break;
4760 case NEON_FRINT64X:
4761 inexact_exception = true;
4762 frint_mode = kFrintToInt64;
4763 break; // Use FPCR rounding mode.
4764 case NEON_FRINT64Z:
4765 inexact_exception = true;
4766 frint_mode = kFrintToInt64;
4767 fpcr_rounding = FPZero;
4768 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004769 case NEON_FRINTI:
4770 break; // Use FPCR rounding mode.
4771 case NEON_FRINTX:
4772 inexact_exception = true;
4773 break;
4774 case NEON_FRINTA:
4775 fpcr_rounding = FPTieAway;
4776 break;
4777 case NEON_FRINTM:
4778 fpcr_rounding = FPNegativeInfinity;
4779 break;
4780 case NEON_FRINTN:
4781 fpcr_rounding = FPTieEven;
4782 break;
4783 case NEON_FRINTP:
4784 fpcr_rounding = FPPositiveInfinity;
4785 break;
4786 case NEON_FRINTZ:
4787 fpcr_rounding = FPZero;
4788 break;
4789
4790 case NEON_FCVTNS:
4791 fcvts(fpf, rd, rn, FPTieEven);
4792 return;
4793 case NEON_FCVTNU:
4794 fcvtu(fpf, rd, rn, FPTieEven);
4795 return;
4796 case NEON_FCVTPS:
4797 fcvts(fpf, rd, rn, FPPositiveInfinity);
4798 return;
4799 case NEON_FCVTPU:
4800 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4801 return;
4802 case NEON_FCVTMS:
4803 fcvts(fpf, rd, rn, FPNegativeInfinity);
4804 return;
4805 case NEON_FCVTMU:
4806 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4807 return;
4808 case NEON_FCVTZS:
4809 fcvts(fpf, rd, rn, FPZero);
4810 return;
4811 case NEON_FCVTZU:
4812 fcvtu(fpf, rd, rn, FPZero);
4813 return;
4814 case NEON_FCVTAS:
4815 fcvts(fpf, rd, rn, FPTieAway);
4816 return;
4817 case NEON_FCVTAU:
4818 fcvtu(fpf, rd, rn, FPTieAway);
4819 return;
4820 case NEON_SCVTF:
4821 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4822 return;
4823 case NEON_UCVTF:
4824 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4825 return;
4826 case NEON_URSQRTE:
4827 ursqrte(fpf, rd, rn);
4828 return;
4829 case NEON_URECPE:
4830 urecpe(fpf, rd, rn);
4831 return;
4832 case NEON_FRSQRTE:
4833 frsqrte(fpf, rd, rn);
4834 return;
4835 case NEON_FRECPE:
4836 frecpe(fpf, rd, rn, fpcr_rounding);
4837 return;
4838 case NEON_FCMGT_zero:
4839 fcmp_zero(fpf, rd, rn, gt);
4840 return;
4841 case NEON_FCMGE_zero:
4842 fcmp_zero(fpf, rd, rn, ge);
4843 return;
4844 case NEON_FCMEQ_zero:
4845 fcmp_zero(fpf, rd, rn, eq);
4846 return;
4847 case NEON_FCMLE_zero:
4848 fcmp_zero(fpf, rd, rn, le);
4849 return;
4850 case NEON_FCMLT_zero:
4851 fcmp_zero(fpf, rd, rn, lt);
4852 return;
4853 default:
4854 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4855 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4856 switch (instr->Mask(NEON2RegMiscMask)) {
4857 case NEON_XTN:
4858 xtn(vf, rd, rn);
4859 return;
4860 case NEON_SQXTN:
4861 sqxtn(vf, rd, rn);
4862 return;
4863 case NEON_UQXTN:
4864 uqxtn(vf, rd, rn);
4865 return;
4866 case NEON_SQXTUN:
4867 sqxtun(vf, rd, rn);
4868 return;
4869 case NEON_SHLL:
4870 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4871 if (instr->Mask(NEON_Q)) {
4872 shll2(vf, rd, rn);
4873 } else {
4874 shll(vf, rd, rn);
4875 }
4876 return;
4877 default:
4878 VIXL_UNIMPLEMENTED();
4879 }
4880 } else {
4881 VIXL_UNIMPLEMENTED();
4882 }
4883 }
4884
4885 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004886 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004887 }
4888}
4889
4890
Jacob Bramleyca789742018-09-13 14:25:46 +01004891void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4892 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4893 NEONFormatDecoder nfd(instr);
4894 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4895
4896 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4897
4898 SimVRegister& rd = ReadVRegister(instr->GetRd());
4899 SimVRegister& rn = ReadVRegister(instr->GetRn());
4900
4901 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4902 case NEON_SCVTF_H:
4903 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4904 return;
4905 case NEON_UCVTF_H:
4906 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4907 return;
4908 case NEON_FCVTNS_H:
4909 fcvts(fpf, rd, rn, FPTieEven);
4910 return;
4911 case NEON_FCVTNU_H:
4912 fcvtu(fpf, rd, rn, FPTieEven);
4913 return;
4914 case NEON_FCVTPS_H:
4915 fcvts(fpf, rd, rn, FPPositiveInfinity);
4916 return;
4917 case NEON_FCVTPU_H:
4918 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4919 return;
4920 case NEON_FCVTMS_H:
4921 fcvts(fpf, rd, rn, FPNegativeInfinity);
4922 return;
4923 case NEON_FCVTMU_H:
4924 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4925 return;
4926 case NEON_FCVTZS_H:
4927 fcvts(fpf, rd, rn, FPZero);
4928 return;
4929 case NEON_FCVTZU_H:
4930 fcvtu(fpf, rd, rn, FPZero);
4931 return;
4932 case NEON_FCVTAS_H:
4933 fcvts(fpf, rd, rn, FPTieAway);
4934 return;
4935 case NEON_FCVTAU_H:
4936 fcvtu(fpf, rd, rn, FPTieAway);
4937 return;
4938 case NEON_FRINTI_H:
4939 frint(fpf, rd, rn, fpcr_rounding, false);
4940 return;
4941 case NEON_FRINTX_H:
4942 frint(fpf, rd, rn, fpcr_rounding, true);
4943 return;
4944 case NEON_FRINTA_H:
4945 frint(fpf, rd, rn, FPTieAway, false);
4946 return;
4947 case NEON_FRINTM_H:
4948 frint(fpf, rd, rn, FPNegativeInfinity, false);
4949 return;
4950 case NEON_FRINTN_H:
4951 frint(fpf, rd, rn, FPTieEven, false);
4952 return;
4953 case NEON_FRINTP_H:
4954 frint(fpf, rd, rn, FPPositiveInfinity, false);
4955 return;
4956 case NEON_FRINTZ_H:
4957 frint(fpf, rd, rn, FPZero, false);
4958 return;
4959 case NEON_FABS_H:
4960 fabs_(fpf, rd, rn);
4961 return;
4962 case NEON_FNEG_H:
4963 fneg(fpf, rd, rn);
4964 return;
4965 case NEON_FSQRT_H:
4966 fsqrt(fpf, rd, rn);
4967 return;
4968 case NEON_FRSQRTE_H:
4969 frsqrte(fpf, rd, rn);
4970 return;
4971 case NEON_FRECPE_H:
4972 frecpe(fpf, rd, rn, fpcr_rounding);
4973 return;
4974 case NEON_FCMGT_H_zero:
4975 fcmp_zero(fpf, rd, rn, gt);
4976 return;
4977 case NEON_FCMGE_H_zero:
4978 fcmp_zero(fpf, rd, rn, ge);
4979 return;
4980 case NEON_FCMEQ_H_zero:
4981 fcmp_zero(fpf, rd, rn, eq);
4982 return;
4983 case NEON_FCMLE_H_zero:
4984 fcmp_zero(fpf, rd, rn, le);
4985 return;
4986 case NEON_FCMLT_H_zero:
4987 fcmp_zero(fpf, rd, rn, lt);
4988 return;
4989 default:
4990 VIXL_UNIMPLEMENTED();
4991 return;
4992 }
4993}
4994
4995
Alexandre Ramesd3832962016-07-04 15:03:43 +01004996void Simulator::VisitNEON3Same(const Instruction* instr) {
4997 NEONFormatDecoder nfd(instr);
4998 SimVRegister& rd = ReadVRegister(instr->GetRd());
4999 SimVRegister& rn = ReadVRegister(instr->GetRn());
5000 SimVRegister& rm = ReadVRegister(instr->GetRm());
5001
5002 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
5003 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
5004 switch (instr->Mask(NEON3SameLogicalMask)) {
5005 case NEON_AND:
5006 and_(vf, rd, rn, rm);
5007 break;
5008 case NEON_ORR:
5009 orr(vf, rd, rn, rm);
5010 break;
5011 case NEON_ORN:
5012 orn(vf, rd, rn, rm);
5013 break;
5014 case NEON_EOR:
5015 eor(vf, rd, rn, rm);
5016 break;
5017 case NEON_BIC:
5018 bic(vf, rd, rn, rm);
5019 break;
5020 case NEON_BIF:
5021 bif(vf, rd, rn, rm);
5022 break;
5023 case NEON_BIT:
5024 bit(vf, rd, rn, rm);
5025 break;
5026 case NEON_BSL:
5027 bsl(vf, rd, rn, rm);
5028 break;
5029 default:
5030 VIXL_UNIMPLEMENTED();
5031 }
5032 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
5033 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5034 switch (instr->Mask(NEON3SameFPMask)) {
5035 case NEON_FADD:
5036 fadd(vf, rd, rn, rm);
5037 break;
5038 case NEON_FSUB:
5039 fsub(vf, rd, rn, rm);
5040 break;
5041 case NEON_FMUL:
5042 fmul(vf, rd, rn, rm);
5043 break;
5044 case NEON_FDIV:
5045 fdiv(vf, rd, rn, rm);
5046 break;
5047 case NEON_FMAX:
5048 fmax(vf, rd, rn, rm);
5049 break;
5050 case NEON_FMIN:
5051 fmin(vf, rd, rn, rm);
5052 break;
5053 case NEON_FMAXNM:
5054 fmaxnm(vf, rd, rn, rm);
5055 break;
5056 case NEON_FMINNM:
5057 fminnm(vf, rd, rn, rm);
5058 break;
5059 case NEON_FMLA:
5060 fmla(vf, rd, rn, rm);
5061 break;
5062 case NEON_FMLS:
5063 fmls(vf, rd, rn, rm);
5064 break;
5065 case NEON_FMULX:
5066 fmulx(vf, rd, rn, rm);
5067 break;
5068 case NEON_FACGE:
5069 fabscmp(vf, rd, rn, rm, ge);
5070 break;
5071 case NEON_FACGT:
5072 fabscmp(vf, rd, rn, rm, gt);
5073 break;
5074 case NEON_FCMEQ:
5075 fcmp(vf, rd, rn, rm, eq);
5076 break;
5077 case NEON_FCMGE:
5078 fcmp(vf, rd, rn, rm, ge);
5079 break;
5080 case NEON_FCMGT:
5081 fcmp(vf, rd, rn, rm, gt);
5082 break;
5083 case NEON_FRECPS:
5084 frecps(vf, rd, rn, rm);
5085 break;
5086 case NEON_FRSQRTS:
5087 frsqrts(vf, rd, rn, rm);
5088 break;
5089 case NEON_FABD:
5090 fabd(vf, rd, rn, rm);
5091 break;
5092 case NEON_FADDP:
5093 faddp(vf, rd, rn, rm);
5094 break;
5095 case NEON_FMAXP:
5096 fmaxp(vf, rd, rn, rm);
5097 break;
5098 case NEON_FMAXNMP:
5099 fmaxnmp(vf, rd, rn, rm);
5100 break;
5101 case NEON_FMINP:
5102 fminp(vf, rd, rn, rm);
5103 break;
5104 case NEON_FMINNMP:
5105 fminnmp(vf, rd, rn, rm);
5106 break;
5107 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005108 // FMLAL{2} and FMLSL{2} have special-case encodings.
5109 switch (instr->Mask(NEON3SameFHMMask)) {
5110 case NEON_FMLAL:
5111 fmlal(vf, rd, rn, rm);
5112 break;
5113 case NEON_FMLAL2:
5114 fmlal2(vf, rd, rn, rm);
5115 break;
5116 case NEON_FMLSL:
5117 fmlsl(vf, rd, rn, rm);
5118 break;
5119 case NEON_FMLSL2:
5120 fmlsl2(vf, rd, rn, rm);
5121 break;
5122 default:
5123 VIXL_UNIMPLEMENTED();
5124 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005125 }
5126 } else {
5127 VectorFormat vf = nfd.GetVectorFormat();
5128 switch (instr->Mask(NEON3SameMask)) {
5129 case NEON_ADD:
5130 add(vf, rd, rn, rm);
5131 break;
5132 case NEON_ADDP:
5133 addp(vf, rd, rn, rm);
5134 break;
5135 case NEON_CMEQ:
5136 cmp(vf, rd, rn, rm, eq);
5137 break;
5138 case NEON_CMGE:
5139 cmp(vf, rd, rn, rm, ge);
5140 break;
5141 case NEON_CMGT:
5142 cmp(vf, rd, rn, rm, gt);
5143 break;
5144 case NEON_CMHI:
5145 cmp(vf, rd, rn, rm, hi);
5146 break;
5147 case NEON_CMHS:
5148 cmp(vf, rd, rn, rm, hs);
5149 break;
5150 case NEON_CMTST:
5151 cmptst(vf, rd, rn, rm);
5152 break;
5153 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01005154 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005155 break;
5156 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01005157 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005158 break;
5159 case NEON_MUL:
5160 mul(vf, rd, rn, rm);
5161 break;
5162 case NEON_PMUL:
5163 pmul(vf, rd, rn, rm);
5164 break;
5165 case NEON_SMAX:
5166 smax(vf, rd, rn, rm);
5167 break;
5168 case NEON_SMAXP:
5169 smaxp(vf, rd, rn, rm);
5170 break;
5171 case NEON_SMIN:
5172 smin(vf, rd, rn, rm);
5173 break;
5174 case NEON_SMINP:
5175 sminp(vf, rd, rn, rm);
5176 break;
5177 case NEON_SUB:
5178 sub(vf, rd, rn, rm);
5179 break;
5180 case NEON_UMAX:
5181 umax(vf, rd, rn, rm);
5182 break;
5183 case NEON_UMAXP:
5184 umaxp(vf, rd, rn, rm);
5185 break;
5186 case NEON_UMIN:
5187 umin(vf, rd, rn, rm);
5188 break;
5189 case NEON_UMINP:
5190 uminp(vf, rd, rn, rm);
5191 break;
5192 case NEON_SSHL:
5193 sshl(vf, rd, rn, rm);
5194 break;
5195 case NEON_USHL:
5196 ushl(vf, rd, rn, rm);
5197 break;
5198 case NEON_SABD:
5199 absdiff(vf, rd, rn, rm, true);
5200 break;
5201 case NEON_UABD:
5202 absdiff(vf, rd, rn, rm, false);
5203 break;
5204 case NEON_SABA:
5205 saba(vf, rd, rn, rm);
5206 break;
5207 case NEON_UABA:
5208 uaba(vf, rd, rn, rm);
5209 break;
5210 case NEON_UQADD:
5211 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5212 break;
5213 case NEON_SQADD:
5214 add(vf, rd, rn, rm).SignedSaturate(vf);
5215 break;
5216 case NEON_UQSUB:
5217 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5218 break;
5219 case NEON_SQSUB:
5220 sub(vf, rd, rn, rm).SignedSaturate(vf);
5221 break;
5222 case NEON_SQDMULH:
5223 sqdmulh(vf, rd, rn, rm);
5224 break;
5225 case NEON_SQRDMULH:
5226 sqrdmulh(vf, rd, rn, rm);
5227 break;
5228 case NEON_UQSHL:
5229 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5230 break;
5231 case NEON_SQSHL:
5232 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5233 break;
5234 case NEON_URSHL:
5235 ushl(vf, rd, rn, rm).Round(vf);
5236 break;
5237 case NEON_SRSHL:
5238 sshl(vf, rd, rn, rm).Round(vf);
5239 break;
5240 case NEON_UQRSHL:
5241 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5242 break;
5243 case NEON_SQRSHL:
5244 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5245 break;
5246 case NEON_UHADD:
5247 add(vf, rd, rn, rm).Uhalve(vf);
5248 break;
5249 case NEON_URHADD:
5250 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
5251 break;
5252 case NEON_SHADD:
5253 add(vf, rd, rn, rm).Halve(vf);
5254 break;
5255 case NEON_SRHADD:
5256 add(vf, rd, rn, rm).Halve(vf).Round(vf);
5257 break;
5258 case NEON_UHSUB:
5259 sub(vf, rd, rn, rm).Uhalve(vf);
5260 break;
5261 case NEON_SHSUB:
5262 sub(vf, rd, rn, rm).Halve(vf);
5263 break;
5264 default:
5265 VIXL_UNIMPLEMENTED();
5266 }
5267 }
5268}
5269
5270
Jacob Bramleyca789742018-09-13 14:25:46 +01005271void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
5272 NEONFormatDecoder nfd(instr);
5273 SimVRegister& rd = ReadVRegister(instr->GetRd());
5274 SimVRegister& rn = ReadVRegister(instr->GetRn());
5275 SimVRegister& rm = ReadVRegister(instr->GetRm());
5276
5277 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
5278 switch (instr->Mask(NEON3SameFP16Mask)) {
5279#define SIM_FUNC(A, B) \
5280 case NEON_##A##_H: \
5281 B(vf, rd, rn, rm); \
5282 break;
5283 SIM_FUNC(FMAXNM, fmaxnm);
5284 SIM_FUNC(FMLA, fmla);
5285 SIM_FUNC(FADD, fadd);
5286 SIM_FUNC(FMULX, fmulx);
5287 SIM_FUNC(FMAX, fmax);
5288 SIM_FUNC(FRECPS, frecps);
5289 SIM_FUNC(FMINNM, fminnm);
5290 SIM_FUNC(FMLS, fmls);
5291 SIM_FUNC(FSUB, fsub);
5292 SIM_FUNC(FMIN, fmin);
5293 SIM_FUNC(FRSQRTS, frsqrts);
5294 SIM_FUNC(FMAXNMP, fmaxnmp);
5295 SIM_FUNC(FADDP, faddp);
5296 SIM_FUNC(FMUL, fmul);
5297 SIM_FUNC(FMAXP, fmaxp);
5298 SIM_FUNC(FDIV, fdiv);
5299 SIM_FUNC(FMINNMP, fminnmp);
5300 SIM_FUNC(FABD, fabd);
5301 SIM_FUNC(FMINP, fminp);
5302#undef SIM_FUNC
5303 case NEON_FCMEQ_H:
5304 fcmp(vf, rd, rn, rm, eq);
5305 break;
5306 case NEON_FCMGE_H:
5307 fcmp(vf, rd, rn, rm, ge);
5308 break;
5309 case NEON_FACGE_H:
5310 fabscmp(vf, rd, rn, rm, ge);
5311 break;
5312 case NEON_FCMGT_H:
5313 fcmp(vf, rd, rn, rm, gt);
5314 break;
5315 case NEON_FACGT_H:
5316 fabscmp(vf, rd, rn, rm, gt);
5317 break;
5318 default:
5319 VIXL_UNIMPLEMENTED();
5320 break;
5321 }
5322}
5323
Carey Williams2809e6c2018-03-13 12:24:16 +00005324void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
5325 NEONFormatDecoder nfd(instr);
5326 SimVRegister& rd = ReadVRegister(instr->GetRd());
5327 SimVRegister& rn = ReadVRegister(instr->GetRn());
5328 SimVRegister& rm = ReadVRegister(instr->GetRm());
5329 int rot = 0;
5330 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01005331 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
5332 rot = instr->GetImmRotFcmlaVec();
5333 fcmla(vf, rd, rn, rm, rot);
5334 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
5335 rot = instr->GetImmRotFcadd();
5336 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01005337 } else {
5338 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01005339 case NEON_SDOT:
5340 sdot(vf, rd, rn, rm);
5341 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005342 case NEON_SQRDMLAH:
5343 sqrdmlah(vf, rd, rn, rm);
5344 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005345 case NEON_UDOT:
5346 udot(vf, rd, rn, rm);
5347 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005348 case NEON_SQRDMLSH:
5349 sqrdmlsh(vf, rd, rn, rm);
5350 break;
5351 default:
5352 VIXL_UNIMPLEMENTED();
5353 break;
5354 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005355 }
5356}
5357
5358
Alexandre Ramesd3832962016-07-04 15:03:43 +01005359void Simulator::VisitNEON3Different(const Instruction* instr) {
5360 NEONFormatDecoder nfd(instr);
5361 VectorFormat vf = nfd.GetVectorFormat();
5362 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5363
5364 SimVRegister& rd = ReadVRegister(instr->GetRd());
5365 SimVRegister& rn = ReadVRegister(instr->GetRn());
5366 SimVRegister& rm = ReadVRegister(instr->GetRm());
5367
5368 switch (instr->Mask(NEON3DifferentMask)) {
5369 case NEON_PMULL:
5370 pmull(vf_l, rd, rn, rm);
5371 break;
5372 case NEON_PMULL2:
5373 pmull2(vf_l, rd, rn, rm);
5374 break;
5375 case NEON_UADDL:
5376 uaddl(vf_l, rd, rn, rm);
5377 break;
5378 case NEON_UADDL2:
5379 uaddl2(vf_l, rd, rn, rm);
5380 break;
5381 case NEON_SADDL:
5382 saddl(vf_l, rd, rn, rm);
5383 break;
5384 case NEON_SADDL2:
5385 saddl2(vf_l, rd, rn, rm);
5386 break;
5387 case NEON_USUBL:
5388 usubl(vf_l, rd, rn, rm);
5389 break;
5390 case NEON_USUBL2:
5391 usubl2(vf_l, rd, rn, rm);
5392 break;
5393 case NEON_SSUBL:
5394 ssubl(vf_l, rd, rn, rm);
5395 break;
5396 case NEON_SSUBL2:
5397 ssubl2(vf_l, rd, rn, rm);
5398 break;
5399 case NEON_SABAL:
5400 sabal(vf_l, rd, rn, rm);
5401 break;
5402 case NEON_SABAL2:
5403 sabal2(vf_l, rd, rn, rm);
5404 break;
5405 case NEON_UABAL:
5406 uabal(vf_l, rd, rn, rm);
5407 break;
5408 case NEON_UABAL2:
5409 uabal2(vf_l, rd, rn, rm);
5410 break;
5411 case NEON_SABDL:
5412 sabdl(vf_l, rd, rn, rm);
5413 break;
5414 case NEON_SABDL2:
5415 sabdl2(vf_l, rd, rn, rm);
5416 break;
5417 case NEON_UABDL:
5418 uabdl(vf_l, rd, rn, rm);
5419 break;
5420 case NEON_UABDL2:
5421 uabdl2(vf_l, rd, rn, rm);
5422 break;
5423 case NEON_SMLAL:
5424 smlal(vf_l, rd, rn, rm);
5425 break;
5426 case NEON_SMLAL2:
5427 smlal2(vf_l, rd, rn, rm);
5428 break;
5429 case NEON_UMLAL:
5430 umlal(vf_l, rd, rn, rm);
5431 break;
5432 case NEON_UMLAL2:
5433 umlal2(vf_l, rd, rn, rm);
5434 break;
5435 case NEON_SMLSL:
5436 smlsl(vf_l, rd, rn, rm);
5437 break;
5438 case NEON_SMLSL2:
5439 smlsl2(vf_l, rd, rn, rm);
5440 break;
5441 case NEON_UMLSL:
5442 umlsl(vf_l, rd, rn, rm);
5443 break;
5444 case NEON_UMLSL2:
5445 umlsl2(vf_l, rd, rn, rm);
5446 break;
5447 case NEON_SMULL:
5448 smull(vf_l, rd, rn, rm);
5449 break;
5450 case NEON_SMULL2:
5451 smull2(vf_l, rd, rn, rm);
5452 break;
5453 case NEON_UMULL:
5454 umull(vf_l, rd, rn, rm);
5455 break;
5456 case NEON_UMULL2:
5457 umull2(vf_l, rd, rn, rm);
5458 break;
5459 case NEON_SQDMLAL:
5460 sqdmlal(vf_l, rd, rn, rm);
5461 break;
5462 case NEON_SQDMLAL2:
5463 sqdmlal2(vf_l, rd, rn, rm);
5464 break;
5465 case NEON_SQDMLSL:
5466 sqdmlsl(vf_l, rd, rn, rm);
5467 break;
5468 case NEON_SQDMLSL2:
5469 sqdmlsl2(vf_l, rd, rn, rm);
5470 break;
5471 case NEON_SQDMULL:
5472 sqdmull(vf_l, rd, rn, rm);
5473 break;
5474 case NEON_SQDMULL2:
5475 sqdmull2(vf_l, rd, rn, rm);
5476 break;
5477 case NEON_UADDW:
5478 uaddw(vf_l, rd, rn, rm);
5479 break;
5480 case NEON_UADDW2:
5481 uaddw2(vf_l, rd, rn, rm);
5482 break;
5483 case NEON_SADDW:
5484 saddw(vf_l, rd, rn, rm);
5485 break;
5486 case NEON_SADDW2:
5487 saddw2(vf_l, rd, rn, rm);
5488 break;
5489 case NEON_USUBW:
5490 usubw(vf_l, rd, rn, rm);
5491 break;
5492 case NEON_USUBW2:
5493 usubw2(vf_l, rd, rn, rm);
5494 break;
5495 case NEON_SSUBW:
5496 ssubw(vf_l, rd, rn, rm);
5497 break;
5498 case NEON_SSUBW2:
5499 ssubw2(vf_l, rd, rn, rm);
5500 break;
5501 case NEON_ADDHN:
5502 addhn(vf, rd, rn, rm);
5503 break;
5504 case NEON_ADDHN2:
5505 addhn2(vf, rd, rn, rm);
5506 break;
5507 case NEON_RADDHN:
5508 raddhn(vf, rd, rn, rm);
5509 break;
5510 case NEON_RADDHN2:
5511 raddhn2(vf, rd, rn, rm);
5512 break;
5513 case NEON_SUBHN:
5514 subhn(vf, rd, rn, rm);
5515 break;
5516 case NEON_SUBHN2:
5517 subhn2(vf, rd, rn, rm);
5518 break;
5519 case NEON_RSUBHN:
5520 rsubhn(vf, rd, rn, rm);
5521 break;
5522 case NEON_RSUBHN2:
5523 rsubhn2(vf, rd, rn, rm);
5524 break;
5525 default:
5526 VIXL_UNIMPLEMENTED();
5527 }
5528}
5529
5530
5531void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5532 NEONFormatDecoder nfd(instr);
5533
Jacob Bramleyca789742018-09-13 14:25:46 +01005534 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5535
Alexandre Ramesd3832962016-07-04 15:03:43 +01005536 SimVRegister& rd = ReadVRegister(instr->GetRd());
5537 SimVRegister& rn = ReadVRegister(instr->GetRn());
5538
Jacob Bramleyca789742018-09-13 14:25:46 +01005539 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5540 VectorFormat vf = nfd.GetVectorFormat(&map_half);
5541 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5542 case NEON_FMAXV_H:
5543 fmaxv(vf, rd, rn);
5544 break;
5545 case NEON_FMINV_H:
5546 fminv(vf, rd, rn);
5547 break;
5548 case NEON_FMAXNMV_H:
5549 fmaxnmv(vf, rd, rn);
5550 break;
5551 case NEON_FMINNMV_H:
5552 fminnmv(vf, rd, rn);
5553 break;
5554 default:
5555 VIXL_UNIMPLEMENTED();
5556 }
5557 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5558 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01005559 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5560
5561 switch (instr->Mask(NEONAcrossLanesFPMask)) {
5562 case NEON_FMAXV:
5563 fmaxv(vf, rd, rn);
5564 break;
5565 case NEON_FMINV:
5566 fminv(vf, rd, rn);
5567 break;
5568 case NEON_FMAXNMV:
5569 fmaxnmv(vf, rd, rn);
5570 break;
5571 case NEON_FMINNMV:
5572 fminnmv(vf, rd, rn);
5573 break;
5574 default:
5575 VIXL_UNIMPLEMENTED();
5576 }
5577 } else {
5578 VectorFormat vf = nfd.GetVectorFormat();
5579
5580 switch (instr->Mask(NEONAcrossLanesMask)) {
5581 case NEON_ADDV:
5582 addv(vf, rd, rn);
5583 break;
5584 case NEON_SMAXV:
5585 smaxv(vf, rd, rn);
5586 break;
5587 case NEON_SMINV:
5588 sminv(vf, rd, rn);
5589 break;
5590 case NEON_UMAXV:
5591 umaxv(vf, rd, rn);
5592 break;
5593 case NEON_UMINV:
5594 uminv(vf, rd, rn);
5595 break;
5596 case NEON_SADDLV:
5597 saddlv(vf, rd, rn);
5598 break;
5599 case NEON_UADDLV:
5600 uaddlv(vf, rd, rn);
5601 break;
5602 default:
5603 VIXL_UNIMPLEMENTED();
5604 }
5605 }
5606}
5607
5608
5609void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5610 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01005611 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01005612 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01005613 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005614 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5615
5616 SimVRegister& rd = ReadVRegister(instr->GetRd());
5617 SimVRegister& rn = ReadVRegister(instr->GetRn());
5618
5619 ByElementOp Op = NULL;
5620
5621 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005622 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005623 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005624 int index_hlm = (index << 1) | instr->GetNEONM();
5625
5626 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5627 // These are oddballs and are best handled as special cases.
5628 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5629 // - The index is always H:L:M.
5630 case NEON_FMLAL_H_byelement:
5631 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5632 return;
5633 case NEON_FMLAL2_H_byelement:
5634 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5635 return;
5636 case NEON_FMLSL_H_byelement:
5637 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5638 return;
5639 case NEON_FMLSL2_H_byelement:
5640 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5641 return;
5642 }
5643
Alexandre Ramesd3832962016-07-04 15:03:43 +01005644 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005645 rm_reg = rm_low_reg;
5646 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005647 }
5648
5649 switch (instr->Mask(NEONByIndexedElementMask)) {
5650 case NEON_MUL_byelement:
5651 Op = &Simulator::mul;
5652 vf = vf_r;
5653 break;
5654 case NEON_MLA_byelement:
5655 Op = &Simulator::mla;
5656 vf = vf_r;
5657 break;
5658 case NEON_MLS_byelement:
5659 Op = &Simulator::mls;
5660 vf = vf_r;
5661 break;
5662 case NEON_SQDMULH_byelement:
5663 Op = &Simulator::sqdmulh;
5664 vf = vf_r;
5665 break;
5666 case NEON_SQRDMULH_byelement:
5667 Op = &Simulator::sqrdmulh;
5668 vf = vf_r;
5669 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005670 case NEON_SDOT_byelement:
5671 Op = &Simulator::sdot;
5672 vf = vf_r;
5673 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005674 case NEON_SQRDMLAH_byelement:
5675 Op = &Simulator::sqrdmlah;
5676 vf = vf_r;
5677 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005678 case NEON_UDOT_byelement:
5679 Op = &Simulator::udot;
5680 vf = vf_r;
5681 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005682 case NEON_SQRDMLSH_byelement:
5683 Op = &Simulator::sqrdmlsh;
5684 vf = vf_r;
5685 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005686 case NEON_SMULL_byelement:
5687 if (instr->Mask(NEON_Q)) {
5688 Op = &Simulator::smull2;
5689 } else {
5690 Op = &Simulator::smull;
5691 }
5692 break;
5693 case NEON_UMULL_byelement:
5694 if (instr->Mask(NEON_Q)) {
5695 Op = &Simulator::umull2;
5696 } else {
5697 Op = &Simulator::umull;
5698 }
5699 break;
5700 case NEON_SMLAL_byelement:
5701 if (instr->Mask(NEON_Q)) {
5702 Op = &Simulator::smlal2;
5703 } else {
5704 Op = &Simulator::smlal;
5705 }
5706 break;
5707 case NEON_UMLAL_byelement:
5708 if (instr->Mask(NEON_Q)) {
5709 Op = &Simulator::umlal2;
5710 } else {
5711 Op = &Simulator::umlal;
5712 }
5713 break;
5714 case NEON_SMLSL_byelement:
5715 if (instr->Mask(NEON_Q)) {
5716 Op = &Simulator::smlsl2;
5717 } else {
5718 Op = &Simulator::smlsl;
5719 }
5720 break;
5721 case NEON_UMLSL_byelement:
5722 if (instr->Mask(NEON_Q)) {
5723 Op = &Simulator::umlsl2;
5724 } else {
5725 Op = &Simulator::umlsl;
5726 }
5727 break;
5728 case NEON_SQDMULL_byelement:
5729 if (instr->Mask(NEON_Q)) {
5730 Op = &Simulator::sqdmull2;
5731 } else {
5732 Op = &Simulator::sqdmull;
5733 }
5734 break;
5735 case NEON_SQDMLAL_byelement:
5736 if (instr->Mask(NEON_Q)) {
5737 Op = &Simulator::sqdmlal2;
5738 } else {
5739 Op = &Simulator::sqdmlal;
5740 }
5741 break;
5742 case NEON_SQDMLSL_byelement:
5743 if (instr->Mask(NEON_Q)) {
5744 Op = &Simulator::sqdmlsl2;
5745 } else {
5746 Op = &Simulator::sqdmlsl;
5747 }
5748 break;
5749 default:
5750 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01005751 if (instr->GetFPType() == 0) {
5752 rm_reg &= 0xf;
5753 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5754 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005755 index = (index << 1) | instr->GetNEONL();
5756 }
5757
5758 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5759
5760 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005761 case NEON_FMUL_H_byelement:
5762 vf = vf_half;
5763 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005764 case NEON_FMUL_byelement:
5765 Op = &Simulator::fmul;
5766 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005767 case NEON_FMLA_H_byelement:
5768 vf = vf_half;
5769 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005770 case NEON_FMLA_byelement:
5771 Op = &Simulator::fmla;
5772 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005773 case NEON_FMLS_H_byelement:
5774 vf = vf_half;
5775 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005776 case NEON_FMLS_byelement:
5777 Op = &Simulator::fmls;
5778 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005779 case NEON_FMULX_H_byelement:
5780 vf = vf_half;
5781 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005782 case NEON_FMULX_byelement:
5783 Op = &Simulator::fmulx;
5784 break;
5785 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005786 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00005787 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005788 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00005789 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005790 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005791 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5792 case NEON_FCMLA_byelement:
5793 vf = vf_r;
5794 fcmla(vf,
5795 rd,
5796 rn,
5797 ReadVRegister(instr->GetRm()),
5798 index,
5799 instr->GetImmRotFcmlaSca());
5800 return;
5801 default:
5802 VIXL_UNIMPLEMENTED();
5803 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005804 }
5805 }
5806
5807 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5808}
5809
5810
5811void Simulator::VisitNEONCopy(const Instruction* instr) {
5812 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5813 VectorFormat vf = nfd.GetVectorFormat();
5814
5815 SimVRegister& rd = ReadVRegister(instr->GetRd());
5816 SimVRegister& rn = ReadVRegister(instr->GetRn());
5817 int imm5 = instr->GetImmNEON5();
5818 int tz = CountTrailingZeros(imm5, 32);
5819 int reg_index = imm5 >> (tz + 1);
5820
5821 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5822 int imm4 = instr->GetImmNEON4();
5823 int rn_index = imm4 >> tz;
5824 ins_element(vf, rd, reg_index, rn, rn_index);
5825 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5826 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5827 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5828 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5829 value &= MaxUintFromFormat(vf);
5830 WriteXRegister(instr->GetRd(), value);
5831 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5832 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5833 if (instr->GetNEONQ()) {
5834 WriteXRegister(instr->GetRd(), value);
5835 } else {
5836 WriteWRegister(instr->GetRd(), (int32_t)value);
5837 }
5838 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5839 dup_element(vf, rd, rn, reg_index);
5840 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5841 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5842 } else {
5843 VIXL_UNIMPLEMENTED();
5844 }
5845}
5846
5847
5848void Simulator::VisitNEONExtract(const Instruction* instr) {
5849 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5850 VectorFormat vf = nfd.GetVectorFormat();
5851 SimVRegister& rd = ReadVRegister(instr->GetRd());
5852 SimVRegister& rn = ReadVRegister(instr->GetRn());
5853 SimVRegister& rm = ReadVRegister(instr->GetRm());
5854 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5855 int index = instr->GetImmNEONExt();
5856 ext(vf, rd, rn, rm, index);
5857 } else {
5858 VIXL_UNIMPLEMENTED();
5859 }
5860}
5861
5862
5863void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5864 AddrMode addr_mode) {
5865 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5866 VectorFormat vf = nfd.GetVectorFormat();
5867
5868 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5869 int reg_size = RegisterSizeInBytesFromFormat(vf);
5870
5871 int reg[4];
5872 uint64_t addr[4];
5873 for (int i = 0; i < 4; i++) {
5874 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5875 addr[i] = addr_base + (i * reg_size);
5876 }
Jacob Bramley423e5422019-11-13 19:15:55 +00005877 int struct_parts = 1;
5878 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005879 bool log_read = true;
5880
Martyn Capewell32009e32016-10-27 11:00:37 +01005881 // Bit 23 determines whether this is an offset or post-index addressing mode.
5882 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5883 // register or immediate in post-index mode.
5884 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005885 VIXL_UNREACHABLE();
5886 }
5887
5888 // We use the PostIndex mask here, as it works in this case for both Offset
5889 // and PostIndex addressing.
5890 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5891 case NEON_LD1_4v:
5892 case NEON_LD1_4v_post:
5893 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005894 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005895 VIXL_FALLTHROUGH();
5896 case NEON_LD1_3v:
5897 case NEON_LD1_3v_post:
5898 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005899 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005900 VIXL_FALLTHROUGH();
5901 case NEON_LD1_2v:
5902 case NEON_LD1_2v_post:
5903 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005904 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005905 VIXL_FALLTHROUGH();
5906 case NEON_LD1_1v:
5907 case NEON_LD1_1v_post:
5908 ld1(vf, ReadVRegister(reg[0]), addr[0]);
5909 break;
5910 case NEON_ST1_4v:
5911 case NEON_ST1_4v_post:
5912 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005913 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005914 VIXL_FALLTHROUGH();
5915 case NEON_ST1_3v:
5916 case NEON_ST1_3v_post:
5917 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005918 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005919 VIXL_FALLTHROUGH();
5920 case NEON_ST1_2v:
5921 case NEON_ST1_2v_post:
5922 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005923 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005924 VIXL_FALLTHROUGH();
5925 case NEON_ST1_1v:
5926 case NEON_ST1_1v_post:
5927 st1(vf, ReadVRegister(reg[0]), addr[0]);
5928 log_read = false;
5929 break;
5930 case NEON_LD2_post:
5931 case NEON_LD2:
5932 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005933 struct_parts = 2;
5934 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005935 break;
5936 case NEON_ST2:
5937 case NEON_ST2_post:
5938 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005939 struct_parts = 2;
5940 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01005941 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005942 break;
5943 case NEON_LD3_post:
5944 case NEON_LD3:
5945 ld3(vf,
5946 ReadVRegister(reg[0]),
5947 ReadVRegister(reg[1]),
5948 ReadVRegister(reg[2]),
5949 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005950 struct_parts = 3;
5951 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005952 break;
5953 case NEON_ST3:
5954 case NEON_ST3_post:
5955 st3(vf,
5956 ReadVRegister(reg[0]),
5957 ReadVRegister(reg[1]),
5958 ReadVRegister(reg[2]),
5959 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005960 struct_parts = 3;
5961 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01005962 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005963 break;
5964 case NEON_ST4:
5965 case NEON_ST4_post:
5966 st4(vf,
5967 ReadVRegister(reg[0]),
5968 ReadVRegister(reg[1]),
5969 ReadVRegister(reg[2]),
5970 ReadVRegister(reg[3]),
5971 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005972 struct_parts = 4;
5973 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01005974 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005975 break;
5976 case NEON_LD4_post:
5977 case NEON_LD4:
5978 ld4(vf,
5979 ReadVRegister(reg[0]),
5980 ReadVRegister(reg[1]),
5981 ReadVRegister(reg[2]),
5982 ReadVRegister(reg[3]),
5983 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005984 struct_parts = 4;
5985 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005986 break;
5987 default:
5988 VIXL_UNIMPLEMENTED();
5989 }
5990
Jacob Bramley7eb3e212019-11-22 17:28:05 +00005991 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00005992 if (do_trace) {
5993 PrintRegisterFormat print_format =
5994 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
5995 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005996 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00005997 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01005998 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00005999 op = "->";
6000 // Stores don't represent a change to the source register's value, so only
6001 // print the relevant part of the value.
6002 print_format = GetPrintRegPartial(print_format);
6003 }
6004
6005 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
6006 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
6007 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
6008 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006009 }
6010 }
6011
6012 if (addr_mode == PostIndex) {
6013 int rm = instr->GetRm();
6014 // The immediate post index addressing mode is indicated by rm = 31.
6015 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00006016 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01006017 : ReadXRegister(rm);
6018 WriteXRegister(instr->GetRn(), addr_base);
6019 } else {
6020 VIXL_ASSERT(addr_mode == Offset);
6021 }
6022}
6023
6024
6025void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
6026 NEONLoadStoreMultiStructHelper(instr, Offset);
6027}
6028
6029
6030void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
6031 const Instruction* instr) {
6032 NEONLoadStoreMultiStructHelper(instr, PostIndex);
6033}
6034
6035
6036void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
6037 AddrMode addr_mode) {
6038 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
6039 int rt = instr->GetRt();
6040
Martyn Capewell32009e32016-10-27 11:00:37 +01006041 // Bit 23 determines whether this is an offset or post-index addressing mode.
6042 // In offset mode, bits 20 to 16 should be zero; these bits encode the
6043 // register or immediate in post-index mode.
6044 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006045 VIXL_UNREACHABLE();
6046 }
6047
6048 // We use the PostIndex mask here, as it works in this case for both Offset
6049 // and PostIndex addressing.
6050 bool do_load = false;
6051
Jacob Bramley423e5422019-11-13 19:15:55 +00006052 bool replicating = false;
6053
Alexandre Ramesd3832962016-07-04 15:03:43 +01006054 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
6055 VectorFormat vf_t = nfd.GetVectorFormat();
6056
6057 VectorFormat vf = kFormat16B;
6058 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
6059 case NEON_LD1_b:
6060 case NEON_LD1_b_post:
6061 case NEON_LD2_b:
6062 case NEON_LD2_b_post:
6063 case NEON_LD3_b:
6064 case NEON_LD3_b_post:
6065 case NEON_LD4_b:
6066 case NEON_LD4_b_post:
6067 do_load = true;
6068 VIXL_FALLTHROUGH();
6069 case NEON_ST1_b:
6070 case NEON_ST1_b_post:
6071 case NEON_ST2_b:
6072 case NEON_ST2_b_post:
6073 case NEON_ST3_b:
6074 case NEON_ST3_b_post:
6075 case NEON_ST4_b:
6076 case NEON_ST4_b_post:
6077 break;
6078
6079 case NEON_LD1_h:
6080 case NEON_LD1_h_post:
6081 case NEON_LD2_h:
6082 case NEON_LD2_h_post:
6083 case NEON_LD3_h:
6084 case NEON_LD3_h_post:
6085 case NEON_LD4_h:
6086 case NEON_LD4_h_post:
6087 do_load = true;
6088 VIXL_FALLTHROUGH();
6089 case NEON_ST1_h:
6090 case NEON_ST1_h_post:
6091 case NEON_ST2_h:
6092 case NEON_ST2_h_post:
6093 case NEON_ST3_h:
6094 case NEON_ST3_h_post:
6095 case NEON_ST4_h:
6096 case NEON_ST4_h_post:
6097 vf = kFormat8H;
6098 break;
6099 case NEON_LD1_s:
6100 case NEON_LD1_s_post:
6101 case NEON_LD2_s:
6102 case NEON_LD2_s_post:
6103 case NEON_LD3_s:
6104 case NEON_LD3_s_post:
6105 case NEON_LD4_s:
6106 case NEON_LD4_s_post:
6107 do_load = true;
6108 VIXL_FALLTHROUGH();
6109 case NEON_ST1_s:
6110 case NEON_ST1_s_post:
6111 case NEON_ST2_s:
6112 case NEON_ST2_s_post:
6113 case NEON_ST3_s:
6114 case NEON_ST3_s_post:
6115 case NEON_ST4_s:
6116 case NEON_ST4_s_post: {
6117 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
6118 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
6119 NEON_LD1_d_post);
6120 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
6121 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
6122 NEON_ST1_d_post);
6123 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
6124 break;
6125 }
6126
6127 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006128 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006129 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006130 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006131 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006132 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006133 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006134 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006135 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006136 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00006137 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006138 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00006139
Alexandre Ramesd3832962016-07-04 15:03:43 +01006140 default:
6141 VIXL_UNIMPLEMENTED();
6142 }
6143
Alexandre Ramesd3832962016-07-04 15:03:43 +01006144 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
6145 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00006146 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006147 int rt2 = (rt + 1) % kNumberOfVRegisters;
6148 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
6149 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
6150 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
6151 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00006152 reg_count = 1;
6153 if (replicating) {
6154 VIXL_ASSERT(do_load);
6155 ld1r(vf, ReadVRegister(rt), addr);
6156 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006157 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006158 } else {
6159 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006160 }
6161 break;
6162 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00006163 reg_count = 2;
6164 if (replicating) {
6165 VIXL_ASSERT(do_load);
6166 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
6167 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006168 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006169 } else {
6170 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006171 }
6172 break;
6173 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00006174 reg_count = 3;
6175 if (replicating) {
6176 VIXL_ASSERT(do_load);
6177 ld3r(vf,
6178 ReadVRegister(rt),
6179 ReadVRegister(rt2),
6180 ReadVRegister(rt3),
6181 addr);
6182 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006183 ld3(vf,
6184 ReadVRegister(rt),
6185 ReadVRegister(rt2),
6186 ReadVRegister(rt3),
6187 lane,
6188 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006189 } else {
6190 st3(vf,
6191 ReadVRegister(rt),
6192 ReadVRegister(rt2),
6193 ReadVRegister(rt3),
6194 lane,
6195 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006196 }
6197 break;
6198 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00006199 reg_count = 4;
6200 if (replicating) {
6201 VIXL_ASSERT(do_load);
6202 ld4r(vf,
6203 ReadVRegister(rt),
6204 ReadVRegister(rt2),
6205 ReadVRegister(rt3),
6206 ReadVRegister(rt4),
6207 addr);
6208 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006209 ld4(vf,
6210 ReadVRegister(rt),
6211 ReadVRegister(rt2),
6212 ReadVRegister(rt3),
6213 ReadVRegister(rt4),
6214 lane,
6215 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006216 } else {
6217 st4(vf,
6218 ReadVRegister(rt),
6219 ReadVRegister(rt2),
6220 ReadVRegister(rt3),
6221 ReadVRegister(rt4),
6222 lane,
6223 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006224 }
6225 break;
6226 default:
6227 VIXL_UNIMPLEMENTED();
6228 }
6229
Jacob Bramley423e5422019-11-13 19:15:55 +00006230 // Trace registers and/or memory writes.
6231 PrintRegisterFormat print_format =
6232 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
6233 if (do_load) {
6234 if (ShouldTraceVRegs()) {
6235 if (replicating) {
6236 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
6237 } else {
6238 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
6239 }
6240 }
6241 } else {
6242 if (ShouldTraceWrites()) {
6243 // Stores don't represent a change to the source register's value, so only
6244 // print the relevant part of the value.
6245 print_format = GetPrintRegPartial(print_format);
6246 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
6247 }
6248 }
6249
Alexandre Ramesd3832962016-07-04 15:03:43 +01006250 if (addr_mode == PostIndex) {
6251 int rm = instr->GetRm();
6252 int lane_size = LaneSizeInBytesFromFormat(vf);
6253 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00006254 addr + ((rm == 31) ? (reg_count * lane_size)
6255 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006256 }
6257}
6258
6259
6260void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
6261 NEONLoadStoreSingleStructHelper(instr, Offset);
6262}
6263
6264
6265void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
6266 const Instruction* instr) {
6267 NEONLoadStoreSingleStructHelper(instr, PostIndex);
6268}
6269
6270
6271void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
6272 SimVRegister& rd = ReadVRegister(instr->GetRd());
6273 int cmode = instr->GetNEONCmode();
6274 int cmode_3_1 = (cmode >> 1) & 7;
6275 int cmode_3 = (cmode >> 3) & 1;
6276 int cmode_2 = (cmode >> 2) & 1;
6277 int cmode_1 = (cmode >> 1) & 1;
6278 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006279 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006280 int q = instr->GetNEONQ();
6281 int op_bit = instr->GetNEONModImmOp();
6282 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006283 // Find the format and immediate value
6284 uint64_t imm = 0;
6285 VectorFormat vform = kFormatUndefined;
6286 switch (cmode_3_1) {
6287 case 0x0:
6288 case 0x1:
6289 case 0x2:
6290 case 0x3:
6291 vform = (q == 1) ? kFormat4S : kFormat2S;
6292 imm = imm8 << (8 * cmode_3_1);
6293 break;
6294 case 0x4:
6295 case 0x5:
6296 vform = (q == 1) ? kFormat8H : kFormat4H;
6297 imm = imm8 << (8 * cmode_1);
6298 break;
6299 case 0x6:
6300 vform = (q == 1) ? kFormat4S : kFormat2S;
6301 if (cmode_0 == 0) {
6302 imm = imm8 << 8 | 0x000000ff;
6303 } else {
6304 imm = imm8 << 16 | 0x0000ffff;
6305 }
6306 break;
6307 case 0x7:
6308 if (cmode_0 == 0 && op_bit == 0) {
6309 vform = q ? kFormat16B : kFormat8B;
6310 imm = imm8;
6311 } else if (cmode_0 == 0 && op_bit == 1) {
6312 vform = q ? kFormat2D : kFormat1D;
6313 imm = 0;
6314 for (int i = 0; i < 8; ++i) {
6315 if (imm8 & (1 << i)) {
6316 imm |= (UINT64_C(0xff) << (8 * i));
6317 }
6318 }
6319 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01006320 if (half_enc == 1) {
6321 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01006322 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006323 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006324 vform = q ? kFormat4S : kFormat2S;
6325 imm = FloatToRawbits(instr->GetImmNEONFP32());
6326 } else if (q == 1) {
6327 vform = kFormat2D;
6328 imm = DoubleToRawbits(instr->GetImmNEONFP64());
6329 } else {
6330 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
6331 VisitUnallocated(instr);
6332 }
6333 }
6334 break;
6335 default:
6336 VIXL_UNREACHABLE();
6337 break;
6338 }
6339
6340 // Find the operation
6341 NEONModifiedImmediateOp op;
6342 if (cmode_3 == 0) {
6343 if (cmode_0 == 0) {
6344 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6345 } else { // cmode<0> == '1'
6346 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6347 }
6348 } else { // cmode<3> == '1'
6349 if (cmode_2 == 0) {
6350 if (cmode_0 == 0) {
6351 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6352 } else { // cmode<0> == '1'
6353 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6354 }
6355 } else { // cmode<2> == '1'
6356 if (cmode_1 == 0) {
6357 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6358 } else { // cmode<1> == '1'
6359 if (cmode_0 == 0) {
6360 op = NEONModifiedImmediate_MOVI;
6361 } else { // cmode<0> == '1'
6362 op = NEONModifiedImmediate_MOVI;
6363 }
6364 }
6365 }
6366 }
6367
6368 // Call the logic function
6369 if (op == NEONModifiedImmediate_ORR) {
6370 orr(vform, rd, rd, imm);
6371 } else if (op == NEONModifiedImmediate_BIC) {
6372 bic(vform, rd, rd, imm);
6373 } else if (op == NEONModifiedImmediate_MOVI) {
6374 movi(vform, rd, imm);
6375 } else if (op == NEONModifiedImmediate_MVNI) {
6376 mvni(vform, rd, imm);
6377 } else {
6378 VisitUnimplemented(instr);
6379 }
6380}
6381
6382
6383void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
6384 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6385 VectorFormat vf = nfd.GetVectorFormat();
6386
6387 SimVRegister& rd = ReadVRegister(instr->GetRd());
6388 SimVRegister& rn = ReadVRegister(instr->GetRn());
6389
6390 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
6391 // These instructions all use a two bit size field, except NOT and RBIT,
6392 // which use the field to encode the operation.
6393 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6394 case NEON_CMEQ_zero_scalar:
6395 cmp(vf, rd, rn, 0, eq);
6396 break;
6397 case NEON_CMGE_zero_scalar:
6398 cmp(vf, rd, rn, 0, ge);
6399 break;
6400 case NEON_CMGT_zero_scalar:
6401 cmp(vf, rd, rn, 0, gt);
6402 break;
6403 case NEON_CMLT_zero_scalar:
6404 cmp(vf, rd, rn, 0, lt);
6405 break;
6406 case NEON_CMLE_zero_scalar:
6407 cmp(vf, rd, rn, 0, le);
6408 break;
6409 case NEON_ABS_scalar:
6410 abs(vf, rd, rn);
6411 break;
6412 case NEON_SQABS_scalar:
6413 abs(vf, rd, rn).SignedSaturate(vf);
6414 break;
6415 case NEON_NEG_scalar:
6416 neg(vf, rd, rn);
6417 break;
6418 case NEON_SQNEG_scalar:
6419 neg(vf, rd, rn).SignedSaturate(vf);
6420 break;
6421 case NEON_SUQADD_scalar:
6422 suqadd(vf, rd, rn);
6423 break;
6424 case NEON_USQADD_scalar:
6425 usqadd(vf, rd, rn);
6426 break;
6427 default:
6428 VIXL_UNIMPLEMENTED();
6429 break;
6430 }
6431 } else {
6432 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6433 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6434
6435 // These instructions all use a one bit size field, except SQXTUN, SQXTN
6436 // and UQXTN, which use a two bit size field.
6437 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
6438 case NEON_FRECPE_scalar:
6439 frecpe(fpf, rd, rn, fpcr_rounding);
6440 break;
6441 case NEON_FRECPX_scalar:
6442 frecpx(fpf, rd, rn);
6443 break;
6444 case NEON_FRSQRTE_scalar:
6445 frsqrte(fpf, rd, rn);
6446 break;
6447 case NEON_FCMGT_zero_scalar:
6448 fcmp_zero(fpf, rd, rn, gt);
6449 break;
6450 case NEON_FCMGE_zero_scalar:
6451 fcmp_zero(fpf, rd, rn, ge);
6452 break;
6453 case NEON_FCMEQ_zero_scalar:
6454 fcmp_zero(fpf, rd, rn, eq);
6455 break;
6456 case NEON_FCMLE_zero_scalar:
6457 fcmp_zero(fpf, rd, rn, le);
6458 break;
6459 case NEON_FCMLT_zero_scalar:
6460 fcmp_zero(fpf, rd, rn, lt);
6461 break;
6462 case NEON_SCVTF_scalar:
6463 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6464 break;
6465 case NEON_UCVTF_scalar:
6466 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6467 break;
6468 case NEON_FCVTNS_scalar:
6469 fcvts(fpf, rd, rn, FPTieEven);
6470 break;
6471 case NEON_FCVTNU_scalar:
6472 fcvtu(fpf, rd, rn, FPTieEven);
6473 break;
6474 case NEON_FCVTPS_scalar:
6475 fcvts(fpf, rd, rn, FPPositiveInfinity);
6476 break;
6477 case NEON_FCVTPU_scalar:
6478 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6479 break;
6480 case NEON_FCVTMS_scalar:
6481 fcvts(fpf, rd, rn, FPNegativeInfinity);
6482 break;
6483 case NEON_FCVTMU_scalar:
6484 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6485 break;
6486 case NEON_FCVTZS_scalar:
6487 fcvts(fpf, rd, rn, FPZero);
6488 break;
6489 case NEON_FCVTZU_scalar:
6490 fcvtu(fpf, rd, rn, FPZero);
6491 break;
6492 case NEON_FCVTAS_scalar:
6493 fcvts(fpf, rd, rn, FPTieAway);
6494 break;
6495 case NEON_FCVTAU_scalar:
6496 fcvtu(fpf, rd, rn, FPTieAway);
6497 break;
6498 case NEON_FCVTXN_scalar:
6499 // Unlike all of the other FP instructions above, fcvtxn encodes dest
6500 // size S as size<0>=1. There's only one case, so we ignore the form.
6501 VIXL_ASSERT(instr->ExtractBit(22) == 1);
6502 fcvtxn(kFormatS, rd, rn);
6503 break;
6504 default:
6505 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6506 case NEON_SQXTN_scalar:
6507 sqxtn(vf, rd, rn);
6508 break;
6509 case NEON_UQXTN_scalar:
6510 uqxtn(vf, rd, rn);
6511 break;
6512 case NEON_SQXTUN_scalar:
6513 sqxtun(vf, rd, rn);
6514 break;
6515 default:
6516 VIXL_UNIMPLEMENTED();
6517 }
6518 }
6519 }
6520}
6521
6522
Jacob Bramleyca789742018-09-13 14:25:46 +01006523void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
6524 VectorFormat fpf = kFormatH;
6525 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6526
6527 SimVRegister& rd = ReadVRegister(instr->GetRd());
6528 SimVRegister& rn = ReadVRegister(instr->GetRn());
6529
6530 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6531 case NEON_FRECPE_H_scalar:
6532 frecpe(fpf, rd, rn, fpcr_rounding);
6533 break;
6534 case NEON_FRECPX_H_scalar:
6535 frecpx(fpf, rd, rn);
6536 break;
6537 case NEON_FRSQRTE_H_scalar:
6538 frsqrte(fpf, rd, rn);
6539 break;
6540 case NEON_FCMGT_H_zero_scalar:
6541 fcmp_zero(fpf, rd, rn, gt);
6542 break;
6543 case NEON_FCMGE_H_zero_scalar:
6544 fcmp_zero(fpf, rd, rn, ge);
6545 break;
6546 case NEON_FCMEQ_H_zero_scalar:
6547 fcmp_zero(fpf, rd, rn, eq);
6548 break;
6549 case NEON_FCMLE_H_zero_scalar:
6550 fcmp_zero(fpf, rd, rn, le);
6551 break;
6552 case NEON_FCMLT_H_zero_scalar:
6553 fcmp_zero(fpf, rd, rn, lt);
6554 break;
6555 case NEON_SCVTF_H_scalar:
6556 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6557 break;
6558 case NEON_UCVTF_H_scalar:
6559 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6560 break;
6561 case NEON_FCVTNS_H_scalar:
6562 fcvts(fpf, rd, rn, FPTieEven);
6563 break;
6564 case NEON_FCVTNU_H_scalar:
6565 fcvtu(fpf, rd, rn, FPTieEven);
6566 break;
6567 case NEON_FCVTPS_H_scalar:
6568 fcvts(fpf, rd, rn, FPPositiveInfinity);
6569 break;
6570 case NEON_FCVTPU_H_scalar:
6571 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6572 break;
6573 case NEON_FCVTMS_H_scalar:
6574 fcvts(fpf, rd, rn, FPNegativeInfinity);
6575 break;
6576 case NEON_FCVTMU_H_scalar:
6577 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6578 break;
6579 case NEON_FCVTZS_H_scalar:
6580 fcvts(fpf, rd, rn, FPZero);
6581 break;
6582 case NEON_FCVTZU_H_scalar:
6583 fcvtu(fpf, rd, rn, FPZero);
6584 break;
6585 case NEON_FCVTAS_H_scalar:
6586 fcvts(fpf, rd, rn, FPTieAway);
6587 break;
6588 case NEON_FCVTAU_H_scalar:
6589 fcvtu(fpf, rd, rn, FPTieAway);
6590 break;
6591 }
6592}
6593
6594
Alexandre Ramesd3832962016-07-04 15:03:43 +01006595void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6596 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6597 VectorFormat vf = nfd.GetVectorFormat();
6598
6599 SimVRegister& rd = ReadVRegister(instr->GetRd());
6600 SimVRegister& rn = ReadVRegister(instr->GetRn());
6601 SimVRegister& rm = ReadVRegister(instr->GetRm());
6602 switch (instr->Mask(NEONScalar3DiffMask)) {
6603 case NEON_SQDMLAL_scalar:
6604 sqdmlal(vf, rd, rn, rm);
6605 break;
6606 case NEON_SQDMLSL_scalar:
6607 sqdmlsl(vf, rd, rn, rm);
6608 break;
6609 case NEON_SQDMULL_scalar:
6610 sqdmull(vf, rd, rn, rm);
6611 break;
6612 default:
6613 VIXL_UNIMPLEMENTED();
6614 }
6615}
6616
6617
6618void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6619 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6620 VectorFormat vf = nfd.GetVectorFormat();
6621
6622 SimVRegister& rd = ReadVRegister(instr->GetRd());
6623 SimVRegister& rn = ReadVRegister(instr->GetRn());
6624 SimVRegister& rm = ReadVRegister(instr->GetRm());
6625
6626 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6627 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6628 switch (instr->Mask(NEONScalar3SameFPMask)) {
6629 case NEON_FMULX_scalar:
6630 fmulx(vf, rd, rn, rm);
6631 break;
6632 case NEON_FACGE_scalar:
6633 fabscmp(vf, rd, rn, rm, ge);
6634 break;
6635 case NEON_FACGT_scalar:
6636 fabscmp(vf, rd, rn, rm, gt);
6637 break;
6638 case NEON_FCMEQ_scalar:
6639 fcmp(vf, rd, rn, rm, eq);
6640 break;
6641 case NEON_FCMGE_scalar:
6642 fcmp(vf, rd, rn, rm, ge);
6643 break;
6644 case NEON_FCMGT_scalar:
6645 fcmp(vf, rd, rn, rm, gt);
6646 break;
6647 case NEON_FRECPS_scalar:
6648 frecps(vf, rd, rn, rm);
6649 break;
6650 case NEON_FRSQRTS_scalar:
6651 frsqrts(vf, rd, rn, rm);
6652 break;
6653 case NEON_FABD_scalar:
6654 fabd(vf, rd, rn, rm);
6655 break;
6656 default:
6657 VIXL_UNIMPLEMENTED();
6658 }
6659 } else {
6660 switch (instr->Mask(NEONScalar3SameMask)) {
6661 case NEON_ADD_scalar:
6662 add(vf, rd, rn, rm);
6663 break;
6664 case NEON_SUB_scalar:
6665 sub(vf, rd, rn, rm);
6666 break;
6667 case NEON_CMEQ_scalar:
6668 cmp(vf, rd, rn, rm, eq);
6669 break;
6670 case NEON_CMGE_scalar:
6671 cmp(vf, rd, rn, rm, ge);
6672 break;
6673 case NEON_CMGT_scalar:
6674 cmp(vf, rd, rn, rm, gt);
6675 break;
6676 case NEON_CMHI_scalar:
6677 cmp(vf, rd, rn, rm, hi);
6678 break;
6679 case NEON_CMHS_scalar:
6680 cmp(vf, rd, rn, rm, hs);
6681 break;
6682 case NEON_CMTST_scalar:
6683 cmptst(vf, rd, rn, rm);
6684 break;
6685 case NEON_USHL_scalar:
6686 ushl(vf, rd, rn, rm);
6687 break;
6688 case NEON_SSHL_scalar:
6689 sshl(vf, rd, rn, rm);
6690 break;
6691 case NEON_SQDMULH_scalar:
6692 sqdmulh(vf, rd, rn, rm);
6693 break;
6694 case NEON_SQRDMULH_scalar:
6695 sqrdmulh(vf, rd, rn, rm);
6696 break;
6697 case NEON_UQADD_scalar:
6698 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6699 break;
6700 case NEON_SQADD_scalar:
6701 add(vf, rd, rn, rm).SignedSaturate(vf);
6702 break;
6703 case NEON_UQSUB_scalar:
6704 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6705 break;
6706 case NEON_SQSUB_scalar:
6707 sub(vf, rd, rn, rm).SignedSaturate(vf);
6708 break;
6709 case NEON_UQSHL_scalar:
6710 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6711 break;
6712 case NEON_SQSHL_scalar:
6713 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6714 break;
6715 case NEON_URSHL_scalar:
6716 ushl(vf, rd, rn, rm).Round(vf);
6717 break;
6718 case NEON_SRSHL_scalar:
6719 sshl(vf, rd, rn, rm).Round(vf);
6720 break;
6721 case NEON_UQRSHL_scalar:
6722 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6723 break;
6724 case NEON_SQRSHL_scalar:
6725 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6726 break;
6727 default:
6728 VIXL_UNIMPLEMENTED();
6729 }
6730 }
6731}
6732
Jacob Bramleyca789742018-09-13 14:25:46 +01006733void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6734 SimVRegister& rd = ReadVRegister(instr->GetRd());
6735 SimVRegister& rn = ReadVRegister(instr->GetRn());
6736 SimVRegister& rm = ReadVRegister(instr->GetRm());
6737
6738 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6739 case NEON_FABD_H_scalar:
6740 fabd(kFormatH, rd, rn, rm);
6741 break;
6742 case NEON_FMULX_H_scalar:
6743 fmulx(kFormatH, rd, rn, rm);
6744 break;
6745 case NEON_FCMEQ_H_scalar:
6746 fcmp(kFormatH, rd, rn, rm, eq);
6747 break;
6748 case NEON_FCMGE_H_scalar:
6749 fcmp(kFormatH, rd, rn, rm, ge);
6750 break;
6751 case NEON_FCMGT_H_scalar:
6752 fcmp(kFormatH, rd, rn, rm, gt);
6753 break;
6754 case NEON_FACGE_H_scalar:
6755 fabscmp(kFormatH, rd, rn, rm, ge);
6756 break;
6757 case NEON_FACGT_H_scalar:
6758 fabscmp(kFormatH, rd, rn, rm, gt);
6759 break;
6760 case NEON_FRECPS_H_scalar:
6761 frecps(kFormatH, rd, rn, rm);
6762 break;
6763 case NEON_FRSQRTS_H_scalar:
6764 frsqrts(kFormatH, rd, rn, rm);
6765 break;
6766 default:
6767 VIXL_UNREACHABLE();
6768 }
6769}
6770
Alexandre Ramesd3832962016-07-04 15:03:43 +01006771
Alexander Gilday43785642018-04-04 13:42:33 +01006772void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6773 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6774 VectorFormat vf = nfd.GetVectorFormat();
6775
6776 SimVRegister& rd = ReadVRegister(instr->GetRd());
6777 SimVRegister& rn = ReadVRegister(instr->GetRn());
6778 SimVRegister& rm = ReadVRegister(instr->GetRm());
6779
6780 switch (instr->Mask(NEONScalar3SameExtraMask)) {
6781 case NEON_SQRDMLAH_scalar:
6782 sqrdmlah(vf, rd, rn, rm);
6783 break;
6784 case NEON_SQRDMLSH_scalar:
6785 sqrdmlsh(vf, rd, rn, rm);
6786 break;
6787 default:
6788 VIXL_UNIMPLEMENTED();
6789 }
6790}
6791
Alexandre Ramesd3832962016-07-04 15:03:43 +01006792void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6793 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6794 VectorFormat vf = nfd.GetVectorFormat();
6795 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6796
6797 SimVRegister& rd = ReadVRegister(instr->GetRd());
6798 SimVRegister& rn = ReadVRegister(instr->GetRn());
6799 ByElementOp Op = NULL;
6800
6801 int rm_reg = instr->GetRm();
6802 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6803 if (instr->GetNEONSize() == 1) {
6804 rm_reg &= 0xf;
6805 index = (index << 1) | instr->GetNEONM();
6806 }
6807
6808 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6809 case NEON_SQDMULL_byelement_scalar:
6810 Op = &Simulator::sqdmull;
6811 break;
6812 case NEON_SQDMLAL_byelement_scalar:
6813 Op = &Simulator::sqdmlal;
6814 break;
6815 case NEON_SQDMLSL_byelement_scalar:
6816 Op = &Simulator::sqdmlsl;
6817 break;
6818 case NEON_SQDMULH_byelement_scalar:
6819 Op = &Simulator::sqdmulh;
6820 vf = vf_r;
6821 break;
6822 case NEON_SQRDMULH_byelement_scalar:
6823 Op = &Simulator::sqrdmulh;
6824 vf = vf_r;
6825 break;
Alexander Gilday43785642018-04-04 13:42:33 +01006826 case NEON_SQRDMLAH_byelement_scalar:
6827 Op = &Simulator::sqrdmlah;
6828 vf = vf_r;
6829 break;
6830 case NEON_SQRDMLSH_byelement_scalar:
6831 Op = &Simulator::sqrdmlsh;
6832 vf = vf_r;
6833 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006834 default:
6835 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6836 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01006837 if (instr->GetFPType() == 0) {
6838 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6839 rm_reg &= 0xf;
6840 vf = kFormatH;
6841 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006842 index = (index << 1) | instr->GetNEONL();
6843 }
6844 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006845 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006846 case NEON_FMUL_byelement_scalar:
6847 Op = &Simulator::fmul;
6848 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006849 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006850 case NEON_FMLA_byelement_scalar:
6851 Op = &Simulator::fmla;
6852 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006853 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006854 case NEON_FMLS_byelement_scalar:
6855 Op = &Simulator::fmls;
6856 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006857 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006858 case NEON_FMULX_byelement_scalar:
6859 Op = &Simulator::fmulx;
6860 break;
6861 default:
6862 VIXL_UNIMPLEMENTED();
6863 }
6864 }
6865
6866 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6867}
6868
6869
6870void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6871 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6872 VectorFormat vf = nfd.GetVectorFormat();
6873
6874 SimVRegister& rd = ReadVRegister(instr->GetRd());
6875 SimVRegister& rn = ReadVRegister(instr->GetRn());
6876
6877 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6878 int imm5 = instr->GetImmNEON5();
6879 int tz = CountTrailingZeros(imm5, 32);
6880 int rn_index = imm5 >> (tz + 1);
6881 dup_element(vf, rd, rn, rn_index);
6882 } else {
6883 VIXL_UNIMPLEMENTED();
6884 }
6885}
6886
6887
6888void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006889 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006890 VectorFormat vf = nfd.GetVectorFormat();
6891
6892 SimVRegister& rd = ReadVRegister(instr->GetRd());
6893 SimVRegister& rn = ReadVRegister(instr->GetRn());
6894 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006895 case NEON_ADDP_scalar: {
6896 // All pairwise operations except ADDP use bit U to differentiate FP16
6897 // from FP32/FP64 variations.
6898 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6899 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006900 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006901 }
6902 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006903 case NEON_FADDP_scalar:
6904 faddp(vf, rd, rn);
6905 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006906 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006907 case NEON_FMAXP_scalar:
6908 fmaxp(vf, rd, rn);
6909 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006910 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006911 case NEON_FMAXNMP_scalar:
6912 fmaxnmp(vf, rd, rn);
6913 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006914 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006915 case NEON_FMINP_scalar:
6916 fminp(vf, rd, rn);
6917 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006918 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006919 case NEON_FMINNMP_scalar:
6920 fminnmp(vf, rd, rn);
6921 break;
6922 default:
6923 VIXL_UNIMPLEMENTED();
6924 }
6925}
6926
6927
6928void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6929 SimVRegister& rd = ReadVRegister(instr->GetRd());
6930 SimVRegister& rn = ReadVRegister(instr->GetRn());
6931 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6932
6933 static const NEONFormatMap map = {{22, 21, 20, 19},
6934 {NF_UNDEF,
6935 NF_B,
6936 NF_H,
6937 NF_H,
6938 NF_S,
6939 NF_S,
6940 NF_S,
6941 NF_S,
6942 NF_D,
6943 NF_D,
6944 NF_D,
6945 NF_D,
6946 NF_D,
6947 NF_D,
6948 NF_D,
6949 NF_D}};
6950 NEONFormatDecoder nfd(instr, &map);
6951 VectorFormat vf = nfd.GetVectorFormat();
6952
6953 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6954 int immhimmb = instr->GetImmNEONImmhImmb();
6955 int right_shift = (16 << highestSetBit) - immhimmb;
6956 int left_shift = immhimmb - (8 << highestSetBit);
6957 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
6958 case NEON_SHL_scalar:
6959 shl(vf, rd, rn, left_shift);
6960 break;
6961 case NEON_SLI_scalar:
6962 sli(vf, rd, rn, left_shift);
6963 break;
6964 case NEON_SQSHL_imm_scalar:
6965 sqshl(vf, rd, rn, left_shift);
6966 break;
6967 case NEON_UQSHL_imm_scalar:
6968 uqshl(vf, rd, rn, left_shift);
6969 break;
6970 case NEON_SQSHLU_scalar:
6971 sqshlu(vf, rd, rn, left_shift);
6972 break;
6973 case NEON_SRI_scalar:
6974 sri(vf, rd, rn, right_shift);
6975 break;
6976 case NEON_SSHR_scalar:
6977 sshr(vf, rd, rn, right_shift);
6978 break;
6979 case NEON_USHR_scalar:
6980 ushr(vf, rd, rn, right_shift);
6981 break;
6982 case NEON_SRSHR_scalar:
6983 sshr(vf, rd, rn, right_shift).Round(vf);
6984 break;
6985 case NEON_URSHR_scalar:
6986 ushr(vf, rd, rn, right_shift).Round(vf);
6987 break;
6988 case NEON_SSRA_scalar:
6989 ssra(vf, rd, rn, right_shift);
6990 break;
6991 case NEON_USRA_scalar:
6992 usra(vf, rd, rn, right_shift);
6993 break;
6994 case NEON_SRSRA_scalar:
6995 srsra(vf, rd, rn, right_shift);
6996 break;
6997 case NEON_URSRA_scalar:
6998 ursra(vf, rd, rn, right_shift);
6999 break;
7000 case NEON_UQSHRN_scalar:
7001 uqshrn(vf, rd, rn, right_shift);
7002 break;
7003 case NEON_UQRSHRN_scalar:
7004 uqrshrn(vf, rd, rn, right_shift);
7005 break;
7006 case NEON_SQSHRN_scalar:
7007 sqshrn(vf, rd, rn, right_shift);
7008 break;
7009 case NEON_SQRSHRN_scalar:
7010 sqrshrn(vf, rd, rn, right_shift);
7011 break;
7012 case NEON_SQSHRUN_scalar:
7013 sqshrun(vf, rd, rn, right_shift);
7014 break;
7015 case NEON_SQRSHRUN_scalar:
7016 sqrshrun(vf, rd, rn, right_shift);
7017 break;
7018 case NEON_FCVTZS_imm_scalar:
7019 fcvts(vf, rd, rn, FPZero, right_shift);
7020 break;
7021 case NEON_FCVTZU_imm_scalar:
7022 fcvtu(vf, rd, rn, FPZero, right_shift);
7023 break;
7024 case NEON_SCVTF_imm_scalar:
7025 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7026 break;
7027 case NEON_UCVTF_imm_scalar:
7028 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7029 break;
7030 default:
7031 VIXL_UNIMPLEMENTED();
7032 }
7033}
7034
7035
7036void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
7037 SimVRegister& rd = ReadVRegister(instr->GetRd());
7038 SimVRegister& rn = ReadVRegister(instr->GetRn());
7039 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
7040
7041 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
7042 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
7043 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01007044 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
7045 NF_4H, NF_8H, NF_4H, NF_8H,
7046 NF_2S, NF_4S, NF_2S, NF_4S,
7047 NF_2S, NF_4S, NF_2S, NF_4S,
7048 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7049 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7050 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7051 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007052 NEONFormatDecoder nfd(instr, &map);
7053 VectorFormat vf = nfd.GetVectorFormat();
7054
7055 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
7056 static const NEONFormatMap map_l =
7057 {{22, 21, 20, 19},
7058 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
7059 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
7060
7061 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
7062 int immhimmb = instr->GetImmNEONImmhImmb();
7063 int right_shift = (16 << highestSetBit) - immhimmb;
7064 int left_shift = immhimmb - (8 << highestSetBit);
7065
7066 switch (instr->Mask(NEONShiftImmediateMask)) {
7067 case NEON_SHL:
7068 shl(vf, rd, rn, left_shift);
7069 break;
7070 case NEON_SLI:
7071 sli(vf, rd, rn, left_shift);
7072 break;
7073 case NEON_SQSHLU:
7074 sqshlu(vf, rd, rn, left_shift);
7075 break;
7076 case NEON_SRI:
7077 sri(vf, rd, rn, right_shift);
7078 break;
7079 case NEON_SSHR:
7080 sshr(vf, rd, rn, right_shift);
7081 break;
7082 case NEON_USHR:
7083 ushr(vf, rd, rn, right_shift);
7084 break;
7085 case NEON_SRSHR:
7086 sshr(vf, rd, rn, right_shift).Round(vf);
7087 break;
7088 case NEON_URSHR:
7089 ushr(vf, rd, rn, right_shift).Round(vf);
7090 break;
7091 case NEON_SSRA:
7092 ssra(vf, rd, rn, right_shift);
7093 break;
7094 case NEON_USRA:
7095 usra(vf, rd, rn, right_shift);
7096 break;
7097 case NEON_SRSRA:
7098 srsra(vf, rd, rn, right_shift);
7099 break;
7100 case NEON_URSRA:
7101 ursra(vf, rd, rn, right_shift);
7102 break;
7103 case NEON_SQSHL_imm:
7104 sqshl(vf, rd, rn, left_shift);
7105 break;
7106 case NEON_UQSHL_imm:
7107 uqshl(vf, rd, rn, left_shift);
7108 break;
7109 case NEON_SCVTF_imm:
7110 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7111 break;
7112 case NEON_UCVTF_imm:
7113 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7114 break;
7115 case NEON_FCVTZS_imm:
7116 fcvts(vf, rd, rn, FPZero, right_shift);
7117 break;
7118 case NEON_FCVTZU_imm:
7119 fcvtu(vf, rd, rn, FPZero, right_shift);
7120 break;
7121 case NEON_SSHLL:
7122 vf = vf_l;
7123 if (instr->Mask(NEON_Q)) {
7124 sshll2(vf, rd, rn, left_shift);
7125 } else {
7126 sshll(vf, rd, rn, left_shift);
7127 }
7128 break;
7129 case NEON_USHLL:
7130 vf = vf_l;
7131 if (instr->Mask(NEON_Q)) {
7132 ushll2(vf, rd, rn, left_shift);
7133 } else {
7134 ushll(vf, rd, rn, left_shift);
7135 }
7136 break;
7137 case NEON_SHRN:
7138 if (instr->Mask(NEON_Q)) {
7139 shrn2(vf, rd, rn, right_shift);
7140 } else {
7141 shrn(vf, rd, rn, right_shift);
7142 }
7143 break;
7144 case NEON_RSHRN:
7145 if (instr->Mask(NEON_Q)) {
7146 rshrn2(vf, rd, rn, right_shift);
7147 } else {
7148 rshrn(vf, rd, rn, right_shift);
7149 }
7150 break;
7151 case NEON_UQSHRN:
7152 if (instr->Mask(NEON_Q)) {
7153 uqshrn2(vf, rd, rn, right_shift);
7154 } else {
7155 uqshrn(vf, rd, rn, right_shift);
7156 }
7157 break;
7158 case NEON_UQRSHRN:
7159 if (instr->Mask(NEON_Q)) {
7160 uqrshrn2(vf, rd, rn, right_shift);
7161 } else {
7162 uqrshrn(vf, rd, rn, right_shift);
7163 }
7164 break;
7165 case NEON_SQSHRN:
7166 if (instr->Mask(NEON_Q)) {
7167 sqshrn2(vf, rd, rn, right_shift);
7168 } else {
7169 sqshrn(vf, rd, rn, right_shift);
7170 }
7171 break;
7172 case NEON_SQRSHRN:
7173 if (instr->Mask(NEON_Q)) {
7174 sqrshrn2(vf, rd, rn, right_shift);
7175 } else {
7176 sqrshrn(vf, rd, rn, right_shift);
7177 }
7178 break;
7179 case NEON_SQSHRUN:
7180 if (instr->Mask(NEON_Q)) {
7181 sqshrun2(vf, rd, rn, right_shift);
7182 } else {
7183 sqshrun(vf, rd, rn, right_shift);
7184 }
7185 break;
7186 case NEON_SQRSHRUN:
7187 if (instr->Mask(NEON_Q)) {
7188 sqrshrun2(vf, rd, rn, right_shift);
7189 } else {
7190 sqrshrun(vf, rd, rn, right_shift);
7191 }
7192 break;
7193 default:
7194 VIXL_UNIMPLEMENTED();
7195 }
7196}
7197
7198
7199void Simulator::VisitNEONTable(const Instruction* instr) {
7200 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7201 VectorFormat vf = nfd.GetVectorFormat();
7202
7203 SimVRegister& rd = ReadVRegister(instr->GetRd());
7204 SimVRegister& rn = ReadVRegister(instr->GetRn());
7205 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
7206 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
7207 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
7208 SimVRegister& rm = ReadVRegister(instr->GetRm());
7209
7210 switch (instr->Mask(NEONTableMask)) {
7211 case NEON_TBL_1v:
7212 tbl(vf, rd, rn, rm);
7213 break;
7214 case NEON_TBL_2v:
7215 tbl(vf, rd, rn, rn2, rm);
7216 break;
7217 case NEON_TBL_3v:
7218 tbl(vf, rd, rn, rn2, rn3, rm);
7219 break;
7220 case NEON_TBL_4v:
7221 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
7222 break;
7223 case NEON_TBX_1v:
7224 tbx(vf, rd, rn, rm);
7225 break;
7226 case NEON_TBX_2v:
7227 tbx(vf, rd, rn, rn2, rm);
7228 break;
7229 case NEON_TBX_3v:
7230 tbx(vf, rd, rn, rn2, rn3, rm);
7231 break;
7232 case NEON_TBX_4v:
7233 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
7234 break;
7235 default:
7236 VIXL_UNIMPLEMENTED();
7237 }
7238}
7239
7240
7241void Simulator::VisitNEONPerm(const Instruction* instr) {
7242 NEONFormatDecoder nfd(instr);
7243 VectorFormat vf = nfd.GetVectorFormat();
7244
7245 SimVRegister& rd = ReadVRegister(instr->GetRd());
7246 SimVRegister& rn = ReadVRegister(instr->GetRn());
7247 SimVRegister& rm = ReadVRegister(instr->GetRm());
7248
7249 switch (instr->Mask(NEONPermMask)) {
7250 case NEON_TRN1:
7251 trn1(vf, rd, rn, rm);
7252 break;
7253 case NEON_TRN2:
7254 trn2(vf, rd, rn, rm);
7255 break;
7256 case NEON_UZP1:
7257 uzp1(vf, rd, rn, rm);
7258 break;
7259 case NEON_UZP2:
7260 uzp2(vf, rd, rn, rm);
7261 break;
7262 case NEON_ZIP1:
7263 zip1(vf, rd, rn, rm);
7264 break;
7265 case NEON_ZIP2:
7266 zip2(vf, rd, rn, rm);
7267 break;
7268 default:
7269 VIXL_UNIMPLEMENTED();
7270 }
7271}
7272
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007273void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
7274 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007275 switch (instr->Mask(SVEAddressGenerationMask)) {
7276 case ADR_z_az_d_s32_scaled:
7277 VIXL_UNIMPLEMENTED();
7278 break;
7279 case ADR_z_az_d_u32_scaled:
7280 VIXL_UNIMPLEMENTED();
7281 break;
7282 case ADR_z_az_sd_same_scaled:
7283 VIXL_UNIMPLEMENTED();
7284 break;
7285 default:
7286 VIXL_UNIMPLEMENTED();
7287 break;
7288 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007289}
7290
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007291void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
7292 const Instruction* instr) {
7293 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07007294 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007295 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007296 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07007297 case ORR_z_zi: {
7298 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7299 uint64_t imm = instr->GetSVEImmLogical();
7300 // Valid immediate is a non-zero bits
7301 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007302 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
7303 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07007304 SVEFormatFromLaneSizeInBytesLog2(lane_size),
7305 ReadVRegister(instr->GetRd()),
7306 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007307 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07007308 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007309 default:
7310 VIXL_UNIMPLEMENTED();
7311 break;
7312 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007313}
7314
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007315void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
7316 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
7317 case DUPM_z_i: {
7318 /* DUPM uses the same lane size and immediate encoding as bitwise logical
7319 * immediate instructions. */
7320 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7321 uint64_t imm = instr->GetSVEImmLogical();
7322 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7323 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
7324 break;
7325 }
7326 default:
7327 VIXL_UNIMPLEMENTED();
7328 break;
7329 }
7330}
7331
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007332void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
7333 USE(instr);
TatWai Chongcfb94212019-05-16 13:30:09 -07007334 SimVRegister& zd = ReadVRegister(instr->GetRd());
7335 SimVRegister& zn = ReadVRegister(instr->GetRn());
7336 SimVRegister& zm = ReadVRegister(instr->GetRm());
7337 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
7338
TatWai Chong13634762019-07-16 16:20:45 -07007339 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07007340 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007341 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007342 logical_op = AND;
7343 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007344 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007345 logical_op = BIC;
7346 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007347 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007348 logical_op = EOR;
7349 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07007350 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007351 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007352 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007353 default:
TatWai Chong13634762019-07-16 16:20:45 -07007354 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007355 VIXL_UNIMPLEMENTED();
7356 break;
7357 }
TatWai Chong13634762019-07-16 16:20:45 -07007358 // Lane size of registers is irrelevant to the bitwise operations, so perform
7359 // the operation on D-sized lanes.
7360 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007361}
7362
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007363void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007364 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007365 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007366 case ASRD_z_p_zi:
7367 VIXL_UNIMPLEMENTED();
7368 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007369 case ASR_z_p_zi:
7370 VIXL_UNIMPLEMENTED();
7371 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007372 case LSL_z_p_zi:
7373 VIXL_UNIMPLEMENTED();
7374 break;
7375 case LSR_z_p_zi:
7376 VIXL_UNIMPLEMENTED();
7377 break;
7378 default:
7379 VIXL_UNIMPLEMENTED();
7380 break;
7381 }
7382}
7383
7384void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
7385 const Instruction* instr) {
7386 USE(instr);
7387 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
7388 case ASRR_z_p_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007389 VIXL_UNIMPLEMENTED();
7390 break;
7391 case ASR_z_p_zz:
7392 VIXL_UNIMPLEMENTED();
7393 break;
7394 case LSLR_z_p_zz:
7395 VIXL_UNIMPLEMENTED();
7396 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007397 case LSL_z_p_zz:
7398 VIXL_UNIMPLEMENTED();
7399 break;
7400 case LSRR_z_p_zz:
7401 VIXL_UNIMPLEMENTED();
7402 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007403 case LSR_z_p_zz:
7404 VIXL_UNIMPLEMENTED();
7405 break;
7406 default:
7407 VIXL_UNIMPLEMENTED();
7408 break;
7409 }
7410}
7411
7412void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
7413 const Instruction* instr) {
7414 USE(instr);
7415 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
7416 case ASR_z_p_zw:
7417 VIXL_UNIMPLEMENTED();
7418 break;
7419 case LSL_z_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007420 VIXL_UNIMPLEMENTED();
7421 break;
7422 case LSR_z_p_zw:
7423 VIXL_UNIMPLEMENTED();
7424 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007425 default:
7426 VIXL_UNIMPLEMENTED();
7427 break;
7428 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007429}
7430
7431void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
7432 USE(instr);
TatWai Chong29a0c432019-11-06 22:20:44 -08007433
7434 SimVRegister& zd = ReadVRegister(instr->GetRd());
7435 SimVRegister& zn = ReadVRegister(instr->GetRn());
7436
7437 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007438 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7439 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007440 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007441 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007442 break;
7443 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007444 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007445 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007446 break;
7447 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08007448 case LSR_z_zw:
7449 shift_op = LSR;
7450 break;
7451 default:
7452 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007453 VIXL_UNIMPLEMENTED();
7454 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08007455 }
7456
7457 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7458 case ASR_z_zi:
7459 case LSL_z_zi:
7460 case LSR_z_zi: {
7461 SimVRegister scratch;
7462 std::pair<int, int> shift_and_lane_size =
7463 instr->GetSVEImmShiftAndLaneSizeLog2();
7464 unsigned lane_size = shift_and_lane_size.second;
7465 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
7466 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7467 dup_immediate(vform, scratch, shift_and_lane_size.first);
7468 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
7469 break;
7470 }
7471 case ASR_z_zw:
7472 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007473 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007474 SVEBitwiseShiftHelper(shift_op,
7475 instr->GetSVEVectorFormat(),
7476 zd,
7477 zn,
7478 ReadVRegister(instr->GetRm()),
7479 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007480 break;
7481 default:
7482 VIXL_UNIMPLEMENTED();
7483 break;
7484 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007485}
7486
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007487void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00007488 // Although the instructions have a separate encoding class, the lane size is
7489 // encoded in the same way as most other SVE instructions.
7490 VectorFormat vform = instr->GetSVEVectorFormat();
7491
7492 int pattern = instr->GetImmSVEPredicateConstraint();
7493 int count = GetPredicateConstraintLaneCount(vform, pattern);
7494 int multiplier = instr->ExtractBits(19, 16) + 1;
7495
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007496 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007497 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007498 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007499 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007500 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007501 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007502 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007503 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007504 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007505 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007506 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007507 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007508 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007509 default:
7510 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00007511 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007512 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00007513
7514 WriteXRegister(instr->GetRd(),
7515 IncDecN(ReadXRegister(instr->GetRd()),
7516 count * multiplier,
7517 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007518}
7519
7520void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007521 VectorFormat vform = instr->GetSVEVectorFormat();
7522 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7523 VIXL_UNIMPLEMENTED();
7524 }
7525
7526 int pattern = instr->GetImmSVEPredicateConstraint();
7527 int count = GetPredicateConstraintLaneCount(vform, pattern);
7528 int multiplier = instr->ExtractBits(19, 16) + 1;
7529
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007530 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
7531 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007532 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007533 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007534 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007535 break;
7536 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007537 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007538 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007539 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007540 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007541 default:
7542 VIXL_UNIMPLEMENTED();
7543 break;
7544 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007545
7546 SimVRegister& zd = ReadVRegister(instr->GetRd());
7547 SimVRegister scratch;
7548 dup_immediate(vform,
7549 scratch,
7550 IncDecN(0,
7551 count * multiplier,
7552 LaneSizeInBitsFromFormat(vform)));
7553 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007554}
7555
7556void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
7557 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007558 // Although the instructions have a separate encoding class, the lane size is
7559 // encoded in the same way as most other SVE instructions.
7560 VectorFormat vform = instr->GetSVEVectorFormat();
7561
7562 int pattern = instr->GetImmSVEPredicateConstraint();
7563 int count = GetPredicateConstraintLaneCount(vform, pattern);
7564 int multiplier = instr->ExtractBits(19, 16) + 1;
7565
7566 unsigned width = kXRegSize;
7567 bool is_signed = false;
7568
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007569 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007570 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007571 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007572 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007573 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007574 width = kWRegSize;
7575 VIXL_FALLTHROUGH();
7576 case SQDECB_r_rs_x:
7577 case SQDECD_r_rs_x:
7578 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007579 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007580 is_signed = true;
7581 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007582 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007583 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007584 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007585 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007586 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007587 width = kWRegSize;
7588 VIXL_FALLTHROUGH();
7589 case SQINCB_r_rs_x:
7590 case SQINCD_r_rs_x:
7591 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007592 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007593 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007594 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007595 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007596 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007597 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007598 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007599 width = kWRegSize;
7600 VIXL_FALLTHROUGH();
7601 case UQDECB_r_rs_x:
7602 case UQDECD_r_rs_x:
7603 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007604 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007605 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007606 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007607 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007608 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007609 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007610 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007611 width = kWRegSize;
7612 VIXL_FALLTHROUGH();
7613 case UQINCB_r_rs_x:
7614 case UQINCD_r_rs_x:
7615 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007616 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007617 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007618 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007619 default:
7620 VIXL_UNIMPLEMENTED();
7621 break;
7622 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007623
7624 WriteXRegister(instr->GetRd(),
7625 IncDecN(ReadXRegister(instr->GetRd()),
7626 count * multiplier,
7627 width,
7628 true,
7629 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007630}
7631
7632void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
7633 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007634 VectorFormat vform = instr->GetSVEVectorFormat();
7635 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7636 VIXL_UNIMPLEMENTED();
7637 }
7638
7639 int pattern = instr->GetImmSVEPredicateConstraint();
7640 int count = GetPredicateConstraintLaneCount(vform, pattern);
7641 int multiplier = instr->ExtractBits(19, 16) + 1;
7642
7643 SimVRegister& zd = ReadVRegister(instr->GetRd());
7644 SimVRegister scratch;
7645 dup_immediate(vform,
7646 scratch,
7647 IncDecN(0,
7648 count * multiplier,
7649 LaneSizeInBitsFromFormat(vform)));
7650
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007651 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7652 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007653 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007654 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007655 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007656 break;
7657 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007658 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007659 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007660 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007661 break;
7662 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007663 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007664 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007665 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007666 break;
7667 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007668 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007669 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007670 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007671 break;
7672 default:
7673 VIXL_UNIMPLEMENTED();
7674 break;
7675 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007676}
7677
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007678void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007679 switch (instr->Mask(SVEElementCountMask)) {
7680 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007681 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007682 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007683 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00007684 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007685 break;
7686 default:
7687 VIXL_UNIMPLEMENTED();
7688 break;
7689 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00007690
7691 // Although the instructions are separated, the lane size is encoded in the
7692 // same way as most other SVE instructions.
7693 VectorFormat vform = instr->GetSVEVectorFormat();
7694
7695 int pattern = instr->GetImmSVEPredicateConstraint();
7696 int count = GetPredicateConstraintLaneCount(vform, pattern);
7697 int multiplier = instr->ExtractBits(19, 16) + 1;
7698 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007699}
7700
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007701void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
7702 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007703 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7704 case FADDA_v_p_z:
7705 VIXL_UNIMPLEMENTED();
7706 break;
7707 default:
7708 VIXL_UNIMPLEMENTED();
7709 break;
7710 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007711}
7712
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007713void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007714 USE(instr);
TatWai Chongd316c5e2019-10-16 12:22:10 -07007715 VectorFormat vform = instr->GetSVEVectorFormat();
7716 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7717 SimVRegister& zm = ReadVRegister(instr->GetRn());
7718 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7719
7720 SimVRegister result;
7721
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007722 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007723 case FABD_z_p_zz:
7724 VIXL_UNIMPLEMENTED();
7725 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007726 case FADD_z_p_zz:
7727 VIXL_UNIMPLEMENTED();
7728 break;
7729 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007730 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007731 break;
7732 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007733 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007734 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007735 case FMAXNM_z_p_zz:
7736 VIXL_UNIMPLEMENTED();
7737 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007738 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007739 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007740 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007741 case FMINNM_z_p_zz:
7742 VIXL_UNIMPLEMENTED();
7743 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007744 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007745 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007746 break;
7747 case FMULX_z_p_zz:
7748 VIXL_UNIMPLEMENTED();
7749 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007750 case FMUL_z_p_zz:
7751 VIXL_UNIMPLEMENTED();
7752 break;
7753 case FSCALE_z_p_zz:
7754 VIXL_UNIMPLEMENTED();
7755 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007756 case FSUBR_z_p_zz:
7757 VIXL_UNIMPLEMENTED();
7758 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007759 case FSUB_z_p_zz:
7760 VIXL_UNIMPLEMENTED();
7761 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007762 default:
7763 VIXL_UNIMPLEMENTED();
7764 break;
7765 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07007766 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007767}
7768
7769void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
7770 const Instruction* instr) {
7771 USE(instr);
7772 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
7773 case FADD_z_p_zs:
7774 VIXL_UNIMPLEMENTED();
7775 break;
7776 case FMAXNM_z_p_zs:
7777 VIXL_UNIMPLEMENTED();
7778 break;
7779 case FMAX_z_p_zs:
7780 VIXL_UNIMPLEMENTED();
7781 break;
7782 case FMINNM_z_p_zs:
7783 VIXL_UNIMPLEMENTED();
7784 break;
7785 case FMIN_z_p_zs:
7786 VIXL_UNIMPLEMENTED();
7787 break;
7788 case FMUL_z_p_zs:
7789 VIXL_UNIMPLEMENTED();
7790 break;
7791 case FSUBR_z_p_zs:
7792 VIXL_UNIMPLEMENTED();
7793 break;
7794 case FSUB_z_p_zs:
7795 VIXL_UNIMPLEMENTED();
7796 break;
7797 default:
7798 VIXL_UNIMPLEMENTED();
7799 break;
7800 }
7801}
7802
7803void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
7804 USE(instr);
7805 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007806 case FTMAD_z_zzi:
7807 VIXL_UNIMPLEMENTED();
7808 break;
7809 default:
7810 VIXL_UNIMPLEMENTED();
7811 break;
7812 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007813}
7814
7815void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
7816 USE(instr);
TatWai Chongfe536042019-10-23 16:34:11 -07007817
7818 VectorFormat vform = instr->GetSVEVectorFormat();
7819 SimVRegister& zd = ReadVRegister(instr->GetRd());
7820 SimVRegister& zn = ReadVRegister(instr->GetRn());
7821 SimVRegister& zm = ReadVRegister(instr->GetRm());
7822
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007823 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7824 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007825 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007826 break;
7827 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007828 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007829 break;
7830 case FRECPS_z_zz:
7831 VIXL_UNIMPLEMENTED();
7832 break;
7833 case FRSQRTS_z_zz:
7834 VIXL_UNIMPLEMENTED();
7835 break;
7836 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007837 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007838 break;
7839 case FTSMUL_z_zz:
7840 VIXL_UNIMPLEMENTED();
7841 break;
7842 default:
7843 VIXL_UNIMPLEMENTED();
7844 break;
7845 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007846}
7847
7848void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
7849 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007850 switch (instr->Mask(SVEFPCompareVectorsMask)) {
7851 case FACGE_p_p_zz:
7852 VIXL_UNIMPLEMENTED();
7853 break;
7854 case FACGT_p_p_zz:
7855 VIXL_UNIMPLEMENTED();
7856 break;
7857 case FCMEQ_p_p_zz:
7858 VIXL_UNIMPLEMENTED();
7859 break;
7860 case FCMGE_p_p_zz:
7861 VIXL_UNIMPLEMENTED();
7862 break;
7863 case FCMGT_p_p_zz:
7864 VIXL_UNIMPLEMENTED();
7865 break;
7866 case FCMNE_p_p_zz:
7867 VIXL_UNIMPLEMENTED();
7868 break;
7869 case FCMUO_p_p_zz:
7870 VIXL_UNIMPLEMENTED();
7871 break;
7872 default:
7873 VIXL_UNIMPLEMENTED();
7874 break;
7875 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007876}
7877
7878void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
7879 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007880 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
7881 case FCMEQ_p_p_z0:
7882 VIXL_UNIMPLEMENTED();
7883 break;
7884 case FCMGE_p_p_z0:
7885 VIXL_UNIMPLEMENTED();
7886 break;
7887 case FCMGT_p_p_z0:
7888 VIXL_UNIMPLEMENTED();
7889 break;
7890 case FCMLE_p_p_z0:
7891 VIXL_UNIMPLEMENTED();
7892 break;
7893 case FCMLT_p_p_z0:
7894 VIXL_UNIMPLEMENTED();
7895 break;
7896 case FCMNE_p_p_z0:
7897 VIXL_UNIMPLEMENTED();
7898 break;
7899 default:
7900 VIXL_UNIMPLEMENTED();
7901 break;
7902 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007903}
7904
7905void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
7906 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007907 switch (instr->Mask(SVEFPComplexAdditionMask)) {
7908 case FCADD_z_p_zz:
7909 VIXL_UNIMPLEMENTED();
7910 break;
7911 default:
7912 VIXL_UNIMPLEMENTED();
7913 break;
7914 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007915}
7916
7917void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
7918 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007919 switch (instr->Mask(SVEFPComplexMulAddMask)) {
7920 case FCMLA_z_p_zzz:
7921 VIXL_UNIMPLEMENTED();
7922 break;
7923 default:
7924 VIXL_UNIMPLEMENTED();
7925 break;
7926 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007927}
7928
7929void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
7930 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007931 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
7932 case FCMLA_z_zzzi_h:
7933 VIXL_UNIMPLEMENTED();
7934 break;
7935 case FCMLA_z_zzzi_s:
7936 VIXL_UNIMPLEMENTED();
7937 break;
7938 default:
7939 VIXL_UNIMPLEMENTED();
7940 break;
7941 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007942}
7943
7944void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
7945 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007946 switch (instr->Mask(SVEFPFastReductionMask)) {
7947 case FADDV_v_p_z:
7948 VIXL_UNIMPLEMENTED();
7949 break;
7950 case FMAXNMV_v_p_z:
7951 VIXL_UNIMPLEMENTED();
7952 break;
7953 case FMAXV_v_p_z:
7954 VIXL_UNIMPLEMENTED();
7955 break;
7956 case FMINNMV_v_p_z:
7957 VIXL_UNIMPLEMENTED();
7958 break;
7959 case FMINV_v_p_z:
7960 VIXL_UNIMPLEMENTED();
7961 break;
7962 default:
7963 VIXL_UNIMPLEMENTED();
7964 break;
7965 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007966}
7967
7968void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
7969 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007970 switch (instr->Mask(SVEFPMulIndexMask)) {
7971 case FMUL_z_zzi_d:
7972 VIXL_UNIMPLEMENTED();
7973 break;
7974 case FMUL_z_zzi_h:
7975 VIXL_UNIMPLEMENTED();
7976 break;
7977 case FMUL_z_zzi_s:
7978 VIXL_UNIMPLEMENTED();
7979 break;
7980 default:
7981 VIXL_UNIMPLEMENTED();
7982 break;
7983 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007984}
7985
7986void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
7987 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007988 switch (instr->Mask(SVEFPMulAddMask)) {
7989 case FMAD_z_p_zzz:
7990 VIXL_UNIMPLEMENTED();
7991 break;
7992 case FMLA_z_p_zzz:
7993 VIXL_UNIMPLEMENTED();
7994 break;
7995 case FMLS_z_p_zzz:
7996 VIXL_UNIMPLEMENTED();
7997 break;
7998 case FMSB_z_p_zzz:
7999 VIXL_UNIMPLEMENTED();
8000 break;
8001 case FNMAD_z_p_zzz:
8002 VIXL_UNIMPLEMENTED();
8003 break;
8004 case FNMLA_z_p_zzz:
8005 VIXL_UNIMPLEMENTED();
8006 break;
8007 case FNMLS_z_p_zzz:
8008 VIXL_UNIMPLEMENTED();
8009 break;
8010 case FNMSB_z_p_zzz:
8011 VIXL_UNIMPLEMENTED();
8012 break;
8013 default:
8014 VIXL_UNIMPLEMENTED();
8015 break;
8016 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008017}
8018
8019void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
8020 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008021 switch (instr->Mask(SVEFPMulAddIndexMask)) {
8022 case FMLA_z_zzzi_d:
8023 VIXL_UNIMPLEMENTED();
8024 break;
8025 case FMLA_z_zzzi_h:
8026 VIXL_UNIMPLEMENTED();
8027 break;
8028 case FMLA_z_zzzi_s:
8029 VIXL_UNIMPLEMENTED();
8030 break;
8031 case FMLS_z_zzzi_d:
8032 VIXL_UNIMPLEMENTED();
8033 break;
8034 case FMLS_z_zzzi_h:
8035 VIXL_UNIMPLEMENTED();
8036 break;
8037 case FMLS_z_zzzi_s:
8038 VIXL_UNIMPLEMENTED();
8039 break;
8040 default:
8041 VIXL_UNIMPLEMENTED();
8042 break;
8043 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008044}
8045
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008046void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008047 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008048 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008049 case FCVTZS_z_p_z_d2w:
8050 VIXL_UNIMPLEMENTED();
8051 break;
8052 case FCVTZS_z_p_z_d2x:
8053 VIXL_UNIMPLEMENTED();
8054 break;
8055 case FCVTZS_z_p_z_fp162h:
8056 VIXL_UNIMPLEMENTED();
8057 break;
8058 case FCVTZS_z_p_z_fp162w:
8059 VIXL_UNIMPLEMENTED();
8060 break;
8061 case FCVTZS_z_p_z_fp162x:
8062 VIXL_UNIMPLEMENTED();
8063 break;
8064 case FCVTZS_z_p_z_s2w:
8065 VIXL_UNIMPLEMENTED();
8066 break;
8067 case FCVTZS_z_p_z_s2x:
8068 VIXL_UNIMPLEMENTED();
8069 break;
8070 case FCVTZU_z_p_z_d2w:
8071 VIXL_UNIMPLEMENTED();
8072 break;
8073 case FCVTZU_z_p_z_d2x:
8074 VIXL_UNIMPLEMENTED();
8075 break;
8076 case FCVTZU_z_p_z_fp162h:
8077 VIXL_UNIMPLEMENTED();
8078 break;
8079 case FCVTZU_z_p_z_fp162w:
8080 VIXL_UNIMPLEMENTED();
8081 break;
8082 case FCVTZU_z_p_z_fp162x:
8083 VIXL_UNIMPLEMENTED();
8084 break;
8085 case FCVTZU_z_p_z_s2w:
8086 VIXL_UNIMPLEMENTED();
8087 break;
8088 case FCVTZU_z_p_z_s2x:
8089 VIXL_UNIMPLEMENTED();
8090 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008091 default:
8092 VIXL_UNIMPLEMENTED();
8093 break;
8094 }
8095}
8096
8097void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
8098 USE(instr);
8099 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008100 case FCVT_z_p_z_d2h:
8101 VIXL_UNIMPLEMENTED();
8102 break;
8103 case FCVT_z_p_z_d2s:
8104 VIXL_UNIMPLEMENTED();
8105 break;
8106 case FCVT_z_p_z_h2d:
8107 VIXL_UNIMPLEMENTED();
8108 break;
8109 case FCVT_z_p_z_h2s:
8110 VIXL_UNIMPLEMENTED();
8111 break;
8112 case FCVT_z_p_z_s2d:
8113 VIXL_UNIMPLEMENTED();
8114 break;
8115 case FCVT_z_p_z_s2h:
8116 VIXL_UNIMPLEMENTED();
8117 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008118 default:
8119 VIXL_UNIMPLEMENTED();
8120 break;
8121 }
8122}
8123
8124void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
8125 USE(instr);
8126 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008127 case FRECPX_z_p_z:
8128 VIXL_UNIMPLEMENTED();
8129 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008130 case FSQRT_z_p_z:
8131 VIXL_UNIMPLEMENTED();
8132 break;
8133 default:
8134 VIXL_UNIMPLEMENTED();
8135 break;
8136 }
8137}
8138
8139void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
8140 USE(instr);
8141 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008142 case FRINTA_z_p_z:
8143 VIXL_UNIMPLEMENTED();
8144 break;
8145 case FRINTI_z_p_z:
8146 VIXL_UNIMPLEMENTED();
8147 break;
8148 case FRINTM_z_p_z:
8149 VIXL_UNIMPLEMENTED();
8150 break;
8151 case FRINTN_z_p_z:
8152 VIXL_UNIMPLEMENTED();
8153 break;
8154 case FRINTP_z_p_z:
8155 VIXL_UNIMPLEMENTED();
8156 break;
8157 case FRINTX_z_p_z:
8158 VIXL_UNIMPLEMENTED();
8159 break;
8160 case FRINTZ_z_p_z:
8161 VIXL_UNIMPLEMENTED();
8162 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008163 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008164 VIXL_UNIMPLEMENTED();
8165 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008166 }
8167}
8168
8169void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
8170 USE(instr);
8171 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008172 case SCVTF_z_p_z_h2fp16:
8173 VIXL_UNIMPLEMENTED();
8174 break;
8175 case SCVTF_z_p_z_w2d:
8176 VIXL_UNIMPLEMENTED();
8177 break;
8178 case SCVTF_z_p_z_w2fp16:
8179 VIXL_UNIMPLEMENTED();
8180 break;
8181 case SCVTF_z_p_z_w2s:
8182 VIXL_UNIMPLEMENTED();
8183 break;
8184 case SCVTF_z_p_z_x2d:
8185 VIXL_UNIMPLEMENTED();
8186 break;
8187 case SCVTF_z_p_z_x2fp16:
8188 VIXL_UNIMPLEMENTED();
8189 break;
8190 case SCVTF_z_p_z_x2s:
8191 VIXL_UNIMPLEMENTED();
8192 break;
8193 case UCVTF_z_p_z_h2fp16:
8194 VIXL_UNIMPLEMENTED();
8195 break;
8196 case UCVTF_z_p_z_w2d:
8197 VIXL_UNIMPLEMENTED();
8198 break;
8199 case UCVTF_z_p_z_w2fp16:
8200 VIXL_UNIMPLEMENTED();
8201 break;
8202 case UCVTF_z_p_z_w2s:
8203 VIXL_UNIMPLEMENTED();
8204 break;
8205 case UCVTF_z_p_z_x2d:
8206 VIXL_UNIMPLEMENTED();
8207 break;
8208 case UCVTF_z_p_z_x2fp16:
8209 VIXL_UNIMPLEMENTED();
8210 break;
8211 case UCVTF_z_p_z_x2s:
8212 VIXL_UNIMPLEMENTED();
8213 break;
8214 default:
8215 VIXL_UNIMPLEMENTED();
8216 break;
8217 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008218}
8219
8220void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
8221 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008222 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8223 case FRECPE_z_z:
8224 VIXL_UNIMPLEMENTED();
8225 break;
8226 case FRSQRTE_z_z:
8227 VIXL_UNIMPLEMENTED();
8228 break;
8229 default:
8230 VIXL_UNIMPLEMENTED();
8231 break;
8232 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008233}
8234
8235void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
8236 USE(instr);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008237
8238 VectorFormat vform = instr->GetSVEVectorFormat();
8239 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
8240
8241 int count = CountActiveLanes(vform, pg);
8242
8243 if (instr->ExtractBit(11) == 0) {
8244 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8245 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8246 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008247 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008248 break;
8249 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008250 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008251 break;
8252 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008253 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008254 break;
8255 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008256 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008257 break;
8258 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008259 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008260 break;
8261 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008262 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008263 break;
8264 default:
8265 VIXL_UNIMPLEMENTED();
8266 break;
8267 }
8268 } else {
8269 bool is_saturating = (instr->ExtractBit(18) == 0);
8270 bool decrement =
8271 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
8272 bool is_signed = (instr->ExtractBit(16) == 0);
8273 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
8274 unsigned width = sf ? kXRegSize : kWRegSize;
8275
8276 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8277 case DECP_r_p_r:
8278 case INCP_r_p_r:
8279 case SQDECP_r_p_r_sx:
8280 case SQDECP_r_p_r_x:
8281 case SQINCP_r_p_r_sx:
8282 case SQINCP_r_p_r_x:
8283 case UQDECP_r_p_r_uw:
8284 case UQDECP_r_p_r_x:
8285 case UQINCP_r_p_r_uw:
8286 case UQINCP_r_p_r_x:
8287 WriteXRegister(instr->GetRd(),
8288 IncDecN(ReadXRegister(instr->GetRd()),
8289 decrement ? -count : count,
8290 width,
8291 is_saturating,
8292 is_signed));
8293 break;
8294 default:
8295 VIXL_UNIMPLEMENTED();
8296 break;
8297 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008298 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008299}
8300
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008301uint64_t Simulator::IncDecN(uint64_t acc,
8302 int64_t delta,
8303 unsigned n,
8304 bool is_saturating,
8305 bool is_signed) {
8306 VIXL_ASSERT(n <= 64);
8307 VIXL_ASSERT(IsIntN(n, delta));
8308
8309 uint64_t sign_mask = UINT64_C(1) << (n - 1);
8310 uint64_t mask = GetUintMask(n);
8311
8312 acc &= mask; // Ignore initial accumulator high bits.
8313 uint64_t result = (acc + delta) & mask;
8314
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008315 bool result_negative = ((result & sign_mask) != 0);
8316
8317 if (is_saturating) {
8318 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00008319 bool acc_negative = ((acc & sign_mask) != 0);
8320 bool delta_negative = delta < 0;
8321
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008322 // If the signs of the operands are the same, but different from the
8323 // result, there was an overflow.
8324 if ((acc_negative == delta_negative) &&
8325 (acc_negative != result_negative)) {
8326 if (result_negative) {
8327 // Saturate to [..., INT<n>_MAX].
8328 result_negative = false;
8329 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
8330 } else {
8331 // Saturate to [INT<n>_MIN, ...].
8332 result_negative = true;
8333 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
8334 }
8335 }
8336 } else {
8337 if ((delta < 0) && (result > acc)) {
8338 // Saturate to [0, ...].
8339 result = 0;
8340 } else if ((delta > 0) && (result < acc)) {
8341 // Saturate to [..., UINT<n>_MAX].
8342 result = mask;
8343 }
8344 }
8345 }
8346
8347 // Sign-extend if necessary.
8348 if (result_negative && is_signed) result |= ~mask;
8349
8350 return result;
8351}
8352
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008353void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
8354 USE(instr);
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008355 VectorFormat vform = instr->GetSVEVectorFormat();
8356 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008357 switch (instr->Mask(SVEIndexGenerationMask)) {
8358 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008359 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008360 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008361 case INDEX_z_rr: {
8362 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
8363 : instr->ExtractSignedBits(9, 5);
8364 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
8365 : instr->ExtractSignedBits(20, 16);
8366 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008367 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008368 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008369 default:
8370 VIXL_UNIMPLEMENTED();
8371 break;
8372 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008373}
8374
8375void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -07008376 VectorFormat vform = instr->GetSVEVectorFormat();
8377 SimVRegister& zd = ReadVRegister(instr->GetRd());
8378 SimVRegister& zn = ReadVRegister(instr->GetRn());
8379 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008380 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8381 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008382 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008383 break;
8384 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008385 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008386 break;
8387 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008388 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008389 break;
8390 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008391 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008392 break;
8393 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008394 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008395 break;
8396 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008397 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008398 break;
8399 default:
8400 VIXL_UNIMPLEMENTED();
8401 break;
8402 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008403}
8404
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008405void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008406 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -07008407 VectorFormat vform = instr->GetSVEVectorFormat();
8408 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8409 SimVRegister& zm = ReadVRegister(instr->GetRn());
8410 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8411 SimVRegister result;
8412
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008413 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008414 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008415 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008416 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008417 case SUBR_z_p_zz:
8418 sub(vform, result, zm, zdn);
8419 break;
8420 case SUB_z_p_zz:
8421 sub(vform, result, zdn, zm);
8422 break;
8423 default:
8424 VIXL_UNIMPLEMENTED();
8425 break;
8426 }
8427 mov_merging(vform, zdn, pg, result);
8428}
8429
8430void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
8431 VectorFormat vform = instr->GetSVEVectorFormat();
8432 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8433 SimVRegister& zm = ReadVRegister(instr->GetRn());
8434 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8435 SimVRegister result;
8436
8437 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008438 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008439 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008440 break;
8441 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008442 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008443 break;
8444 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008445 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008446 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008447 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008448 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008449 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008450 default:
8451 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008452 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008453 }
8454 mov_merging(vform, zdn, pg, result);
8455}
8456
8457void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
8458 VectorFormat vform = instr->GetSVEVectorFormat();
8459 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8460 SimVRegister& zm = ReadVRegister(instr->GetRn());
8461 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8462 SimVRegister result;
8463
8464 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
8465 case MUL_z_p_zz:
8466 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008467 break;
8468 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008469 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008470 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008471 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008472 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008473 break;
8474 default:
8475 VIXL_UNIMPLEMENTED();
8476 break;
8477 }
TatWai Chong13634762019-07-16 16:20:45 -07008478 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008479}
8480
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008481void Simulator::VisitSVEIntMinMaxDifference_Predicated(
8482 const Instruction* instr) {
8483 VectorFormat vform = instr->GetSVEVectorFormat();
8484 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8485 SimVRegister& zm = ReadVRegister(instr->GetRn());
8486 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8487 SimVRegister result;
8488
8489 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
8490 case SABD_z_p_zz:
8491 absdiff(vform, result, zdn, zm, true);
8492 break;
8493 case SMAX_z_p_zz:
8494 smax(vform, result, zdn, zm);
8495 break;
8496 case SMIN_z_p_zz:
8497 smin(vform, result, zdn, zm);
8498 break;
8499 case UABD_z_p_zz:
8500 absdiff(vform, result, zdn, zm, false);
8501 break;
8502 case UMAX_z_p_zz:
8503 umax(vform, result, zdn, zm);
8504 break;
8505 case UMIN_z_p_zz:
8506 umin(vform, result, zdn, zm);
8507 break;
8508 default:
8509 VIXL_UNIMPLEMENTED();
8510 break;
8511 }
8512 mov_merging(vform, zdn, pg, result);
8513}
8514
8515void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
8516 VectorFormat vform = instr->GetSVEVectorFormat();
8517 SimVRegister& zd = ReadVRegister(instr->GetRd());
8518 SimVRegister scratch;
8519
8520 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
8521 case MUL_z_zi:
8522 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
8523 mul(vform, zd, zd, scratch);
8524 break;
8525 default:
8526 VIXL_UNIMPLEMENTED();
8527 break;
8528 }
8529}
8530
8531void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
8532 VectorFormat vform = instr->GetSVEVectorFormat();
8533 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8534 SimVRegister& zm = ReadVRegister(instr->GetRn());
8535 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8536 SimVRegister result;
8537
8538 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
8539
8540 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
8541 case SDIVR_z_p_zz:
8542 sdiv(vform, result, zm, zdn);
8543 break;
8544 case SDIV_z_p_zz:
8545 sdiv(vform, result, zdn, zm);
8546 break;
8547 case UDIVR_z_p_zz:
8548 udiv(vform, result, zm, zdn);
8549 break;
8550 case UDIV_z_p_zz:
8551 udiv(vform, result, zdn, zm);
8552 break;
8553 default:
8554 VIXL_UNIMPLEMENTED();
8555 break;
8556 }
8557 mov_merging(vform, zdn, pg, result);
8558}
8559
8560void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
8561 VectorFormat vform = instr->GetSVEVectorFormat();
8562 SimVRegister& zd = ReadVRegister(instr->GetRd());
8563 SimVRegister scratch;
8564
8565 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
8566 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
8567
8568 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
8569 case SMAX_z_zi:
8570 dup_immediate(vform, scratch, signed_imm);
8571 smax(vform, zd, zd, scratch);
8572 break;
8573 case SMIN_z_zi:
8574 dup_immediate(vform, scratch, signed_imm);
8575 smin(vform, zd, zd, scratch);
8576 break;
8577 case UMAX_z_zi:
8578 dup_immediate(vform, scratch, unsigned_imm);
8579 umax(vform, zd, zd, scratch);
8580 break;
8581 case UMIN_z_zi:
8582 dup_immediate(vform, scratch, unsigned_imm);
8583 umin(vform, zd, zd, scratch);
8584 break;
8585 default:
8586 VIXL_UNIMPLEMENTED();
8587 break;
8588 }
8589}
8590
8591void Simulator::VisitSVEIntCompareScalarCountAndLimit(
8592 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -07008593 unsigned rn_code = instr->GetRn();
8594 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008595 SimPRegister& pd = ReadPRegister(instr->GetPd());
8596 VectorFormat vform = instr->GetSVEVectorFormat();
8597 bool is_64_bit = instr->ExtractBit(12) == 1;
8598 int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8599 int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
TatWai Chongc844bb22019-06-10 15:32:53 -07008600
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008601 bool last = true;
8602 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
8603 bool cond = false;
8604 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
8605 case WHILELE_p_p_rr:
8606 cond = src1 <= src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008607 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008608 case WHILELO_p_p_rr:
8609 cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
8610 break;
8611 case WHILELS_p_p_rr:
8612 cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
8613 break;
8614 case WHILELT_p_p_rr:
8615 cond = src1 < src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008616 break;
8617 default:
TatWai Chongc844bb22019-06-10 15:32:53 -07008618 VIXL_UNIMPLEMENTED();
8619 break;
8620 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008621 last = last && cond;
8622 LogicPRegister dst(pd);
8623 dst.SetActive(vform, lane, last);
8624 src1 += 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008625 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008626
8627 PredTest(vform, GetPTrue(), pd);
8628 LogSystemRegister(NZCV);
8629}
8630
8631void Simulator::VisitSVEConditionallyTerminateScalars(
8632 const Instruction* instr) {
8633 unsigned rn_code = instr->GetRn();
8634 unsigned rm_code = instr->GetRm();
8635 bool is_64_bit = instr->ExtractBit(22) == 1;
8636 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8637 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
8638 bool term;
8639 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
8640 case CTERMEQ_rr:
8641 term = src1 == src2;
8642 break;
8643 case CTERMNE_rr:
8644 term = src1 != src2;
8645 break;
8646 default:
8647 term = false;
8648 VIXL_UNIMPLEMENTED();
8649 break;
8650 }
8651 ReadNzcv().SetN(term ? 1 : 0);
8652 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -07008653 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008654}
8655
8656void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
8657 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008658 bool commute_inputs = false;
8659 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008660 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8661 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008662 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008663 break;
8664 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008665 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008666 break;
8667 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008668 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008669 break;
8670 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008671 cond = ge;
8672 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008673 break;
8674 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008675 cond = gt;
8676 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008677 break;
8678 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008679 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008680 break;
8681 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008682 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008683 VIXL_UNIMPLEMENTED();
8684 break;
8685 }
TatWai Chong302729c2019-06-14 16:18:51 -07008686
8687 VectorFormat vform = instr->GetSVEVectorFormat();
8688 SimVRegister src2;
8689 dup_immediate(vform,
8690 src2,
8691 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
8692 SVEIntCompareVectorsHelper(cond,
8693 vform,
8694 ReadPRegister(instr->GetPd()),
8695 ReadPRegister(instr->GetPgLow8()),
8696 commute_inputs ? src2
8697 : ReadVRegister(instr->GetRn()),
8698 commute_inputs ? ReadVRegister(instr->GetRn())
8699 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008700}
8701
8702void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
8703 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008704 bool commute_inputs = false;
8705 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008706 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8707 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008708 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008709 break;
8710 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008711 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008712 break;
8713 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008714 cond = hi;
8715 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008716 break;
8717 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008718 cond = hs;
8719 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008720 break;
8721 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008722 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008723 VIXL_UNIMPLEMENTED();
8724 break;
8725 }
TatWai Chong302729c2019-06-14 16:18:51 -07008726
8727 VectorFormat vform = instr->GetSVEVectorFormat();
8728 SimVRegister src2;
8729 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
8730 SVEIntCompareVectorsHelper(cond,
8731 vform,
8732 ReadPRegister(instr->GetPd()),
8733 ReadPRegister(instr->GetPgLow8()),
8734 commute_inputs ? src2
8735 : ReadVRegister(instr->GetRn()),
8736 commute_inputs ? ReadVRegister(instr->GetRn())
8737 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008738}
8739
8740void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
8741 USE(instr);
TatWai Chong96713fe2019-06-04 16:39:37 -07008742
8743 Instr op = instr->Mask(SVEIntCompareVectorsMask);
8744 bool is_wide_elements = false;
8745 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008746 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -07008747 case CMPGE_p_p_zw:
8748 case CMPGT_p_p_zw:
8749 case CMPHI_p_p_zw:
8750 case CMPHS_p_p_zw:
8751 case CMPLE_p_p_zw:
8752 case CMPLO_p_p_zw:
8753 case CMPLS_p_p_zw:
8754 case CMPLT_p_p_zw:
8755 case CMPNE_p_p_zw:
8756 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008757 break;
TatWai Chong96713fe2019-06-04 16:39:37 -07008758 }
8759
TatWai Chong302729c2019-06-14 16:18:51 -07008760 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -07008761 switch (op) {
8762 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008763 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008764 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008765 break;
8766 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008767 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008768 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008769 break;
8770 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008771 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008772 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008773 break;
8774 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008775 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008776 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008777 break;
8778 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008779 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008780 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008781 break;
8782 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008783 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008784 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -07008785 break;
8786 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008787 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -07008788 break;
8789 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008790 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -07008791 break;
8792 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008793 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -07008794 break;
8795 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008796 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008797 break;
8798 default:
8799 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -07008800 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008801 break;
8802 }
TatWai Chong96713fe2019-06-04 16:39:37 -07008803
TatWai Chong302729c2019-06-14 16:18:51 -07008804 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -07008805 instr->GetSVEVectorFormat(),
8806 ReadPRegister(instr->GetPd()),
8807 ReadPRegister(instr->GetPgLow8()),
8808 ReadVRegister(instr->GetRn()),
8809 ReadVRegister(instr->GetRm()),
8810 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008811}
8812
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008813void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00008814 VectorFormat vform = instr->GetSVEVectorFormat();
8815 SimVRegister& zd = ReadVRegister(instr->GetRd());
8816 SimVRegister& zn = ReadVRegister(instr->GetRn());
8817
8818 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
8819 (vform == kFormatVnD));
8820
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008821 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008822 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +00008823 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008824 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008825 default:
8826 VIXL_UNIMPLEMENTED();
8827 break;
8828 }
8829}
8830
8831void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00008832 VectorFormat vform = instr->GetSVEVectorFormat();
8833 SimVRegister& zd = ReadVRegister(instr->GetRd());
8834 SimVRegister& zn = ReadVRegister(instr->GetRn());
8835 SimVRegister& zm = ReadVRegister(instr->GetRm());
8836
8837 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
8838 (vform == kFormatVnD));
8839
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008840 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008841 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +00008842 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008843 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008844 default:
8845 VIXL_UNIMPLEMENTED();
8846 break;
8847 }
8848}
8849
8850void Simulator::VisitSVEConstructivePrefix_Unpredicated(
8851 const Instruction* instr) {
8852 SimVRegister& zd = ReadVRegister(instr->GetRd());
8853 SimVRegister& zn = ReadVRegister(instr->GetRn());
8854
8855 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008856 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008857 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
8858 // Record the movprfx, so the next ExecuteInstruction() can check it.
8859 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008860 break;
8861 default:
8862 VIXL_UNIMPLEMENTED();
8863 break;
8864 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008865}
8866
8867void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +01008868 VectorFormat vform = instr->GetSVEVectorFormat();
8869
8870 SimVRegister& zd = ReadVRegister(instr->GetRd());
8871 SimVRegister& zm = ReadVRegister(instr->GetRm());
8872
8873 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008874 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008875 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008876 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008877 break;
8878 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008879 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008880 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008881 case MAD_z_p_zzz:
8882 // 'za' is encoded in 'Rn'.
8883 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008884 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008885 case MSB_z_p_zzz: {
8886 // 'za' is encoded in 'Rn'.
8887 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
8888 break;
8889 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008890 default:
8891 VIXL_UNIMPLEMENTED();
8892 break;
8893 }
Jacob Bramley22023df2019-05-14 17:55:43 +01008894 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008895}
8896
8897void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
8898 USE(instr);
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008899
8900 VectorFormat vform = instr->GetSVEVectorFormat();
8901 SimVRegister& zda = ReadVRegister(instr->GetRd());
8902 SimVRegister& zn = ReadVRegister(instr->GetRn());
8903 SimVRegister& zm = ReadVRegister(instr->GetRm());
8904
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008905 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8906 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008907 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008908 break;
8909 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008910 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008911 break;
8912 default:
8913 VIXL_UNIMPLEMENTED();
8914 break;
8915 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008916}
8917
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008918void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008919 VectorFormat vform = instr->GetSVEVectorFormat();
8920 SimVRegister& zn = ReadVRegister(instr->GetRn());
8921 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8922 SimVRegister& zd = ReadVRegister(instr->GetRd());
8923
8924 switch (instr->Mask(SVEMovprfxMask)) {
8925 case MOVPRFX_z_p_z:
8926 if (instr->ExtractBit(16)) {
8927 mov_merging(vform, zd, pg, zn);
8928 } else {
8929 mov_zeroing(vform, zd, pg, zn);
8930 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008931
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008932 // Record the movprfx, so the next ExecuteInstruction() can check it.
8933 movprfx_ = instr;
8934 break;
8935 default:
8936 VIXL_UNIMPLEMENTED();
8937 break;
8938 }
8939}
8940
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008941void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008942 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +01008943 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008944 SimVRegister& zn = ReadVRegister(instr->GetRn());
8945 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8946
8947 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
8948 switch (instr->Mask(SVEIntReductionLogicalMask)) {
8949 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008950 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008951 break;
8952 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008953 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008954 break;
8955 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008956 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008957 break;
8958 default:
8959 VIXL_UNIMPLEMENTED();
8960 break;
8961 }
8962 } else {
8963 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008964 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008965 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008966 break;
8967 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008968 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008969 break;
8970 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008971 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008972 break;
8973 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008974 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008975 break;
8976 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008977 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008978 break;
8979 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008980 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008981 break;
8982 default:
8983 VIXL_UNIMPLEMENTED();
8984 break;
8985 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008986 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008987}
8988
8989void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
8990 USE(instr);
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008991
8992 VectorFormat vform = instr->GetSVEVectorFormat();
8993 SimVRegister& zn = ReadVRegister(instr->GetRn());
8994
8995 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008996 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
8997 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008998 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008999 break;
9000 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009001 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009002 break;
9003 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009004 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009005 break;
9006 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009007 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009008 break;
9009 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009010 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009011 break;
9012 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009013 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009014 break;
9015 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009016 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009017 break;
9018 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009019 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009020 break;
9021 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009022 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009023 break;
9024 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009025 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009026 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009027 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009028 break;
9029 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009030 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009031 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009032 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009033 break;
9034 default:
9035 VIXL_UNIMPLEMENTED();
9036 break;
9037 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009038
9039 SimVRegister& zd = ReadVRegister(instr->GetRd());
9040 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9041 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009042}
9043
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009044void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009045 // There is only one instruction in this group.
9046 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
9047
9048 VectorFormat vform = instr->GetSVEVectorFormat();
9049 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
9050 SimVRegister& zd = ReadVRegister(instr->GetRd());
9051
9052 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009053 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009054 case FCPY_z_p_i: {
9055 int imm8 = instr->ExtractBits(12, 5);
9056 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
9057 Instruction::Imm8ToFP64(imm8));
9058 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009059 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009060 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009061 default:
9062 VIXL_UNIMPLEMENTED();
9063 break;
9064 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009065 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009066}
9067
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009068void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
9069 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +01009070 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01009071 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +01009072 SimVRegister scratch;
9073
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009074 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
9075 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009076
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009077 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009078 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009079 add_uint(vform, zd, zd, imm);
9080 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009081 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009082 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
9083 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009084 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009085 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
9086 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009087 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009088 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +01009089 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009090 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009091 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009092 sub_uint(vform, zd, zd, imm);
9093 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009094 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009095 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9096 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009097 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009098 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9099 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009100 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009101 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009102 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009103}
TatWai Chong6995bfd2019-09-26 10:48:05 +01009104
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009105void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
9106 SimVRegister& zd = ReadVRegister(instr->GetRd());
9107
9108 int64_t imm = instr->GetImmSVEIntWideSigned();
9109 imm <<= instr->ExtractBit(13) * 8;
9110
9111 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
9112 case DUP_z_i:
9113 dup_immediate(instr->GetSVEVectorFormat(), zd, imm);
9114 break;
9115 default:
9116 VIXL_UNIMPLEMENTED();
9117 break;
9118 }
9119}
9120
9121void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
9122 VectorFormat vform = instr->GetSVEVectorFormat();
9123 SimVRegister& zd = ReadVRegister(instr->GetRd());
9124
9125 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009126 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +01009127 switch (vform) {
9128 case kFormatVnH:
9129 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
9130 break;
9131 case kFormatVnS:
9132 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
9133 break;
9134 case kFormatVnD:
9135 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
9136 break;
9137 default:
9138 VIXL_UNIMPLEMENTED();
9139 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009140 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009141 default:
9142 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009143 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009144 }
9145}
9146
9147void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
9148 const Instruction* instr) {
9149 USE(instr);
9150 switch (instr->Mask(
9151 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
9152 case LD1H_z_p_bz_s_x32_scaled:
9153 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009154 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009155 case LD1SH_z_p_bz_s_x32_scaled:
9156 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009157 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009158 case LDFF1H_z_p_bz_s_x32_scaled:
9159 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009160 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009161 case LDFF1SH_z_p_bz_s_x32_scaled:
9162 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009163 break;
9164 default:
9165 VIXL_UNIMPLEMENTED();
9166 break;
9167 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009168}
9169
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009170void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009171 const Instruction* instr) {
9172 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009173 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
9174 case LD1B_z_p_bz_s_x32_unscaled:
9175 VIXL_UNIMPLEMENTED();
9176 break;
9177 case LD1H_z_p_bz_s_x32_unscaled:
9178 VIXL_UNIMPLEMENTED();
9179 break;
9180 case LD1SB_z_p_bz_s_x32_unscaled:
9181 VIXL_UNIMPLEMENTED();
9182 break;
9183 case LD1SH_z_p_bz_s_x32_unscaled:
9184 VIXL_UNIMPLEMENTED();
9185 break;
9186 case LD1W_z_p_bz_s_x32_unscaled:
9187 VIXL_UNIMPLEMENTED();
9188 break;
9189 case LDFF1B_z_p_bz_s_x32_unscaled:
9190 VIXL_UNIMPLEMENTED();
9191 break;
9192 case LDFF1H_z_p_bz_s_x32_unscaled:
9193 VIXL_UNIMPLEMENTED();
9194 break;
9195 case LDFF1SB_z_p_bz_s_x32_unscaled:
9196 VIXL_UNIMPLEMENTED();
9197 break;
9198 case LDFF1SH_z_p_bz_s_x32_unscaled:
9199 VIXL_UNIMPLEMENTED();
9200 break;
9201 case LDFF1W_z_p_bz_s_x32_unscaled:
9202 VIXL_UNIMPLEMENTED();
9203 break;
9204 default:
9205 VIXL_UNIMPLEMENTED();
9206 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009207 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009208}
9209
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009210void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
9211 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009212 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009213 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
9214 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009215 VIXL_UNIMPLEMENTED();
9216 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009217 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009218 VIXL_UNIMPLEMENTED();
9219 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009220 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009221 VIXL_UNIMPLEMENTED();
9222 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009223 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009224 VIXL_UNIMPLEMENTED();
9225 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009226 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009227 VIXL_UNIMPLEMENTED();
9228 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009229 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009230 VIXL_UNIMPLEMENTED();
9231 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009232 case LDFF1H_z_p_ai_s:
9233 VIXL_UNIMPLEMENTED();
9234 break;
9235 case LDFF1SB_z_p_ai_s:
9236 VIXL_UNIMPLEMENTED();
9237 break;
9238 case LDFF1SH_z_p_ai_s:
9239 VIXL_UNIMPLEMENTED();
9240 break;
9241 case LDFF1W_z_p_ai_s:
9242 VIXL_UNIMPLEMENTED();
9243 break;
9244 default:
9245 VIXL_UNIMPLEMENTED();
9246 break;
9247 }
9248}
9249
9250void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
9251 const Instruction* instr) {
9252 USE(instr);
9253 switch (
9254 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
9255 case LD1W_z_p_bz_s_x32_scaled:
9256 VIXL_UNIMPLEMENTED();
9257 break;
9258 case LDFF1W_z_p_bz_s_x32_scaled:
9259 VIXL_UNIMPLEMENTED();
9260 break;
9261 default:
9262 VIXL_UNIMPLEMENTED();
9263 break;
9264 }
9265}
9266
9267void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
9268 const Instruction* instr) {
9269 USE(instr);
9270 switch (
9271 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
9272 case PRFB_i_p_bz_s_x32_scaled:
9273 VIXL_UNIMPLEMENTED();
9274 break;
9275 case PRFD_i_p_bz_s_x32_scaled:
9276 VIXL_UNIMPLEMENTED();
9277 break;
9278 case PRFH_i_p_bz_s_x32_scaled:
9279 VIXL_UNIMPLEMENTED();
9280 break;
9281 case PRFW_i_p_bz_s_x32_scaled:
9282 VIXL_UNIMPLEMENTED();
9283 break;
9284 default:
9285 VIXL_UNIMPLEMENTED();
9286 break;
9287 }
9288}
9289
9290void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
9291 const Instruction* instr) {
9292 USE(instr);
9293 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
9294 case PRFB_i_p_ai_s:
9295 VIXL_UNIMPLEMENTED();
9296 break;
9297 case PRFD_i_p_ai_s:
9298 VIXL_UNIMPLEMENTED();
9299 break;
9300 case PRFH_i_p_ai_s:
9301 VIXL_UNIMPLEMENTED();
9302 break;
9303 case PRFW_i_p_ai_s:
9304 VIXL_UNIMPLEMENTED();
9305 break;
9306 default:
9307 VIXL_UNIMPLEMENTED();
9308 break;
9309 }
9310}
9311
9312void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
9313 const Instruction* instr) {
9314 USE(instr);
9315 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
9316 case PRFB_i_p_bi_s:
9317 VIXL_UNIMPLEMENTED();
9318 break;
9319 case PRFD_i_p_bi_s:
9320 VIXL_UNIMPLEMENTED();
9321 break;
9322 case PRFH_i_p_bi_s:
9323 VIXL_UNIMPLEMENTED();
9324 break;
9325 case PRFW_i_p_bi_s:
9326 VIXL_UNIMPLEMENTED();
9327 break;
9328 default:
9329 VIXL_UNIMPLEMENTED();
9330 break;
9331 }
9332}
9333
9334void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
9335 const Instruction* instr) {
9336 USE(instr);
9337 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
9338 case PRFB_i_p_br_s:
9339 VIXL_UNIMPLEMENTED();
9340 break;
9341 case PRFD_i_p_br_s:
9342 VIXL_UNIMPLEMENTED();
9343 break;
9344 case PRFH_i_p_br_s:
9345 VIXL_UNIMPLEMENTED();
9346 break;
9347 case PRFW_i_p_br_s:
9348 VIXL_UNIMPLEMENTED();
9349 break;
9350 default:
9351 VIXL_UNIMPLEMENTED();
9352 break;
9353 }
9354}
9355
9356void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
9357 USE(instr);
9358 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
9359 case LD1RB_z_p_bi_u16:
9360 VIXL_UNIMPLEMENTED();
9361 break;
9362 case LD1RB_z_p_bi_u32:
9363 VIXL_UNIMPLEMENTED();
9364 break;
9365 case LD1RB_z_p_bi_u64:
9366 VIXL_UNIMPLEMENTED();
9367 break;
9368 case LD1RB_z_p_bi_u8:
9369 VIXL_UNIMPLEMENTED();
9370 break;
9371 case LD1RD_z_p_bi_u64:
9372 VIXL_UNIMPLEMENTED();
9373 break;
9374 case LD1RH_z_p_bi_u16:
9375 VIXL_UNIMPLEMENTED();
9376 break;
9377 case LD1RH_z_p_bi_u32:
9378 VIXL_UNIMPLEMENTED();
9379 break;
9380 case LD1RH_z_p_bi_u64:
9381 VIXL_UNIMPLEMENTED();
9382 break;
9383 case LD1RSB_z_p_bi_s16:
9384 VIXL_UNIMPLEMENTED();
9385 break;
9386 case LD1RSB_z_p_bi_s32:
9387 VIXL_UNIMPLEMENTED();
9388 break;
9389 case LD1RSB_z_p_bi_s64:
9390 VIXL_UNIMPLEMENTED();
9391 break;
9392 case LD1RSH_z_p_bi_s32:
9393 VIXL_UNIMPLEMENTED();
9394 break;
9395 case LD1RSH_z_p_bi_s64:
9396 VIXL_UNIMPLEMENTED();
9397 break;
9398 case LD1RSW_z_p_bi_s64:
9399 VIXL_UNIMPLEMENTED();
9400 break;
9401 case LD1RW_z_p_bi_u32:
9402 VIXL_UNIMPLEMENTED();
9403 break;
9404 case LD1RW_z_p_bi_u64:
9405 VIXL_UNIMPLEMENTED();
9406 break;
9407 default:
9408 VIXL_UNIMPLEMENTED();
9409 break;
9410 }
9411}
9412
9413void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
9414 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
9415 case LDR_p_bi: {
9416 SimPRegister& pt = ReadPRegister(instr->GetPt());
9417 int pl = GetPredicateLengthInBytes();
9418 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9419 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9420 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
9421 for (int i = 0; i < pl; i++) {
9422 pt.Insert(i, Memory::Read<uint8_t>(address + i));
9423 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009424 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009425 break;
9426 }
9427 default:
9428 VIXL_UNIMPLEMENTED();
9429 break;
9430 }
9431}
9432
9433void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
9434 USE(instr);
9435 switch (instr->Mask(SVELoadVectorRegisterMask)) {
9436 case LDR_z_bi: {
9437 SimVRegister& zt = ReadVRegister(instr->GetRt());
9438 int vl = GetVectorLengthInBytes();
9439 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9440 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9441 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
9442 for (int i = 0; i < vl; i++) {
9443 zt.Insert(i, Memory::Read<uint8_t>(address + i));
9444 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009445 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009446 break;
9447 }
9448 default:
9449 VIXL_UNIMPLEMENTED();
9450 break;
9451 }
9452}
9453
9454void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
9455 const Instruction* instr) {
9456 USE(instr);
9457 switch (instr->Mask(
9458 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009459 case LD1D_z_p_bz_d_x32_scaled:
9460 VIXL_UNIMPLEMENTED();
9461 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009462 case LD1H_z_p_bz_d_x32_scaled:
9463 VIXL_UNIMPLEMENTED();
9464 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009465 case LD1SH_z_p_bz_d_x32_scaled:
9466 VIXL_UNIMPLEMENTED();
9467 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009468 case LD1SW_z_p_bz_d_x32_scaled:
9469 VIXL_UNIMPLEMENTED();
9470 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009471 case LD1W_z_p_bz_d_x32_scaled:
9472 VIXL_UNIMPLEMENTED();
9473 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009474 case LDFF1D_z_p_bz_d_x32_scaled:
9475 VIXL_UNIMPLEMENTED();
9476 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009477 case LDFF1H_z_p_bz_d_x32_scaled:
9478 VIXL_UNIMPLEMENTED();
9479 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009480 case LDFF1SH_z_p_bz_d_x32_scaled:
9481 VIXL_UNIMPLEMENTED();
9482 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009483 case LDFF1SW_z_p_bz_d_x32_scaled:
9484 VIXL_UNIMPLEMENTED();
9485 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009486 case LDFF1W_z_p_bz_d_x32_scaled:
9487 VIXL_UNIMPLEMENTED();
9488 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009489 default:
9490 VIXL_UNIMPLEMENTED();
9491 break;
9492 }
9493}
9494
9495void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
9496 const Instruction* instr) {
9497 USE(instr);
9498 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
9499 case LD1D_z_p_bz_d_64_scaled:
9500 VIXL_UNIMPLEMENTED();
9501 break;
9502 case LD1H_z_p_bz_d_64_scaled:
9503 VIXL_UNIMPLEMENTED();
9504 break;
9505 case LD1SH_z_p_bz_d_64_scaled:
9506 VIXL_UNIMPLEMENTED();
9507 break;
9508 case LD1SW_z_p_bz_d_64_scaled:
9509 VIXL_UNIMPLEMENTED();
9510 break;
9511 case LD1W_z_p_bz_d_64_scaled:
9512 VIXL_UNIMPLEMENTED();
9513 break;
9514 case LDFF1D_z_p_bz_d_64_scaled:
9515 VIXL_UNIMPLEMENTED();
9516 break;
9517 case LDFF1H_z_p_bz_d_64_scaled:
9518 VIXL_UNIMPLEMENTED();
9519 break;
9520 case LDFF1SH_z_p_bz_d_64_scaled:
9521 VIXL_UNIMPLEMENTED();
9522 break;
9523 case LDFF1SW_z_p_bz_d_64_scaled:
9524 VIXL_UNIMPLEMENTED();
9525 break;
9526 case LDFF1W_z_p_bz_d_64_scaled:
9527 VIXL_UNIMPLEMENTED();
9528 break;
9529 default:
9530 VIXL_UNIMPLEMENTED();
9531 break;
9532 }
9533}
9534
9535void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
9536 const Instruction* instr) {
9537 USE(instr);
9538 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
9539 case LD1B_z_p_bz_d_64_unscaled:
9540 VIXL_UNIMPLEMENTED();
9541 break;
9542 case LD1D_z_p_bz_d_64_unscaled:
9543 VIXL_UNIMPLEMENTED();
9544 break;
9545 case LD1H_z_p_bz_d_64_unscaled:
9546 VIXL_UNIMPLEMENTED();
9547 break;
9548 case LD1SB_z_p_bz_d_64_unscaled:
9549 VIXL_UNIMPLEMENTED();
9550 break;
9551 case LD1SH_z_p_bz_d_64_unscaled:
9552 VIXL_UNIMPLEMENTED();
9553 break;
9554 case LD1SW_z_p_bz_d_64_unscaled:
9555 VIXL_UNIMPLEMENTED();
9556 break;
9557 case LD1W_z_p_bz_d_64_unscaled:
9558 VIXL_UNIMPLEMENTED();
9559 break;
9560 case LDFF1B_z_p_bz_d_64_unscaled:
9561 VIXL_UNIMPLEMENTED();
9562 break;
9563 case LDFF1D_z_p_bz_d_64_unscaled:
9564 VIXL_UNIMPLEMENTED();
9565 break;
9566 case LDFF1H_z_p_bz_d_64_unscaled:
9567 VIXL_UNIMPLEMENTED();
9568 break;
9569 case LDFF1SB_z_p_bz_d_64_unscaled:
9570 VIXL_UNIMPLEMENTED();
9571 break;
9572 case LDFF1SH_z_p_bz_d_64_unscaled:
9573 VIXL_UNIMPLEMENTED();
9574 break;
9575 case LDFF1SW_z_p_bz_d_64_unscaled:
9576 VIXL_UNIMPLEMENTED();
9577 break;
9578 case LDFF1W_z_p_bz_d_64_unscaled:
9579 VIXL_UNIMPLEMENTED();
9580 break;
9581 default:
9582 VIXL_UNIMPLEMENTED();
9583 break;
9584 }
9585}
9586
9587void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
9588 const Instruction* instr) {
9589 USE(instr);
9590 switch (instr->Mask(
9591 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9592 case LD1B_z_p_bz_d_x32_unscaled:
9593 VIXL_UNIMPLEMENTED();
9594 break;
9595 case LD1D_z_p_bz_d_x32_unscaled:
9596 VIXL_UNIMPLEMENTED();
9597 break;
9598 case LD1H_z_p_bz_d_x32_unscaled:
9599 VIXL_UNIMPLEMENTED();
9600 break;
9601 case LD1SB_z_p_bz_d_x32_unscaled:
9602 VIXL_UNIMPLEMENTED();
9603 break;
9604 case LD1SH_z_p_bz_d_x32_unscaled:
9605 VIXL_UNIMPLEMENTED();
9606 break;
9607 case LD1SW_z_p_bz_d_x32_unscaled:
9608 VIXL_UNIMPLEMENTED();
9609 break;
9610 case LD1W_z_p_bz_d_x32_unscaled:
9611 VIXL_UNIMPLEMENTED();
9612 break;
9613 case LDFF1B_z_p_bz_d_x32_unscaled:
9614 VIXL_UNIMPLEMENTED();
9615 break;
9616 case LDFF1D_z_p_bz_d_x32_unscaled:
9617 VIXL_UNIMPLEMENTED();
9618 break;
9619 case LDFF1H_z_p_bz_d_x32_unscaled:
9620 VIXL_UNIMPLEMENTED();
9621 break;
9622 case LDFF1SB_z_p_bz_d_x32_unscaled:
9623 VIXL_UNIMPLEMENTED();
9624 break;
9625 case LDFF1SH_z_p_bz_d_x32_unscaled:
9626 VIXL_UNIMPLEMENTED();
9627 break;
9628 case LDFF1SW_z_p_bz_d_x32_unscaled:
9629 VIXL_UNIMPLEMENTED();
9630 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009631 case LDFF1W_z_p_bz_d_x32_unscaled:
9632 VIXL_UNIMPLEMENTED();
9633 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009634 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009635 VIXL_UNIMPLEMENTED();
9636 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009637 }
9638}
9639
9640void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
9641 const Instruction* instr) {
9642 USE(instr);
9643 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
9644 case LD1B_z_p_ai_d:
9645 VIXL_UNIMPLEMENTED();
9646 break;
9647 case LD1D_z_p_ai_d:
9648 VIXL_UNIMPLEMENTED();
9649 break;
9650 case LD1H_z_p_ai_d:
9651 VIXL_UNIMPLEMENTED();
9652 break;
9653 case LD1SB_z_p_ai_d:
9654 VIXL_UNIMPLEMENTED();
9655 break;
9656 case LD1SH_z_p_ai_d:
9657 VIXL_UNIMPLEMENTED();
9658 break;
9659 case LD1SW_z_p_ai_d:
9660 VIXL_UNIMPLEMENTED();
9661 break;
9662 case LD1W_z_p_ai_d:
9663 VIXL_UNIMPLEMENTED();
9664 break;
9665 case LDFF1B_z_p_ai_d:
9666 VIXL_UNIMPLEMENTED();
9667 break;
9668 case LDFF1D_z_p_ai_d:
9669 VIXL_UNIMPLEMENTED();
9670 break;
9671 case LDFF1H_z_p_ai_d:
9672 VIXL_UNIMPLEMENTED();
9673 break;
9674 case LDFF1SB_z_p_ai_d:
9675 VIXL_UNIMPLEMENTED();
9676 break;
9677 case LDFF1SH_z_p_ai_d:
9678 VIXL_UNIMPLEMENTED();
9679 break;
9680 case LDFF1SW_z_p_ai_d:
9681 VIXL_UNIMPLEMENTED();
9682 break;
9683 case LDFF1W_z_p_ai_d:
9684 VIXL_UNIMPLEMENTED();
9685 break;
9686 default:
9687 VIXL_UNIMPLEMENTED();
9688 break;
9689 }
9690}
9691
9692void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
9693 const Instruction* instr) {
9694 USE(instr);
9695 switch (
9696 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009697 case PRFB_i_p_bz_d_64_scaled:
9698 VIXL_UNIMPLEMENTED();
9699 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009700 case PRFD_i_p_bz_d_64_scaled:
9701 VIXL_UNIMPLEMENTED();
9702 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009703 case PRFH_i_p_bz_d_64_scaled:
9704 VIXL_UNIMPLEMENTED();
9705 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009706 case PRFW_i_p_bz_d_64_scaled:
9707 VIXL_UNIMPLEMENTED();
9708 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009709 default:
9710 VIXL_UNIMPLEMENTED();
9711 break;
9712 }
9713}
9714
9715void Simulator::
9716 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
9717 const Instruction* instr) {
9718 USE(instr);
9719 switch (instr->Mask(
9720 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9721 case PRFB_i_p_bz_d_x32_scaled:
9722 VIXL_UNIMPLEMENTED();
9723 break;
9724 case PRFD_i_p_bz_d_x32_scaled:
9725 VIXL_UNIMPLEMENTED();
9726 break;
9727 case PRFH_i_p_bz_d_x32_scaled:
9728 VIXL_UNIMPLEMENTED();
9729 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009730 case PRFW_i_p_bz_d_x32_scaled:
9731 VIXL_UNIMPLEMENTED();
9732 break;
9733 default:
9734 VIXL_UNIMPLEMENTED();
9735 break;
9736 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009737}
9738
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009739void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
9740 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009741 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009742 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
9743 case PRFB_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009744 VIXL_UNIMPLEMENTED();
9745 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009746 case PRFD_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009747 VIXL_UNIMPLEMENTED();
9748 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009749 case PRFH_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009750 VIXL_UNIMPLEMENTED();
9751 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009752 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009753 VIXL_UNIMPLEMENTED();
9754 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009755 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009756 VIXL_UNIMPLEMENTED();
9757 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009758 }
9759}
9760
9761void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
9762 const Instruction* instr) {
9763 USE(instr);
9764 switch (instr->Mask(SVEContiguousFirstFaultLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009765 case LDFF1B_z_p_br_u16:
9766 VIXL_UNIMPLEMENTED();
9767 break;
9768 case LDFF1B_z_p_br_u32:
9769 VIXL_UNIMPLEMENTED();
9770 break;
9771 case LDFF1B_z_p_br_u64:
9772 VIXL_UNIMPLEMENTED();
9773 break;
9774 case LDFF1B_z_p_br_u8:
9775 VIXL_UNIMPLEMENTED();
9776 break;
9777 case LDFF1D_z_p_br_u64:
9778 VIXL_UNIMPLEMENTED();
9779 break;
9780 case LDFF1H_z_p_br_u16:
9781 VIXL_UNIMPLEMENTED();
9782 break;
9783 case LDFF1H_z_p_br_u32:
9784 VIXL_UNIMPLEMENTED();
9785 break;
9786 case LDFF1H_z_p_br_u64:
9787 VIXL_UNIMPLEMENTED();
9788 break;
9789 case LDFF1SB_z_p_br_s16:
9790 VIXL_UNIMPLEMENTED();
9791 break;
9792 case LDFF1SB_z_p_br_s32:
9793 VIXL_UNIMPLEMENTED();
9794 break;
9795 case LDFF1SB_z_p_br_s64:
9796 VIXL_UNIMPLEMENTED();
9797 break;
9798 case LDFF1SH_z_p_br_s32:
9799 VIXL_UNIMPLEMENTED();
9800 break;
9801 case LDFF1SH_z_p_br_s64:
9802 VIXL_UNIMPLEMENTED();
9803 break;
9804 case LDFF1SW_z_p_br_s64:
9805 VIXL_UNIMPLEMENTED();
9806 break;
9807 case LDFF1W_z_p_br_u32:
9808 VIXL_UNIMPLEMENTED();
9809 break;
9810 case LDFF1W_z_p_br_u64:
9811 VIXL_UNIMPLEMENTED();
9812 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009813 default:
9814 VIXL_UNIMPLEMENTED();
9815 break;
9816 }
9817}
9818
9819void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
9820 const Instruction* instr) {
9821 USE(instr);
9822 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009823 case LDNF1B_z_p_bi_u16:
9824 VIXL_UNIMPLEMENTED();
9825 break;
9826 case LDNF1B_z_p_bi_u32:
9827 VIXL_UNIMPLEMENTED();
9828 break;
9829 case LDNF1B_z_p_bi_u64:
9830 VIXL_UNIMPLEMENTED();
9831 break;
9832 case LDNF1B_z_p_bi_u8:
9833 VIXL_UNIMPLEMENTED();
9834 break;
9835 case LDNF1D_z_p_bi_u64:
9836 VIXL_UNIMPLEMENTED();
9837 break;
9838 case LDNF1H_z_p_bi_u16:
9839 VIXL_UNIMPLEMENTED();
9840 break;
9841 case LDNF1H_z_p_bi_u32:
9842 VIXL_UNIMPLEMENTED();
9843 break;
9844 case LDNF1H_z_p_bi_u64:
9845 VIXL_UNIMPLEMENTED();
9846 break;
9847 case LDNF1SB_z_p_bi_s16:
9848 VIXL_UNIMPLEMENTED();
9849 break;
9850 case LDNF1SB_z_p_bi_s32:
9851 VIXL_UNIMPLEMENTED();
9852 break;
9853 case LDNF1SB_z_p_bi_s64:
9854 VIXL_UNIMPLEMENTED();
9855 break;
9856 case LDNF1SH_z_p_bi_s32:
9857 VIXL_UNIMPLEMENTED();
9858 break;
9859 case LDNF1SH_z_p_bi_s64:
9860 VIXL_UNIMPLEMENTED();
9861 break;
9862 case LDNF1SW_z_p_bi_s64:
9863 VIXL_UNIMPLEMENTED();
9864 break;
9865 case LDNF1W_z_p_bi_u32:
9866 VIXL_UNIMPLEMENTED();
9867 break;
9868 case LDNF1W_z_p_bi_u64:
9869 VIXL_UNIMPLEMENTED();
9870 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009871 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009872 VIXL_UNIMPLEMENTED();
9873 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009874 }
9875}
9876
9877void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
9878 const Instruction* instr) {
9879 USE(instr);
9880 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
9881 case LDNT1B_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009882 VIXL_UNIMPLEMENTED();
9883 break;
9884 case LDNT1D_z_p_bi_contiguous:
9885 VIXL_UNIMPLEMENTED();
9886 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009887 case LDNT1H_z_p_bi_contiguous:
9888 VIXL_UNIMPLEMENTED();
9889 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009890 case LDNT1W_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009891 VIXL_UNIMPLEMENTED();
9892 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009893 default:
9894 VIXL_UNIMPLEMENTED();
9895 break;
9896 }
9897}
9898
9899void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
9900 const Instruction* instr) {
9901 USE(instr);
9902 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
9903 case LDNT1B_z_p_br_contiguous:
9904 VIXL_UNIMPLEMENTED();
9905 break;
9906 case LDNT1D_z_p_br_contiguous:
9907 VIXL_UNIMPLEMENTED();
9908 break;
9909 case LDNT1H_z_p_br_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009910 VIXL_UNIMPLEMENTED();
9911 break;
9912 case LDNT1W_z_p_br_contiguous:
9913 VIXL_UNIMPLEMENTED();
9914 break;
9915 default:
9916 VIXL_UNIMPLEMENTED();
9917 break;
9918 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009919}
9920
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009921void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
9922 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009923 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009924 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
9925 case LD1RQB_z_p_bi_u8:
9926 VIXL_UNIMPLEMENTED();
9927 break;
9928 case LD1RQD_z_p_bi_u64:
9929 VIXL_UNIMPLEMENTED();
9930 break;
9931 case LD1RQH_z_p_bi_u16:
9932 VIXL_UNIMPLEMENTED();
9933 break;
9934 case LD1RQW_z_p_bi_u32:
9935 VIXL_UNIMPLEMENTED();
9936 break;
9937 default:
9938 VIXL_UNIMPLEMENTED();
9939 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009940 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009941}
9942
9943void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
9944 const Instruction* instr) {
9945 USE(instr);
9946 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
9947 case LD1RQB_z_p_br_contiguous:
9948 VIXL_UNIMPLEMENTED();
9949 break;
9950 case LD1RQD_z_p_br_contiguous:
9951 VIXL_UNIMPLEMENTED();
9952 break;
9953 case LD1RQH_z_p_br_contiguous:
9954 VIXL_UNIMPLEMENTED();
9955 break;
9956 case LD1RQW_z_p_br_contiguous:
9957 VIXL_UNIMPLEMENTED();
9958 break;
9959 default:
9960 VIXL_UNIMPLEMENTED();
9961 break;
9962 }
9963}
9964
9965void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
9966 const Instruction* instr) {
9967 USE(instr);
9968 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
9969 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009970 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009971 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009972 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009973 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009974 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009975 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009976 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009977 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009978 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009979 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +00009980 case LD4W_z_p_bi_contiguous: {
9981 int vl = GetVectorLengthInBytes();
9982 int msz = instr->ExtractBits(24, 23);
9983 int reg_count = instr->ExtractBits(22, 21) + 1;
9984 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
9985 LogicSVEAddressVector addr(
9986 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
9987 addr.SetMsizeInBytesLog2(msz);
9988 addr.SetRegCount(reg_count);
9989 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
9990 ReadPRegister(instr->GetPgLow8()),
9991 instr->GetRt(),
9992 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009993 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +00009994 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009995 default:
9996 VIXL_UNIMPLEMENTED();
9997 break;
9998 }
9999}
10000
10001void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
10002 const Instruction* instr) {
10003 USE(instr);
10004 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
10005 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010006 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010007 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010008 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010009 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010010 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010011 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010012 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010013 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010014 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010015 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000010016 case LD4W_z_p_br_contiguous: {
10017 int msz = instr->ExtractBits(24, 23);
10018 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10019 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10020 LogicSVEAddressVector addr(
10021 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10022 addr.SetMsizeInBytesLog2(msz);
10023 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10024 SVEStructuredLoadHelper(vform,
10025 ReadPRegister(instr->GetPgLow8()),
10026 instr->GetRt(),
10027 addr,
10028 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010029 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000010030 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010031 default:
10032 VIXL_UNIMPLEMENTED();
10033 break;
10034 }
10035}
10036
10037void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
10038 const Instruction* instr) {
10039 USE(instr);
10040 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
10041 case ST1H_z_p_bz_s_x32_scaled:
10042 VIXL_UNIMPLEMENTED();
10043 break;
10044 case ST1W_z_p_bz_s_x32_scaled:
10045 VIXL_UNIMPLEMENTED();
10046 break;
10047 default:
10048 VIXL_UNIMPLEMENTED();
10049 break;
10050 }
10051}
10052
10053void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
10054 const Instruction* instr) {
10055 USE(instr);
10056 switch (
10057 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
10058 case ST1B_z_p_bz_s_x32_unscaled:
10059 VIXL_UNIMPLEMENTED();
10060 break;
10061 case ST1H_z_p_bz_s_x32_unscaled:
10062 VIXL_UNIMPLEMENTED();
10063 break;
10064 case ST1W_z_p_bz_s_x32_unscaled:
10065 VIXL_UNIMPLEMENTED();
10066 break;
10067 default:
10068 VIXL_UNIMPLEMENTED();
10069 break;
10070 }
10071}
10072
10073void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
10074 const Instruction* instr) {
10075 USE(instr);
10076 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
10077 case ST1B_z_p_ai_s:
10078 VIXL_UNIMPLEMENTED();
10079 break;
10080 case ST1H_z_p_ai_s:
10081 VIXL_UNIMPLEMENTED();
10082 break;
10083 case ST1W_z_p_ai_s:
10084 VIXL_UNIMPLEMENTED();
10085 break;
10086 default:
10087 VIXL_UNIMPLEMENTED();
10088 break;
10089 }
10090}
10091
10092void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
10093 const Instruction* instr) {
10094 USE(instr);
10095 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
10096 case ST1D_z_p_bz_d_64_scaled:
10097 VIXL_UNIMPLEMENTED();
10098 break;
10099 case ST1H_z_p_bz_d_64_scaled:
10100 VIXL_UNIMPLEMENTED();
10101 break;
10102 case ST1W_z_p_bz_d_64_scaled:
10103 VIXL_UNIMPLEMENTED();
10104 break;
10105 default:
10106 VIXL_UNIMPLEMENTED();
10107 break;
10108 }
10109}
10110
10111void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
10112 const Instruction* instr) {
10113 USE(instr);
10114 switch (
10115 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
10116 case ST1B_z_p_bz_d_64_unscaled:
10117 VIXL_UNIMPLEMENTED();
10118 break;
10119 case ST1D_z_p_bz_d_64_unscaled:
10120 VIXL_UNIMPLEMENTED();
10121 break;
10122 case ST1H_z_p_bz_d_64_unscaled:
10123 VIXL_UNIMPLEMENTED();
10124 break;
10125 case ST1W_z_p_bz_d_64_unscaled:
10126 VIXL_UNIMPLEMENTED();
10127 break;
10128 default:
10129 VIXL_UNIMPLEMENTED();
10130 break;
10131 }
10132}
10133
10134void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
10135 const Instruction* instr) {
10136 USE(instr);
10137 switch (instr->Mask(
10138 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
10139 case ST1D_z_p_bz_d_x32_scaled:
10140 VIXL_UNIMPLEMENTED();
10141 break;
10142 case ST1H_z_p_bz_d_x32_scaled:
10143 VIXL_UNIMPLEMENTED();
10144 break;
10145 case ST1W_z_p_bz_d_x32_scaled:
10146 VIXL_UNIMPLEMENTED();
10147 break;
10148 default:
10149 VIXL_UNIMPLEMENTED();
10150 break;
10151 }
10152}
10153
10154void Simulator::
10155 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
10156 const Instruction* instr) {
10157 USE(instr);
10158 switch (instr->Mask(
10159 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
10160 case ST1B_z_p_bz_d_x32_unscaled:
10161 VIXL_UNIMPLEMENTED();
10162 break;
10163 case ST1D_z_p_bz_d_x32_unscaled:
10164 VIXL_UNIMPLEMENTED();
10165 break;
10166 case ST1H_z_p_bz_d_x32_unscaled:
10167 VIXL_UNIMPLEMENTED();
10168 break;
10169 case ST1W_z_p_bz_d_x32_unscaled:
10170 VIXL_UNIMPLEMENTED();
10171 break;
10172 default:
10173 VIXL_UNIMPLEMENTED();
10174 break;
10175 }
10176}
10177
10178void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
10179 const Instruction* instr) {
10180 USE(instr);
10181 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
10182 case ST1B_z_p_ai_d:
10183 VIXL_UNIMPLEMENTED();
10184 break;
10185 case ST1D_z_p_ai_d:
10186 VIXL_UNIMPLEMENTED();
10187 break;
10188 case ST1H_z_p_ai_d:
10189 VIXL_UNIMPLEMENTED();
10190 break;
10191 case ST1W_z_p_ai_d:
10192 VIXL_UNIMPLEMENTED();
10193 break;
10194 default:
10195 VIXL_UNIMPLEMENTED();
10196 break;
10197 }
10198}
10199
10200void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
10201 const Instruction* instr) {
10202 USE(instr);
10203 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
10204 case STNT1B_z_p_bi_contiguous:
10205 VIXL_UNIMPLEMENTED();
10206 break;
10207 case STNT1D_z_p_bi_contiguous:
10208 VIXL_UNIMPLEMENTED();
10209 break;
10210 case STNT1H_z_p_bi_contiguous:
10211 VIXL_UNIMPLEMENTED();
10212 break;
10213 case STNT1W_z_p_bi_contiguous:
10214 VIXL_UNIMPLEMENTED();
10215 break;
10216 default:
10217 VIXL_UNIMPLEMENTED();
10218 break;
10219 }
10220}
10221
10222void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
10223 const Instruction* instr) {
10224 USE(instr);
10225 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
10226 case STNT1B_z_p_br_contiguous:
10227 VIXL_UNIMPLEMENTED();
10228 break;
10229 case STNT1D_z_p_br_contiguous:
10230 VIXL_UNIMPLEMENTED();
10231 break;
10232 case STNT1H_z_p_br_contiguous:
10233 VIXL_UNIMPLEMENTED();
10234 break;
10235 case STNT1W_z_p_br_contiguous:
10236 VIXL_UNIMPLEMENTED();
10237 break;
10238 default:
10239 VIXL_UNIMPLEMENTED();
10240 break;
10241 }
10242}
10243
10244void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
10245 const Instruction* instr) {
10246 USE(instr);
10247 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
10248 case ST1B_z_p_bi:
10249 case ST1D_z_p_bi:
10250 case ST1H_z_p_bi:
10251 case ST1W_z_p_bi: {
10252 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010253 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10254 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
10255 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10256 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10257 uint64_t offset =
10258 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010259 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010260 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010261 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010262 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10263 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010264 ReadPRegister(instr->GetPgLow8()),
10265 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010266 addr);
10267 break;
10268 }
10269 default:
10270 VIXL_UNIMPLEMENTED();
10271 break;
10272 }
10273}
10274
10275void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
10276 const Instruction* instr) {
10277 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
10278 case ST1B_z_p_br:
10279 case ST1D_z_p_br:
10280 case ST1H_z_p_br:
10281 case ST1W_z_p_br: {
10282 uint64_t offset = ReadXRegister(instr->GetRm());
10283 offset <<= instr->ExtractBits(24, 23);
10284 VectorFormat vform =
10285 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
10286 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010287 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
10288 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010289 ReadPRegister(instr->GetPgLow8()),
10290 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010291 addr);
10292 break;
10293 }
10294 default:
10295 VIXL_UNIMPLEMENTED();
10296 break;
10297 }
10298}
10299
10300void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
10301 const Instruction* instr) {
10302 VectorFormat vform = instr->GetSVEVectorFormat();
10303 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10304 SimVRegister z_result;
10305
10306 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
10307 case CPY_z_p_v:
10308 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
10309 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
10310 break;
10311 default:
10312 VIXL_UNIMPLEMENTED();
10313 break;
10314 }
10315}
10316
10317void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
10318 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010319 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
10320 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010321 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010322 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010323 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010324 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010325 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010326 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010327 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010328 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010329 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010330 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010331 case ST4W_z_p_bi_contiguous: {
10332 int vl = GetVectorLengthInBytes();
10333 int msz = instr->ExtractBits(24, 23);
10334 int reg_count = instr->ExtractBits(22, 21) + 1;
10335 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10336 LogicSVEAddressVector addr(
10337 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10338 addr.SetMsizeInBytesLog2(msz);
10339 addr.SetRegCount(reg_count);
10340 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10341 ReadPRegister(instr->GetPgLow8()),
10342 instr->GetRt(),
10343 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010344 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010345 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010346 default:
10347 VIXL_UNIMPLEMENTED();
10348 break;
10349 }
10350}
10351
10352void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
10353 const Instruction* instr) {
10354 USE(instr);
10355 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
10356 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010357 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010358 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010359 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010360 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010361 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010362 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010363 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010364 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010365 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010366 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010367 case ST4W_z_p_br_contiguous: {
10368 int msz = instr->ExtractBits(24, 23);
10369 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10370 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10371 LogicSVEAddressVector addr(
10372 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10373 addr.SetMsizeInBytesLog2(msz);
10374 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10375 SVEStructuredStoreHelper(vform,
10376 ReadPRegister(instr->GetPgLow8()),
10377 instr->GetRt(),
10378 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010379 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010380 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010381 default:
10382 VIXL_UNIMPLEMENTED();
10383 break;
10384 }
10385}
10386
10387void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
10388 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
10389 case STR_p_bi: {
10390 SimPRegister& pt = ReadPRegister(instr->GetPt());
10391 int pl = GetPredicateLengthInBytes();
10392 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10393 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10394 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
10395 for (int i = 0; i < pl; i++) {
10396 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
10397 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010398 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010399 break;
10400 }
10401 default:
10402 VIXL_UNIMPLEMENTED();
10403 break;
10404 }
10405}
10406
10407void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
10408 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
10409 case STR_z_bi: {
10410 SimVRegister& zt = ReadVRegister(instr->GetRt());
10411 int vl = GetVectorLengthInBytes();
10412 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10413 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10414 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
10415 for (int i = 0; i < vl; i++) {
10416 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
10417 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010418 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010419 break;
10420 }
10421 default:
10422 VIXL_UNIMPLEMENTED();
10423 break;
10424 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010425}
10426
10427void Simulator::VisitSVEMulIndex(const Instruction* instr) {
10428 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010429 switch (instr->Mask(SVEMulIndexMask)) {
10430 case SDOT_z_zzzi_d:
10431 VIXL_UNIMPLEMENTED();
10432 break;
10433 case SDOT_z_zzzi_s:
10434 VIXL_UNIMPLEMENTED();
10435 break;
10436 case UDOT_z_zzzi_d:
10437 VIXL_UNIMPLEMENTED();
10438 break;
10439 case UDOT_z_zzzi_s:
10440 VIXL_UNIMPLEMENTED();
10441 break;
10442 default:
10443 VIXL_UNIMPLEMENTED();
10444 break;
10445 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010446}
10447
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010448void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010449 SimPRegister& pd = ReadPRegister(instr->GetPd());
10450 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10451 SimPRegister& pn = ReadPRegister(instr->GetPn());
10452 SimPRegister result;
10453
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010454 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010455 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010456 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010457 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010458 break;
10459 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010460 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010461 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010462 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010463 default:
10464 VIXL_UNIMPLEMENTED();
10465 break;
10466 }
TatWai Chong5d872292020-01-02 15:39:51 -080010467
10468 if (instr->ExtractBit(4) == 1) {
10469 mov_merging(pd, pg, result);
10470 } else {
10471 mov_zeroing(pd, pg, result);
10472 }
10473
10474 // Set flag if needed.
10475 if (instr->ExtractBit(22) == 1) {
10476 PredTest(kFormatVnB, pg, pd);
10477 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010478}
10479
10480void Simulator::VisitSVEPropagateBreakToNextPartition(
10481 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010482 SimPRegister& pdm = ReadPRegister(instr->GetPd());
10483 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10484 SimPRegister& pn = ReadPRegister(instr->GetPn());
10485
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010486 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010487 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010488 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080010489 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010490 break;
10491 default:
10492 VIXL_UNIMPLEMENTED();
10493 break;
10494 }
TatWai Chong5d872292020-01-02 15:39:51 -080010495
10496 // Set flag if needed.
10497 if (instr->ExtractBit(22) == 1) {
10498 PredTest(kFormatVnB, pg, pdm);
10499 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010500}
10501
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010502void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010503 SimPRegister& pd = ReadPRegister(instr->GetPd());
10504 SimPRegister& pn = ReadPRegister(instr->GetPn());
10505
10506 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10507 SimVRegister zero;
10508 dup_immediate(kFormatVnB, zero, 0);
10509
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010510 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010511 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010512 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010513 break;
10514 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010515 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010516 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010517 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010518 VIXL_UNIMPLEMENTED();
10519 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010520 }
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010521 Simulator::ExtractFromSimVRegister(pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010522}
10523
10524void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010525 VectorFormat vform = instr->GetSVEVectorFormat();
10526 SimPRegister& pd = ReadPRegister(instr->GetPd());
10527 SimPRegister& pn = ReadPRegister(instr->GetPn());
10528 SimPRegister& pm = ReadPRegister(instr->GetPm());
10529
10530 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
10531 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
10532
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010533 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010534 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010535 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010536 break;
10537 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010538 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010539 break;
10540 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010541 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010542 break;
10543 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010544 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010545 break;
10546 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010547 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010548 break;
10549 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010550 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010551 break;
10552 default:
10553 VIXL_UNIMPLEMENTED();
10554 break;
10555 }
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010556 Simulator::ExtractFromSimVRegister(pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010557}
10558
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010559void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010560 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010561 case REV_p_p: {
10562 VectorFormat vform = instr->GetSVEVectorFormat();
10563 SimPRegister& pn = ReadPRegister(instr->GetPn());
10564 SimPRegister& pd = ReadPRegister(instr->GetPd());
10565 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10566 rev(vform, temp, temp);
10567 Simulator::ExtractFromSimVRegister(pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010568 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010569 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010570 default:
10571 VIXL_UNIMPLEMENTED();
10572 break;
10573 }
10574}
10575
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010576void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
10577 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010578 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
10579 case EXT_z_zi_des:
10580 VIXL_UNIMPLEMENTED();
10581 break;
10582 default:
10583 VIXL_UNIMPLEMENTED();
10584 break;
10585 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010586}
10587
10588void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
10589 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010590 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
10591 case TRN1_z_zz:
10592 VIXL_UNIMPLEMENTED();
10593 break;
10594 case TRN2_z_zz:
10595 VIXL_UNIMPLEMENTED();
10596 break;
10597 case UZP1_z_zz:
10598 VIXL_UNIMPLEMENTED();
10599 break;
10600 case UZP2_z_zz:
10601 VIXL_UNIMPLEMENTED();
10602 break;
10603 case ZIP1_z_zz:
10604 VIXL_UNIMPLEMENTED();
10605 break;
10606 case ZIP2_z_zz:
10607 VIXL_UNIMPLEMENTED();
10608 break;
10609 default:
10610 VIXL_UNIMPLEMENTED();
10611 break;
10612 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010613}
10614
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010615void Simulator::VisitSVEConditionallyBroadcastElementToVector(
10616 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010617 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010618 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010619 case CLASTA_z_p_zz:
10620 VIXL_UNIMPLEMENTED();
10621 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010622 case CLASTB_z_p_zz:
10623 VIXL_UNIMPLEMENTED();
10624 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010625 default:
10626 VIXL_UNIMPLEMENTED();
10627 break;
10628 }
10629}
10630
10631void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
10632 const Instruction* instr) {
10633 USE(instr);
10634 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
10635 case CLASTA_v_p_z:
10636 VIXL_UNIMPLEMENTED();
10637 break;
10638 case CLASTB_v_p_z:
10639 VIXL_UNIMPLEMENTED();
10640 break;
10641 default:
10642 VIXL_UNIMPLEMENTED();
10643 break;
10644 }
10645}
10646
10647void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
10648 const Instruction* instr) {
10649 USE(instr);
10650 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
10651 case CLASTA_r_p_z:
10652 VIXL_UNIMPLEMENTED();
10653 break;
10654 case CLASTB_r_p_z:
10655 VIXL_UNIMPLEMENTED();
10656 break;
10657 default:
10658 VIXL_UNIMPLEMENTED();
10659 break;
10660 }
10661}
10662
10663void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
10664 const Instruction* instr) {
10665 USE(instr);
10666 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
10667 case LASTA_v_p_z:
10668 VIXL_UNIMPLEMENTED();
10669 break;
10670 case LASTB_v_p_z:
10671 VIXL_UNIMPLEMENTED();
10672 break;
10673 default:
10674 VIXL_UNIMPLEMENTED();
10675 break;
10676 }
10677}
10678
10679void Simulator::VisitSVEExtractElementToGeneralRegister(
10680 const Instruction* instr) {
10681 USE(instr);
10682 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
10683 case LASTA_r_p_z:
10684 VIXL_UNIMPLEMENTED();
10685 break;
10686 case LASTB_r_p_z:
10687 VIXL_UNIMPLEMENTED();
10688 break;
10689 default:
10690 VIXL_UNIMPLEMENTED();
10691 break;
10692 }
10693}
10694
10695void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
10696 USE(instr);
10697 switch (instr->Mask(SVECompressActiveElementsMask)) {
10698 case COMPACT_z_p_z:
10699 VIXL_UNIMPLEMENTED();
10700 break;
10701 default:
10702 VIXL_UNIMPLEMENTED();
10703 break;
10704 }
10705}
10706
10707void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
10708 const Instruction* instr) {
10709 VectorFormat vform = instr->GetSVEVectorFormat();
10710 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10711 SimVRegister z_result;
10712
10713 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010714 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010010715 dup_immediate(vform,
10716 z_result,
10717 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10718 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010719 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010720 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010721 VIXL_UNIMPLEMENTED();
10722 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010723 }
10724}
10725
10726void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010727 VectorFormat vform = instr->GetSVEVectorFormat();
10728 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
10729 SimVRegister& zd = ReadVRegister(instr->GetRd());
10730
10731 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010732 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010733 case CPY_z_p_i: {
10734 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
10735 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
10736 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010737 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010738 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010739 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010740 VIXL_UNIMPLEMENTED();
10741 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010742 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010743
10744 if (instr->ExtractBit(14) != 0) {
10745 mov_merging(vform, zd, pg, result);
10746 } else {
10747 mov_zeroing(vform, zd, pg, result);
10748 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010749}
10750
10751void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000010752 SimVRegister& zd = ReadVRegister(instr->GetRd());
10753 SimVRegister& zn = ReadVRegister(instr->GetRn());
10754 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10755 SimVRegister result;
10756
10757 // In NEON, the chunk size in which elements are REVersed is in the
10758 // instruction mnemonic, and the element size attached to the register.
10759 // SVE reverses the semantics; the mapping to logic functions below is to
10760 // account for this.
10761 VectorFormat chunk_form = instr->GetSVEVectorFormat();
10762 VectorFormat element_form = kFormatUndefined;
10763
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010764 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010765 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010766 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010767 break;
10768 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010769 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
10770 (chunk_form == kFormatVnD));
10771 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010772 break;
10773 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010774 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
10775 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010776 break;
10777 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010778 VIXL_ASSERT(chunk_form == kFormatVnD);
10779 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010780 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010781 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010782 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010783 break;
10784 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000010785
10786 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
10787 VIXL_ASSERT(element_form != kFormatUndefined);
10788 switch (chunk_form) {
10789 case kFormatVnH:
10790 rev16(element_form, result, zn);
10791 break;
10792 case kFormatVnS:
10793 rev32(element_form, result, zn);
10794 break;
10795 case kFormatVnD:
10796 rev64(element_form, result, zn);
10797 break;
10798 default:
10799 VIXL_UNIMPLEMENTED();
10800 }
10801 }
10802
10803 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010804}
10805
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010806void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010807 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010808 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
10809 case SPLICE_z_p_zz_des:
10810 VIXL_UNIMPLEMENTED();
10811 break;
10812 default:
10813 VIXL_UNIMPLEMENTED();
10814 break;
10815 }
10816}
TatWai Chong4f28df72019-08-14 17:50:30 -070010817
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010818void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
10819 SimVRegister& zd = ReadVRegister(instr->GetRd());
10820 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
10821 case DUP_z_r:
10822 dup_immediate(instr->GetSVEVectorFormat(),
10823 zd,
10824 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10825 break;
10826 default:
10827 VIXL_UNIMPLEMENTED();
10828 break;
10829 }
10830}
10831
10832void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
10833 SimVRegister& zd = ReadVRegister(instr->GetRd());
10834 VectorFormat vform = instr->GetSVEVectorFormat();
10835 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
10836 case INSR_z_v:
10837 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
10838 break;
10839 default:
10840 VIXL_UNIMPLEMENTED();
10841 break;
10842 }
10843}
10844
10845void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
10846 SimVRegister& zd = ReadVRegister(instr->GetRd());
10847 VectorFormat vform = instr->GetSVEVectorFormat();
10848 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
10849 case INSR_z_r:
10850 insr(vform, zd, ReadXRegister(instr->GetRn()));
10851 break;
10852 default:
10853 VIXL_UNIMPLEMENTED();
10854 break;
10855 }
10856}
10857
10858void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
10859 SimVRegister& zd = ReadVRegister(instr->GetRd());
10860 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070010861 case DUP_z_zi: {
10862 std::pair<int, int> index_and_lane_size =
10863 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10864 int index = index_and_lane_size.first;
10865 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
10866 VectorFormat vform =
10867 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
10868 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
10869 // Out of bounds, set the destination register to zero.
10870 dup_immediate(kFormatVnD, zd, 0);
10871 } else {
10872 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
10873 }
10874 return;
10875 }
TatWai Chong4f28df72019-08-14 17:50:30 -070010876 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010877 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070010878 break;
10879 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010880}
TatWai Chong4f28df72019-08-14 17:50:30 -070010881
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010882void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
10883 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070010884 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010885 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010886 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010887 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010888 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010889 default:
10890 VIXL_UNIMPLEMENTED();
10891 break;
10892 }
10893}
10894
10895void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
10896 SimVRegister& zd = ReadVRegister(instr->GetRd());
10897 VectorFormat vform = instr->GetSVEVectorFormat();
10898 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010899 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010900 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010901 break;
10902 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010903 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010904 break;
10905 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010906 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010907 break;
10908 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010909 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
10910 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010911 default:
10912 VIXL_UNIMPLEMENTED();
10913 break;
10914 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010915}
10916
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010917void Simulator::VisitSVETableLookup(const Instruction* instr) {
10918 SimVRegister& zd = ReadVRegister(instr->GetRd());
10919 switch (instr->Mask(SVETableLookupMask)) {
10920 case TBL_z_zz_1:
10921 Table(instr->GetSVEVectorFormat(),
10922 zd,
10923 ReadVRegister(instr->GetRn()),
10924 ReadVRegister(instr->GetRm()));
10925 return;
10926 default:
10927 break;
10928 }
10929}
10930
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010931void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
10932 USE(instr);
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010933
10934 VectorFormat vform = instr->GetSVEVectorFormat();
10935 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10936 SimPRegister& pn = ReadPRegister(instr->GetPn());
10937
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010938 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010939 case CNTP_r_p_p: {
10940 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010941 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010942 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010943 default:
10944 VIXL_UNIMPLEMENTED();
10945 break;
10946 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010947}
10948
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010949void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
10950 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080010951 SimPRegister& pd = ReadPRegister(instr->GetPd());
10952 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10953 SimPRegister& pn = ReadPRegister(instr->GetPn());
10954 SimPRegister& pm = ReadPRegister(instr->GetPm());
10955 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070010956 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010957 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010958 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010959 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010960 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010961 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010962 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010963 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010964 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010965 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010966 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010967 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010968 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010969 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010970 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070010971 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080010972 result,
10973 pn,
10974 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010975 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080010976 case SEL_p_p_pp:
10977 sel(pd, pg, pn, pm);
10978 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010979 default:
10980 VIXL_UNIMPLEMENTED();
10981 break;
10982 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080010983
10984 mov_zeroing(pd, pg, result);
10985 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
10986 PredTest(kFormatVnB, pg, pd);
10987 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010988}
10989
Jacob Bramley0ce75842019-07-17 18:12:50 +010010990void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010991 USE(instr);
Jacob Bramley0ce75842019-07-17 18:12:50 +010010992 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
10993 LogicPRegister pdn = ReadPRegister(instr->GetPd());
10994 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010995 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010010996 pfirst(pdn, pg, pdn);
10997 // TODO: Is this broken when pg == pdn?
10998 PredTest(kFormatVnB, pg, pdn);
10999 break;
11000 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011001 VIXL_UNIMPLEMENTED();
11002 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011003 }
11004}
11005
11006void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
11007 USE(instr);
11008 // This group only contains PTRUE{S}, and there are no unallocated encodings.
11009 VIXL_STATIC_ASSERT(
11010 SVEPredicateInitializeMask ==
11011 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
11012 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
11013 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
11014
11015 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11016 VectorFormat vform = instr->GetSVEVectorFormat();
11017
11018 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
11019 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
11020}
11021
11022void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
11023 USE(instr);
11024 // This group only contains PNEXT, and there are no unallocated encodings.
11025 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
11026 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
11027
11028 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11029 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11030 VectorFormat vform = instr->GetSVEVectorFormat();
11031
11032 pnext(vform, pdn, pg, pdn);
11033 // TODO: Is this broken when pg == pdn?
11034 PredTest(vform, pg, pdn);
11035}
11036
11037void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
11038 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080011039 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11040 LogicPRegister pg(ReadPRegister(instr->GetPn()));
11041 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011042 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
11043 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011044 // Do nothing.
11045 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011046 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011047 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011048 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011049 default:
11050 VIXL_UNIMPLEMENTED();
11051 break;
11052 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080011053
11054 LogicPRegister ffr(ReadFFR());
11055 mov_zeroing(pd, pg, ffr);
11056
11057 if (flags == SetFlags) {
11058 PredTest(kFormatVnB, pg, pd);
11059 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010011060}
11061
11062void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
11063 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011064 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11065 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010011066 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011067 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080011068 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011069 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011070 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011071 VIXL_UNIMPLEMENTED();
11072 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011073 }
11074}
11075
11076void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
11077 USE(instr);
11078 switch (instr->Mask(SVEPredicateTestMask)) {
11079 case PTEST_p_p:
11080 PredTest(kFormatVnB,
11081 ReadPRegister(instr->ExtractBits(13, 10)),
11082 ReadPRegister(instr->GetPn()));
11083 break;
11084 default:
11085 VIXL_UNIMPLEMENTED();
11086 break;
11087 }
11088}
11089
11090void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
11091 USE(instr);
11092 switch (instr->Mask(SVEPredicateZeroMask)) {
11093 case PFALSE_p:
11094 pfalse(ReadPRegister(instr->GetPd()));
11095 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011096 default:
11097 VIXL_UNIMPLEMENTED();
11098 break;
11099 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011100}
11101
11102void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080011103 SimPRegister& pd = ReadPRegister(instr->GetPd());
11104 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11105 SimPRegister& pn = ReadPRegister(instr->GetPn());
11106 SimPRegister& pm = ReadPRegister(instr->GetPm());
11107
11108 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011109 switch (instr->Mask(SVEPropagateBreakMask)) {
11110 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011111 set_flags = true;
11112 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011113 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011114 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011115 break;
11116 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011117 set_flags = true;
11118 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011119 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011120 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011121 break;
11122 default:
11123 VIXL_UNIMPLEMENTED();
11124 break;
11125 }
TatWai Chong38303d92019-12-02 15:49:29 -080011126
11127 if (set_flags) {
11128 PredTest(kFormatVnB, pg, pd);
11129 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011130}
11131
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011132void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
11133 uint64_t length = 0;
11134 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
11135 case ADDPL_r_ri:
11136 length = GetPredicateLengthInBytes();
11137 break;
11138 case ADDVL_r_ri:
11139 length = GetVectorLengthInBytes();
11140 break;
11141 default:
11142 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011143 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011144 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011145 WriteXRegister(instr->GetRd(),
11146 base + (length * instr->GetImmSVEVLScale()),
11147 LogRegWrites,
11148 Reg31IsStackPointer);
11149}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011150
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011151void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
11152 int64_t scale = instr->GetImmSVEVLScale();
11153
11154 switch (instr->Mask(SVEStackFrameSizeMask)) {
11155 case RDVL_r_i:
11156 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
11157 break;
11158 default:
11159 VIXL_UNIMPLEMENTED();
11160 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011161}
11162
11163void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
11164 USE(instr);
TatWai Chong6205eb42019-09-24 10:07:20 +010011165
11166 // The only instruction in this group is `sel`, and there are no unused
11167 // encodings.
11168 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
11169
11170 VectorFormat vform = instr->GetSVEVectorFormat();
11171 SimVRegister& zd = ReadVRegister(instr->GetRd());
11172 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11173 SimVRegister& zn = ReadVRegister(instr->GetRn());
11174 SimVRegister& zm = ReadVRegister(instr->GetRm());
11175
11176 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011177}
11178
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011179void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011180 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011181 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011182 case SETFFR_f: {
11183 LogicPRegister ffr(ReadFFR());
11184 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011185 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011186 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011187 default:
11188 VIXL_UNIMPLEMENTED();
11189 break;
11190 }
11191}
11192
11193void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
11194 USE(instr);
11195 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011196 case WRFFR_f_p: {
11197 SimPRegister pn(ReadPRegister(instr->GetPn()));
11198 bool last_active = true;
11199 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
11200 bool active = pn.GetBit(i);
11201 if (active && !last_active) {
11202 // `pn` is non-monotonic. This is UNPREDICTABLE.
11203 VIXL_ABORT();
11204 }
11205 last_active = active;
11206 }
11207 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011208 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011209 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011210 default:
11211 VIXL_UNIMPLEMENTED();
11212 break;
11213 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011214}
Alexandre Ramesd3832962016-07-04 15:03:43 +010011215
TatWai Chong6205eb42019-09-24 10:07:20 +010011216void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
11217 USE(instr);
11218 bool is_signed;
11219 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
11220 case LD1B_z_p_bi_u8:
11221 case LD1B_z_p_bi_u16:
11222 case LD1B_z_p_bi_u32:
11223 case LD1B_z_p_bi_u64:
11224 case LD1H_z_p_bi_u16:
11225 case LD1H_z_p_bi_u32:
11226 case LD1H_z_p_bi_u64:
11227 case LD1W_z_p_bi_u32:
11228 case LD1W_z_p_bi_u64:
11229 case LD1D_z_p_bi_u64:
11230 is_signed = false;
11231 break;
11232 case LD1SB_z_p_bi_s16:
11233 case LD1SB_z_p_bi_s32:
11234 case LD1SB_z_p_bi_s64:
11235 case LD1SH_z_p_bi_s32:
11236 case LD1SH_z_p_bi_s64:
11237 case LD1SW_z_p_bi_s64:
11238 is_signed = true;
11239 break;
11240 default:
11241 // This encoding group is complete, so no other values should be possible.
11242 VIXL_UNREACHABLE();
11243 is_signed = false;
11244 break;
11245 }
11246
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011247 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010011248 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11249 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011250 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
11251 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
11252 uint64_t offset =
11253 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011254 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011255 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011256 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11257 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011258 ReadPRegister(instr->GetPgLow8()),
11259 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011260 addr,
11261 is_signed);
11262}
11263
11264void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
11265 const Instruction* instr) {
11266 bool is_signed;
11267 USE(instr);
11268 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
11269 case LD1B_z_p_br_u8:
11270 case LD1B_z_p_br_u16:
11271 case LD1B_z_p_br_u32:
11272 case LD1B_z_p_br_u64:
11273 case LD1H_z_p_br_u16:
11274 case LD1H_z_p_br_u32:
11275 case LD1H_z_p_br_u64:
11276 case LD1W_z_p_br_u32:
11277 case LD1W_z_p_br_u64:
11278 case LD1D_z_p_br_u64:
11279 is_signed = false;
11280 break;
11281 case LD1SB_z_p_br_s16:
11282 case LD1SB_z_p_br_s32:
11283 case LD1SB_z_p_br_s64:
11284 case LD1SH_z_p_br_s32:
11285 case LD1SH_z_p_br_s64:
11286 case LD1SW_z_p_br_s64:
11287 is_signed = true;
11288 break;
11289 default:
11290 // This encoding group is complete, so no other values should be possible.
11291 VIXL_UNREACHABLE();
11292 is_signed = false;
11293 break;
11294 }
11295
11296 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11297 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11298 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11299 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11300 uint64_t offset = ReadXRegister(instr->GetRm());
11301 offset <<= msize_in_bytes_log2;
11302 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011303 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11304 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011305 ReadPRegister(instr->GetPgLow8()),
11306 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011307 addr,
11308 is_signed);
11309}
11310
Alexandre Ramesd3832962016-07-04 15:03:43 +010011311void Simulator::DoUnreachable(const Instruction* instr) {
11312 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11313 (instr->GetImmException() == kUnreachableOpcode));
11314
11315 fprintf(stream_,
11316 "Hit UNREACHABLE marker at pc=%p.\n",
11317 reinterpret_cast<const void*>(instr));
11318 abort();
11319}
11320
11321
11322void Simulator::DoTrace(const Instruction* instr) {
11323 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11324 (instr->GetImmException() == kTraceOpcode));
11325
11326 // Read the arguments encoded inline in the instruction stream.
11327 uint32_t parameters;
11328 uint32_t command;
11329
11330 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11331 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11332 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
11333
11334 switch (command) {
11335 case TRACE_ENABLE:
11336 SetTraceParameters(GetTraceParameters() | parameters);
11337 break;
11338 case TRACE_DISABLE:
11339 SetTraceParameters(GetTraceParameters() & ~parameters);
11340 break;
11341 default:
11342 VIXL_UNREACHABLE();
11343 }
11344
11345 WritePc(instr->GetInstructionAtOffset(kTraceLength));
11346}
11347
11348
11349void Simulator::DoLog(const Instruction* instr) {
11350 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11351 (instr->GetImmException() == kLogOpcode));
11352
11353 // Read the arguments encoded inline in the instruction stream.
11354 uint32_t parameters;
11355
11356 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11357 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11358
11359 // We don't support a one-shot LOG_DISASM.
11360 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
11361 // Print the requested information.
11362 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
11363 if (parameters & LOG_REGS) PrintRegisters();
11364 if (parameters & LOG_VREGS) PrintVRegisters();
11365
11366 WritePc(instr->GetInstructionAtOffset(kLogLength));
11367}
11368
11369
11370void Simulator::DoPrintf(const Instruction* instr) {
11371 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11372 (instr->GetImmException() == kPrintfOpcode));
11373
11374 // Read the arguments encoded inline in the instruction stream.
11375 uint32_t arg_count;
11376 uint32_t arg_pattern_list;
11377 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11378 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
11379 memcpy(&arg_pattern_list,
11380 instr + kPrintfArgPatternListOffset,
11381 sizeof(arg_pattern_list));
11382
11383 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
11384 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
11385
11386 // We need to call the host printf function with a set of arguments defined by
11387 // arg_pattern_list. Because we don't know the types and sizes of the
11388 // arguments, this is very difficult to do in a robust and portable way. To
11389 // work around the problem, we pick apart the format string, and print one
11390 // format placeholder at a time.
11391
11392 // Allocate space for the format string. We take a copy, so we can modify it.
11393 // Leave enough space for one extra character per expected argument (plus the
11394 // '\0' termination).
11395 const char* format_base = ReadRegister<const char*>(0);
11396 VIXL_ASSERT(format_base != NULL);
11397 size_t length = strlen(format_base) + 1;
11398 char* const format = new char[length + arg_count];
11399
11400 // A list of chunks, each with exactly one format placeholder.
11401 const char* chunks[kPrintfMaxArgCount];
11402
11403 // Copy the format string and search for format placeholders.
11404 uint32_t placeholder_count = 0;
11405 char* format_scratch = format;
11406 for (size_t i = 0; i < length; i++) {
11407 if (format_base[i] != '%') {
11408 *format_scratch++ = format_base[i];
11409 } else {
11410 if (format_base[i + 1] == '%') {
11411 // Ignore explicit "%%" sequences.
11412 *format_scratch++ = format_base[i];
11413 i++;
11414 // Chunks after the first are passed as format strings to printf, so we
11415 // need to escape '%' characters in those chunks.
11416 if (placeholder_count > 0) *format_scratch++ = format_base[i];
11417 } else {
11418 VIXL_CHECK(placeholder_count < arg_count);
11419 // Insert '\0' before placeholders, and store their locations.
11420 *format_scratch++ = '\0';
11421 chunks[placeholder_count++] = format_scratch;
11422 *format_scratch++ = format_base[i];
11423 }
11424 }
11425 }
11426 VIXL_CHECK(placeholder_count == arg_count);
11427
11428 // Finally, call printf with each chunk, passing the appropriate register
11429 // argument. Normally, printf returns the number of bytes transmitted, so we
11430 // can emulate a single printf call by adding the result from each chunk. If
11431 // any call returns a negative (error) value, though, just return that value.
11432
11433 printf("%s", clr_printf);
11434
11435 // Because '\0' is inserted before each placeholder, the first string in
11436 // 'format' contains no format placeholders and should be printed literally.
11437 int result = printf("%s", format);
11438 int pcs_r = 1; // Start at x1. x0 holds the format string.
11439 int pcs_f = 0; // Start at d0.
11440 if (result >= 0) {
11441 for (uint32_t i = 0; i < placeholder_count; i++) {
11442 int part_result = -1;
11443
11444 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
11445 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
11446 switch (arg_pattern) {
11447 case kPrintfArgW:
11448 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
11449 break;
11450 case kPrintfArgX:
11451 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
11452 break;
11453 case kPrintfArgD:
11454 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
11455 break;
11456 default:
11457 VIXL_UNREACHABLE();
11458 }
11459
11460 if (part_result < 0) {
11461 // Handle error values.
11462 result = part_result;
11463 break;
11464 }
11465
11466 result += part_result;
11467 }
11468 }
11469
11470 printf("%s", clr_normal);
11471
11472 // Printf returns its result in x0 (just like the C library's printf).
11473 WriteXRegister(0, result);
11474
11475 // The printf parameters are inlined in the code, so skip them.
11476 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
11477
11478 // Set LR as if we'd just called a native printf function.
11479 WriteLr(ReadPc());
11480
11481 delete[] format;
11482}
11483
Alexandre Rames064e02d2016-07-12 11:53:13 +010011484
Alexandre Ramesca73ba02016-07-28 09:16:03 +010011485#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010011486void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011487 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011488 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
11489 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011490 uintptr_t call_wrapper_address =
11491 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
11492 uintptr_t function_address =
11493 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080011494 RuntimeCallType call_type = static_cast<RuntimeCallType>(
11495 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011496 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010011497 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011498
11499 if (call_type == kCallRuntime) {
11500 WriteRegister(kLinkRegCode,
11501 instr->GetInstructionAtOffset(kRuntimeCallLength));
11502 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011503 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011504 // Read the return address from `lr` and write it into `pc`.
11505 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011506}
11507#else
11508void Simulator::DoRuntimeCall(const Instruction* instr) {
11509 USE(instr);
11510 VIXL_UNREACHABLE();
11511}
11512#endif
11513
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011514
11515void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
11516 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
11517
11518 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011519 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011520 std::numeric_limits<ElementType>::max());
11521
11522 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
11523
11524 size_t element_size = sizeof(ElementType);
11525 size_t offset = kConfigureCPUFeaturesListOffset;
11526
11527 // Read the kNone-terminated list of features.
11528 CPUFeatures parameters;
11529 while (true) {
11530 ElementType feature = Memory::Read<ElementType>(instr + offset);
11531 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011532 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011533 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
11534 }
11535
11536 switch (instr->GetImmException()) {
11537 case kSetCPUFeaturesOpcode:
11538 SetCPUFeatures(parameters);
11539 break;
11540 case kEnableCPUFeaturesOpcode:
11541 GetCPUFeatures()->Combine(parameters);
11542 break;
11543 case kDisableCPUFeaturesOpcode:
11544 GetCPUFeatures()->Remove(parameters);
11545 break;
11546 default:
11547 VIXL_UNREACHABLE();
11548 break;
11549 }
11550
11551 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
11552}
11553
11554
11555void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
11556 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11557 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
11558 USE(instr);
11559
11560 saved_cpu_features_.push_back(*GetCPUFeatures());
11561}
11562
11563
11564void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
11565 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11566 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
11567 USE(instr);
11568
11569 SetCPUFeatures(saved_cpu_features_.back());
11570 saved_cpu_features_.pop_back();
11571}
11572
11573
Alexandre Ramesd3832962016-07-04 15:03:43 +010011574} // namespace aarch64
11575} // namespace vixl
11576
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010011577#endif // VIXL_INCLUDE_SIMULATOR_AARCH64