blob: 781a848c922e67a4ed0c351161a4937ec5503eeb [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) {
Martyn Capewell50e9f552020-01-07 17:45:03 +00007969 VectorFormat vform = kFormatUndefined;
7970 unsigned zm_code = instr->GetRm() & 0xf;
7971 unsigned index = instr->ExtractBits(20, 19);
7972
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007973 switch (instr->Mask(SVEFPMulIndexMask)) {
7974 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +00007975 vform = kFormatVnD;
7976 index >>= 1; // Only bit 20 is the index for D lanes.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007977 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +00007978 case FMUL_z_zzi_h_i3h:
7979 index += 4; // Bit 22 (i3h) is the top bit of index.
7980 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007981 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +00007982 vform = kFormatVnH;
7983 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007984 break;
7985 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +00007986 vform = kFormatVnS;
7987 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007988 break;
7989 default:
7990 VIXL_UNIMPLEMENTED();
7991 break;
7992 }
Martyn Capewell50e9f552020-01-07 17:45:03 +00007993
7994 SimVRegister& zd = ReadVRegister(instr->GetRd());
7995 SimVRegister& zn = ReadVRegister(instr->GetRn());
7996 SimVRegister temp;
7997
7998 dup_element(vform, temp, ReadVRegister(zm_code), index);
7999 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008000}
8001
8002void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
8003 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008004 switch (instr->Mask(SVEFPMulAddMask)) {
8005 case FMAD_z_p_zzz:
8006 VIXL_UNIMPLEMENTED();
8007 break;
8008 case FMLA_z_p_zzz:
8009 VIXL_UNIMPLEMENTED();
8010 break;
8011 case FMLS_z_p_zzz:
8012 VIXL_UNIMPLEMENTED();
8013 break;
8014 case FMSB_z_p_zzz:
8015 VIXL_UNIMPLEMENTED();
8016 break;
8017 case FNMAD_z_p_zzz:
8018 VIXL_UNIMPLEMENTED();
8019 break;
8020 case FNMLA_z_p_zzz:
8021 VIXL_UNIMPLEMENTED();
8022 break;
8023 case FNMLS_z_p_zzz:
8024 VIXL_UNIMPLEMENTED();
8025 break;
8026 case FNMSB_z_p_zzz:
8027 VIXL_UNIMPLEMENTED();
8028 break;
8029 default:
8030 VIXL_UNIMPLEMENTED();
8031 break;
8032 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008033}
8034
8035void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
8036 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008037 switch (instr->Mask(SVEFPMulAddIndexMask)) {
8038 case FMLA_z_zzzi_d:
8039 VIXL_UNIMPLEMENTED();
8040 break;
8041 case FMLA_z_zzzi_h:
8042 VIXL_UNIMPLEMENTED();
8043 break;
8044 case FMLA_z_zzzi_s:
8045 VIXL_UNIMPLEMENTED();
8046 break;
8047 case FMLS_z_zzzi_d:
8048 VIXL_UNIMPLEMENTED();
8049 break;
8050 case FMLS_z_zzzi_h:
8051 VIXL_UNIMPLEMENTED();
8052 break;
8053 case FMLS_z_zzzi_s:
8054 VIXL_UNIMPLEMENTED();
8055 break;
8056 default:
8057 VIXL_UNIMPLEMENTED();
8058 break;
8059 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008060}
8061
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008062void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -08008063 SimVRegister& zd = ReadVRegister(instr->GetRd());
8064 SimVRegister& zn = ReadVRegister(instr->GetRn());
8065 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8066 int dst_data_size;
8067 int src_data_size;
8068
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008069 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008070 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008071 case FCVTZU_z_p_z_d2w:
8072 dst_data_size = kSRegSize;
8073 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008074 break;
8075 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008076 case FCVTZU_z_p_z_d2x:
8077 dst_data_size = kDRegSize;
8078 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008079 break;
8080 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008081 case FCVTZU_z_p_z_fp162h:
8082 dst_data_size = kHRegSize;
8083 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008084 break;
8085 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008086 case FCVTZU_z_p_z_fp162w:
8087 dst_data_size = kSRegSize;
8088 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008089 break;
8090 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008091 case FCVTZU_z_p_z_fp162x:
8092 dst_data_size = kDRegSize;
8093 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008094 break;
8095 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008096 case FCVTZU_z_p_z_s2w:
8097 dst_data_size = kSRegSize;
8098 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008099 break;
8100 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008101 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008102 dst_data_size = kDRegSize;
8103 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008104 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008105 default:
8106 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -08008107 dst_data_size = 0;
8108 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008109 break;
8110 }
TatWai Chongdb7437c2020-01-09 17:44:10 -08008111
8112 VectorFormat vform =
8113 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8114 USE(vform);
8115
8116 if (instr->ExtractBit(16) == 0) {
8117 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8118 } else {
8119 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8120 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008121}
8122
8123void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
8124 USE(instr);
8125 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008126 case FCVT_z_p_z_d2h:
8127 VIXL_UNIMPLEMENTED();
8128 break;
8129 case FCVT_z_p_z_d2s:
8130 VIXL_UNIMPLEMENTED();
8131 break;
8132 case FCVT_z_p_z_h2d:
8133 VIXL_UNIMPLEMENTED();
8134 break;
8135 case FCVT_z_p_z_h2s:
8136 VIXL_UNIMPLEMENTED();
8137 break;
8138 case FCVT_z_p_z_s2d:
8139 VIXL_UNIMPLEMENTED();
8140 break;
8141 case FCVT_z_p_z_s2h:
8142 VIXL_UNIMPLEMENTED();
8143 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008144 default:
8145 VIXL_UNIMPLEMENTED();
8146 break;
8147 }
8148}
8149
8150void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
8151 USE(instr);
8152 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008153 case FRECPX_z_p_z:
8154 VIXL_UNIMPLEMENTED();
8155 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008156 case FSQRT_z_p_z:
8157 VIXL_UNIMPLEMENTED();
8158 break;
8159 default:
8160 VIXL_UNIMPLEMENTED();
8161 break;
8162 }
8163}
8164
8165void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
8166 USE(instr);
8167 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008168 case FRINTA_z_p_z:
8169 VIXL_UNIMPLEMENTED();
8170 break;
8171 case FRINTI_z_p_z:
8172 VIXL_UNIMPLEMENTED();
8173 break;
8174 case FRINTM_z_p_z:
8175 VIXL_UNIMPLEMENTED();
8176 break;
8177 case FRINTN_z_p_z:
8178 VIXL_UNIMPLEMENTED();
8179 break;
8180 case FRINTP_z_p_z:
8181 VIXL_UNIMPLEMENTED();
8182 break;
8183 case FRINTX_z_p_z:
8184 VIXL_UNIMPLEMENTED();
8185 break;
8186 case FRINTZ_z_p_z:
8187 VIXL_UNIMPLEMENTED();
8188 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008189 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008190 VIXL_UNIMPLEMENTED();
8191 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008192 }
8193}
8194
8195void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
8196 USE(instr);
8197 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008198 case SCVTF_z_p_z_h2fp16:
8199 VIXL_UNIMPLEMENTED();
8200 break;
8201 case SCVTF_z_p_z_w2d:
8202 VIXL_UNIMPLEMENTED();
8203 break;
8204 case SCVTF_z_p_z_w2fp16:
8205 VIXL_UNIMPLEMENTED();
8206 break;
8207 case SCVTF_z_p_z_w2s:
8208 VIXL_UNIMPLEMENTED();
8209 break;
8210 case SCVTF_z_p_z_x2d:
8211 VIXL_UNIMPLEMENTED();
8212 break;
8213 case SCVTF_z_p_z_x2fp16:
8214 VIXL_UNIMPLEMENTED();
8215 break;
8216 case SCVTF_z_p_z_x2s:
8217 VIXL_UNIMPLEMENTED();
8218 break;
8219 case UCVTF_z_p_z_h2fp16:
8220 VIXL_UNIMPLEMENTED();
8221 break;
8222 case UCVTF_z_p_z_w2d:
8223 VIXL_UNIMPLEMENTED();
8224 break;
8225 case UCVTF_z_p_z_w2fp16:
8226 VIXL_UNIMPLEMENTED();
8227 break;
8228 case UCVTF_z_p_z_w2s:
8229 VIXL_UNIMPLEMENTED();
8230 break;
8231 case UCVTF_z_p_z_x2d:
8232 VIXL_UNIMPLEMENTED();
8233 break;
8234 case UCVTF_z_p_z_x2fp16:
8235 VIXL_UNIMPLEMENTED();
8236 break;
8237 case UCVTF_z_p_z_x2s:
8238 VIXL_UNIMPLEMENTED();
8239 break;
8240 default:
8241 VIXL_UNIMPLEMENTED();
8242 break;
8243 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008244}
8245
8246void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
8247 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008248 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8249 case FRECPE_z_z:
8250 VIXL_UNIMPLEMENTED();
8251 break;
8252 case FRSQRTE_z_z:
8253 VIXL_UNIMPLEMENTED();
8254 break;
8255 default:
8256 VIXL_UNIMPLEMENTED();
8257 break;
8258 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008259}
8260
8261void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
8262 USE(instr);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008263
8264 VectorFormat vform = instr->GetSVEVectorFormat();
8265 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
8266
8267 int count = CountActiveLanes(vform, pg);
8268
8269 if (instr->ExtractBit(11) == 0) {
8270 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8271 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8272 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008273 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008274 break;
8275 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008276 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008277 break;
8278 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008279 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008280 break;
8281 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008282 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008283 break;
8284 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008285 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008286 break;
8287 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008288 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008289 break;
8290 default:
8291 VIXL_UNIMPLEMENTED();
8292 break;
8293 }
8294 } else {
8295 bool is_saturating = (instr->ExtractBit(18) == 0);
8296 bool decrement =
8297 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
8298 bool is_signed = (instr->ExtractBit(16) == 0);
8299 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
8300 unsigned width = sf ? kXRegSize : kWRegSize;
8301
8302 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8303 case DECP_r_p_r:
8304 case INCP_r_p_r:
8305 case SQDECP_r_p_r_sx:
8306 case SQDECP_r_p_r_x:
8307 case SQINCP_r_p_r_sx:
8308 case SQINCP_r_p_r_x:
8309 case UQDECP_r_p_r_uw:
8310 case UQDECP_r_p_r_x:
8311 case UQINCP_r_p_r_uw:
8312 case UQINCP_r_p_r_x:
8313 WriteXRegister(instr->GetRd(),
8314 IncDecN(ReadXRegister(instr->GetRd()),
8315 decrement ? -count : count,
8316 width,
8317 is_saturating,
8318 is_signed));
8319 break;
8320 default:
8321 VIXL_UNIMPLEMENTED();
8322 break;
8323 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008324 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008325}
8326
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008327uint64_t Simulator::IncDecN(uint64_t acc,
8328 int64_t delta,
8329 unsigned n,
8330 bool is_saturating,
8331 bool is_signed) {
8332 VIXL_ASSERT(n <= 64);
8333 VIXL_ASSERT(IsIntN(n, delta));
8334
8335 uint64_t sign_mask = UINT64_C(1) << (n - 1);
8336 uint64_t mask = GetUintMask(n);
8337
8338 acc &= mask; // Ignore initial accumulator high bits.
8339 uint64_t result = (acc + delta) & mask;
8340
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008341 bool result_negative = ((result & sign_mask) != 0);
8342
8343 if (is_saturating) {
8344 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00008345 bool acc_negative = ((acc & sign_mask) != 0);
8346 bool delta_negative = delta < 0;
8347
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008348 // If the signs of the operands are the same, but different from the
8349 // result, there was an overflow.
8350 if ((acc_negative == delta_negative) &&
8351 (acc_negative != result_negative)) {
8352 if (result_negative) {
8353 // Saturate to [..., INT<n>_MAX].
8354 result_negative = false;
8355 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
8356 } else {
8357 // Saturate to [INT<n>_MIN, ...].
8358 result_negative = true;
8359 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
8360 }
8361 }
8362 } else {
8363 if ((delta < 0) && (result > acc)) {
8364 // Saturate to [0, ...].
8365 result = 0;
8366 } else if ((delta > 0) && (result < acc)) {
8367 // Saturate to [..., UINT<n>_MAX].
8368 result = mask;
8369 }
8370 }
8371 }
8372
8373 // Sign-extend if necessary.
8374 if (result_negative && is_signed) result |= ~mask;
8375
8376 return result;
8377}
8378
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008379void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
8380 USE(instr);
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008381 VectorFormat vform = instr->GetSVEVectorFormat();
8382 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008383 switch (instr->Mask(SVEIndexGenerationMask)) {
8384 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008385 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008386 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008387 case INDEX_z_rr: {
8388 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
8389 : instr->ExtractSignedBits(9, 5);
8390 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
8391 : instr->ExtractSignedBits(20, 16);
8392 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008393 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008394 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008395 default:
8396 VIXL_UNIMPLEMENTED();
8397 break;
8398 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008399}
8400
8401void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -07008402 VectorFormat vform = instr->GetSVEVectorFormat();
8403 SimVRegister& zd = ReadVRegister(instr->GetRd());
8404 SimVRegister& zn = ReadVRegister(instr->GetRn());
8405 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008406 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8407 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008408 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008409 break;
8410 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008411 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008412 break;
8413 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008414 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008415 break;
8416 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008417 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008418 break;
8419 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008420 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008421 break;
8422 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008423 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008424 break;
8425 default:
8426 VIXL_UNIMPLEMENTED();
8427 break;
8428 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008429}
8430
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008431void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008432 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -07008433 VectorFormat vform = instr->GetSVEVectorFormat();
8434 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8435 SimVRegister& zm = ReadVRegister(instr->GetRn());
8436 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8437 SimVRegister result;
8438
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008439 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008440 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008441 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008442 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008443 case SUBR_z_p_zz:
8444 sub(vform, result, zm, zdn);
8445 break;
8446 case SUB_z_p_zz:
8447 sub(vform, result, zdn, zm);
8448 break;
8449 default:
8450 VIXL_UNIMPLEMENTED();
8451 break;
8452 }
8453 mov_merging(vform, zdn, pg, result);
8454}
8455
8456void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
8457 VectorFormat vform = instr->GetSVEVectorFormat();
8458 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8459 SimVRegister& zm = ReadVRegister(instr->GetRn());
8460 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8461 SimVRegister result;
8462
8463 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008464 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008465 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008466 break;
8467 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008468 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008469 break;
8470 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008471 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008472 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008473 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008474 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008475 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008476 default:
8477 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008478 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008479 }
8480 mov_merging(vform, zdn, pg, result);
8481}
8482
8483void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
8484 VectorFormat vform = instr->GetSVEVectorFormat();
8485 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8486 SimVRegister& zm = ReadVRegister(instr->GetRn());
8487 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8488 SimVRegister result;
8489
8490 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
8491 case MUL_z_p_zz:
8492 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008493 break;
8494 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008495 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008496 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008497 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008498 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008499 break;
8500 default:
8501 VIXL_UNIMPLEMENTED();
8502 break;
8503 }
TatWai Chong13634762019-07-16 16:20:45 -07008504 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008505}
8506
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008507void Simulator::VisitSVEIntMinMaxDifference_Predicated(
8508 const Instruction* instr) {
8509 VectorFormat vform = instr->GetSVEVectorFormat();
8510 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8511 SimVRegister& zm = ReadVRegister(instr->GetRn());
8512 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8513 SimVRegister result;
8514
8515 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
8516 case SABD_z_p_zz:
8517 absdiff(vform, result, zdn, zm, true);
8518 break;
8519 case SMAX_z_p_zz:
8520 smax(vform, result, zdn, zm);
8521 break;
8522 case SMIN_z_p_zz:
8523 smin(vform, result, zdn, zm);
8524 break;
8525 case UABD_z_p_zz:
8526 absdiff(vform, result, zdn, zm, false);
8527 break;
8528 case UMAX_z_p_zz:
8529 umax(vform, result, zdn, zm);
8530 break;
8531 case UMIN_z_p_zz:
8532 umin(vform, result, zdn, zm);
8533 break;
8534 default:
8535 VIXL_UNIMPLEMENTED();
8536 break;
8537 }
8538 mov_merging(vform, zdn, pg, result);
8539}
8540
8541void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
8542 VectorFormat vform = instr->GetSVEVectorFormat();
8543 SimVRegister& zd = ReadVRegister(instr->GetRd());
8544 SimVRegister scratch;
8545
8546 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
8547 case MUL_z_zi:
8548 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
8549 mul(vform, zd, zd, scratch);
8550 break;
8551 default:
8552 VIXL_UNIMPLEMENTED();
8553 break;
8554 }
8555}
8556
8557void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
8558 VectorFormat vform = instr->GetSVEVectorFormat();
8559 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8560 SimVRegister& zm = ReadVRegister(instr->GetRn());
8561 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8562 SimVRegister result;
8563
8564 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
8565
8566 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
8567 case SDIVR_z_p_zz:
8568 sdiv(vform, result, zm, zdn);
8569 break;
8570 case SDIV_z_p_zz:
8571 sdiv(vform, result, zdn, zm);
8572 break;
8573 case UDIVR_z_p_zz:
8574 udiv(vform, result, zm, zdn);
8575 break;
8576 case UDIV_z_p_zz:
8577 udiv(vform, result, zdn, zm);
8578 break;
8579 default:
8580 VIXL_UNIMPLEMENTED();
8581 break;
8582 }
8583 mov_merging(vform, zdn, pg, result);
8584}
8585
8586void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
8587 VectorFormat vform = instr->GetSVEVectorFormat();
8588 SimVRegister& zd = ReadVRegister(instr->GetRd());
8589 SimVRegister scratch;
8590
8591 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
8592 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
8593
8594 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
8595 case SMAX_z_zi:
8596 dup_immediate(vform, scratch, signed_imm);
8597 smax(vform, zd, zd, scratch);
8598 break;
8599 case SMIN_z_zi:
8600 dup_immediate(vform, scratch, signed_imm);
8601 smin(vform, zd, zd, scratch);
8602 break;
8603 case UMAX_z_zi:
8604 dup_immediate(vform, scratch, unsigned_imm);
8605 umax(vform, zd, zd, scratch);
8606 break;
8607 case UMIN_z_zi:
8608 dup_immediate(vform, scratch, unsigned_imm);
8609 umin(vform, zd, zd, scratch);
8610 break;
8611 default:
8612 VIXL_UNIMPLEMENTED();
8613 break;
8614 }
8615}
8616
8617void Simulator::VisitSVEIntCompareScalarCountAndLimit(
8618 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -07008619 unsigned rn_code = instr->GetRn();
8620 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008621 SimPRegister& pd = ReadPRegister(instr->GetPd());
8622 VectorFormat vform = instr->GetSVEVectorFormat();
8623 bool is_64_bit = instr->ExtractBit(12) == 1;
8624 int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8625 int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
TatWai Chongc844bb22019-06-10 15:32:53 -07008626
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008627 bool last = true;
8628 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
8629 bool cond = false;
8630 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
8631 case WHILELE_p_p_rr:
8632 cond = src1 <= src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008633 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008634 case WHILELO_p_p_rr:
8635 cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
8636 break;
8637 case WHILELS_p_p_rr:
8638 cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
8639 break;
8640 case WHILELT_p_p_rr:
8641 cond = src1 < src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008642 break;
8643 default:
TatWai Chongc844bb22019-06-10 15:32:53 -07008644 VIXL_UNIMPLEMENTED();
8645 break;
8646 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008647 last = last && cond;
8648 LogicPRegister dst(pd);
8649 dst.SetActive(vform, lane, last);
8650 src1 += 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008651 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008652
8653 PredTest(vform, GetPTrue(), pd);
8654 LogSystemRegister(NZCV);
8655}
8656
8657void Simulator::VisitSVEConditionallyTerminateScalars(
8658 const Instruction* instr) {
8659 unsigned rn_code = instr->GetRn();
8660 unsigned rm_code = instr->GetRm();
8661 bool is_64_bit = instr->ExtractBit(22) == 1;
8662 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8663 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
8664 bool term;
8665 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
8666 case CTERMEQ_rr:
8667 term = src1 == src2;
8668 break;
8669 case CTERMNE_rr:
8670 term = src1 != src2;
8671 break;
8672 default:
8673 term = false;
8674 VIXL_UNIMPLEMENTED();
8675 break;
8676 }
8677 ReadNzcv().SetN(term ? 1 : 0);
8678 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -07008679 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008680}
8681
8682void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
8683 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008684 bool commute_inputs = false;
8685 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008686 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8687 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008688 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008689 break;
8690 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008691 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008692 break;
8693 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008694 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008695 break;
8696 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008697 cond = ge;
8698 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008699 break;
8700 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008701 cond = gt;
8702 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008703 break;
8704 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008705 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008706 break;
8707 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008708 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008709 VIXL_UNIMPLEMENTED();
8710 break;
8711 }
TatWai Chong302729c2019-06-14 16:18:51 -07008712
8713 VectorFormat vform = instr->GetSVEVectorFormat();
8714 SimVRegister src2;
8715 dup_immediate(vform,
8716 src2,
8717 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
8718 SVEIntCompareVectorsHelper(cond,
8719 vform,
8720 ReadPRegister(instr->GetPd()),
8721 ReadPRegister(instr->GetPgLow8()),
8722 commute_inputs ? src2
8723 : ReadVRegister(instr->GetRn()),
8724 commute_inputs ? ReadVRegister(instr->GetRn())
8725 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008726}
8727
8728void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
8729 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008730 bool commute_inputs = false;
8731 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008732 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8733 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008734 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008735 break;
8736 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008737 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008738 break;
8739 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008740 cond = hi;
8741 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008742 break;
8743 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008744 cond = hs;
8745 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008746 break;
8747 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008748 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008749 VIXL_UNIMPLEMENTED();
8750 break;
8751 }
TatWai Chong302729c2019-06-14 16:18:51 -07008752
8753 VectorFormat vform = instr->GetSVEVectorFormat();
8754 SimVRegister src2;
8755 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
8756 SVEIntCompareVectorsHelper(cond,
8757 vform,
8758 ReadPRegister(instr->GetPd()),
8759 ReadPRegister(instr->GetPgLow8()),
8760 commute_inputs ? src2
8761 : ReadVRegister(instr->GetRn()),
8762 commute_inputs ? ReadVRegister(instr->GetRn())
8763 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008764}
8765
8766void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
8767 USE(instr);
TatWai Chong96713fe2019-06-04 16:39:37 -07008768
8769 Instr op = instr->Mask(SVEIntCompareVectorsMask);
8770 bool is_wide_elements = false;
8771 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008772 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -07008773 case CMPGE_p_p_zw:
8774 case CMPGT_p_p_zw:
8775 case CMPHI_p_p_zw:
8776 case CMPHS_p_p_zw:
8777 case CMPLE_p_p_zw:
8778 case CMPLO_p_p_zw:
8779 case CMPLS_p_p_zw:
8780 case CMPLT_p_p_zw:
8781 case CMPNE_p_p_zw:
8782 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008783 break;
TatWai Chong96713fe2019-06-04 16:39:37 -07008784 }
8785
TatWai Chong302729c2019-06-14 16:18:51 -07008786 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -07008787 switch (op) {
8788 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008789 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008790 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008791 break;
8792 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008793 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008794 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008795 break;
8796 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008797 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008798 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008799 break;
8800 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008801 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008802 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008803 break;
8804 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008805 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008806 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008807 break;
8808 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008809 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008810 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -07008811 break;
8812 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008813 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -07008814 break;
8815 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008816 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -07008817 break;
8818 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008819 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -07008820 break;
8821 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008822 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008823 break;
8824 default:
8825 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -07008826 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008827 break;
8828 }
TatWai Chong96713fe2019-06-04 16:39:37 -07008829
TatWai Chong302729c2019-06-14 16:18:51 -07008830 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -07008831 instr->GetSVEVectorFormat(),
8832 ReadPRegister(instr->GetPd()),
8833 ReadPRegister(instr->GetPgLow8()),
8834 ReadVRegister(instr->GetRn()),
8835 ReadVRegister(instr->GetRm()),
8836 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008837}
8838
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008839void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00008840 VectorFormat vform = instr->GetSVEVectorFormat();
8841 SimVRegister& zd = ReadVRegister(instr->GetRd());
8842 SimVRegister& zn = ReadVRegister(instr->GetRn());
8843
8844 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
8845 (vform == kFormatVnD));
8846
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008847 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008848 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +00008849 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008850 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008851 default:
8852 VIXL_UNIMPLEMENTED();
8853 break;
8854 }
8855}
8856
8857void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00008858 VectorFormat vform = instr->GetSVEVectorFormat();
8859 SimVRegister& zd = ReadVRegister(instr->GetRd());
8860 SimVRegister& zn = ReadVRegister(instr->GetRn());
8861 SimVRegister& zm = ReadVRegister(instr->GetRm());
8862
8863 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
8864 (vform == kFormatVnD));
8865
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008866 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008867 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +00008868 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008869 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008870 default:
8871 VIXL_UNIMPLEMENTED();
8872 break;
8873 }
8874}
8875
8876void Simulator::VisitSVEConstructivePrefix_Unpredicated(
8877 const Instruction* instr) {
8878 SimVRegister& zd = ReadVRegister(instr->GetRd());
8879 SimVRegister& zn = ReadVRegister(instr->GetRn());
8880
8881 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008882 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008883 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
8884 // Record the movprfx, so the next ExecuteInstruction() can check it.
8885 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008886 break;
8887 default:
8888 VIXL_UNIMPLEMENTED();
8889 break;
8890 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008891}
8892
8893void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +01008894 VectorFormat vform = instr->GetSVEVectorFormat();
8895
8896 SimVRegister& zd = ReadVRegister(instr->GetRd());
8897 SimVRegister& zm = ReadVRegister(instr->GetRm());
8898
8899 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008900 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008901 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008902 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008903 break;
8904 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008905 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008906 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008907 case MAD_z_p_zzz:
8908 // 'za' is encoded in 'Rn'.
8909 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008910 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008911 case MSB_z_p_zzz: {
8912 // 'za' is encoded in 'Rn'.
8913 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
8914 break;
8915 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008916 default:
8917 VIXL_UNIMPLEMENTED();
8918 break;
8919 }
Jacob Bramley22023df2019-05-14 17:55:43 +01008920 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008921}
8922
8923void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
8924 USE(instr);
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008925
8926 VectorFormat vform = instr->GetSVEVectorFormat();
8927 SimVRegister& zda = ReadVRegister(instr->GetRd());
8928 SimVRegister& zn = ReadVRegister(instr->GetRn());
8929 SimVRegister& zm = ReadVRegister(instr->GetRm());
8930
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008931 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8932 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008933 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008934 break;
8935 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008936 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008937 break;
8938 default:
8939 VIXL_UNIMPLEMENTED();
8940 break;
8941 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008942}
8943
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008944void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008945 VectorFormat vform = instr->GetSVEVectorFormat();
8946 SimVRegister& zn = ReadVRegister(instr->GetRn());
8947 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8948 SimVRegister& zd = ReadVRegister(instr->GetRd());
8949
8950 switch (instr->Mask(SVEMovprfxMask)) {
8951 case MOVPRFX_z_p_z:
8952 if (instr->ExtractBit(16)) {
8953 mov_merging(vform, zd, pg, zn);
8954 } else {
8955 mov_zeroing(vform, zd, pg, zn);
8956 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008957
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008958 // Record the movprfx, so the next ExecuteInstruction() can check it.
8959 movprfx_ = instr;
8960 break;
8961 default:
8962 VIXL_UNIMPLEMENTED();
8963 break;
8964 }
8965}
8966
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008967void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008968 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +01008969 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008970 SimVRegister& zn = ReadVRegister(instr->GetRn());
8971 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8972
8973 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
8974 switch (instr->Mask(SVEIntReductionLogicalMask)) {
8975 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008976 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008977 break;
8978 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008979 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008980 break;
8981 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008982 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008983 break;
8984 default:
8985 VIXL_UNIMPLEMENTED();
8986 break;
8987 }
8988 } else {
8989 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008990 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008991 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008992 break;
8993 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008994 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008995 break;
8996 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008997 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008998 break;
8999 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009000 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009001 break;
9002 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009003 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009004 break;
9005 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009006 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009007 break;
9008 default:
9009 VIXL_UNIMPLEMENTED();
9010 break;
9011 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009012 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009013}
9014
9015void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
9016 USE(instr);
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009017
9018 VectorFormat vform = instr->GetSVEVectorFormat();
9019 SimVRegister& zn = ReadVRegister(instr->GetRn());
9020
9021 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009022 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
9023 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009024 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009025 break;
9026 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009027 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009028 break;
9029 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009030 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009031 break;
9032 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009033 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009034 break;
9035 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009036 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009037 break;
9038 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009039 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009040 break;
9041 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009042 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009043 break;
9044 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009045 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009046 break;
9047 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009048 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009049 break;
9050 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009051 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009052 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009053 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009054 break;
9055 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009056 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009057 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009058 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009059 break;
9060 default:
9061 VIXL_UNIMPLEMENTED();
9062 break;
9063 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009064
9065 SimVRegister& zd = ReadVRegister(instr->GetRd());
9066 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9067 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009068}
9069
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009070void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009071 // There is only one instruction in this group.
9072 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
9073
9074 VectorFormat vform = instr->GetSVEVectorFormat();
9075 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
9076 SimVRegister& zd = ReadVRegister(instr->GetRd());
9077
9078 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009079 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009080 case FCPY_z_p_i: {
9081 int imm8 = instr->ExtractBits(12, 5);
9082 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
9083 Instruction::Imm8ToFP64(imm8));
9084 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009085 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009086 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009087 default:
9088 VIXL_UNIMPLEMENTED();
9089 break;
9090 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009091 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009092}
9093
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009094void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
9095 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +01009096 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01009097 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +01009098 SimVRegister scratch;
9099
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009100 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
9101 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009102
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009103 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009104 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009105 add_uint(vform, zd, zd, imm);
9106 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009107 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009108 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
9109 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009110 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009111 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
9112 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009113 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009114 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +01009115 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009116 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009117 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009118 sub_uint(vform, zd, zd, imm);
9119 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009120 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009121 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9122 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009123 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009124 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9125 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009126 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009127 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009128 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009129}
TatWai Chong6995bfd2019-09-26 10:48:05 +01009130
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009131void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
9132 SimVRegister& zd = ReadVRegister(instr->GetRd());
9133
9134 int64_t imm = instr->GetImmSVEIntWideSigned();
9135 imm <<= instr->ExtractBit(13) * 8;
9136
9137 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
9138 case DUP_z_i:
9139 dup_immediate(instr->GetSVEVectorFormat(), zd, imm);
9140 break;
9141 default:
9142 VIXL_UNIMPLEMENTED();
9143 break;
9144 }
9145}
9146
9147void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
9148 VectorFormat vform = instr->GetSVEVectorFormat();
9149 SimVRegister& zd = ReadVRegister(instr->GetRd());
9150
9151 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009152 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +01009153 switch (vform) {
9154 case kFormatVnH:
9155 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
9156 break;
9157 case kFormatVnS:
9158 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
9159 break;
9160 case kFormatVnD:
9161 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
9162 break;
9163 default:
9164 VIXL_UNIMPLEMENTED();
9165 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009166 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009167 default:
9168 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009169 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009170 }
9171}
9172
9173void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
9174 const Instruction* instr) {
9175 USE(instr);
9176 switch (instr->Mask(
9177 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
9178 case LD1H_z_p_bz_s_x32_scaled:
9179 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009180 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009181 case LD1SH_z_p_bz_s_x32_scaled:
9182 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009183 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009184 case LDFF1H_z_p_bz_s_x32_scaled:
9185 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009186 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009187 case LDFF1SH_z_p_bz_s_x32_scaled:
9188 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009189 break;
9190 default:
9191 VIXL_UNIMPLEMENTED();
9192 break;
9193 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009194}
9195
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009196void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009197 const Instruction* instr) {
9198 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009199 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
9200 case LD1B_z_p_bz_s_x32_unscaled:
9201 VIXL_UNIMPLEMENTED();
9202 break;
9203 case LD1H_z_p_bz_s_x32_unscaled:
9204 VIXL_UNIMPLEMENTED();
9205 break;
9206 case LD1SB_z_p_bz_s_x32_unscaled:
9207 VIXL_UNIMPLEMENTED();
9208 break;
9209 case LD1SH_z_p_bz_s_x32_unscaled:
9210 VIXL_UNIMPLEMENTED();
9211 break;
9212 case LD1W_z_p_bz_s_x32_unscaled:
9213 VIXL_UNIMPLEMENTED();
9214 break;
9215 case LDFF1B_z_p_bz_s_x32_unscaled:
9216 VIXL_UNIMPLEMENTED();
9217 break;
9218 case LDFF1H_z_p_bz_s_x32_unscaled:
9219 VIXL_UNIMPLEMENTED();
9220 break;
9221 case LDFF1SB_z_p_bz_s_x32_unscaled:
9222 VIXL_UNIMPLEMENTED();
9223 break;
9224 case LDFF1SH_z_p_bz_s_x32_unscaled:
9225 VIXL_UNIMPLEMENTED();
9226 break;
9227 case LDFF1W_z_p_bz_s_x32_unscaled:
9228 VIXL_UNIMPLEMENTED();
9229 break;
9230 default:
9231 VIXL_UNIMPLEMENTED();
9232 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009233 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009234}
9235
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009236void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
9237 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009238 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009239 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
9240 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009241 VIXL_UNIMPLEMENTED();
9242 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009243 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009244 VIXL_UNIMPLEMENTED();
9245 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009246 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009247 VIXL_UNIMPLEMENTED();
9248 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009249 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009250 VIXL_UNIMPLEMENTED();
9251 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009252 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009253 VIXL_UNIMPLEMENTED();
9254 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009255 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009256 VIXL_UNIMPLEMENTED();
9257 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009258 case LDFF1H_z_p_ai_s:
9259 VIXL_UNIMPLEMENTED();
9260 break;
9261 case LDFF1SB_z_p_ai_s:
9262 VIXL_UNIMPLEMENTED();
9263 break;
9264 case LDFF1SH_z_p_ai_s:
9265 VIXL_UNIMPLEMENTED();
9266 break;
9267 case LDFF1W_z_p_ai_s:
9268 VIXL_UNIMPLEMENTED();
9269 break;
9270 default:
9271 VIXL_UNIMPLEMENTED();
9272 break;
9273 }
9274}
9275
9276void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
9277 const Instruction* instr) {
9278 USE(instr);
9279 switch (
9280 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
9281 case LD1W_z_p_bz_s_x32_scaled:
9282 VIXL_UNIMPLEMENTED();
9283 break;
9284 case LDFF1W_z_p_bz_s_x32_scaled:
9285 VIXL_UNIMPLEMENTED();
9286 break;
9287 default:
9288 VIXL_UNIMPLEMENTED();
9289 break;
9290 }
9291}
9292
9293void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
9294 const Instruction* instr) {
9295 USE(instr);
9296 switch (
9297 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
9298 case PRFB_i_p_bz_s_x32_scaled:
9299 VIXL_UNIMPLEMENTED();
9300 break;
9301 case PRFD_i_p_bz_s_x32_scaled:
9302 VIXL_UNIMPLEMENTED();
9303 break;
9304 case PRFH_i_p_bz_s_x32_scaled:
9305 VIXL_UNIMPLEMENTED();
9306 break;
9307 case PRFW_i_p_bz_s_x32_scaled:
9308 VIXL_UNIMPLEMENTED();
9309 break;
9310 default:
9311 VIXL_UNIMPLEMENTED();
9312 break;
9313 }
9314}
9315
9316void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
9317 const Instruction* instr) {
9318 USE(instr);
9319 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
9320 case PRFB_i_p_ai_s:
9321 VIXL_UNIMPLEMENTED();
9322 break;
9323 case PRFD_i_p_ai_s:
9324 VIXL_UNIMPLEMENTED();
9325 break;
9326 case PRFH_i_p_ai_s:
9327 VIXL_UNIMPLEMENTED();
9328 break;
9329 case PRFW_i_p_ai_s:
9330 VIXL_UNIMPLEMENTED();
9331 break;
9332 default:
9333 VIXL_UNIMPLEMENTED();
9334 break;
9335 }
9336}
9337
9338void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
9339 const Instruction* instr) {
9340 USE(instr);
9341 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
9342 case PRFB_i_p_bi_s:
9343 VIXL_UNIMPLEMENTED();
9344 break;
9345 case PRFD_i_p_bi_s:
9346 VIXL_UNIMPLEMENTED();
9347 break;
9348 case PRFH_i_p_bi_s:
9349 VIXL_UNIMPLEMENTED();
9350 break;
9351 case PRFW_i_p_bi_s:
9352 VIXL_UNIMPLEMENTED();
9353 break;
9354 default:
9355 VIXL_UNIMPLEMENTED();
9356 break;
9357 }
9358}
9359
9360void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
9361 const Instruction* instr) {
9362 USE(instr);
9363 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
9364 case PRFB_i_p_br_s:
9365 VIXL_UNIMPLEMENTED();
9366 break;
9367 case PRFD_i_p_br_s:
9368 VIXL_UNIMPLEMENTED();
9369 break;
9370 case PRFH_i_p_br_s:
9371 VIXL_UNIMPLEMENTED();
9372 break;
9373 case PRFW_i_p_br_s:
9374 VIXL_UNIMPLEMENTED();
9375 break;
9376 default:
9377 VIXL_UNIMPLEMENTED();
9378 break;
9379 }
9380}
9381
9382void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
9383 USE(instr);
9384 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
9385 case LD1RB_z_p_bi_u16:
9386 VIXL_UNIMPLEMENTED();
9387 break;
9388 case LD1RB_z_p_bi_u32:
9389 VIXL_UNIMPLEMENTED();
9390 break;
9391 case LD1RB_z_p_bi_u64:
9392 VIXL_UNIMPLEMENTED();
9393 break;
9394 case LD1RB_z_p_bi_u8:
9395 VIXL_UNIMPLEMENTED();
9396 break;
9397 case LD1RD_z_p_bi_u64:
9398 VIXL_UNIMPLEMENTED();
9399 break;
9400 case LD1RH_z_p_bi_u16:
9401 VIXL_UNIMPLEMENTED();
9402 break;
9403 case LD1RH_z_p_bi_u32:
9404 VIXL_UNIMPLEMENTED();
9405 break;
9406 case LD1RH_z_p_bi_u64:
9407 VIXL_UNIMPLEMENTED();
9408 break;
9409 case LD1RSB_z_p_bi_s16:
9410 VIXL_UNIMPLEMENTED();
9411 break;
9412 case LD1RSB_z_p_bi_s32:
9413 VIXL_UNIMPLEMENTED();
9414 break;
9415 case LD1RSB_z_p_bi_s64:
9416 VIXL_UNIMPLEMENTED();
9417 break;
9418 case LD1RSH_z_p_bi_s32:
9419 VIXL_UNIMPLEMENTED();
9420 break;
9421 case LD1RSH_z_p_bi_s64:
9422 VIXL_UNIMPLEMENTED();
9423 break;
9424 case LD1RSW_z_p_bi_s64:
9425 VIXL_UNIMPLEMENTED();
9426 break;
9427 case LD1RW_z_p_bi_u32:
9428 VIXL_UNIMPLEMENTED();
9429 break;
9430 case LD1RW_z_p_bi_u64:
9431 VIXL_UNIMPLEMENTED();
9432 break;
9433 default:
9434 VIXL_UNIMPLEMENTED();
9435 break;
9436 }
9437}
9438
9439void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
9440 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
9441 case LDR_p_bi: {
9442 SimPRegister& pt = ReadPRegister(instr->GetPt());
9443 int pl = GetPredicateLengthInBytes();
9444 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9445 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9446 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
9447 for (int i = 0; i < pl; i++) {
9448 pt.Insert(i, Memory::Read<uint8_t>(address + i));
9449 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009450 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009451 break;
9452 }
9453 default:
9454 VIXL_UNIMPLEMENTED();
9455 break;
9456 }
9457}
9458
9459void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
9460 USE(instr);
9461 switch (instr->Mask(SVELoadVectorRegisterMask)) {
9462 case LDR_z_bi: {
9463 SimVRegister& zt = ReadVRegister(instr->GetRt());
9464 int vl = GetVectorLengthInBytes();
9465 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9466 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9467 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
9468 for (int i = 0; i < vl; i++) {
9469 zt.Insert(i, Memory::Read<uint8_t>(address + i));
9470 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009471 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009472 break;
9473 }
9474 default:
9475 VIXL_UNIMPLEMENTED();
9476 break;
9477 }
9478}
9479
9480void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
9481 const Instruction* instr) {
9482 USE(instr);
9483 switch (instr->Mask(
9484 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009485 case LD1D_z_p_bz_d_x32_scaled:
9486 VIXL_UNIMPLEMENTED();
9487 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009488 case LD1H_z_p_bz_d_x32_scaled:
9489 VIXL_UNIMPLEMENTED();
9490 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009491 case LD1SH_z_p_bz_d_x32_scaled:
9492 VIXL_UNIMPLEMENTED();
9493 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009494 case LD1SW_z_p_bz_d_x32_scaled:
9495 VIXL_UNIMPLEMENTED();
9496 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009497 case LD1W_z_p_bz_d_x32_scaled:
9498 VIXL_UNIMPLEMENTED();
9499 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009500 case LDFF1D_z_p_bz_d_x32_scaled:
9501 VIXL_UNIMPLEMENTED();
9502 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009503 case LDFF1H_z_p_bz_d_x32_scaled:
9504 VIXL_UNIMPLEMENTED();
9505 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009506 case LDFF1SH_z_p_bz_d_x32_scaled:
9507 VIXL_UNIMPLEMENTED();
9508 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009509 case LDFF1SW_z_p_bz_d_x32_scaled:
9510 VIXL_UNIMPLEMENTED();
9511 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009512 case LDFF1W_z_p_bz_d_x32_scaled:
9513 VIXL_UNIMPLEMENTED();
9514 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009515 default:
9516 VIXL_UNIMPLEMENTED();
9517 break;
9518 }
9519}
9520
9521void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
9522 const Instruction* instr) {
9523 USE(instr);
9524 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
9525 case LD1D_z_p_bz_d_64_scaled:
9526 VIXL_UNIMPLEMENTED();
9527 break;
9528 case LD1H_z_p_bz_d_64_scaled:
9529 VIXL_UNIMPLEMENTED();
9530 break;
9531 case LD1SH_z_p_bz_d_64_scaled:
9532 VIXL_UNIMPLEMENTED();
9533 break;
9534 case LD1SW_z_p_bz_d_64_scaled:
9535 VIXL_UNIMPLEMENTED();
9536 break;
9537 case LD1W_z_p_bz_d_64_scaled:
9538 VIXL_UNIMPLEMENTED();
9539 break;
9540 case LDFF1D_z_p_bz_d_64_scaled:
9541 VIXL_UNIMPLEMENTED();
9542 break;
9543 case LDFF1H_z_p_bz_d_64_scaled:
9544 VIXL_UNIMPLEMENTED();
9545 break;
9546 case LDFF1SH_z_p_bz_d_64_scaled:
9547 VIXL_UNIMPLEMENTED();
9548 break;
9549 case LDFF1SW_z_p_bz_d_64_scaled:
9550 VIXL_UNIMPLEMENTED();
9551 break;
9552 case LDFF1W_z_p_bz_d_64_scaled:
9553 VIXL_UNIMPLEMENTED();
9554 break;
9555 default:
9556 VIXL_UNIMPLEMENTED();
9557 break;
9558 }
9559}
9560
9561void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
9562 const Instruction* instr) {
9563 USE(instr);
9564 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
9565 case LD1B_z_p_bz_d_64_unscaled:
9566 VIXL_UNIMPLEMENTED();
9567 break;
9568 case LD1D_z_p_bz_d_64_unscaled:
9569 VIXL_UNIMPLEMENTED();
9570 break;
9571 case LD1H_z_p_bz_d_64_unscaled:
9572 VIXL_UNIMPLEMENTED();
9573 break;
9574 case LD1SB_z_p_bz_d_64_unscaled:
9575 VIXL_UNIMPLEMENTED();
9576 break;
9577 case LD1SH_z_p_bz_d_64_unscaled:
9578 VIXL_UNIMPLEMENTED();
9579 break;
9580 case LD1SW_z_p_bz_d_64_unscaled:
9581 VIXL_UNIMPLEMENTED();
9582 break;
9583 case LD1W_z_p_bz_d_64_unscaled:
9584 VIXL_UNIMPLEMENTED();
9585 break;
9586 case LDFF1B_z_p_bz_d_64_unscaled:
9587 VIXL_UNIMPLEMENTED();
9588 break;
9589 case LDFF1D_z_p_bz_d_64_unscaled:
9590 VIXL_UNIMPLEMENTED();
9591 break;
9592 case LDFF1H_z_p_bz_d_64_unscaled:
9593 VIXL_UNIMPLEMENTED();
9594 break;
9595 case LDFF1SB_z_p_bz_d_64_unscaled:
9596 VIXL_UNIMPLEMENTED();
9597 break;
9598 case LDFF1SH_z_p_bz_d_64_unscaled:
9599 VIXL_UNIMPLEMENTED();
9600 break;
9601 case LDFF1SW_z_p_bz_d_64_unscaled:
9602 VIXL_UNIMPLEMENTED();
9603 break;
9604 case LDFF1W_z_p_bz_d_64_unscaled:
9605 VIXL_UNIMPLEMENTED();
9606 break;
9607 default:
9608 VIXL_UNIMPLEMENTED();
9609 break;
9610 }
9611}
9612
9613void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
9614 const Instruction* instr) {
9615 USE(instr);
9616 switch (instr->Mask(
9617 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9618 case LD1B_z_p_bz_d_x32_unscaled:
9619 VIXL_UNIMPLEMENTED();
9620 break;
9621 case LD1D_z_p_bz_d_x32_unscaled:
9622 VIXL_UNIMPLEMENTED();
9623 break;
9624 case LD1H_z_p_bz_d_x32_unscaled:
9625 VIXL_UNIMPLEMENTED();
9626 break;
9627 case LD1SB_z_p_bz_d_x32_unscaled:
9628 VIXL_UNIMPLEMENTED();
9629 break;
9630 case LD1SH_z_p_bz_d_x32_unscaled:
9631 VIXL_UNIMPLEMENTED();
9632 break;
9633 case LD1SW_z_p_bz_d_x32_unscaled:
9634 VIXL_UNIMPLEMENTED();
9635 break;
9636 case LD1W_z_p_bz_d_x32_unscaled:
9637 VIXL_UNIMPLEMENTED();
9638 break;
9639 case LDFF1B_z_p_bz_d_x32_unscaled:
9640 VIXL_UNIMPLEMENTED();
9641 break;
9642 case LDFF1D_z_p_bz_d_x32_unscaled:
9643 VIXL_UNIMPLEMENTED();
9644 break;
9645 case LDFF1H_z_p_bz_d_x32_unscaled:
9646 VIXL_UNIMPLEMENTED();
9647 break;
9648 case LDFF1SB_z_p_bz_d_x32_unscaled:
9649 VIXL_UNIMPLEMENTED();
9650 break;
9651 case LDFF1SH_z_p_bz_d_x32_unscaled:
9652 VIXL_UNIMPLEMENTED();
9653 break;
9654 case LDFF1SW_z_p_bz_d_x32_unscaled:
9655 VIXL_UNIMPLEMENTED();
9656 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009657 case LDFF1W_z_p_bz_d_x32_unscaled:
9658 VIXL_UNIMPLEMENTED();
9659 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009660 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009661 VIXL_UNIMPLEMENTED();
9662 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009663 }
9664}
9665
9666void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
9667 const Instruction* instr) {
9668 USE(instr);
9669 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
9670 case LD1B_z_p_ai_d:
9671 VIXL_UNIMPLEMENTED();
9672 break;
9673 case LD1D_z_p_ai_d:
9674 VIXL_UNIMPLEMENTED();
9675 break;
9676 case LD1H_z_p_ai_d:
9677 VIXL_UNIMPLEMENTED();
9678 break;
9679 case LD1SB_z_p_ai_d:
9680 VIXL_UNIMPLEMENTED();
9681 break;
9682 case LD1SH_z_p_ai_d:
9683 VIXL_UNIMPLEMENTED();
9684 break;
9685 case LD1SW_z_p_ai_d:
9686 VIXL_UNIMPLEMENTED();
9687 break;
9688 case LD1W_z_p_ai_d:
9689 VIXL_UNIMPLEMENTED();
9690 break;
9691 case LDFF1B_z_p_ai_d:
9692 VIXL_UNIMPLEMENTED();
9693 break;
9694 case LDFF1D_z_p_ai_d:
9695 VIXL_UNIMPLEMENTED();
9696 break;
9697 case LDFF1H_z_p_ai_d:
9698 VIXL_UNIMPLEMENTED();
9699 break;
9700 case LDFF1SB_z_p_ai_d:
9701 VIXL_UNIMPLEMENTED();
9702 break;
9703 case LDFF1SH_z_p_ai_d:
9704 VIXL_UNIMPLEMENTED();
9705 break;
9706 case LDFF1SW_z_p_ai_d:
9707 VIXL_UNIMPLEMENTED();
9708 break;
9709 case LDFF1W_z_p_ai_d:
9710 VIXL_UNIMPLEMENTED();
9711 break;
9712 default:
9713 VIXL_UNIMPLEMENTED();
9714 break;
9715 }
9716}
9717
9718void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
9719 const Instruction* instr) {
9720 USE(instr);
9721 switch (
9722 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009723 case PRFB_i_p_bz_d_64_scaled:
9724 VIXL_UNIMPLEMENTED();
9725 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009726 case PRFD_i_p_bz_d_64_scaled:
9727 VIXL_UNIMPLEMENTED();
9728 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009729 case PRFH_i_p_bz_d_64_scaled:
9730 VIXL_UNIMPLEMENTED();
9731 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009732 case PRFW_i_p_bz_d_64_scaled:
9733 VIXL_UNIMPLEMENTED();
9734 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009735 default:
9736 VIXL_UNIMPLEMENTED();
9737 break;
9738 }
9739}
9740
9741void Simulator::
9742 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
9743 const Instruction* instr) {
9744 USE(instr);
9745 switch (instr->Mask(
9746 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9747 case PRFB_i_p_bz_d_x32_scaled:
9748 VIXL_UNIMPLEMENTED();
9749 break;
9750 case PRFD_i_p_bz_d_x32_scaled:
9751 VIXL_UNIMPLEMENTED();
9752 break;
9753 case PRFH_i_p_bz_d_x32_scaled:
9754 VIXL_UNIMPLEMENTED();
9755 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009756 case PRFW_i_p_bz_d_x32_scaled:
9757 VIXL_UNIMPLEMENTED();
9758 break;
9759 default:
9760 VIXL_UNIMPLEMENTED();
9761 break;
9762 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009763}
9764
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009765void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
9766 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009767 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009768 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
9769 case PRFB_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009770 VIXL_UNIMPLEMENTED();
9771 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009772 case PRFD_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009773 VIXL_UNIMPLEMENTED();
9774 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009775 case PRFH_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009776 VIXL_UNIMPLEMENTED();
9777 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009778 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009779 VIXL_UNIMPLEMENTED();
9780 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009781 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009782 VIXL_UNIMPLEMENTED();
9783 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009784 }
9785}
9786
9787void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
9788 const Instruction* instr) {
9789 USE(instr);
9790 switch (instr->Mask(SVEContiguousFirstFaultLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009791 case LDFF1B_z_p_br_u16:
9792 VIXL_UNIMPLEMENTED();
9793 break;
9794 case LDFF1B_z_p_br_u32:
9795 VIXL_UNIMPLEMENTED();
9796 break;
9797 case LDFF1B_z_p_br_u64:
9798 VIXL_UNIMPLEMENTED();
9799 break;
9800 case LDFF1B_z_p_br_u8:
9801 VIXL_UNIMPLEMENTED();
9802 break;
9803 case LDFF1D_z_p_br_u64:
9804 VIXL_UNIMPLEMENTED();
9805 break;
9806 case LDFF1H_z_p_br_u16:
9807 VIXL_UNIMPLEMENTED();
9808 break;
9809 case LDFF1H_z_p_br_u32:
9810 VIXL_UNIMPLEMENTED();
9811 break;
9812 case LDFF1H_z_p_br_u64:
9813 VIXL_UNIMPLEMENTED();
9814 break;
9815 case LDFF1SB_z_p_br_s16:
9816 VIXL_UNIMPLEMENTED();
9817 break;
9818 case LDFF1SB_z_p_br_s32:
9819 VIXL_UNIMPLEMENTED();
9820 break;
9821 case LDFF1SB_z_p_br_s64:
9822 VIXL_UNIMPLEMENTED();
9823 break;
9824 case LDFF1SH_z_p_br_s32:
9825 VIXL_UNIMPLEMENTED();
9826 break;
9827 case LDFF1SH_z_p_br_s64:
9828 VIXL_UNIMPLEMENTED();
9829 break;
9830 case LDFF1SW_z_p_br_s64:
9831 VIXL_UNIMPLEMENTED();
9832 break;
9833 case LDFF1W_z_p_br_u32:
9834 VIXL_UNIMPLEMENTED();
9835 break;
9836 case LDFF1W_z_p_br_u64:
9837 VIXL_UNIMPLEMENTED();
9838 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009839 default:
9840 VIXL_UNIMPLEMENTED();
9841 break;
9842 }
9843}
9844
9845void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
9846 const Instruction* instr) {
9847 USE(instr);
9848 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009849 case LDNF1B_z_p_bi_u16:
9850 VIXL_UNIMPLEMENTED();
9851 break;
9852 case LDNF1B_z_p_bi_u32:
9853 VIXL_UNIMPLEMENTED();
9854 break;
9855 case LDNF1B_z_p_bi_u64:
9856 VIXL_UNIMPLEMENTED();
9857 break;
9858 case LDNF1B_z_p_bi_u8:
9859 VIXL_UNIMPLEMENTED();
9860 break;
9861 case LDNF1D_z_p_bi_u64:
9862 VIXL_UNIMPLEMENTED();
9863 break;
9864 case LDNF1H_z_p_bi_u16:
9865 VIXL_UNIMPLEMENTED();
9866 break;
9867 case LDNF1H_z_p_bi_u32:
9868 VIXL_UNIMPLEMENTED();
9869 break;
9870 case LDNF1H_z_p_bi_u64:
9871 VIXL_UNIMPLEMENTED();
9872 break;
9873 case LDNF1SB_z_p_bi_s16:
9874 VIXL_UNIMPLEMENTED();
9875 break;
9876 case LDNF1SB_z_p_bi_s32:
9877 VIXL_UNIMPLEMENTED();
9878 break;
9879 case LDNF1SB_z_p_bi_s64:
9880 VIXL_UNIMPLEMENTED();
9881 break;
9882 case LDNF1SH_z_p_bi_s32:
9883 VIXL_UNIMPLEMENTED();
9884 break;
9885 case LDNF1SH_z_p_bi_s64:
9886 VIXL_UNIMPLEMENTED();
9887 break;
9888 case LDNF1SW_z_p_bi_s64:
9889 VIXL_UNIMPLEMENTED();
9890 break;
9891 case LDNF1W_z_p_bi_u32:
9892 VIXL_UNIMPLEMENTED();
9893 break;
9894 case LDNF1W_z_p_bi_u64:
9895 VIXL_UNIMPLEMENTED();
9896 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009897 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009898 VIXL_UNIMPLEMENTED();
9899 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009900 }
9901}
9902
9903void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
9904 const Instruction* instr) {
9905 USE(instr);
9906 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
9907 case LDNT1B_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009908 VIXL_UNIMPLEMENTED();
9909 break;
9910 case LDNT1D_z_p_bi_contiguous:
9911 VIXL_UNIMPLEMENTED();
9912 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009913 case LDNT1H_z_p_bi_contiguous:
9914 VIXL_UNIMPLEMENTED();
9915 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009916 case LDNT1W_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009917 VIXL_UNIMPLEMENTED();
9918 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009919 default:
9920 VIXL_UNIMPLEMENTED();
9921 break;
9922 }
9923}
9924
9925void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
9926 const Instruction* instr) {
9927 USE(instr);
9928 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
9929 case LDNT1B_z_p_br_contiguous:
9930 VIXL_UNIMPLEMENTED();
9931 break;
9932 case LDNT1D_z_p_br_contiguous:
9933 VIXL_UNIMPLEMENTED();
9934 break;
9935 case LDNT1H_z_p_br_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009936 VIXL_UNIMPLEMENTED();
9937 break;
9938 case LDNT1W_z_p_br_contiguous:
9939 VIXL_UNIMPLEMENTED();
9940 break;
9941 default:
9942 VIXL_UNIMPLEMENTED();
9943 break;
9944 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009945}
9946
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009947void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
9948 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009949 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009950 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
9951 case LD1RQB_z_p_bi_u8:
9952 VIXL_UNIMPLEMENTED();
9953 break;
9954 case LD1RQD_z_p_bi_u64:
9955 VIXL_UNIMPLEMENTED();
9956 break;
9957 case LD1RQH_z_p_bi_u16:
9958 VIXL_UNIMPLEMENTED();
9959 break;
9960 case LD1RQW_z_p_bi_u32:
9961 VIXL_UNIMPLEMENTED();
9962 break;
9963 default:
9964 VIXL_UNIMPLEMENTED();
9965 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009966 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009967}
9968
9969void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
9970 const Instruction* instr) {
9971 USE(instr);
9972 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
9973 case LD1RQB_z_p_br_contiguous:
9974 VIXL_UNIMPLEMENTED();
9975 break;
9976 case LD1RQD_z_p_br_contiguous:
9977 VIXL_UNIMPLEMENTED();
9978 break;
9979 case LD1RQH_z_p_br_contiguous:
9980 VIXL_UNIMPLEMENTED();
9981 break;
9982 case LD1RQW_z_p_br_contiguous:
9983 VIXL_UNIMPLEMENTED();
9984 break;
9985 default:
9986 VIXL_UNIMPLEMENTED();
9987 break;
9988 }
9989}
9990
9991void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
9992 const Instruction* instr) {
9993 USE(instr);
9994 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
9995 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009996 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009997 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009998 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009999 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010000 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010001 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010002 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010003 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010004 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010005 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000010006 case LD4W_z_p_bi_contiguous: {
10007 int vl = GetVectorLengthInBytes();
10008 int msz = instr->ExtractBits(24, 23);
10009 int reg_count = instr->ExtractBits(22, 21) + 1;
10010 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10011 LogicSVEAddressVector addr(
10012 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10013 addr.SetMsizeInBytesLog2(msz);
10014 addr.SetRegCount(reg_count);
10015 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10016 ReadPRegister(instr->GetPgLow8()),
10017 instr->GetRt(),
10018 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010019 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000010020 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010021 default:
10022 VIXL_UNIMPLEMENTED();
10023 break;
10024 }
10025}
10026
10027void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
10028 const Instruction* instr) {
10029 USE(instr);
10030 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
10031 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010032 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010033 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010034 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010035 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010036 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010037 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010038 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010039 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010040 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010041 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000010042 case LD4W_z_p_br_contiguous: {
10043 int msz = instr->ExtractBits(24, 23);
10044 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10045 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10046 LogicSVEAddressVector addr(
10047 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10048 addr.SetMsizeInBytesLog2(msz);
10049 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10050 SVEStructuredLoadHelper(vform,
10051 ReadPRegister(instr->GetPgLow8()),
10052 instr->GetRt(),
10053 addr,
10054 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010055 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000010056 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010057 default:
10058 VIXL_UNIMPLEMENTED();
10059 break;
10060 }
10061}
10062
10063void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
10064 const Instruction* instr) {
10065 USE(instr);
10066 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
10067 case ST1H_z_p_bz_s_x32_scaled:
10068 VIXL_UNIMPLEMENTED();
10069 break;
10070 case ST1W_z_p_bz_s_x32_scaled:
10071 VIXL_UNIMPLEMENTED();
10072 break;
10073 default:
10074 VIXL_UNIMPLEMENTED();
10075 break;
10076 }
10077}
10078
10079void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
10080 const Instruction* instr) {
10081 USE(instr);
10082 switch (
10083 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
10084 case ST1B_z_p_bz_s_x32_unscaled:
10085 VIXL_UNIMPLEMENTED();
10086 break;
10087 case ST1H_z_p_bz_s_x32_unscaled:
10088 VIXL_UNIMPLEMENTED();
10089 break;
10090 case ST1W_z_p_bz_s_x32_unscaled:
10091 VIXL_UNIMPLEMENTED();
10092 break;
10093 default:
10094 VIXL_UNIMPLEMENTED();
10095 break;
10096 }
10097}
10098
10099void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
10100 const Instruction* instr) {
10101 USE(instr);
10102 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
10103 case ST1B_z_p_ai_s:
10104 VIXL_UNIMPLEMENTED();
10105 break;
10106 case ST1H_z_p_ai_s:
10107 VIXL_UNIMPLEMENTED();
10108 break;
10109 case ST1W_z_p_ai_s:
10110 VIXL_UNIMPLEMENTED();
10111 break;
10112 default:
10113 VIXL_UNIMPLEMENTED();
10114 break;
10115 }
10116}
10117
10118void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
10119 const Instruction* instr) {
10120 USE(instr);
10121 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
10122 case ST1D_z_p_bz_d_64_scaled:
10123 VIXL_UNIMPLEMENTED();
10124 break;
10125 case ST1H_z_p_bz_d_64_scaled:
10126 VIXL_UNIMPLEMENTED();
10127 break;
10128 case ST1W_z_p_bz_d_64_scaled:
10129 VIXL_UNIMPLEMENTED();
10130 break;
10131 default:
10132 VIXL_UNIMPLEMENTED();
10133 break;
10134 }
10135}
10136
10137void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
10138 const Instruction* instr) {
10139 USE(instr);
10140 switch (
10141 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
10142 case ST1B_z_p_bz_d_64_unscaled:
10143 VIXL_UNIMPLEMENTED();
10144 break;
10145 case ST1D_z_p_bz_d_64_unscaled:
10146 VIXL_UNIMPLEMENTED();
10147 break;
10148 case ST1H_z_p_bz_d_64_unscaled:
10149 VIXL_UNIMPLEMENTED();
10150 break;
10151 case ST1W_z_p_bz_d_64_unscaled:
10152 VIXL_UNIMPLEMENTED();
10153 break;
10154 default:
10155 VIXL_UNIMPLEMENTED();
10156 break;
10157 }
10158}
10159
10160void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
10161 const Instruction* instr) {
10162 USE(instr);
10163 switch (instr->Mask(
10164 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
10165 case ST1D_z_p_bz_d_x32_scaled:
10166 VIXL_UNIMPLEMENTED();
10167 break;
10168 case ST1H_z_p_bz_d_x32_scaled:
10169 VIXL_UNIMPLEMENTED();
10170 break;
10171 case ST1W_z_p_bz_d_x32_scaled:
10172 VIXL_UNIMPLEMENTED();
10173 break;
10174 default:
10175 VIXL_UNIMPLEMENTED();
10176 break;
10177 }
10178}
10179
10180void Simulator::
10181 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
10182 const Instruction* instr) {
10183 USE(instr);
10184 switch (instr->Mask(
10185 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
10186 case ST1B_z_p_bz_d_x32_unscaled:
10187 VIXL_UNIMPLEMENTED();
10188 break;
10189 case ST1D_z_p_bz_d_x32_unscaled:
10190 VIXL_UNIMPLEMENTED();
10191 break;
10192 case ST1H_z_p_bz_d_x32_unscaled:
10193 VIXL_UNIMPLEMENTED();
10194 break;
10195 case ST1W_z_p_bz_d_x32_unscaled:
10196 VIXL_UNIMPLEMENTED();
10197 break;
10198 default:
10199 VIXL_UNIMPLEMENTED();
10200 break;
10201 }
10202}
10203
10204void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
10205 const Instruction* instr) {
10206 USE(instr);
10207 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
10208 case ST1B_z_p_ai_d:
10209 VIXL_UNIMPLEMENTED();
10210 break;
10211 case ST1D_z_p_ai_d:
10212 VIXL_UNIMPLEMENTED();
10213 break;
10214 case ST1H_z_p_ai_d:
10215 VIXL_UNIMPLEMENTED();
10216 break;
10217 case ST1W_z_p_ai_d:
10218 VIXL_UNIMPLEMENTED();
10219 break;
10220 default:
10221 VIXL_UNIMPLEMENTED();
10222 break;
10223 }
10224}
10225
10226void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
10227 const Instruction* instr) {
10228 USE(instr);
10229 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
10230 case STNT1B_z_p_bi_contiguous:
10231 VIXL_UNIMPLEMENTED();
10232 break;
10233 case STNT1D_z_p_bi_contiguous:
10234 VIXL_UNIMPLEMENTED();
10235 break;
10236 case STNT1H_z_p_bi_contiguous:
10237 VIXL_UNIMPLEMENTED();
10238 break;
10239 case STNT1W_z_p_bi_contiguous:
10240 VIXL_UNIMPLEMENTED();
10241 break;
10242 default:
10243 VIXL_UNIMPLEMENTED();
10244 break;
10245 }
10246}
10247
10248void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
10249 const Instruction* instr) {
10250 USE(instr);
10251 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
10252 case STNT1B_z_p_br_contiguous:
10253 VIXL_UNIMPLEMENTED();
10254 break;
10255 case STNT1D_z_p_br_contiguous:
10256 VIXL_UNIMPLEMENTED();
10257 break;
10258 case STNT1H_z_p_br_contiguous:
10259 VIXL_UNIMPLEMENTED();
10260 break;
10261 case STNT1W_z_p_br_contiguous:
10262 VIXL_UNIMPLEMENTED();
10263 break;
10264 default:
10265 VIXL_UNIMPLEMENTED();
10266 break;
10267 }
10268}
10269
10270void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
10271 const Instruction* instr) {
10272 USE(instr);
10273 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
10274 case ST1B_z_p_bi:
10275 case ST1D_z_p_bi:
10276 case ST1H_z_p_bi:
10277 case ST1W_z_p_bi: {
10278 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010279 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10280 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
10281 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10282 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10283 uint64_t offset =
10284 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010285 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010286 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010287 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010288 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10289 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010290 ReadPRegister(instr->GetPgLow8()),
10291 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010292 addr);
10293 break;
10294 }
10295 default:
10296 VIXL_UNIMPLEMENTED();
10297 break;
10298 }
10299}
10300
10301void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
10302 const Instruction* instr) {
10303 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
10304 case ST1B_z_p_br:
10305 case ST1D_z_p_br:
10306 case ST1H_z_p_br:
10307 case ST1W_z_p_br: {
10308 uint64_t offset = ReadXRegister(instr->GetRm());
10309 offset <<= instr->ExtractBits(24, 23);
10310 VectorFormat vform =
10311 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
10312 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010313 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
10314 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010315 ReadPRegister(instr->GetPgLow8()),
10316 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010317 addr);
10318 break;
10319 }
10320 default:
10321 VIXL_UNIMPLEMENTED();
10322 break;
10323 }
10324}
10325
10326void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
10327 const Instruction* instr) {
10328 VectorFormat vform = instr->GetSVEVectorFormat();
10329 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10330 SimVRegister z_result;
10331
10332 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
10333 case CPY_z_p_v:
10334 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
10335 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
10336 break;
10337 default:
10338 VIXL_UNIMPLEMENTED();
10339 break;
10340 }
10341}
10342
10343void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
10344 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010345 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
10346 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010347 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010348 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010349 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010350 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010351 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010352 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010353 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010354 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010355 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010356 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010357 case ST4W_z_p_bi_contiguous: {
10358 int vl = GetVectorLengthInBytes();
10359 int msz = instr->ExtractBits(24, 23);
10360 int reg_count = instr->ExtractBits(22, 21) + 1;
10361 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10362 LogicSVEAddressVector addr(
10363 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10364 addr.SetMsizeInBytesLog2(msz);
10365 addr.SetRegCount(reg_count);
10366 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10367 ReadPRegister(instr->GetPgLow8()),
10368 instr->GetRt(),
10369 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010370 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010371 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010372 default:
10373 VIXL_UNIMPLEMENTED();
10374 break;
10375 }
10376}
10377
10378void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
10379 const Instruction* instr) {
10380 USE(instr);
10381 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
10382 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010383 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010384 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010385 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010386 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010387 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010388 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010389 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010390 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010391 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010392 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010393 case ST4W_z_p_br_contiguous: {
10394 int msz = instr->ExtractBits(24, 23);
10395 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10396 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10397 LogicSVEAddressVector addr(
10398 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10399 addr.SetMsizeInBytesLog2(msz);
10400 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10401 SVEStructuredStoreHelper(vform,
10402 ReadPRegister(instr->GetPgLow8()),
10403 instr->GetRt(),
10404 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010405 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010406 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010407 default:
10408 VIXL_UNIMPLEMENTED();
10409 break;
10410 }
10411}
10412
10413void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
10414 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
10415 case STR_p_bi: {
10416 SimPRegister& pt = ReadPRegister(instr->GetPt());
10417 int pl = GetPredicateLengthInBytes();
10418 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10419 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10420 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
10421 for (int i = 0; i < pl; i++) {
10422 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
10423 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010424 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010425 break;
10426 }
10427 default:
10428 VIXL_UNIMPLEMENTED();
10429 break;
10430 }
10431}
10432
10433void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
10434 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
10435 case STR_z_bi: {
10436 SimVRegister& zt = ReadVRegister(instr->GetRt());
10437 int vl = GetVectorLengthInBytes();
10438 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10439 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10440 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
10441 for (int i = 0; i < vl; i++) {
10442 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
10443 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010444 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010445 break;
10446 }
10447 default:
10448 VIXL_UNIMPLEMENTED();
10449 break;
10450 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010451}
10452
10453void Simulator::VisitSVEMulIndex(const Instruction* instr) {
10454 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010455 switch (instr->Mask(SVEMulIndexMask)) {
10456 case SDOT_z_zzzi_d:
10457 VIXL_UNIMPLEMENTED();
10458 break;
10459 case SDOT_z_zzzi_s:
10460 VIXL_UNIMPLEMENTED();
10461 break;
10462 case UDOT_z_zzzi_d:
10463 VIXL_UNIMPLEMENTED();
10464 break;
10465 case UDOT_z_zzzi_s:
10466 VIXL_UNIMPLEMENTED();
10467 break;
10468 default:
10469 VIXL_UNIMPLEMENTED();
10470 break;
10471 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010472}
10473
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010474void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010475 SimPRegister& pd = ReadPRegister(instr->GetPd());
10476 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10477 SimPRegister& pn = ReadPRegister(instr->GetPn());
10478 SimPRegister result;
10479
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010480 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010481 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010482 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010483 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010484 break;
10485 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010486 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010487 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010488 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010489 default:
10490 VIXL_UNIMPLEMENTED();
10491 break;
10492 }
TatWai Chong5d872292020-01-02 15:39:51 -080010493
10494 if (instr->ExtractBit(4) == 1) {
10495 mov_merging(pd, pg, result);
10496 } else {
10497 mov_zeroing(pd, pg, result);
10498 }
10499
10500 // Set flag if needed.
10501 if (instr->ExtractBit(22) == 1) {
10502 PredTest(kFormatVnB, pg, pd);
10503 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010504}
10505
10506void Simulator::VisitSVEPropagateBreakToNextPartition(
10507 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010508 SimPRegister& pdm = ReadPRegister(instr->GetPd());
10509 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10510 SimPRegister& pn = ReadPRegister(instr->GetPn());
10511
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010512 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010513 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010514 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080010515 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010516 break;
10517 default:
10518 VIXL_UNIMPLEMENTED();
10519 break;
10520 }
TatWai Chong5d872292020-01-02 15:39:51 -080010521
10522 // Set flag if needed.
10523 if (instr->ExtractBit(22) == 1) {
10524 PredTest(kFormatVnB, pg, pdm);
10525 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010526}
10527
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010528void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010529 SimPRegister& pd = ReadPRegister(instr->GetPd());
10530 SimPRegister& pn = ReadPRegister(instr->GetPn());
10531
10532 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10533 SimVRegister zero;
10534 dup_immediate(kFormatVnB, zero, 0);
10535
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010536 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010537 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010538 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010539 break;
10540 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010541 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010542 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010543 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010544 VIXL_UNIMPLEMENTED();
10545 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010546 }
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010547 Simulator::ExtractFromSimVRegister(pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010548}
10549
10550void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010551 VectorFormat vform = instr->GetSVEVectorFormat();
10552 SimPRegister& pd = ReadPRegister(instr->GetPd());
10553 SimPRegister& pn = ReadPRegister(instr->GetPn());
10554 SimPRegister& pm = ReadPRegister(instr->GetPm());
10555
10556 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
10557 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
10558
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010559 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010560 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010561 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010562 break;
10563 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010564 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010565 break;
10566 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010567 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010568 break;
10569 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010570 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010571 break;
10572 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010573 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010574 break;
10575 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010576 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010577 break;
10578 default:
10579 VIXL_UNIMPLEMENTED();
10580 break;
10581 }
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010582 Simulator::ExtractFromSimVRegister(pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010583}
10584
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010585void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010586 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010587 case REV_p_p: {
10588 VectorFormat vform = instr->GetSVEVectorFormat();
10589 SimPRegister& pn = ReadPRegister(instr->GetPn());
10590 SimPRegister& pd = ReadPRegister(instr->GetPd());
10591 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10592 rev(vform, temp, temp);
10593 Simulator::ExtractFromSimVRegister(pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010594 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010595 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010596 default:
10597 VIXL_UNIMPLEMENTED();
10598 break;
10599 }
10600}
10601
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010602void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
10603 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010604 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
10605 case EXT_z_zi_des:
10606 VIXL_UNIMPLEMENTED();
10607 break;
10608 default:
10609 VIXL_UNIMPLEMENTED();
10610 break;
10611 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010612}
10613
10614void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000010615 VectorFormat vform = instr->GetSVEVectorFormat();
10616 SimVRegister& zd = ReadVRegister(instr->GetRd());
10617 SimVRegister& zn = ReadVRegister(instr->GetRn());
10618 SimVRegister& zm = ReadVRegister(instr->GetRm());
10619
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010620 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
10621 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010622 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010623 break;
10624 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010625 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010626 break;
10627 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010628 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010629 break;
10630 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010631 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010632 break;
10633 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010634 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010635 break;
10636 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010637 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010638 break;
10639 default:
10640 VIXL_UNIMPLEMENTED();
10641 break;
10642 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010643}
10644
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010645void Simulator::VisitSVEConditionallyBroadcastElementToVector(
10646 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010647 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010648 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010649 case CLASTA_z_p_zz:
10650 VIXL_UNIMPLEMENTED();
10651 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010652 case CLASTB_z_p_zz:
10653 VIXL_UNIMPLEMENTED();
10654 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010655 default:
10656 VIXL_UNIMPLEMENTED();
10657 break;
10658 }
10659}
10660
10661void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
10662 const Instruction* instr) {
10663 USE(instr);
10664 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
10665 case CLASTA_v_p_z:
10666 VIXL_UNIMPLEMENTED();
10667 break;
10668 case CLASTB_v_p_z:
10669 VIXL_UNIMPLEMENTED();
10670 break;
10671 default:
10672 VIXL_UNIMPLEMENTED();
10673 break;
10674 }
10675}
10676
10677void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
10678 const Instruction* instr) {
10679 USE(instr);
10680 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
10681 case CLASTA_r_p_z:
10682 VIXL_UNIMPLEMENTED();
10683 break;
10684 case CLASTB_r_p_z:
10685 VIXL_UNIMPLEMENTED();
10686 break;
10687 default:
10688 VIXL_UNIMPLEMENTED();
10689 break;
10690 }
10691}
10692
10693void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
10694 const Instruction* instr) {
10695 USE(instr);
10696 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
10697 case LASTA_v_p_z:
10698 VIXL_UNIMPLEMENTED();
10699 break;
10700 case LASTB_v_p_z:
10701 VIXL_UNIMPLEMENTED();
10702 break;
10703 default:
10704 VIXL_UNIMPLEMENTED();
10705 break;
10706 }
10707}
10708
10709void Simulator::VisitSVEExtractElementToGeneralRegister(
10710 const Instruction* instr) {
10711 USE(instr);
10712 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
10713 case LASTA_r_p_z:
10714 VIXL_UNIMPLEMENTED();
10715 break;
10716 case LASTB_r_p_z:
10717 VIXL_UNIMPLEMENTED();
10718 break;
10719 default:
10720 VIXL_UNIMPLEMENTED();
10721 break;
10722 }
10723}
10724
10725void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
10726 USE(instr);
10727 switch (instr->Mask(SVECompressActiveElementsMask)) {
10728 case COMPACT_z_p_z:
10729 VIXL_UNIMPLEMENTED();
10730 break;
10731 default:
10732 VIXL_UNIMPLEMENTED();
10733 break;
10734 }
10735}
10736
10737void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
10738 const Instruction* instr) {
10739 VectorFormat vform = instr->GetSVEVectorFormat();
10740 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10741 SimVRegister z_result;
10742
10743 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010744 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010010745 dup_immediate(vform,
10746 z_result,
10747 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10748 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010749 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010750 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010751 VIXL_UNIMPLEMENTED();
10752 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010753 }
10754}
10755
10756void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010757 VectorFormat vform = instr->GetSVEVectorFormat();
10758 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
10759 SimVRegister& zd = ReadVRegister(instr->GetRd());
10760
10761 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010762 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010763 case CPY_z_p_i: {
10764 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
10765 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
10766 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010767 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010768 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010769 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010770 VIXL_UNIMPLEMENTED();
10771 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010772 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010773
10774 if (instr->ExtractBit(14) != 0) {
10775 mov_merging(vform, zd, pg, result);
10776 } else {
10777 mov_zeroing(vform, zd, pg, result);
10778 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010779}
10780
10781void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000010782 SimVRegister& zd = ReadVRegister(instr->GetRd());
10783 SimVRegister& zn = ReadVRegister(instr->GetRn());
10784 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10785 SimVRegister result;
10786
10787 // In NEON, the chunk size in which elements are REVersed is in the
10788 // instruction mnemonic, and the element size attached to the register.
10789 // SVE reverses the semantics; the mapping to logic functions below is to
10790 // account for this.
10791 VectorFormat chunk_form = instr->GetSVEVectorFormat();
10792 VectorFormat element_form = kFormatUndefined;
10793
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010794 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010795 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010796 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010797 break;
10798 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010799 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
10800 (chunk_form == kFormatVnD));
10801 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010802 break;
10803 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010804 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
10805 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010806 break;
10807 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010808 VIXL_ASSERT(chunk_form == kFormatVnD);
10809 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010810 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010811 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010812 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010813 break;
10814 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000010815
10816 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
10817 VIXL_ASSERT(element_form != kFormatUndefined);
10818 switch (chunk_form) {
10819 case kFormatVnH:
10820 rev16(element_form, result, zn);
10821 break;
10822 case kFormatVnS:
10823 rev32(element_form, result, zn);
10824 break;
10825 case kFormatVnD:
10826 rev64(element_form, result, zn);
10827 break;
10828 default:
10829 VIXL_UNIMPLEMENTED();
10830 }
10831 }
10832
10833 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010834}
10835
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010836void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010837 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010838 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
10839 case SPLICE_z_p_zz_des:
10840 VIXL_UNIMPLEMENTED();
10841 break;
10842 default:
10843 VIXL_UNIMPLEMENTED();
10844 break;
10845 }
10846}
TatWai Chong4f28df72019-08-14 17:50:30 -070010847
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010848void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
10849 SimVRegister& zd = ReadVRegister(instr->GetRd());
10850 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
10851 case DUP_z_r:
10852 dup_immediate(instr->GetSVEVectorFormat(),
10853 zd,
10854 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10855 break;
10856 default:
10857 VIXL_UNIMPLEMENTED();
10858 break;
10859 }
10860}
10861
10862void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
10863 SimVRegister& zd = ReadVRegister(instr->GetRd());
10864 VectorFormat vform = instr->GetSVEVectorFormat();
10865 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
10866 case INSR_z_v:
10867 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
10868 break;
10869 default:
10870 VIXL_UNIMPLEMENTED();
10871 break;
10872 }
10873}
10874
10875void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
10876 SimVRegister& zd = ReadVRegister(instr->GetRd());
10877 VectorFormat vform = instr->GetSVEVectorFormat();
10878 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
10879 case INSR_z_r:
10880 insr(vform, zd, ReadXRegister(instr->GetRn()));
10881 break;
10882 default:
10883 VIXL_UNIMPLEMENTED();
10884 break;
10885 }
10886}
10887
10888void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
10889 SimVRegister& zd = ReadVRegister(instr->GetRd());
10890 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070010891 case DUP_z_zi: {
10892 std::pair<int, int> index_and_lane_size =
10893 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10894 int index = index_and_lane_size.first;
10895 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
10896 VectorFormat vform =
10897 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
10898 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
10899 // Out of bounds, set the destination register to zero.
10900 dup_immediate(kFormatVnD, zd, 0);
10901 } else {
10902 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
10903 }
10904 return;
10905 }
TatWai Chong4f28df72019-08-14 17:50:30 -070010906 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010907 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070010908 break;
10909 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010910}
TatWai Chong4f28df72019-08-14 17:50:30 -070010911
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010912void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
10913 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070010914 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010915 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010916 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010917 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010918 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010919 default:
10920 VIXL_UNIMPLEMENTED();
10921 break;
10922 }
10923}
10924
10925void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
10926 SimVRegister& zd = ReadVRegister(instr->GetRd());
10927 VectorFormat vform = instr->GetSVEVectorFormat();
10928 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010929 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010930 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010931 break;
10932 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010933 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010934 break;
10935 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010936 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010937 break;
10938 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010939 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
10940 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010941 default:
10942 VIXL_UNIMPLEMENTED();
10943 break;
10944 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010945}
10946
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010947void Simulator::VisitSVETableLookup(const Instruction* instr) {
10948 SimVRegister& zd = ReadVRegister(instr->GetRd());
10949 switch (instr->Mask(SVETableLookupMask)) {
10950 case TBL_z_zz_1:
10951 Table(instr->GetSVEVectorFormat(),
10952 zd,
10953 ReadVRegister(instr->GetRn()),
10954 ReadVRegister(instr->GetRm()));
10955 return;
10956 default:
10957 break;
10958 }
10959}
10960
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010961void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
10962 USE(instr);
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010963
10964 VectorFormat vform = instr->GetSVEVectorFormat();
10965 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10966 SimPRegister& pn = ReadPRegister(instr->GetPn());
10967
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010968 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010969 case CNTP_r_p_p: {
10970 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010971 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010972 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010973 default:
10974 VIXL_UNIMPLEMENTED();
10975 break;
10976 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010977}
10978
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010979void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
10980 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080010981 SimPRegister& pd = ReadPRegister(instr->GetPd());
10982 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10983 SimPRegister& pn = ReadPRegister(instr->GetPn());
10984 SimPRegister& pm = ReadPRegister(instr->GetPm());
10985 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070010986 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010987 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010988 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010989 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010990 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010991 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010992 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010993 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010994 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010995 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010996 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010997 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010998 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010999 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011000 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070011001 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080011002 result,
11003 pn,
11004 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011005 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080011006 case SEL_p_p_pp:
11007 sel(pd, pg, pn, pm);
11008 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011009 default:
11010 VIXL_UNIMPLEMENTED();
11011 break;
11012 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080011013
11014 mov_zeroing(pd, pg, result);
11015 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
11016 PredTest(kFormatVnB, pg, pd);
11017 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011018}
11019
Jacob Bramley0ce75842019-07-17 18:12:50 +010011020void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011021 USE(instr);
Jacob Bramley0ce75842019-07-17 18:12:50 +010011022 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11023 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11024 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011025 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010011026 pfirst(pdn, pg, pdn);
11027 // TODO: Is this broken when pg == pdn?
11028 PredTest(kFormatVnB, pg, pdn);
11029 break;
11030 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011031 VIXL_UNIMPLEMENTED();
11032 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011033 }
11034}
11035
11036void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
11037 USE(instr);
11038 // This group only contains PTRUE{S}, and there are no unallocated encodings.
11039 VIXL_STATIC_ASSERT(
11040 SVEPredicateInitializeMask ==
11041 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
11042 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
11043 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
11044
11045 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11046 VectorFormat vform = instr->GetSVEVectorFormat();
11047
11048 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
11049 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
11050}
11051
11052void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
11053 USE(instr);
11054 // This group only contains PNEXT, and there are no unallocated encodings.
11055 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
11056 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
11057
11058 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11059 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11060 VectorFormat vform = instr->GetSVEVectorFormat();
11061
11062 pnext(vform, pdn, pg, pdn);
11063 // TODO: Is this broken when pg == pdn?
11064 PredTest(vform, pg, pdn);
11065}
11066
11067void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
11068 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080011069 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11070 LogicPRegister pg(ReadPRegister(instr->GetPn()));
11071 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011072 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
11073 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011074 // Do nothing.
11075 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011076 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011077 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011078 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011079 default:
11080 VIXL_UNIMPLEMENTED();
11081 break;
11082 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080011083
11084 LogicPRegister ffr(ReadFFR());
11085 mov_zeroing(pd, pg, ffr);
11086
11087 if (flags == SetFlags) {
11088 PredTest(kFormatVnB, pg, pd);
11089 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010011090}
11091
11092void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
11093 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011094 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11095 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010011096 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011097 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080011098 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011099 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011100 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011101 VIXL_UNIMPLEMENTED();
11102 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011103 }
11104}
11105
11106void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
11107 USE(instr);
11108 switch (instr->Mask(SVEPredicateTestMask)) {
11109 case PTEST_p_p:
11110 PredTest(kFormatVnB,
11111 ReadPRegister(instr->ExtractBits(13, 10)),
11112 ReadPRegister(instr->GetPn()));
11113 break;
11114 default:
11115 VIXL_UNIMPLEMENTED();
11116 break;
11117 }
11118}
11119
11120void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
11121 USE(instr);
11122 switch (instr->Mask(SVEPredicateZeroMask)) {
11123 case PFALSE_p:
11124 pfalse(ReadPRegister(instr->GetPd()));
11125 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011126 default:
11127 VIXL_UNIMPLEMENTED();
11128 break;
11129 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011130}
11131
11132void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080011133 SimPRegister& pd = ReadPRegister(instr->GetPd());
11134 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11135 SimPRegister& pn = ReadPRegister(instr->GetPn());
11136 SimPRegister& pm = ReadPRegister(instr->GetPm());
11137
11138 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011139 switch (instr->Mask(SVEPropagateBreakMask)) {
11140 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011141 set_flags = true;
11142 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011143 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011144 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011145 break;
11146 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011147 set_flags = true;
11148 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011149 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011150 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011151 break;
11152 default:
11153 VIXL_UNIMPLEMENTED();
11154 break;
11155 }
TatWai Chong38303d92019-12-02 15:49:29 -080011156
11157 if (set_flags) {
11158 PredTest(kFormatVnB, pg, pd);
11159 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011160}
11161
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011162void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
11163 uint64_t length = 0;
11164 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
11165 case ADDPL_r_ri:
11166 length = GetPredicateLengthInBytes();
11167 break;
11168 case ADDVL_r_ri:
11169 length = GetVectorLengthInBytes();
11170 break;
11171 default:
11172 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011173 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011174 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011175 WriteXRegister(instr->GetRd(),
11176 base + (length * instr->GetImmSVEVLScale()),
11177 LogRegWrites,
11178 Reg31IsStackPointer);
11179}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011180
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011181void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
11182 int64_t scale = instr->GetImmSVEVLScale();
11183
11184 switch (instr->Mask(SVEStackFrameSizeMask)) {
11185 case RDVL_r_i:
11186 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
11187 break;
11188 default:
11189 VIXL_UNIMPLEMENTED();
11190 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011191}
11192
11193void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
11194 USE(instr);
TatWai Chong6205eb42019-09-24 10:07:20 +010011195
11196 // The only instruction in this group is `sel`, and there are no unused
11197 // encodings.
11198 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
11199
11200 VectorFormat vform = instr->GetSVEVectorFormat();
11201 SimVRegister& zd = ReadVRegister(instr->GetRd());
11202 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11203 SimVRegister& zn = ReadVRegister(instr->GetRn());
11204 SimVRegister& zm = ReadVRegister(instr->GetRm());
11205
11206 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011207}
11208
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011209void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011210 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011211 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011212 case SETFFR_f: {
11213 LogicPRegister ffr(ReadFFR());
11214 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011215 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011216 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011217 default:
11218 VIXL_UNIMPLEMENTED();
11219 break;
11220 }
11221}
11222
11223void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
11224 USE(instr);
11225 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011226 case WRFFR_f_p: {
11227 SimPRegister pn(ReadPRegister(instr->GetPn()));
11228 bool last_active = true;
11229 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
11230 bool active = pn.GetBit(i);
11231 if (active && !last_active) {
11232 // `pn` is non-monotonic. This is UNPREDICTABLE.
11233 VIXL_ABORT();
11234 }
11235 last_active = active;
11236 }
11237 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011238 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011239 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011240 default:
11241 VIXL_UNIMPLEMENTED();
11242 break;
11243 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011244}
Alexandre Ramesd3832962016-07-04 15:03:43 +010011245
TatWai Chong6205eb42019-09-24 10:07:20 +010011246void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
11247 USE(instr);
11248 bool is_signed;
11249 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
11250 case LD1B_z_p_bi_u8:
11251 case LD1B_z_p_bi_u16:
11252 case LD1B_z_p_bi_u32:
11253 case LD1B_z_p_bi_u64:
11254 case LD1H_z_p_bi_u16:
11255 case LD1H_z_p_bi_u32:
11256 case LD1H_z_p_bi_u64:
11257 case LD1W_z_p_bi_u32:
11258 case LD1W_z_p_bi_u64:
11259 case LD1D_z_p_bi_u64:
11260 is_signed = false;
11261 break;
11262 case LD1SB_z_p_bi_s16:
11263 case LD1SB_z_p_bi_s32:
11264 case LD1SB_z_p_bi_s64:
11265 case LD1SH_z_p_bi_s32:
11266 case LD1SH_z_p_bi_s64:
11267 case LD1SW_z_p_bi_s64:
11268 is_signed = true;
11269 break;
11270 default:
11271 // This encoding group is complete, so no other values should be possible.
11272 VIXL_UNREACHABLE();
11273 is_signed = false;
11274 break;
11275 }
11276
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011277 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010011278 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11279 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011280 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
11281 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
11282 uint64_t offset =
11283 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011284 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011285 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011286 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11287 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011288 ReadPRegister(instr->GetPgLow8()),
11289 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011290 addr,
11291 is_signed);
11292}
11293
11294void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
11295 const Instruction* instr) {
11296 bool is_signed;
11297 USE(instr);
11298 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
11299 case LD1B_z_p_br_u8:
11300 case LD1B_z_p_br_u16:
11301 case LD1B_z_p_br_u32:
11302 case LD1B_z_p_br_u64:
11303 case LD1H_z_p_br_u16:
11304 case LD1H_z_p_br_u32:
11305 case LD1H_z_p_br_u64:
11306 case LD1W_z_p_br_u32:
11307 case LD1W_z_p_br_u64:
11308 case LD1D_z_p_br_u64:
11309 is_signed = false;
11310 break;
11311 case LD1SB_z_p_br_s16:
11312 case LD1SB_z_p_br_s32:
11313 case LD1SB_z_p_br_s64:
11314 case LD1SH_z_p_br_s32:
11315 case LD1SH_z_p_br_s64:
11316 case LD1SW_z_p_br_s64:
11317 is_signed = true;
11318 break;
11319 default:
11320 // This encoding group is complete, so no other values should be possible.
11321 VIXL_UNREACHABLE();
11322 is_signed = false;
11323 break;
11324 }
11325
11326 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11327 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11328 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11329 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11330 uint64_t offset = ReadXRegister(instr->GetRm());
11331 offset <<= msize_in_bytes_log2;
11332 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011333 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11334 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011335 ReadPRegister(instr->GetPgLow8()),
11336 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011337 addr,
11338 is_signed);
11339}
11340
Alexandre Ramesd3832962016-07-04 15:03:43 +010011341void Simulator::DoUnreachable(const Instruction* instr) {
11342 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11343 (instr->GetImmException() == kUnreachableOpcode));
11344
11345 fprintf(stream_,
11346 "Hit UNREACHABLE marker at pc=%p.\n",
11347 reinterpret_cast<const void*>(instr));
11348 abort();
11349}
11350
11351
11352void Simulator::DoTrace(const Instruction* instr) {
11353 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11354 (instr->GetImmException() == kTraceOpcode));
11355
11356 // Read the arguments encoded inline in the instruction stream.
11357 uint32_t parameters;
11358 uint32_t command;
11359
11360 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11361 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11362 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
11363
11364 switch (command) {
11365 case TRACE_ENABLE:
11366 SetTraceParameters(GetTraceParameters() | parameters);
11367 break;
11368 case TRACE_DISABLE:
11369 SetTraceParameters(GetTraceParameters() & ~parameters);
11370 break;
11371 default:
11372 VIXL_UNREACHABLE();
11373 }
11374
11375 WritePc(instr->GetInstructionAtOffset(kTraceLength));
11376}
11377
11378
11379void Simulator::DoLog(const Instruction* instr) {
11380 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11381 (instr->GetImmException() == kLogOpcode));
11382
11383 // Read the arguments encoded inline in the instruction stream.
11384 uint32_t parameters;
11385
11386 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11387 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11388
11389 // We don't support a one-shot LOG_DISASM.
11390 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
11391 // Print the requested information.
11392 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
11393 if (parameters & LOG_REGS) PrintRegisters();
11394 if (parameters & LOG_VREGS) PrintVRegisters();
11395
11396 WritePc(instr->GetInstructionAtOffset(kLogLength));
11397}
11398
11399
11400void Simulator::DoPrintf(const Instruction* instr) {
11401 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11402 (instr->GetImmException() == kPrintfOpcode));
11403
11404 // Read the arguments encoded inline in the instruction stream.
11405 uint32_t arg_count;
11406 uint32_t arg_pattern_list;
11407 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11408 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
11409 memcpy(&arg_pattern_list,
11410 instr + kPrintfArgPatternListOffset,
11411 sizeof(arg_pattern_list));
11412
11413 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
11414 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
11415
11416 // We need to call the host printf function with a set of arguments defined by
11417 // arg_pattern_list. Because we don't know the types and sizes of the
11418 // arguments, this is very difficult to do in a robust and portable way. To
11419 // work around the problem, we pick apart the format string, and print one
11420 // format placeholder at a time.
11421
11422 // Allocate space for the format string. We take a copy, so we can modify it.
11423 // Leave enough space for one extra character per expected argument (plus the
11424 // '\0' termination).
11425 const char* format_base = ReadRegister<const char*>(0);
11426 VIXL_ASSERT(format_base != NULL);
11427 size_t length = strlen(format_base) + 1;
11428 char* const format = new char[length + arg_count];
11429
11430 // A list of chunks, each with exactly one format placeholder.
11431 const char* chunks[kPrintfMaxArgCount];
11432
11433 // Copy the format string and search for format placeholders.
11434 uint32_t placeholder_count = 0;
11435 char* format_scratch = format;
11436 for (size_t i = 0; i < length; i++) {
11437 if (format_base[i] != '%') {
11438 *format_scratch++ = format_base[i];
11439 } else {
11440 if (format_base[i + 1] == '%') {
11441 // Ignore explicit "%%" sequences.
11442 *format_scratch++ = format_base[i];
11443 i++;
11444 // Chunks after the first are passed as format strings to printf, so we
11445 // need to escape '%' characters in those chunks.
11446 if (placeholder_count > 0) *format_scratch++ = format_base[i];
11447 } else {
11448 VIXL_CHECK(placeholder_count < arg_count);
11449 // Insert '\0' before placeholders, and store their locations.
11450 *format_scratch++ = '\0';
11451 chunks[placeholder_count++] = format_scratch;
11452 *format_scratch++ = format_base[i];
11453 }
11454 }
11455 }
11456 VIXL_CHECK(placeholder_count == arg_count);
11457
11458 // Finally, call printf with each chunk, passing the appropriate register
11459 // argument. Normally, printf returns the number of bytes transmitted, so we
11460 // can emulate a single printf call by adding the result from each chunk. If
11461 // any call returns a negative (error) value, though, just return that value.
11462
11463 printf("%s", clr_printf);
11464
11465 // Because '\0' is inserted before each placeholder, the first string in
11466 // 'format' contains no format placeholders and should be printed literally.
11467 int result = printf("%s", format);
11468 int pcs_r = 1; // Start at x1. x0 holds the format string.
11469 int pcs_f = 0; // Start at d0.
11470 if (result >= 0) {
11471 for (uint32_t i = 0; i < placeholder_count; i++) {
11472 int part_result = -1;
11473
11474 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
11475 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
11476 switch (arg_pattern) {
11477 case kPrintfArgW:
11478 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
11479 break;
11480 case kPrintfArgX:
11481 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
11482 break;
11483 case kPrintfArgD:
11484 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
11485 break;
11486 default:
11487 VIXL_UNREACHABLE();
11488 }
11489
11490 if (part_result < 0) {
11491 // Handle error values.
11492 result = part_result;
11493 break;
11494 }
11495
11496 result += part_result;
11497 }
11498 }
11499
11500 printf("%s", clr_normal);
11501
11502 // Printf returns its result in x0 (just like the C library's printf).
11503 WriteXRegister(0, result);
11504
11505 // The printf parameters are inlined in the code, so skip them.
11506 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
11507
11508 // Set LR as if we'd just called a native printf function.
11509 WriteLr(ReadPc());
11510
11511 delete[] format;
11512}
11513
Alexandre Rames064e02d2016-07-12 11:53:13 +010011514
Alexandre Ramesca73ba02016-07-28 09:16:03 +010011515#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010011516void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011517 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011518 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
11519 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011520 uintptr_t call_wrapper_address =
11521 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
11522 uintptr_t function_address =
11523 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080011524 RuntimeCallType call_type = static_cast<RuntimeCallType>(
11525 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011526 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010011527 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011528
11529 if (call_type == kCallRuntime) {
11530 WriteRegister(kLinkRegCode,
11531 instr->GetInstructionAtOffset(kRuntimeCallLength));
11532 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011533 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011534 // Read the return address from `lr` and write it into `pc`.
11535 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011536}
11537#else
11538void Simulator::DoRuntimeCall(const Instruction* instr) {
11539 USE(instr);
11540 VIXL_UNREACHABLE();
11541}
11542#endif
11543
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011544
11545void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
11546 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
11547
11548 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011549 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011550 std::numeric_limits<ElementType>::max());
11551
11552 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
11553
11554 size_t element_size = sizeof(ElementType);
11555 size_t offset = kConfigureCPUFeaturesListOffset;
11556
11557 // Read the kNone-terminated list of features.
11558 CPUFeatures parameters;
11559 while (true) {
11560 ElementType feature = Memory::Read<ElementType>(instr + offset);
11561 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011562 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011563 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
11564 }
11565
11566 switch (instr->GetImmException()) {
11567 case kSetCPUFeaturesOpcode:
11568 SetCPUFeatures(parameters);
11569 break;
11570 case kEnableCPUFeaturesOpcode:
11571 GetCPUFeatures()->Combine(parameters);
11572 break;
11573 case kDisableCPUFeaturesOpcode:
11574 GetCPUFeatures()->Remove(parameters);
11575 break;
11576 default:
11577 VIXL_UNREACHABLE();
11578 break;
11579 }
11580
11581 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
11582}
11583
11584
11585void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
11586 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11587 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
11588 USE(instr);
11589
11590 saved_cpu_features_.push_back(*GetCPUFeatures());
11591}
11592
11593
11594void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
11595 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11596 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
11597 USE(instr);
11598
11599 SetCPUFeatures(saved_cpu_features_.back());
11600 saved_cpu_features_.pop_back();
11601}
11602
11603
Alexandre Ramesd3832962016-07-04 15:03:43 +010011604} // namespace aarch64
11605} // namespace vixl
11606
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010011607#endif // VIXL_INCLUDE_SIMULATOR_AARCH64