blob: cd5a2d6cea3c6f46f13ff8991e5291e218cf4984 [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
Jacob Bramley85a9c102019-12-09 17:48:29 +000029#include <errno.h>
30#include <unistd.h>
31
Alexandre Ramesd3832962016-07-04 15:03:43 +010032#include <cmath>
Pierre Langlois1bce0072017-06-06 17:58:58 +010033#include <cstring>
Martyn Capewell5b24fb32016-11-02 18:52:55 +000034#include <limits>
Alexandre Ramesd3832962016-07-04 15:03:43 +010035
Alexandre Ramesb49bdb72016-09-26 12:08:57 +010036#include "simulator-aarch64.h"
Alexandre Ramesd3832962016-07-04 15:03:43 +010037
38namespace vixl {
39namespace aarch64 {
40
Jacob Bramleyca789742018-09-13 14:25:46 +010041using vixl::internal::SimFloat16;
42
Alexandre Ramesd3832962016-07-04 15:03:43 +010043const Instruction* Simulator::kEndOfSimAddress = NULL;
44
45void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
46 int width = msb - lsb + 1;
47 VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
48
49 bits <<= lsb;
50 uint32_t mask = ((1 << width) - 1) << lsb;
51 VIXL_ASSERT((mask & write_ignore_mask_) == 0);
52
53 value_ = (value_ & ~mask) | (bits & mask);
54}
55
56
57SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
58 switch (id) {
59 case NZCV:
60 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
61 case FPCR:
62 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
63 default:
64 VIXL_UNREACHABLE();
65 return SimSystemRegister();
66 }
67}
68
69
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +000070Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack)
71 : memory_(std::move(stack)),
72 movprfx_(NULL),
73 cpu_features_auditor_(decoder, CPUFeatures::All()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010074 // Ensure that shift operations act as the simulator expects.
75 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
76 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
77
Jacob Bramley85a9c102019-12-09 17:48:29 +000078 // Set up a dummy pipe for CanReadMemory.
79 VIXL_CHECK(pipe(dummy_pipe_fd_) == 0);
80
Alexandre Ramesd3832962016-07-04 15:03:43 +010081 // Set up the decoder.
82 decoder_ = decoder;
83 decoder_->AppendVisitor(this);
84
85 stream_ = stream;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010086
Alexandre Ramesd3832962016-07-04 15:03:43 +010087 print_disasm_ = new PrintDisassembler(stream_);
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010088 // The Simulator and Disassembler share the same available list, held by the
89 // auditor. The Disassembler only annotates instructions with features that
90 // are _not_ available, so registering the auditor should have no effect
91 // unless the simulator is about to abort (due to missing features). In
92 // practice, this means that with trace enabled, the simulator will crash just
93 // after the disassembler prints the instruction, with the missing features
94 // enumerated.
95 print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
96
Alexandre Ramesd3832962016-07-04 15:03:43 +010097 SetColouredTrace(false);
98 trace_parameters_ = LOG_NONE;
99
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100100 // We have to configure the SVE vector register length before calling
101 // ResetState().
102 SetVectorLengthInBits(kZRegMinSize);
103
Alexandre Ramesd3832962016-07-04 15:03:43 +0100104 ResetState();
105
Alexandre Ramesd3832962016-07-04 15:03:43 +0100106 // Print a warning about exclusive-access instructions, but only the first
107 // time they are encountered. This warning can be silenced using
108 // SilenceExclusiveAccessWarning().
109 print_exclusive_access_warning_ = true;
Martyn Capewellcb963f72018-10-22 15:25:28 +0100110
111 guard_pages_ = false;
TatWai Chong04edf682018-12-27 16:01:02 -0800112
113 // Initialize the common state of RNDR and RNDRRS.
114 uint16_t seed[3] = {11, 22, 33};
Jacob Bramley85a9c102019-12-09 17:48:29 +0000115 VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));
116 memcpy(rand_state_, seed, sizeof(rand_state_));
TatWai Chongb2d8d1f2019-10-21 15:19:31 -0700117
118 // Initialize all bits of pseudo predicate register to true.
119 LogicPRegister ones(pregister_all_true_);
120 ones.SetAllBits();
Alexandre Ramesd3832962016-07-04 15:03:43 +0100121}
122
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100123void Simulator::ResetSystemRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100124 // Reset the system registers.
125 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
126 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
TatWai Chong4023d7a2019-11-18 14:16:28 -0800127 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100128}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100129
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100130void Simulator::ResetRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100131 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
132 WriteXRegister(i, 0xbadbeef);
133 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100134 // Returning to address 0 exits the Simulator.
135 WriteLr(kEndOfSimAddress);
136}
Pierre Langlois23703a72016-08-15 17:23:39 +0100137
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100138void Simulator::ResetVRegisters() {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800139 // 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 +0100140 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
141 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
TatWai Chonge3d059b2019-02-27 15:04:51 -0800142 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100143 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100144 vregisters_[i].NotifyAccessAsZ();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100145 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800146 // Encode the register number and (D-sized) lane into each NaN, to
147 // make them easier to trace.
148 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
149 (0x0000000000000001 * lane);
150 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
151 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100152 vregisters_[i].Insert(lane, nan_bits);
TatWai Chonge3d059b2019-02-27 15:04:51 -0800153 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100154 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100155}
TatWai Chonge3d059b2019-02-27 15:04:51 -0800156
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100157void Simulator::ResetPRegisters() {
158 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
159 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
160 // Ensure the register configuration fits in this bit encoding.
161 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
162 VIXL_ASSERT(lane_count <= UINT8_MAX);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700163 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100164 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
165 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge0590cc2019-03-18 16:23:59 -0700166 // Encode the register number and (H-sized) lane into each lane slot.
167 uint16_t bits = (0x0100 * lane) | i;
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100168 pregisters_[i].Insert(lane, bits);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700169 }
170 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100171}
TatWai Chonge0590cc2019-03-18 16:23:59 -0700172
TatWai Chong4023d7a2019-11-18 14:16:28 -0800173void Simulator::ResetFFR() {
174 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
175 int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
176 ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
177}
178
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100179void Simulator::ResetState() {
180 ResetSystemRegisters();
181 ResetRegisters();
182 ResetVRegisters();
183 ResetPRegisters();
Martyn Capewellcb963f72018-10-22 15:25:28 +0100184
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +0000185 WriteSp(memory_.GetStack().GetBase());
186
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100187 pc_ = NULL;
188 pc_modified_ = false;
189
190 // BTI state.
Martyn Capewellcb963f72018-10-22 15:25:28 +0100191 btype_ = DefaultBType;
192 next_btype_ = DefaultBType;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100193}
194
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100195void Simulator::SetVectorLengthInBits(unsigned vector_length) {
196 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
197 (vector_length <= kZRegMaxSize));
198 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
199 vector_length_ = vector_length;
200
201 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
202 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
203 }
204 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
205 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
206 }
207
TatWai Chong4023d7a2019-11-18 14:16:28 -0800208 ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
209
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100210 ResetVRegisters();
211 ResetPRegisters();
TatWai Chong4023d7a2019-11-18 14:16:28 -0800212 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100213}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100214
215Simulator::~Simulator() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100216 // The decoder may outlive the simulator.
217 decoder_->RemoveVisitor(print_disasm_);
218 delete print_disasm_;
Jacob Bramley85a9c102019-12-09 17:48:29 +0000219 close(dummy_pipe_fd_[0]);
220 close(dummy_pipe_fd_[1]);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100221}
222
223
224void Simulator::Run() {
225 // Flush any written registers before executing anything, so that
226 // manually-set registers are logged _before_ the first instruction.
227 LogAllWrittenRegisters();
228
229 while (pc_ != kEndOfSimAddress) {
230 ExecuteInstruction();
231 }
232}
233
234
235void Simulator::RunFrom(const Instruction* first) {
Jacob Bramleye79723a2016-06-07 17:50:47 +0100236 WritePc(first, NoBranchLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100237 Run();
238}
239
240
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100241// clang-format off
Alexandre Ramesd3832962016-07-04 15:03:43 +0100242const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
243 "x6", "x7", "x8", "x9", "x10", "x11",
244 "x12", "x13", "x14", "x15", "x16", "x17",
245 "x18", "x19", "x20", "x21", "x22", "x23",
246 "x24", "x25", "x26", "x27", "x28", "x29",
247 "lr", "xzr", "sp"};
248
249const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
250 "w6", "w7", "w8", "w9", "w10", "w11",
251 "w12", "w13", "w14", "w15", "w16", "w17",
252 "w18", "w19", "w20", "w21", "w22", "w23",
253 "w24", "w25", "w26", "w27", "w28", "w29",
254 "w30", "wzr", "wsp"};
255
Jacob Bramley423e5422019-11-13 19:15:55 +0000256const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",
257 "b6", "b7", "b8", "b9", "b10", "b11",
258 "b12", "b13", "b14", "b15", "b16", "b17",
259 "b18", "b19", "b20", "b21", "b22", "b23",
260 "b24", "b25", "b26", "b27", "b28", "b29",
261 "b30", "b31"};
262
Carey Williamsd8bb3572018-04-10 11:58:07 +0100263const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
264 "h6", "h7", "h8", "h9", "h10", "h11",
265 "h12", "h13", "h14", "h15", "h16", "h17",
266 "h18", "h19", "h20", "h21", "h22", "h23",
267 "h24", "h25", "h26", "h27", "h28", "h29",
268 "h30", "h31"};
269
Alexandre Ramesd3832962016-07-04 15:03:43 +0100270const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
271 "s6", "s7", "s8", "s9", "s10", "s11",
272 "s12", "s13", "s14", "s15", "s16", "s17",
273 "s18", "s19", "s20", "s21", "s22", "s23",
274 "s24", "s25", "s26", "s27", "s28", "s29",
275 "s30", "s31"};
276
277const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
278 "d6", "d7", "d8", "d9", "d10", "d11",
279 "d12", "d13", "d14", "d15", "d16", "d17",
280 "d18", "d19", "d20", "d21", "d22", "d23",
281 "d24", "d25", "d26", "d27", "d28", "d29",
282 "d30", "d31"};
283
284const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
285 "v6", "v7", "v8", "v9", "v10", "v11",
286 "v12", "v13", "v14", "v15", "v16", "v17",
287 "v18", "v19", "v20", "v21", "v22", "v23",
288 "v24", "v25", "v26", "v27", "v28", "v29",
289 "v30", "v31"};
290
TatWai Chong72d2e562019-05-16 11:22:22 -0700291const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
292 "z6", "z7", "z8", "z9", "z10", "z11",
293 "z12", "z13", "z14", "z15", "z16", "z17",
294 "z18", "z19", "z20", "z21", "z22", "z23",
295 "z24", "z25", "z26", "z27", "z28", "z29",
296 "z30", "z31"};
297
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100298const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
299 "p6", "p7", "p8", "p9", "p10", "p11",
300 "p12", "p13", "p14", "p15"};
301// clang-format on
302
Alexandre Ramesd3832962016-07-04 15:03:43 +0100303
304const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100305 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000306 if ((code == kSPRegInternalCode) ||
307 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100308 code = kZeroRegCode + 1;
309 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000310 VIXL_ASSERT(code < ArrayLength(wreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100311 return wreg_names[code];
312}
313
314
315const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100316 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000317 if ((code == kSPRegInternalCode) ||
318 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100319 code = kZeroRegCode + 1;
320 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000321 VIXL_ASSERT(code < ArrayLength(xreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100322 return xreg_names[code];
323}
324
325
Jacob Bramley423e5422019-11-13 19:15:55 +0000326const char* Simulator::BRegNameForCode(unsigned code) {
327 VIXL_ASSERT(code < kNumberOfVRegisters);
328 return breg_names[code];
329}
330
331
Carey Williamsd8bb3572018-04-10 11:58:07 +0100332const char* Simulator::HRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100333 VIXL_ASSERT(code < kNumberOfVRegisters);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100334 return hreg_names[code];
335}
336
337
Alexandre Ramesd3832962016-07-04 15:03:43 +0100338const char* Simulator::SRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100339 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100340 return sreg_names[code];
341}
342
343
344const char* Simulator::DRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100345 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100346 return dreg_names[code];
347}
348
349
350const char* Simulator::VRegNameForCode(unsigned code) {
351 VIXL_ASSERT(code < kNumberOfVRegisters);
352 return vreg_names[code];
353}
354
355
TatWai Chong72d2e562019-05-16 11:22:22 -0700356const char* Simulator::ZRegNameForCode(unsigned code) {
357 VIXL_ASSERT(code < kNumberOfZRegisters);
358 return zreg_names[code];
359}
360
361
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100362const char* Simulator::PRegNameForCode(unsigned code) {
363 VIXL_ASSERT(code < kNumberOfPRegisters);
364 return preg_names[code];
365}
366
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000367SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
368 SimVRegister ones, result;
369 dup_immediate(kFormatVnB, ones, 0xff);
370 mov_zeroing(kFormatVnB, result, pg, ones);
371 return result;
372}
373
TatWai Chong47c26842020-02-10 01:51:32 -0800374void Simulator::ExtractFromSimVRegister(VectorFormat vform,
375 SimPRegister& pd,
376 SimVRegister vreg) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000377 SimVRegister zero;
378 dup_immediate(kFormatVnB, zero, 0);
379 SVEIntCompareVectorsHelper(ne,
TatWai Chong47c26842020-02-10 01:51:32 -0800380 vform,
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000381 pd,
382 GetPTrue(),
383 vreg,
384 zero,
385 false,
386 LeaveFlags);
387}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100388
Alexandre Ramesd3832962016-07-04 15:03:43 +0100389#define COLOUR(colour_code) "\033[0;" colour_code "m"
390#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
Jacob Bramleye79723a2016-06-07 17:50:47 +0100391#define COLOUR_HIGHLIGHT "\033[43m"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100392#define NORMAL ""
393#define GREY "30"
394#define RED "31"
395#define GREEN "32"
396#define YELLOW "33"
397#define BLUE "34"
398#define MAGENTA "35"
399#define CYAN "36"
400#define WHITE "37"
401void Simulator::SetColouredTrace(bool value) {
402 coloured_trace_ = value;
403
404 clr_normal = value ? COLOUR(NORMAL) : "";
405 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
406 clr_flag_value = value ? COLOUR(NORMAL) : "";
407 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
408 clr_reg_value = value ? COLOUR(CYAN) : "";
409 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
410 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100411 clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
412 clr_preg_value = value ? COLOUR(GREEN) : "";
Alexandre Ramesd3832962016-07-04 15:03:43 +0100413 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
414 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
415 clr_warning_message = value ? COLOUR(YELLOW) : "";
416 clr_printf = value ? COLOUR(GREEN) : "";
Jacob Bramleye79723a2016-06-07 17:50:47 +0100417 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100418
419 if (value) {
420 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
421 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
422 } else {
423 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
424 print_disasm_->SetCPUFeaturesSuffix("");
425 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100426}
427
428
429void Simulator::SetTraceParameters(int parameters) {
430 bool disasm_before = trace_parameters_ & LOG_DISASM;
431 trace_parameters_ = parameters;
432 bool disasm_after = trace_parameters_ & LOG_DISASM;
433
434 if (disasm_before != disasm_after) {
435 if (disasm_after) {
436 decoder_->InsertVisitorBefore(print_disasm_, this);
437 } else {
438 decoder_->RemoveVisitor(print_disasm_);
439 }
440 }
441}
442
443
Alexandre Ramesd3832962016-07-04 15:03:43 +0100444// Helpers ---------------------------------------------------------------------
445uint64_t Simulator::AddWithCarry(unsigned reg_size,
446 bool set_flags,
447 uint64_t left,
448 uint64_t right,
449 int carry_in) {
450 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
451 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
452
453 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
454 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
455 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
456
457 left &= reg_mask;
458 right &= reg_mask;
459 uint64_t result = (left + right + carry_in) & reg_mask;
460
461 if (set_flags) {
462 ReadNzcv().SetN(CalcNFlag(result, reg_size));
463 ReadNzcv().SetZ(CalcZFlag(result));
464
465 // Compute the C flag by comparing the result to the max unsigned integer.
466 uint64_t max_uint_2op = max_uint - carry_in;
467 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
468 ReadNzcv().SetC(C ? 1 : 0);
469
470 // Overflow iff the sign bit is the same for the two inputs and different
471 // for the result.
472 uint64_t left_sign = left & sign_mask;
473 uint64_t right_sign = right & sign_mask;
474 uint64_t result_sign = result & sign_mask;
475 bool V = (left_sign == right_sign) && (left_sign != result_sign);
476 ReadNzcv().SetV(V ? 1 : 0);
477
478 LogSystemRegister(NZCV);
479 }
480 return result;
481}
482
483
484int64_t Simulator::ShiftOperand(unsigned reg_size,
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000485 uint64_t uvalue,
Alexandre Ramesd3832962016-07-04 15:03:43 +0100486 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100487 unsigned amount) const {
TatWai Chong29a0c432019-11-06 22:20:44 -0800488 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
489 (reg_size == kSRegSize) || (reg_size == kDRegSize));
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000490 if (amount > 0) {
491 uint64_t mask = GetUintMask(reg_size);
492 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
493 // The behavior is undefined in c++ if the shift amount greater than or
494 // equal to the register lane size. Work out the shifted result based on
495 // architectural behavior before performing the c++ type shfit operations.
496 switch (shift_type) {
497 case LSL:
498 if (amount >= reg_size) {
499 return UINT64_C(0);
500 }
501 uvalue <<= amount;
502 break;
503 case LSR:
504 if (amount >= reg_size) {
505 return UINT64_C(0);
506 }
507 uvalue >>= amount;
508 break;
509 case ASR:
510 if (amount >= reg_size) {
511 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
512 }
513 uvalue >>= amount;
514 if (is_negative) {
515 // Simulate sign-extension to 64 bits.
516 uvalue |= ~UINT64_C(0) << (reg_size - amount);
517 }
518 break;
519 case ROR: {
520 uvalue = RotateRight(uvalue, amount, reg_size);
521 break;
TatWai Chong29a0c432019-11-06 22:20:44 -0800522 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000523 default:
524 VIXL_UNIMPLEMENTED();
525 return 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100526 }
Martyn Capewell3bf2d162020-02-17 15:04:36 +0000527 uvalue &= mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100528 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000529
530 int64_t result;
531 memcpy(&result, &uvalue, sizeof(result));
532 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100533}
534
535
536int64_t Simulator::ExtendValue(unsigned reg_size,
537 int64_t value,
538 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100539 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100540 switch (extend_type) {
541 case UXTB:
542 value &= kByteMask;
543 break;
544 case UXTH:
545 value &= kHalfWordMask;
546 break;
547 case UXTW:
548 value &= kWordMask;
549 break;
550 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000551 value &= kByteMask;
552 if ((value & 0x80) != 0) {
553 value |= ~UINT64_C(0) << 8;
554 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100555 break;
556 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000557 value &= kHalfWordMask;
558 if ((value & 0x8000) != 0) {
559 value |= ~UINT64_C(0) << 16;
560 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100561 break;
562 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000563 value &= kWordMask;
564 if ((value & 0x80000000) != 0) {
565 value |= ~UINT64_C(0) << 32;
566 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100567 break;
568 case UXTX:
569 case SXTX:
570 break;
571 default:
572 VIXL_UNREACHABLE();
573 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000574 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100575}
576
577
578void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
579 AssertSupportedFPCR();
580
581 // TODO: This assumes that the C++ implementation handles comparisons in the
582 // way that we expect (as per AssertSupportedFPCR()).
583 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100584 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100585 ReadNzcv().SetRawValue(FPUnorderedFlag);
586 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
587 (trap == EnableTrap)) {
588 process_exception = true;
589 }
590 } else if (val0 < val1) {
591 ReadNzcv().SetRawValue(FPLessThanFlag);
592 } else if (val0 > val1) {
593 ReadNzcv().SetRawValue(FPGreaterThanFlag);
594 } else if (val0 == val1) {
595 ReadNzcv().SetRawValue(FPEqualFlag);
596 } else {
597 VIXL_UNREACHABLE();
598 }
599 LogSystemRegister(NZCV);
600 if (process_exception) FPProcessException();
601}
602
603
Alexandre Rames868bfc42016-07-19 17:10:48 +0100604uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
605 VIXL_ASSERT(mem_op.IsValid());
606 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
607 if (mem_op.IsImmediateOffset()) {
608 return base + mem_op.GetOffset();
609 } else {
610 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
611 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100612 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100613 if (mem_op.GetShift() != NO_SHIFT) {
614 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
615 }
616 if (mem_op.GetExtend() != NO_EXTEND) {
617 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
618 }
619 return static_cast<uint64_t>(base + offset);
620 }
621}
622
623
Alexandre Ramesd3832962016-07-04 15:03:43 +0100624Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
625 unsigned reg_size, unsigned lane_size) {
626 VIXL_ASSERT(reg_size >= lane_size);
627
628 uint32_t format = 0;
629 if (reg_size != lane_size) {
630 switch (reg_size) {
631 default:
632 VIXL_UNREACHABLE();
633 break;
634 case kQRegSizeInBytes:
635 format = kPrintRegAsQVector;
636 break;
637 case kDRegSizeInBytes:
638 format = kPrintRegAsDVector;
639 break;
640 }
641 }
642
643 switch (lane_size) {
644 default:
645 VIXL_UNREACHABLE();
646 break;
647 case kQRegSizeInBytes:
648 format |= kPrintReg1Q;
649 break;
650 case kDRegSizeInBytes:
651 format |= kPrintReg1D;
652 break;
653 case kSRegSizeInBytes:
654 format |= kPrintReg1S;
655 break;
656 case kHRegSizeInBytes:
657 format |= kPrintReg1H;
658 break;
659 case kBRegSizeInBytes:
660 format |= kPrintReg1B;
661 break;
662 }
663 // These sizes would be duplicate case labels.
664 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
665 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
666 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
667 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
668
669 return static_cast<PrintRegisterFormat>(format);
670}
671
672
673Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
674 VectorFormat vform) {
675 switch (vform) {
676 default:
677 VIXL_UNREACHABLE();
678 return kPrintReg16B;
679 case kFormat16B:
680 return kPrintReg16B;
681 case kFormat8B:
682 return kPrintReg8B;
683 case kFormat8H:
684 return kPrintReg8H;
685 case kFormat4H:
686 return kPrintReg4H;
687 case kFormat4S:
688 return kPrintReg4S;
689 case kFormat2S:
690 return kPrintReg2S;
691 case kFormat2D:
692 return kPrintReg2D;
693 case kFormat1D:
694 return kPrintReg1D;
695
696 case kFormatB:
697 return kPrintReg1B;
698 case kFormatH:
699 return kPrintReg1H;
700 case kFormatS:
701 return kPrintReg1S;
702 case kFormatD:
703 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +0100704
705 case kFormatVnB:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000706 return kPrintRegVnB;
Jacob Bramleye668b202019-08-14 17:57:34 +0100707 case kFormatVnH:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000708 return kPrintRegVnH;
Jacob Bramleye668b202019-08-14 17:57:34 +0100709 case kFormatVnS:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000710 return kPrintRegVnS;
Jacob Bramleye668b202019-08-14 17:57:34 +0100711 case kFormatVnD:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000712 return kPrintRegVnD;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100713 }
714}
715
716
717Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
718 VectorFormat vform) {
719 switch (vform) {
720 default:
721 VIXL_UNREACHABLE();
722 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100723 case kFormat8H:
724 return kPrintReg8HFP;
725 case kFormat4H:
726 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100727 case kFormat4S:
728 return kPrintReg4SFP;
729 case kFormat2S:
730 return kPrintReg2SFP;
731 case kFormat2D:
732 return kPrintReg2DFP;
733 case kFormat1D:
734 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100735 case kFormatH:
736 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100737 case kFormatS:
738 return kPrintReg1SFP;
739 case kFormatD:
740 return kPrintReg1DFP;
741 }
742}
743
Jacob Bramley423e5422019-11-13 19:15:55 +0000744void Simulator::PrintRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100745 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
Jacob Bramley423e5422019-11-13 19:15:55 +0000746 if (i == kSpRegCode) i = kSPRegInternalCode;
747 PrintRegister(i);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100748 }
749}
750
Jacob Bramley423e5422019-11-13 19:15:55 +0000751void Simulator::PrintVRegisters() {
752 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
753 PrintVRegister(i);
754 }
755}
756
757void Simulator::PrintZRegisters() {
758 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
759 PrintZRegister(i);
760 }
761}
762
763void Simulator::PrintWrittenRegisters() {
764 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
765 if (registers_[i].WrittenSinceLastLog()) {
766 if (i == kSpRegCode) i = kSPRegInternalCode;
767 PrintRegister(i);
768 }
769 }
770}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100771
772void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100773 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100774 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100775 if (vregisters_[i].WrittenSinceLastLog()) {
776 // Z registers are initialised in the constructor before the user can
777 // configure the CPU features, so we must also check for SVE here.
778 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
779 PrintZRegister(i);
780 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +0000781 PrintVRegister(i);
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100782 }
783 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100784 }
785}
786
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100787void Simulator::PrintWrittenPRegisters() {
788 // P registers are initialised in the constructor before the user can
789 // configure the CPU features, so we must check for SVE here.
790 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
791 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
792 if (pregisters_[i].WrittenSinceLastLog()) {
793 PrintPRegister(i);
794 }
795 }
Jacob Bramley0d754e92020-06-18 10:59:09 +0100796 if (ReadFFR().WrittenSinceLastLog()) PrintFFR();
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100797}
798
Alexandre Ramesd3832962016-07-04 15:03:43 +0100799void Simulator::PrintSystemRegisters() {
800 PrintSystemRegister(NZCV);
801 PrintSystemRegister(FPCR);
802}
803
Jacob Bramley423e5422019-11-13 19:15:55 +0000804void Simulator::PrintRegisterValue(const uint8_t* value,
805 int value_size,
806 PrintRegisterFormat format) {
807 int print_width = GetPrintRegSizeInBytes(format);
808 VIXL_ASSERT(print_width <= value_size);
809 for (int i = value_size - 1; i >= print_width; i--) {
810 // Pad with spaces so that values align vertically.
Alexandre Ramesd3832962016-07-04 15:03:43 +0100811 fprintf(stream_, " ");
Jacob Bramley423e5422019-11-13 19:15:55 +0000812 // If we aren't explicitly printing a partial value, ensure that the
813 // unprinted bits are zero.
814 VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100815 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100816 fprintf(stream_, "0x");
Jacob Bramley423e5422019-11-13 19:15:55 +0000817 for (int i = print_width - 1; i >= 0; i--) {
818 fprintf(stream_, "%02x", value[i]);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100819 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100820}
821
Jacob Bramley423e5422019-11-13 19:15:55 +0000822void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
823 uint16_t lane_mask,
824 PrintRegisterFormat format) {
825 VIXL_ASSERT((format & kPrintRegAsFP) != 0);
826 int lane_size = GetPrintRegLaneSizeInBytes(format);
827 fprintf(stream_, " (");
828 bool last_inactive = false;
829 const char* sep = "";
830 for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
831 bool access = (lane_mask & (1 << (i * lane_size))) != 0;
832 if (access) {
833 // Read the lane as a double, so we can format all FP types in the same
834 // way. We squash NaNs, and a double can exactly represent any other value
835 // that the smaller types can represent, so this is lossless.
836 double element;
837 switch (lane_size) {
838 case kHRegSizeInBytes: {
839 Float16 element_fp16;
840 VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
841 memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
842 element = FPToDouble(element_fp16, kUseDefaultNaN);
843 break;
844 }
845 case kSRegSizeInBytes: {
846 float element_fp32;
847 memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
848 element = static_cast<double>(element_fp32);
849 break;
850 }
851 case kDRegSizeInBytes: {
852 memcpy(&element, &value[i * lane_size], sizeof(element));
853 break;
854 }
855 default:
856 VIXL_UNREACHABLE();
857 fprintf(stream_, "{UnknownFPValue}");
858 continue;
859 }
860 if (IsNaN(element)) {
861 // The fprintf behaviour for NaNs is implementation-defined. Always
862 // print "nan", so that traces are consistent.
863 fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
864 } else {
865 fprintf(stream_,
866 "%s%s%#.4g%s",
867 sep,
868 clr_vreg_value,
869 element,
870 clr_normal);
871 }
872 last_inactive = false;
873 } else if (!last_inactive) {
874 // Replace each contiguous sequence of inactive lanes with "...".
875 fprintf(stream_, "%s...", sep);
876 last_inactive = true;
877 }
878 }
879 fprintf(stream_, ")");
880}
881
882void Simulator::PrintRegister(int code,
883 PrintRegisterFormat format,
884 const char* suffix) {
885 VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
886 (static_cast<unsigned>(code) == kSPRegInternalCode));
887 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
888 VIXL_ASSERT((format & kPrintRegAsFP) == 0);
889
890 SimRegister* reg;
891 SimRegister zero;
892 if (code == kZeroRegCode) {
893 reg = &zero;
894 } else {
895 // registers_[31] holds the SP.
896 VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
897 reg = &registers_[code % kNumberOfRegisters];
898 }
899
900 // We trace register writes as whole register values, implying that any
901 // unprinted bits are all zero:
902 // "# x{code}: 0x{-----value----}"
903 // "# w{code}: 0x{-value}"
904 // Stores trace partial register values, implying nothing about the unprinted
905 // bits:
906 // "# x{code}<63:0>: 0x{-----value----}"
907 // "# x{code}<31:0>: 0x{-value}"
908 // "# x{code}<15:0>: 0x{--}"
909 // "# x{code}<7:0>: 0x{}"
910
911 bool is_partial = (format & kPrintRegPartial) != 0;
912 unsigned print_reg_size = GetPrintRegSizeInBits(format);
913 std::stringstream name;
914 if (is_partial) {
915 name << XRegNameForCode(code) << GetPartialRegSuffix(format);
916 } else {
917 // Notify the register that it has been logged, but only if we're printing
918 // all of it.
919 reg->NotifyRegisterLogged();
920 switch (print_reg_size) {
921 case kWRegSize:
922 name << WRegNameForCode(code);
923 break;
924 case kXRegSize:
925 name << XRegNameForCode(code);
926 break;
927 default:
928 VIXL_UNREACHABLE();
929 return;
930 }
931 }
932
933 fprintf(stream_,
934 "# %s%*s: %s",
935 clr_reg_name,
936 kPrintRegisterNameFieldWidth,
937 name.str().c_str(),
938 clr_reg_value);
939 PrintRegisterValue(*reg, format);
940 fprintf(stream_, "%s%s", clr_normal, suffix);
941}
942
943void Simulator::PrintVRegister(int code,
944 PrintRegisterFormat format,
945 const char* suffix) {
946 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
947 VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
948 ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
949 ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
950
951 // We trace register writes as whole register values, implying that any
952 // unprinted bits are all zero:
953 // "# v{code}: 0x{-------------value------------}"
954 // "# d{code}: 0x{-----value----}"
955 // "# s{code}: 0x{-value}"
956 // "# h{code}: 0x{--}"
957 // "# b{code}: 0x{}"
958 // Stores trace partial register values, implying nothing about the unprinted
959 // bits:
960 // "# v{code}<127:0>: 0x{-------------value------------}"
961 // "# v{code}<63:0>: 0x{-----value----}"
962 // "# v{code}<31:0>: 0x{-value}"
963 // "# v{code}<15:0>: 0x{--}"
964 // "# v{code}<7:0>: 0x{}"
965
966 bool is_partial = ((format & kPrintRegPartial) != 0);
967 std::stringstream name;
968 unsigned print_reg_size = GetPrintRegSizeInBits(format);
969 if (is_partial) {
970 name << VRegNameForCode(code) << GetPartialRegSuffix(format);
971 } else {
972 // Notify the register that it has been logged, but only if we're printing
973 // all of it.
974 vregisters_[code].NotifyRegisterLogged();
975 switch (print_reg_size) {
976 case kBRegSize:
977 name << BRegNameForCode(code);
978 break;
979 case kHRegSize:
980 name << HRegNameForCode(code);
981 break;
982 case kSRegSize:
983 name << SRegNameForCode(code);
984 break;
985 case kDRegSize:
986 name << DRegNameForCode(code);
987 break;
988 case kQRegSize:
989 name << VRegNameForCode(code);
990 break;
991 default:
992 VIXL_UNREACHABLE();
993 return;
994 }
995 }
996
997 fprintf(stream_,
998 "# %s%*s: %s",
999 clr_vreg_name,
1000 kPrintRegisterNameFieldWidth,
1001 name.str().c_str(),
1002 clr_vreg_value);
1003 PrintRegisterValue(vregisters_[code], format);
1004 fprintf(stream_, "%s", clr_normal);
1005 if ((format & kPrintRegAsFP) != 0) {
1006 PrintRegisterValueFPAnnotations(vregisters_[code], format);
1007 }
1008 fprintf(stream_, "%s", suffix);
1009}
1010
1011void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1012 int reg_count,
1013 uint16_t focus_mask,
1014 PrintRegisterFormat format) {
1015 bool print_fp = (format & kPrintRegAsFP) != 0;
1016 // Suppress FP formatting, so we can specify the lanes we're interested in.
1017 PrintRegisterFormat format_no_fp =
1018 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1019
1020 for (int r = 0; r < reg_count; r++) {
1021 int code = (rt_code + r) % kNumberOfVRegisters;
1022 PrintVRegister(code, format_no_fp, "");
1023 if (print_fp) {
1024 PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1025 }
1026 fprintf(stream_, "\n");
1027 }
1028}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001029
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001030void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1031 int q_index,
1032 int reg_count,
1033 uint16_t focus_mask,
1034 PrintRegisterFormat format) {
1035 bool print_fp = (format & kPrintRegAsFP) != 0;
1036 // Suppress FP formatting, so we can specify the lanes we're interested in.
1037 PrintRegisterFormat format_no_fp =
1038 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
TatWai Chong72d2e562019-05-16 11:22:22 -07001039
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001040 PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
TatWai Chong72d2e562019-05-16 11:22:22 -07001041
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001042 const unsigned size = kQRegSizeInBytes;
1043 unsigned byte_index = q_index * size;
1044 const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1045 VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
TatWai Chong72d2e562019-05-16 11:22:22 -07001046
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001047 for (int r = 0; r < reg_count; r++) {
1048 int code = (rt_code + r) % kNumberOfZRegisters;
1049 PrintPartialZRegister(code, q_index, format_no_fp, "");
1050 if (print_fp) {
1051 PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
TatWai Chong72d2e562019-05-16 11:22:22 -07001052 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001053 fprintf(stream_, "\n");
TatWai Chong72d2e562019-05-16 11:22:22 -07001054 }
TatWai Chong72d2e562019-05-16 11:22:22 -07001055}
1056
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001057void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1058 // We're going to print the register in parts, so force a partial format.
1059 format = GetPrintRegPartial(format);
1060 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1061 int vl = GetVectorLengthInBits();
1062 VIXL_ASSERT((vl % kQRegSize) == 0);
1063 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1064 PrintPartialZRegister(code, i, format);
1065 }
1066 vregisters_[code].NotifyRegisterLogged();
1067}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001068
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001069void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1070 // We're going to print the register in parts, so force a partial format.
1071 format = GetPrintRegPartial(format);
1072 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1073 int vl = GetVectorLengthInBits();
1074 VIXL_ASSERT((vl % kQRegSize) == 0);
1075 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1076 PrintPartialPRegister(code, i, format);
1077 }
1078 pregisters_[code].NotifyRegisterLogged();
1079}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001080
Jacob Bramley0d754e92020-06-18 10:59:09 +01001081void Simulator::PrintFFR(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 SimPRegister& ffr = ReadFFR();
1088 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1089 PrintPartialPRegister("FFR", ffr, i, format);
1090 }
1091 ffr.NotifyRegisterLogged();
1092}
1093
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001094void Simulator::PrintPartialZRegister(int code,
1095 int q_index,
1096 PrintRegisterFormat format,
1097 const char* suffix) {
1098 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1099 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1100 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1101 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001102
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001103 // We _only_ trace partial Z register values in Q-sized chunks, because
1104 // they're often too large to reasonably fit on a single line. Each line
1105 // implies nothing about the unprinted bits.
1106 // "# z{code}<127:0>: 0x{-------------value------------}"
1107
1108 format = GetPrintRegAsQChunkOfSVE(format);
1109
1110 const unsigned size = kQRegSizeInBytes;
1111 unsigned byte_index = q_index * size;
1112 const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1113 VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1114
1115 int lsb = q_index * kQRegSize;
1116 int msb = lsb + kQRegSize - 1;
1117 std::stringstream name;
1118 name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001119
1120 fprintf(stream_,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001121 "# %s%*s: %s",
1122 clr_vreg_name,
1123 kPrintRegisterNameFieldWidth,
1124 name.str().c_str(),
1125 clr_vreg_value);
1126 PrintRegisterValue(value, size, format);
1127 fprintf(stream_, "%s", clr_normal);
1128 if ((format & kPrintRegAsFP) != 0) {
1129 PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1130 }
1131 fprintf(stream_, "%s", suffix);
1132}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001133
Jacob Bramley0d754e92020-06-18 10:59:09 +01001134void Simulator::PrintPartialPRegister(const char* name,
1135 const SimPRegister& reg,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001136 int q_index,
1137 PrintRegisterFormat format,
1138 const char* suffix) {
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001139 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1140 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1141 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1142
1143 // We don't currently use the format for anything here.
1144 USE(format);
1145
1146 // We _only_ trace partial P register values, because they're often too large
1147 // to reasonably fit on a single line. Each line implies nothing about the
1148 // unprinted bits.
1149 //
1150 // We print values in binary, with spaces between each bit, in order for the
1151 // bits to align with the Z register bytes that they predicate.
Jacob Bramley0d754e92020-06-18 10:59:09 +01001152 // "# {name}<15:0>: 0b{-------------value------------}"
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001153
1154 int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1155 int lsb = q_index * print_size_in_bits;
1156 int msb = lsb + print_size_in_bits - 1;
Jacob Bramley0d754e92020-06-18 10:59:09 +01001157 std::stringstream prefix;
1158 prefix << name << '<' << msb << ':' << lsb << '>';
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001159
1160 fprintf(stream_,
1161 "# %s%*s: %s0b",
1162 clr_preg_name,
1163 kPrintRegisterNameFieldWidth,
Jacob Bramley0d754e92020-06-18 10:59:09 +01001164 prefix.str().c_str(),
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001165 clr_preg_value);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001166 for (int i = msb; i >= lsb; i--) {
Jacob Bramley0d754e92020-06-18 10:59:09 +01001167 fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001168 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001169 fprintf(stream_, "%s%s", clr_normal, suffix);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001170}
1171
Jacob Bramley0d754e92020-06-18 10:59:09 +01001172void Simulator::PrintPartialPRegister(int code,
1173 int q_index,
1174 PrintRegisterFormat format,
1175 const char* suffix) {
1176 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1177 PrintPartialPRegister(PRegNameForCode(code),
1178 pregisters_[code],
1179 q_index,
1180 format,
1181 suffix);
1182}
1183
Alexandre Ramesd3832962016-07-04 15:03:43 +01001184void Simulator::PrintSystemRegister(SystemRegister id) {
1185 switch (id) {
1186 case NZCV:
1187 fprintf(stream_,
1188 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1189 clr_flag_name,
1190 clr_flag_value,
1191 ReadNzcv().GetN(),
1192 ReadNzcv().GetZ(),
1193 ReadNzcv().GetC(),
1194 ReadNzcv().GetV(),
1195 clr_normal);
1196 break;
1197 case FPCR: {
1198 static const char* rmode[] = {"0b00 (Round to Nearest)",
1199 "0b01 (Round towards Plus Infinity)",
1200 "0b10 (Round towards Minus Infinity)",
1201 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001202 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001203 fprintf(stream_,
1204 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1205 clr_flag_name,
1206 clr_flag_value,
1207 ReadFpcr().GetAHP(),
1208 ReadFpcr().GetDN(),
1209 ReadFpcr().GetFZ(),
1210 rmode[ReadFpcr().GetRMode()],
1211 clr_normal);
1212 break;
1213 }
1214 default:
1215 VIXL_UNREACHABLE();
1216 }
1217}
1218
Jacob Bramley423e5422019-11-13 19:15:55 +00001219uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1220 uint16_t future_access_mask,
1221 int struct_element_count,
1222 int lane_size_in_bytes,
1223 const char* op,
1224 uintptr_t address,
1225 int reg_size_in_bytes) {
1226 // We want to assume that we'll access at least one lane.
1227 VIXL_ASSERT(access_mask != 0);
1228 VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1229 (reg_size_in_bytes == kQRegSizeInBytes));
1230 bool started_annotation = false;
1231 // Indent to match the register field, the fixed formatting, and the value
1232 // prefix ("0x"): "# {name}: 0x"
1233 fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1234 // First, annotate the lanes (byte by byte).
1235 for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1236 bool access = (access_mask & (1 << lane)) != 0;
1237 bool future = (future_access_mask & (1 << lane)) != 0;
1238 if (started_annotation) {
1239 // If we've started an annotation, draw a horizontal line in addition to
1240 // any other symbols.
1241 if (access) {
1242 fprintf(stream_, "─╨");
1243 } else if (future) {
1244 fprintf(stream_, "─║");
1245 } else {
1246 fprintf(stream_, "──");
1247 }
1248 } else {
1249 if (access) {
1250 started_annotation = true;
1251 fprintf(stream_, " â•™");
1252 } else if (future) {
1253 fprintf(stream_, " â•‘");
1254 } else {
1255 fprintf(stream_, " ");
1256 }
1257 }
1258 }
1259 VIXL_ASSERT(started_annotation);
1260 fprintf(stream_, "─ 0x");
1261 int lane_size_in_nibbles = lane_size_in_bytes * 2;
1262 // Print the most-significant struct element first.
1263 const char* sep = "";
1264 for (int i = struct_element_count - 1; i >= 0; i--) {
1265 int offset = lane_size_in_bytes * i;
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00001266 uint64_t nibble = MemReadUint(lane_size_in_bytes, address + offset);
Jacob Bramley423e5422019-11-13 19:15:55 +00001267 fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1268 sep = "'";
1269 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001270 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001271 " %s %s0x%016" PRIxPTR "%s\n",
1272 op,
1273 clr_memory_address,
1274 address,
1275 clr_normal);
1276 return future_access_mask & ~access_mask;
1277}
1278
1279void Simulator::PrintAccess(int code,
1280 PrintRegisterFormat format,
1281 const char* op,
1282 uintptr_t address) {
1283 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1284 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1285 if ((format & kPrintRegPartial) == 0) {
1286 registers_[code].NotifyRegisterLogged();
1287 }
1288 // Scalar-format accesses use a simple format:
1289 // "# {reg}: 0x{value} -> {address}"
1290
1291 // Suppress the newline, so the access annotation goes on the same line.
1292 PrintRegister(code, format, "");
1293 fprintf(stream_,
1294 " %s %s0x%016" PRIxPTR "%s\n",
1295 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001296 clr_memory_address,
1297 address,
1298 clr_normal);
1299}
1300
Jacob Bramley423e5422019-11-13 19:15:55 +00001301void Simulator::PrintVAccess(int code,
1302 PrintRegisterFormat format,
1303 const char* op,
1304 uintptr_t address) {
1305 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001306
Jacob Bramley423e5422019-11-13 19:15:55 +00001307 // Scalar-format accesses use a simple format:
1308 // "# v{code}: 0x{value} -> {address}"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001309
Jacob Bramley423e5422019-11-13 19:15:55 +00001310 // Suppress the newline, so the access annotation goes on the same line.
1311 PrintVRegister(code, format, "");
Alexandre Ramesd3832962016-07-04 15:03:43 +01001312 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001313 " %s %s0x%016" PRIxPTR "%s\n",
1314 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001315 clr_memory_address,
1316 address,
1317 clr_normal);
1318}
1319
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001320void Simulator::PrintVStructAccess(int rt_code,
Jacob Bramley423e5422019-11-13 19:15:55 +00001321 int reg_count,
1322 PrintRegisterFormat format,
1323 const char* op,
1324 uintptr_t address) {
1325 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1326
1327 // For example:
1328 // "# v{code}: 0x{value}"
1329 // "# ...: 0x{value}"
1330 // "# ║ ╙─ {struct_value} -> {lowest_address}"
1331 // "# ╙───── {struct_value} -> {highest_address}"
1332
1333 uint16_t lane_mask = GetPrintRegLaneMask(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001334 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
Jacob Bramley423e5422019-11-13 19:15:55 +00001335
1336 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1337 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1338 for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1339 uint16_t access_mask = 1 << i;
1340 VIXL_ASSERT((lane_mask & access_mask) != 0);
1341 lane_mask = PrintPartialAccess(access_mask,
1342 lane_mask,
1343 reg_count,
1344 lane_size_in_bytes,
1345 op,
1346 address + (i * reg_count));
1347 }
1348}
1349
1350void Simulator::PrintVSingleStructAccess(int rt_code,
1351 int reg_count,
1352 int lane,
1353 PrintRegisterFormat format,
1354 const char* op,
1355 uintptr_t address) {
1356 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1357
1358 // For example:
1359 // "# v{code}: 0x{value}"
1360 // "# ...: 0x{value}"
1361 // "# ╙───── {struct_value} -> {address}"
1362
1363 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1364 uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1365 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1366 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1367}
1368
1369void Simulator::PrintVReplicatingStructAccess(int rt_code,
1370 int reg_count,
1371 PrintRegisterFormat format,
1372 const char* op,
1373 uintptr_t address) {
1374 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1375
1376 // For example:
1377 // "# v{code}: 0x{value}"
1378 // "# ...: 0x{value}"
1379 // "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1380
1381 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1382 uint16_t lane_mask = GetPrintRegLaneMask(format);
1383 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1384 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1385}
1386
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001387void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1388 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1389
1390 // Scalar-format accesses are split into separate chunks, each of which uses a
1391 // simple format:
1392 // "# z{code}<127:0>: 0x{value} -> {address}"
1393 // "# z{code}<255:128>: 0x{value} -> {address + 16}"
1394 // "# z{code}<383:256>: 0x{value} -> {address + 32}"
1395 // etc
1396
1397 int vl = GetVectorLengthInBits();
1398 VIXL_ASSERT((vl % kQRegSize) == 0);
1399 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1400 // Suppress the newline, so the access annotation goes on the same line.
1401 PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1402 fprintf(stream_,
1403 " %s %s0x%016" PRIxPTR "%s\n",
1404 op,
1405 clr_memory_address,
1406 address,
1407 clr_normal);
1408 address += kQRegSizeInBytes;
1409 }
1410}
1411
1412void Simulator::PrintZStructAccess(int rt_code,
1413 int reg_count,
1414 const LogicPRegister& pg,
1415 PrintRegisterFormat format,
1416 int msize_in_bytes,
1417 const char* op,
1418 const LogicSVEAddressVector& addr) {
1419 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1420
1421 // For example:
1422 // "# z{code}<255:128>: 0x{value}"
1423 // "# ...<255:128>: 0x{value}"
1424 // "# ║ ╙─ {struct_value} -> {first_address}"
1425 // "# ╙───── {struct_value} -> {last_address}"
1426
1427 // We're going to print the register in parts, so force a partial format.
1428 bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1429 format = GetPrintRegPartial(format);
1430
1431 int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1432 int vl = GetVectorLengthInBits();
1433 VIXL_ASSERT((vl % kQRegSize) == 0);
1434 int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1435 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1436 uint16_t pred =
1437 pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1438 if ((pred == 0) && skip_inactive_chunks) continue;
1439
1440 PrintZRegistersForStructuredAccess(rt_code,
1441 q_index,
1442 reg_count,
1443 pred,
1444 format);
1445 if (pred == 0) {
1446 // This register chunk has no active lanes. The loop below would print
1447 // nothing, so leave a blank line to keep structures grouped together.
1448 fprintf(stream_, "#\n");
1449 continue;
1450 }
1451 for (int i = 0; i < lanes_per_q; i++) {
1452 uint16_t access = 1 << (i * esize_in_bytes);
1453 int lane = (q_index * lanes_per_q) + i;
1454 // Skip inactive lanes.
1455 if ((pred & access) == 0) continue;
1456 pred = PrintPartialAccess(access,
1457 pred,
1458 reg_count,
1459 msize_in_bytes,
1460 op,
1461 addr.GetStructAddress(lane));
1462 }
1463 }
1464
1465 // We print the whole register, even for stores.
1466 for (int i = 0; i < reg_count; i++) {
1467 vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1468 }
1469}
1470
1471void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1472 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1473
1474 // Scalar-format accesses are split into separate chunks, each of which uses a
1475 // simple format:
1476 // "# p{code}<15:0>: 0b{value} -> {address}"
1477 // "# p{code}<31:16>: 0b{value} -> {address + 2}"
1478 // "# p{code}<47:32>: 0b{value} -> {address + 4}"
1479 // etc
1480
1481 int vl = GetVectorLengthInBits();
1482 VIXL_ASSERT((vl % kQRegSize) == 0);
1483 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1484 // Suppress the newline, so the access annotation goes on the same line.
1485 PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1486 fprintf(stream_,
1487 " %s %s0x%016" PRIxPTR "%s\n",
1488 op,
1489 clr_memory_address,
1490 address,
1491 clr_normal);
1492 address += kQRegSizeInBytes;
1493 }
1494}
1495
Jacob Bramley423e5422019-11-13 19:15:55 +00001496void Simulator::PrintRead(int rt_code,
1497 PrintRegisterFormat format,
1498 uintptr_t address) {
1499 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1500 registers_[rt_code].NotifyRegisterLogged();
1501 PrintAccess(rt_code, format, "<-", address);
1502}
1503
1504void Simulator::PrintExtendingRead(int rt_code,
1505 PrintRegisterFormat format,
1506 int access_size_in_bytes,
1507 uintptr_t address) {
1508 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1509 if (access_size_in_bytes == reg_size_in_bytes) {
1510 // There is no extension here, so print a simple load.
1511 PrintRead(rt_code, format, address);
1512 return;
1513 }
1514 VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1515
1516 // For sign- and zero-extension, make it clear that the resulting register
1517 // value is different from what is loaded from memory.
1518 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1519 registers_[rt_code].NotifyRegisterLogged();
1520 PrintRegister(rt_code, format);
1521 PrintPartialAccess(1,
1522 0,
1523 1,
1524 access_size_in_bytes,
1525 "<-",
1526 address,
1527 kXRegSizeInBytes);
1528}
1529
1530void Simulator::PrintVRead(int rt_code,
1531 PrintRegisterFormat format,
1532 uintptr_t address) {
1533 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1534 vregisters_[rt_code].NotifyRegisterLogged();
1535 PrintVAccess(rt_code, format, "<-", address);
1536}
1537
Jacob Bramley423e5422019-11-13 19:15:55 +00001538void Simulator::PrintWrite(int rt_code,
1539 PrintRegisterFormat format,
1540 uintptr_t address) {
1541 // Because this trace doesn't represent a change to the source register's
1542 // value, only print the relevant part of the value.
1543 format = GetPrintRegPartial(format);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001544 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001545 registers_[rt_code].NotifyRegisterLogged();
1546 PrintAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001547}
1548
Jacob Bramley423e5422019-11-13 19:15:55 +00001549void Simulator::PrintVWrite(int rt_code,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001550 PrintRegisterFormat format,
Jacob Bramley423e5422019-11-13 19:15:55 +00001551 uintptr_t address) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001552 // Because this trace doesn't represent a change to the source register's
Jacob Bramley423e5422019-11-13 19:15:55 +00001553 // value, only print the relevant part of the value.
1554 format = GetPrintRegPartial(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001555 // It only makes sense to write scalar values here. Vectors are handled by
1556 // PrintVStructAccess.
Jacob Bramley423e5422019-11-13 19:15:55 +00001557 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001558 PrintVAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001559}
1560
Jacob Bramleye79723a2016-06-07 17:50:47 +01001561void Simulator::PrintTakenBranch(const Instruction* target) {
1562 fprintf(stream_,
1563 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1564 clr_branch_marker,
1565 clr_normal,
1566 reinterpret_cast<uint64_t>(target));
1567}
1568
Alexandre Ramesd3832962016-07-04 15:03:43 +01001569// Visitors---------------------------------------------------------------------
1570
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001571
1572void Simulator::VisitReserved(const Instruction* instr) {
1573 // UDF is the only instruction in this group, and the Decoder is precise here.
1574 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1575
1576 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1577 reinterpret_cast<const void*>(instr),
1578 instr->GetInstructionBits());
1579 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1580}
1581
1582
Alexandre Ramesd3832962016-07-04 15:03:43 +01001583void Simulator::VisitUnimplemented(const Instruction* instr) {
1584 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1585 reinterpret_cast<const void*>(instr),
1586 instr->GetInstructionBits());
1587 VIXL_UNIMPLEMENTED();
1588}
1589
1590
1591void Simulator::VisitUnallocated(const Instruction* instr) {
1592 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1593 reinterpret_cast<const void*>(instr),
1594 instr->GetInstructionBits());
1595 VIXL_UNIMPLEMENTED();
1596}
1597
1598
1599void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1600 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1601 (instr->Mask(PCRelAddressingMask) == ADRP));
1602
1603 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1604}
1605
1606
1607void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1608 switch (instr->Mask(UnconditionalBranchMask)) {
1609 case BL:
1610 WriteLr(instr->GetNextInstruction());
1611 VIXL_FALLTHROUGH();
1612 case B:
1613 WritePc(instr->GetImmPCOffsetTarget());
1614 break;
1615 default:
1616 VIXL_UNREACHABLE();
1617 }
1618}
1619
1620
1621void Simulator::VisitConditionalBranch(const Instruction* instr) {
1622 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1623 if (ConditionPassed(instr->GetConditionBranch())) {
1624 WritePc(instr->GetImmPCOffsetTarget());
1625 }
1626}
1627
Martyn Capewellcb963f72018-10-22 15:25:28 +01001628BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1629 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1630 case BLR:
1631 case BLRAA:
1632 case BLRAB:
1633 case BLRAAZ:
1634 case BLRABZ:
1635 return BranchAndLink;
1636 case BR:
1637 case BRAA:
1638 case BRAB:
1639 case BRAAZ:
1640 case BRABZ:
1641 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1642 !PcIsInGuardedPage()) {
1643 return BranchFromUnguardedOrToIP;
1644 }
1645 return BranchFromGuardedNotToIP;
1646 }
1647 return DefaultBType;
1648}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001649
1650void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01001651 bool authenticate = false;
1652 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01001653 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01001654 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001655
1656 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1657 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01001658 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001659 VIXL_FALLTHROUGH();
1660 case BR:
1661 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01001662 break;
1663
1664 case BLRAAZ:
1665 case BLRABZ:
1666 link = true;
1667 VIXL_FALLTHROUGH();
1668 case BRAAZ:
1669 case BRABZ:
1670 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001671 break;
1672
1673 case BLRAA:
1674 case BLRAB:
1675 link = true;
1676 VIXL_FALLTHROUGH();
1677 case BRAA:
1678 case BRAB:
1679 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001680 context = ReadXRegister(instr->GetRd());
1681 break;
1682
1683 case RETAA:
1684 case RETAB:
1685 authenticate = true;
1686 addr = ReadXRegister(kLinkRegCode);
1687 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001688 break;
1689 default:
1690 VIXL_UNREACHABLE();
1691 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001692
1693 if (link) {
1694 WriteLr(instr->GetNextInstruction());
1695 }
1696
1697 if (authenticate) {
1698 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1699 addr = AuthPAC(addr, context, key, kInstructionPointer);
1700
1701 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1702 if (((addr >> error_lsb) & 0x3) != 0x0) {
1703 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1704 }
1705 }
1706
Martyn Capewellcb963f72018-10-22 15:25:28 +01001707 WritePc(Instruction::Cast(addr));
1708 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001709}
1710
1711
1712void Simulator::VisitTestBranch(const Instruction* instr) {
1713 unsigned bit_pos =
1714 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1715 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1716 bool take_branch = false;
1717 switch (instr->Mask(TestBranchMask)) {
1718 case TBZ:
1719 take_branch = bit_zero;
1720 break;
1721 case TBNZ:
1722 take_branch = !bit_zero;
1723 break;
1724 default:
1725 VIXL_UNIMPLEMENTED();
1726 }
1727 if (take_branch) {
1728 WritePc(instr->GetImmPCOffsetTarget());
1729 }
1730}
1731
1732
1733void Simulator::VisitCompareBranch(const Instruction* instr) {
1734 unsigned rt = instr->GetRt();
1735 bool take_branch = false;
1736 switch (instr->Mask(CompareBranchMask)) {
1737 case CBZ_w:
1738 take_branch = (ReadWRegister(rt) == 0);
1739 break;
1740 case CBZ_x:
1741 take_branch = (ReadXRegister(rt) == 0);
1742 break;
1743 case CBNZ_w:
1744 take_branch = (ReadWRegister(rt) != 0);
1745 break;
1746 case CBNZ_x:
1747 take_branch = (ReadXRegister(rt) != 0);
1748 break;
1749 default:
1750 VIXL_UNIMPLEMENTED();
1751 }
1752 if (take_branch) {
1753 WritePc(instr->GetImmPCOffsetTarget());
1754 }
1755}
1756
1757
1758void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1759 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1760 bool set_flags = instr->GetFlagsUpdate();
1761 int64_t new_val = 0;
1762 Instr operation = instr->Mask(AddSubOpMask);
1763
1764 switch (operation) {
1765 case ADD:
1766 case ADDS: {
1767 new_val = AddWithCarry(reg_size,
1768 set_flags,
1769 ReadRegister(reg_size,
1770 instr->GetRn(),
1771 instr->GetRnMode()),
1772 op2);
1773 break;
1774 }
1775 case SUB:
1776 case SUBS: {
1777 new_val = AddWithCarry(reg_size,
1778 set_flags,
1779 ReadRegister(reg_size,
1780 instr->GetRn(),
1781 instr->GetRnMode()),
1782 ~op2,
1783 1);
1784 break;
1785 }
1786 default:
1787 VIXL_UNREACHABLE();
1788 }
1789
1790 WriteRegister(reg_size,
1791 instr->GetRd(),
1792 new_val,
1793 LogRegWrites,
1794 instr->GetRdMode());
1795}
1796
1797
1798void Simulator::VisitAddSubShifted(const Instruction* instr) {
1799 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1800 int64_t op2 = ShiftOperand(reg_size,
1801 ReadRegister(reg_size, instr->GetRm()),
1802 static_cast<Shift>(instr->GetShiftDP()),
1803 instr->GetImmDPShift());
1804 AddSubHelper(instr, op2);
1805}
1806
1807
1808void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1809 int64_t op2 = instr->GetImmAddSub()
Jacob Bramley2b66cd62020-06-05 14:07:55 +01001810 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001811 AddSubHelper(instr, op2);
1812}
1813
1814
1815void Simulator::VisitAddSubExtended(const Instruction* instr) {
1816 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1817 int64_t op2 = ExtendValue(reg_size,
1818 ReadRegister(reg_size, instr->GetRm()),
1819 static_cast<Extend>(instr->GetExtendMode()),
1820 instr->GetImmExtendShift());
1821 AddSubHelper(instr, op2);
1822}
1823
1824
1825void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1826 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1827 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1828 int64_t new_val;
1829
1830 if ((instr->Mask(AddSubOpMask) == SUB) ||
1831 (instr->Mask(AddSubOpMask) == SUBS)) {
1832 op2 = ~op2;
1833 }
1834
1835 new_val = AddWithCarry(reg_size,
1836 instr->GetFlagsUpdate(),
1837 ReadRegister(reg_size, instr->GetRn()),
1838 op2,
1839 ReadC());
1840
1841 WriteRegister(reg_size, instr->GetRd(), new_val);
1842}
1843
1844
Alexander Gilday2487f142018-11-05 13:07:27 +00001845void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1846 switch (instr->Mask(RotateRightIntoFlagsMask)) {
1847 case RMIF: {
1848 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1849 unsigned shift = instr->GetImmRMIFRotation();
1850 unsigned mask = instr->GetNzcv();
1851 uint64_t rotated = RotateRight(value, shift, kXRegSize);
1852
1853 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1854 break;
1855 }
1856 }
1857}
1858
1859
1860void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1861 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1862 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1863
1864 unsigned sign_bit = (value >> msb) & 1;
1865 unsigned overflow_bit = (value >> (msb + 1)) & 1;
1866 ReadNzcv().SetN(sign_bit);
1867 ReadNzcv().SetZ((value << (31 - msb)) == 0);
1868 ReadNzcv().SetV(sign_bit ^ overflow_bit);
1869}
1870
1871
Alexandre Ramesd3832962016-07-04 15:03:43 +01001872void Simulator::VisitLogicalShifted(const Instruction* instr) {
1873 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1874 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1875 unsigned shift_amount = instr->GetImmDPShift();
1876 int64_t op2 = ShiftOperand(reg_size,
1877 ReadRegister(reg_size, instr->GetRm()),
1878 shift_type,
1879 shift_amount);
1880 if (instr->Mask(NOT) == NOT) {
1881 op2 = ~op2;
1882 }
1883 LogicalHelper(instr, op2);
1884}
1885
1886
1887void Simulator::VisitLogicalImmediate(const Instruction* instr) {
Martyn Capewella26a26c2020-09-23 11:30:53 +01001888 if (instr->GetImmLogical() == 0) {
1889 VIXL_UNIMPLEMENTED();
1890 } else {
1891 LogicalHelper(instr, instr->GetImmLogical());
1892 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001893}
1894
1895
1896void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1897 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1898 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1899 int64_t result = 0;
1900 bool update_flags = false;
1901
1902 // Switch on the logical operation, stripping out the NOT bit, as it has a
1903 // different meaning for logical immediate instructions.
1904 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1905 case ANDS:
1906 update_flags = true;
1907 VIXL_FALLTHROUGH();
1908 case AND:
1909 result = op1 & op2;
1910 break;
1911 case ORR:
1912 result = op1 | op2;
1913 break;
1914 case EOR:
1915 result = op1 ^ op2;
1916 break;
1917 default:
1918 VIXL_UNIMPLEMENTED();
1919 }
1920
1921 if (update_flags) {
1922 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1923 ReadNzcv().SetZ(CalcZFlag(result));
1924 ReadNzcv().SetC(0);
1925 ReadNzcv().SetV(0);
1926 LogSystemRegister(NZCV);
1927 }
1928
1929 WriteRegister(reg_size,
1930 instr->GetRd(),
1931 result,
1932 LogRegWrites,
1933 instr->GetRdMode());
1934}
1935
1936
1937void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1938 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1939 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1940}
1941
1942
1943void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1944 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1945}
1946
1947
1948void Simulator::ConditionalCompareHelper(const Instruction* instr,
1949 int64_t op2) {
1950 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1951 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1952
1953 if (ConditionPassed(instr->GetCondition())) {
1954 // If the condition passes, set the status flags to the result of comparing
1955 // the operands.
1956 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1957 AddWithCarry(reg_size, true, op1, ~op2, 1);
1958 } else {
1959 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1960 AddWithCarry(reg_size, true, op1, op2, 0);
1961 }
1962 } else {
1963 // If the condition fails, set the status flags to the nzcv immediate.
1964 ReadNzcv().SetFlags(instr->GetNzcv());
1965 LogSystemRegister(NZCV);
1966 }
1967}
1968
1969
1970void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1971 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1972 LoadStoreHelper(instr, offset, Offset);
1973}
1974
1975
1976void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1977 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1978}
1979
1980
1981void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1982 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1983}
1984
1985
1986void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1987 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1988}
1989
1990
Alexander Gilday311edf22018-10-29 13:41:41 +00001991template <typename T1, typename T2>
1992void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1993 unsigned rt = instr->GetRt();
1994 unsigned rn = instr->GetRn();
1995
1996 unsigned element_size = sizeof(T2);
1997 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1998 int offset = instr->GetImmLS();
1999 address += offset;
2000
2001 // Verify that the address is available to the host.
2002 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2003
2004 // Check the alignment of `address`.
2005 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2006 VIXL_ALIGNMENT_EXCEPTION();
2007 }
2008
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002009 WriteRegister<T1>(rt, static_cast<T1>(MemRead<T2>(address)));
Alexander Gilday311edf22018-10-29 13:41:41 +00002010
2011 // Approximate load-acquire by issuing a full barrier after the load.
2012 __sync_synchronize();
2013
Jacob Bramley423e5422019-11-13 19:15:55 +00002014 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00002015}
2016
2017
2018template <typename T>
2019void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
2020 unsigned rt = instr->GetRt();
2021 unsigned rn = instr->GetRn();
2022
2023 unsigned element_size = sizeof(T);
2024 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2025 int offset = instr->GetImmLS();
2026 address += offset;
2027
2028 // Verify that the address is available to the host.
2029 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2030
2031 // Check the alignment of `address`.
2032 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2033 VIXL_ALIGNMENT_EXCEPTION();
2034 }
2035
2036 // Approximate store-release by issuing a full barrier after the load.
2037 __sync_synchronize();
2038
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002039 MemWrite<T>(address, ReadRegister<T>(rt));
Alexander Gilday311edf22018-10-29 13:41:41 +00002040
Jacob Bramley423e5422019-11-13 19:15:55 +00002041 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00002042}
2043
2044
2045void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
2046 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
2047 case LDAPURB:
2048 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
2049 break;
2050 case LDAPURH:
2051 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
2052 break;
2053 case LDAPUR_w:
2054 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
2055 break;
2056 case LDAPUR_x:
2057 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
2058 break;
2059 case LDAPURSB_w:
2060 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
2061 break;
2062 case LDAPURSB_x:
2063 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
2064 break;
2065 case LDAPURSH_w:
2066 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
2067 break;
2068 case LDAPURSH_x:
2069 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
2070 break;
2071 case LDAPURSW:
2072 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
2073 break;
2074 case STLURB:
2075 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
2076 break;
2077 case STLURH:
2078 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
2079 break;
2080 case STLUR_w:
2081 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
2082 break;
2083 case STLUR_x:
2084 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
2085 break;
2086 }
2087}
2088
2089
Alexander Gilday75605592018-11-01 09:30:29 +00002090void Simulator::VisitLoadStorePAC(const Instruction* instr) {
2091 unsigned dst = instr->GetRt();
2092 unsigned addr_reg = instr->GetRn();
2093
2094 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2095
2096 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
2097 address = AuthPAC(address, 0, key, kDataPointer);
2098
2099 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
2100 if (((address >> error_lsb) & 0x3) != 0x0) {
2101 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
2102 }
2103
2104
2105 if ((addr_reg == 31) && ((address % 16) != 0)) {
2106 // When the base register is SP the stack pointer is required to be
2107 // quadword aligned prior to the address calculation and write-backs.
2108 // Misalignment will cause a stack alignment fault.
2109 VIXL_ALIGNMENT_EXCEPTION();
2110 }
2111
2112 int64_t offset = instr->GetImmLSPAC();
2113 address += offset;
2114
2115 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
2116 // Pre-index mode.
2117 VIXL_ASSERT(offset != 0);
2118 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
2119 }
2120
2121 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
2122
2123 // Verify that the calculated address is available to the host.
2124 VIXL_ASSERT(address == addr_ptr);
2125
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002126 WriteXRegister(dst, MemRead<uint64_t>(addr_ptr), NoRegLog);
Alexander Gilday75605592018-11-01 09:30:29 +00002127 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00002128 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00002129}
2130
2131
Alexandre Ramesd3832962016-07-04 15:03:43 +01002132void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
2133 Extend ext = static_cast<Extend>(instr->GetExtendMode());
2134 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
2135 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
2136
2137 int64_t offset =
2138 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
2139 LoadStoreHelper(instr, offset, Offset);
2140}
2141
2142
2143void Simulator::LoadStoreHelper(const Instruction* instr,
2144 int64_t offset,
2145 AddrMode addrmode) {
2146 unsigned srcdst = instr->GetRt();
2147 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2148
Jacob Bramley423e5422019-11-13 19:15:55 +00002149 bool rt_is_vreg = false;
2150 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002151 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
2152 switch (op) {
2153 case LDRB_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002154 WriteWRegister(srcdst, MemRead<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002155 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002156 break;
2157 case LDRH_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002158 WriteWRegister(srcdst, MemRead<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002159 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002160 break;
2161 case LDR_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002162 WriteWRegister(srcdst, MemRead<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002163 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002164 break;
2165 case LDR_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002166 WriteXRegister(srcdst, MemRead<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002167 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002168 break;
2169 case LDRSB_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002170 WriteWRegister(srcdst, MemRead<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002171 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002172 break;
2173 case LDRSH_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002174 WriteWRegister(srcdst, MemRead<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002175 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002176 break;
2177 case LDRSB_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002178 WriteXRegister(srcdst, MemRead<int8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002179 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002180 break;
2181 case LDRSH_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002182 WriteXRegister(srcdst, MemRead<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002183 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002184 break;
2185 case LDRSW_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002186 WriteXRegister(srcdst, MemRead<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002187 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002188 break;
2189 case LDR_b:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002190 WriteBRegister(srcdst, MemRead<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002191 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002192 break;
2193 case LDR_h:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002194 WriteHRegister(srcdst, MemRead<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002195 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002196 break;
2197 case LDR_s:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002198 WriteSRegister(srcdst, MemRead<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002199 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002200 break;
2201 case LDR_d:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002202 WriteDRegister(srcdst, MemRead<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002203 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002204 break;
2205 case LDR_q:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002206 WriteQRegister(srcdst, MemRead<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002207 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002208 break;
2209
2210 case STRB_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002211 MemWrite<uint8_t>(address, ReadWRegister(srcdst));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002212 break;
2213 case STRH_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002214 MemWrite<uint16_t>(address, ReadWRegister(srcdst));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002215 break;
2216 case STR_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002217 MemWrite<uint32_t>(address, ReadWRegister(srcdst));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002218 break;
2219 case STR_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002220 MemWrite<uint64_t>(address, ReadXRegister(srcdst));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002221 break;
2222 case STR_b:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002223 MemWrite<uint8_t>(address, ReadBRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002224 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002225 break;
2226 case STR_h:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002227 MemWrite<uint16_t>(address, ReadHRegisterBits(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002228 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002229 break;
2230 case STR_s:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002231 MemWrite<float>(address, ReadSRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002232 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002233 break;
2234 case STR_d:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002235 MemWrite<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002236 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002237 break;
2238 case STR_q:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002239 MemWrite<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002240 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002241 break;
2242
2243 // Ignore prfm hint instructions.
2244 case PRFM:
2245 break;
2246
2247 default:
2248 VIXL_UNIMPLEMENTED();
2249 }
2250
Jacob Bramley423e5422019-11-13 19:15:55 +00002251 // Print a detailed trace (including the memory address).
2252 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002253 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00002254 unsigned result_size = extend ? extend_to_size : access_size;
2255 PrintRegisterFormat print_format =
2256 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2257 : GetPrintRegisterFormatForSize(result_size);
2258
Alexandre Ramesd3832962016-07-04 15:03:43 +01002259 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002260 if (rt_is_vreg) {
2261 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002262 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002263 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002264 }
2265 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002266 if (rt_is_vreg) {
2267 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002268 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002269 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002270 }
2271 } else {
2272 VIXL_ASSERT(op == PRFM);
2273 }
2274
2275 local_monitor_.MaybeClear();
2276}
2277
2278
2279void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
2280 LoadStorePairHelper(instr, Offset);
2281}
2282
2283
2284void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
2285 LoadStorePairHelper(instr, PreIndex);
2286}
2287
2288
2289void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
2290 LoadStorePairHelper(instr, PostIndex);
2291}
2292
2293
2294void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
2295 LoadStorePairHelper(instr, Offset);
2296}
2297
2298
2299void Simulator::LoadStorePairHelper(const Instruction* instr,
2300 AddrMode addrmode) {
2301 unsigned rt = instr->GetRt();
2302 unsigned rt2 = instr->GetRt2();
2303 int element_size = 1 << instr->GetSizeLSPair();
2304 int64_t offset = instr->GetImmLSPair() * element_size;
2305 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2306 uintptr_t address2 = address + element_size;
2307
2308 LoadStorePairOp op =
2309 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
2310
2311 // 'rt' and 'rt2' can only be aliased for stores.
2312 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2313
Jacob Bramley423e5422019-11-13 19:15:55 +00002314 bool rt_is_vreg = false;
2315 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002316 switch (op) {
2317 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
2318 // will print a more detailed log.
2319 case LDP_w: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002320 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
2321 WriteWRegister(rt2, MemRead<uint32_t>(address2), NoRegLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002322 break;
2323 }
2324 case LDP_s: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002325 WriteSRegister(rt, MemRead<float>(address), NoRegLog);
2326 WriteSRegister(rt2, MemRead<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002327 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002328 break;
2329 }
2330 case LDP_x: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002331 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
2332 WriteXRegister(rt2, MemRead<uint64_t>(address2), NoRegLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002333 break;
2334 }
2335 case LDP_d: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002336 WriteDRegister(rt, MemRead<double>(address), NoRegLog);
2337 WriteDRegister(rt2, MemRead<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002338 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002339 break;
2340 }
2341 case LDP_q: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002342 WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog);
2343 WriteQRegister(rt2, MemRead<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002344 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002345 break;
2346 }
2347 case LDPSW_x: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002348 WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog);
2349 WriteXRegister(rt2, MemRead<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002350 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002351 break;
2352 }
2353 case STP_w: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002354 MemWrite<uint32_t>(address, ReadWRegister(rt));
2355 MemWrite<uint32_t>(address2, ReadWRegister(rt2));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002356 break;
2357 }
2358 case STP_s: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002359 MemWrite<float>(address, ReadSRegister(rt));
2360 MemWrite<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002361 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002362 break;
2363 }
2364 case STP_x: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002365 MemWrite<uint64_t>(address, ReadXRegister(rt));
2366 MemWrite<uint64_t>(address2, ReadXRegister(rt2));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002367 break;
2368 }
2369 case STP_d: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002370 MemWrite<double>(address, ReadDRegister(rt));
2371 MemWrite<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002372 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002373 break;
2374 }
2375 case STP_q: {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002376 MemWrite<qreg_t>(address, ReadQRegister(rt));
2377 MemWrite<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002378 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002379 break;
2380 }
2381 default:
2382 VIXL_UNREACHABLE();
2383 }
2384
Jacob Bramley423e5422019-11-13 19:15:55 +00002385 // Print a detailed trace (including the memory address).
2386 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
2387 PrintRegisterFormat print_format =
2388 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2389 : GetPrintRegisterFormatForSize(result_size);
2390
Alexandre Ramesd3832962016-07-04 15:03:43 +01002391 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002392 if (rt_is_vreg) {
2393 LogVRead(rt, print_format, address);
2394 LogVRead(rt2, print_format, address2);
2395 } else if (sign_extend) {
2396 LogExtendingRead(rt, print_format, element_size, address);
2397 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002398 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002399 LogRead(rt, print_format, address);
2400 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002401 }
2402 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002403 if (rt_is_vreg) {
2404 LogVWrite(rt, print_format, address);
2405 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002406 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002407 LogWrite(rt, print_format, address);
2408 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002409 }
2410 }
2411
2412 local_monitor_.MaybeClear();
2413}
2414
2415
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002416template <typename T>
2417void Simulator::CompareAndSwapHelper(const Instruction* instr) {
2418 unsigned rs = instr->GetRs();
2419 unsigned rt = instr->GetRt();
2420 unsigned rn = instr->GetRn();
2421
2422 unsigned element_size = sizeof(T);
2423 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2424
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002425 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2426
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002427 bool is_acquire = instr->ExtractBit(22) == 1;
2428 bool is_release = instr->ExtractBit(15) == 1;
2429
2430 T comparevalue = ReadRegister<T>(rs);
2431 T newvalue = ReadRegister<T>(rt);
2432
2433 // The architecture permits that the data read clears any exclusive monitors
2434 // associated with that location, even if the compare subsequently fails.
2435 local_monitor_.Clear();
2436
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002437 T data = MemRead<T>(address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002438 if (is_acquire) {
2439 // Approximate load-acquire by issuing a full barrier after the load.
2440 __sync_synchronize();
2441 }
2442
2443 if (data == comparevalue) {
2444 if (is_release) {
2445 // Approximate store-release by issuing a full barrier before the store.
2446 __sync_synchronize();
2447 }
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002448 MemWrite<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00002449 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002450 }
Jacob Bramley3eb24e92020-07-03 18:17:36 +01002451 WriteRegister<T>(rs, data, NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002452 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002453}
2454
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002455
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002456template <typename T>
2457void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
2458 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
2459 unsigned rs = instr->GetRs();
2460 unsigned rt = instr->GetRt();
2461 unsigned rn = instr->GetRn();
2462
Jacob Bramley3eb24e92020-07-03 18:17:36 +01002463 VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002464
2465 unsigned element_size = sizeof(T);
2466 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002467
2468 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
2469
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002470 uint64_t address2 = address + element_size;
2471
2472 bool is_acquire = instr->ExtractBit(22) == 1;
2473 bool is_release = instr->ExtractBit(15) == 1;
2474
2475 T comparevalue_high = ReadRegister<T>(rs + 1);
2476 T comparevalue_low = ReadRegister<T>(rs);
2477 T newvalue_high = ReadRegister<T>(rt + 1);
2478 T newvalue_low = ReadRegister<T>(rt);
2479
2480 // The architecture permits that the data read clears any exclusive monitors
2481 // associated with that location, even if the compare subsequently fails.
2482 local_monitor_.Clear();
2483
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002484 T data_low = MemRead<T>(address);
2485 T data_high = MemRead<T>(address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002486
2487 if (is_acquire) {
2488 // Approximate load-acquire by issuing a full barrier after the load.
2489 __sync_synchronize();
2490 }
2491
2492 bool same =
2493 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2494 if (same) {
2495 if (is_release) {
2496 // Approximate store-release by issuing a full barrier before the store.
2497 __sync_synchronize();
2498 }
2499
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002500 MemWrite<T>(address, newvalue_low);
2501 MemWrite<T>(address2, newvalue_high);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002502 }
2503
Jacob Bramley3eb24e92020-07-03 18:17:36 +01002504 WriteRegister<T>(rs + 1, data_high, NoRegLog);
2505 WriteRegister<T>(rs, data_low, NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002506
Jacob Bramley423e5422019-11-13 19:15:55 +00002507 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
Jacob Bramley3eb24e92020-07-03 18:17:36 +01002508 LogRead(rs, format, address);
2509 LogRead(rs + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002510
2511 if (same) {
Jacob Bramley3eb24e92020-07-03 18:17:36 +01002512 LogWrite(rt, format, address);
2513 LogWrite(rt + 1, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002514 }
2515}
2516
Jacob Bramley85a9c102019-12-09 17:48:29 +00002517bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
2518 // To simulate fault-tolerant loads, we need to know what host addresses we
2519 // can access without generating a real fault. One way to do that is to
2520 // attempt to `write()` the memory to a dummy pipe[1]. This is more portable
2521 // and less intrusive than using (global) signal handlers.
2522 //
2523 // [1]: https://stackoverflow.com/questions/7134590
2524
2525 size_t written = 0;
2526 bool can_read = true;
2527 // `write` will normally return after one invocation, but it is allowed to
2528 // handle only part of the operation, so wrap it in a loop.
2529 while (can_read && (written < size)) {
2530 ssize_t result = write(dummy_pipe_fd_[1],
2531 reinterpret_cast<void*>(address + written),
2532 size - written);
2533 if (result > 0) {
2534 written += result;
2535 } else {
2536 switch (result) {
2537 case -EPERM:
2538 case -EFAULT:
2539 // The address range is not accessible.
2540 // `write` is supposed to return -EFAULT in this case, but in practice
2541 // it seems to return -EPERM, so we accept that too.
2542 can_read = false;
2543 break;
2544 case -EINTR:
2545 // The call was interrupted by a signal. Just try again.
2546 break;
2547 default:
2548 // Any other error is fatal.
2549 VIXL_ABORT();
2550 }
2551 }
2552 }
2553 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
2554 // the dummy data is buffered. As before, we expect to drain the whole write
2555 // in one invocation, but cannot guarantee that, so we wrap it in a loop. This
2556 // function is primarily intended to implement SVE fault-tolerant loads, so
2557 // the maximum Z register size is a good default buffer size.
2558 char buffer[kZRegMaxSizeInBytes];
2559 while (written > 0) {
2560 ssize_t result = read(dummy_pipe_fd_[0],
2561 reinterpret_cast<void*>(buffer),
2562 sizeof(buffer));
2563 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
2564 // we've read everything that was written, so treat 0 as an error.
2565 if (result > 0) {
2566 VIXL_ASSERT(static_cast<size_t>(result) <= written);
2567 written -= result;
2568 } else {
2569 // For -EINTR, just try again. We can't handle any other error.
2570 VIXL_CHECK(result == -EINTR);
2571 }
2572 }
2573
2574 return can_read;
2575}
Alexandre Ramesd3832962016-07-04 15:03:43 +01002576
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002577void Simulator::PrintExclusiveAccessWarning() {
2578 if (print_exclusive_access_warning_) {
2579 fprintf(stderr,
2580 "%sWARNING:%s VIXL simulator support for "
2581 "load-/store-/clear-exclusive "
2582 "instructions is limited. Refer to the README for details.%s\n",
2583 clr_warning,
2584 clr_warning_message,
2585 clr_normal);
2586 print_exclusive_access_warning_ = false;
2587 }
2588}
2589
Alexandre Ramesd3832962016-07-04 15:03:43 +01002590void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002591 LoadStoreExclusive op =
2592 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
2593
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002594 switch (op) {
2595 case CAS_w:
2596 case CASA_w:
2597 case CASL_w:
2598 case CASAL_w:
2599 CompareAndSwapHelper<uint32_t>(instr);
2600 break;
2601 case CAS_x:
2602 case CASA_x:
2603 case CASL_x:
2604 case CASAL_x:
2605 CompareAndSwapHelper<uint64_t>(instr);
2606 break;
2607 case CASB:
2608 case CASAB:
2609 case CASLB:
2610 case CASALB:
2611 CompareAndSwapHelper<uint8_t>(instr);
2612 break;
2613 case CASH:
2614 case CASAH:
2615 case CASLH:
2616 case CASALH:
2617 CompareAndSwapHelper<uint16_t>(instr);
2618 break;
2619 case CASP_w:
2620 case CASPA_w:
2621 case CASPL_w:
2622 case CASPAL_w:
2623 CompareAndSwapPairHelper<uint32_t>(instr);
2624 break;
2625 case CASP_x:
2626 case CASPA_x:
2627 case CASPL_x:
2628 case CASPAL_x:
2629 CompareAndSwapPairHelper<uint64_t>(instr);
2630 break;
2631 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002632 PrintExclusiveAccessWarning();
2633
2634 unsigned rs = instr->GetRs();
2635 unsigned rt = instr->GetRt();
2636 unsigned rt2 = instr->GetRt2();
2637 unsigned rn = instr->GetRn();
2638
2639 bool is_exclusive = !instr->GetLdStXNotExclusive();
2640 bool is_acquire_release =
2641 !is_exclusive || instr->GetLdStXAcquireRelease();
2642 bool is_load = instr->GetLdStXLoad();
2643 bool is_pair = instr->GetLdStXPair();
2644
2645 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2646 unsigned access_size = is_pair ? element_size * 2 : element_size;
2647 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2648
2649 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2650
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002651 if (is_load) {
2652 if (is_exclusive) {
2653 local_monitor_.MarkExclusive(address, access_size);
2654 } else {
2655 // Any non-exclusive load can clear the local monitor as a side
2656 // effect. We don't need to do this, but it is useful to stress the
2657 // simulated code.
2658 local_monitor_.Clear();
2659 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002660
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002661 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2662 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00002663 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002664 switch (op) {
2665 case LDXRB_w:
2666 case LDAXRB_w:
2667 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002668 case LDLARB:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002669 WriteWRegister(rt, MemRead<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002670 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002671 break;
2672 case LDXRH_w:
2673 case LDAXRH_w:
2674 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002675 case LDLARH:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002676 WriteWRegister(rt, MemRead<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002677 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002678 break;
2679 case LDXR_w:
2680 case LDAXR_w:
2681 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002682 case LDLAR_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002683 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002684 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002685 break;
2686 case LDXR_x:
2687 case LDAXR_x:
2688 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002689 case LDLAR_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002690 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002691 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002692 break;
2693 case LDXP_w:
2694 case LDAXP_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002695 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002696 WriteWRegister(rt2,
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002697 MemRead<uint32_t>(address + element_size),
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002698 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002699 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002700 break;
2701 case LDXP_x:
2702 case LDAXP_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002703 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002704 WriteXRegister(rt2,
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002705 MemRead<uint64_t>(address + element_size),
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002706 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002707 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002708 break;
2709 default:
2710 VIXL_UNREACHABLE();
2711 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002712
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002713 if (is_acquire_release) {
2714 // Approximate load-acquire by issuing a full barrier after the load.
2715 __sync_synchronize();
2716 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002717
Jacob Bramley423e5422019-11-13 19:15:55 +00002718 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
2719 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002720 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002721 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002722 }
2723 } else {
2724 if (is_acquire_release) {
2725 // Approximate store-release by issuing a full barrier before the
2726 // store.
2727 __sync_synchronize();
2728 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002729
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002730 bool do_store = true;
2731 if (is_exclusive) {
2732 do_store = local_monitor_.IsExclusive(address, access_size) &&
2733 global_monitor_.IsExclusive(address, access_size);
2734 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002735
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002736 // - All exclusive stores explicitly clear the local monitor.
2737 local_monitor_.Clear();
2738 } else {
2739 // - Any other store can clear the local monitor as a side effect.
2740 local_monitor_.MaybeClear();
2741 }
2742
2743 if (do_store) {
2744 switch (op) {
2745 case STXRB_w:
2746 case STLXRB_w:
2747 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002748 case STLLRB:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002749 MemWrite<uint8_t>(address, ReadWRegister(rt));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002750 break;
2751 case STXRH_w:
2752 case STLXRH_w:
2753 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002754 case STLLRH:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002755 MemWrite<uint16_t>(address, ReadWRegister(rt));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002756 break;
2757 case STXR_w:
2758 case STLXR_w:
2759 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002760 case STLLR_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002761 MemWrite<uint32_t>(address, ReadWRegister(rt));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002762 break;
2763 case STXR_x:
2764 case STLXR_x:
2765 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002766 case STLLR_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002767 MemWrite<uint64_t>(address, ReadXRegister(rt));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002768 break;
2769 case STXP_w:
2770 case STLXP_w:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002771 MemWrite<uint32_t>(address, ReadWRegister(rt));
2772 MemWrite<uint32_t>(address + element_size, ReadWRegister(rt2));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002773 break;
2774 case STXP_x:
2775 case STLXP_x:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002776 MemWrite<uint64_t>(address, ReadXRegister(rt));
2777 MemWrite<uint64_t>(address + element_size, ReadXRegister(rt2));
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002778 break;
2779 default:
2780 VIXL_UNREACHABLE();
2781 }
2782
Jacob Bramley423e5422019-11-13 19:15:55 +00002783 PrintRegisterFormat format =
2784 GetPrintRegisterFormatForSize(element_size);
2785 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002786 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002787 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002788 }
2789 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002790 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002791 }
2792}
2793
Jacob Bramleyca789742018-09-13 14:25:46 +01002794template <typename T>
2795void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2796 unsigned rs = instr->GetRs();
2797 unsigned rt = instr->GetRt();
2798 unsigned rn = instr->GetRn();
2799
2800 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2801 bool is_release = instr->ExtractBit(22) == 1;
2802
2803 unsigned element_size = sizeof(T);
2804 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2805
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002806 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002807
2808 T value = ReadRegister<T>(rs);
2809
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002810 T data = MemRead<T>(address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002811
2812 if (is_acquire) {
2813 // Approximate load-acquire by issuing a full barrier after the load.
2814 __sync_synchronize();
2815 }
2816
2817 T result = 0;
2818 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2819 case LDADDOp:
2820 result = data + value;
2821 break;
2822 case LDCLROp:
2823 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2824 result = data & ~value;
2825 break;
2826 case LDEOROp:
2827 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2828 result = data ^ value;
2829 break;
2830 case LDSETOp:
2831 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2832 result = data | value;
2833 break;
2834
2835 // Signed/Unsigned difference is done via the templated type T.
2836 case LDSMAXOp:
2837 case LDUMAXOp:
2838 result = (data > value) ? data : value;
2839 break;
2840 case LDSMINOp:
2841 case LDUMINOp:
2842 result = (data > value) ? value : data;
2843 break;
2844 }
2845
2846 if (is_release) {
2847 // Approximate store-release by issuing a full barrier before the store.
2848 __sync_synchronize();
2849 }
2850
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002851 MemWrite<T>(address, result);
Jacob Bramleyca789742018-09-13 14:25:46 +01002852 WriteRegister<T>(rt, data, NoRegLog);
2853
Jacob Bramley423e5422019-11-13 19:15:55 +00002854 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2855 LogRead(rt, format, address);
2856 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002857}
2858
2859template <typename T>
2860void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2861 unsigned rs = instr->GetRs();
2862 unsigned rt = instr->GetRt();
2863 unsigned rn = instr->GetRn();
2864
2865 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2866 bool is_release = instr->ExtractBit(22) == 1;
2867
2868 unsigned element_size = sizeof(T);
2869 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2870
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002871 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002872
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002873 T data = MemRead<T>(address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002874 if (is_acquire) {
2875 // Approximate load-acquire by issuing a full barrier after the load.
2876 __sync_synchronize();
2877 }
2878
2879 if (is_release) {
2880 // Approximate store-release by issuing a full barrier before the store.
2881 __sync_synchronize();
2882 }
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002883 MemWrite<T>(address, ReadRegister<T>(rs));
Jacob Bramleyca789742018-09-13 14:25:46 +01002884
2885 WriteRegister<T>(rt, data);
2886
Jacob Bramley423e5422019-11-13 19:15:55 +00002887 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2888 LogRead(rt, format, address);
2889 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002890}
2891
2892template <typename T>
2893void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2894 unsigned rt = instr->GetRt();
2895 unsigned rn = instr->GetRn();
2896
2897 unsigned element_size = sizeof(T);
2898 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2899
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002900 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2901
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00002902 WriteRegister<T>(rt, MemRead<T>(address));
Jacob Bramleyca789742018-09-13 14:25:46 +01002903
2904 // Approximate load-acquire by issuing a full barrier after the load.
2905 __sync_synchronize();
2906
Jacob Bramley423e5422019-11-13 19:15:55 +00002907 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002908}
2909
2910#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2911 V(LDADD) \
2912 V(LDCLR) \
2913 V(LDEOR) \
2914 V(LDSET) \
2915 V(LDUMAX) \
2916 V(LDUMIN)
2917
2918#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2919 V(LDSMAX) \
2920 V(LDSMIN)
2921
2922void Simulator::VisitAtomicMemory(const Instruction* instr) {
2923 switch (instr->Mask(AtomicMemoryMask)) {
2924// clang-format off
2925#define SIM_FUNC_B(A) \
2926 case A##B: \
2927 case A##AB: \
2928 case A##LB: \
2929 case A##ALB:
2930#define SIM_FUNC_H(A) \
2931 case A##H: \
2932 case A##AH: \
2933 case A##LH: \
2934 case A##ALH:
2935#define SIM_FUNC_w(A) \
2936 case A##_w: \
2937 case A##A_w: \
2938 case A##L_w: \
2939 case A##AL_w:
2940#define SIM_FUNC_x(A) \
2941 case A##_x: \
2942 case A##A_x: \
2943 case A##L_x: \
2944 case A##AL_x:
2945
2946 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2947 AtomicMemorySimpleHelper<uint8_t>(instr);
2948 break;
2949 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2950 AtomicMemorySimpleHelper<int8_t>(instr);
2951 break;
2952 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2953 AtomicMemorySimpleHelper<uint16_t>(instr);
2954 break;
2955 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2956 AtomicMemorySimpleHelper<int16_t>(instr);
2957 break;
2958 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2959 AtomicMemorySimpleHelper<uint32_t>(instr);
2960 break;
2961 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2962 AtomicMemorySimpleHelper<int32_t>(instr);
2963 break;
2964 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2965 AtomicMemorySimpleHelper<uint64_t>(instr);
2966 break;
2967 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2968 AtomicMemorySimpleHelper<int64_t>(instr);
2969 break;
2970 // clang-format on
2971
2972 case SWPB:
2973 case SWPAB:
2974 case SWPLB:
2975 case SWPALB:
2976 AtomicMemorySwapHelper<uint8_t>(instr);
2977 break;
2978 case SWPH:
2979 case SWPAH:
2980 case SWPLH:
2981 case SWPALH:
2982 AtomicMemorySwapHelper<uint16_t>(instr);
2983 break;
2984 case SWP_w:
2985 case SWPA_w:
2986 case SWPL_w:
2987 case SWPAL_w:
2988 AtomicMemorySwapHelper<uint32_t>(instr);
2989 break;
2990 case SWP_x:
2991 case SWPA_x:
2992 case SWPL_x:
2993 case SWPAL_x:
2994 AtomicMemorySwapHelper<uint64_t>(instr);
2995 break;
2996 case LDAPRB:
2997 LoadAcquireRCpcHelper<uint8_t>(instr);
2998 break;
2999 case LDAPRH:
3000 LoadAcquireRCpcHelper<uint16_t>(instr);
3001 break;
3002 case LDAPR_w:
3003 LoadAcquireRCpcHelper<uint32_t>(instr);
3004 break;
3005 case LDAPR_x:
3006 LoadAcquireRCpcHelper<uint64_t>(instr);
3007 break;
3008 }
3009}
3010
Alexandre Ramesd3832962016-07-04 15:03:43 +01003011
3012void Simulator::VisitLoadLiteral(const Instruction* instr) {
3013 unsigned rt = instr->GetRt();
3014 uint64_t address = instr->GetLiteralAddress<uint64_t>();
3015
3016 // Verify that the calculated address is available to the host.
3017 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3018
3019 switch (instr->Mask(LoadLiteralMask)) {
3020 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
3021 // print a more detailed log.
3022 case LDR_w_lit:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00003023 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003024 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003025 break;
3026 case LDR_x_lit:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00003027 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003028 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003029 break;
3030 case LDR_s_lit:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00003031 WriteSRegister(rt, MemRead<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003032 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003033 break;
3034 case LDR_d_lit:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00003035 WriteDRegister(rt, MemRead<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003036 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003037 break;
3038 case LDR_q_lit:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00003039 WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003040 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003041 break;
3042 case LDRSW_x_lit:
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00003043 WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003044 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003045 break;
3046
3047 // Ignore prfm hint instructions.
3048 case PRFM_lit:
3049 break;
3050
3051 default:
3052 VIXL_UNREACHABLE();
3053 }
3054
3055 local_monitor_.MaybeClear();
3056}
3057
3058
3059uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
3060 int64_t offset,
3061 AddrMode addrmode) {
3062 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
3063
3064 if ((addr_reg == 31) && ((address % 16) != 0)) {
3065 // When the base register is SP the stack pointer is required to be
3066 // quadword aligned prior to the address calculation and write-backs.
3067 // Misalignment will cause a stack alignment fault.
3068 VIXL_ALIGNMENT_EXCEPTION();
3069 }
3070
3071 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
3072 VIXL_ASSERT(offset != 0);
3073 // Only preindex should log the register update here. For Postindex, the
3074 // update will be printed automatically by LogWrittenRegisters _after_ the
3075 // memory access itself is logged.
3076 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
3077 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
3078 }
3079
3080 if ((addrmode == Offset) || (addrmode == PreIndex)) {
3081 address += offset;
3082 }
3083
3084 // Verify that the calculated address is available to the host.
3085 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3086
3087 return static_cast<uintptr_t>(address);
3088}
3089
3090
3091void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
3092 MoveWideImmediateOp mov_op =
3093 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
3094 int64_t new_xn_val = 0;
3095
3096 bool is_64_bits = instr->GetSixtyFourBits() == 1;
3097 // Shift is limited for W operations.
3098 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
3099
3100 // Get the shifted immediate.
3101 int64_t shift = instr->GetShiftMoveWide() * 16;
3102 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
3103 << shift;
3104
3105 // Compute the new value.
3106 switch (mov_op) {
3107 case MOVN_w:
3108 case MOVN_x: {
3109 new_xn_val = ~shifted_imm16;
3110 if (!is_64_bits) new_xn_val &= kWRegMask;
3111 break;
3112 }
3113 case MOVK_w:
3114 case MOVK_x: {
3115 unsigned reg_code = instr->GetRd();
3116 int64_t prev_xn_val =
3117 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
3118 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
3119 break;
3120 }
3121 case MOVZ_w:
3122 case MOVZ_x: {
3123 new_xn_val = shifted_imm16;
3124 break;
3125 }
3126 default:
3127 VIXL_UNREACHABLE();
3128 }
3129
3130 // Update the destination register.
3131 WriteXRegister(instr->GetRd(), new_xn_val);
3132}
3133
3134
3135void Simulator::VisitConditionalSelect(const Instruction* instr) {
3136 uint64_t new_val = ReadXRegister(instr->GetRn());
3137
3138 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
3139 new_val = ReadXRegister(instr->GetRm());
3140 switch (instr->Mask(ConditionalSelectMask)) {
3141 case CSEL_w:
3142 case CSEL_x:
3143 break;
3144 case CSINC_w:
3145 case CSINC_x:
3146 new_val++;
3147 break;
3148 case CSINV_w:
3149 case CSINV_x:
3150 new_val = ~new_val;
3151 break;
3152 case CSNEG_w:
3153 case CSNEG_x:
3154 new_val = -new_val;
3155 break;
3156 default:
3157 VIXL_UNIMPLEMENTED();
3158 }
3159 }
3160 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3161 WriteRegister(reg_size, instr->GetRd(), new_val);
3162}
3163
3164
Jacob Bramleyca789742018-09-13 14:25:46 +01003165// clang-format off
3166#define PAUTH_MODES(V) \
3167 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
3168 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
3169 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
3170 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
3171 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
3172 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
3173 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
3174 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
3175// clang-format on
3176
Alexandre Ramesd3832962016-07-04 15:03:43 +01003177void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
3178 unsigned dst = instr->GetRd();
3179 unsigned src = instr->GetRn();
3180
3181 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003182#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
3183 case PAC##SUFFIX: { \
3184 uint64_t ptr = ReadXRegister(dst); \
3185 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
3186 break; \
3187 } \
3188 case AUT##SUFFIX: { \
3189 uint64_t ptr = ReadXRegister(dst); \
3190 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
3191 break; \
3192 }
3193
3194 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
3195#undef DEFINE_PAUTH_FUNCS
3196
3197 case XPACI:
3198 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
3199 break;
3200 case XPACD:
3201 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
3202 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003203 case RBIT_w:
3204 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
3205 break;
3206 case RBIT_x:
3207 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
3208 break;
3209 case REV16_w:
3210 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
3211 break;
3212 case REV16_x:
3213 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
3214 break;
3215 case REV_w:
3216 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
3217 break;
3218 case REV32_x:
3219 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
3220 break;
3221 case REV_x:
3222 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
3223 break;
3224 case CLZ_w:
3225 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
3226 break;
3227 case CLZ_x:
3228 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
3229 break;
3230 case CLS_w:
3231 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
3232 break;
3233 case CLS_x:
3234 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
3235 break;
3236 default:
3237 VIXL_UNIMPLEMENTED();
3238 }
3239}
3240
3241
3242uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
3243 VIXL_ASSERT((n > 32) && (n <= 64));
3244 for (unsigned i = (n - 1); i >= 32; i--) {
3245 if (((data >> i) & 1) != 0) {
3246 uint64_t polysh32 = (uint64_t)poly << (i - 32);
3247 uint64_t mask = (UINT64_C(1) << i) - 1;
3248 data = ((data & mask) ^ polysh32);
3249 }
3250 }
3251 return data & 0xffffffff;
3252}
3253
3254
3255template <typename T>
3256uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
3257 unsigned size = sizeof(val) * 8; // Number of bits in type T.
3258 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
3259 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
3260 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
3261 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
3262}
3263
3264
3265uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
3266 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
3267 // the CRC of each 32-bit word sequentially.
3268 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
3269 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
3270}
3271
3272
3273void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
3274 Shift shift_op = NO_SHIFT;
3275 int64_t result = 0;
3276 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3277
3278 switch (instr->Mask(DataProcessing2SourceMask)) {
3279 case SDIV_w: {
3280 int32_t rn = ReadWRegister(instr->GetRn());
3281 int32_t rm = ReadWRegister(instr->GetRm());
3282 if ((rn == kWMinInt) && (rm == -1)) {
3283 result = kWMinInt;
3284 } else if (rm == 0) {
3285 // Division by zero can be trapped, but not on A-class processors.
3286 result = 0;
3287 } else {
3288 result = rn / rm;
3289 }
3290 break;
3291 }
3292 case SDIV_x: {
3293 int64_t rn = ReadXRegister(instr->GetRn());
3294 int64_t rm = ReadXRegister(instr->GetRm());
3295 if ((rn == kXMinInt) && (rm == -1)) {
3296 result = kXMinInt;
3297 } else if (rm == 0) {
3298 // Division by zero can be trapped, but not on A-class processors.
3299 result = 0;
3300 } else {
3301 result = rn / rm;
3302 }
3303 break;
3304 }
3305 case UDIV_w: {
3306 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
3307 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
3308 if (rm == 0) {
3309 // Division by zero can be trapped, but not on A-class processors.
3310 result = 0;
3311 } else {
3312 result = rn / rm;
3313 }
3314 break;
3315 }
3316 case UDIV_x: {
3317 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3318 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
3319 if (rm == 0) {
3320 // Division by zero can be trapped, but not on A-class processors.
3321 result = 0;
3322 } else {
3323 result = rn / rm;
3324 }
3325 break;
3326 }
3327 case LSLV_w:
3328 case LSLV_x:
3329 shift_op = LSL;
3330 break;
3331 case LSRV_w:
3332 case LSRV_x:
3333 shift_op = LSR;
3334 break;
3335 case ASRV_w:
3336 case ASRV_x:
3337 shift_op = ASR;
3338 break;
3339 case RORV_w:
3340 case RORV_x:
3341 shift_op = ROR;
3342 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003343 case PACGA: {
3344 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3345 uint64_t src = static_cast<uint64_t>(
3346 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
3347 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
3348 result = code & 0xffffffff00000000;
3349 break;
3350 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003351 case CRC32B: {
3352 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3353 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3354 result = Crc32Checksum(acc, val, CRC32_POLY);
3355 break;
3356 }
3357 case CRC32H: {
3358 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3359 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3360 result = Crc32Checksum(acc, val, CRC32_POLY);
3361 break;
3362 }
3363 case CRC32W: {
3364 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3365 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3366 result = Crc32Checksum(acc, val, CRC32_POLY);
3367 break;
3368 }
3369 case CRC32X: {
3370 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3371 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3372 result = Crc32Checksum(acc, val, CRC32_POLY);
3373 reg_size = kWRegSize;
3374 break;
3375 }
3376 case CRC32CB: {
3377 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3378 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3379 result = Crc32Checksum(acc, val, CRC32C_POLY);
3380 break;
3381 }
3382 case CRC32CH: {
3383 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3384 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3385 result = Crc32Checksum(acc, val, CRC32C_POLY);
3386 break;
3387 }
3388 case CRC32CW: {
3389 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3390 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3391 result = Crc32Checksum(acc, val, CRC32C_POLY);
3392 break;
3393 }
3394 case CRC32CX: {
3395 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3396 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3397 result = Crc32Checksum(acc, val, CRC32C_POLY);
3398 reg_size = kWRegSize;
3399 break;
3400 }
3401 default:
3402 VIXL_UNIMPLEMENTED();
3403 }
3404
3405 if (shift_op != NO_SHIFT) {
3406 // Shift distance encoded in the least-significant five/six bits of the
3407 // register.
3408 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
3409 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
3410 result = ShiftOperand(reg_size,
3411 ReadRegister(reg_size, instr->GetRn()),
3412 shift_op,
3413 shift);
3414 }
3415 WriteRegister(reg_size, instr->GetRd(), result);
3416}
3417
3418
Alexandre Ramesd3832962016-07-04 15:03:43 +01003419void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
3420 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3421
3422 uint64_t result = 0;
3423 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
3424 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
3425 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
3426 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
3427 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003428 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
3429 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003430 switch (instr->Mask(DataProcessing3SourceMask)) {
3431 case MADD_w:
3432 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003433 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003434 break;
3435 case MSUB_w:
3436 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003437 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003438 break;
3439 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003440 result = ReadXRegister(instr->GetRa()) +
3441 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003442 break;
3443 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003444 result = ReadXRegister(instr->GetRa()) -
3445 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003446 break;
3447 case UMADDL_x:
3448 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
3449 break;
3450 case UMSUBL_x:
3451 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
3452 break;
3453 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003454 result =
3455 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
3456 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003457 break;
3458 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003459 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
3460 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003461 break;
3462 default:
3463 VIXL_UNIMPLEMENTED();
3464 }
3465 WriteRegister(reg_size, instr->GetRd(), result);
3466}
3467
3468
3469void Simulator::VisitBitfield(const Instruction* instr) {
3470 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3471 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003472 int R = instr->GetImmR();
3473 int S = instr->GetImmS();
3474 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003475 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003476 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003477 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003478 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003479 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003480 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003481 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003482 diff += reg_size;
3483 }
3484
3485 // inzero indicates if the extracted bitfield is inserted into the
3486 // destination register value or in zero.
3487 // If extend is true, extend the sign of the extracted bitfield.
3488 bool inzero = false;
3489 bool extend = false;
3490 switch (instr->Mask(BitfieldMask)) {
3491 case BFM_x:
3492 case BFM_w:
3493 break;
3494 case SBFM_x:
3495 case SBFM_w:
3496 inzero = true;
3497 extend = true;
3498 break;
3499 case UBFM_x:
3500 case UBFM_w:
3501 inzero = true;
3502 break;
3503 default:
3504 VIXL_UNIMPLEMENTED();
3505 }
3506
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003507 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
3508 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003509 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003510 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003511 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003512 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
3513 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003514
3515 // Merge sign extension, dest/zero and bitfield.
3516 result = signbits | (result & mask) | (dst & ~mask);
3517
3518 WriteRegister(reg_size, instr->GetRd(), result);
3519}
3520
3521
3522void Simulator::VisitExtract(const Instruction* instr) {
3523 unsigned lsb = instr->GetImmS();
3524 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3525 uint64_t low_res =
3526 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Jacob Bramley2fe55ec2020-03-20 17:03:48 +00003527 uint64_t high_res = (lsb == 0)
3528 ? 0
3529 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
3530 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003531 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
3532}
3533
3534
3535void Simulator::VisitFPImmediate(const Instruction* instr) {
3536 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01003537 unsigned dest = instr->GetRd();
3538 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003539 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01003540 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01003541 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003542 case FMOV_s_imm:
3543 WriteSRegister(dest, instr->GetImmFP32());
3544 break;
3545 case FMOV_d_imm:
3546 WriteDRegister(dest, instr->GetImmFP64());
3547 break;
3548 default:
3549 VIXL_UNREACHABLE();
3550 }
3551}
3552
3553
3554void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
3555 AssertSupportedFPCR();
3556
3557 unsigned dst = instr->GetRd();
3558 unsigned src = instr->GetRn();
3559
3560 FPRounding round = ReadRMode();
3561
3562 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003563 case FCVTAS_wh:
3564 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
3565 break;
3566 case FCVTAS_xh:
3567 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
3568 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003569 case FCVTAS_ws:
3570 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
3571 break;
3572 case FCVTAS_xs:
3573 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
3574 break;
3575 case FCVTAS_wd:
3576 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
3577 break;
3578 case FCVTAS_xd:
3579 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
3580 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003581 case FCVTAU_wh:
3582 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
3583 break;
3584 case FCVTAU_xh:
3585 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
3586 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003587 case FCVTAU_ws:
3588 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3589 break;
3590 case FCVTAU_xs:
3591 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3592 break;
3593 case FCVTAU_wd:
3594 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3595 break;
3596 case FCVTAU_xd:
3597 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3598 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003599 case FCVTMS_wh:
3600 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3601 break;
3602 case FCVTMS_xh:
3603 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3604 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003605 case FCVTMS_ws:
3606 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3607 break;
3608 case FCVTMS_xs:
3609 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3610 break;
3611 case FCVTMS_wd:
3612 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3613 break;
3614 case FCVTMS_xd:
3615 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3616 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003617 case FCVTMU_wh:
3618 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3619 break;
3620 case FCVTMU_xh:
3621 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3622 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003623 case FCVTMU_ws:
3624 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3625 break;
3626 case FCVTMU_xs:
3627 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3628 break;
3629 case FCVTMU_wd:
3630 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3631 break;
3632 case FCVTMU_xd:
3633 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3634 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003635 case FCVTPS_wh:
3636 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3637 break;
3638 case FCVTPS_xh:
3639 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3640 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003641 case FCVTPS_ws:
3642 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3643 break;
3644 case FCVTPS_xs:
3645 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3646 break;
3647 case FCVTPS_wd:
3648 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3649 break;
3650 case FCVTPS_xd:
3651 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3652 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003653 case FCVTPU_wh:
3654 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3655 break;
3656 case FCVTPU_xh:
3657 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3658 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003659 case FCVTPU_ws:
3660 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3661 break;
3662 case FCVTPU_xs:
3663 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3664 break;
3665 case FCVTPU_wd:
3666 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3667 break;
3668 case FCVTPU_xd:
3669 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3670 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003671 case FCVTNS_wh:
3672 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3673 break;
3674 case FCVTNS_xh:
3675 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3676 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003677 case FCVTNS_ws:
3678 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3679 break;
3680 case FCVTNS_xs:
3681 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3682 break;
3683 case FCVTNS_wd:
3684 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3685 break;
3686 case FCVTNS_xd:
3687 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3688 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003689 case FCVTNU_wh:
3690 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3691 break;
3692 case FCVTNU_xh:
3693 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3694 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003695 case FCVTNU_ws:
3696 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3697 break;
3698 case FCVTNU_xs:
3699 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3700 break;
3701 case FCVTNU_wd:
3702 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3703 break;
3704 case FCVTNU_xd:
3705 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3706 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003707 case FCVTZS_wh:
3708 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3709 break;
3710 case FCVTZS_xh:
3711 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3712 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003713 case FCVTZS_ws:
3714 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3715 break;
3716 case FCVTZS_xs:
3717 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3718 break;
3719 case FCVTZS_wd:
3720 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3721 break;
3722 case FCVTZS_xd:
3723 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3724 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003725 case FCVTZU_wh:
3726 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3727 break;
3728 case FCVTZU_xh:
3729 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3730 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003731 case FCVTZU_ws:
3732 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3733 break;
3734 case FCVTZU_xs:
3735 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3736 break;
3737 case FCVTZU_wd:
3738 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3739 break;
3740 case FCVTZU_xd:
3741 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3742 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003743 case FJCVTZS:
3744 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3745 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003746 case FMOV_hw:
3747 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3748 break;
3749 case FMOV_wh:
3750 WriteWRegister(dst, ReadHRegisterBits(src));
3751 break;
3752 case FMOV_xh:
3753 WriteXRegister(dst, ReadHRegisterBits(src));
3754 break;
3755 case FMOV_hx:
3756 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3757 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003758 case FMOV_ws:
3759 WriteWRegister(dst, ReadSRegisterBits(src));
3760 break;
3761 case FMOV_xd:
3762 WriteXRegister(dst, ReadDRegisterBits(src));
3763 break;
3764 case FMOV_sw:
3765 WriteSRegisterBits(dst, ReadWRegister(src));
3766 break;
3767 case FMOV_dx:
3768 WriteDRegisterBits(dst, ReadXRegister(src));
3769 break;
3770 case FMOV_d1_x:
3771 LogicVRegister(ReadVRegister(dst))
3772 .SetUint(kFormatD, 1, ReadXRegister(src));
3773 break;
3774 case FMOV_x_d1:
3775 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3776 break;
3777
3778 // A 32-bit input can be handled in the same way as a 64-bit input, since
3779 // the sign- or zero-extension will not affect the conversion.
3780 case SCVTF_dx:
3781 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3782 break;
3783 case SCVTF_dw:
3784 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3785 break;
3786 case UCVTF_dx:
3787 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3788 break;
3789 case UCVTF_dw: {
3790 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003791 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003792 break;
3793 }
3794 case SCVTF_sx:
3795 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3796 break;
3797 case SCVTF_sw:
3798 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3799 break;
3800 case UCVTF_sx:
3801 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3802 break;
3803 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01003804 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3805 break;
3806 }
3807 case SCVTF_hx:
3808 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3809 break;
3810 case SCVTF_hw:
3811 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3812 break;
3813 case UCVTF_hx:
3814 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3815 break;
3816 case UCVTF_hw: {
3817 WriteHRegister(dst,
3818 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003819 break;
3820 }
3821
3822 default:
3823 VIXL_UNREACHABLE();
3824 }
3825}
3826
3827
3828void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3829 AssertSupportedFPCR();
3830
3831 unsigned dst = instr->GetRd();
3832 unsigned src = instr->GetRn();
3833 int fbits = 64 - instr->GetFPScale();
3834
3835 FPRounding round = ReadRMode();
3836
3837 switch (instr->Mask(FPFixedPointConvertMask)) {
3838 // A 32-bit input can be handled in the same way as a 64-bit input, since
3839 // the sign- or zero-extension will not affect the conversion.
3840 case SCVTF_dx_fixed:
3841 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3842 break;
3843 case SCVTF_dw_fixed:
3844 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3845 break;
3846 case UCVTF_dx_fixed:
3847 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3848 break;
3849 case UCVTF_dw_fixed: {
3850 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003851 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003852 break;
3853 }
3854 case SCVTF_sx_fixed:
3855 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3856 break;
3857 case SCVTF_sw_fixed:
3858 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3859 break;
3860 case UCVTF_sx_fixed:
3861 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3862 break;
3863 case UCVTF_sw_fixed: {
3864 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003865 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3866 break;
3867 }
3868 case SCVTF_hx_fixed:
3869 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3870 break;
3871 case SCVTF_hw_fixed:
3872 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3873 break;
3874 case UCVTF_hx_fixed:
3875 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3876 break;
3877 case UCVTF_hw_fixed: {
3878 WriteHRegister(dst,
3879 UFixedToFloat16(ReadRegister<uint32_t>(src),
3880 fbits,
3881 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003882 break;
3883 }
3884 case FCVTZS_xd_fixed:
3885 WriteXRegister(dst,
3886 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3887 FPZero));
3888 break;
3889 case FCVTZS_wd_fixed:
3890 WriteWRegister(dst,
3891 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3892 FPZero));
3893 break;
3894 case FCVTZU_xd_fixed:
3895 WriteXRegister(dst,
3896 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3897 FPZero));
3898 break;
3899 case FCVTZU_wd_fixed:
3900 WriteWRegister(dst,
3901 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3902 FPZero));
3903 break;
3904 case FCVTZS_xs_fixed:
3905 WriteXRegister(dst,
3906 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3907 FPZero));
3908 break;
3909 case FCVTZS_ws_fixed:
3910 WriteWRegister(dst,
3911 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3912 FPZero));
3913 break;
3914 case FCVTZU_xs_fixed:
3915 WriteXRegister(dst,
3916 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3917 FPZero));
3918 break;
3919 case FCVTZU_ws_fixed:
3920 WriteWRegister(dst,
3921 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3922 FPZero));
3923 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003924 case FCVTZS_xh_fixed: {
3925 double output =
3926 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3927 WriteXRegister(dst, FPToInt64(output, FPZero));
3928 break;
3929 }
3930 case FCVTZS_wh_fixed: {
3931 double output =
3932 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3933 WriteWRegister(dst, FPToInt32(output, FPZero));
3934 break;
3935 }
3936 case FCVTZU_xh_fixed: {
3937 double output =
3938 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3939 WriteXRegister(dst, FPToUInt64(output, FPZero));
3940 break;
3941 }
3942 case FCVTZU_wh_fixed: {
3943 double output =
3944 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3945 WriteWRegister(dst, FPToUInt32(output, FPZero));
3946 break;
3947 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003948 default:
3949 VIXL_UNREACHABLE();
3950 }
3951}
3952
3953
3954void Simulator::VisitFPCompare(const Instruction* instr) {
3955 AssertSupportedFPCR();
3956
3957 FPTrapFlags trap = DisableTrap;
3958 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003959 case FCMPE_h:
3960 trap = EnableTrap;
3961 VIXL_FALLTHROUGH();
3962 case FCMP_h:
3963 FPCompare(ReadHRegister(instr->GetRn()),
3964 ReadHRegister(instr->GetRm()),
3965 trap);
3966 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003967 case FCMPE_s:
3968 trap = EnableTrap;
3969 VIXL_FALLTHROUGH();
3970 case FCMP_s:
3971 FPCompare(ReadSRegister(instr->GetRn()),
3972 ReadSRegister(instr->GetRm()),
3973 trap);
3974 break;
3975 case FCMPE_d:
3976 trap = EnableTrap;
3977 VIXL_FALLTHROUGH();
3978 case FCMP_d:
3979 FPCompare(ReadDRegister(instr->GetRn()),
3980 ReadDRegister(instr->GetRm()),
3981 trap);
3982 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003983 case FCMPE_h_zero:
3984 trap = EnableTrap;
3985 VIXL_FALLTHROUGH();
3986 case FCMP_h_zero:
3987 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3988 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003989 case FCMPE_s_zero:
3990 trap = EnableTrap;
3991 VIXL_FALLTHROUGH();
3992 case FCMP_s_zero:
3993 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3994 break;
3995 case FCMPE_d_zero:
3996 trap = EnableTrap;
3997 VIXL_FALLTHROUGH();
3998 case FCMP_d_zero:
3999 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
4000 break;
4001 default:
4002 VIXL_UNIMPLEMENTED();
4003 }
4004}
4005
4006
4007void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
4008 AssertSupportedFPCR();
4009
4010 FPTrapFlags trap = DisableTrap;
4011 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004012 case FCCMPE_h:
4013 trap = EnableTrap;
4014 VIXL_FALLTHROUGH();
4015 case FCCMP_h:
4016 if (ConditionPassed(instr->GetCondition())) {
4017 FPCompare(ReadHRegister(instr->GetRn()),
4018 ReadHRegister(instr->GetRm()),
4019 trap);
4020 } else {
4021 ReadNzcv().SetFlags(instr->GetNzcv());
4022 LogSystemRegister(NZCV);
4023 }
4024 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004025 case FCCMPE_s:
4026 trap = EnableTrap;
4027 VIXL_FALLTHROUGH();
4028 case FCCMP_s:
4029 if (ConditionPassed(instr->GetCondition())) {
4030 FPCompare(ReadSRegister(instr->GetRn()),
4031 ReadSRegister(instr->GetRm()),
4032 trap);
4033 } else {
4034 ReadNzcv().SetFlags(instr->GetNzcv());
4035 LogSystemRegister(NZCV);
4036 }
4037 break;
4038 case FCCMPE_d:
4039 trap = EnableTrap;
4040 VIXL_FALLTHROUGH();
4041 case FCCMP_d:
4042 if (ConditionPassed(instr->GetCondition())) {
4043 FPCompare(ReadDRegister(instr->GetRn()),
4044 ReadDRegister(instr->GetRm()),
4045 trap);
4046 } else {
4047 ReadNzcv().SetFlags(instr->GetNzcv());
4048 LogSystemRegister(NZCV);
4049 }
4050 break;
4051 default:
4052 VIXL_UNIMPLEMENTED();
4053 }
4054}
4055
4056
4057void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
4058 AssertSupportedFPCR();
4059
4060 Instr selected;
4061 if (ConditionPassed(instr->GetCondition())) {
4062 selected = instr->GetRn();
4063 } else {
4064 selected = instr->GetRm();
4065 }
4066
4067 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004068 case FCSEL_h:
4069 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
4070 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004071 case FCSEL_s:
4072 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
4073 break;
4074 case FCSEL_d:
4075 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
4076 break;
4077 default:
4078 VIXL_UNIMPLEMENTED();
4079 }
4080}
4081
4082
4083void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
4084 AssertSupportedFPCR();
4085
4086 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01004087 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01004088 switch (instr->Mask(FPTypeMask)) {
4089 default:
4090 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4091 case FP64:
4092 vform = kFormatD;
4093 break;
4094 case FP32:
4095 vform = kFormatS;
4096 break;
4097 case FP16:
4098 vform = kFormatH;
4099 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004100 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004101
Alexandre Ramesd3832962016-07-04 15:03:43 +01004102 SimVRegister& rd = ReadVRegister(instr->GetRd());
4103 SimVRegister& rn = ReadVRegister(instr->GetRn());
4104 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004105 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004106
4107 unsigned fd = instr->GetRd();
4108 unsigned fn = instr->GetRn();
4109
4110 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01004111 case FMOV_h:
4112 WriteHRegister(fd, ReadHRegister(fn));
4113 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004114 case FMOV_s:
4115 WriteSRegister(fd, ReadSRegister(fn));
4116 return;
4117 case FMOV_d:
4118 WriteDRegister(fd, ReadDRegister(fn));
4119 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004120 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004121 case FABS_s:
4122 case FABS_d:
4123 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
4124 // Explicitly log the register update whilst we have type information.
4125 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4126 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004127 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004128 case FNEG_s:
4129 case FNEG_d:
4130 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
4131 // Explicitly log the register update whilst we have type information.
4132 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4133 return;
4134 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01004135 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004136 return;
4137 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01004138 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004139 return;
4140 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01004141 WriteHRegister(fd,
4142 Float16ToRawbits(
4143 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004144 return;
4145 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01004146 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004147 return;
4148 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01004149 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004150 return;
4151 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01004152 WriteHRegister(fd,
4153 Float16ToRawbits(
4154 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004155 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004156 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004157 case FSQRT_s:
4158 case FSQRT_d:
4159 fsqrt(vform, rd, rn);
4160 // Explicitly log the register update whilst we have type information.
4161 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4162 return;
TatWai Chong04471812019-03-19 14:29:00 -07004163 case FRINT32X_s:
4164 case FRINT32X_d:
4165 inexact_exception = true;
4166 frint_mode = kFrintToInt32;
4167 break; // Use FPCR rounding mode.
4168 case FRINT64X_s:
4169 case FRINT64X_d:
4170 inexact_exception = true;
4171 frint_mode = kFrintToInt64;
4172 break; // Use FPCR rounding mode.
4173 case FRINT32Z_s:
4174 case FRINT32Z_d:
4175 inexact_exception = true;
4176 frint_mode = kFrintToInt32;
4177 fpcr_rounding = FPZero;
4178 break;
4179 case FRINT64Z_s:
4180 case FRINT64Z_d:
4181 inexact_exception = true;
4182 frint_mode = kFrintToInt64;
4183 fpcr_rounding = FPZero;
4184 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004185 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004186 case FRINTI_s:
4187 case FRINTI_d:
4188 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01004189 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004190 case FRINTX_s:
4191 case FRINTX_d:
4192 inexact_exception = true;
4193 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004194 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004195 case FRINTA_s:
4196 case FRINTA_d:
4197 fpcr_rounding = FPTieAway;
4198 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004199 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004200 case FRINTM_s:
4201 case FRINTM_d:
4202 fpcr_rounding = FPNegativeInfinity;
4203 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004204 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004205 case FRINTN_s:
4206 case FRINTN_d:
4207 fpcr_rounding = FPTieEven;
4208 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004209 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004210 case FRINTP_s:
4211 case FRINTP_d:
4212 fpcr_rounding = FPPositiveInfinity;
4213 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004214 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004215 case FRINTZ_s:
4216 case FRINTZ_d:
4217 fpcr_rounding = FPZero;
4218 break;
4219 default:
4220 VIXL_UNIMPLEMENTED();
4221 }
4222
4223 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004224 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004225 // Explicitly log the register update whilst we have type information.
4226 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4227}
4228
4229
4230void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
4231 AssertSupportedFPCR();
4232
Carey Williamsd8bb3572018-04-10 11:58:07 +01004233 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01004234 switch (instr->Mask(FPTypeMask)) {
4235 default:
4236 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4237 case FP64:
4238 vform = kFormatD;
4239 break;
4240 case FP32:
4241 vform = kFormatS;
4242 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004243 case FP16:
4244 vform = kFormatH;
4245 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004246 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004247 SimVRegister& rd = ReadVRegister(instr->GetRd());
4248 SimVRegister& rn = ReadVRegister(instr->GetRn());
4249 SimVRegister& rm = ReadVRegister(instr->GetRm());
4250
4251 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004252 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004253 case FADD_s:
4254 case FADD_d:
4255 fadd(vform, rd, rn, rm);
4256 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004257 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004258 case FSUB_s:
4259 case FSUB_d:
4260 fsub(vform, rd, rn, rm);
4261 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004262 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004263 case FMUL_s:
4264 case FMUL_d:
4265 fmul(vform, rd, rn, rm);
4266 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004267 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004268 case FNMUL_s:
4269 case FNMUL_d:
4270 fnmul(vform, rd, rn, rm);
4271 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004272 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004273 case FDIV_s:
4274 case FDIV_d:
4275 fdiv(vform, rd, rn, rm);
4276 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004277 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004278 case FMAX_s:
4279 case FMAX_d:
4280 fmax(vform, rd, rn, rm);
4281 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004282 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004283 case FMIN_s:
4284 case FMIN_d:
4285 fmin(vform, rd, rn, rm);
4286 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004287 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004288 case FMAXNM_s:
4289 case FMAXNM_d:
4290 fmaxnm(vform, rd, rn, rm);
4291 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004292 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004293 case FMINNM_s:
4294 case FMINNM_d:
4295 fminnm(vform, rd, rn, rm);
4296 break;
4297 default:
4298 VIXL_UNREACHABLE();
4299 }
4300 // Explicitly log the register update whilst we have type information.
4301 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
4302}
4303
4304
4305void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
4306 AssertSupportedFPCR();
4307
4308 unsigned fd = instr->GetRd();
4309 unsigned fn = instr->GetRn();
4310 unsigned fm = instr->GetRm();
4311 unsigned fa = instr->GetRa();
4312
4313 switch (instr->Mask(FPDataProcessing3SourceMask)) {
4314 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01004315 case FMADD_h:
4316 WriteHRegister(fd,
4317 FPMulAdd(ReadHRegister(fa),
4318 ReadHRegister(fn),
4319 ReadHRegister(fm)));
4320 break;
4321 case FMSUB_h:
4322 WriteHRegister(fd,
4323 FPMulAdd(ReadHRegister(fa),
4324 -ReadHRegister(fn),
4325 ReadHRegister(fm)));
4326 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004327 case FMADD_s:
4328 WriteSRegister(fd,
4329 FPMulAdd(ReadSRegister(fa),
4330 ReadSRegister(fn),
4331 ReadSRegister(fm)));
4332 break;
4333 case FMSUB_s:
4334 WriteSRegister(fd,
4335 FPMulAdd(ReadSRegister(fa),
4336 -ReadSRegister(fn),
4337 ReadSRegister(fm)));
4338 break;
4339 case FMADD_d:
4340 WriteDRegister(fd,
4341 FPMulAdd(ReadDRegister(fa),
4342 ReadDRegister(fn),
4343 ReadDRegister(fm)));
4344 break;
4345 case FMSUB_d:
4346 WriteDRegister(fd,
4347 FPMulAdd(ReadDRegister(fa),
4348 -ReadDRegister(fn),
4349 ReadDRegister(fm)));
4350 break;
4351 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01004352 case FNMADD_h:
4353 WriteHRegister(fd,
4354 FPMulAdd(-ReadHRegister(fa),
4355 -ReadHRegister(fn),
4356 ReadHRegister(fm)));
4357 break;
4358 case FNMSUB_h:
4359 WriteHRegister(fd,
4360 FPMulAdd(-ReadHRegister(fa),
4361 ReadHRegister(fn),
4362 ReadHRegister(fm)));
4363 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004364 case FNMADD_s:
4365 WriteSRegister(fd,
4366 FPMulAdd(-ReadSRegister(fa),
4367 -ReadSRegister(fn),
4368 ReadSRegister(fm)));
4369 break;
4370 case FNMSUB_s:
4371 WriteSRegister(fd,
4372 FPMulAdd(-ReadSRegister(fa),
4373 ReadSRegister(fn),
4374 ReadSRegister(fm)));
4375 break;
4376 case FNMADD_d:
4377 WriteDRegister(fd,
4378 FPMulAdd(-ReadDRegister(fa),
4379 -ReadDRegister(fn),
4380 ReadDRegister(fm)));
4381 break;
4382 case FNMSUB_d:
4383 WriteDRegister(fd,
4384 FPMulAdd(-ReadDRegister(fa),
4385 ReadDRegister(fn),
4386 ReadDRegister(fm)));
4387 break;
4388 default:
4389 VIXL_UNIMPLEMENTED();
4390 }
4391}
4392
4393
4394bool Simulator::FPProcessNaNs(const Instruction* instr) {
4395 unsigned fd = instr->GetRd();
4396 unsigned fn = instr->GetRn();
4397 unsigned fm = instr->GetRm();
4398 bool done = false;
4399
4400 if (instr->Mask(FP64) == FP64) {
4401 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004402 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004403 WriteDRegister(fd, result);
4404 done = true;
4405 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004406 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004407 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004408 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004409 WriteSRegister(fd, result);
4410 done = true;
4411 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004412 } else {
4413 VIXL_ASSERT(instr->Mask(FP16) == FP16);
4414 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01004415 }
4416
4417 return done;
4418}
4419
4420
4421void Simulator::SysOp_W(int op, int64_t val) {
4422 switch (op) {
4423 case IVAU:
4424 case CVAC:
4425 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01004426 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08004427 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004428 case CIVAC: {
4429 // Perform a dummy memory access to ensure that we have read access
4430 // to the specified address.
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00004431 volatile uint8_t y = MemRead<uint8_t>(val);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004432 USE(y);
4433 // TODO: Implement "case ZVA:".
4434 break;
4435 }
4436 default:
4437 VIXL_UNIMPLEMENTED();
4438 }
4439}
4440
4441
Jacob Bramleyca789742018-09-13 14:25:46 +01004442// clang-format off
4443#define PAUTH_SYSTEM_MODES(V) \
4444 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
4445 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
4446 V(AZ, 30, 0x00000000, kPACKeyIA) \
4447 V(BZ, 30, 0x00000000, kPACKeyIB) \
4448 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
4449 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
4450// clang-format on
4451
4452
Alexandre Ramesd3832962016-07-04 15:03:43 +01004453void Simulator::VisitSystem(const Instruction* instr) {
4454 // Some system instructions hijack their Op and Cp fields to represent a
4455 // range of immediates instead of indicating a different instruction. This
4456 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01004457 if (instr->GetInstructionBits() == XPACLRI) {
4458 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00004459 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
4460 switch (instr->Mask(SystemPStateMask)) {
4461 case CFINV:
4462 ReadNzcv().SetC(!ReadC());
4463 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00004464 case AXFLAG:
4465 ReadNzcv().SetN(0);
4466 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
4467 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
4468 ReadNzcv().SetV(0);
4469 break;
4470 case XAFLAG: {
4471 // Can't set the flags in place due to the logical dependencies.
4472 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
4473 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
4474 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
4475 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
4476 ReadNzcv().SetN(n);
4477 ReadNzcv().SetZ(z);
4478 ReadNzcv().SetC(c);
4479 ReadNzcv().SetV(v);
4480 break;
4481 }
Alexander Gilday2487f142018-11-05 13:07:27 +00004482 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004483 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004484 // Check BType allows PACI[AB]SP instructions.
4485 if (PcIsInGuardedPage()) {
4486 Instr i = instr->Mask(SystemPAuthMask);
4487 if ((i == PACIASP) || (i == PACIBSP)) {
4488 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004489 case BranchFromGuardedNotToIP:
4490 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
4491 // assume here to be zero. This allows execution of PACI[AB]SP when
4492 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00004493 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004494 case BranchFromUnguardedOrToIP:
4495 case BranchAndLink:
4496 break;
4497 }
4498 }
4499 }
4500
Jacob Bramleyca789742018-09-13 14:25:46 +01004501 switch (instr->Mask(SystemPAuthMask)) {
4502#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
4503 case PACI##SUFFIX: \
4504 WriteXRegister(DST, \
4505 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
4506 break; \
4507 case AUTI##SUFFIX: \
4508 WriteXRegister(DST, \
4509 AuthPAC(ReadXRegister(DST), \
4510 MOD, \
4511 KEY, \
4512 kInstructionPointer)); \
4513 break;
4514
4515 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
4516#undef DEFINE_PAUTH_FUNCS
4517 }
4518 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
4519 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004520 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
4521 switch (instr->Mask(SystemExclusiveMonitorMask)) {
4522 case CLREX: {
4523 PrintExclusiveAccessWarning();
4524 ClearLocalMonitor();
4525 break;
4526 }
4527 }
4528 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
4529 switch (instr->Mask(SystemSysRegMask)) {
4530 case MRS: {
4531 switch (instr->GetImmSystemRegister()) {
4532 case NZCV:
4533 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
4534 break;
4535 case FPCR:
4536 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
4537 break;
TatWai Chong04edf682018-12-27 16:01:02 -08004538 case RNDR:
4539 case RNDRRS: {
Jacob Bramley85a9c102019-12-09 17:48:29 +00004540 uint64_t high = jrand48(rand_state_);
4541 uint64_t low = jrand48(rand_state_);
TatWai Chong04edf682018-12-27 16:01:02 -08004542 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
4543 WriteXRegister(instr->GetRt(), rand_num);
4544 // Simulate successful random number generation.
4545 // TODO: Return failure occasionally as a random number cannot be
4546 // returned in a period of time.
4547 ReadNzcv().SetRawValue(NoFlag);
4548 LogSystemRegister(NZCV);
4549 break;
4550 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004551 default:
4552 VIXL_UNIMPLEMENTED();
4553 }
4554 break;
4555 }
4556 case MSR: {
4557 switch (instr->GetImmSystemRegister()) {
4558 case NZCV:
4559 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
4560 LogSystemRegister(NZCV);
4561 break;
4562 case FPCR:
4563 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
4564 LogSystemRegister(FPCR);
4565 break;
4566 default:
4567 VIXL_UNIMPLEMENTED();
4568 }
4569 break;
4570 }
4571 }
4572 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
4573 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
4574 switch (instr->GetImmHint()) {
4575 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01004576 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00004577 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004578 case BTI_jc:
4579 break;
4580 case BTI:
4581 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
4582 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
4583 }
4584 break;
4585 case BTI_c:
4586 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
4587 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
4588 }
4589 break;
4590 case BTI_j:
4591 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4592 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4593 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004594 break;
4595 default:
4596 VIXL_UNIMPLEMENTED();
4597 }
4598 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4599 __sync_synchronize();
4600 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4601 switch (instr->Mask(SystemSysMask)) {
4602 case SYS:
4603 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4604 break;
4605 default:
4606 VIXL_UNIMPLEMENTED();
4607 }
4608 } else {
4609 VIXL_UNIMPLEMENTED();
4610 }
4611}
4612
4613
4614void Simulator::VisitException(const Instruction* instr) {
4615 switch (instr->Mask(ExceptionMask)) {
4616 case HLT:
4617 switch (instr->GetImmException()) {
4618 case kUnreachableOpcode:
4619 DoUnreachable(instr);
4620 return;
4621 case kTraceOpcode:
4622 DoTrace(instr);
4623 return;
4624 case kLogOpcode:
4625 DoLog(instr);
4626 return;
4627 case kPrintfOpcode:
4628 DoPrintf(instr);
4629 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01004630 case kRuntimeCallOpcode:
4631 DoRuntimeCall(instr);
4632 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01004633 case kSetCPUFeaturesOpcode:
4634 case kEnableCPUFeaturesOpcode:
4635 case kDisableCPUFeaturesOpcode:
4636 DoConfigureCPUFeatures(instr);
4637 return;
4638 case kSaveCPUFeaturesOpcode:
4639 DoSaveCPUFeatures(instr);
4640 return;
4641 case kRestoreCPUFeaturesOpcode:
4642 DoRestoreCPUFeatures(instr);
4643 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004644 default:
4645 HostBreakpoint();
4646 return;
4647 }
4648 case BRK:
4649 HostBreakpoint();
4650 return;
4651 default:
4652 VIXL_UNIMPLEMENTED();
4653 }
4654}
4655
4656
4657void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4658 VisitUnimplemented(instr);
4659}
4660
4661
4662void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4663 VisitUnimplemented(instr);
4664}
4665
4666
4667void Simulator::VisitCryptoAES(const Instruction* instr) {
4668 VisitUnimplemented(instr);
4669}
4670
4671
4672void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4673 NEONFormatDecoder nfd(instr);
4674 VectorFormat vf = nfd.GetVectorFormat();
4675
4676 static const NEONFormatMap map_lp =
4677 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4678 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4679
4680 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4681 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4682
4683 static const NEONFormatMap map_fcvtn = {{22, 30},
4684 {NF_4H, NF_8H, NF_2S, NF_4S}};
4685 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4686
4687 SimVRegister& rd = ReadVRegister(instr->GetRd());
4688 SimVRegister& rn = ReadVRegister(instr->GetRn());
4689
4690 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4691 // These instructions all use a two bit size field, except NOT and RBIT,
4692 // which use the field to encode the operation.
4693 switch (instr->Mask(NEON2RegMiscMask)) {
4694 case NEON_REV64:
4695 rev64(vf, rd, rn);
4696 break;
4697 case NEON_REV32:
4698 rev32(vf, rd, rn);
4699 break;
4700 case NEON_REV16:
4701 rev16(vf, rd, rn);
4702 break;
4703 case NEON_SUQADD:
4704 suqadd(vf, rd, rn);
4705 break;
4706 case NEON_USQADD:
4707 usqadd(vf, rd, rn);
4708 break;
4709 case NEON_CLS:
4710 cls(vf, rd, rn);
4711 break;
4712 case NEON_CLZ:
4713 clz(vf, rd, rn);
4714 break;
4715 case NEON_CNT:
4716 cnt(vf, rd, rn);
4717 break;
4718 case NEON_SQABS:
4719 abs(vf, rd, rn).SignedSaturate(vf);
4720 break;
4721 case NEON_SQNEG:
4722 neg(vf, rd, rn).SignedSaturate(vf);
4723 break;
4724 case NEON_CMGT_zero:
4725 cmp(vf, rd, rn, 0, gt);
4726 break;
4727 case NEON_CMGE_zero:
4728 cmp(vf, rd, rn, 0, ge);
4729 break;
4730 case NEON_CMEQ_zero:
4731 cmp(vf, rd, rn, 0, eq);
4732 break;
4733 case NEON_CMLE_zero:
4734 cmp(vf, rd, rn, 0, le);
4735 break;
4736 case NEON_CMLT_zero:
4737 cmp(vf, rd, rn, 0, lt);
4738 break;
4739 case NEON_ABS:
4740 abs(vf, rd, rn);
4741 break;
4742 case NEON_NEG:
4743 neg(vf, rd, rn);
4744 break;
4745 case NEON_SADDLP:
4746 saddlp(vf_lp, rd, rn);
4747 break;
4748 case NEON_UADDLP:
4749 uaddlp(vf_lp, rd, rn);
4750 break;
4751 case NEON_SADALP:
4752 sadalp(vf_lp, rd, rn);
4753 break;
4754 case NEON_UADALP:
4755 uadalp(vf_lp, rd, rn);
4756 break;
4757 case NEON_RBIT_NOT:
4758 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4759 switch (instr->GetFPType()) {
4760 case 0:
4761 not_(vf, rd, rn);
4762 break;
4763 case 1:
4764 rbit(vf, rd, rn);
4765 break;
4766 default:
4767 VIXL_UNIMPLEMENTED();
4768 }
4769 break;
4770 }
4771 } else {
4772 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4773 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4774 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004775 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004776
4777 // These instructions all use a one bit size field, except XTN, SQXTUN,
4778 // SHLL, SQXTN and UQXTN, which use a two bit size field.
4779 switch (instr->Mask(NEON2RegMiscFPMask)) {
4780 case NEON_FABS:
4781 fabs_(fpf, rd, rn);
4782 return;
4783 case NEON_FNEG:
4784 fneg(fpf, rd, rn);
4785 return;
4786 case NEON_FSQRT:
4787 fsqrt(fpf, rd, rn);
4788 return;
4789 case NEON_FCVTL:
4790 if (instr->Mask(NEON_Q)) {
4791 fcvtl2(vf_fcvtl, rd, rn);
4792 } else {
4793 fcvtl(vf_fcvtl, rd, rn);
4794 }
4795 return;
4796 case NEON_FCVTN:
4797 if (instr->Mask(NEON_Q)) {
4798 fcvtn2(vf_fcvtn, rd, rn);
4799 } else {
4800 fcvtn(vf_fcvtn, rd, rn);
4801 }
4802 return;
4803 case NEON_FCVTXN:
4804 if (instr->Mask(NEON_Q)) {
4805 fcvtxn2(vf_fcvtn, rd, rn);
4806 } else {
4807 fcvtxn(vf_fcvtn, rd, rn);
4808 }
4809 return;
4810
4811 // The following instructions break from the switch statement, rather
4812 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07004813 case NEON_FRINT32X:
4814 inexact_exception = true;
4815 frint_mode = kFrintToInt32;
4816 break; // Use FPCR rounding mode.
4817 case NEON_FRINT32Z:
4818 inexact_exception = true;
4819 frint_mode = kFrintToInt32;
4820 fpcr_rounding = FPZero;
4821 break;
4822 case NEON_FRINT64X:
4823 inexact_exception = true;
4824 frint_mode = kFrintToInt64;
4825 break; // Use FPCR rounding mode.
4826 case NEON_FRINT64Z:
4827 inexact_exception = true;
4828 frint_mode = kFrintToInt64;
4829 fpcr_rounding = FPZero;
4830 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004831 case NEON_FRINTI:
4832 break; // Use FPCR rounding mode.
4833 case NEON_FRINTX:
4834 inexact_exception = true;
4835 break;
4836 case NEON_FRINTA:
4837 fpcr_rounding = FPTieAway;
4838 break;
4839 case NEON_FRINTM:
4840 fpcr_rounding = FPNegativeInfinity;
4841 break;
4842 case NEON_FRINTN:
4843 fpcr_rounding = FPTieEven;
4844 break;
4845 case NEON_FRINTP:
4846 fpcr_rounding = FPPositiveInfinity;
4847 break;
4848 case NEON_FRINTZ:
4849 fpcr_rounding = FPZero;
4850 break;
4851
4852 case NEON_FCVTNS:
4853 fcvts(fpf, rd, rn, FPTieEven);
4854 return;
4855 case NEON_FCVTNU:
4856 fcvtu(fpf, rd, rn, FPTieEven);
4857 return;
4858 case NEON_FCVTPS:
4859 fcvts(fpf, rd, rn, FPPositiveInfinity);
4860 return;
4861 case NEON_FCVTPU:
4862 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4863 return;
4864 case NEON_FCVTMS:
4865 fcvts(fpf, rd, rn, FPNegativeInfinity);
4866 return;
4867 case NEON_FCVTMU:
4868 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4869 return;
4870 case NEON_FCVTZS:
4871 fcvts(fpf, rd, rn, FPZero);
4872 return;
4873 case NEON_FCVTZU:
4874 fcvtu(fpf, rd, rn, FPZero);
4875 return;
4876 case NEON_FCVTAS:
4877 fcvts(fpf, rd, rn, FPTieAway);
4878 return;
4879 case NEON_FCVTAU:
4880 fcvtu(fpf, rd, rn, FPTieAway);
4881 return;
4882 case NEON_SCVTF:
4883 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4884 return;
4885 case NEON_UCVTF:
4886 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4887 return;
4888 case NEON_URSQRTE:
4889 ursqrte(fpf, rd, rn);
4890 return;
4891 case NEON_URECPE:
4892 urecpe(fpf, rd, rn);
4893 return;
4894 case NEON_FRSQRTE:
4895 frsqrte(fpf, rd, rn);
4896 return;
4897 case NEON_FRECPE:
4898 frecpe(fpf, rd, rn, fpcr_rounding);
4899 return;
4900 case NEON_FCMGT_zero:
4901 fcmp_zero(fpf, rd, rn, gt);
4902 return;
4903 case NEON_FCMGE_zero:
4904 fcmp_zero(fpf, rd, rn, ge);
4905 return;
4906 case NEON_FCMEQ_zero:
4907 fcmp_zero(fpf, rd, rn, eq);
4908 return;
4909 case NEON_FCMLE_zero:
4910 fcmp_zero(fpf, rd, rn, le);
4911 return;
4912 case NEON_FCMLT_zero:
4913 fcmp_zero(fpf, rd, rn, lt);
4914 return;
4915 default:
4916 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4917 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4918 switch (instr->Mask(NEON2RegMiscMask)) {
4919 case NEON_XTN:
4920 xtn(vf, rd, rn);
4921 return;
4922 case NEON_SQXTN:
4923 sqxtn(vf, rd, rn);
4924 return;
4925 case NEON_UQXTN:
4926 uqxtn(vf, rd, rn);
4927 return;
4928 case NEON_SQXTUN:
4929 sqxtun(vf, rd, rn);
4930 return;
4931 case NEON_SHLL:
4932 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4933 if (instr->Mask(NEON_Q)) {
4934 shll2(vf, rd, rn);
4935 } else {
4936 shll(vf, rd, rn);
4937 }
4938 return;
4939 default:
4940 VIXL_UNIMPLEMENTED();
4941 }
4942 } else {
4943 VIXL_UNIMPLEMENTED();
4944 }
4945 }
4946
4947 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004948 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004949 }
4950}
4951
4952
Jacob Bramleyca789742018-09-13 14:25:46 +01004953void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4954 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4955 NEONFormatDecoder nfd(instr);
4956 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4957
4958 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4959
4960 SimVRegister& rd = ReadVRegister(instr->GetRd());
4961 SimVRegister& rn = ReadVRegister(instr->GetRn());
4962
4963 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4964 case NEON_SCVTF_H:
4965 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4966 return;
4967 case NEON_UCVTF_H:
4968 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4969 return;
4970 case NEON_FCVTNS_H:
4971 fcvts(fpf, rd, rn, FPTieEven);
4972 return;
4973 case NEON_FCVTNU_H:
4974 fcvtu(fpf, rd, rn, FPTieEven);
4975 return;
4976 case NEON_FCVTPS_H:
4977 fcvts(fpf, rd, rn, FPPositiveInfinity);
4978 return;
4979 case NEON_FCVTPU_H:
4980 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4981 return;
4982 case NEON_FCVTMS_H:
4983 fcvts(fpf, rd, rn, FPNegativeInfinity);
4984 return;
4985 case NEON_FCVTMU_H:
4986 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4987 return;
4988 case NEON_FCVTZS_H:
4989 fcvts(fpf, rd, rn, FPZero);
4990 return;
4991 case NEON_FCVTZU_H:
4992 fcvtu(fpf, rd, rn, FPZero);
4993 return;
4994 case NEON_FCVTAS_H:
4995 fcvts(fpf, rd, rn, FPTieAway);
4996 return;
4997 case NEON_FCVTAU_H:
4998 fcvtu(fpf, rd, rn, FPTieAway);
4999 return;
5000 case NEON_FRINTI_H:
5001 frint(fpf, rd, rn, fpcr_rounding, false);
5002 return;
5003 case NEON_FRINTX_H:
5004 frint(fpf, rd, rn, fpcr_rounding, true);
5005 return;
5006 case NEON_FRINTA_H:
5007 frint(fpf, rd, rn, FPTieAway, false);
5008 return;
5009 case NEON_FRINTM_H:
5010 frint(fpf, rd, rn, FPNegativeInfinity, false);
5011 return;
5012 case NEON_FRINTN_H:
5013 frint(fpf, rd, rn, FPTieEven, false);
5014 return;
5015 case NEON_FRINTP_H:
5016 frint(fpf, rd, rn, FPPositiveInfinity, false);
5017 return;
5018 case NEON_FRINTZ_H:
5019 frint(fpf, rd, rn, FPZero, false);
5020 return;
5021 case NEON_FABS_H:
5022 fabs_(fpf, rd, rn);
5023 return;
5024 case NEON_FNEG_H:
5025 fneg(fpf, rd, rn);
5026 return;
5027 case NEON_FSQRT_H:
5028 fsqrt(fpf, rd, rn);
5029 return;
5030 case NEON_FRSQRTE_H:
5031 frsqrte(fpf, rd, rn);
5032 return;
5033 case NEON_FRECPE_H:
5034 frecpe(fpf, rd, rn, fpcr_rounding);
5035 return;
5036 case NEON_FCMGT_H_zero:
5037 fcmp_zero(fpf, rd, rn, gt);
5038 return;
5039 case NEON_FCMGE_H_zero:
5040 fcmp_zero(fpf, rd, rn, ge);
5041 return;
5042 case NEON_FCMEQ_H_zero:
5043 fcmp_zero(fpf, rd, rn, eq);
5044 return;
5045 case NEON_FCMLE_H_zero:
5046 fcmp_zero(fpf, rd, rn, le);
5047 return;
5048 case NEON_FCMLT_H_zero:
5049 fcmp_zero(fpf, rd, rn, lt);
5050 return;
5051 default:
5052 VIXL_UNIMPLEMENTED();
5053 return;
5054 }
5055}
5056
5057
Alexandre Ramesd3832962016-07-04 15:03:43 +01005058void Simulator::VisitNEON3Same(const Instruction* instr) {
5059 NEONFormatDecoder nfd(instr);
5060 SimVRegister& rd = ReadVRegister(instr->GetRd());
5061 SimVRegister& rn = ReadVRegister(instr->GetRn());
5062 SimVRegister& rm = ReadVRegister(instr->GetRm());
5063
5064 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
5065 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
5066 switch (instr->Mask(NEON3SameLogicalMask)) {
5067 case NEON_AND:
5068 and_(vf, rd, rn, rm);
5069 break;
5070 case NEON_ORR:
5071 orr(vf, rd, rn, rm);
5072 break;
5073 case NEON_ORN:
5074 orn(vf, rd, rn, rm);
5075 break;
5076 case NEON_EOR:
5077 eor(vf, rd, rn, rm);
5078 break;
5079 case NEON_BIC:
5080 bic(vf, rd, rn, rm);
5081 break;
5082 case NEON_BIF:
5083 bif(vf, rd, rn, rm);
5084 break;
5085 case NEON_BIT:
5086 bit(vf, rd, rn, rm);
5087 break;
5088 case NEON_BSL:
5089 bsl(vf, rd, rn, rm);
5090 break;
5091 default:
5092 VIXL_UNIMPLEMENTED();
5093 }
5094 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
5095 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5096 switch (instr->Mask(NEON3SameFPMask)) {
5097 case NEON_FADD:
5098 fadd(vf, rd, rn, rm);
5099 break;
5100 case NEON_FSUB:
5101 fsub(vf, rd, rn, rm);
5102 break;
5103 case NEON_FMUL:
5104 fmul(vf, rd, rn, rm);
5105 break;
5106 case NEON_FDIV:
5107 fdiv(vf, rd, rn, rm);
5108 break;
5109 case NEON_FMAX:
5110 fmax(vf, rd, rn, rm);
5111 break;
5112 case NEON_FMIN:
5113 fmin(vf, rd, rn, rm);
5114 break;
5115 case NEON_FMAXNM:
5116 fmaxnm(vf, rd, rn, rm);
5117 break;
5118 case NEON_FMINNM:
5119 fminnm(vf, rd, rn, rm);
5120 break;
5121 case NEON_FMLA:
TatWai Chongf8d29f12020-02-16 22:53:18 -08005122 fmla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005123 break;
5124 case NEON_FMLS:
TatWai Chongf8d29f12020-02-16 22:53:18 -08005125 fmls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005126 break;
5127 case NEON_FMULX:
5128 fmulx(vf, rd, rn, rm);
5129 break;
5130 case NEON_FACGE:
5131 fabscmp(vf, rd, rn, rm, ge);
5132 break;
5133 case NEON_FACGT:
5134 fabscmp(vf, rd, rn, rm, gt);
5135 break;
5136 case NEON_FCMEQ:
5137 fcmp(vf, rd, rn, rm, eq);
5138 break;
5139 case NEON_FCMGE:
5140 fcmp(vf, rd, rn, rm, ge);
5141 break;
5142 case NEON_FCMGT:
5143 fcmp(vf, rd, rn, rm, gt);
5144 break;
5145 case NEON_FRECPS:
5146 frecps(vf, rd, rn, rm);
5147 break;
5148 case NEON_FRSQRTS:
5149 frsqrts(vf, rd, rn, rm);
5150 break;
5151 case NEON_FABD:
5152 fabd(vf, rd, rn, rm);
5153 break;
5154 case NEON_FADDP:
5155 faddp(vf, rd, rn, rm);
5156 break;
5157 case NEON_FMAXP:
5158 fmaxp(vf, rd, rn, rm);
5159 break;
5160 case NEON_FMAXNMP:
5161 fmaxnmp(vf, rd, rn, rm);
5162 break;
5163 case NEON_FMINP:
5164 fminp(vf, rd, rn, rm);
5165 break;
5166 case NEON_FMINNMP:
5167 fminnmp(vf, rd, rn, rm);
5168 break;
5169 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005170 // FMLAL{2} and FMLSL{2} have special-case encodings.
5171 switch (instr->Mask(NEON3SameFHMMask)) {
5172 case NEON_FMLAL:
5173 fmlal(vf, rd, rn, rm);
5174 break;
5175 case NEON_FMLAL2:
5176 fmlal2(vf, rd, rn, rm);
5177 break;
5178 case NEON_FMLSL:
5179 fmlsl(vf, rd, rn, rm);
5180 break;
5181 case NEON_FMLSL2:
5182 fmlsl2(vf, rd, rn, rm);
5183 break;
5184 default:
5185 VIXL_UNIMPLEMENTED();
5186 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005187 }
5188 } else {
5189 VectorFormat vf = nfd.GetVectorFormat();
5190 switch (instr->Mask(NEON3SameMask)) {
5191 case NEON_ADD:
5192 add(vf, rd, rn, rm);
5193 break;
5194 case NEON_ADDP:
5195 addp(vf, rd, rn, rm);
5196 break;
5197 case NEON_CMEQ:
5198 cmp(vf, rd, rn, rm, eq);
5199 break;
5200 case NEON_CMGE:
5201 cmp(vf, rd, rn, rm, ge);
5202 break;
5203 case NEON_CMGT:
5204 cmp(vf, rd, rn, rm, gt);
5205 break;
5206 case NEON_CMHI:
5207 cmp(vf, rd, rn, rm, hi);
5208 break;
5209 case NEON_CMHS:
5210 cmp(vf, rd, rn, rm, hs);
5211 break;
5212 case NEON_CMTST:
5213 cmptst(vf, rd, rn, rm);
5214 break;
5215 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01005216 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005217 break;
5218 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01005219 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005220 break;
5221 case NEON_MUL:
5222 mul(vf, rd, rn, rm);
5223 break;
5224 case NEON_PMUL:
5225 pmul(vf, rd, rn, rm);
5226 break;
5227 case NEON_SMAX:
5228 smax(vf, rd, rn, rm);
5229 break;
5230 case NEON_SMAXP:
5231 smaxp(vf, rd, rn, rm);
5232 break;
5233 case NEON_SMIN:
5234 smin(vf, rd, rn, rm);
5235 break;
5236 case NEON_SMINP:
5237 sminp(vf, rd, rn, rm);
5238 break;
5239 case NEON_SUB:
5240 sub(vf, rd, rn, rm);
5241 break;
5242 case NEON_UMAX:
5243 umax(vf, rd, rn, rm);
5244 break;
5245 case NEON_UMAXP:
5246 umaxp(vf, rd, rn, rm);
5247 break;
5248 case NEON_UMIN:
5249 umin(vf, rd, rn, rm);
5250 break;
5251 case NEON_UMINP:
5252 uminp(vf, rd, rn, rm);
5253 break;
5254 case NEON_SSHL:
5255 sshl(vf, rd, rn, rm);
5256 break;
5257 case NEON_USHL:
5258 ushl(vf, rd, rn, rm);
5259 break;
5260 case NEON_SABD:
5261 absdiff(vf, rd, rn, rm, true);
5262 break;
5263 case NEON_UABD:
5264 absdiff(vf, rd, rn, rm, false);
5265 break;
5266 case NEON_SABA:
5267 saba(vf, rd, rn, rm);
5268 break;
5269 case NEON_UABA:
5270 uaba(vf, rd, rn, rm);
5271 break;
5272 case NEON_UQADD:
5273 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5274 break;
5275 case NEON_SQADD:
5276 add(vf, rd, rn, rm).SignedSaturate(vf);
5277 break;
5278 case NEON_UQSUB:
5279 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5280 break;
5281 case NEON_SQSUB:
5282 sub(vf, rd, rn, rm).SignedSaturate(vf);
5283 break;
5284 case NEON_SQDMULH:
5285 sqdmulh(vf, rd, rn, rm);
5286 break;
5287 case NEON_SQRDMULH:
5288 sqrdmulh(vf, rd, rn, rm);
5289 break;
5290 case NEON_UQSHL:
5291 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5292 break;
5293 case NEON_SQSHL:
5294 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5295 break;
5296 case NEON_URSHL:
5297 ushl(vf, rd, rn, rm).Round(vf);
5298 break;
5299 case NEON_SRSHL:
5300 sshl(vf, rd, rn, rm).Round(vf);
5301 break;
5302 case NEON_UQRSHL:
5303 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5304 break;
5305 case NEON_SQRSHL:
5306 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5307 break;
5308 case NEON_UHADD:
5309 add(vf, rd, rn, rm).Uhalve(vf);
5310 break;
5311 case NEON_URHADD:
5312 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
5313 break;
5314 case NEON_SHADD:
5315 add(vf, rd, rn, rm).Halve(vf);
5316 break;
5317 case NEON_SRHADD:
5318 add(vf, rd, rn, rm).Halve(vf).Round(vf);
5319 break;
5320 case NEON_UHSUB:
5321 sub(vf, rd, rn, rm).Uhalve(vf);
5322 break;
5323 case NEON_SHSUB:
5324 sub(vf, rd, rn, rm).Halve(vf);
5325 break;
5326 default:
5327 VIXL_UNIMPLEMENTED();
5328 }
5329 }
5330}
5331
5332
Jacob Bramleyca789742018-09-13 14:25:46 +01005333void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
5334 NEONFormatDecoder nfd(instr);
5335 SimVRegister& rd = ReadVRegister(instr->GetRd());
5336 SimVRegister& rn = ReadVRegister(instr->GetRn());
5337 SimVRegister& rm = ReadVRegister(instr->GetRm());
5338
5339 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
5340 switch (instr->Mask(NEON3SameFP16Mask)) {
5341#define SIM_FUNC(A, B) \
5342 case NEON_##A##_H: \
5343 B(vf, rd, rn, rm); \
5344 break;
5345 SIM_FUNC(FMAXNM, fmaxnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01005346 SIM_FUNC(FADD, fadd);
5347 SIM_FUNC(FMULX, fmulx);
5348 SIM_FUNC(FMAX, fmax);
5349 SIM_FUNC(FRECPS, frecps);
5350 SIM_FUNC(FMINNM, fminnm);
Jacob Bramleyca789742018-09-13 14:25:46 +01005351 SIM_FUNC(FSUB, fsub);
5352 SIM_FUNC(FMIN, fmin);
5353 SIM_FUNC(FRSQRTS, frsqrts);
5354 SIM_FUNC(FMAXNMP, fmaxnmp);
5355 SIM_FUNC(FADDP, faddp);
5356 SIM_FUNC(FMUL, fmul);
5357 SIM_FUNC(FMAXP, fmaxp);
5358 SIM_FUNC(FDIV, fdiv);
5359 SIM_FUNC(FMINNMP, fminnmp);
5360 SIM_FUNC(FABD, fabd);
5361 SIM_FUNC(FMINP, fminp);
5362#undef SIM_FUNC
TatWai Chongf8d29f12020-02-16 22:53:18 -08005363 case NEON_FMLA_H:
5364 fmla(vf, rd, rd, rn, rm);
5365 break;
5366 case NEON_FMLS_H:
5367 fmls(vf, rd, rd, rn, rm);
5368 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005369 case NEON_FCMEQ_H:
5370 fcmp(vf, rd, rn, rm, eq);
5371 break;
5372 case NEON_FCMGE_H:
5373 fcmp(vf, rd, rn, rm, ge);
5374 break;
5375 case NEON_FACGE_H:
5376 fabscmp(vf, rd, rn, rm, ge);
5377 break;
5378 case NEON_FCMGT_H:
5379 fcmp(vf, rd, rn, rm, gt);
5380 break;
5381 case NEON_FACGT_H:
5382 fabscmp(vf, rd, rn, rm, gt);
5383 break;
5384 default:
5385 VIXL_UNIMPLEMENTED();
5386 break;
5387 }
5388}
5389
Carey Williams2809e6c2018-03-13 12:24:16 +00005390void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
5391 NEONFormatDecoder nfd(instr);
5392 SimVRegister& rd = ReadVRegister(instr->GetRd());
5393 SimVRegister& rn = ReadVRegister(instr->GetRn());
5394 SimVRegister& rm = ReadVRegister(instr->GetRm());
5395 int rot = 0;
5396 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01005397 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
5398 rot = instr->GetImmRotFcmlaVec();
Martyn Capewell75f1c432020-03-30 09:23:27 +01005399 fcmla(vf, rd, rn, rm, rd, rot);
Jacob Bramley364c82b2018-08-24 17:51:52 +01005400 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
5401 rot = instr->GetImmRotFcadd();
5402 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01005403 } else {
5404 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01005405 case NEON_SDOT:
5406 sdot(vf, rd, rn, rm);
5407 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005408 case NEON_SQRDMLAH:
5409 sqrdmlah(vf, rd, rn, rm);
5410 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005411 case NEON_UDOT:
5412 udot(vf, rd, rn, rm);
5413 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005414 case NEON_SQRDMLSH:
5415 sqrdmlsh(vf, rd, rn, rm);
5416 break;
5417 default:
5418 VIXL_UNIMPLEMENTED();
5419 break;
5420 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005421 }
5422}
5423
5424
Alexandre Ramesd3832962016-07-04 15:03:43 +01005425void Simulator::VisitNEON3Different(const Instruction* instr) {
5426 NEONFormatDecoder nfd(instr);
5427 VectorFormat vf = nfd.GetVectorFormat();
5428 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5429
5430 SimVRegister& rd = ReadVRegister(instr->GetRd());
5431 SimVRegister& rn = ReadVRegister(instr->GetRn());
5432 SimVRegister& rm = ReadVRegister(instr->GetRm());
5433
5434 switch (instr->Mask(NEON3DifferentMask)) {
5435 case NEON_PMULL:
5436 pmull(vf_l, rd, rn, rm);
5437 break;
5438 case NEON_PMULL2:
5439 pmull2(vf_l, rd, rn, rm);
5440 break;
5441 case NEON_UADDL:
5442 uaddl(vf_l, rd, rn, rm);
5443 break;
5444 case NEON_UADDL2:
5445 uaddl2(vf_l, rd, rn, rm);
5446 break;
5447 case NEON_SADDL:
5448 saddl(vf_l, rd, rn, rm);
5449 break;
5450 case NEON_SADDL2:
5451 saddl2(vf_l, rd, rn, rm);
5452 break;
5453 case NEON_USUBL:
5454 usubl(vf_l, rd, rn, rm);
5455 break;
5456 case NEON_USUBL2:
5457 usubl2(vf_l, rd, rn, rm);
5458 break;
5459 case NEON_SSUBL:
5460 ssubl(vf_l, rd, rn, rm);
5461 break;
5462 case NEON_SSUBL2:
5463 ssubl2(vf_l, rd, rn, rm);
5464 break;
5465 case NEON_SABAL:
5466 sabal(vf_l, rd, rn, rm);
5467 break;
5468 case NEON_SABAL2:
5469 sabal2(vf_l, rd, rn, rm);
5470 break;
5471 case NEON_UABAL:
5472 uabal(vf_l, rd, rn, rm);
5473 break;
5474 case NEON_UABAL2:
5475 uabal2(vf_l, rd, rn, rm);
5476 break;
5477 case NEON_SABDL:
5478 sabdl(vf_l, rd, rn, rm);
5479 break;
5480 case NEON_SABDL2:
5481 sabdl2(vf_l, rd, rn, rm);
5482 break;
5483 case NEON_UABDL:
5484 uabdl(vf_l, rd, rn, rm);
5485 break;
5486 case NEON_UABDL2:
5487 uabdl2(vf_l, rd, rn, rm);
5488 break;
5489 case NEON_SMLAL:
5490 smlal(vf_l, rd, rn, rm);
5491 break;
5492 case NEON_SMLAL2:
5493 smlal2(vf_l, rd, rn, rm);
5494 break;
5495 case NEON_UMLAL:
5496 umlal(vf_l, rd, rn, rm);
5497 break;
5498 case NEON_UMLAL2:
5499 umlal2(vf_l, rd, rn, rm);
5500 break;
5501 case NEON_SMLSL:
5502 smlsl(vf_l, rd, rn, rm);
5503 break;
5504 case NEON_SMLSL2:
5505 smlsl2(vf_l, rd, rn, rm);
5506 break;
5507 case NEON_UMLSL:
5508 umlsl(vf_l, rd, rn, rm);
5509 break;
5510 case NEON_UMLSL2:
5511 umlsl2(vf_l, rd, rn, rm);
5512 break;
5513 case NEON_SMULL:
5514 smull(vf_l, rd, rn, rm);
5515 break;
5516 case NEON_SMULL2:
5517 smull2(vf_l, rd, rn, rm);
5518 break;
5519 case NEON_UMULL:
5520 umull(vf_l, rd, rn, rm);
5521 break;
5522 case NEON_UMULL2:
5523 umull2(vf_l, rd, rn, rm);
5524 break;
5525 case NEON_SQDMLAL:
5526 sqdmlal(vf_l, rd, rn, rm);
5527 break;
5528 case NEON_SQDMLAL2:
5529 sqdmlal2(vf_l, rd, rn, rm);
5530 break;
5531 case NEON_SQDMLSL:
5532 sqdmlsl(vf_l, rd, rn, rm);
5533 break;
5534 case NEON_SQDMLSL2:
5535 sqdmlsl2(vf_l, rd, rn, rm);
5536 break;
5537 case NEON_SQDMULL:
5538 sqdmull(vf_l, rd, rn, rm);
5539 break;
5540 case NEON_SQDMULL2:
5541 sqdmull2(vf_l, rd, rn, rm);
5542 break;
5543 case NEON_UADDW:
5544 uaddw(vf_l, rd, rn, rm);
5545 break;
5546 case NEON_UADDW2:
5547 uaddw2(vf_l, rd, rn, rm);
5548 break;
5549 case NEON_SADDW:
5550 saddw(vf_l, rd, rn, rm);
5551 break;
5552 case NEON_SADDW2:
5553 saddw2(vf_l, rd, rn, rm);
5554 break;
5555 case NEON_USUBW:
5556 usubw(vf_l, rd, rn, rm);
5557 break;
5558 case NEON_USUBW2:
5559 usubw2(vf_l, rd, rn, rm);
5560 break;
5561 case NEON_SSUBW:
5562 ssubw(vf_l, rd, rn, rm);
5563 break;
5564 case NEON_SSUBW2:
5565 ssubw2(vf_l, rd, rn, rm);
5566 break;
5567 case NEON_ADDHN:
5568 addhn(vf, rd, rn, rm);
5569 break;
5570 case NEON_ADDHN2:
5571 addhn2(vf, rd, rn, rm);
5572 break;
5573 case NEON_RADDHN:
5574 raddhn(vf, rd, rn, rm);
5575 break;
5576 case NEON_RADDHN2:
5577 raddhn2(vf, rd, rn, rm);
5578 break;
5579 case NEON_SUBHN:
5580 subhn(vf, rd, rn, rm);
5581 break;
5582 case NEON_SUBHN2:
5583 subhn2(vf, rd, rn, rm);
5584 break;
5585 case NEON_RSUBHN:
5586 rsubhn(vf, rd, rn, rm);
5587 break;
5588 case NEON_RSUBHN2:
5589 rsubhn2(vf, rd, rn, rm);
5590 break;
5591 default:
5592 VIXL_UNIMPLEMENTED();
5593 }
5594}
5595
5596
5597void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5598 NEONFormatDecoder nfd(instr);
5599
Jacob Bramleyca789742018-09-13 14:25:46 +01005600 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5601
Alexandre Ramesd3832962016-07-04 15:03:43 +01005602 SimVRegister& rd = ReadVRegister(instr->GetRd());
5603 SimVRegister& rn = ReadVRegister(instr->GetRn());
5604
Jacob Bramleyca789742018-09-13 14:25:46 +01005605 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5606 VectorFormat vf = nfd.GetVectorFormat(&map_half);
5607 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5608 case NEON_FMAXV_H:
5609 fmaxv(vf, rd, rn);
5610 break;
5611 case NEON_FMINV_H:
5612 fminv(vf, rd, rn);
5613 break;
5614 case NEON_FMAXNMV_H:
5615 fmaxnmv(vf, rd, rn);
5616 break;
5617 case NEON_FMINNMV_H:
5618 fminnmv(vf, rd, rn);
5619 break;
5620 default:
5621 VIXL_UNIMPLEMENTED();
5622 }
5623 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5624 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01005625 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5626
5627 switch (instr->Mask(NEONAcrossLanesFPMask)) {
5628 case NEON_FMAXV:
5629 fmaxv(vf, rd, rn);
5630 break;
5631 case NEON_FMINV:
5632 fminv(vf, rd, rn);
5633 break;
5634 case NEON_FMAXNMV:
5635 fmaxnmv(vf, rd, rn);
5636 break;
5637 case NEON_FMINNMV:
5638 fminnmv(vf, rd, rn);
5639 break;
5640 default:
5641 VIXL_UNIMPLEMENTED();
5642 }
5643 } else {
5644 VectorFormat vf = nfd.GetVectorFormat();
5645
5646 switch (instr->Mask(NEONAcrossLanesMask)) {
5647 case NEON_ADDV:
5648 addv(vf, rd, rn);
5649 break;
5650 case NEON_SMAXV:
5651 smaxv(vf, rd, rn);
5652 break;
5653 case NEON_SMINV:
5654 sminv(vf, rd, rn);
5655 break;
5656 case NEON_UMAXV:
5657 umaxv(vf, rd, rn);
5658 break;
5659 case NEON_UMINV:
5660 uminv(vf, rd, rn);
5661 break;
5662 case NEON_SADDLV:
5663 saddlv(vf, rd, rn);
5664 break;
5665 case NEON_UADDLV:
5666 uaddlv(vf, rd, rn);
5667 break;
5668 default:
5669 VIXL_UNIMPLEMENTED();
5670 }
5671 }
5672}
5673
5674
5675void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5676 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01005677 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01005678 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01005679 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005680 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5681
5682 SimVRegister& rd = ReadVRegister(instr->GetRd());
5683 SimVRegister& rn = ReadVRegister(instr->GetRn());
5684
5685 ByElementOp Op = NULL;
5686
5687 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005688 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005689 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005690 int index_hlm = (index << 1) | instr->GetNEONM();
5691
5692 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5693 // These are oddballs and are best handled as special cases.
5694 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5695 // - The index is always H:L:M.
5696 case NEON_FMLAL_H_byelement:
5697 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5698 return;
5699 case NEON_FMLAL2_H_byelement:
5700 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5701 return;
5702 case NEON_FMLSL_H_byelement:
5703 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5704 return;
5705 case NEON_FMLSL2_H_byelement:
5706 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5707 return;
5708 }
5709
Alexandre Ramesd3832962016-07-04 15:03:43 +01005710 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005711 rm_reg = rm_low_reg;
5712 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005713 }
5714
5715 switch (instr->Mask(NEONByIndexedElementMask)) {
5716 case NEON_MUL_byelement:
5717 Op = &Simulator::mul;
5718 vf = vf_r;
5719 break;
5720 case NEON_MLA_byelement:
5721 Op = &Simulator::mla;
5722 vf = vf_r;
5723 break;
5724 case NEON_MLS_byelement:
5725 Op = &Simulator::mls;
5726 vf = vf_r;
5727 break;
5728 case NEON_SQDMULH_byelement:
5729 Op = &Simulator::sqdmulh;
5730 vf = vf_r;
5731 break;
5732 case NEON_SQRDMULH_byelement:
5733 Op = &Simulator::sqrdmulh;
5734 vf = vf_r;
5735 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005736 case NEON_SDOT_byelement:
5737 Op = &Simulator::sdot;
5738 vf = vf_r;
5739 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005740 case NEON_SQRDMLAH_byelement:
5741 Op = &Simulator::sqrdmlah;
5742 vf = vf_r;
5743 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005744 case NEON_UDOT_byelement:
5745 Op = &Simulator::udot;
5746 vf = vf_r;
5747 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005748 case NEON_SQRDMLSH_byelement:
5749 Op = &Simulator::sqrdmlsh;
5750 vf = vf_r;
5751 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005752 case NEON_SMULL_byelement:
5753 if (instr->Mask(NEON_Q)) {
5754 Op = &Simulator::smull2;
5755 } else {
5756 Op = &Simulator::smull;
5757 }
5758 break;
5759 case NEON_UMULL_byelement:
5760 if (instr->Mask(NEON_Q)) {
5761 Op = &Simulator::umull2;
5762 } else {
5763 Op = &Simulator::umull;
5764 }
5765 break;
5766 case NEON_SMLAL_byelement:
5767 if (instr->Mask(NEON_Q)) {
5768 Op = &Simulator::smlal2;
5769 } else {
5770 Op = &Simulator::smlal;
5771 }
5772 break;
5773 case NEON_UMLAL_byelement:
5774 if (instr->Mask(NEON_Q)) {
5775 Op = &Simulator::umlal2;
5776 } else {
5777 Op = &Simulator::umlal;
5778 }
5779 break;
5780 case NEON_SMLSL_byelement:
5781 if (instr->Mask(NEON_Q)) {
5782 Op = &Simulator::smlsl2;
5783 } else {
5784 Op = &Simulator::smlsl;
5785 }
5786 break;
5787 case NEON_UMLSL_byelement:
5788 if (instr->Mask(NEON_Q)) {
5789 Op = &Simulator::umlsl2;
5790 } else {
5791 Op = &Simulator::umlsl;
5792 }
5793 break;
5794 case NEON_SQDMULL_byelement:
5795 if (instr->Mask(NEON_Q)) {
5796 Op = &Simulator::sqdmull2;
5797 } else {
5798 Op = &Simulator::sqdmull;
5799 }
5800 break;
5801 case NEON_SQDMLAL_byelement:
5802 if (instr->Mask(NEON_Q)) {
5803 Op = &Simulator::sqdmlal2;
5804 } else {
5805 Op = &Simulator::sqdmlal;
5806 }
5807 break;
5808 case NEON_SQDMLSL_byelement:
5809 if (instr->Mask(NEON_Q)) {
5810 Op = &Simulator::sqdmlsl2;
5811 } else {
5812 Op = &Simulator::sqdmlsl;
5813 }
5814 break;
5815 default:
5816 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01005817 if (instr->GetFPType() == 0) {
5818 rm_reg &= 0xf;
5819 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5820 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005821 index = (index << 1) | instr->GetNEONL();
5822 }
5823
5824 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5825
5826 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005827 case NEON_FMUL_H_byelement:
5828 vf = vf_half;
5829 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005830 case NEON_FMUL_byelement:
5831 Op = &Simulator::fmul;
5832 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005833 case NEON_FMLA_H_byelement:
5834 vf = vf_half;
5835 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005836 case NEON_FMLA_byelement:
5837 Op = &Simulator::fmla;
5838 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005839 case NEON_FMLS_H_byelement:
5840 vf = vf_half;
5841 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005842 case NEON_FMLS_byelement:
5843 Op = &Simulator::fmls;
5844 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005845 case NEON_FMULX_H_byelement:
5846 vf = vf_half;
5847 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005848 case NEON_FMULX_byelement:
5849 Op = &Simulator::fmulx;
5850 break;
5851 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005852 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00005853 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005854 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00005855 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005856 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005857 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5858 case NEON_FCMLA_byelement:
5859 vf = vf_r;
5860 fcmla(vf,
5861 rd,
5862 rn,
5863 ReadVRegister(instr->GetRm()),
5864 index,
5865 instr->GetImmRotFcmlaSca());
5866 return;
5867 default:
5868 VIXL_UNIMPLEMENTED();
5869 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005870 }
5871 }
5872
5873 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5874}
5875
5876
5877void Simulator::VisitNEONCopy(const Instruction* instr) {
5878 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5879 VectorFormat vf = nfd.GetVectorFormat();
5880
5881 SimVRegister& rd = ReadVRegister(instr->GetRd());
5882 SimVRegister& rn = ReadVRegister(instr->GetRn());
5883 int imm5 = instr->GetImmNEON5();
5884 int tz = CountTrailingZeros(imm5, 32);
5885 int reg_index = imm5 >> (tz + 1);
5886
5887 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5888 int imm4 = instr->GetImmNEON4();
5889 int rn_index = imm4 >> tz;
5890 ins_element(vf, rd, reg_index, rn, rn_index);
5891 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5892 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5893 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5894 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5895 value &= MaxUintFromFormat(vf);
5896 WriteXRegister(instr->GetRd(), value);
5897 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5898 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5899 if (instr->GetNEONQ()) {
5900 WriteXRegister(instr->GetRd(), value);
5901 } else {
5902 WriteWRegister(instr->GetRd(), (int32_t)value);
5903 }
5904 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5905 dup_element(vf, rd, rn, reg_index);
5906 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5907 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5908 } else {
5909 VIXL_UNIMPLEMENTED();
5910 }
5911}
5912
5913
5914void Simulator::VisitNEONExtract(const Instruction* instr) {
5915 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5916 VectorFormat vf = nfd.GetVectorFormat();
5917 SimVRegister& rd = ReadVRegister(instr->GetRd());
5918 SimVRegister& rn = ReadVRegister(instr->GetRn());
5919 SimVRegister& rm = ReadVRegister(instr->GetRm());
5920 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5921 int index = instr->GetImmNEONExt();
5922 ext(vf, rd, rn, rm, index);
5923 } else {
5924 VIXL_UNIMPLEMENTED();
5925 }
5926}
5927
5928
5929void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5930 AddrMode addr_mode) {
5931 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5932 VectorFormat vf = nfd.GetVectorFormat();
5933
5934 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5935 int reg_size = RegisterSizeInBytesFromFormat(vf);
5936
5937 int reg[4];
5938 uint64_t addr[4];
5939 for (int i = 0; i < 4; i++) {
5940 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5941 addr[i] = addr_base + (i * reg_size);
5942 }
Jacob Bramley423e5422019-11-13 19:15:55 +00005943 int struct_parts = 1;
5944 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005945 bool log_read = true;
5946
Martyn Capewell32009e32016-10-27 11:00:37 +01005947 // Bit 23 determines whether this is an offset or post-index addressing mode.
5948 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5949 // register or immediate in post-index mode.
5950 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005951 VIXL_UNREACHABLE();
5952 }
5953
5954 // We use the PostIndex mask here, as it works in this case for both Offset
5955 // and PostIndex addressing.
5956 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5957 case NEON_LD1_4v:
5958 case NEON_LD1_4v_post:
5959 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005960 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005961 VIXL_FALLTHROUGH();
5962 case NEON_LD1_3v:
5963 case NEON_LD1_3v_post:
5964 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005965 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005966 VIXL_FALLTHROUGH();
5967 case NEON_LD1_2v:
5968 case NEON_LD1_2v_post:
5969 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005970 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005971 VIXL_FALLTHROUGH();
5972 case NEON_LD1_1v:
5973 case NEON_LD1_1v_post:
5974 ld1(vf, ReadVRegister(reg[0]), addr[0]);
5975 break;
5976 case NEON_ST1_4v:
5977 case NEON_ST1_4v_post:
5978 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005979 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005980 VIXL_FALLTHROUGH();
5981 case NEON_ST1_3v:
5982 case NEON_ST1_3v_post:
5983 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005984 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005985 VIXL_FALLTHROUGH();
5986 case NEON_ST1_2v:
5987 case NEON_ST1_2v_post:
5988 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005989 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005990 VIXL_FALLTHROUGH();
5991 case NEON_ST1_1v:
5992 case NEON_ST1_1v_post:
5993 st1(vf, ReadVRegister(reg[0]), addr[0]);
5994 log_read = false;
5995 break;
5996 case NEON_LD2_post:
5997 case NEON_LD2:
5998 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005999 struct_parts = 2;
6000 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006001 break;
6002 case NEON_ST2:
6003 case NEON_ST2_post:
6004 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006005 struct_parts = 2;
6006 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01006007 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006008 break;
6009 case NEON_LD3_post:
6010 case NEON_LD3:
6011 ld3(vf,
6012 ReadVRegister(reg[0]),
6013 ReadVRegister(reg[1]),
6014 ReadVRegister(reg[2]),
6015 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006016 struct_parts = 3;
6017 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006018 break;
6019 case NEON_ST3:
6020 case NEON_ST3_post:
6021 st3(vf,
6022 ReadVRegister(reg[0]),
6023 ReadVRegister(reg[1]),
6024 ReadVRegister(reg[2]),
6025 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006026 struct_parts = 3;
6027 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01006028 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006029 break;
6030 case NEON_ST4:
6031 case NEON_ST4_post:
6032 st4(vf,
6033 ReadVRegister(reg[0]),
6034 ReadVRegister(reg[1]),
6035 ReadVRegister(reg[2]),
6036 ReadVRegister(reg[3]),
6037 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006038 struct_parts = 4;
6039 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01006040 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006041 break;
6042 case NEON_LD4_post:
6043 case NEON_LD4:
6044 ld4(vf,
6045 ReadVRegister(reg[0]),
6046 ReadVRegister(reg[1]),
6047 ReadVRegister(reg[2]),
6048 ReadVRegister(reg[3]),
6049 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006050 struct_parts = 4;
6051 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006052 break;
6053 default:
6054 VIXL_UNIMPLEMENTED();
6055 }
6056
Jacob Bramley7eb3e212019-11-22 17:28:05 +00006057 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00006058 if (do_trace) {
6059 PrintRegisterFormat print_format =
6060 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
6061 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006062 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00006063 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01006064 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00006065 op = "->";
6066 // Stores don't represent a change to the source register's value, so only
6067 // print the relevant part of the value.
6068 print_format = GetPrintRegPartial(print_format);
6069 }
6070
6071 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
6072 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
6073 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
6074 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006075 }
6076 }
6077
6078 if (addr_mode == PostIndex) {
6079 int rm = instr->GetRm();
6080 // The immediate post index addressing mode is indicated by rm = 31.
6081 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00006082 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01006083 : ReadXRegister(rm);
6084 WriteXRegister(instr->GetRn(), addr_base);
6085 } else {
6086 VIXL_ASSERT(addr_mode == Offset);
6087 }
6088}
6089
6090
6091void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
6092 NEONLoadStoreMultiStructHelper(instr, Offset);
6093}
6094
6095
6096void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
6097 const Instruction* instr) {
6098 NEONLoadStoreMultiStructHelper(instr, PostIndex);
6099}
6100
6101
6102void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
6103 AddrMode addr_mode) {
6104 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
6105 int rt = instr->GetRt();
6106
Martyn Capewell32009e32016-10-27 11:00:37 +01006107 // Bit 23 determines whether this is an offset or post-index addressing mode.
6108 // In offset mode, bits 20 to 16 should be zero; these bits encode the
6109 // register or immediate in post-index mode.
6110 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006111 VIXL_UNREACHABLE();
6112 }
6113
6114 // We use the PostIndex mask here, as it works in this case for both Offset
6115 // and PostIndex addressing.
6116 bool do_load = false;
6117
Jacob Bramley423e5422019-11-13 19:15:55 +00006118 bool replicating = false;
6119
Alexandre Ramesd3832962016-07-04 15:03:43 +01006120 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
6121 VectorFormat vf_t = nfd.GetVectorFormat();
6122
6123 VectorFormat vf = kFormat16B;
6124 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
6125 case NEON_LD1_b:
6126 case NEON_LD1_b_post:
6127 case NEON_LD2_b:
6128 case NEON_LD2_b_post:
6129 case NEON_LD3_b:
6130 case NEON_LD3_b_post:
6131 case NEON_LD4_b:
6132 case NEON_LD4_b_post:
6133 do_load = true;
6134 VIXL_FALLTHROUGH();
6135 case NEON_ST1_b:
6136 case NEON_ST1_b_post:
6137 case NEON_ST2_b:
6138 case NEON_ST2_b_post:
6139 case NEON_ST3_b:
6140 case NEON_ST3_b_post:
6141 case NEON_ST4_b:
6142 case NEON_ST4_b_post:
6143 break;
6144
6145 case NEON_LD1_h:
6146 case NEON_LD1_h_post:
6147 case NEON_LD2_h:
6148 case NEON_LD2_h_post:
6149 case NEON_LD3_h:
6150 case NEON_LD3_h_post:
6151 case NEON_LD4_h:
6152 case NEON_LD4_h_post:
6153 do_load = true;
6154 VIXL_FALLTHROUGH();
6155 case NEON_ST1_h:
6156 case NEON_ST1_h_post:
6157 case NEON_ST2_h:
6158 case NEON_ST2_h_post:
6159 case NEON_ST3_h:
6160 case NEON_ST3_h_post:
6161 case NEON_ST4_h:
6162 case NEON_ST4_h_post:
6163 vf = kFormat8H;
6164 break;
6165 case NEON_LD1_s:
6166 case NEON_LD1_s_post:
6167 case NEON_LD2_s:
6168 case NEON_LD2_s_post:
6169 case NEON_LD3_s:
6170 case NEON_LD3_s_post:
6171 case NEON_LD4_s:
6172 case NEON_LD4_s_post:
6173 do_load = true;
6174 VIXL_FALLTHROUGH();
6175 case NEON_ST1_s:
6176 case NEON_ST1_s_post:
6177 case NEON_ST2_s:
6178 case NEON_ST2_s_post:
6179 case NEON_ST3_s:
6180 case NEON_ST3_s_post:
6181 case NEON_ST4_s:
6182 case NEON_ST4_s_post: {
6183 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
6184 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
6185 NEON_LD1_d_post);
6186 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
6187 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
6188 NEON_ST1_d_post);
6189 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
6190 break;
6191 }
6192
6193 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006194 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006195 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006196 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006197 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006198 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006199 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006200 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006201 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006202 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00006203 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006204 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00006205
Alexandre Ramesd3832962016-07-04 15:03:43 +01006206 default:
6207 VIXL_UNIMPLEMENTED();
6208 }
6209
Alexandre Ramesd3832962016-07-04 15:03:43 +01006210 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
6211 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00006212 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006213 int rt2 = (rt + 1) % kNumberOfVRegisters;
6214 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
6215 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
6216 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
6217 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00006218 reg_count = 1;
6219 if (replicating) {
6220 VIXL_ASSERT(do_load);
6221 ld1r(vf, ReadVRegister(rt), addr);
6222 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006223 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006224 } else {
6225 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006226 }
6227 break;
6228 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00006229 reg_count = 2;
6230 if (replicating) {
6231 VIXL_ASSERT(do_load);
6232 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
6233 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006234 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006235 } else {
6236 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006237 }
6238 break;
6239 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00006240 reg_count = 3;
6241 if (replicating) {
6242 VIXL_ASSERT(do_load);
6243 ld3r(vf,
6244 ReadVRegister(rt),
6245 ReadVRegister(rt2),
6246 ReadVRegister(rt3),
6247 addr);
6248 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006249 ld3(vf,
6250 ReadVRegister(rt),
6251 ReadVRegister(rt2),
6252 ReadVRegister(rt3),
6253 lane,
6254 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006255 } else {
6256 st3(vf,
6257 ReadVRegister(rt),
6258 ReadVRegister(rt2),
6259 ReadVRegister(rt3),
6260 lane,
6261 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006262 }
6263 break;
6264 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00006265 reg_count = 4;
6266 if (replicating) {
6267 VIXL_ASSERT(do_load);
6268 ld4r(vf,
6269 ReadVRegister(rt),
6270 ReadVRegister(rt2),
6271 ReadVRegister(rt3),
6272 ReadVRegister(rt4),
6273 addr);
6274 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006275 ld4(vf,
6276 ReadVRegister(rt),
6277 ReadVRegister(rt2),
6278 ReadVRegister(rt3),
6279 ReadVRegister(rt4),
6280 lane,
6281 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006282 } else {
6283 st4(vf,
6284 ReadVRegister(rt),
6285 ReadVRegister(rt2),
6286 ReadVRegister(rt3),
6287 ReadVRegister(rt4),
6288 lane,
6289 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006290 }
6291 break;
6292 default:
6293 VIXL_UNIMPLEMENTED();
6294 }
6295
Jacob Bramley423e5422019-11-13 19:15:55 +00006296 // Trace registers and/or memory writes.
6297 PrintRegisterFormat print_format =
6298 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
6299 if (do_load) {
6300 if (ShouldTraceVRegs()) {
6301 if (replicating) {
6302 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
6303 } else {
6304 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
6305 }
6306 }
6307 } else {
6308 if (ShouldTraceWrites()) {
6309 // Stores don't represent a change to the source register's value, so only
6310 // print the relevant part of the value.
6311 print_format = GetPrintRegPartial(print_format);
6312 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
6313 }
6314 }
6315
Alexandre Ramesd3832962016-07-04 15:03:43 +01006316 if (addr_mode == PostIndex) {
6317 int rm = instr->GetRm();
6318 int lane_size = LaneSizeInBytesFromFormat(vf);
6319 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00006320 addr + ((rm == 31) ? (reg_count * lane_size)
6321 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006322 }
6323}
6324
6325
6326void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
6327 NEONLoadStoreSingleStructHelper(instr, Offset);
6328}
6329
6330
6331void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
6332 const Instruction* instr) {
6333 NEONLoadStoreSingleStructHelper(instr, PostIndex);
6334}
6335
6336
6337void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
6338 SimVRegister& rd = ReadVRegister(instr->GetRd());
6339 int cmode = instr->GetNEONCmode();
6340 int cmode_3_1 = (cmode >> 1) & 7;
6341 int cmode_3 = (cmode >> 3) & 1;
6342 int cmode_2 = (cmode >> 2) & 1;
6343 int cmode_1 = (cmode >> 1) & 1;
6344 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006345 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006346 int q = instr->GetNEONQ();
6347 int op_bit = instr->GetNEONModImmOp();
6348 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006349 // Find the format and immediate value
6350 uint64_t imm = 0;
6351 VectorFormat vform = kFormatUndefined;
6352 switch (cmode_3_1) {
6353 case 0x0:
6354 case 0x1:
6355 case 0x2:
6356 case 0x3:
6357 vform = (q == 1) ? kFormat4S : kFormat2S;
6358 imm = imm8 << (8 * cmode_3_1);
6359 break;
6360 case 0x4:
6361 case 0x5:
6362 vform = (q == 1) ? kFormat8H : kFormat4H;
6363 imm = imm8 << (8 * cmode_1);
6364 break;
6365 case 0x6:
6366 vform = (q == 1) ? kFormat4S : kFormat2S;
6367 if (cmode_0 == 0) {
6368 imm = imm8 << 8 | 0x000000ff;
6369 } else {
6370 imm = imm8 << 16 | 0x0000ffff;
6371 }
6372 break;
6373 case 0x7:
6374 if (cmode_0 == 0 && op_bit == 0) {
6375 vform = q ? kFormat16B : kFormat8B;
6376 imm = imm8;
6377 } else if (cmode_0 == 0 && op_bit == 1) {
6378 vform = q ? kFormat2D : kFormat1D;
6379 imm = 0;
6380 for (int i = 0; i < 8; ++i) {
6381 if (imm8 & (1 << i)) {
6382 imm |= (UINT64_C(0xff) << (8 * i));
6383 }
6384 }
6385 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01006386 if (half_enc == 1) {
6387 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01006388 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006389 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006390 vform = q ? kFormat4S : kFormat2S;
6391 imm = FloatToRawbits(instr->GetImmNEONFP32());
6392 } else if (q == 1) {
6393 vform = kFormat2D;
6394 imm = DoubleToRawbits(instr->GetImmNEONFP64());
6395 } else {
6396 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
6397 VisitUnallocated(instr);
6398 }
6399 }
6400 break;
6401 default:
6402 VIXL_UNREACHABLE();
6403 break;
6404 }
6405
6406 // Find the operation
6407 NEONModifiedImmediateOp op;
6408 if (cmode_3 == 0) {
6409 if (cmode_0 == 0) {
6410 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6411 } else { // cmode<0> == '1'
6412 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6413 }
6414 } else { // cmode<3> == '1'
6415 if (cmode_2 == 0) {
6416 if (cmode_0 == 0) {
6417 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6418 } else { // cmode<0> == '1'
6419 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6420 }
6421 } else { // cmode<2> == '1'
6422 if (cmode_1 == 0) {
6423 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6424 } else { // cmode<1> == '1'
6425 if (cmode_0 == 0) {
6426 op = NEONModifiedImmediate_MOVI;
6427 } else { // cmode<0> == '1'
6428 op = NEONModifiedImmediate_MOVI;
6429 }
6430 }
6431 }
6432 }
6433
6434 // Call the logic function
6435 if (op == NEONModifiedImmediate_ORR) {
6436 orr(vform, rd, rd, imm);
6437 } else if (op == NEONModifiedImmediate_BIC) {
6438 bic(vform, rd, rd, imm);
6439 } else if (op == NEONModifiedImmediate_MOVI) {
6440 movi(vform, rd, imm);
6441 } else if (op == NEONModifiedImmediate_MVNI) {
6442 mvni(vform, rd, imm);
6443 } else {
6444 VisitUnimplemented(instr);
6445 }
6446}
6447
6448
6449void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
6450 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6451 VectorFormat vf = nfd.GetVectorFormat();
6452
6453 SimVRegister& rd = ReadVRegister(instr->GetRd());
6454 SimVRegister& rn = ReadVRegister(instr->GetRn());
6455
6456 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
6457 // These instructions all use a two bit size field, except NOT and RBIT,
6458 // which use the field to encode the operation.
6459 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6460 case NEON_CMEQ_zero_scalar:
6461 cmp(vf, rd, rn, 0, eq);
6462 break;
6463 case NEON_CMGE_zero_scalar:
6464 cmp(vf, rd, rn, 0, ge);
6465 break;
6466 case NEON_CMGT_zero_scalar:
6467 cmp(vf, rd, rn, 0, gt);
6468 break;
6469 case NEON_CMLT_zero_scalar:
6470 cmp(vf, rd, rn, 0, lt);
6471 break;
6472 case NEON_CMLE_zero_scalar:
6473 cmp(vf, rd, rn, 0, le);
6474 break;
6475 case NEON_ABS_scalar:
6476 abs(vf, rd, rn);
6477 break;
6478 case NEON_SQABS_scalar:
6479 abs(vf, rd, rn).SignedSaturate(vf);
6480 break;
6481 case NEON_NEG_scalar:
6482 neg(vf, rd, rn);
6483 break;
6484 case NEON_SQNEG_scalar:
6485 neg(vf, rd, rn).SignedSaturate(vf);
6486 break;
6487 case NEON_SUQADD_scalar:
6488 suqadd(vf, rd, rn);
6489 break;
6490 case NEON_USQADD_scalar:
6491 usqadd(vf, rd, rn);
6492 break;
6493 default:
6494 VIXL_UNIMPLEMENTED();
6495 break;
6496 }
6497 } else {
6498 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6499 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6500
6501 // These instructions all use a one bit size field, except SQXTUN, SQXTN
6502 // and UQXTN, which use a two bit size field.
6503 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
6504 case NEON_FRECPE_scalar:
6505 frecpe(fpf, rd, rn, fpcr_rounding);
6506 break;
6507 case NEON_FRECPX_scalar:
6508 frecpx(fpf, rd, rn);
6509 break;
6510 case NEON_FRSQRTE_scalar:
6511 frsqrte(fpf, rd, rn);
6512 break;
6513 case NEON_FCMGT_zero_scalar:
6514 fcmp_zero(fpf, rd, rn, gt);
6515 break;
6516 case NEON_FCMGE_zero_scalar:
6517 fcmp_zero(fpf, rd, rn, ge);
6518 break;
6519 case NEON_FCMEQ_zero_scalar:
6520 fcmp_zero(fpf, rd, rn, eq);
6521 break;
6522 case NEON_FCMLE_zero_scalar:
6523 fcmp_zero(fpf, rd, rn, le);
6524 break;
6525 case NEON_FCMLT_zero_scalar:
6526 fcmp_zero(fpf, rd, rn, lt);
6527 break;
6528 case NEON_SCVTF_scalar:
6529 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6530 break;
6531 case NEON_UCVTF_scalar:
6532 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6533 break;
6534 case NEON_FCVTNS_scalar:
6535 fcvts(fpf, rd, rn, FPTieEven);
6536 break;
6537 case NEON_FCVTNU_scalar:
6538 fcvtu(fpf, rd, rn, FPTieEven);
6539 break;
6540 case NEON_FCVTPS_scalar:
6541 fcvts(fpf, rd, rn, FPPositiveInfinity);
6542 break;
6543 case NEON_FCVTPU_scalar:
6544 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6545 break;
6546 case NEON_FCVTMS_scalar:
6547 fcvts(fpf, rd, rn, FPNegativeInfinity);
6548 break;
6549 case NEON_FCVTMU_scalar:
6550 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6551 break;
6552 case NEON_FCVTZS_scalar:
6553 fcvts(fpf, rd, rn, FPZero);
6554 break;
6555 case NEON_FCVTZU_scalar:
6556 fcvtu(fpf, rd, rn, FPZero);
6557 break;
6558 case NEON_FCVTAS_scalar:
6559 fcvts(fpf, rd, rn, FPTieAway);
6560 break;
6561 case NEON_FCVTAU_scalar:
6562 fcvtu(fpf, rd, rn, FPTieAway);
6563 break;
6564 case NEON_FCVTXN_scalar:
6565 // Unlike all of the other FP instructions above, fcvtxn encodes dest
6566 // size S as size<0>=1. There's only one case, so we ignore the form.
6567 VIXL_ASSERT(instr->ExtractBit(22) == 1);
6568 fcvtxn(kFormatS, rd, rn);
6569 break;
6570 default:
6571 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6572 case NEON_SQXTN_scalar:
6573 sqxtn(vf, rd, rn);
6574 break;
6575 case NEON_UQXTN_scalar:
6576 uqxtn(vf, rd, rn);
6577 break;
6578 case NEON_SQXTUN_scalar:
6579 sqxtun(vf, rd, rn);
6580 break;
6581 default:
6582 VIXL_UNIMPLEMENTED();
6583 }
6584 }
6585 }
6586}
6587
6588
Jacob Bramleyca789742018-09-13 14:25:46 +01006589void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
6590 VectorFormat fpf = kFormatH;
6591 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6592
6593 SimVRegister& rd = ReadVRegister(instr->GetRd());
6594 SimVRegister& rn = ReadVRegister(instr->GetRn());
6595
6596 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6597 case NEON_FRECPE_H_scalar:
6598 frecpe(fpf, rd, rn, fpcr_rounding);
6599 break;
6600 case NEON_FRECPX_H_scalar:
6601 frecpx(fpf, rd, rn);
6602 break;
6603 case NEON_FRSQRTE_H_scalar:
6604 frsqrte(fpf, rd, rn);
6605 break;
6606 case NEON_FCMGT_H_zero_scalar:
6607 fcmp_zero(fpf, rd, rn, gt);
6608 break;
6609 case NEON_FCMGE_H_zero_scalar:
6610 fcmp_zero(fpf, rd, rn, ge);
6611 break;
6612 case NEON_FCMEQ_H_zero_scalar:
6613 fcmp_zero(fpf, rd, rn, eq);
6614 break;
6615 case NEON_FCMLE_H_zero_scalar:
6616 fcmp_zero(fpf, rd, rn, le);
6617 break;
6618 case NEON_FCMLT_H_zero_scalar:
6619 fcmp_zero(fpf, rd, rn, lt);
6620 break;
6621 case NEON_SCVTF_H_scalar:
6622 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6623 break;
6624 case NEON_UCVTF_H_scalar:
6625 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6626 break;
6627 case NEON_FCVTNS_H_scalar:
6628 fcvts(fpf, rd, rn, FPTieEven);
6629 break;
6630 case NEON_FCVTNU_H_scalar:
6631 fcvtu(fpf, rd, rn, FPTieEven);
6632 break;
6633 case NEON_FCVTPS_H_scalar:
6634 fcvts(fpf, rd, rn, FPPositiveInfinity);
6635 break;
6636 case NEON_FCVTPU_H_scalar:
6637 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6638 break;
6639 case NEON_FCVTMS_H_scalar:
6640 fcvts(fpf, rd, rn, FPNegativeInfinity);
6641 break;
6642 case NEON_FCVTMU_H_scalar:
6643 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6644 break;
6645 case NEON_FCVTZS_H_scalar:
6646 fcvts(fpf, rd, rn, FPZero);
6647 break;
6648 case NEON_FCVTZU_H_scalar:
6649 fcvtu(fpf, rd, rn, FPZero);
6650 break;
6651 case NEON_FCVTAS_H_scalar:
6652 fcvts(fpf, rd, rn, FPTieAway);
6653 break;
6654 case NEON_FCVTAU_H_scalar:
6655 fcvtu(fpf, rd, rn, FPTieAway);
6656 break;
6657 }
6658}
6659
6660
Alexandre Ramesd3832962016-07-04 15:03:43 +01006661void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6662 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6663 VectorFormat vf = nfd.GetVectorFormat();
6664
6665 SimVRegister& rd = ReadVRegister(instr->GetRd());
6666 SimVRegister& rn = ReadVRegister(instr->GetRn());
6667 SimVRegister& rm = ReadVRegister(instr->GetRm());
6668 switch (instr->Mask(NEONScalar3DiffMask)) {
6669 case NEON_SQDMLAL_scalar:
6670 sqdmlal(vf, rd, rn, rm);
6671 break;
6672 case NEON_SQDMLSL_scalar:
6673 sqdmlsl(vf, rd, rn, rm);
6674 break;
6675 case NEON_SQDMULL_scalar:
6676 sqdmull(vf, rd, rn, rm);
6677 break;
6678 default:
6679 VIXL_UNIMPLEMENTED();
6680 }
6681}
6682
6683
6684void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6685 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6686 VectorFormat vf = nfd.GetVectorFormat();
6687
6688 SimVRegister& rd = ReadVRegister(instr->GetRd());
6689 SimVRegister& rn = ReadVRegister(instr->GetRn());
6690 SimVRegister& rm = ReadVRegister(instr->GetRm());
6691
6692 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6693 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6694 switch (instr->Mask(NEONScalar3SameFPMask)) {
6695 case NEON_FMULX_scalar:
6696 fmulx(vf, rd, rn, rm);
6697 break;
6698 case NEON_FACGE_scalar:
6699 fabscmp(vf, rd, rn, rm, ge);
6700 break;
6701 case NEON_FACGT_scalar:
6702 fabscmp(vf, rd, rn, rm, gt);
6703 break;
6704 case NEON_FCMEQ_scalar:
6705 fcmp(vf, rd, rn, rm, eq);
6706 break;
6707 case NEON_FCMGE_scalar:
6708 fcmp(vf, rd, rn, rm, ge);
6709 break;
6710 case NEON_FCMGT_scalar:
6711 fcmp(vf, rd, rn, rm, gt);
6712 break;
6713 case NEON_FRECPS_scalar:
6714 frecps(vf, rd, rn, rm);
6715 break;
6716 case NEON_FRSQRTS_scalar:
6717 frsqrts(vf, rd, rn, rm);
6718 break;
6719 case NEON_FABD_scalar:
6720 fabd(vf, rd, rn, rm);
6721 break;
6722 default:
6723 VIXL_UNIMPLEMENTED();
6724 }
6725 } else {
6726 switch (instr->Mask(NEONScalar3SameMask)) {
6727 case NEON_ADD_scalar:
6728 add(vf, rd, rn, rm);
6729 break;
6730 case NEON_SUB_scalar:
6731 sub(vf, rd, rn, rm);
6732 break;
6733 case NEON_CMEQ_scalar:
6734 cmp(vf, rd, rn, rm, eq);
6735 break;
6736 case NEON_CMGE_scalar:
6737 cmp(vf, rd, rn, rm, ge);
6738 break;
6739 case NEON_CMGT_scalar:
6740 cmp(vf, rd, rn, rm, gt);
6741 break;
6742 case NEON_CMHI_scalar:
6743 cmp(vf, rd, rn, rm, hi);
6744 break;
6745 case NEON_CMHS_scalar:
6746 cmp(vf, rd, rn, rm, hs);
6747 break;
6748 case NEON_CMTST_scalar:
6749 cmptst(vf, rd, rn, rm);
6750 break;
6751 case NEON_USHL_scalar:
6752 ushl(vf, rd, rn, rm);
6753 break;
6754 case NEON_SSHL_scalar:
6755 sshl(vf, rd, rn, rm);
6756 break;
6757 case NEON_SQDMULH_scalar:
6758 sqdmulh(vf, rd, rn, rm);
6759 break;
6760 case NEON_SQRDMULH_scalar:
6761 sqrdmulh(vf, rd, rn, rm);
6762 break;
6763 case NEON_UQADD_scalar:
6764 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6765 break;
6766 case NEON_SQADD_scalar:
6767 add(vf, rd, rn, rm).SignedSaturate(vf);
6768 break;
6769 case NEON_UQSUB_scalar:
6770 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6771 break;
6772 case NEON_SQSUB_scalar:
6773 sub(vf, rd, rn, rm).SignedSaturate(vf);
6774 break;
6775 case NEON_UQSHL_scalar:
6776 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6777 break;
6778 case NEON_SQSHL_scalar:
6779 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6780 break;
6781 case NEON_URSHL_scalar:
6782 ushl(vf, rd, rn, rm).Round(vf);
6783 break;
6784 case NEON_SRSHL_scalar:
6785 sshl(vf, rd, rn, rm).Round(vf);
6786 break;
6787 case NEON_UQRSHL_scalar:
6788 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6789 break;
6790 case NEON_SQRSHL_scalar:
6791 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6792 break;
6793 default:
6794 VIXL_UNIMPLEMENTED();
6795 }
6796 }
6797}
6798
Jacob Bramleyca789742018-09-13 14:25:46 +01006799void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6800 SimVRegister& rd = ReadVRegister(instr->GetRd());
6801 SimVRegister& rn = ReadVRegister(instr->GetRn());
6802 SimVRegister& rm = ReadVRegister(instr->GetRm());
6803
6804 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6805 case NEON_FABD_H_scalar:
6806 fabd(kFormatH, rd, rn, rm);
6807 break;
6808 case NEON_FMULX_H_scalar:
6809 fmulx(kFormatH, rd, rn, rm);
6810 break;
6811 case NEON_FCMEQ_H_scalar:
6812 fcmp(kFormatH, rd, rn, rm, eq);
6813 break;
6814 case NEON_FCMGE_H_scalar:
6815 fcmp(kFormatH, rd, rn, rm, ge);
6816 break;
6817 case NEON_FCMGT_H_scalar:
6818 fcmp(kFormatH, rd, rn, rm, gt);
6819 break;
6820 case NEON_FACGE_H_scalar:
6821 fabscmp(kFormatH, rd, rn, rm, ge);
6822 break;
6823 case NEON_FACGT_H_scalar:
6824 fabscmp(kFormatH, rd, rn, rm, gt);
6825 break;
6826 case NEON_FRECPS_H_scalar:
6827 frecps(kFormatH, rd, rn, rm);
6828 break;
6829 case NEON_FRSQRTS_H_scalar:
6830 frsqrts(kFormatH, rd, rn, rm);
6831 break;
6832 default:
6833 VIXL_UNREACHABLE();
6834 }
6835}
6836
Alexandre Ramesd3832962016-07-04 15:03:43 +01006837
Alexander Gilday43785642018-04-04 13:42:33 +01006838void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6839 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6840 VectorFormat vf = nfd.GetVectorFormat();
6841
6842 SimVRegister& rd = ReadVRegister(instr->GetRd());
6843 SimVRegister& rn = ReadVRegister(instr->GetRn());
6844 SimVRegister& rm = ReadVRegister(instr->GetRm());
6845
6846 switch (instr->Mask(NEONScalar3SameExtraMask)) {
6847 case NEON_SQRDMLAH_scalar:
6848 sqrdmlah(vf, rd, rn, rm);
6849 break;
6850 case NEON_SQRDMLSH_scalar:
6851 sqrdmlsh(vf, rd, rn, rm);
6852 break;
6853 default:
6854 VIXL_UNIMPLEMENTED();
6855 }
6856}
6857
Alexandre Ramesd3832962016-07-04 15:03:43 +01006858void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6859 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6860 VectorFormat vf = nfd.GetVectorFormat();
6861 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6862
6863 SimVRegister& rd = ReadVRegister(instr->GetRd());
6864 SimVRegister& rn = ReadVRegister(instr->GetRn());
6865 ByElementOp Op = NULL;
6866
6867 int rm_reg = instr->GetRm();
6868 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6869 if (instr->GetNEONSize() == 1) {
6870 rm_reg &= 0xf;
6871 index = (index << 1) | instr->GetNEONM();
6872 }
6873
6874 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6875 case NEON_SQDMULL_byelement_scalar:
6876 Op = &Simulator::sqdmull;
6877 break;
6878 case NEON_SQDMLAL_byelement_scalar:
6879 Op = &Simulator::sqdmlal;
6880 break;
6881 case NEON_SQDMLSL_byelement_scalar:
6882 Op = &Simulator::sqdmlsl;
6883 break;
6884 case NEON_SQDMULH_byelement_scalar:
6885 Op = &Simulator::sqdmulh;
6886 vf = vf_r;
6887 break;
6888 case NEON_SQRDMULH_byelement_scalar:
6889 Op = &Simulator::sqrdmulh;
6890 vf = vf_r;
6891 break;
Alexander Gilday43785642018-04-04 13:42:33 +01006892 case NEON_SQRDMLAH_byelement_scalar:
6893 Op = &Simulator::sqrdmlah;
6894 vf = vf_r;
6895 break;
6896 case NEON_SQRDMLSH_byelement_scalar:
6897 Op = &Simulator::sqrdmlsh;
6898 vf = vf_r;
6899 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006900 default:
6901 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6902 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01006903 if (instr->GetFPType() == 0) {
6904 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6905 rm_reg &= 0xf;
6906 vf = kFormatH;
6907 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006908 index = (index << 1) | instr->GetNEONL();
6909 }
6910 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006911 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006912 case NEON_FMUL_byelement_scalar:
6913 Op = &Simulator::fmul;
6914 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006915 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006916 case NEON_FMLA_byelement_scalar:
6917 Op = &Simulator::fmla;
6918 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006919 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006920 case NEON_FMLS_byelement_scalar:
6921 Op = &Simulator::fmls;
6922 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006923 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006924 case NEON_FMULX_byelement_scalar:
6925 Op = &Simulator::fmulx;
6926 break;
6927 default:
6928 VIXL_UNIMPLEMENTED();
6929 }
6930 }
6931
6932 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6933}
6934
6935
6936void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6937 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6938 VectorFormat vf = nfd.GetVectorFormat();
6939
6940 SimVRegister& rd = ReadVRegister(instr->GetRd());
6941 SimVRegister& rn = ReadVRegister(instr->GetRn());
6942
6943 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6944 int imm5 = instr->GetImmNEON5();
6945 int tz = CountTrailingZeros(imm5, 32);
6946 int rn_index = imm5 >> (tz + 1);
6947 dup_element(vf, rd, rn, rn_index);
6948 } else {
6949 VIXL_UNIMPLEMENTED();
6950 }
6951}
6952
6953
6954void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006955 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006956 VectorFormat vf = nfd.GetVectorFormat();
6957
6958 SimVRegister& rd = ReadVRegister(instr->GetRd());
6959 SimVRegister& rn = ReadVRegister(instr->GetRn());
6960 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006961 case NEON_ADDP_scalar: {
6962 // All pairwise operations except ADDP use bit U to differentiate FP16
6963 // from FP32/FP64 variations.
6964 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6965 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006966 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006967 }
6968 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006969 case NEON_FADDP_scalar:
6970 faddp(vf, rd, rn);
6971 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006972 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006973 case NEON_FMAXP_scalar:
6974 fmaxp(vf, rd, rn);
6975 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006976 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006977 case NEON_FMAXNMP_scalar:
6978 fmaxnmp(vf, rd, rn);
6979 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006980 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006981 case NEON_FMINP_scalar:
6982 fminp(vf, rd, rn);
6983 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006984 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006985 case NEON_FMINNMP_scalar:
6986 fminnmp(vf, rd, rn);
6987 break;
6988 default:
6989 VIXL_UNIMPLEMENTED();
6990 }
6991}
6992
6993
6994void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6995 SimVRegister& rd = ReadVRegister(instr->GetRd());
6996 SimVRegister& rn = ReadVRegister(instr->GetRn());
6997 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6998
6999 static const NEONFormatMap map = {{22, 21, 20, 19},
7000 {NF_UNDEF,
7001 NF_B,
7002 NF_H,
7003 NF_H,
7004 NF_S,
7005 NF_S,
7006 NF_S,
7007 NF_S,
7008 NF_D,
7009 NF_D,
7010 NF_D,
7011 NF_D,
7012 NF_D,
7013 NF_D,
7014 NF_D,
7015 NF_D}};
7016 NEONFormatDecoder nfd(instr, &map);
7017 VectorFormat vf = nfd.GetVectorFormat();
7018
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00007019 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
7020 int immh_immb = instr->GetImmNEONImmhImmb();
7021 int right_shift = (16 << highest_set_bit) - immh_immb;
7022 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007023 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
7024 case NEON_SHL_scalar:
7025 shl(vf, rd, rn, left_shift);
7026 break;
7027 case NEON_SLI_scalar:
7028 sli(vf, rd, rn, left_shift);
7029 break;
7030 case NEON_SQSHL_imm_scalar:
7031 sqshl(vf, rd, rn, left_shift);
7032 break;
7033 case NEON_UQSHL_imm_scalar:
7034 uqshl(vf, rd, rn, left_shift);
7035 break;
7036 case NEON_SQSHLU_scalar:
7037 sqshlu(vf, rd, rn, left_shift);
7038 break;
7039 case NEON_SRI_scalar:
7040 sri(vf, rd, rn, right_shift);
7041 break;
7042 case NEON_SSHR_scalar:
7043 sshr(vf, rd, rn, right_shift);
7044 break;
7045 case NEON_USHR_scalar:
7046 ushr(vf, rd, rn, right_shift);
7047 break;
7048 case NEON_SRSHR_scalar:
7049 sshr(vf, rd, rn, right_shift).Round(vf);
7050 break;
7051 case NEON_URSHR_scalar:
7052 ushr(vf, rd, rn, right_shift).Round(vf);
7053 break;
7054 case NEON_SSRA_scalar:
7055 ssra(vf, rd, rn, right_shift);
7056 break;
7057 case NEON_USRA_scalar:
7058 usra(vf, rd, rn, right_shift);
7059 break;
7060 case NEON_SRSRA_scalar:
7061 srsra(vf, rd, rn, right_shift);
7062 break;
7063 case NEON_URSRA_scalar:
7064 ursra(vf, rd, rn, right_shift);
7065 break;
7066 case NEON_UQSHRN_scalar:
7067 uqshrn(vf, rd, rn, right_shift);
7068 break;
7069 case NEON_UQRSHRN_scalar:
7070 uqrshrn(vf, rd, rn, right_shift);
7071 break;
7072 case NEON_SQSHRN_scalar:
7073 sqshrn(vf, rd, rn, right_shift);
7074 break;
7075 case NEON_SQRSHRN_scalar:
7076 sqrshrn(vf, rd, rn, right_shift);
7077 break;
7078 case NEON_SQSHRUN_scalar:
7079 sqshrun(vf, rd, rn, right_shift);
7080 break;
7081 case NEON_SQRSHRUN_scalar:
7082 sqrshrun(vf, rd, rn, right_shift);
7083 break;
7084 case NEON_FCVTZS_imm_scalar:
7085 fcvts(vf, rd, rn, FPZero, right_shift);
7086 break;
7087 case NEON_FCVTZU_imm_scalar:
7088 fcvtu(vf, rd, rn, FPZero, right_shift);
7089 break;
7090 case NEON_SCVTF_imm_scalar:
7091 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7092 break;
7093 case NEON_UCVTF_imm_scalar:
7094 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7095 break;
7096 default:
7097 VIXL_UNIMPLEMENTED();
7098 }
7099}
7100
7101
7102void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
7103 SimVRegister& rd = ReadVRegister(instr->GetRd());
7104 SimVRegister& rn = ReadVRegister(instr->GetRn());
7105 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
7106
7107 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
7108 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
7109 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01007110 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
7111 NF_4H, NF_8H, NF_4H, NF_8H,
7112 NF_2S, NF_4S, NF_2S, NF_4S,
7113 NF_2S, NF_4S, NF_2S, NF_4S,
7114 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7115 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7116 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7117 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007118 NEONFormatDecoder nfd(instr, &map);
7119 VectorFormat vf = nfd.GetVectorFormat();
7120
7121 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
7122 static const NEONFormatMap map_l =
7123 {{22, 21, 20, 19},
7124 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
7125 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
7126
Jacob Bramleyacd32aa2019-12-12 18:08:20 +00007127 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
7128 int immh_immb = instr->GetImmNEONImmhImmb();
7129 int right_shift = (16 << highest_set_bit) - immh_immb;
7130 int left_shift = immh_immb - (8 << highest_set_bit);
Alexandre Ramesd3832962016-07-04 15:03:43 +01007131
7132 switch (instr->Mask(NEONShiftImmediateMask)) {
7133 case NEON_SHL:
7134 shl(vf, rd, rn, left_shift);
7135 break;
7136 case NEON_SLI:
7137 sli(vf, rd, rn, left_shift);
7138 break;
7139 case NEON_SQSHLU:
7140 sqshlu(vf, rd, rn, left_shift);
7141 break;
7142 case NEON_SRI:
7143 sri(vf, rd, rn, right_shift);
7144 break;
7145 case NEON_SSHR:
7146 sshr(vf, rd, rn, right_shift);
7147 break;
7148 case NEON_USHR:
7149 ushr(vf, rd, rn, right_shift);
7150 break;
7151 case NEON_SRSHR:
7152 sshr(vf, rd, rn, right_shift).Round(vf);
7153 break;
7154 case NEON_URSHR:
7155 ushr(vf, rd, rn, right_shift).Round(vf);
7156 break;
7157 case NEON_SSRA:
7158 ssra(vf, rd, rn, right_shift);
7159 break;
7160 case NEON_USRA:
7161 usra(vf, rd, rn, right_shift);
7162 break;
7163 case NEON_SRSRA:
7164 srsra(vf, rd, rn, right_shift);
7165 break;
7166 case NEON_URSRA:
7167 ursra(vf, rd, rn, right_shift);
7168 break;
7169 case NEON_SQSHL_imm:
7170 sqshl(vf, rd, rn, left_shift);
7171 break;
7172 case NEON_UQSHL_imm:
7173 uqshl(vf, rd, rn, left_shift);
7174 break;
7175 case NEON_SCVTF_imm:
7176 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7177 break;
7178 case NEON_UCVTF_imm:
7179 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7180 break;
7181 case NEON_FCVTZS_imm:
7182 fcvts(vf, rd, rn, FPZero, right_shift);
7183 break;
7184 case NEON_FCVTZU_imm:
7185 fcvtu(vf, rd, rn, FPZero, right_shift);
7186 break;
7187 case NEON_SSHLL:
7188 vf = vf_l;
7189 if (instr->Mask(NEON_Q)) {
7190 sshll2(vf, rd, rn, left_shift);
7191 } else {
7192 sshll(vf, rd, rn, left_shift);
7193 }
7194 break;
7195 case NEON_USHLL:
7196 vf = vf_l;
7197 if (instr->Mask(NEON_Q)) {
7198 ushll2(vf, rd, rn, left_shift);
7199 } else {
7200 ushll(vf, rd, rn, left_shift);
7201 }
7202 break;
7203 case NEON_SHRN:
7204 if (instr->Mask(NEON_Q)) {
7205 shrn2(vf, rd, rn, right_shift);
7206 } else {
7207 shrn(vf, rd, rn, right_shift);
7208 }
7209 break;
7210 case NEON_RSHRN:
7211 if (instr->Mask(NEON_Q)) {
7212 rshrn2(vf, rd, rn, right_shift);
7213 } else {
7214 rshrn(vf, rd, rn, right_shift);
7215 }
7216 break;
7217 case NEON_UQSHRN:
7218 if (instr->Mask(NEON_Q)) {
7219 uqshrn2(vf, rd, rn, right_shift);
7220 } else {
7221 uqshrn(vf, rd, rn, right_shift);
7222 }
7223 break;
7224 case NEON_UQRSHRN:
7225 if (instr->Mask(NEON_Q)) {
7226 uqrshrn2(vf, rd, rn, right_shift);
7227 } else {
7228 uqrshrn(vf, rd, rn, right_shift);
7229 }
7230 break;
7231 case NEON_SQSHRN:
7232 if (instr->Mask(NEON_Q)) {
7233 sqshrn2(vf, rd, rn, right_shift);
7234 } else {
7235 sqshrn(vf, rd, rn, right_shift);
7236 }
7237 break;
7238 case NEON_SQRSHRN:
7239 if (instr->Mask(NEON_Q)) {
7240 sqrshrn2(vf, rd, rn, right_shift);
7241 } else {
7242 sqrshrn(vf, rd, rn, right_shift);
7243 }
7244 break;
7245 case NEON_SQSHRUN:
7246 if (instr->Mask(NEON_Q)) {
7247 sqshrun2(vf, rd, rn, right_shift);
7248 } else {
7249 sqshrun(vf, rd, rn, right_shift);
7250 }
7251 break;
7252 case NEON_SQRSHRUN:
7253 if (instr->Mask(NEON_Q)) {
7254 sqrshrun2(vf, rd, rn, right_shift);
7255 } else {
7256 sqrshrun(vf, rd, rn, right_shift);
7257 }
7258 break;
7259 default:
7260 VIXL_UNIMPLEMENTED();
7261 }
7262}
7263
7264
7265void Simulator::VisitNEONTable(const Instruction* instr) {
7266 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7267 VectorFormat vf = nfd.GetVectorFormat();
7268
7269 SimVRegister& rd = ReadVRegister(instr->GetRd());
7270 SimVRegister& rn = ReadVRegister(instr->GetRn());
7271 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
7272 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
7273 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
7274 SimVRegister& rm = ReadVRegister(instr->GetRm());
7275
7276 switch (instr->Mask(NEONTableMask)) {
7277 case NEON_TBL_1v:
7278 tbl(vf, rd, rn, rm);
7279 break;
7280 case NEON_TBL_2v:
7281 tbl(vf, rd, rn, rn2, rm);
7282 break;
7283 case NEON_TBL_3v:
7284 tbl(vf, rd, rn, rn2, rn3, rm);
7285 break;
7286 case NEON_TBL_4v:
7287 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
7288 break;
7289 case NEON_TBX_1v:
7290 tbx(vf, rd, rn, rm);
7291 break;
7292 case NEON_TBX_2v:
7293 tbx(vf, rd, rn, rn2, rm);
7294 break;
7295 case NEON_TBX_3v:
7296 tbx(vf, rd, rn, rn2, rn3, rm);
7297 break;
7298 case NEON_TBX_4v:
7299 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
7300 break;
7301 default:
7302 VIXL_UNIMPLEMENTED();
7303 }
7304}
7305
7306
7307void Simulator::VisitNEONPerm(const Instruction* instr) {
7308 NEONFormatDecoder nfd(instr);
7309 VectorFormat vf = nfd.GetVectorFormat();
7310
7311 SimVRegister& rd = ReadVRegister(instr->GetRd());
7312 SimVRegister& rn = ReadVRegister(instr->GetRn());
7313 SimVRegister& rm = ReadVRegister(instr->GetRm());
7314
7315 switch (instr->Mask(NEONPermMask)) {
7316 case NEON_TRN1:
7317 trn1(vf, rd, rn, rm);
7318 break;
7319 case NEON_TRN2:
7320 trn2(vf, rd, rn, rm);
7321 break;
7322 case NEON_UZP1:
7323 uzp1(vf, rd, rn, rm);
7324 break;
7325 case NEON_UZP2:
7326 uzp2(vf, rd, rn, rm);
7327 break;
7328 case NEON_ZIP1:
7329 zip1(vf, rd, rn, rm);
7330 break;
7331 case NEON_ZIP2:
7332 zip2(vf, rd, rn, rm);
7333 break;
7334 default:
7335 VIXL_UNIMPLEMENTED();
7336 }
7337}
7338
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007339void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
Martyn Capewell48522f52020-03-16 15:31:19 +00007340 SimVRegister& zd = ReadVRegister(instr->GetRd());
7341 SimVRegister& zn = ReadVRegister(instr->GetRn());
7342 SimVRegister& zm = ReadVRegister(instr->GetRm());
7343 SimVRegister temp;
7344
7345 VectorFormat vform = kFormatVnD;
7346 mov(vform, temp, zm);
7347
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007348 switch (instr->Mask(SVEAddressGenerationMask)) {
7349 case ADR_z_az_d_s32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00007350 sxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007351 break;
7352 case ADR_z_az_d_u32_scaled:
Martyn Capewell48522f52020-03-16 15:31:19 +00007353 uxt(vform, temp, temp, kSRegSize);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007354 break;
Martyn Capewell48522f52020-03-16 15:31:19 +00007355 case ADR_z_az_s_same_scaled:
7356 vform = kFormatVnS;
7357 break;
7358 case ADR_z_az_d_same_scaled:
7359 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007360 break;
7361 default:
7362 VIXL_UNIMPLEMENTED();
7363 break;
7364 }
Martyn Capewell48522f52020-03-16 15:31:19 +00007365
7366 int shift_amount = instr->ExtractBits(11, 10);
7367 shl(vform, temp, temp, shift_amount);
7368 add(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007369}
7370
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007371void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
7372 const Instruction* instr) {
7373 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07007374 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007375 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007376 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07007377 case ORR_z_zi: {
7378 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7379 uint64_t imm = instr->GetSVEImmLogical();
7380 // Valid immediate is a non-zero bits
7381 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007382 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
7383 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07007384 SVEFormatFromLaneSizeInBytesLog2(lane_size),
7385 ReadVRegister(instr->GetRd()),
7386 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007387 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07007388 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007389 default:
7390 VIXL_UNIMPLEMENTED();
7391 break;
7392 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007393}
7394
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007395void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
7396 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
7397 case DUPM_z_i: {
7398 /* DUPM uses the same lane size and immediate encoding as bitwise logical
7399 * immediate instructions. */
7400 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7401 uint64_t imm = instr->GetSVEImmLogical();
7402 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7403 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
7404 break;
7405 }
7406 default:
7407 VIXL_UNIMPLEMENTED();
7408 break;
7409 }
7410}
7411
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007412void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
TatWai Chongcfb94212019-05-16 13:30:09 -07007413 SimVRegister& zd = ReadVRegister(instr->GetRd());
7414 SimVRegister& zn = ReadVRegister(instr->GetRn());
7415 SimVRegister& zm = ReadVRegister(instr->GetRm());
7416 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
7417
TatWai Chong13634762019-07-16 16:20:45 -07007418 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07007419 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007420 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007421 logical_op = AND;
7422 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007423 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007424 logical_op = BIC;
7425 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007426 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007427 logical_op = EOR;
7428 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07007429 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007430 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007431 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007432 default:
TatWai Chong13634762019-07-16 16:20:45 -07007433 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007434 VIXL_UNIMPLEMENTED();
7435 break;
7436 }
TatWai Chong13634762019-07-16 16:20:45 -07007437 // Lane size of registers is irrelevant to the bitwise operations, so perform
7438 // the operation on D-sized lanes.
7439 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007440}
7441
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007442void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewell83e86612020-02-19 15:46:15 +00007443 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7444 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7445
7446 SimVRegister scratch;
7447 SimVRegister result;
7448
7449 bool for_division = false;
7450 Shift shift_op = NO_SHIFT;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007451 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007452 case ASRD_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00007453 shift_op = ASR;
7454 for_division = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007455 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007456 case ASR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00007457 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007458 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007459 case LSL_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00007460 shift_op = LSL;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007461 break;
7462 case LSR_z_p_zi:
Martyn Capewell83e86612020-02-19 15:46:15 +00007463 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007464 break;
7465 default:
7466 VIXL_UNIMPLEMENTED();
7467 break;
7468 }
Martyn Capewell83e86612020-02-19 15:46:15 +00007469
7470 std::pair<int, int> shift_and_lane_size =
7471 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
7472 unsigned lane_size = shift_and_lane_size.second;
7473 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7474 int shift_dist = shift_and_lane_size.first;
7475
7476 if ((shift_op == ASR) && for_division) {
7477 asrd(vform, result, zdn, shift_dist);
7478 } else {
7479 if (shift_op == LSL) {
7480 // Shift distance is computed differently for LSL. Convert the result.
7481 shift_dist = (8 << lane_size) - shift_dist;
7482 }
7483 dup_immediate(vform, scratch, shift_dist);
7484 SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
7485 }
7486 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007487}
7488
7489void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
7490 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00007491 VectorFormat vform = instr->GetSVEVectorFormat();
7492 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7493 SimVRegister& zm = ReadVRegister(instr->GetRn());
7494 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7495
7496 SimVRegister result;
7497 SimVRegister shiftand; // Vector to be shifted.
7498 SimVRegister shiftor; // Vector shift amount.
7499
7500 Shift shift_op = ASR;
7501 mov(vform, shiftand, zdn);
7502 mov(vform, shiftor, zm);
7503
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007504 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
7505 case ASRR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00007506 mov(vform, shiftand, zm);
7507 mov(vform, shiftor, zdn);
7508 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007509 case ASR_z_p_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007510 break;
7511 case LSLR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00007512 mov(vform, shiftand, zm);
7513 mov(vform, shiftor, zdn);
7514 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007515 case LSL_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00007516 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007517 break;
7518 case LSRR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00007519 mov(vform, shiftand, zm);
7520 mov(vform, shiftor, zdn);
7521 VIXL_FALLTHROUGH();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007522 case LSR_z_p_zz:
Martyn Capewell76c094a2020-02-13 17:26:49 +00007523 shift_op = LSR;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007524 break;
7525 default:
7526 VIXL_UNIMPLEMENTED();
7527 break;
7528 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00007529 SVEBitwiseShiftHelper(shift_op,
7530 vform,
7531 result,
7532 shiftand,
7533 shiftor,
7534 /* is_wide_elements = */ false);
7535 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007536}
7537
7538void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
7539 const Instruction* instr) {
Martyn Capewell76c094a2020-02-13 17:26:49 +00007540 VectorFormat vform = instr->GetSVEVectorFormat();
7541 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7542 SimVRegister& zm = ReadVRegister(instr->GetRn());
7543 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7544
7545 SimVRegister result;
7546 Shift shift_op = ASR;
7547
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007548 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
7549 case ASR_z_p_zw:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007550 break;
7551 case LSL_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00007552 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007553 break;
7554 case LSR_z_p_zw:
Martyn Capewell76c094a2020-02-13 17:26:49 +00007555 shift_op = LSR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007556 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007557 default:
7558 VIXL_UNIMPLEMENTED();
7559 break;
7560 }
Martyn Capewell76c094a2020-02-13 17:26:49 +00007561 SVEBitwiseShiftHelper(shift_op,
7562 vform,
7563 result,
7564 zdn,
7565 zm,
7566 /* is_wide_elements = */ true);
7567 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007568}
7569
7570void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
TatWai Chong29a0c432019-11-06 22:20:44 -08007571 SimVRegister& zd = ReadVRegister(instr->GetRd());
7572 SimVRegister& zn = ReadVRegister(instr->GetRn());
7573
7574 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007575 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7576 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007577 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007578 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007579 break;
7580 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007581 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007582 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007583 break;
7584 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08007585 case LSR_z_zw:
7586 shift_op = LSR;
7587 break;
7588 default:
7589 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007590 VIXL_UNIMPLEMENTED();
7591 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08007592 }
7593
7594 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7595 case ASR_z_zi:
7596 case LSL_z_zi:
7597 case LSR_z_zi: {
7598 SimVRegister scratch;
7599 std::pair<int, int> shift_and_lane_size =
Martyn Capewell83e86612020-02-19 15:46:15 +00007600 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
TatWai Chong29a0c432019-11-06 22:20:44 -08007601 unsigned lane_size = shift_and_lane_size.second;
7602 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
7603 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
Martyn Capewell147b0ba2020-02-19 11:16:02 +00007604 int shift_dist = shift_and_lane_size.first;
7605 if (shift_op == LSL) {
7606 // Shift distance is computed differently for LSL. Convert the result.
7607 shift_dist = (8 << lane_size) - shift_dist;
7608 }
7609 dup_immediate(vform, scratch, shift_dist);
TatWai Chong29a0c432019-11-06 22:20:44 -08007610 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
7611 break;
7612 }
7613 case ASR_z_zw:
7614 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007615 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007616 SVEBitwiseShiftHelper(shift_op,
7617 instr->GetSVEVectorFormat(),
7618 zd,
7619 zn,
7620 ReadVRegister(instr->GetRm()),
7621 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007622 break;
7623 default:
7624 VIXL_UNIMPLEMENTED();
7625 break;
7626 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007627}
7628
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007629void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00007630 // Although the instructions have a separate encoding class, the lane size is
7631 // encoded in the same way as most other SVE instructions.
7632 VectorFormat vform = instr->GetSVEVectorFormat();
7633
7634 int pattern = instr->GetImmSVEPredicateConstraint();
7635 int count = GetPredicateConstraintLaneCount(vform, pattern);
7636 int multiplier = instr->ExtractBits(19, 16) + 1;
7637
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007638 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007639 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007640 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007641 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007642 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007643 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007644 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007645 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007646 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007647 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007648 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007649 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007650 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007651 default:
7652 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00007653 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007654 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00007655
7656 WriteXRegister(instr->GetRd(),
7657 IncDecN(ReadXRegister(instr->GetRd()),
7658 count * multiplier,
7659 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007660}
7661
7662void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007663 VectorFormat vform = instr->GetSVEVectorFormat();
7664 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7665 VIXL_UNIMPLEMENTED();
7666 }
7667
7668 int pattern = instr->GetImmSVEPredicateConstraint();
7669 int count = GetPredicateConstraintLaneCount(vform, pattern);
7670 int multiplier = instr->ExtractBits(19, 16) + 1;
7671
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007672 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
7673 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007674 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007675 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007676 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007677 break;
7678 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007679 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007680 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007681 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007682 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007683 default:
7684 VIXL_UNIMPLEMENTED();
7685 break;
7686 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007687
7688 SimVRegister& zd = ReadVRegister(instr->GetRd());
7689 SimVRegister scratch;
7690 dup_immediate(vform,
7691 scratch,
7692 IncDecN(0,
7693 count * multiplier,
7694 LaneSizeInBitsFromFormat(vform)));
7695 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007696}
7697
7698void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
7699 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007700 // Although the instructions have a separate encoding class, the lane size is
7701 // encoded in the same way as most other SVE instructions.
7702 VectorFormat vform = instr->GetSVEVectorFormat();
7703
7704 int pattern = instr->GetImmSVEPredicateConstraint();
7705 int count = GetPredicateConstraintLaneCount(vform, pattern);
7706 int multiplier = instr->ExtractBits(19, 16) + 1;
7707
7708 unsigned width = kXRegSize;
7709 bool is_signed = false;
7710
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007711 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007712 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007713 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007714 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007715 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007716 width = kWRegSize;
7717 VIXL_FALLTHROUGH();
7718 case SQDECB_r_rs_x:
7719 case SQDECD_r_rs_x:
7720 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007721 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007722 is_signed = true;
7723 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007724 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007725 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007726 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007727 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007728 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007729 width = kWRegSize;
7730 VIXL_FALLTHROUGH();
7731 case SQINCB_r_rs_x:
7732 case SQINCD_r_rs_x:
7733 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007734 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007735 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007736 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007737 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007738 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007739 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007740 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007741 width = kWRegSize;
7742 VIXL_FALLTHROUGH();
7743 case UQDECB_r_rs_x:
7744 case UQDECD_r_rs_x:
7745 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007746 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007747 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007748 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007749 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007750 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007751 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007752 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007753 width = kWRegSize;
7754 VIXL_FALLTHROUGH();
7755 case UQINCB_r_rs_x:
7756 case UQINCD_r_rs_x:
7757 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007758 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007759 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007760 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007761 default:
7762 VIXL_UNIMPLEMENTED();
7763 break;
7764 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007765
7766 WriteXRegister(instr->GetRd(),
7767 IncDecN(ReadXRegister(instr->GetRd()),
7768 count * multiplier,
7769 width,
7770 true,
7771 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007772}
7773
7774void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
7775 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007776 VectorFormat vform = instr->GetSVEVectorFormat();
7777 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7778 VIXL_UNIMPLEMENTED();
7779 }
7780
7781 int pattern = instr->GetImmSVEPredicateConstraint();
7782 int count = GetPredicateConstraintLaneCount(vform, pattern);
7783 int multiplier = instr->ExtractBits(19, 16) + 1;
7784
7785 SimVRegister& zd = ReadVRegister(instr->GetRd());
7786 SimVRegister scratch;
7787 dup_immediate(vform,
7788 scratch,
7789 IncDecN(0,
7790 count * multiplier,
7791 LaneSizeInBitsFromFormat(vform)));
7792
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007793 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7794 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007795 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007796 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007797 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007798 break;
7799 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007800 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007801 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007802 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007803 break;
7804 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007805 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007806 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007807 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007808 break;
7809 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007810 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007811 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007812 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007813 break;
7814 default:
7815 VIXL_UNIMPLEMENTED();
7816 break;
7817 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007818}
7819
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007820void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007821 switch (instr->Mask(SVEElementCountMask)) {
7822 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007823 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007824 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007825 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00007826 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007827 break;
7828 default:
7829 VIXL_UNIMPLEMENTED();
7830 break;
7831 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00007832
7833 // Although the instructions are separated, the lane size is encoded in the
7834 // same way as most other SVE instructions.
7835 VectorFormat vform = instr->GetSVEVectorFormat();
7836
7837 int pattern = instr->GetImmSVEPredicateConstraint();
7838 int count = GetPredicateConstraintLaneCount(vform, pattern);
7839 int multiplier = instr->ExtractBits(19, 16) + 1;
7840 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007841}
7842
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007843void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
Martyn Capewell4a9829f2020-01-30 17:41:01 +00007844 VectorFormat vform = instr->GetSVEVectorFormat();
7845 SimVRegister& vdn = ReadVRegister(instr->GetRd());
7846 SimVRegister& zm = ReadVRegister(instr->GetRn());
7847 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7848
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007849 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7850 case FADDA_v_p_z:
Martyn Capewell4a9829f2020-01-30 17:41:01 +00007851 fadda(vform, vdn, pg, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007852 break;
7853 default:
7854 VIXL_UNIMPLEMENTED();
7855 break;
7856 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007857}
7858
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007859void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
TatWai Chongd316c5e2019-10-16 12:22:10 -07007860 VectorFormat vform = instr->GetSVEVectorFormat();
7861 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7862 SimVRegister& zm = ReadVRegister(instr->GetRn());
7863 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7864
7865 SimVRegister result;
7866
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007867 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007868 case FABD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007869 fabd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007870 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007871 case FADD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007872 fadd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007873 break;
7874 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007875 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007876 break;
7877 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007878 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007879 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007880 case FMAXNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007881 fmaxnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007882 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007883 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007884 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007885 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007886 case FMINNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007887 fminnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007888 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007889 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007890 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007891 break;
7892 case FMULX_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007893 fmulx(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007894 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007895 case FMUL_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007896 fmul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007897 break;
7898 case FSCALE_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007899 fscale(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007900 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007901 case FSUBR_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007902 fsub(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007903 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007904 case FSUB_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007905 fsub(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007906 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007907 default:
7908 VIXL_UNIMPLEMENTED();
7909 break;
7910 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07007911 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007912}
7913
7914void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
7915 const Instruction* instr) {
Martyn Capewella2fadc22020-01-16 16:09:55 +00007916 VectorFormat vform = instr->GetSVEVectorFormat();
7917 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7918 VIXL_UNIMPLEMENTED();
7919 }
7920
7921 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7922 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7923 SimVRegister result;
7924
7925 int i1 = instr->ExtractBit(5);
7926 SimVRegister add_sub_imm, min_max_imm, mul_imm;
7927 uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
7928 uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
7929 uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
7930 dup_immediate(vform, add_sub_imm, i1 ? one : half);
7931 dup_immediate(vform, min_max_imm, i1 ? one : 0);
7932 dup_immediate(vform, mul_imm, i1 ? two : half);
7933
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007934 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
7935 case FADD_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007936 fadd(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007937 break;
7938 case FMAXNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007939 fmaxnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007940 break;
7941 case FMAX_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007942 fmax(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007943 break;
7944 case FMINNM_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007945 fminnm(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007946 break;
7947 case FMIN_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007948 fmin(vform, result, zdn, min_max_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007949 break;
7950 case FMUL_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007951 fmul(vform, result, zdn, mul_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007952 break;
7953 case FSUBR_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007954 fsub(vform, result, add_sub_imm, zdn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007955 break;
7956 case FSUB_z_p_zs:
Martyn Capewella2fadc22020-01-16 16:09:55 +00007957 fsub(vform, result, zdn, add_sub_imm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007958 break;
7959 default:
7960 VIXL_UNIMPLEMENTED();
7961 break;
7962 }
Martyn Capewella2fadc22020-01-16 16:09:55 +00007963 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007964}
7965
7966void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00007967 VectorFormat vform = instr->GetSVEVectorFormat();
7968 SimVRegister& zd = ReadVRegister(instr->GetRd());
7969 SimVRegister& zm = ReadVRegister(instr->GetRn());
7970
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007971 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007972 case FTMAD_z_zzi:
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00007973 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007974 break;
7975 default:
7976 VIXL_UNIMPLEMENTED();
7977 break;
7978 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007979}
7980
7981void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
TatWai Chongfe536042019-10-23 16:34:11 -07007982 VectorFormat vform = instr->GetSVEVectorFormat();
7983 SimVRegister& zd = ReadVRegister(instr->GetRd());
7984 SimVRegister& zn = ReadVRegister(instr->GetRn());
7985 SimVRegister& zm = ReadVRegister(instr->GetRm());
7986
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007987 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7988 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007989 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007990 break;
7991 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007992 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007993 break;
7994 case FRECPS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00007995 frecps(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007996 break;
7997 case FRSQRTS_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00007998 frsqrts(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007999 break;
8000 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07008001 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008002 break;
8003 case FTSMUL_z_zz:
Martyn Capewellefd9dc72020-02-13 10:46:29 +00008004 ftsmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008005 break;
8006 default:
8007 VIXL_UNIMPLEMENTED();
8008 break;
8009 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008010}
8011
8012void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
TatWai Chong47c26842020-02-10 01:51:32 -08008013 SimPRegister& pd = ReadPRegister(instr->GetPd());
8014 SimVRegister& zn = ReadVRegister(instr->GetRn());
8015 SimVRegister& zm = ReadVRegister(instr->GetRm());
8016 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8017 VectorFormat vform = instr->GetSVEVectorFormat();
8018 SimVRegister result;
8019
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008020 switch (instr->Mask(SVEFPCompareVectorsMask)) {
8021 case FACGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08008022 fabscmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008023 break;
8024 case FACGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08008025 fabscmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008026 break;
8027 case FCMEQ_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08008028 fcmp(vform, result, zn, zm, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008029 break;
8030 case FCMGE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08008031 fcmp(vform, result, zn, zm, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008032 break;
8033 case FCMGT_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08008034 fcmp(vform, result, zn, zm, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008035 break;
8036 case FCMNE_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08008037 fcmp(vform, result, zn, zm, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008038 break;
8039 case FCMUO_p_p_zz:
TatWai Chong47c26842020-02-10 01:51:32 -08008040 fcmp(vform, result, zn, zm, uo);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008041 break;
8042 default:
8043 VIXL_UNIMPLEMENTED();
8044 break;
8045 }
TatWai Chong47c26842020-02-10 01:51:32 -08008046
8047 ExtractFromSimVRegister(vform, pd, result);
8048 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008049}
8050
8051void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
TatWai Chonge3775132020-02-16 22:13:17 -08008052 SimPRegister& pd = ReadPRegister(instr->GetPd());
8053 SimVRegister& zn = ReadVRegister(instr->GetRn());
8054 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8055 VectorFormat vform = instr->GetSVEVectorFormat();
8056 SimVRegister result;
8057
8058 SimVRegister zeros;
8059 dup_immediate(kFormatVnD, zeros, 0);
8060
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008061 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
8062 case FCMEQ_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08008063 fcmp(vform, result, zn, zeros, eq);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008064 break;
8065 case FCMGE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08008066 fcmp(vform, result, zn, zeros, ge);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008067 break;
8068 case FCMGT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08008069 fcmp(vform, result, zn, zeros, gt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008070 break;
8071 case FCMLE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08008072 fcmp(vform, result, zn, zeros, le);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008073 break;
8074 case FCMLT_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08008075 fcmp(vform, result, zn, zeros, lt);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008076 break;
8077 case FCMNE_p_p_z0:
TatWai Chonge3775132020-02-16 22:13:17 -08008078 fcmp(vform, result, zn, zeros, ne);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008079 break;
8080 default:
8081 VIXL_UNIMPLEMENTED();
8082 break;
8083 }
TatWai Chonge3775132020-02-16 22:13:17 -08008084
8085 ExtractFromSimVRegister(vform, pd, result);
8086 mov_zeroing(pd, pg, pd);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008087}
8088
8089void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
Martyn Capewell0b1afa82020-03-04 11:31:42 +00008090 VectorFormat vform = instr->GetSVEVectorFormat();
8091
8092 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
8093 VIXL_UNIMPLEMENTED();
8094 }
8095
8096 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8097 SimVRegister& zm = ReadVRegister(instr->GetRn());
8098 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8099 int rot = instr->ExtractBit(16);
8100
8101 SimVRegister result;
8102
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008103 switch (instr->Mask(SVEFPComplexAdditionMask)) {
8104 case FCADD_z_p_zz:
Martyn Capewell0b1afa82020-03-04 11:31:42 +00008105 fcadd(vform, result, zdn, zm, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008106 break;
8107 default:
8108 VIXL_UNIMPLEMENTED();
8109 break;
8110 }
Martyn Capewell0b1afa82020-03-04 11:31:42 +00008111 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008112}
8113
8114void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
Martyn Capewell75f1c432020-03-30 09:23:27 +01008115 VectorFormat vform = instr->GetSVEVectorFormat();
8116
8117 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
8118 VIXL_UNIMPLEMENTED();
8119 }
8120
8121 SimVRegister& zda = ReadVRegister(instr->GetRd());
8122 SimVRegister& zn = ReadVRegister(instr->GetRn());
8123 SimVRegister& zm = ReadVRegister(instr->GetRm());
8124 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8125 int rot = instr->ExtractBits(14, 13);
8126
8127 SimVRegister result;
8128
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008129 switch (instr->Mask(SVEFPComplexMulAddMask)) {
8130 case FCMLA_z_p_zzz:
Martyn Capewell75f1c432020-03-30 09:23:27 +01008131 fcmla(vform, result, zn, zm, zda, rot);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008132 break;
8133 default:
8134 VIXL_UNIMPLEMENTED();
8135 break;
8136 }
Martyn Capewell75f1c432020-03-30 09:23:27 +01008137 mov_merging(vform, zda, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008138}
8139
8140void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
Martyn Capewelle4886e52020-03-30 09:28:52 +01008141 SimVRegister& zda = ReadVRegister(instr->GetRd());
8142 SimVRegister& zn = ReadVRegister(instr->GetRn());
8143 int rot = instr->ExtractBits(11, 10);
8144 unsigned zm_code = instr->GetRm();
8145 int index = -1;
8146 VectorFormat vform, vform_dup;
8147
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008148 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
8149 case FCMLA_z_zzzi_h:
Martyn Capewelle4886e52020-03-30 09:28:52 +01008150 vform = kFormatVnH;
8151 vform_dup = kFormatVnS;
8152 index = zm_code >> 3;
8153 zm_code &= 0x7;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008154 break;
8155 case FCMLA_z_zzzi_s:
Martyn Capewelle4886e52020-03-30 09:28:52 +01008156 vform = kFormatVnS;
8157 vform_dup = kFormatVnD;
8158 index = zm_code >> 4;
8159 zm_code &= 0xf;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008160 break;
8161 default:
8162 VIXL_UNIMPLEMENTED();
8163 break;
8164 }
Martyn Capewelle4886e52020-03-30 09:28:52 +01008165
8166 if (index >= 0) {
8167 SimVRegister temp;
8168 dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
8169 fcmla(vform, zda, zn, temp, zda, rot);
8170 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008171}
8172
Martyn Capewell894962f2020-02-05 15:46:44 +00008173typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
8174 LogicVRegister dst,
8175 const LogicVRegister& src);
8176
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008177void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
Martyn Capewell894962f2020-02-05 15:46:44 +00008178 VectorFormat vform = instr->GetSVEVectorFormat();
8179 SimVRegister& vd = ReadVRegister(instr->GetRd());
8180 SimVRegister& zn = ReadVRegister(instr->GetRn());
8181 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8182 int lane_size = LaneSizeInBitsFromFormat(vform);
8183
8184 uint64_t inactive_value = 0;
8185 FastReduceFn fn = nullptr;
8186
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008187 switch (instr->Mask(SVEFPFastReductionMask)) {
8188 case FADDV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00008189 fn = &Simulator::faddv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008190 break;
8191 case FMAXNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00008192 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
8193 fn = &Simulator::fmaxnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008194 break;
8195 case FMAXV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00008196 inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
8197 fn = &Simulator::fmaxv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008198 break;
8199 case FMINNMV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00008200 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
8201 fn = &Simulator::fminnmv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008202 break;
8203 case FMINV_v_p_z:
Martyn Capewell894962f2020-02-05 15:46:44 +00008204 inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
8205 fn = &Simulator::fminv;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008206 break;
8207 default:
8208 VIXL_UNIMPLEMENTED();
8209 break;
8210 }
Martyn Capewell894962f2020-02-05 15:46:44 +00008211
8212 SimVRegister scratch;
8213 dup_immediate(vform, scratch, inactive_value);
8214 mov_merging(vform, scratch, pg, zn);
8215 if (fn != nullptr) (this->*fn)(vform, vd, scratch);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008216}
8217
8218void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
Martyn Capewell50e9f552020-01-07 17:45:03 +00008219 VectorFormat vform = kFormatUndefined;
8220 unsigned zm_code = instr->GetRm() & 0xf;
8221 unsigned index = instr->ExtractBits(20, 19);
8222
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008223 switch (instr->Mask(SVEFPMulIndexMask)) {
8224 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +00008225 vform = kFormatVnD;
8226 index >>= 1; // Only bit 20 is the index for D lanes.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008227 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +00008228 case FMUL_z_zzi_h_i3h:
8229 index += 4; // Bit 22 (i3h) is the top bit of index.
8230 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008231 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +00008232 vform = kFormatVnH;
8233 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008234 break;
8235 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +00008236 vform = kFormatVnS;
8237 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008238 break;
8239 default:
8240 VIXL_UNIMPLEMENTED();
8241 break;
8242 }
Martyn Capewell50e9f552020-01-07 17:45:03 +00008243
8244 SimVRegister& zd = ReadVRegister(instr->GetRd());
8245 SimVRegister& zn = ReadVRegister(instr->GetRn());
8246 SimVRegister temp;
8247
Martyn Capewell46352612020-07-02 15:47:54 +01008248 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
Martyn Capewell50e9f552020-01-07 17:45:03 +00008249 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008250}
8251
8252void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
TatWai Chongf8d29f12020-02-16 22:53:18 -08008253 VectorFormat vform = instr->GetSVEVectorFormat();
8254
8255 SimVRegister& zd = ReadVRegister(instr->GetRd());
8256 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8257 SimVRegister result;
8258
8259 if (instr->ExtractBit(15) == 0) {
8260 // Floating-point multiply-accumulate writing addend.
8261 SimVRegister& zm = ReadVRegister(instr->GetRm());
8262 SimVRegister& zn = ReadVRegister(instr->GetRn());
8263
8264 switch (instr->Mask(SVEFPMulAddMask)) {
8265 // zda = zda + zn * zm
8266 case FMLA_z_p_zzz:
8267 fmla(vform, result, zd, zn, zm);
8268 break;
8269 // zda = -zda + -zn * zm
8270 case FNMLA_z_p_zzz:
8271 fneg(vform, result, zd);
8272 fmls(vform, result, result, zn, zm);
8273 break;
8274 // zda = zda + -zn * zm
8275 case FMLS_z_p_zzz:
8276 fmls(vform, result, zd, zn, zm);
8277 break;
8278 // zda = -zda + zn * zm
8279 case FNMLS_z_p_zzz:
8280 fneg(vform, result, zd);
8281 fmla(vform, result, result, zn, zm);
8282 break;
8283 default:
8284 VIXL_UNIMPLEMENTED();
8285 break;
8286 }
8287 } else {
8288 // Floating-point multiply-accumulate writing multiplicand.
8289 SimVRegister& za = ReadVRegister(instr->GetRm());
8290 SimVRegister& zm = ReadVRegister(instr->GetRn());
8291
8292 switch (instr->Mask(SVEFPMulAddMask)) {
8293 // zdn = za + zdn * zm
8294 case FMAD_z_p_zzz:
8295 fmla(vform, result, za, zd, zm);
8296 break;
8297 // zdn = -za + -zdn * zm
8298 case FNMAD_z_p_zzz:
8299 fneg(vform, result, za);
8300 fmls(vform, result, result, zd, zm);
8301 break;
8302 // zdn = za + -zdn * zm
8303 case FMSB_z_p_zzz:
8304 fmls(vform, result, za, zd, zm);
8305 break;
8306 // zdn = -za + zdn * zm
8307 case FNMSB_z_p_zzz:
8308 fneg(vform, result, za);
8309 fmla(vform, result, result, zd, zm);
8310 break;
8311 default:
8312 VIXL_UNIMPLEMENTED();
8313 break;
8314 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008315 }
TatWai Chongf8d29f12020-02-16 22:53:18 -08008316
8317 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008318}
8319
8320void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
TatWai Chonga2c1bb72020-02-16 23:16:47 -08008321 VectorFormat vform = kFormatUndefined;
8322 unsigned zm_code = 0xffffffff;
8323 unsigned index = 0xffffffff;
8324
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008325 switch (instr->Mask(SVEFPMulAddIndexMask)) {
8326 case FMLA_z_zzzi_d:
TatWai Chonga2c1bb72020-02-16 23:16:47 -08008327 case FMLS_z_zzzi_d:
8328 vform = kFormatVnD;
8329 zm_code = instr->GetRmLow16();
8330 // Only bit 20 is the index for D lanes.
8331 index = instr->ExtractBit(20);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008332 break;
8333 case FMLA_z_zzzi_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008334 case FMLS_z_zzzi_s:
TatWai Chonga2c1bb72020-02-16 23:16:47 -08008335 vform = kFormatVnS;
8336 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
8337 index = instr->ExtractBits(20, 19);
8338 break;
8339 case FMLA_z_zzzi_h:
8340 case FMLS_z_zzzi_h:
8341 case FMLA_z_zzzi_h_i3h:
8342 case FMLS_z_zzzi_h_i3h:
8343 vform = kFormatVnH;
8344 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
8345 index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008346 break;
8347 default:
8348 VIXL_UNIMPLEMENTED();
8349 break;
8350 }
TatWai Chonga2c1bb72020-02-16 23:16:47 -08008351
8352 SimVRegister& zd = ReadVRegister(instr->GetRd());
8353 SimVRegister& zn = ReadVRegister(instr->GetRn());
8354 SimVRegister temp;
8355
Martyn Capewellc7501512020-03-16 10:35:33 +00008356 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
TatWai Chonga2c1bb72020-02-16 23:16:47 -08008357 if (instr->ExtractBit(10) == 1) {
8358 fmls(vform, zd, zd, zn, temp);
8359 } else {
8360 fmla(vform, zd, zd, zn, temp);
8361 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008362}
8363
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008364void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -08008365 SimVRegister& zd = ReadVRegister(instr->GetRd());
8366 SimVRegister& zn = ReadVRegister(instr->GetRn());
8367 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8368 int dst_data_size;
8369 int src_data_size;
8370
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008371 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008372 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008373 case FCVTZU_z_p_z_d2w:
8374 dst_data_size = kSRegSize;
8375 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008376 break;
8377 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008378 case FCVTZU_z_p_z_d2x:
8379 dst_data_size = kDRegSize;
8380 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008381 break;
8382 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008383 case FCVTZU_z_p_z_fp162h:
8384 dst_data_size = kHRegSize;
8385 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008386 break;
8387 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008388 case FCVTZU_z_p_z_fp162w:
8389 dst_data_size = kSRegSize;
8390 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008391 break;
8392 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008393 case FCVTZU_z_p_z_fp162x:
8394 dst_data_size = kDRegSize;
8395 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008396 break;
8397 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008398 case FCVTZU_z_p_z_s2w:
8399 dst_data_size = kSRegSize;
8400 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008401 break;
8402 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008403 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008404 dst_data_size = kDRegSize;
8405 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008406 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008407 default:
8408 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -08008409 dst_data_size = 0;
8410 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008411 break;
8412 }
TatWai Chongdb7437c2020-01-09 17:44:10 -08008413
8414 VectorFormat vform =
8415 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
TatWai Chongdb7437c2020-01-09 17:44:10 -08008416
8417 if (instr->ExtractBit(16) == 0) {
8418 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8419 } else {
8420 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8421 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008422}
8423
8424void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
TatWai Chong2cb1b612020-03-04 23:51:21 -08008425 SimVRegister& zd = ReadVRegister(instr->GetRd());
8426 SimVRegister& zn = ReadVRegister(instr->GetRn());
8427 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8428 int dst_data_size;
8429 int src_data_size;
8430
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008431 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008432 case FCVT_z_p_z_d2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -08008433 dst_data_size = kHRegSize;
8434 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008435 break;
8436 case FCVT_z_p_z_d2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -08008437 dst_data_size = kSRegSize;
8438 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008439 break;
8440 case FCVT_z_p_z_h2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -08008441 dst_data_size = kDRegSize;
8442 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008443 break;
8444 case FCVT_z_p_z_h2s:
TatWai Chong2cb1b612020-03-04 23:51:21 -08008445 dst_data_size = kSRegSize;
8446 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008447 break;
8448 case FCVT_z_p_z_s2d:
TatWai Chong2cb1b612020-03-04 23:51:21 -08008449 dst_data_size = kDRegSize;
8450 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008451 break;
8452 case FCVT_z_p_z_s2h:
TatWai Chong2cb1b612020-03-04 23:51:21 -08008453 dst_data_size = kHRegSize;
8454 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008455 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008456 default:
8457 VIXL_UNIMPLEMENTED();
TatWai Chong2cb1b612020-03-04 23:51:21 -08008458 dst_data_size = 0;
8459 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008460 break;
8461 }
TatWai Chong2cb1b612020-03-04 23:51:21 -08008462 VectorFormat vform =
8463 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8464
8465 fcvt(vform, dst_data_size, src_data_size, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008466}
8467
8468void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
TatWai Chongf60f6dc2020-02-21 10:48:11 -08008469 SimVRegister& zd = ReadVRegister(instr->GetRd());
8470 SimVRegister& zn = ReadVRegister(instr->GetRn());
8471 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8472 VectorFormat vform = instr->GetSVEVectorFormat();
8473 SimVRegister result;
8474
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008475 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008476 case FRECPX_z_p_z:
TatWai Chongf60f6dc2020-02-21 10:48:11 -08008477 frecpx(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008478 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008479 case FSQRT_z_p_z:
TatWai Chongb4a25f62020-02-27 00:53:57 -08008480 fsqrt(vform, result, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008481 break;
8482 default:
8483 VIXL_UNIMPLEMENTED();
8484 break;
8485 }
TatWai Chongf60f6dc2020-02-21 10:48:11 -08008486 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008487}
8488
8489void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008490 SimVRegister& zd = ReadVRegister(instr->GetRd());
8491 SimVRegister& zn = ReadVRegister(instr->GetRn());
8492 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8493 VectorFormat vform = instr->GetSVEVectorFormat();
8494 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8495 bool exact_exception = false;
8496
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008497 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008498 case FRINTA_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008499 fpcr_rounding = FPTieAway;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008500 break;
8501 case FRINTI_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008502 break; // Use FPCR rounding mode.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008503 case FRINTM_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008504 fpcr_rounding = FPNegativeInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008505 break;
8506 case FRINTN_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008507 fpcr_rounding = FPTieEven;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008508 break;
8509 case FRINTP_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008510 fpcr_rounding = FPPositiveInfinity;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008511 break;
8512 case FRINTX_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008513 exact_exception = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008514 break;
8515 case FRINTZ_z_p_z:
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008516 fpcr_rounding = FPZero;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008517 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008518 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008519 VIXL_UNIMPLEMENTED();
8520 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008521 }
TatWai Chongf07b8ce2020-02-17 00:05:54 -08008522
8523 SimVRegister result;
8524 frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
8525 mov_merging(vform, zd, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008526}
8527
8528void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
TatWai Chong31cd6a02020-01-10 13:03:26 -08008529 SimVRegister& zd = ReadVRegister(instr->GetRd());
8530 SimVRegister& zn = ReadVRegister(instr->GetRn());
8531 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8532 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8533 int dst_data_size;
8534 int src_data_size;
8535
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008536 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008537 case SCVTF_z_p_z_h2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008538 case UCVTF_z_p_z_h2fp16:
8539 dst_data_size = kHRegSize;
8540 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008541 break;
8542 case SCVTF_z_p_z_w2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008543 case UCVTF_z_p_z_w2d:
8544 dst_data_size = kDRegSize;
8545 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008546 break;
8547 case SCVTF_z_p_z_w2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008548 case UCVTF_z_p_z_w2fp16:
8549 dst_data_size = kHRegSize;
8550 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008551 break;
8552 case SCVTF_z_p_z_w2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008553 case UCVTF_z_p_z_w2s:
8554 dst_data_size = kSRegSize;
8555 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008556 break;
8557 case SCVTF_z_p_z_x2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008558 case UCVTF_z_p_z_x2d:
8559 dst_data_size = kDRegSize;
8560 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008561 break;
8562 case SCVTF_z_p_z_x2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008563 case UCVTF_z_p_z_x2fp16:
8564 dst_data_size = kHRegSize;
8565 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008566 break;
8567 case SCVTF_z_p_z_x2s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008568 case UCVTF_z_p_z_x2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008569 dst_data_size = kSRegSize;
8570 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008571 break;
8572 default:
8573 VIXL_UNIMPLEMENTED();
TatWai Chong31cd6a02020-01-10 13:03:26 -08008574 dst_data_size = 0;
8575 src_data_size = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008576 break;
8577 }
TatWai Chong31cd6a02020-01-10 13:03:26 -08008578
8579 VectorFormat vform =
8580 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8581
8582 if (instr->ExtractBit(16) == 0) {
8583 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
8584 } else {
8585 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
8586 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008587}
8588
8589void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
Martyn Capewell13050ca2020-02-11 16:43:40 +00008590 VectorFormat vform = instr->GetSVEVectorFormat();
8591 SimVRegister& zd = ReadVRegister(instr->GetRd());
8592 SimVRegister& zn = ReadVRegister(instr->GetRn());
8593 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8594
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008595 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8596 case FRECPE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +00008597 frecpe(vform, zd, zn, fpcr_rounding);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008598 break;
8599 case FRSQRTE_z_z:
Martyn Capewell13050ca2020-02-11 16:43:40 +00008600 frsqrte(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008601 break;
8602 default:
8603 VIXL_UNIMPLEMENTED();
8604 break;
8605 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008606}
8607
8608void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008609 VectorFormat vform = instr->GetSVEVectorFormat();
8610 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
8611
8612 int count = CountActiveLanes(vform, pg);
8613
8614 if (instr->ExtractBit(11) == 0) {
8615 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8616 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8617 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008618 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008619 break;
8620 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008621 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008622 break;
8623 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008624 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008625 break;
8626 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008627 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008628 break;
8629 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008630 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008631 break;
8632 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008633 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008634 break;
8635 default:
8636 VIXL_UNIMPLEMENTED();
8637 break;
8638 }
8639 } else {
8640 bool is_saturating = (instr->ExtractBit(18) == 0);
8641 bool decrement =
8642 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
8643 bool is_signed = (instr->ExtractBit(16) == 0);
8644 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
8645 unsigned width = sf ? kXRegSize : kWRegSize;
8646
8647 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8648 case DECP_r_p_r:
8649 case INCP_r_p_r:
8650 case SQDECP_r_p_r_sx:
8651 case SQDECP_r_p_r_x:
8652 case SQINCP_r_p_r_sx:
8653 case SQINCP_r_p_r_x:
8654 case UQDECP_r_p_r_uw:
8655 case UQDECP_r_p_r_x:
8656 case UQINCP_r_p_r_uw:
8657 case UQINCP_r_p_r_x:
8658 WriteXRegister(instr->GetRd(),
8659 IncDecN(ReadXRegister(instr->GetRd()),
8660 decrement ? -count : count,
8661 width,
8662 is_saturating,
8663 is_signed));
8664 break;
8665 default:
8666 VIXL_UNIMPLEMENTED();
8667 break;
8668 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008669 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008670}
8671
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008672uint64_t Simulator::IncDecN(uint64_t acc,
8673 int64_t delta,
8674 unsigned n,
8675 bool is_saturating,
8676 bool is_signed) {
8677 VIXL_ASSERT(n <= 64);
8678 VIXL_ASSERT(IsIntN(n, delta));
8679
8680 uint64_t sign_mask = UINT64_C(1) << (n - 1);
8681 uint64_t mask = GetUintMask(n);
8682
8683 acc &= mask; // Ignore initial accumulator high bits.
8684 uint64_t result = (acc + delta) & mask;
8685
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008686 bool result_negative = ((result & sign_mask) != 0);
8687
8688 if (is_saturating) {
8689 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00008690 bool acc_negative = ((acc & sign_mask) != 0);
8691 bool delta_negative = delta < 0;
8692
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008693 // If the signs of the operands are the same, but different from the
8694 // result, there was an overflow.
8695 if ((acc_negative == delta_negative) &&
8696 (acc_negative != result_negative)) {
8697 if (result_negative) {
8698 // Saturate to [..., INT<n>_MAX].
8699 result_negative = false;
8700 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
8701 } else {
8702 // Saturate to [INT<n>_MIN, ...].
8703 result_negative = true;
8704 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
8705 }
8706 }
8707 } else {
8708 if ((delta < 0) && (result > acc)) {
8709 // Saturate to [0, ...].
8710 result = 0;
8711 } else if ((delta > 0) && (result < acc)) {
8712 // Saturate to [..., UINT<n>_MAX].
8713 result = mask;
8714 }
8715 }
8716 }
8717
8718 // Sign-extend if necessary.
8719 if (result_negative && is_signed) result |= ~mask;
8720
8721 return result;
8722}
8723
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008724void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008725 VectorFormat vform = instr->GetSVEVectorFormat();
8726 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008727 switch (instr->Mask(SVEIndexGenerationMask)) {
8728 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008729 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008730 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008731 case INDEX_z_rr: {
8732 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
8733 : instr->ExtractSignedBits(9, 5);
8734 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
8735 : instr->ExtractSignedBits(20, 16);
8736 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008737 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008738 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008739 default:
8740 VIXL_UNIMPLEMENTED();
8741 break;
8742 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008743}
8744
8745void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -07008746 VectorFormat vform = instr->GetSVEVectorFormat();
8747 SimVRegister& zd = ReadVRegister(instr->GetRd());
8748 SimVRegister& zn = ReadVRegister(instr->GetRn());
8749 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008750 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8751 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008752 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008753 break;
8754 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008755 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008756 break;
8757 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008758 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008759 break;
8760 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008761 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008762 break;
8763 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008764 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008765 break;
8766 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008767 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008768 break;
8769 default:
8770 VIXL_UNIMPLEMENTED();
8771 break;
8772 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008773}
8774
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008775void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008776 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -07008777 VectorFormat vform = instr->GetSVEVectorFormat();
8778 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8779 SimVRegister& zm = ReadVRegister(instr->GetRn());
8780 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8781 SimVRegister result;
8782
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008783 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008784 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008785 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008786 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008787 case SUBR_z_p_zz:
8788 sub(vform, result, zm, zdn);
8789 break;
8790 case SUB_z_p_zz:
8791 sub(vform, result, zdn, zm);
8792 break;
8793 default:
8794 VIXL_UNIMPLEMENTED();
8795 break;
8796 }
8797 mov_merging(vform, zdn, pg, result);
8798}
8799
8800void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
8801 VectorFormat vform = instr->GetSVEVectorFormat();
8802 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8803 SimVRegister& zm = ReadVRegister(instr->GetRn());
8804 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8805 SimVRegister result;
8806
8807 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008808 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008809 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008810 break;
8811 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008812 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008813 break;
8814 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008815 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008816 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008817 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008818 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008819 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008820 default:
8821 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008822 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008823 }
8824 mov_merging(vform, zdn, pg, result);
8825}
8826
8827void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
8828 VectorFormat vform = instr->GetSVEVectorFormat();
8829 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8830 SimVRegister& zm = ReadVRegister(instr->GetRn());
8831 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8832 SimVRegister result;
8833
8834 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
8835 case MUL_z_p_zz:
8836 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008837 break;
8838 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008839 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008840 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008841 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008842 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008843 break;
8844 default:
8845 VIXL_UNIMPLEMENTED();
8846 break;
8847 }
TatWai Chong13634762019-07-16 16:20:45 -07008848 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008849}
8850
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008851void Simulator::VisitSVEIntMinMaxDifference_Predicated(
8852 const Instruction* instr) {
8853 VectorFormat vform = instr->GetSVEVectorFormat();
8854 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8855 SimVRegister& zm = ReadVRegister(instr->GetRn());
8856 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8857 SimVRegister result;
8858
8859 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
8860 case SABD_z_p_zz:
8861 absdiff(vform, result, zdn, zm, true);
8862 break;
8863 case SMAX_z_p_zz:
8864 smax(vform, result, zdn, zm);
8865 break;
8866 case SMIN_z_p_zz:
8867 smin(vform, result, zdn, zm);
8868 break;
8869 case UABD_z_p_zz:
8870 absdiff(vform, result, zdn, zm, false);
8871 break;
8872 case UMAX_z_p_zz:
8873 umax(vform, result, zdn, zm);
8874 break;
8875 case UMIN_z_p_zz:
8876 umin(vform, result, zdn, zm);
8877 break;
8878 default:
8879 VIXL_UNIMPLEMENTED();
8880 break;
8881 }
8882 mov_merging(vform, zdn, pg, result);
8883}
8884
8885void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
8886 VectorFormat vform = instr->GetSVEVectorFormat();
8887 SimVRegister& zd = ReadVRegister(instr->GetRd());
8888 SimVRegister scratch;
8889
8890 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
8891 case MUL_z_zi:
8892 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
8893 mul(vform, zd, zd, scratch);
8894 break;
8895 default:
8896 VIXL_UNIMPLEMENTED();
8897 break;
8898 }
8899}
8900
8901void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
8902 VectorFormat vform = instr->GetSVEVectorFormat();
8903 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8904 SimVRegister& zm = ReadVRegister(instr->GetRn());
8905 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8906 SimVRegister result;
8907
8908 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
8909
8910 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
8911 case SDIVR_z_p_zz:
8912 sdiv(vform, result, zm, zdn);
8913 break;
8914 case SDIV_z_p_zz:
8915 sdiv(vform, result, zdn, zm);
8916 break;
8917 case UDIVR_z_p_zz:
8918 udiv(vform, result, zm, zdn);
8919 break;
8920 case UDIV_z_p_zz:
8921 udiv(vform, result, zdn, zm);
8922 break;
8923 default:
8924 VIXL_UNIMPLEMENTED();
8925 break;
8926 }
8927 mov_merging(vform, zdn, pg, result);
8928}
8929
8930void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
8931 VectorFormat vform = instr->GetSVEVectorFormat();
8932 SimVRegister& zd = ReadVRegister(instr->GetRd());
8933 SimVRegister scratch;
8934
8935 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
8936 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
8937
8938 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
8939 case SMAX_z_zi:
8940 dup_immediate(vform, scratch, signed_imm);
8941 smax(vform, zd, zd, scratch);
8942 break;
8943 case SMIN_z_zi:
8944 dup_immediate(vform, scratch, signed_imm);
8945 smin(vform, zd, zd, scratch);
8946 break;
8947 case UMAX_z_zi:
8948 dup_immediate(vform, scratch, unsigned_imm);
8949 umax(vform, zd, zd, scratch);
8950 break;
8951 case UMIN_z_zi:
8952 dup_immediate(vform, scratch, unsigned_imm);
8953 umin(vform, zd, zd, scratch);
8954 break;
8955 default:
8956 VIXL_UNIMPLEMENTED();
8957 break;
8958 }
8959}
8960
8961void Simulator::VisitSVEIntCompareScalarCountAndLimit(
8962 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -07008963 unsigned rn_code = instr->GetRn();
8964 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008965 SimPRegister& pd = ReadPRegister(instr->GetPd());
8966 VectorFormat vform = instr->GetSVEVectorFormat();
8967 bool is_64_bit = instr->ExtractBit(12) == 1;
8968 int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8969 int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
TatWai Chongc844bb22019-06-10 15:32:53 -07008970
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008971 bool last = true;
8972 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
8973 bool cond = false;
8974 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
8975 case WHILELE_p_p_rr:
8976 cond = src1 <= src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008977 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008978 case WHILELO_p_p_rr:
8979 cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
8980 break;
8981 case WHILELS_p_p_rr:
8982 cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
8983 break;
8984 case WHILELT_p_p_rr:
8985 cond = src1 < src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008986 break;
8987 default:
TatWai Chongc844bb22019-06-10 15:32:53 -07008988 VIXL_UNIMPLEMENTED();
8989 break;
8990 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008991 last = last && cond;
8992 LogicPRegister dst(pd);
8993 dst.SetActive(vform, lane, last);
8994 src1 += 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008995 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008996
8997 PredTest(vform, GetPTrue(), pd);
8998 LogSystemRegister(NZCV);
8999}
9000
9001void Simulator::VisitSVEConditionallyTerminateScalars(
9002 const Instruction* instr) {
9003 unsigned rn_code = instr->GetRn();
9004 unsigned rm_code = instr->GetRm();
9005 bool is_64_bit = instr->ExtractBit(22) == 1;
9006 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
9007 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
9008 bool term;
9009 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
9010 case CTERMEQ_rr:
9011 term = src1 == src2;
9012 break;
9013 case CTERMNE_rr:
9014 term = src1 != src2;
9015 break;
9016 default:
9017 term = false;
9018 VIXL_UNIMPLEMENTED();
9019 break;
9020 }
9021 ReadNzcv().SetN(term ? 1 : 0);
9022 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -07009023 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009024}
9025
9026void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -07009027 bool commute_inputs = false;
9028 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009029 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
9030 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009031 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009032 break;
9033 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009034 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009035 break;
9036 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009037 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009038 break;
9039 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009040 cond = ge;
9041 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009042 break;
9043 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009044 cond = gt;
9045 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009046 break;
9047 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009048 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009049 break;
9050 default:
TatWai Chong302729c2019-06-14 16:18:51 -07009051 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009052 VIXL_UNIMPLEMENTED();
9053 break;
9054 }
TatWai Chong302729c2019-06-14 16:18:51 -07009055
9056 VectorFormat vform = instr->GetSVEVectorFormat();
9057 SimVRegister src2;
9058 dup_immediate(vform,
9059 src2,
9060 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
9061 SVEIntCompareVectorsHelper(cond,
9062 vform,
9063 ReadPRegister(instr->GetPd()),
9064 ReadPRegister(instr->GetPgLow8()),
9065 commute_inputs ? src2
9066 : ReadVRegister(instr->GetRn()),
9067 commute_inputs ? ReadVRegister(instr->GetRn())
9068 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009069}
9070
9071void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
TatWai Chong302729c2019-06-14 16:18:51 -07009072 bool commute_inputs = false;
9073 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009074 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
9075 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009076 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009077 break;
9078 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009079 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009080 break;
9081 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009082 cond = hi;
9083 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009084 break;
9085 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07009086 cond = hs;
9087 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009088 break;
9089 default:
TatWai Chong302729c2019-06-14 16:18:51 -07009090 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009091 VIXL_UNIMPLEMENTED();
9092 break;
9093 }
TatWai Chong302729c2019-06-14 16:18:51 -07009094
9095 VectorFormat vform = instr->GetSVEVectorFormat();
9096 SimVRegister src2;
9097 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
9098 SVEIntCompareVectorsHelper(cond,
9099 vform,
9100 ReadPRegister(instr->GetPd()),
9101 ReadPRegister(instr->GetPgLow8()),
9102 commute_inputs ? src2
9103 : ReadVRegister(instr->GetRn()),
9104 commute_inputs ? ReadVRegister(instr->GetRn())
9105 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009106}
9107
9108void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
TatWai Chong96713fe2019-06-04 16:39:37 -07009109 Instr op = instr->Mask(SVEIntCompareVectorsMask);
9110 bool is_wide_elements = false;
9111 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009112 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -07009113 case CMPGE_p_p_zw:
9114 case CMPGT_p_p_zw:
9115 case CMPHI_p_p_zw:
9116 case CMPHS_p_p_zw:
9117 case CMPLE_p_p_zw:
9118 case CMPLO_p_p_zw:
9119 case CMPLS_p_p_zw:
9120 case CMPLT_p_p_zw:
9121 case CMPNE_p_p_zw:
9122 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009123 break;
TatWai Chong96713fe2019-06-04 16:39:37 -07009124 }
9125
TatWai Chong302729c2019-06-14 16:18:51 -07009126 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -07009127 switch (op) {
9128 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009129 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07009130 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009131 break;
9132 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009133 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07009134 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009135 break;
9136 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009137 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07009138 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009139 break;
9140 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009141 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07009142 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009143 break;
9144 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009145 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07009146 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009147 break;
9148 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009149 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07009150 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -07009151 break;
9152 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07009153 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -07009154 break;
9155 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07009156 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -07009157 break;
9158 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07009159 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -07009160 break;
9161 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07009162 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009163 break;
9164 default:
9165 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -07009166 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009167 break;
9168 }
TatWai Chong96713fe2019-06-04 16:39:37 -07009169
TatWai Chong302729c2019-06-14 16:18:51 -07009170 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -07009171 instr->GetSVEVectorFormat(),
9172 ReadPRegister(instr->GetPd()),
9173 ReadPRegister(instr->GetPgLow8()),
9174 ReadVRegister(instr->GetRn()),
9175 ReadVRegister(instr->GetRm()),
9176 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009177}
9178
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009179void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00009180 VectorFormat vform = instr->GetSVEVectorFormat();
9181 SimVRegister& zd = ReadVRegister(instr->GetRd());
9182 SimVRegister& zn = ReadVRegister(instr->GetRn());
9183
9184 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
9185 (vform == kFormatVnD));
9186
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009187 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009188 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +00009189 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009190 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009191 default:
9192 VIXL_UNIMPLEMENTED();
9193 break;
9194 }
9195}
9196
9197void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00009198 VectorFormat vform = instr->GetSVEVectorFormat();
9199 SimVRegister& zd = ReadVRegister(instr->GetRd());
9200 SimVRegister& zn = ReadVRegister(instr->GetRn());
9201 SimVRegister& zm = ReadVRegister(instr->GetRm());
9202
9203 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
9204 (vform == kFormatVnD));
9205
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009206 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009207 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +00009208 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009209 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009210 default:
9211 VIXL_UNIMPLEMENTED();
9212 break;
9213 }
9214}
9215
9216void Simulator::VisitSVEConstructivePrefix_Unpredicated(
9217 const Instruction* instr) {
9218 SimVRegister& zd = ReadVRegister(instr->GetRd());
9219 SimVRegister& zn = ReadVRegister(instr->GetRn());
9220
9221 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009222 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009223 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
9224 // Record the movprfx, so the next ExecuteInstruction() can check it.
9225 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009226 break;
9227 default:
9228 VIXL_UNIMPLEMENTED();
9229 break;
9230 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009231}
9232
9233void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +01009234 VectorFormat vform = instr->GetSVEVectorFormat();
9235
9236 SimVRegister& zd = ReadVRegister(instr->GetRd());
9237 SimVRegister& zm = ReadVRegister(instr->GetRm());
9238
9239 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009240 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009241 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01009242 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009243 break;
9244 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01009245 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009246 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01009247 case MAD_z_p_zzz:
9248 // 'za' is encoded in 'Rn'.
9249 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009250 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01009251 case MSB_z_p_zzz: {
9252 // 'za' is encoded in 'Rn'.
9253 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
9254 break;
9255 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009256 default:
9257 VIXL_UNIMPLEMENTED();
9258 break;
9259 }
Jacob Bramley22023df2019-05-14 17:55:43 +01009260 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009261}
9262
9263void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
TatWai Chong4d2a4e92019-10-23 16:19:32 -07009264 VectorFormat vform = instr->GetSVEVectorFormat();
9265 SimVRegister& zda = ReadVRegister(instr->GetRd());
9266 SimVRegister& zn = ReadVRegister(instr->GetRn());
9267 SimVRegister& zm = ReadVRegister(instr->GetRm());
9268
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009269 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
9270 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07009271 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009272 break;
9273 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07009274 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009275 break;
9276 default:
9277 VIXL_UNIMPLEMENTED();
9278 break;
9279 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009280}
9281
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009282void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009283 VectorFormat vform = instr->GetSVEVectorFormat();
9284 SimVRegister& zn = ReadVRegister(instr->GetRn());
9285 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9286 SimVRegister& zd = ReadVRegister(instr->GetRd());
9287
9288 switch (instr->Mask(SVEMovprfxMask)) {
9289 case MOVPRFX_z_p_z:
9290 if (instr->ExtractBit(16)) {
9291 mov_merging(vform, zd, pg, zn);
9292 } else {
9293 mov_zeroing(vform, zd, pg, zn);
9294 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009295
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009296 // Record the movprfx, so the next ExecuteInstruction() can check it.
9297 movprfx_ = instr;
9298 break;
9299 default:
9300 VIXL_UNIMPLEMENTED();
9301 break;
9302 }
9303}
9304
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009305void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009306 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +01009307 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009308 SimVRegister& zn = ReadVRegister(instr->GetRn());
9309 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9310
9311 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
9312 switch (instr->Mask(SVEIntReductionLogicalMask)) {
9313 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01009314 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009315 break;
9316 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01009317 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009318 break;
9319 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01009320 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009321 break;
9322 default:
9323 VIXL_UNIMPLEMENTED();
9324 break;
9325 }
9326 } else {
9327 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009328 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009329 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009330 break;
9331 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009332 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009333 break;
9334 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009335 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009336 break;
9337 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009338 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009339 break;
9340 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009341 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009342 break;
9343 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009344 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009345 break;
9346 default:
9347 VIXL_UNIMPLEMENTED();
9348 break;
9349 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009350 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009351}
9352
9353void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009354 VectorFormat vform = instr->GetSVEVectorFormat();
9355 SimVRegister& zn = ReadVRegister(instr->GetRn());
9356
9357 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009358 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
9359 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009360 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009361 break;
9362 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009363 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009364 break;
9365 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009366 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009367 break;
9368 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009369 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009370 break;
9371 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009372 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009373 break;
9374 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009375 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009376 break;
9377 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009378 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009379 break;
9380 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009381 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009382 break;
9383 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009384 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009385 break;
9386 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009387 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009388 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009389 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009390 break;
9391 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009392 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009393 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009394 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009395 break;
9396 default:
9397 VIXL_UNIMPLEMENTED();
9398 break;
9399 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009400
9401 SimVRegister& zd = ReadVRegister(instr->GetRd());
9402 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9403 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009404}
9405
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009406void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009407 // There is only one instruction in this group.
9408 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
9409
9410 VectorFormat vform = instr->GetSVEVectorFormat();
9411 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
9412 SimVRegister& zd = ReadVRegister(instr->GetRd());
9413
9414 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009415 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009416 case FCPY_z_p_i: {
9417 int imm8 = instr->ExtractBits(12, 5);
9418 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
9419 Instruction::Imm8ToFP64(imm8));
9420 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009421 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009422 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009423 default:
9424 VIXL_UNIMPLEMENTED();
9425 break;
9426 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009427 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009428}
9429
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009430void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
9431 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +01009432 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01009433 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +01009434 SimVRegister scratch;
9435
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009436 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
9437 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009438
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009439 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009440 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009441 add_uint(vform, zd, zd, imm);
9442 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009443 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009444 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
9445 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009446 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009447 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
9448 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009449 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009450 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +01009451 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009452 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009453 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009454 sub_uint(vform, zd, zd, imm);
9455 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009456 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009457 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9458 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009459 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009460 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9461 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009462 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009463 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009464 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009465}
TatWai Chong6995bfd2019-09-26 10:48:05 +01009466
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009467void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
9468 SimVRegister& zd = ReadVRegister(instr->GetRd());
9469
Martyn Capewell8ed83522020-08-11 16:19:43 +01009470 VectorFormat format = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009471 int64_t imm = instr->GetImmSVEIntWideSigned();
Martyn Capewell8ed83522020-08-11 16:19:43 +01009472 int shift = instr->ExtractBit(13) * 8;
9473 imm *= 1 << shift;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009474
9475 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
9476 case DUP_z_i:
Martyn Capewell8ed83522020-08-11 16:19:43 +01009477 // The encoding of byte-sized lanes with lsl #8 is undefined.
9478 if ((format == kFormatVnB) && (shift == 8)) {
9479 VIXL_UNIMPLEMENTED();
9480 } else {
9481 dup_immediate(format, zd, imm);
9482 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009483 break;
9484 default:
9485 VIXL_UNIMPLEMENTED();
9486 break;
9487 }
9488}
9489
9490void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
9491 VectorFormat vform = instr->GetSVEVectorFormat();
9492 SimVRegister& zd = ReadVRegister(instr->GetRd());
9493
9494 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009495 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +01009496 switch (vform) {
9497 case kFormatVnH:
9498 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
9499 break;
9500 case kFormatVnS:
9501 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
9502 break;
9503 case kFormatVnD:
9504 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
9505 break;
9506 default:
9507 VIXL_UNIMPLEMENTED();
9508 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009509 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009510 default:
9511 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009512 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009513 }
9514}
9515
9516void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
9517 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009518 switch (instr->Mask(
9519 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
9520 case LD1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009521 case LD1SH_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009522 case LDFF1H_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009523 case LDFF1SH_z_p_bz_s_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009524 break;
9525 default:
9526 VIXL_UNIMPLEMENTED();
9527 break;
9528 }
TatWai Chong113d9192020-05-19 01:02:36 -07009529
TatWai Chongcd3f6c52020-06-14 00:42:39 -07009530 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9531 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009532}
9533
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009534void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009535 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009536 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
9537 case LD1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009538 case LD1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009539 case LD1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009540 case LD1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009541 case LD1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009542 case LDFF1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009543 case LDFF1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009544 case LDFF1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009545 case LDFF1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009546 case LDFF1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009547 break;
9548 default:
9549 VIXL_UNIMPLEMENTED();
9550 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009551 }
TatWai Chong113d9192020-05-19 01:02:36 -07009552
TatWai Chongcd3f6c52020-06-14 00:42:39 -07009553 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9554 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009555}
9556
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009557void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
9558 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009559 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
9560 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009561 VIXL_UNIMPLEMENTED();
9562 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009563 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009564 VIXL_UNIMPLEMENTED();
9565 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009566 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009567 VIXL_UNIMPLEMENTED();
9568 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009569 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009570 VIXL_UNIMPLEMENTED();
9571 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009572 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009573 VIXL_UNIMPLEMENTED();
9574 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009575 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009576 VIXL_UNIMPLEMENTED();
9577 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009578 case LDFF1H_z_p_ai_s:
9579 VIXL_UNIMPLEMENTED();
9580 break;
9581 case LDFF1SB_z_p_ai_s:
9582 VIXL_UNIMPLEMENTED();
9583 break;
9584 case LDFF1SH_z_p_ai_s:
9585 VIXL_UNIMPLEMENTED();
9586 break;
9587 case LDFF1W_z_p_ai_s:
9588 VIXL_UNIMPLEMENTED();
9589 break;
9590 default:
9591 VIXL_UNIMPLEMENTED();
9592 break;
9593 }
9594}
9595
9596void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
9597 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009598 switch (
9599 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
9600 case LD1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009601 case LDFF1W_z_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009602 break;
9603 default:
9604 VIXL_UNIMPLEMENTED();
9605 break;
9606 }
TatWai Chong113d9192020-05-19 01:02:36 -07009607
TatWai Chongcd3f6c52020-06-14 00:42:39 -07009608 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9609 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009610}
9611
9612void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
9613 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009614 switch (
9615 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -07009616 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009617 case PRFB_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009618 case PRFD_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009619 case PRFH_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009620 case PRFW_i_p_bz_s_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009621 break;
9622 default:
9623 VIXL_UNIMPLEMENTED();
9624 break;
9625 }
9626}
9627
9628void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
9629 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009630 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -07009631 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009632 case PRFB_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009633 case PRFD_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009634 case PRFH_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009635 case PRFW_i_p_ai_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009636 break;
9637 default:
9638 VIXL_UNIMPLEMENTED();
9639 break;
9640 }
9641}
9642
9643void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
9644 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009645 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -07009646 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009647 case PRFB_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009648 case PRFD_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009649 case PRFH_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009650 case PRFW_i_p_bi_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009651 break;
9652 default:
9653 VIXL_UNIMPLEMENTED();
9654 break;
9655 }
9656}
9657
9658void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
9659 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009660 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -07009661 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009662 case PRFB_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009663 case PRFD_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009664 case PRFH_i_p_br_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009665 case PRFW_i_p_br_s:
Martyn Capewellecca4b12020-07-02 14:30:50 +01009666 if (instr->GetRm() == kZeroRegCode) {
9667 VIXL_UNIMPLEMENTED();
9668 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009669 break;
9670 default:
9671 VIXL_UNIMPLEMENTED();
9672 break;
9673 }
9674}
9675
9676void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
TatWai Chong85e15102020-05-04 21:00:40 -07009677 bool is_signed;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009678 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009679 case LD1RB_z_p_bi_u8:
TatWai Chong85e15102020-05-04 21:00:40 -07009680 case LD1RB_z_p_bi_u16:
9681 case LD1RB_z_p_bi_u32:
9682 case LD1RB_z_p_bi_u64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009683 case LD1RH_z_p_bi_u16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009684 case LD1RH_z_p_bi_u32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009685 case LD1RH_z_p_bi_u64:
TatWai Chong85e15102020-05-04 21:00:40 -07009686 case LD1RW_z_p_bi_u32:
9687 case LD1RW_z_p_bi_u64:
9688 case LD1RD_z_p_bi_u64:
9689 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009690 break;
9691 case LD1RSB_z_p_bi_s16:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009692 case LD1RSB_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009693 case LD1RSB_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009694 case LD1RSH_z_p_bi_s32:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009695 case LD1RSH_z_p_bi_s64:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009696 case LD1RSW_z_p_bi_s64:
TatWai Chong85e15102020-05-04 21:00:40 -07009697 is_signed = true;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009698 break;
9699 default:
TatWai Chong85e15102020-05-04 21:00:40 -07009700 // This encoding group is complete, so no other values should be possible.
9701 VIXL_UNREACHABLE();
9702 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009703 break;
9704 }
TatWai Chong85e15102020-05-04 21:00:40 -07009705
9706 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
9707 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
9708 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
9709 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
9710 uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
9711 uint64_t base = ReadXRegister(instr->GetRn()) + offset;
9712 VectorFormat unpack_vform =
9713 SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
9714 SimVRegister temp;
9715 ld1r(vform, unpack_vform, temp, base, is_signed);
9716 mov_zeroing(vform,
9717 ReadVRegister(instr->GetRt()),
9718 ReadPRegister(instr->GetPgLow8()),
9719 temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009720}
9721
9722void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
9723 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
9724 case LDR_p_bi: {
9725 SimPRegister& pt = ReadPRegister(instr->GetPt());
9726 int pl = GetPredicateLengthInBytes();
9727 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9728 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9729 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
9730 for (int i = 0; i < pl; i++) {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00009731 pt.Insert(i, MemRead<uint8_t>(address + i));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009732 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009733 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009734 break;
9735 }
9736 default:
9737 VIXL_UNIMPLEMENTED();
9738 break;
9739 }
9740}
9741
9742void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009743 switch (instr->Mask(SVELoadVectorRegisterMask)) {
9744 case LDR_z_bi: {
9745 SimVRegister& zt = ReadVRegister(instr->GetRt());
9746 int vl = GetVectorLengthInBytes();
9747 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9748 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9749 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
9750 for (int i = 0; i < vl; i++) {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +00009751 zt.Insert(i, MemRead<uint8_t>(address + i));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009752 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009753 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009754 break;
9755 }
9756 default:
9757 VIXL_UNIMPLEMENTED();
9758 break;
9759 }
9760}
9761
9762void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
9763 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009764 switch (instr->Mask(
9765 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009766 case LD1D_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009767 case LD1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009768 case LD1SH_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009769 case LD1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009770 case LD1W_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009771 case LDFF1H_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009772 case LDFF1W_z_p_bz_d_x32_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -07009773 case LDFF1D_z_p_bz_d_x32_scaled:
9774 case LDFF1SH_z_p_bz_d_x32_scaled:
9775 case LDFF1SW_z_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009776 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009777 default:
9778 VIXL_UNIMPLEMENTED();
9779 break;
9780 }
TatWai Chong1af34f12020-06-01 20:54:06 -07009781
TatWai Chongcd3f6c52020-06-14 00:42:39 -07009782 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9783 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009784}
9785
9786void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
9787 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009788 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
9789 case LD1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009790 case LD1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009791 case LD1SH_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009792 case LD1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009793 case LD1W_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009794 case LDFF1H_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009795 case LDFF1W_z_p_bz_d_64_scaled:
TatWai Chong1af34f12020-06-01 20:54:06 -07009796 case LDFF1D_z_p_bz_d_64_scaled:
9797 case LDFF1SH_z_p_bz_d_64_scaled:
9798 case LDFF1SW_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009799 break;
9800 default:
9801 VIXL_UNIMPLEMENTED();
9802 break;
9803 }
TatWai Chong1af34f12020-06-01 20:54:06 -07009804
TatWai Chongcd3f6c52020-06-14 00:42:39 -07009805 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009806}
9807
9808void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
9809 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009810 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
9811 case LD1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009812 case LD1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009813 case LD1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009814 case LD1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009815 case LD1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009816 case LD1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009817 case LD1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009818 case LDFF1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009819 case LDFF1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009820 case LDFF1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009821 case LDFF1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009822 case LDFF1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009823 case LDFF1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009824 case LDFF1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009825 break;
9826 default:
9827 VIXL_UNIMPLEMENTED();
9828 break;
9829 }
TatWai Chong113d9192020-05-19 01:02:36 -07009830
TatWai Chongcd3f6c52020-06-14 00:42:39 -07009831 SVEGatherLoadScalarPlusVectorHelper(instr,
9832 kFormatVnD,
9833 NO_SVE_OFFSET_MODIFIER);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009834}
9835
9836void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
9837 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009838 switch (instr->Mask(
9839 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9840 case LD1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009841 case LD1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009842 case LD1H_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009843 case LD1SB_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009844 case LD1SH_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009845 case LD1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009846 case LD1W_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009847 case LDFF1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009848 case LDFF1H_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009849 case LDFF1W_z_p_bz_d_x32_unscaled:
TatWai Chong1af34f12020-06-01 20:54:06 -07009850 case LDFF1D_z_p_bz_d_x32_unscaled:
9851 case LDFF1SB_z_p_bz_d_x32_unscaled:
9852 case LDFF1SH_z_p_bz_d_x32_unscaled:
9853 case LDFF1SW_z_p_bz_d_x32_unscaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009854 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009855 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009856 VIXL_UNIMPLEMENTED();
9857 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009858 }
TatWai Chong1af34f12020-06-01 20:54:06 -07009859
TatWai Chongcd3f6c52020-06-14 00:42:39 -07009860 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9861 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009862}
9863
9864void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
9865 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009866 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
9867 case LD1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009868 case LD1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009869 case LD1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009870 case LD1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009871 case LD1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009872 case LD1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009873 case LD1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009874 case LDFF1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009875 case LDFF1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009876 case LDFF1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009877 case LDFF1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009878 case LDFF1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009879 case LDFF1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009880 case LDFF1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009881 break;
9882 default:
9883 VIXL_UNIMPLEMENTED();
9884 break;
9885 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +00009886 bool is_signed = instr->ExtractBit(14) == 0;
9887 bool is_ff = instr->ExtractBit(13) == 1;
9888 // Note that these instructions don't use the Dtype encoding.
9889 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
9890 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
9891 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
9892 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9893 if (is_ff) {
9894 VIXL_UNIMPLEMENTED();
9895 } else {
9896 SVEStructuredLoadHelper(kFormatVnD,
9897 ReadPRegister(instr->GetPgLow8()),
9898 instr->GetRt(),
9899 addr,
9900 is_signed);
9901 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009902}
9903
9904void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
9905 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009906 switch (
9907 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -07009908 // Ignore prefetch hint instructions.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009909 case PRFB_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009910 case PRFD_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009911 case PRFH_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009912 case PRFW_i_p_bz_d_64_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009913 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009914 default:
9915 VIXL_UNIMPLEMENTED();
9916 break;
9917 }
9918}
9919
9920void Simulator::
9921 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
9922 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009923 switch (instr->Mask(
9924 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -07009925 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009926 case PRFB_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009927 case PRFD_i_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009928 case PRFH_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009929 case PRFW_i_p_bz_d_x32_scaled:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009930 break;
9931 default:
9932 VIXL_UNIMPLEMENTED();
9933 break;
9934 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009935}
9936
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009937void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
9938 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009939 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
TatWai Chong3db2c492020-03-29 22:20:41 -07009940 // Ignore prefetch hint instructions.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009941 case PRFB_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009942 case PRFD_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009943 case PRFH_i_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009944 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009945 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009946 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009947 VIXL_UNIMPLEMENTED();
9948 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009949 }
9950}
9951
9952void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
9953 const Instruction* instr) {
Jacob Bramley85a9c102019-12-09 17:48:29 +00009954 bool is_signed;
Jacob Bramley85a9c102019-12-09 17:48:29 +00009955 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009956 case LDFF1B_z_p_br_u8:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009957 case LDFF1B_z_p_br_u16:
9958 case LDFF1B_z_p_br_u32:
9959 case LDFF1B_z_p_br_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009960 case LDFF1H_z_p_br_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009961 case LDFF1H_z_p_br_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009962 case LDFF1H_z_p_br_u64:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009963 case LDFF1W_z_p_br_u32:
9964 case LDFF1W_z_p_br_u64:
9965 case LDFF1D_z_p_br_u64:
9966 is_signed = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009967 break;
9968 case LDFF1SB_z_p_br_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009969 case LDFF1SB_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009970 case LDFF1SB_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009971 case LDFF1SH_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009972 case LDFF1SH_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009973 case LDFF1SW_z_p_br_s64:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009974 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009975 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009976 default:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009977 // This encoding group is complete, so no other values should be possible.
9978 VIXL_UNREACHABLE();
9979 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009980 break;
9981 }
Jacob Bramley85a9c102019-12-09 17:48:29 +00009982
9983 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
9984 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
9985 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
9986 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
9987 uint64_t offset = ReadXRegister(instr->GetRm());
9988 offset <<= msize_in_bytes_log2;
9989 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
9990 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9991 SVEFaultTolerantLoadHelper(vform,
9992 ReadPRegister(instr->GetPgLow8()),
9993 instr->GetRt(),
9994 addr,
9995 kSVEFirstFaultLoad,
9996 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009997}
9998
9999void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
10000 const Instruction* instr) {
Martyn Capewell5f9b3802020-03-24 16:16:36 +000010001 bool is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010002 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010003 case LDNF1B_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010004 case LDNF1B_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010005 case LDNF1B_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010006 case LDNF1B_z_p_bi_u8:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010007 case LDNF1D_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010008 case LDNF1H_z_p_bi_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010009 case LDNF1H_z_p_bi_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010010 case LDNF1H_z_p_bi_u64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000010011 case LDNF1W_z_p_bi_u32:
10012 case LDNF1W_z_p_bi_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010013 break;
10014 case LDNF1SB_z_p_bi_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010015 case LDNF1SB_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010016 case LDNF1SB_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010017 case LDNF1SH_z_p_bi_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010018 case LDNF1SH_z_p_bi_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010019 case LDNF1SW_z_p_bi_s64:
Martyn Capewell5f9b3802020-03-24 16:16:36 +000010020 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010021 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010022 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010023 VIXL_UNIMPLEMENTED();
10024 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010025 }
Martyn Capewell5f9b3802020-03-24 16:16:36 +000010026 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
10027 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
10028 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
10029 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
10030 int vl = GetVectorLengthInBytes();
10031 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10032 uint64_t offset =
10033 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
10034 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10035 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10036 SVEFaultTolerantLoadHelper(vform,
10037 ReadPRegister(instr->GetPgLow8()),
10038 instr->GetRt(),
10039 addr,
10040 kSVENonFaultLoad,
10041 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010042}
10043
10044void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
10045 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000010046 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10047 VectorFormat vform = kFormatUndefined;
10048
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010049 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
10050 case LDNT1B_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010051 vform = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010052 break;
10053 case LDNT1D_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010054 vform = kFormatVnD;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010055 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010056 case LDNT1H_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010057 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010058 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010059 case LDNT1W_z_p_bi_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010060 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010061 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010062 default:
10063 VIXL_UNIMPLEMENTED();
10064 break;
10065 }
Martyn Capewell72765d12020-03-23 14:25:53 +000010066 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10067 int vl = GetVectorLengthInBytes();
10068 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
10069 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10070 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10071 SVEStructuredLoadHelper(vform,
10072 pg,
10073 instr->GetRt(),
10074 addr,
10075 /* is_signed = */ false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010076}
10077
10078void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
10079 const Instruction* instr) {
Martyn Capewell72765d12020-03-23 14:25:53 +000010080 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10081 VectorFormat vform = kFormatUndefined;
10082
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010083 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
10084 case LDNT1B_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010085 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010086 break;
10087 case LDNT1D_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010088 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010089 break;
10090 case LDNT1H_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010091 vform = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010092 break;
10093 case LDNT1W_z_p_br_contiguous:
Martyn Capewell72765d12020-03-23 14:25:53 +000010094 vform = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010095 break;
10096 default:
10097 VIXL_UNIMPLEMENTED();
10098 break;
10099 }
Martyn Capewell72765d12020-03-23 14:25:53 +000010100 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10101 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
10102 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10103 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10104 SVEStructuredLoadHelper(vform,
10105 pg,
10106 instr->GetRt(),
10107 addr,
10108 /* is_signed = */ false);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010109}
10110
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010111void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
10112 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010113 SimVRegister& zt = ReadVRegister(instr->GetRt());
10114 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10115
10116 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
10117 uint64_t offset = instr->ExtractSignedBits(19, 16) * 16;
10118
10119 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010120 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
10121 case LD1RQB_z_p_bi_u8:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010122 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010123 break;
10124 case LD1RQD_z_p_bi_u64:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010125 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010126 break;
10127 case LD1RQH_z_p_bi_u16:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010128 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010129 break;
10130 case LD1RQW_z_p_bi_u32:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010131 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010132 break;
10133 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010134 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010135 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010136 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010137 ld1(kFormat16B, zt, addr + offset);
10138 mov_zeroing(vform, zt, pg, zt);
10139 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010140}
10141
10142void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
10143 const Instruction* instr) {
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010144 SimVRegister& zt = ReadVRegister(instr->GetRt());
10145 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10146
10147 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
10148 uint64_t offset = ReadXRegister(instr->GetRm());
10149
10150 VectorFormat vform = kFormatUndefined;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010151 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
10152 case LD1RQB_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010153 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010154 break;
10155 case LD1RQD_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010156 vform = kFormatVnD;
10157 offset <<= 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010158 break;
10159 case LD1RQH_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010160 vform = kFormatVnH;
10161 offset <<= 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010162 break;
10163 case LD1RQW_z_p_br_contiguous:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010164 vform = kFormatVnS;
10165 offset <<= 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010166 break;
10167 default:
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010168 addr = offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010169 break;
10170 }
Martyn Capewell452ad8b2020-03-19 15:49:57 +000010171 ld1(kFormat16B, zt, addr + offset);
10172 mov_zeroing(vform, zt, pg, zt);
10173 dup_element(kFormatVnQ, zt, zt, 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010174}
10175
10176void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
10177 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010178 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
10179 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010180 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010181 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010182 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010183 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010184 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010185 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010186 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010187 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010188 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010189 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000010190 case LD4W_z_p_bi_contiguous: {
10191 int vl = GetVectorLengthInBytes();
10192 int msz = instr->ExtractBits(24, 23);
10193 int reg_count = instr->ExtractBits(22, 21) + 1;
10194 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10195 LogicSVEAddressVector addr(
10196 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10197 addr.SetMsizeInBytesLog2(msz);
10198 addr.SetRegCount(reg_count);
10199 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10200 ReadPRegister(instr->GetPgLow8()),
10201 instr->GetRt(),
10202 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010203 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000010204 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010205 default:
10206 VIXL_UNIMPLEMENTED();
10207 break;
10208 }
10209}
10210
10211void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
10212 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010213 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
10214 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010215 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010216 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010217 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010218 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010219 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010220 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010221 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010222 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010223 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010224 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000010225 case LD4W_z_p_br_contiguous: {
10226 int msz = instr->ExtractBits(24, 23);
10227 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10228 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10229 LogicSVEAddressVector addr(
10230 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10231 addr.SetMsizeInBytesLog2(msz);
10232 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10233 SVEStructuredLoadHelper(vform,
10234 ReadPRegister(instr->GetPgLow8()),
10235 instr->GetRt(),
10236 addr,
10237 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010238 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000010239 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010240 default:
10241 VIXL_UNIMPLEMENTED();
10242 break;
10243 }
10244}
10245
10246void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
10247 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010248 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
10249 case ST1H_z_p_bz_s_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070010250 case ST1W_z_p_bz_s_x32_scaled: {
10251 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10252 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10253 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
10254 uint64_t base = ReadXRegister(instr->GetRn());
10255 SVEOffsetModifier mod =
10256 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10257 LogicSVEAddressVector addr(base,
10258 &ReadVRegister(instr->GetRm()),
10259 kFormatVnS,
10260 mod,
10261 scale);
10262 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10263 SVEStructuredStoreHelper(kFormatVnS,
10264 ReadPRegister(instr->GetPgLow8()),
10265 instr->GetRt(),
10266 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010267 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070010268 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010269 default:
10270 VIXL_UNIMPLEMENTED();
10271 break;
10272 }
10273}
10274
10275void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
10276 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010277 switch (
10278 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
10279 case ST1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010280 case ST1H_z_p_bz_s_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070010281 case ST1W_z_p_bz_s_x32_unscaled: {
10282 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10283 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10284 uint64_t base = ReadXRegister(instr->GetRn());
10285 SVEOffsetModifier mod =
10286 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10287 LogicSVEAddressVector addr(base,
10288 &ReadVRegister(instr->GetRm()),
10289 kFormatVnS,
10290 mod);
10291 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10292 SVEStructuredStoreHelper(kFormatVnS,
10293 ReadPRegister(instr->GetPgLow8()),
10294 instr->GetRt(),
10295 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010296 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070010297 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010298 default:
10299 VIXL_UNIMPLEMENTED();
10300 break;
10301 }
10302}
10303
10304void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
10305 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010010306 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010307 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
10308 case ST1B_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010010309 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010310 break;
10311 case ST1H_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010010312 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010313 break;
10314 case ST1W_z_p_ai_s:
Martyn Capewellb56cf222020-05-05 17:38:28 +010010315 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010316 break;
10317 default:
10318 VIXL_UNIMPLEMENTED();
10319 break;
10320 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010010321 uint64_t imm = instr->ExtractBits(20, 16) << msz;
10322 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
10323 addr.SetMsizeInBytesLog2(msz);
10324 SVEStructuredStoreHelper(kFormatVnS,
10325 ReadPRegister(instr->GetPgLow8()),
10326 instr->GetRt(),
10327 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010328}
10329
10330void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
10331 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010332 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
10333 case ST1D_z_p_bz_d_64_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010334 case ST1H_z_p_bz_d_64_scaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010010335 case ST1W_z_p_bz_d_64_scaled: {
10336 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10337 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10338 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
10339 uint64_t base = ReadXRegister(instr->GetRn());
10340 LogicSVEAddressVector addr(base,
10341 &ReadVRegister(instr->GetRm()),
10342 kFormatVnD,
10343 SVE_LSL,
10344 scale);
10345 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10346 SVEStructuredStoreHelper(kFormatVnD,
10347 ReadPRegister(instr->GetPgLow8()),
10348 instr->GetRt(),
10349 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010350 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010010351 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010352 default:
10353 VIXL_UNIMPLEMENTED();
10354 break;
10355 }
10356}
10357
10358void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
10359 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010360 switch (
10361 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
10362 case ST1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010363 case ST1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010364 case ST1H_z_p_bz_d_64_unscaled:
Martyn Capewellfa098bc2020-05-12 10:21:56 +010010365 case ST1W_z_p_bz_d_64_unscaled: {
10366 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10367 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010010368 uint64_t base = ReadXRegister(instr->GetRn());
10369 LogicSVEAddressVector addr(base,
10370 &ReadVRegister(instr->GetRm()),
10371 kFormatVnD,
TatWai Chong5f3928c2020-06-11 00:09:20 -070010372 NO_SVE_OFFSET_MODIFIER);
Martyn Capewellfa098bc2020-05-12 10:21:56 +010010373 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10374 SVEStructuredStoreHelper(kFormatVnD,
10375 ReadPRegister(instr->GetPgLow8()),
10376 instr->GetRt(),
10377 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010378 break;
Martyn Capewellfa098bc2020-05-12 10:21:56 +010010379 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010380 default:
10381 VIXL_UNIMPLEMENTED();
10382 break;
10383 }
10384}
10385
10386void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
10387 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010388 switch (instr->Mask(
10389 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
10390 case ST1D_z_p_bz_d_x32_scaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010391 case ST1H_z_p_bz_d_x32_scaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070010392 case ST1W_z_p_bz_d_x32_scaled: {
10393 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10394 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10395 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
10396 uint64_t base = ReadXRegister(instr->GetRn());
10397 SVEOffsetModifier mod =
10398 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10399 LogicSVEAddressVector addr(base,
10400 &ReadVRegister(instr->GetRm()),
10401 kFormatVnD,
10402 mod,
10403 scale);
10404 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10405 SVEStructuredStoreHelper(kFormatVnD,
10406 ReadPRegister(instr->GetPgLow8()),
10407 instr->GetRt(),
10408 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010409 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070010410 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010411 default:
10412 VIXL_UNIMPLEMENTED();
10413 break;
10414 }
10415}
10416
10417void Simulator::
10418 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
10419 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010420 switch (instr->Mask(
10421 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
10422 case ST1B_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010423 case ST1D_z_p_bz_d_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010424 case ST1H_z_p_bz_d_x32_unscaled:
TatWai Chong5f3928c2020-06-11 00:09:20 -070010425 case ST1W_z_p_bz_d_x32_unscaled: {
10426 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10427 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10428 uint64_t base = ReadXRegister(instr->GetRn());
10429 SVEOffsetModifier mod =
10430 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10431 LogicSVEAddressVector addr(base,
10432 &ReadVRegister(instr->GetRm()),
10433 kFormatVnD,
10434 mod);
10435 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10436 SVEStructuredStoreHelper(kFormatVnD,
10437 ReadPRegister(instr->GetPgLow8()),
10438 instr->GetRt(),
10439 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010440 break;
TatWai Chong5f3928c2020-06-11 00:09:20 -070010441 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010442 default:
10443 VIXL_UNIMPLEMENTED();
10444 break;
10445 }
10446}
10447
10448void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
10449 const Instruction* instr) {
Martyn Capewellb56cf222020-05-05 17:38:28 +010010450 int msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010451 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
10452 case ST1B_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010010453 msz = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010454 break;
10455 case ST1D_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010010456 msz = 3;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010457 break;
10458 case ST1H_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010010459 msz = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010460 break;
10461 case ST1W_z_p_ai_d:
Martyn Capewellb56cf222020-05-05 17:38:28 +010010462 msz = 2;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010463 break;
10464 default:
10465 VIXL_UNIMPLEMENTED();
10466 break;
10467 }
Martyn Capewellb56cf222020-05-05 17:38:28 +010010468 uint64_t imm = instr->ExtractBits(20, 16) << msz;
10469 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
10470 addr.SetMsizeInBytesLog2(msz);
10471 SVEStructuredStoreHelper(kFormatVnD,
10472 ReadPRegister(instr->GetPgLow8()),
10473 instr->GetRt(),
10474 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010475}
10476
10477void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
10478 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010479 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10480 VectorFormat vform = kFormatUndefined;
10481
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010482 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
10483 case STNT1B_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010484 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010485 break;
10486 case STNT1D_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010487 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010488 break;
10489 case STNT1H_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010490 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010491 break;
10492 case STNT1W_z_p_bi_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010493 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010494 break;
10495 default:
10496 VIXL_UNIMPLEMENTED();
10497 break;
10498 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010499 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10500 int vl = GetVectorLengthInBytes();
10501 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
10502 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10503 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10504 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010505}
10506
10507void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
10508 const Instruction* instr) {
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010509 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10510 VectorFormat vform = kFormatUndefined;
10511
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010512 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
10513 case STNT1B_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010514 vform = kFormatVnB;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010515 break;
10516 case STNT1D_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010517 vform = kFormatVnD;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010518 break;
10519 case STNT1H_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010520 vform = kFormatVnH;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010521 break;
10522 case STNT1W_z_p_br_contiguous:
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010523 vform = kFormatVnS;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010524 break;
10525 default:
10526 VIXL_UNIMPLEMENTED();
10527 break;
10528 }
Martyn Capewell3e2fb502020-03-24 12:04:07 +000010529 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10530 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
10531 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10532 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10533 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010534}
10535
10536void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
10537 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010538 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
10539 case ST1B_z_p_bi:
10540 case ST1D_z_p_bi:
10541 case ST1H_z_p_bi:
10542 case ST1W_z_p_bi: {
10543 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010544 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10545 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
10546 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10547 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10548 uint64_t offset =
10549 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010550 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010551 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010552 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010553 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10554 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010555 ReadPRegister(instr->GetPgLow8()),
10556 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010557 addr);
10558 break;
10559 }
10560 default:
10561 VIXL_UNIMPLEMENTED();
10562 break;
10563 }
10564}
10565
10566void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
10567 const Instruction* instr) {
10568 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
10569 case ST1B_z_p_br:
10570 case ST1D_z_p_br:
10571 case ST1H_z_p_br:
10572 case ST1W_z_p_br: {
10573 uint64_t offset = ReadXRegister(instr->GetRm());
10574 offset <<= instr->ExtractBits(24, 23);
10575 VectorFormat vform =
10576 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
10577 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010578 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
10579 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010580 ReadPRegister(instr->GetPgLow8()),
10581 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010582 addr);
10583 break;
10584 }
10585 default:
10586 VIXL_UNIMPLEMENTED();
10587 break;
10588 }
10589}
10590
10591void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
10592 const Instruction* instr) {
10593 VectorFormat vform = instr->GetSVEVectorFormat();
10594 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10595 SimVRegister z_result;
10596
10597 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
10598 case CPY_z_p_v:
10599 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
10600 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
10601 break;
10602 default:
10603 VIXL_UNIMPLEMENTED();
10604 break;
10605 }
10606}
10607
10608void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
10609 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010610 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
10611 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010612 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010613 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010614 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010615 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010616 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010617 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010618 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010619 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010620 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010621 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010622 case ST4W_z_p_bi_contiguous: {
10623 int vl = GetVectorLengthInBytes();
10624 int msz = instr->ExtractBits(24, 23);
10625 int reg_count = instr->ExtractBits(22, 21) + 1;
10626 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10627 LogicSVEAddressVector addr(
10628 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10629 addr.SetMsizeInBytesLog2(msz);
10630 addr.SetRegCount(reg_count);
10631 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10632 ReadPRegister(instr->GetPgLow8()),
10633 instr->GetRt(),
10634 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010635 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010636 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010637 default:
10638 VIXL_UNIMPLEMENTED();
10639 break;
10640 }
10641}
10642
10643void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
10644 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010645 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
10646 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010647 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010648 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010649 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010650 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010651 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010652 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010653 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010654 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010655 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010656 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010657 case ST4W_z_p_br_contiguous: {
10658 int msz = instr->ExtractBits(24, 23);
10659 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10660 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10661 LogicSVEAddressVector addr(
10662 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10663 addr.SetMsizeInBytesLog2(msz);
10664 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10665 SVEStructuredStoreHelper(vform,
10666 ReadPRegister(instr->GetPgLow8()),
10667 instr->GetRt(),
10668 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010669 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010670 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010671 default:
10672 VIXL_UNIMPLEMENTED();
10673 break;
10674 }
10675}
10676
10677void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
10678 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
10679 case STR_p_bi: {
10680 SimPRegister& pt = ReadPRegister(instr->GetPt());
10681 int pl = GetPredicateLengthInBytes();
10682 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10683 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10684 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
10685 for (int i = 0; i < pl; i++) {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +000010686 MemWrite(address + i, pt.GetLane<uint8_t>(i));
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010687 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010688 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010689 break;
10690 }
10691 default:
10692 VIXL_UNIMPLEMENTED();
10693 break;
10694 }
10695}
10696
10697void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
10698 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
10699 case STR_z_bi: {
10700 SimVRegister& zt = ReadVRegister(instr->GetRt());
10701 int vl = GetVectorLengthInBytes();
10702 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10703 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10704 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
10705 for (int i = 0; i < vl; i++) {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +000010706 MemWrite(address + i, zt.GetLane<uint8_t>(i));
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010707 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010708 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010709 break;
10710 }
10711 default:
10712 VIXL_UNIMPLEMENTED();
10713 break;
10714 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010715}
10716
10717void Simulator::VisitSVEMulIndex(const Instruction* instr) {
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070010718 VectorFormat vform = instr->GetSVEVectorFormat();
10719 SimVRegister& zda = ReadVRegister(instr->GetRd());
10720 SimVRegister& zn = ReadVRegister(instr->GetRn());
10721
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010722 switch (instr->Mask(SVEMulIndexMask)) {
10723 case SDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070010724 sdot(vform,
10725 zda,
10726 zn,
10727 ReadVRegister(instr->ExtractBits(19, 16)),
10728 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010729 break;
10730 case SDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070010731 sdot(vform,
10732 zda,
10733 zn,
10734 ReadVRegister(instr->ExtractBits(18, 16)),
10735 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010736 break;
10737 case UDOT_z_zzzi_d:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070010738 udot(vform,
10739 zda,
10740 zn,
10741 ReadVRegister(instr->ExtractBits(19, 16)),
10742 instr->ExtractBit(20));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010743 break;
10744 case UDOT_z_zzzi_s:
TatWai Chongfa3f6bf2020-03-13 00:22:03 -070010745 udot(vform,
10746 zda,
10747 zn,
10748 ReadVRegister(instr->ExtractBits(18, 16)),
10749 instr->ExtractBits(20, 19));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010750 break;
10751 default:
10752 VIXL_UNIMPLEMENTED();
10753 break;
10754 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010755}
10756
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010757void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010758 SimPRegister& pd = ReadPRegister(instr->GetPd());
10759 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10760 SimPRegister& pn = ReadPRegister(instr->GetPn());
10761 SimPRegister result;
10762
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010763 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010764 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010765 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010766 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010767 break;
10768 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010769 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010770 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010771 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010772 default:
10773 VIXL_UNIMPLEMENTED();
10774 break;
10775 }
TatWai Chong5d872292020-01-02 15:39:51 -080010776
10777 if (instr->ExtractBit(4) == 1) {
10778 mov_merging(pd, pg, result);
10779 } else {
10780 mov_zeroing(pd, pg, result);
10781 }
10782
10783 // Set flag if needed.
10784 if (instr->ExtractBit(22) == 1) {
10785 PredTest(kFormatVnB, pg, pd);
10786 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010787}
10788
10789void Simulator::VisitSVEPropagateBreakToNextPartition(
10790 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010791 SimPRegister& pdm = ReadPRegister(instr->GetPd());
10792 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10793 SimPRegister& pn = ReadPRegister(instr->GetPn());
10794
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010795 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010796 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010797 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080010798 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010799 break;
10800 default:
10801 VIXL_UNIMPLEMENTED();
10802 break;
10803 }
TatWai Chong5d872292020-01-02 15:39:51 -080010804
10805 // Set flag if needed.
10806 if (instr->ExtractBit(22) == 1) {
Jacob Bramleya3d61102020-07-01 16:49:47 +010010807 // Note that this ignores `pg`.
10808 PredTest(kFormatVnB, GetPTrue(), pdm);
TatWai Chong5d872292020-01-02 15:39:51 -080010809 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010810}
10811
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010812void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010813 SimPRegister& pd = ReadPRegister(instr->GetPd());
10814 SimPRegister& pn = ReadPRegister(instr->GetPn());
10815
10816 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10817 SimVRegister zero;
10818 dup_immediate(kFormatVnB, zero, 0);
10819
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010820 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010821 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010822 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010823 break;
10824 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010825 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010826 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010827 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010828 VIXL_UNIMPLEMENTED();
10829 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010830 }
TatWai Chong47c26842020-02-10 01:51:32 -080010831 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010832}
10833
10834void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010835 VectorFormat vform = instr->GetSVEVectorFormat();
10836 SimPRegister& pd = ReadPRegister(instr->GetPd());
10837 SimPRegister& pn = ReadPRegister(instr->GetPn());
10838 SimPRegister& pm = ReadPRegister(instr->GetPm());
10839
10840 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
10841 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
10842
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010843 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010844 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010845 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010846 break;
10847 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010848 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010849 break;
10850 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010851 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010852 break;
10853 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010854 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010855 break;
10856 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010857 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010858 break;
10859 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010860 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010861 break;
10862 default:
10863 VIXL_UNIMPLEMENTED();
10864 break;
10865 }
TatWai Chong47c26842020-02-10 01:51:32 -080010866 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010867}
10868
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010869void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010870 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010871 case REV_p_p: {
10872 VectorFormat vform = instr->GetSVEVectorFormat();
10873 SimPRegister& pn = ReadPRegister(instr->GetPn());
10874 SimPRegister& pd = ReadPRegister(instr->GetPd());
10875 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10876 rev(vform, temp, temp);
TatWai Chong47c26842020-02-10 01:51:32 -080010877 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010878 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010879 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010880 default:
10881 VIXL_UNIMPLEMENTED();
10882 break;
10883 }
10884}
10885
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010886void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
Martyn Capewellac07af12019-12-02 14:55:05 +000010887 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10888 // Second source register "Zm" is encoded where "Zn" would usually be.
10889 SimVRegister& zm = ReadVRegister(instr->GetRn());
10890
10891 const int imm8h_mask = 0x001F0000;
10892 const int imm8l_mask = 0x00001C00;
10893 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
10894 int vl = GetVectorLengthInBytes();
10895 index = (index >= vl) ? 0 : index;
10896
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010897 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
10898 case EXT_z_zi_des:
Martyn Capewellac07af12019-12-02 14:55:05 +000010899 ext(kFormatVnB, zdn, zdn, zm, index);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010900 break;
10901 default:
10902 VIXL_UNIMPLEMENTED();
10903 break;
10904 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010905}
10906
10907void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000010908 VectorFormat vform = instr->GetSVEVectorFormat();
10909 SimVRegister& zd = ReadVRegister(instr->GetRd());
10910 SimVRegister& zn = ReadVRegister(instr->GetRn());
10911 SimVRegister& zm = ReadVRegister(instr->GetRm());
10912
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010913 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
10914 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010915 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010916 break;
10917 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010918 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010919 break;
10920 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010921 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010922 break;
10923 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010924 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010925 break;
10926 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010927 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010928 break;
10929 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010930 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010931 break;
10932 default:
10933 VIXL_UNIMPLEMENTED();
10934 break;
10935 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010936}
10937
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010938void Simulator::VisitSVEConditionallyBroadcastElementToVector(
10939 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000010940 VectorFormat vform = instr->GetSVEVectorFormat();
10941 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10942 SimVRegister& zm = ReadVRegister(instr->GetRn());
10943 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10944
10945 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010946 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010947 case CLASTA_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000010948 active_offset = 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010949 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010950 case CLASTB_z_p_zz:
Martyn Capewellf804b602020-02-24 18:57:18 +000010951 active_offset = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010952 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010953 default:
10954 VIXL_UNIMPLEMENTED();
10955 break;
10956 }
Martyn Capewellf804b602020-02-24 18:57:18 +000010957
10958 if (active_offset >= 0) {
10959 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
10960 if (value.first) {
10961 dup_immediate(vform, zdn, value.second);
10962 } else {
10963 // Trigger a line of trace for the operation, even though it doesn't
10964 // change the register value.
10965 mov(vform, zdn, zdn);
10966 }
10967 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010968}
10969
10970void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
10971 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000010972 VectorFormat vform = instr->GetSVEVectorFormat();
10973 SimVRegister& vdn = ReadVRegister(instr->GetRd());
10974 SimVRegister& zm = ReadVRegister(instr->GetRn());
10975 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10976
10977 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010978 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
10979 case CLASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000010980 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010981 break;
10982 case CLASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000010983 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010984 break;
10985 default:
10986 VIXL_UNIMPLEMENTED();
10987 break;
10988 }
Martyn Capewellf804b602020-02-24 18:57:18 +000010989
10990 if (active_offset >= 0) {
10991 LogicVRegister dst(vdn);
10992 uint64_t src1_value = dst.Uint(vform, 0);
10993 std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
10994 dup_immediate(vform, vdn, 0);
10995 dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
10996 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010997}
10998
10999void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
11000 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000011001 VectorFormat vform = instr->GetSVEVectorFormat();
11002 SimVRegister& zm = ReadVRegister(instr->GetRn());
11003 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11004
11005 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011006 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
11007 case CLASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000011008 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011009 break;
11010 case CLASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000011011 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011012 break;
11013 default:
11014 VIXL_UNIMPLEMENTED();
11015 break;
11016 }
Martyn Capewellf804b602020-02-24 18:57:18 +000011017
11018 if (active_offset >= 0) {
11019 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
11020 uint64_t masked_src = ReadXRegister(instr->GetRd()) &
11021 GetUintMask(LaneSizeInBitsFromFormat(vform));
11022 WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
11023 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011024}
11025
11026void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
11027 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000011028 VectorFormat vform = instr->GetSVEVectorFormat();
11029 SimVRegister& vdn = ReadVRegister(instr->GetRd());
11030 SimVRegister& zm = ReadVRegister(instr->GetRn());
11031 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11032
11033 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011034 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
11035 case LASTA_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000011036 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011037 break;
11038 case LASTB_v_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000011039 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011040 break;
11041 default:
11042 VIXL_UNIMPLEMENTED();
11043 break;
11044 }
Martyn Capewellf804b602020-02-24 18:57:18 +000011045
11046 if (active_offset >= 0) {
11047 LogicVRegister dst(vdn);
11048 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
11049 dup_immediate(vform, vdn, 0);
11050 dst.SetUint(vform, 0, value.second);
11051 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011052}
11053
11054void Simulator::VisitSVEExtractElementToGeneralRegister(
11055 const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000011056 VectorFormat vform = instr->GetSVEVectorFormat();
11057 SimVRegister& zm = ReadVRegister(instr->GetRn());
11058 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11059
11060 int active_offset = -1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011061 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
11062 case LASTA_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000011063 active_offset = 1;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011064 break;
11065 case LASTB_r_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000011066 active_offset = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011067 break;
11068 default:
11069 VIXL_UNIMPLEMENTED();
11070 break;
11071 }
Martyn Capewellf804b602020-02-24 18:57:18 +000011072
11073 if (active_offset >= 0) {
11074 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
11075 WriteXRegister(instr->GetRd(), value.second);
11076 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011077}
11078
11079void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000011080 VectorFormat vform = instr->GetSVEVectorFormat();
11081 SimVRegister& zd = ReadVRegister(instr->GetRd());
11082 SimVRegister& zn = ReadVRegister(instr->GetRn());
11083 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11084
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011085 switch (instr->Mask(SVECompressActiveElementsMask)) {
11086 case COMPACT_z_p_z:
Martyn Capewellf804b602020-02-24 18:57:18 +000011087 compact(vform, zd, pg, zn);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011088 break;
11089 default:
11090 VIXL_UNIMPLEMENTED();
11091 break;
11092 }
11093}
11094
11095void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
11096 const Instruction* instr) {
11097 VectorFormat vform = instr->GetSVEVectorFormat();
11098 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11099 SimVRegister z_result;
11100
11101 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011102 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010011103 dup_immediate(vform,
11104 z_result,
11105 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
11106 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011107 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011108 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011109 VIXL_UNIMPLEMENTED();
11110 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011111 }
11112}
11113
11114void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011115 VectorFormat vform = instr->GetSVEVectorFormat();
11116 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11117 SimVRegister& zd = ReadVRegister(instr->GetRd());
11118
11119 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011120 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011121 case CPY_z_p_i: {
11122 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
11123 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
11124 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011125 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011126 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011127 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011128 VIXL_UNIMPLEMENTED();
11129 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011130 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010011131
11132 if (instr->ExtractBit(14) != 0) {
11133 mov_merging(vform, zd, pg, result);
11134 } else {
11135 mov_zeroing(vform, zd, pg, result);
11136 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011137}
11138
11139void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000011140 SimVRegister& zd = ReadVRegister(instr->GetRd());
11141 SimVRegister& zn = ReadVRegister(instr->GetRn());
11142 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11143 SimVRegister result;
11144
11145 // In NEON, the chunk size in which elements are REVersed is in the
11146 // instruction mnemonic, and the element size attached to the register.
11147 // SVE reverses the semantics; the mapping to logic functions below is to
11148 // account for this.
11149 VectorFormat chunk_form = instr->GetSVEVectorFormat();
11150 VectorFormat element_form = kFormatUndefined;
11151
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011152 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011153 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000011154 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011155 break;
11156 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000011157 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
11158 (chunk_form == kFormatVnD));
11159 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011160 break;
11161 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000011162 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
11163 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011164 break;
11165 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000011166 VIXL_ASSERT(chunk_form == kFormatVnD);
11167 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011168 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011169 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011170 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011171 break;
11172 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000011173
11174 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
11175 VIXL_ASSERT(element_form != kFormatUndefined);
11176 switch (chunk_form) {
11177 case kFormatVnH:
11178 rev16(element_form, result, zn);
11179 break;
11180 case kFormatVnS:
11181 rev32(element_form, result, zn);
11182 break;
11183 case kFormatVnD:
11184 rev64(element_form, result, zn);
11185 break;
11186 default:
11187 VIXL_UNIMPLEMENTED();
11188 }
11189 }
11190
11191 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011192}
11193
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011194void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellf804b602020-02-24 18:57:18 +000011195 VectorFormat vform = instr->GetSVEVectorFormat();
11196 SimVRegister& zdn = ReadVRegister(instr->GetRd());
11197 SimVRegister& zm = ReadVRegister(instr->GetRn());
11198 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11199
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011200 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
11201 case SPLICE_z_p_zz_des:
Martyn Capewellf804b602020-02-24 18:57:18 +000011202 splice(vform, zdn, pg, zdn, zm);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011203 break;
11204 default:
11205 VIXL_UNIMPLEMENTED();
11206 break;
11207 }
11208}
TatWai Chong4f28df72019-08-14 17:50:30 -070011209
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011210void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
11211 SimVRegister& zd = ReadVRegister(instr->GetRd());
11212 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
11213 case DUP_z_r:
11214 dup_immediate(instr->GetSVEVectorFormat(),
11215 zd,
11216 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
11217 break;
11218 default:
11219 VIXL_UNIMPLEMENTED();
11220 break;
11221 }
11222}
11223
11224void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
11225 SimVRegister& zd = ReadVRegister(instr->GetRd());
11226 VectorFormat vform = instr->GetSVEVectorFormat();
11227 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
11228 case INSR_z_v:
11229 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
11230 break;
11231 default:
11232 VIXL_UNIMPLEMENTED();
11233 break;
11234 }
11235}
11236
11237void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
11238 SimVRegister& zd = ReadVRegister(instr->GetRd());
11239 VectorFormat vform = instr->GetSVEVectorFormat();
11240 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
11241 case INSR_z_r:
11242 insr(vform, zd, ReadXRegister(instr->GetRn()));
11243 break;
11244 default:
11245 VIXL_UNIMPLEMENTED();
11246 break;
11247 }
11248}
11249
11250void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
11251 SimVRegister& zd = ReadVRegister(instr->GetRd());
11252 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070011253 case DUP_z_zi: {
11254 std::pair<int, int> index_and_lane_size =
11255 instr->GetSVEPermuteIndexAndLaneSizeLog2();
11256 int index = index_and_lane_size.first;
11257 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
11258 VectorFormat vform =
11259 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
11260 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
11261 // Out of bounds, set the destination register to zero.
11262 dup_immediate(kFormatVnD, zd, 0);
11263 } else {
11264 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
11265 }
11266 return;
11267 }
TatWai Chong4f28df72019-08-14 17:50:30 -070011268 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011269 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070011270 break;
11271 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011272}
TatWai Chong4f28df72019-08-14 17:50:30 -070011273
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011274void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
11275 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070011276 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011277 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011278 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070011279 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011280 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011281 default:
11282 VIXL_UNIMPLEMENTED();
11283 break;
11284 }
11285}
11286
11287void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
11288 SimVRegister& zd = ReadVRegister(instr->GetRd());
11289 VectorFormat vform = instr->GetSVEVectorFormat();
11290 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011291 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070011292 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011293 break;
11294 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070011295 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011296 break;
11297 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070011298 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011299 break;
11300 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070011301 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
11302 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011303 default:
11304 VIXL_UNIMPLEMENTED();
11305 break;
11306 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011307}
11308
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011309void Simulator::VisitSVETableLookup(const Instruction* instr) {
11310 SimVRegister& zd = ReadVRegister(instr->GetRd());
11311 switch (instr->Mask(SVETableLookupMask)) {
11312 case TBL_z_zz_1:
11313 Table(instr->GetSVEVectorFormat(),
11314 zd,
11315 ReadVRegister(instr->GetRn()),
11316 ReadVRegister(instr->GetRm()));
11317 return;
11318 default:
11319 break;
11320 }
11321}
11322
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011323void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010011324 VectorFormat vform = instr->GetSVEVectorFormat();
11325 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11326 SimPRegister& pn = ReadPRegister(instr->GetPn());
11327
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011328 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010011329 case CNTP_r_p_p: {
11330 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011331 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010011332 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011333 default:
11334 VIXL_UNIMPLEMENTED();
11335 break;
11336 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011337}
11338
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011339void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
11340 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080011341 SimPRegister& pd = ReadPRegister(instr->GetPd());
11342 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11343 SimPRegister& pn = ReadPRegister(instr->GetPn());
11344 SimPRegister& pm = ReadPRegister(instr->GetPm());
11345 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070011346 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011347 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011348 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011349 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011350 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011351 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011352 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011353 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011354 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011355 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011356 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011357 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011358 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011359 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011360 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070011361 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080011362 result,
11363 pn,
11364 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011365 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080011366 case SEL_p_p_pp:
11367 sel(pd, pg, pn, pm);
11368 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011369 default:
11370 VIXL_UNIMPLEMENTED();
11371 break;
11372 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080011373
11374 mov_zeroing(pd, pg, result);
11375 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
11376 PredTest(kFormatVnB, pg, pd);
11377 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011378}
11379
Jacob Bramley0ce75842019-07-17 18:12:50 +010011380void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010011381 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11382 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11383 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011384 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010011385 pfirst(pdn, pg, pdn);
11386 // TODO: Is this broken when pg == pdn?
11387 PredTest(kFormatVnB, pg, pdn);
11388 break;
11389 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011390 VIXL_UNIMPLEMENTED();
11391 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011392 }
11393}
11394
11395void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010011396 // This group only contains PTRUE{S}, and there are no unallocated encodings.
11397 VIXL_STATIC_ASSERT(
11398 SVEPredicateInitializeMask ==
11399 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
11400 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
11401 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
11402
11403 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11404 VectorFormat vform = instr->GetSVEVectorFormat();
11405
11406 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
11407 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
11408}
11409
11410void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010011411 // This group only contains PNEXT, and there are no unallocated encodings.
11412 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
11413 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
11414
11415 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11416 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11417 VectorFormat vform = instr->GetSVEVectorFormat();
11418
11419 pnext(vform, pdn, pg, pdn);
11420 // TODO: Is this broken when pg == pdn?
11421 PredTest(vform, pg, pdn);
11422}
11423
11424void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
11425 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080011426 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11427 LogicPRegister pg(ReadPRegister(instr->GetPn()));
11428 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011429 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
11430 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011431 // Do nothing.
11432 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011433 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011434 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011435 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011436 default:
11437 VIXL_UNIMPLEMENTED();
11438 break;
11439 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080011440
11441 LogicPRegister ffr(ReadFFR());
11442 mov_zeroing(pd, pg, ffr);
11443
11444 if (flags == SetFlags) {
11445 PredTest(kFormatVnB, pg, pd);
11446 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010011447}
11448
11449void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
11450 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011451 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11452 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010011453 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011454 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080011455 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011456 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011457 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011458 VIXL_UNIMPLEMENTED();
11459 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011460 }
11461}
11462
11463void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010011464 switch (instr->Mask(SVEPredicateTestMask)) {
11465 case PTEST_p_p:
11466 PredTest(kFormatVnB,
11467 ReadPRegister(instr->ExtractBits(13, 10)),
11468 ReadPRegister(instr->GetPn()));
11469 break;
11470 default:
11471 VIXL_UNIMPLEMENTED();
11472 break;
11473 }
11474}
11475
11476void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
Jacob Bramley0ce75842019-07-17 18:12:50 +010011477 switch (instr->Mask(SVEPredicateZeroMask)) {
11478 case PFALSE_p:
11479 pfalse(ReadPRegister(instr->GetPd()));
11480 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011481 default:
11482 VIXL_UNIMPLEMENTED();
11483 break;
11484 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011485}
11486
11487void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080011488 SimPRegister& pd = ReadPRegister(instr->GetPd());
11489 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11490 SimPRegister& pn = ReadPRegister(instr->GetPn());
11491 SimPRegister& pm = ReadPRegister(instr->GetPm());
11492
11493 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011494 switch (instr->Mask(SVEPropagateBreakMask)) {
11495 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011496 set_flags = true;
11497 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011498 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011499 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011500 break;
11501 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011502 set_flags = true;
11503 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011504 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011505 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011506 break;
11507 default:
11508 VIXL_UNIMPLEMENTED();
11509 break;
11510 }
TatWai Chong38303d92019-12-02 15:49:29 -080011511
11512 if (set_flags) {
11513 PredTest(kFormatVnB, pg, pd);
11514 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011515}
11516
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011517void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
11518 uint64_t length = 0;
11519 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
11520 case ADDPL_r_ri:
11521 length = GetPredicateLengthInBytes();
11522 break;
11523 case ADDVL_r_ri:
11524 length = GetVectorLengthInBytes();
11525 break;
11526 default:
11527 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011528 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011529 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011530 WriteXRegister(instr->GetRd(),
11531 base + (length * instr->GetImmSVEVLScale()),
11532 LogRegWrites,
11533 Reg31IsStackPointer);
11534}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011535
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011536void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
11537 int64_t scale = instr->GetImmSVEVLScale();
11538
11539 switch (instr->Mask(SVEStackFrameSizeMask)) {
11540 case RDVL_r_i:
11541 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
11542 break;
11543 default:
11544 VIXL_UNIMPLEMENTED();
11545 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011546}
11547
11548void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010011549 // The only instruction in this group is `sel`, and there are no unused
11550 // encodings.
11551 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
11552
11553 VectorFormat vform = instr->GetSVEVectorFormat();
11554 SimVRegister& zd = ReadVRegister(instr->GetRd());
11555 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11556 SimVRegister& zn = ReadVRegister(instr->GetRn());
11557 SimVRegister& zm = ReadVRegister(instr->GetRm());
11558
11559 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011560}
11561
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011562void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011563 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011564 case SETFFR_f: {
11565 LogicPRegister ffr(ReadFFR());
11566 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011567 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011568 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011569 default:
11570 VIXL_UNIMPLEMENTED();
11571 break;
11572 }
11573}
11574
11575void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011576 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011577 case WRFFR_f_p: {
11578 SimPRegister pn(ReadPRegister(instr->GetPn()));
11579 bool last_active = true;
11580 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
11581 bool active = pn.GetBit(i);
11582 if (active && !last_active) {
11583 // `pn` is non-monotonic. This is UNPREDICTABLE.
11584 VIXL_ABORT();
11585 }
11586 last_active = active;
11587 }
11588 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011589 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011590 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011591 default:
11592 VIXL_UNIMPLEMENTED();
11593 break;
11594 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011595}
Alexandre Ramesd3832962016-07-04 15:03:43 +010011596
TatWai Chong6205eb42019-09-24 10:07:20 +010011597void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
TatWai Chong6205eb42019-09-24 10:07:20 +010011598 bool is_signed;
11599 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
11600 case LD1B_z_p_bi_u8:
11601 case LD1B_z_p_bi_u16:
11602 case LD1B_z_p_bi_u32:
11603 case LD1B_z_p_bi_u64:
11604 case LD1H_z_p_bi_u16:
11605 case LD1H_z_p_bi_u32:
11606 case LD1H_z_p_bi_u64:
11607 case LD1W_z_p_bi_u32:
11608 case LD1W_z_p_bi_u64:
11609 case LD1D_z_p_bi_u64:
11610 is_signed = false;
11611 break;
11612 case LD1SB_z_p_bi_s16:
11613 case LD1SB_z_p_bi_s32:
11614 case LD1SB_z_p_bi_s64:
11615 case LD1SH_z_p_bi_s32:
11616 case LD1SH_z_p_bi_s64:
11617 case LD1SW_z_p_bi_s64:
11618 is_signed = true;
11619 break;
11620 default:
11621 // This encoding group is complete, so no other values should be possible.
11622 VIXL_UNREACHABLE();
11623 is_signed = false;
11624 break;
11625 }
11626
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011627 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010011628 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11629 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011630 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
11631 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
11632 uint64_t offset =
11633 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011634 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011635 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011636 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11637 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011638 ReadPRegister(instr->GetPgLow8()),
11639 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011640 addr,
11641 is_signed);
11642}
11643
11644void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
11645 const Instruction* instr) {
11646 bool is_signed;
TatWai Chong6205eb42019-09-24 10:07:20 +010011647 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
11648 case LD1B_z_p_br_u8:
11649 case LD1B_z_p_br_u16:
11650 case LD1B_z_p_br_u32:
11651 case LD1B_z_p_br_u64:
11652 case LD1H_z_p_br_u16:
11653 case LD1H_z_p_br_u32:
11654 case LD1H_z_p_br_u64:
11655 case LD1W_z_p_br_u32:
11656 case LD1W_z_p_br_u64:
11657 case LD1D_z_p_br_u64:
11658 is_signed = false;
11659 break;
11660 case LD1SB_z_p_br_s16:
11661 case LD1SB_z_p_br_s32:
11662 case LD1SB_z_p_br_s64:
11663 case LD1SH_z_p_br_s32:
11664 case LD1SH_z_p_br_s64:
11665 case LD1SW_z_p_br_s64:
11666 is_signed = true;
11667 break;
11668 default:
11669 // This encoding group is complete, so no other values should be possible.
11670 VIXL_UNREACHABLE();
11671 is_signed = false;
11672 break;
11673 }
11674
11675 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11676 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11677 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11678 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11679 uint64_t offset = ReadXRegister(instr->GetRm());
11680 offset <<= msize_in_bytes_log2;
11681 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011682 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11683 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011684 ReadPRegister(instr->GetPgLow8()),
11685 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011686 addr,
11687 is_signed);
11688}
11689
Alexandre Ramesd3832962016-07-04 15:03:43 +010011690void Simulator::DoUnreachable(const Instruction* instr) {
11691 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11692 (instr->GetImmException() == kUnreachableOpcode));
11693
11694 fprintf(stream_,
11695 "Hit UNREACHABLE marker at pc=%p.\n",
11696 reinterpret_cast<const void*>(instr));
11697 abort();
11698}
11699
11700
11701void Simulator::DoTrace(const Instruction* instr) {
11702 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11703 (instr->GetImmException() == kTraceOpcode));
11704
11705 // Read the arguments encoded inline in the instruction stream.
11706 uint32_t parameters;
11707 uint32_t command;
11708
11709 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11710 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11711 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
11712
11713 switch (command) {
11714 case TRACE_ENABLE:
11715 SetTraceParameters(GetTraceParameters() | parameters);
11716 break;
11717 case TRACE_DISABLE:
11718 SetTraceParameters(GetTraceParameters() & ~parameters);
11719 break;
11720 default:
11721 VIXL_UNREACHABLE();
11722 }
11723
11724 WritePc(instr->GetInstructionAtOffset(kTraceLength));
11725}
11726
11727
11728void Simulator::DoLog(const Instruction* instr) {
11729 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11730 (instr->GetImmException() == kLogOpcode));
11731
11732 // Read the arguments encoded inline in the instruction stream.
11733 uint32_t parameters;
11734
11735 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11736 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11737
11738 // We don't support a one-shot LOG_DISASM.
11739 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
11740 // Print the requested information.
11741 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
11742 if (parameters & LOG_REGS) PrintRegisters();
11743 if (parameters & LOG_VREGS) PrintVRegisters();
11744
11745 WritePc(instr->GetInstructionAtOffset(kLogLength));
11746}
11747
11748
11749void Simulator::DoPrintf(const Instruction* instr) {
11750 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11751 (instr->GetImmException() == kPrintfOpcode));
11752
11753 // Read the arguments encoded inline in the instruction stream.
11754 uint32_t arg_count;
11755 uint32_t arg_pattern_list;
11756 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11757 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
11758 memcpy(&arg_pattern_list,
11759 instr + kPrintfArgPatternListOffset,
11760 sizeof(arg_pattern_list));
11761
11762 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
11763 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
11764
11765 // We need to call the host printf function with a set of arguments defined by
11766 // arg_pattern_list. Because we don't know the types and sizes of the
11767 // arguments, this is very difficult to do in a robust and portable way. To
11768 // work around the problem, we pick apart the format string, and print one
11769 // format placeholder at a time.
11770
11771 // Allocate space for the format string. We take a copy, so we can modify it.
11772 // Leave enough space for one extra character per expected argument (plus the
11773 // '\0' termination).
11774 const char* format_base = ReadRegister<const char*>(0);
11775 VIXL_ASSERT(format_base != NULL);
11776 size_t length = strlen(format_base) + 1;
11777 char* const format = new char[length + arg_count];
11778
11779 // A list of chunks, each with exactly one format placeholder.
11780 const char* chunks[kPrintfMaxArgCount];
11781
11782 // Copy the format string and search for format placeholders.
11783 uint32_t placeholder_count = 0;
11784 char* format_scratch = format;
11785 for (size_t i = 0; i < length; i++) {
11786 if (format_base[i] != '%') {
11787 *format_scratch++ = format_base[i];
11788 } else {
11789 if (format_base[i + 1] == '%') {
11790 // Ignore explicit "%%" sequences.
11791 *format_scratch++ = format_base[i];
11792 i++;
11793 // Chunks after the first are passed as format strings to printf, so we
11794 // need to escape '%' characters in those chunks.
11795 if (placeholder_count > 0) *format_scratch++ = format_base[i];
11796 } else {
11797 VIXL_CHECK(placeholder_count < arg_count);
11798 // Insert '\0' before placeholders, and store their locations.
11799 *format_scratch++ = '\0';
11800 chunks[placeholder_count++] = format_scratch;
11801 *format_scratch++ = format_base[i];
11802 }
11803 }
11804 }
11805 VIXL_CHECK(placeholder_count == arg_count);
11806
11807 // Finally, call printf with each chunk, passing the appropriate register
11808 // argument. Normally, printf returns the number of bytes transmitted, so we
11809 // can emulate a single printf call by adding the result from each chunk. If
11810 // any call returns a negative (error) value, though, just return that value.
11811
11812 printf("%s", clr_printf);
11813
11814 // Because '\0' is inserted before each placeholder, the first string in
11815 // 'format' contains no format placeholders and should be printed literally.
11816 int result = printf("%s", format);
11817 int pcs_r = 1; // Start at x1. x0 holds the format string.
11818 int pcs_f = 0; // Start at d0.
11819 if (result >= 0) {
11820 for (uint32_t i = 0; i < placeholder_count; i++) {
11821 int part_result = -1;
11822
11823 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
11824 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
11825 switch (arg_pattern) {
11826 case kPrintfArgW:
11827 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
11828 break;
11829 case kPrintfArgX:
11830 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
11831 break;
11832 case kPrintfArgD:
11833 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
11834 break;
11835 default:
11836 VIXL_UNREACHABLE();
11837 }
11838
11839 if (part_result < 0) {
11840 // Handle error values.
11841 result = part_result;
11842 break;
11843 }
11844
11845 result += part_result;
11846 }
11847 }
11848
11849 printf("%s", clr_normal);
11850
11851 // Printf returns its result in x0 (just like the C library's printf).
11852 WriteXRegister(0, result);
11853
11854 // The printf parameters are inlined in the code, so skip them.
11855 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
11856
11857 // Set LR as if we'd just called a native printf function.
11858 WriteLr(ReadPc());
11859
11860 delete[] format;
11861}
11862
Alexandre Rames064e02d2016-07-12 11:53:13 +010011863
Alexandre Ramesca73ba02016-07-28 09:16:03 +010011864#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010011865void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011866 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011867 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
11868 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011869 uintptr_t call_wrapper_address =
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +000011870 MemRead<uintptr_t>(instr + kRuntimeCallWrapperOffset);
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011871 uintptr_t function_address =
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +000011872 MemRead<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080011873 RuntimeCallType call_type = static_cast<RuntimeCallType>(
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +000011874 MemRead<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011875 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010011876 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011877
11878 if (call_type == kCallRuntime) {
11879 WriteRegister(kLinkRegCode,
11880 instr->GetInstructionAtOffset(kRuntimeCallLength));
11881 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011882 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011883 // Read the return address from `lr` and write it into `pc`.
11884 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011885}
11886#else
11887void Simulator::DoRuntimeCall(const Instruction* instr) {
11888 USE(instr);
11889 VIXL_UNREACHABLE();
11890}
11891#endif
11892
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011893
11894void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
11895 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
11896
11897 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011898 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011899 std::numeric_limits<ElementType>::max());
11900
11901 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
11902
11903 size_t element_size = sizeof(ElementType);
11904 size_t offset = kConfigureCPUFeaturesListOffset;
11905
11906 // Read the kNone-terminated list of features.
11907 CPUFeatures parameters;
11908 while (true) {
Jacob Bramleyc4ef66e2020-10-30 18:25:43 +000011909 ElementType feature = MemRead<ElementType>(instr + offset);
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011910 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011911 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011912 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
11913 }
11914
11915 switch (instr->GetImmException()) {
11916 case kSetCPUFeaturesOpcode:
11917 SetCPUFeatures(parameters);
11918 break;
11919 case kEnableCPUFeaturesOpcode:
11920 GetCPUFeatures()->Combine(parameters);
11921 break;
11922 case kDisableCPUFeaturesOpcode:
11923 GetCPUFeatures()->Remove(parameters);
11924 break;
11925 default:
11926 VIXL_UNREACHABLE();
11927 break;
11928 }
11929
11930 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
11931}
11932
11933
11934void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
11935 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11936 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
11937 USE(instr);
11938
11939 saved_cpu_features_.push_back(*GetCPUFeatures());
11940}
11941
11942
11943void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
11944 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11945 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
11946 USE(instr);
11947
11948 SetCPUFeatures(saved_cpu_features_.back());
11949 saved_cpu_features_.pop_back();
11950}
11951
11952
Alexandre Ramesd3832962016-07-04 15:03:43 +010011953} // namespace aarch64
11954} // namespace vixl
11955
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010011956#endif // VIXL_INCLUDE_SIMULATOR_AARCH64