blob: 8879d026ce1774a88a5eac75d90b33d313733604 [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 Bramleyc44ce3d2018-06-12 15:39:09 +010070Simulator::Simulator(Decoder* decoder, FILE* stream)
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010071 : movprfx_(NULL), cpu_features_auditor_(decoder, CPUFeatures::All()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010072 // Ensure that shift operations act as the simulator expects.
73 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
74 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
75
Jacob Bramley85a9c102019-12-09 17:48:29 +000076 // Set up a dummy pipe for CanReadMemory.
77 VIXL_CHECK(pipe(dummy_pipe_fd_) == 0);
78
Alexandre Ramesd3832962016-07-04 15:03:43 +010079 instruction_stats_ = false;
80
81 // 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
106 // Allocate and set up the simulator stack.
107 stack_ = new byte[stack_size_];
108 stack_limit_ = stack_ + stack_protection_size_;
109 // Configure the starting stack pointer.
110 // - Find the top of the stack.
111 byte* tos = stack_ + stack_size_;
112 // - There's a protection region at both ends of the stack.
113 tos -= stack_protection_size_;
114 // - The stack pointer must be 16-byte aligned.
115 tos = AlignDown(tos, 16);
116 WriteSp(tos);
117
118 instrumentation_ = NULL;
119
120 // Print a warning about exclusive-access instructions, but only the first
121 // time they are encountered. This warning can be silenced using
122 // SilenceExclusiveAccessWarning().
123 print_exclusive_access_warning_ = true;
Martyn Capewellcb963f72018-10-22 15:25:28 +0100124
125 guard_pages_ = false;
TatWai Chong04edf682018-12-27 16:01:02 -0800126
127 // Initialize the common state of RNDR and RNDRRS.
128 uint16_t seed[3] = {11, 22, 33};
Jacob Bramley85a9c102019-12-09 17:48:29 +0000129 VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));
130 memcpy(rand_state_, seed, sizeof(rand_state_));
TatWai Chongb2d8d1f2019-10-21 15:19:31 -0700131
132 // Initialize all bits of pseudo predicate register to true.
133 LogicPRegister ones(pregister_all_true_);
134 ones.SetAllBits();
Alexandre Ramesd3832962016-07-04 15:03:43 +0100135}
136
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100137void Simulator::ResetSystemRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100138 // Reset the system registers.
139 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
140 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
TatWai Chong4023d7a2019-11-18 14:16:28 -0800141 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100142}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100143
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100144void Simulator::ResetRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100145 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
146 WriteXRegister(i, 0xbadbeef);
147 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100148 // Returning to address 0 exits the Simulator.
149 WriteLr(kEndOfSimAddress);
150}
Pierre Langlois23703a72016-08-15 17:23:39 +0100151
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100152void Simulator::ResetVRegisters() {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800153 // 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 +0100154 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
155 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
TatWai Chonge3d059b2019-02-27 15:04:51 -0800156 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100157 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100158 vregisters_[i].NotifyAccessAsZ();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100159 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800160 // Encode the register number and (D-sized) lane into each NaN, to
161 // make them easier to trace.
162 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
163 (0x0000000000000001 * lane);
164 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
165 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100166 vregisters_[i].Insert(lane, nan_bits);
TatWai Chonge3d059b2019-02-27 15:04:51 -0800167 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100168 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100169}
TatWai Chonge3d059b2019-02-27 15:04:51 -0800170
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100171void Simulator::ResetPRegisters() {
172 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
173 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
174 // Ensure the register configuration fits in this bit encoding.
175 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
176 VIXL_ASSERT(lane_count <= UINT8_MAX);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700177 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100178 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
179 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge0590cc2019-03-18 16:23:59 -0700180 // Encode the register number and (H-sized) lane into each lane slot.
181 uint16_t bits = (0x0100 * lane) | i;
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100182 pregisters_[i].Insert(lane, bits);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700183 }
184 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100185}
TatWai Chonge0590cc2019-03-18 16:23:59 -0700186
TatWai Chong4023d7a2019-11-18 14:16:28 -0800187void Simulator::ResetFFR() {
188 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
189 int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
190 ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
191}
192
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100193void Simulator::ResetState() {
194 ResetSystemRegisters();
195 ResetRegisters();
196 ResetVRegisters();
197 ResetPRegisters();
Martyn Capewellcb963f72018-10-22 15:25:28 +0100198
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100199 pc_ = NULL;
200 pc_modified_ = false;
201
202 // BTI state.
Martyn Capewellcb963f72018-10-22 15:25:28 +0100203 btype_ = DefaultBType;
204 next_btype_ = DefaultBType;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100205}
206
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100207void Simulator::SetVectorLengthInBits(unsigned vector_length) {
208 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
209 (vector_length <= kZRegMaxSize));
210 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
211 vector_length_ = vector_length;
212
213 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
214 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
215 }
216 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
217 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
218 }
219
TatWai Chong4023d7a2019-11-18 14:16:28 -0800220 ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
221
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100222 ResetVRegisters();
223 ResetPRegisters();
TatWai Chong4023d7a2019-11-18 14:16:28 -0800224 ResetFFR();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100225}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100226
227Simulator::~Simulator() {
228 delete[] stack_;
229 // The decoder may outlive the simulator.
230 decoder_->RemoveVisitor(print_disasm_);
231 delete print_disasm_;
232
233 decoder_->RemoveVisitor(instrumentation_);
234 delete instrumentation_;
Jacob Bramley85a9c102019-12-09 17:48:29 +0000235
236 close(dummy_pipe_fd_[0]);
237 close(dummy_pipe_fd_[1]);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100238}
239
240
241void Simulator::Run() {
242 // Flush any written registers before executing anything, so that
243 // manually-set registers are logged _before_ the first instruction.
244 LogAllWrittenRegisters();
245
246 while (pc_ != kEndOfSimAddress) {
247 ExecuteInstruction();
248 }
249}
250
251
252void Simulator::RunFrom(const Instruction* first) {
Jacob Bramleye79723a2016-06-07 17:50:47 +0100253 WritePc(first, NoBranchLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100254 Run();
255}
256
257
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100258// clang-format off
Alexandre Ramesd3832962016-07-04 15:03:43 +0100259const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
260 "x6", "x7", "x8", "x9", "x10", "x11",
261 "x12", "x13", "x14", "x15", "x16", "x17",
262 "x18", "x19", "x20", "x21", "x22", "x23",
263 "x24", "x25", "x26", "x27", "x28", "x29",
264 "lr", "xzr", "sp"};
265
266const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
267 "w6", "w7", "w8", "w9", "w10", "w11",
268 "w12", "w13", "w14", "w15", "w16", "w17",
269 "w18", "w19", "w20", "w21", "w22", "w23",
270 "w24", "w25", "w26", "w27", "w28", "w29",
271 "w30", "wzr", "wsp"};
272
Jacob Bramley423e5422019-11-13 19:15:55 +0000273const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",
274 "b6", "b7", "b8", "b9", "b10", "b11",
275 "b12", "b13", "b14", "b15", "b16", "b17",
276 "b18", "b19", "b20", "b21", "b22", "b23",
277 "b24", "b25", "b26", "b27", "b28", "b29",
278 "b30", "b31"};
279
Carey Williamsd8bb3572018-04-10 11:58:07 +0100280const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
281 "h6", "h7", "h8", "h9", "h10", "h11",
282 "h12", "h13", "h14", "h15", "h16", "h17",
283 "h18", "h19", "h20", "h21", "h22", "h23",
284 "h24", "h25", "h26", "h27", "h28", "h29",
285 "h30", "h31"};
286
Alexandre Ramesd3832962016-07-04 15:03:43 +0100287const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
288 "s6", "s7", "s8", "s9", "s10", "s11",
289 "s12", "s13", "s14", "s15", "s16", "s17",
290 "s18", "s19", "s20", "s21", "s22", "s23",
291 "s24", "s25", "s26", "s27", "s28", "s29",
292 "s30", "s31"};
293
294const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
295 "d6", "d7", "d8", "d9", "d10", "d11",
296 "d12", "d13", "d14", "d15", "d16", "d17",
297 "d18", "d19", "d20", "d21", "d22", "d23",
298 "d24", "d25", "d26", "d27", "d28", "d29",
299 "d30", "d31"};
300
301const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
302 "v6", "v7", "v8", "v9", "v10", "v11",
303 "v12", "v13", "v14", "v15", "v16", "v17",
304 "v18", "v19", "v20", "v21", "v22", "v23",
305 "v24", "v25", "v26", "v27", "v28", "v29",
306 "v30", "v31"};
307
TatWai Chong72d2e562019-05-16 11:22:22 -0700308const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
309 "z6", "z7", "z8", "z9", "z10", "z11",
310 "z12", "z13", "z14", "z15", "z16", "z17",
311 "z18", "z19", "z20", "z21", "z22", "z23",
312 "z24", "z25", "z26", "z27", "z28", "z29",
313 "z30", "z31"};
314
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100315const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
316 "p6", "p7", "p8", "p9", "p10", "p11",
317 "p12", "p13", "p14", "p15"};
318// clang-format on
319
Alexandre Ramesd3832962016-07-04 15:03:43 +0100320
321const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100322 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000323 if ((code == kSPRegInternalCode) ||
324 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100325 code = kZeroRegCode + 1;
326 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000327 VIXL_ASSERT(code < ArrayLength(wreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100328 return wreg_names[code];
329}
330
331
332const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100333 // If the code represents the stack pointer, index the name after zr.
Jacob Bramley423e5422019-11-13 19:15:55 +0000334 if ((code == kSPRegInternalCode) ||
335 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100336 code = kZeroRegCode + 1;
337 }
Jacob Bramley423e5422019-11-13 19:15:55 +0000338 VIXL_ASSERT(code < ArrayLength(xreg_names));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100339 return xreg_names[code];
340}
341
342
Jacob Bramley423e5422019-11-13 19:15:55 +0000343const char* Simulator::BRegNameForCode(unsigned code) {
344 VIXL_ASSERT(code < kNumberOfVRegisters);
345 return breg_names[code];
346}
347
348
Carey Williamsd8bb3572018-04-10 11:58:07 +0100349const char* Simulator::HRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100350 VIXL_ASSERT(code < kNumberOfVRegisters);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100351 return hreg_names[code];
352}
353
354
Alexandre Ramesd3832962016-07-04 15:03:43 +0100355const char* Simulator::SRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100356 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100357 return sreg_names[code];
358}
359
360
361const char* Simulator::DRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100362 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100363 return dreg_names[code];
364}
365
366
367const char* Simulator::VRegNameForCode(unsigned code) {
368 VIXL_ASSERT(code < kNumberOfVRegisters);
369 return vreg_names[code];
370}
371
372
TatWai Chong72d2e562019-05-16 11:22:22 -0700373const char* Simulator::ZRegNameForCode(unsigned code) {
374 VIXL_ASSERT(code < kNumberOfZRegisters);
375 return zreg_names[code];
376}
377
378
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100379const char* Simulator::PRegNameForCode(unsigned code) {
380 VIXL_ASSERT(code < kNumberOfPRegisters);
381 return preg_names[code];
382}
383
Martyn Capewell7fd6fd52019-12-06 14:50:15 +0000384SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
385 SimVRegister ones, result;
386 dup_immediate(kFormatVnB, ones, 0xff);
387 mov_zeroing(kFormatVnB, result, pg, ones);
388 return result;
389}
390
391void Simulator::ExtractFromSimVRegister(SimPRegister& pd, SimVRegister vreg) {
392 SimVRegister zero;
393 dup_immediate(kFormatVnB, zero, 0);
394 SVEIntCompareVectorsHelper(ne,
395 kFormatVnB,
396 pd,
397 GetPTrue(),
398 vreg,
399 zero,
400 false,
401 LeaveFlags);
402}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100403
Alexandre Ramesd3832962016-07-04 15:03:43 +0100404#define COLOUR(colour_code) "\033[0;" colour_code "m"
405#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
Jacob Bramleye79723a2016-06-07 17:50:47 +0100406#define COLOUR_HIGHLIGHT "\033[43m"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100407#define NORMAL ""
408#define GREY "30"
409#define RED "31"
410#define GREEN "32"
411#define YELLOW "33"
412#define BLUE "34"
413#define MAGENTA "35"
414#define CYAN "36"
415#define WHITE "37"
416void Simulator::SetColouredTrace(bool value) {
417 coloured_trace_ = value;
418
419 clr_normal = value ? COLOUR(NORMAL) : "";
420 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
421 clr_flag_value = value ? COLOUR(NORMAL) : "";
422 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
423 clr_reg_value = value ? COLOUR(CYAN) : "";
424 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
425 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100426 clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
427 clr_preg_value = value ? COLOUR(GREEN) : "";
Alexandre Ramesd3832962016-07-04 15:03:43 +0100428 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
429 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
430 clr_warning_message = value ? COLOUR(YELLOW) : "";
431 clr_printf = value ? COLOUR(GREEN) : "";
Jacob Bramleye79723a2016-06-07 17:50:47 +0100432 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100433
434 if (value) {
435 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
436 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
437 } else {
438 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
439 print_disasm_->SetCPUFeaturesSuffix("");
440 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100441}
442
443
444void Simulator::SetTraceParameters(int parameters) {
445 bool disasm_before = trace_parameters_ & LOG_DISASM;
446 trace_parameters_ = parameters;
447 bool disasm_after = trace_parameters_ & LOG_DISASM;
448
449 if (disasm_before != disasm_after) {
450 if (disasm_after) {
451 decoder_->InsertVisitorBefore(print_disasm_, this);
452 } else {
453 decoder_->RemoveVisitor(print_disasm_);
454 }
455 }
456}
457
458
459void Simulator::SetInstructionStats(bool value) {
460 if (value != instruction_stats_) {
461 if (value) {
462 if (instrumentation_ == NULL) {
463 // Set the sample period to 10, as the VIXL examples and tests are
464 // short.
465 instrumentation_ = new Instrument("vixl_stats.csv", 10);
466 }
467 decoder_->AppendVisitor(instrumentation_);
468 } else if (instrumentation_ != NULL) {
469 decoder_->RemoveVisitor(instrumentation_);
470 }
471 instruction_stats_ = value;
472 }
473}
474
475// Helpers ---------------------------------------------------------------------
476uint64_t Simulator::AddWithCarry(unsigned reg_size,
477 bool set_flags,
478 uint64_t left,
479 uint64_t right,
480 int carry_in) {
481 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
482 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
483
484 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
485 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
486 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
487
488 left &= reg_mask;
489 right &= reg_mask;
490 uint64_t result = (left + right + carry_in) & reg_mask;
491
492 if (set_flags) {
493 ReadNzcv().SetN(CalcNFlag(result, reg_size));
494 ReadNzcv().SetZ(CalcZFlag(result));
495
496 // Compute the C flag by comparing the result to the max unsigned integer.
497 uint64_t max_uint_2op = max_uint - carry_in;
498 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
499 ReadNzcv().SetC(C ? 1 : 0);
500
501 // Overflow iff the sign bit is the same for the two inputs and different
502 // for the result.
503 uint64_t left_sign = left & sign_mask;
504 uint64_t right_sign = right & sign_mask;
505 uint64_t result_sign = result & sign_mask;
506 bool V = (left_sign == right_sign) && (left_sign != result_sign);
507 ReadNzcv().SetV(V ? 1 : 0);
508
509 LogSystemRegister(NZCV);
510 }
511 return result;
512}
513
514
515int64_t Simulator::ShiftOperand(unsigned reg_size,
516 int64_t value,
517 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100518 unsigned amount) const {
TatWai Chong29a0c432019-11-06 22:20:44 -0800519 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
520 (reg_size == kSRegSize) || (reg_size == kDRegSize));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100521 if (amount == 0) {
522 return value;
523 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000524
TatWai Chong29a0c432019-11-06 22:20:44 -0800525 uint64_t uvalue = static_cast<uint64_t>(value);
526 uint64_t mask = GetUintMask(reg_size);
527 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
528 // The behavior is undefined in c++ if the shift amount greater than or equal
529 // to the register lane size. Work out the shifted result based on
530 // architectural behavior before performing the c++ type shfit operations.
Alexandre Ramesd3832962016-07-04 15:03:43 +0100531 switch (shift_type) {
532 case LSL:
TatWai Chong29a0c432019-11-06 22:20:44 -0800533 if (amount >= reg_size) {
534 return UINT64_C(0);
535 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000536 uvalue <<= amount;
537 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100538 case LSR:
TatWai Chong29a0c432019-11-06 22:20:44 -0800539 if (amount >= reg_size) {
540 return UINT64_C(0);
541 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000542 uvalue >>= amount;
543 break;
544 case ASR:
TatWai Chong29a0c432019-11-06 22:20:44 -0800545 if (amount >= reg_size) {
546 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
547 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000548 uvalue >>= amount;
549 if (is_negative) {
550 // Simulate sign-extension to 64 bits.
551 uvalue |= ~UINT64_C(0) << (reg_size - amount);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100552 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000553 break;
554 case ROR: {
Martyn Capewellfb8e3df2016-11-03 15:50:19 +0000555 uvalue = RotateRight(uvalue, amount, reg_size);
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000556 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100557 }
558 default:
559 VIXL_UNIMPLEMENTED();
560 return 0;
561 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000562 uvalue &= mask;
563
564 int64_t result;
565 memcpy(&result, &uvalue, sizeof(result));
566 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100567}
568
569
570int64_t Simulator::ExtendValue(unsigned reg_size,
571 int64_t value,
572 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100573 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100574 switch (extend_type) {
575 case UXTB:
576 value &= kByteMask;
577 break;
578 case UXTH:
579 value &= kHalfWordMask;
580 break;
581 case UXTW:
582 value &= kWordMask;
583 break;
584 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000585 value &= kByteMask;
586 if ((value & 0x80) != 0) {
587 value |= ~UINT64_C(0) << 8;
588 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100589 break;
590 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000591 value &= kHalfWordMask;
592 if ((value & 0x8000) != 0) {
593 value |= ~UINT64_C(0) << 16;
594 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100595 break;
596 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000597 value &= kWordMask;
598 if ((value & 0x80000000) != 0) {
599 value |= ~UINT64_C(0) << 32;
600 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100601 break;
602 case UXTX:
603 case SXTX:
604 break;
605 default:
606 VIXL_UNREACHABLE();
607 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000608 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100609}
610
611
612void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
613 AssertSupportedFPCR();
614
615 // TODO: This assumes that the C++ implementation handles comparisons in the
616 // way that we expect (as per AssertSupportedFPCR()).
617 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100618 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100619 ReadNzcv().SetRawValue(FPUnorderedFlag);
620 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
621 (trap == EnableTrap)) {
622 process_exception = true;
623 }
624 } else if (val0 < val1) {
625 ReadNzcv().SetRawValue(FPLessThanFlag);
626 } else if (val0 > val1) {
627 ReadNzcv().SetRawValue(FPGreaterThanFlag);
628 } else if (val0 == val1) {
629 ReadNzcv().SetRawValue(FPEqualFlag);
630 } else {
631 VIXL_UNREACHABLE();
632 }
633 LogSystemRegister(NZCV);
634 if (process_exception) FPProcessException();
635}
636
637
Alexandre Rames868bfc42016-07-19 17:10:48 +0100638uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
639 VIXL_ASSERT(mem_op.IsValid());
640 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
641 if (mem_op.IsImmediateOffset()) {
642 return base + mem_op.GetOffset();
643 } else {
644 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
645 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100646 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100647 if (mem_op.GetShift() != NO_SHIFT) {
648 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
649 }
650 if (mem_op.GetExtend() != NO_EXTEND) {
651 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
652 }
653 return static_cast<uint64_t>(base + offset);
654 }
655}
656
657
Alexandre Ramesd3832962016-07-04 15:03:43 +0100658Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
659 unsigned reg_size, unsigned lane_size) {
660 VIXL_ASSERT(reg_size >= lane_size);
661
662 uint32_t format = 0;
663 if (reg_size != lane_size) {
664 switch (reg_size) {
665 default:
666 VIXL_UNREACHABLE();
667 break;
668 case kQRegSizeInBytes:
669 format = kPrintRegAsQVector;
670 break;
671 case kDRegSizeInBytes:
672 format = kPrintRegAsDVector;
673 break;
674 }
675 }
676
677 switch (lane_size) {
678 default:
679 VIXL_UNREACHABLE();
680 break;
681 case kQRegSizeInBytes:
682 format |= kPrintReg1Q;
683 break;
684 case kDRegSizeInBytes:
685 format |= kPrintReg1D;
686 break;
687 case kSRegSizeInBytes:
688 format |= kPrintReg1S;
689 break;
690 case kHRegSizeInBytes:
691 format |= kPrintReg1H;
692 break;
693 case kBRegSizeInBytes:
694 format |= kPrintReg1B;
695 break;
696 }
697 // These sizes would be duplicate case labels.
698 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
699 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
700 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
701 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
702
703 return static_cast<PrintRegisterFormat>(format);
704}
705
706
707Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
708 VectorFormat vform) {
709 switch (vform) {
710 default:
711 VIXL_UNREACHABLE();
712 return kPrintReg16B;
713 case kFormat16B:
714 return kPrintReg16B;
715 case kFormat8B:
716 return kPrintReg8B;
717 case kFormat8H:
718 return kPrintReg8H;
719 case kFormat4H:
720 return kPrintReg4H;
721 case kFormat4S:
722 return kPrintReg4S;
723 case kFormat2S:
724 return kPrintReg2S;
725 case kFormat2D:
726 return kPrintReg2D;
727 case kFormat1D:
728 return kPrintReg1D;
729
730 case kFormatB:
731 return kPrintReg1B;
732 case kFormatH:
733 return kPrintReg1H;
734 case kFormatS:
735 return kPrintReg1S;
736 case kFormatD:
737 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +0100738
739 case kFormatVnB:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000740 return kPrintRegVnB;
Jacob Bramleye668b202019-08-14 17:57:34 +0100741 case kFormatVnH:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000742 return kPrintRegVnH;
Jacob Bramleye668b202019-08-14 17:57:34 +0100743 case kFormatVnS:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000744 return kPrintRegVnS;
Jacob Bramleye668b202019-08-14 17:57:34 +0100745 case kFormatVnD:
Jacob Bramley7eb3e212019-11-22 17:28:05 +0000746 return kPrintRegVnD;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100747 }
748}
749
750
751Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
752 VectorFormat vform) {
753 switch (vform) {
754 default:
755 VIXL_UNREACHABLE();
756 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100757 case kFormat8H:
758 return kPrintReg8HFP;
759 case kFormat4H:
760 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100761 case kFormat4S:
762 return kPrintReg4SFP;
763 case kFormat2S:
764 return kPrintReg2SFP;
765 case kFormat2D:
766 return kPrintReg2DFP;
767 case kFormat1D:
768 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100769 case kFormatH:
770 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100771 case kFormatS:
772 return kPrintReg1SFP;
773 case kFormatD:
774 return kPrintReg1DFP;
775 }
776}
777
Jacob Bramley423e5422019-11-13 19:15:55 +0000778void Simulator::PrintRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100779 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
Jacob Bramley423e5422019-11-13 19:15:55 +0000780 if (i == kSpRegCode) i = kSPRegInternalCode;
781 PrintRegister(i);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100782 }
783}
784
Jacob Bramley423e5422019-11-13 19:15:55 +0000785void Simulator::PrintVRegisters() {
786 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
787 PrintVRegister(i);
788 }
789}
790
791void Simulator::PrintZRegisters() {
792 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
793 PrintZRegister(i);
794 }
795}
796
797void Simulator::PrintWrittenRegisters() {
798 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
799 if (registers_[i].WrittenSinceLastLog()) {
800 if (i == kSpRegCode) i = kSPRegInternalCode;
801 PrintRegister(i);
802 }
803 }
804}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100805
806void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100807 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100808 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100809 if (vregisters_[i].WrittenSinceLastLog()) {
810 // Z registers are initialised in the constructor before the user can
811 // configure the CPU features, so we must also check for SVE here.
812 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
813 PrintZRegister(i);
814 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +0000815 PrintVRegister(i);
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100816 }
817 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100818 }
819}
820
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100821void Simulator::PrintWrittenPRegisters() {
822 // P registers are initialised in the constructor before the user can
823 // configure the CPU features, so we must check for SVE here.
824 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
825 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
826 if (pregisters_[i].WrittenSinceLastLog()) {
827 PrintPRegister(i);
828 }
829 }
830}
831
Alexandre Ramesd3832962016-07-04 15:03:43 +0100832void Simulator::PrintSystemRegisters() {
833 PrintSystemRegister(NZCV);
834 PrintSystemRegister(FPCR);
835}
836
Jacob Bramley423e5422019-11-13 19:15:55 +0000837void Simulator::PrintRegisterValue(const uint8_t* value,
838 int value_size,
839 PrintRegisterFormat format) {
840 int print_width = GetPrintRegSizeInBytes(format);
841 VIXL_ASSERT(print_width <= value_size);
842 for (int i = value_size - 1; i >= print_width; i--) {
843 // Pad with spaces so that values align vertically.
Alexandre Ramesd3832962016-07-04 15:03:43 +0100844 fprintf(stream_, " ");
Jacob Bramley423e5422019-11-13 19:15:55 +0000845 // If we aren't explicitly printing a partial value, ensure that the
846 // unprinted bits are zero.
847 VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100848 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100849 fprintf(stream_, "0x");
Jacob Bramley423e5422019-11-13 19:15:55 +0000850 for (int i = print_width - 1; i >= 0; i--) {
851 fprintf(stream_, "%02x", value[i]);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100852 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100853}
854
Jacob Bramley423e5422019-11-13 19:15:55 +0000855void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
856 uint16_t lane_mask,
857 PrintRegisterFormat format) {
858 VIXL_ASSERT((format & kPrintRegAsFP) != 0);
859 int lane_size = GetPrintRegLaneSizeInBytes(format);
860 fprintf(stream_, " (");
861 bool last_inactive = false;
862 const char* sep = "";
863 for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
864 bool access = (lane_mask & (1 << (i * lane_size))) != 0;
865 if (access) {
866 // Read the lane as a double, so we can format all FP types in the same
867 // way. We squash NaNs, and a double can exactly represent any other value
868 // that the smaller types can represent, so this is lossless.
869 double element;
870 switch (lane_size) {
871 case kHRegSizeInBytes: {
872 Float16 element_fp16;
873 VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
874 memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
875 element = FPToDouble(element_fp16, kUseDefaultNaN);
876 break;
877 }
878 case kSRegSizeInBytes: {
879 float element_fp32;
880 memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
881 element = static_cast<double>(element_fp32);
882 break;
883 }
884 case kDRegSizeInBytes: {
885 memcpy(&element, &value[i * lane_size], sizeof(element));
886 break;
887 }
888 default:
889 VIXL_UNREACHABLE();
890 fprintf(stream_, "{UnknownFPValue}");
891 continue;
892 }
893 if (IsNaN(element)) {
894 // The fprintf behaviour for NaNs is implementation-defined. Always
895 // print "nan", so that traces are consistent.
896 fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
897 } else {
898 fprintf(stream_,
899 "%s%s%#.4g%s",
900 sep,
901 clr_vreg_value,
902 element,
903 clr_normal);
904 }
905 last_inactive = false;
906 } else if (!last_inactive) {
907 // Replace each contiguous sequence of inactive lanes with "...".
908 fprintf(stream_, "%s...", sep);
909 last_inactive = true;
910 }
911 }
912 fprintf(stream_, ")");
913}
914
915void Simulator::PrintRegister(int code,
916 PrintRegisterFormat format,
917 const char* suffix) {
918 VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
919 (static_cast<unsigned>(code) == kSPRegInternalCode));
920 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
921 VIXL_ASSERT((format & kPrintRegAsFP) == 0);
922
923 SimRegister* reg;
924 SimRegister zero;
925 if (code == kZeroRegCode) {
926 reg = &zero;
927 } else {
928 // registers_[31] holds the SP.
929 VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
930 reg = &registers_[code % kNumberOfRegisters];
931 }
932
933 // We trace register writes as whole register values, implying that any
934 // unprinted bits are all zero:
935 // "# x{code}: 0x{-----value----}"
936 // "# w{code}: 0x{-value}"
937 // Stores trace partial register values, implying nothing about the unprinted
938 // bits:
939 // "# x{code}<63:0>: 0x{-----value----}"
940 // "# x{code}<31:0>: 0x{-value}"
941 // "# x{code}<15:0>: 0x{--}"
942 // "# x{code}<7:0>: 0x{}"
943
944 bool is_partial = (format & kPrintRegPartial) != 0;
945 unsigned print_reg_size = GetPrintRegSizeInBits(format);
946 std::stringstream name;
947 if (is_partial) {
948 name << XRegNameForCode(code) << GetPartialRegSuffix(format);
949 } else {
950 // Notify the register that it has been logged, but only if we're printing
951 // all of it.
952 reg->NotifyRegisterLogged();
953 switch (print_reg_size) {
954 case kWRegSize:
955 name << WRegNameForCode(code);
956 break;
957 case kXRegSize:
958 name << XRegNameForCode(code);
959 break;
960 default:
961 VIXL_UNREACHABLE();
962 return;
963 }
964 }
965
966 fprintf(stream_,
967 "# %s%*s: %s",
968 clr_reg_name,
969 kPrintRegisterNameFieldWidth,
970 name.str().c_str(),
971 clr_reg_value);
972 PrintRegisterValue(*reg, format);
973 fprintf(stream_, "%s%s", clr_normal, suffix);
974}
975
976void Simulator::PrintVRegister(int code,
977 PrintRegisterFormat format,
978 const char* suffix) {
979 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
980 VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
981 ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
982 ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
983
984 // We trace register writes as whole register values, implying that any
985 // unprinted bits are all zero:
986 // "# v{code}: 0x{-------------value------------}"
987 // "# d{code}: 0x{-----value----}"
988 // "# s{code}: 0x{-value}"
989 // "# h{code}: 0x{--}"
990 // "# b{code}: 0x{}"
991 // Stores trace partial register values, implying nothing about the unprinted
992 // bits:
993 // "# v{code}<127:0>: 0x{-------------value------------}"
994 // "# v{code}<63:0>: 0x{-----value----}"
995 // "# v{code}<31:0>: 0x{-value}"
996 // "# v{code}<15:0>: 0x{--}"
997 // "# v{code}<7:0>: 0x{}"
998
999 bool is_partial = ((format & kPrintRegPartial) != 0);
1000 std::stringstream name;
1001 unsigned print_reg_size = GetPrintRegSizeInBits(format);
1002 if (is_partial) {
1003 name << VRegNameForCode(code) << GetPartialRegSuffix(format);
1004 } else {
1005 // Notify the register that it has been logged, but only if we're printing
1006 // all of it.
1007 vregisters_[code].NotifyRegisterLogged();
1008 switch (print_reg_size) {
1009 case kBRegSize:
1010 name << BRegNameForCode(code);
1011 break;
1012 case kHRegSize:
1013 name << HRegNameForCode(code);
1014 break;
1015 case kSRegSize:
1016 name << SRegNameForCode(code);
1017 break;
1018 case kDRegSize:
1019 name << DRegNameForCode(code);
1020 break;
1021 case kQRegSize:
1022 name << VRegNameForCode(code);
1023 break;
1024 default:
1025 VIXL_UNREACHABLE();
1026 return;
1027 }
1028 }
1029
1030 fprintf(stream_,
1031 "# %s%*s: %s",
1032 clr_vreg_name,
1033 kPrintRegisterNameFieldWidth,
1034 name.str().c_str(),
1035 clr_vreg_value);
1036 PrintRegisterValue(vregisters_[code], format);
1037 fprintf(stream_, "%s", clr_normal);
1038 if ((format & kPrintRegAsFP) != 0) {
1039 PrintRegisterValueFPAnnotations(vregisters_[code], format);
1040 }
1041 fprintf(stream_, "%s", suffix);
1042}
1043
1044void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1045 int reg_count,
1046 uint16_t focus_mask,
1047 PrintRegisterFormat format) {
1048 bool print_fp = (format & kPrintRegAsFP) != 0;
1049 // Suppress FP formatting, so we can specify the lanes we're interested in.
1050 PrintRegisterFormat format_no_fp =
1051 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1052
1053 for (int r = 0; r < reg_count; r++) {
1054 int code = (rt_code + r) % kNumberOfVRegisters;
1055 PrintVRegister(code, format_no_fp, "");
1056 if (print_fp) {
1057 PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1058 }
1059 fprintf(stream_, "\n");
1060 }
1061}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001062
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001063void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1064 int q_index,
1065 int reg_count,
1066 uint16_t focus_mask,
1067 PrintRegisterFormat format) {
1068 bool print_fp = (format & kPrintRegAsFP) != 0;
1069 // Suppress FP formatting, so we can specify the lanes we're interested in.
1070 PrintRegisterFormat format_no_fp =
1071 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
TatWai Chong72d2e562019-05-16 11:22:22 -07001072
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001073 PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
TatWai Chong72d2e562019-05-16 11:22:22 -07001074
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001075 const unsigned size = kQRegSizeInBytes;
1076 unsigned byte_index = q_index * size;
1077 const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1078 VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
TatWai Chong72d2e562019-05-16 11:22:22 -07001079
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001080 for (int r = 0; r < reg_count; r++) {
1081 int code = (rt_code + r) % kNumberOfZRegisters;
1082 PrintPartialZRegister(code, q_index, format_no_fp, "");
1083 if (print_fp) {
1084 PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
TatWai Chong72d2e562019-05-16 11:22:22 -07001085 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001086 fprintf(stream_, "\n");
TatWai Chong72d2e562019-05-16 11:22:22 -07001087 }
TatWai Chong72d2e562019-05-16 11:22:22 -07001088}
1089
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001090void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1091 // We're going to print the register in parts, so force a partial format.
1092 format = GetPrintRegPartial(format);
1093 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1094 int vl = GetVectorLengthInBits();
1095 VIXL_ASSERT((vl % kQRegSize) == 0);
1096 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1097 PrintPartialZRegister(code, i, format);
1098 }
1099 vregisters_[code].NotifyRegisterLogged();
1100}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001101
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001102void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1103 // We're going to print the register in parts, so force a partial format.
1104 format = GetPrintRegPartial(format);
1105 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1106 int vl = GetVectorLengthInBits();
1107 VIXL_ASSERT((vl % kQRegSize) == 0);
1108 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1109 PrintPartialPRegister(code, i, format);
1110 }
1111 pregisters_[code].NotifyRegisterLogged();
1112}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001113
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001114void Simulator::PrintPartialZRegister(int code,
1115 int q_index,
1116 PrintRegisterFormat format,
1117 const char* suffix) {
1118 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1119 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1120 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1121 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001122
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001123 // We _only_ trace partial Z register values in Q-sized chunks, because
1124 // they're often too large to reasonably fit on a single line. Each line
1125 // implies nothing about the unprinted bits.
1126 // "# z{code}<127:0>: 0x{-------------value------------}"
1127
1128 format = GetPrintRegAsQChunkOfSVE(format);
1129
1130 const unsigned size = kQRegSizeInBytes;
1131 unsigned byte_index = q_index * size;
1132 const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1133 VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1134
1135 int lsb = q_index * kQRegSize;
1136 int msb = lsb + kQRegSize - 1;
1137 std::stringstream name;
1138 name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001139
1140 fprintf(stream_,
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001141 "# %s%*s: %s",
1142 clr_vreg_name,
1143 kPrintRegisterNameFieldWidth,
1144 name.str().c_str(),
1145 clr_vreg_value);
1146 PrintRegisterValue(value, size, format);
1147 fprintf(stream_, "%s", clr_normal);
1148 if ((format & kPrintRegAsFP) != 0) {
1149 PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1150 }
1151 fprintf(stream_, "%s", suffix);
1152}
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001153
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001154void Simulator::PrintPartialPRegister(int code,
1155 int q_index,
1156 PrintRegisterFormat format,
1157 const char* suffix) {
1158 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1159 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1160 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1161 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1162
1163 // We don't currently use the format for anything here.
1164 USE(format);
1165
1166 // We _only_ trace partial P register values, because they're often too large
1167 // to reasonably fit on a single line. Each line implies nothing about the
1168 // unprinted bits.
1169 //
1170 // We print values in binary, with spaces between each bit, in order for the
1171 // bits to align with the Z register bytes that they predicate.
1172 // "# p{code}<15:0>: 0b{-------------value------------}"
1173
1174 int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1175 int lsb = q_index * print_size_in_bits;
1176 int msb = lsb + print_size_in_bits - 1;
1177 std::stringstream name;
1178 name << PRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
1179
1180 fprintf(stream_,
1181 "# %s%*s: %s0b",
1182 clr_preg_name,
1183 kPrintRegisterNameFieldWidth,
1184 name.str().c_str(),
1185 clr_preg_value);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001186 for (int i = msb; i >= lsb; i--) {
1187 fprintf(stream_, " %c", pregisters_[code].GetBit(i) ? '1' : '0');
1188 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001189 fprintf(stream_, "%s%s", clr_normal, suffix);
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001190}
1191
Alexandre Ramesd3832962016-07-04 15:03:43 +01001192void Simulator::PrintSystemRegister(SystemRegister id) {
1193 switch (id) {
1194 case NZCV:
1195 fprintf(stream_,
1196 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1197 clr_flag_name,
1198 clr_flag_value,
1199 ReadNzcv().GetN(),
1200 ReadNzcv().GetZ(),
1201 ReadNzcv().GetC(),
1202 ReadNzcv().GetV(),
1203 clr_normal);
1204 break;
1205 case FPCR: {
1206 static const char* rmode[] = {"0b00 (Round to Nearest)",
1207 "0b01 (Round towards Plus Infinity)",
1208 "0b10 (Round towards Minus Infinity)",
1209 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001210 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001211 fprintf(stream_,
1212 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1213 clr_flag_name,
1214 clr_flag_value,
1215 ReadFpcr().GetAHP(),
1216 ReadFpcr().GetDN(),
1217 ReadFpcr().GetFZ(),
1218 rmode[ReadFpcr().GetRMode()],
1219 clr_normal);
1220 break;
1221 }
1222 default:
1223 VIXL_UNREACHABLE();
1224 }
1225}
1226
Jacob Bramley423e5422019-11-13 19:15:55 +00001227uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1228 uint16_t future_access_mask,
1229 int struct_element_count,
1230 int lane_size_in_bytes,
1231 const char* op,
1232 uintptr_t address,
1233 int reg_size_in_bytes) {
1234 // We want to assume that we'll access at least one lane.
1235 VIXL_ASSERT(access_mask != 0);
1236 VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1237 (reg_size_in_bytes == kQRegSizeInBytes));
1238 bool started_annotation = false;
1239 // Indent to match the register field, the fixed formatting, and the value
1240 // prefix ("0x"): "# {name}: 0x"
1241 fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1242 // First, annotate the lanes (byte by byte).
1243 for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1244 bool access = (access_mask & (1 << lane)) != 0;
1245 bool future = (future_access_mask & (1 << lane)) != 0;
1246 if (started_annotation) {
1247 // If we've started an annotation, draw a horizontal line in addition to
1248 // any other symbols.
1249 if (access) {
1250 fprintf(stream_, "─╨");
1251 } else if (future) {
1252 fprintf(stream_, "─║");
1253 } else {
1254 fprintf(stream_, "──");
1255 }
1256 } else {
1257 if (access) {
1258 started_annotation = true;
1259 fprintf(stream_, " â•™");
1260 } else if (future) {
1261 fprintf(stream_, " â•‘");
1262 } else {
1263 fprintf(stream_, " ");
1264 }
1265 }
1266 }
1267 VIXL_ASSERT(started_annotation);
1268 fprintf(stream_, "─ 0x");
1269 int lane_size_in_nibbles = lane_size_in_bytes * 2;
1270 // Print the most-significant struct element first.
1271 const char* sep = "";
1272 for (int i = struct_element_count - 1; i >= 0; i--) {
1273 int offset = lane_size_in_bytes * i;
1274 uint64_t nibble = Memory::Read(lane_size_in_bytes, address + offset);
1275 fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1276 sep = "'";
1277 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001278 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001279 " %s %s0x%016" PRIxPTR "%s\n",
1280 op,
1281 clr_memory_address,
1282 address,
1283 clr_normal);
1284 return future_access_mask & ~access_mask;
1285}
1286
1287void Simulator::PrintAccess(int code,
1288 PrintRegisterFormat format,
1289 const char* op,
1290 uintptr_t address) {
1291 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1292 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1293 if ((format & kPrintRegPartial) == 0) {
1294 registers_[code].NotifyRegisterLogged();
1295 }
1296 // Scalar-format accesses use a simple format:
1297 // "# {reg}: 0x{value} -> {address}"
1298
1299 // Suppress the newline, so the access annotation goes on the same line.
1300 PrintRegister(code, format, "");
1301 fprintf(stream_,
1302 " %s %s0x%016" PRIxPTR "%s\n",
1303 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001304 clr_memory_address,
1305 address,
1306 clr_normal);
1307}
1308
Jacob Bramley423e5422019-11-13 19:15:55 +00001309void Simulator::PrintVAccess(int code,
1310 PrintRegisterFormat format,
1311 const char* op,
1312 uintptr_t address) {
1313 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001314
Jacob Bramley423e5422019-11-13 19:15:55 +00001315 // Scalar-format accesses use a simple format:
1316 // "# v{code}: 0x{value} -> {address}"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001317
Jacob Bramley423e5422019-11-13 19:15:55 +00001318 // Suppress the newline, so the access annotation goes on the same line.
1319 PrintVRegister(code, format, "");
Alexandre Ramesd3832962016-07-04 15:03:43 +01001320 fprintf(stream_,
Jacob Bramley423e5422019-11-13 19:15:55 +00001321 " %s %s0x%016" PRIxPTR "%s\n",
1322 op,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001323 clr_memory_address,
1324 address,
1325 clr_normal);
1326}
1327
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001328void Simulator::PrintVStructAccess(int rt_code,
Jacob Bramley423e5422019-11-13 19:15:55 +00001329 int reg_count,
1330 PrintRegisterFormat format,
1331 const char* op,
1332 uintptr_t address) {
1333 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1334
1335 // For example:
1336 // "# v{code}: 0x{value}"
1337 // "# ...: 0x{value}"
1338 // "# ║ ╙─ {struct_value} -> {lowest_address}"
1339 // "# ╙───── {struct_value} -> {highest_address}"
1340
1341 uint16_t lane_mask = GetPrintRegLaneMask(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001342 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
Jacob Bramley423e5422019-11-13 19:15:55 +00001343
1344 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1345 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1346 for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1347 uint16_t access_mask = 1 << i;
1348 VIXL_ASSERT((lane_mask & access_mask) != 0);
1349 lane_mask = PrintPartialAccess(access_mask,
1350 lane_mask,
1351 reg_count,
1352 lane_size_in_bytes,
1353 op,
1354 address + (i * reg_count));
1355 }
1356}
1357
1358void Simulator::PrintVSingleStructAccess(int rt_code,
1359 int reg_count,
1360 int lane,
1361 PrintRegisterFormat format,
1362 const char* op,
1363 uintptr_t address) {
1364 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1365
1366 // For example:
1367 // "# v{code}: 0x{value}"
1368 // "# ...: 0x{value}"
1369 // "# ╙───── {struct_value} -> {address}"
1370
1371 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1372 uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1373 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1374 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1375}
1376
1377void Simulator::PrintVReplicatingStructAccess(int rt_code,
1378 int reg_count,
1379 PrintRegisterFormat format,
1380 const char* op,
1381 uintptr_t address) {
1382 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1383
1384 // For example:
1385 // "# v{code}: 0x{value}"
1386 // "# ...: 0x{value}"
1387 // "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1388
1389 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1390 uint16_t lane_mask = GetPrintRegLaneMask(format);
1391 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1392 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1393}
1394
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001395void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1396 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1397
1398 // Scalar-format accesses are split into separate chunks, each of which uses a
1399 // simple format:
1400 // "# z{code}<127:0>: 0x{value} -> {address}"
1401 // "# z{code}<255:128>: 0x{value} -> {address + 16}"
1402 // "# z{code}<383:256>: 0x{value} -> {address + 32}"
1403 // etc
1404
1405 int vl = GetVectorLengthInBits();
1406 VIXL_ASSERT((vl % kQRegSize) == 0);
1407 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1408 // Suppress the newline, so the access annotation goes on the same line.
1409 PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1410 fprintf(stream_,
1411 " %s %s0x%016" PRIxPTR "%s\n",
1412 op,
1413 clr_memory_address,
1414 address,
1415 clr_normal);
1416 address += kQRegSizeInBytes;
1417 }
1418}
1419
1420void Simulator::PrintZStructAccess(int rt_code,
1421 int reg_count,
1422 const LogicPRegister& pg,
1423 PrintRegisterFormat format,
1424 int msize_in_bytes,
1425 const char* op,
1426 const LogicSVEAddressVector& addr) {
1427 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1428
1429 // For example:
1430 // "# z{code}<255:128>: 0x{value}"
1431 // "# ...<255:128>: 0x{value}"
1432 // "# ║ ╙─ {struct_value} -> {first_address}"
1433 // "# ╙───── {struct_value} -> {last_address}"
1434
1435 // We're going to print the register in parts, so force a partial format.
1436 bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1437 format = GetPrintRegPartial(format);
1438
1439 int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1440 int vl = GetVectorLengthInBits();
1441 VIXL_ASSERT((vl % kQRegSize) == 0);
1442 int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1443 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1444 uint16_t pred =
1445 pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1446 if ((pred == 0) && skip_inactive_chunks) continue;
1447
1448 PrintZRegistersForStructuredAccess(rt_code,
1449 q_index,
1450 reg_count,
1451 pred,
1452 format);
1453 if (pred == 0) {
1454 // This register chunk has no active lanes. The loop below would print
1455 // nothing, so leave a blank line to keep structures grouped together.
1456 fprintf(stream_, "#\n");
1457 continue;
1458 }
1459 for (int i = 0; i < lanes_per_q; i++) {
1460 uint16_t access = 1 << (i * esize_in_bytes);
1461 int lane = (q_index * lanes_per_q) + i;
1462 // Skip inactive lanes.
1463 if ((pred & access) == 0) continue;
1464 pred = PrintPartialAccess(access,
1465 pred,
1466 reg_count,
1467 msize_in_bytes,
1468 op,
1469 addr.GetStructAddress(lane));
1470 }
1471 }
1472
1473 // We print the whole register, even for stores.
1474 for (int i = 0; i < reg_count; i++) {
1475 vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1476 }
1477}
1478
1479void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1480 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1481
1482 // Scalar-format accesses are split into separate chunks, each of which uses a
1483 // simple format:
1484 // "# p{code}<15:0>: 0b{value} -> {address}"
1485 // "# p{code}<31:16>: 0b{value} -> {address + 2}"
1486 // "# p{code}<47:32>: 0b{value} -> {address + 4}"
1487 // etc
1488
1489 int vl = GetVectorLengthInBits();
1490 VIXL_ASSERT((vl % kQRegSize) == 0);
1491 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1492 // Suppress the newline, so the access annotation goes on the same line.
1493 PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1494 fprintf(stream_,
1495 " %s %s0x%016" PRIxPTR "%s\n",
1496 op,
1497 clr_memory_address,
1498 address,
1499 clr_normal);
1500 address += kQRegSizeInBytes;
1501 }
1502}
1503
Jacob Bramley423e5422019-11-13 19:15:55 +00001504void Simulator::PrintRead(int rt_code,
1505 PrintRegisterFormat format,
1506 uintptr_t address) {
1507 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1508 registers_[rt_code].NotifyRegisterLogged();
1509 PrintAccess(rt_code, format, "<-", address);
1510}
1511
1512void Simulator::PrintExtendingRead(int rt_code,
1513 PrintRegisterFormat format,
1514 int access_size_in_bytes,
1515 uintptr_t address) {
1516 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1517 if (access_size_in_bytes == reg_size_in_bytes) {
1518 // There is no extension here, so print a simple load.
1519 PrintRead(rt_code, format, address);
1520 return;
1521 }
1522 VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1523
1524 // For sign- and zero-extension, make it clear that the resulting register
1525 // value is different from what is loaded from memory.
1526 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1527 registers_[rt_code].NotifyRegisterLogged();
1528 PrintRegister(rt_code, format);
1529 PrintPartialAccess(1,
1530 0,
1531 1,
1532 access_size_in_bytes,
1533 "<-",
1534 address,
1535 kXRegSizeInBytes);
1536}
1537
1538void Simulator::PrintVRead(int rt_code,
1539 PrintRegisterFormat format,
1540 uintptr_t address) {
1541 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1542 vregisters_[rt_code].NotifyRegisterLogged();
1543 PrintVAccess(rt_code, format, "<-", address);
1544}
1545
Jacob Bramley423e5422019-11-13 19:15:55 +00001546void Simulator::PrintWrite(int rt_code,
1547 PrintRegisterFormat format,
1548 uintptr_t address) {
1549 // Because this trace doesn't represent a change to the source register's
1550 // value, only print the relevant part of the value.
1551 format = GetPrintRegPartial(format);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001552 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001553 registers_[rt_code].NotifyRegisterLogged();
1554 PrintAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001555}
1556
Jacob Bramley423e5422019-11-13 19:15:55 +00001557void Simulator::PrintVWrite(int rt_code,
Alexandre Ramesd3832962016-07-04 15:03:43 +01001558 PrintRegisterFormat format,
Jacob Bramley423e5422019-11-13 19:15:55 +00001559 uintptr_t address) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001560 // Because this trace doesn't represent a change to the source register's
Jacob Bramley423e5422019-11-13 19:15:55 +00001561 // value, only print the relevant part of the value.
1562 format = GetPrintRegPartial(format);
Jacob Bramley7eb3e212019-11-22 17:28:05 +00001563 // It only makes sense to write scalar values here. Vectors are handled by
1564 // PrintVStructAccess.
Jacob Bramley423e5422019-11-13 19:15:55 +00001565 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
Jacob Bramley423e5422019-11-13 19:15:55 +00001566 PrintVAccess(rt_code, format, "->", address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001567}
1568
Jacob Bramleye79723a2016-06-07 17:50:47 +01001569void Simulator::PrintTakenBranch(const Instruction* target) {
1570 fprintf(stream_,
1571 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1572 clr_branch_marker,
1573 clr_normal,
1574 reinterpret_cast<uint64_t>(target));
1575}
1576
Alexandre Ramesd3832962016-07-04 15:03:43 +01001577// Visitors---------------------------------------------------------------------
1578
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001579
1580void Simulator::VisitReserved(const Instruction* instr) {
1581 // UDF is the only instruction in this group, and the Decoder is precise here.
1582 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1583
1584 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1585 reinterpret_cast<const void*>(instr),
1586 instr->GetInstructionBits());
1587 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1588}
1589
1590
Alexandre Ramesd3832962016-07-04 15:03:43 +01001591void Simulator::VisitUnimplemented(const Instruction* instr) {
1592 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1593 reinterpret_cast<const void*>(instr),
1594 instr->GetInstructionBits());
1595 VIXL_UNIMPLEMENTED();
1596}
1597
1598
1599void Simulator::VisitUnallocated(const Instruction* instr) {
1600 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1601 reinterpret_cast<const void*>(instr),
1602 instr->GetInstructionBits());
1603 VIXL_UNIMPLEMENTED();
1604}
1605
1606
1607void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1608 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1609 (instr->Mask(PCRelAddressingMask) == ADRP));
1610
1611 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1612}
1613
1614
1615void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1616 switch (instr->Mask(UnconditionalBranchMask)) {
1617 case BL:
1618 WriteLr(instr->GetNextInstruction());
1619 VIXL_FALLTHROUGH();
1620 case B:
1621 WritePc(instr->GetImmPCOffsetTarget());
1622 break;
1623 default:
1624 VIXL_UNREACHABLE();
1625 }
1626}
1627
1628
1629void Simulator::VisitConditionalBranch(const Instruction* instr) {
1630 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1631 if (ConditionPassed(instr->GetConditionBranch())) {
1632 WritePc(instr->GetImmPCOffsetTarget());
1633 }
1634}
1635
Martyn Capewellcb963f72018-10-22 15:25:28 +01001636BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1637 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1638 case BLR:
1639 case BLRAA:
1640 case BLRAB:
1641 case BLRAAZ:
1642 case BLRABZ:
1643 return BranchAndLink;
1644 case BR:
1645 case BRAA:
1646 case BRAB:
1647 case BRAAZ:
1648 case BRABZ:
1649 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1650 !PcIsInGuardedPage()) {
1651 return BranchFromUnguardedOrToIP;
1652 }
1653 return BranchFromGuardedNotToIP;
1654 }
1655 return DefaultBType;
1656}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001657
1658void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01001659 bool authenticate = false;
1660 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01001661 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01001662 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001663
1664 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1665 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01001666 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001667 VIXL_FALLTHROUGH();
1668 case BR:
1669 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01001670 break;
1671
1672 case BLRAAZ:
1673 case BLRABZ:
1674 link = true;
1675 VIXL_FALLTHROUGH();
1676 case BRAAZ:
1677 case BRABZ:
1678 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001679 break;
1680
1681 case BLRAA:
1682 case BLRAB:
1683 link = true;
1684 VIXL_FALLTHROUGH();
1685 case BRAA:
1686 case BRAB:
1687 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001688 context = ReadXRegister(instr->GetRd());
1689 break;
1690
1691 case RETAA:
1692 case RETAB:
1693 authenticate = true;
1694 addr = ReadXRegister(kLinkRegCode);
1695 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001696 break;
1697 default:
1698 VIXL_UNREACHABLE();
1699 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001700
1701 if (link) {
1702 WriteLr(instr->GetNextInstruction());
1703 }
1704
1705 if (authenticate) {
1706 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1707 addr = AuthPAC(addr, context, key, kInstructionPointer);
1708
1709 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1710 if (((addr >> error_lsb) & 0x3) != 0x0) {
1711 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1712 }
1713 }
1714
Martyn Capewellcb963f72018-10-22 15:25:28 +01001715 WritePc(Instruction::Cast(addr));
1716 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001717}
1718
1719
1720void Simulator::VisitTestBranch(const Instruction* instr) {
1721 unsigned bit_pos =
1722 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1723 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1724 bool take_branch = false;
1725 switch (instr->Mask(TestBranchMask)) {
1726 case TBZ:
1727 take_branch = bit_zero;
1728 break;
1729 case TBNZ:
1730 take_branch = !bit_zero;
1731 break;
1732 default:
1733 VIXL_UNIMPLEMENTED();
1734 }
1735 if (take_branch) {
1736 WritePc(instr->GetImmPCOffsetTarget());
1737 }
1738}
1739
1740
1741void Simulator::VisitCompareBranch(const Instruction* instr) {
1742 unsigned rt = instr->GetRt();
1743 bool take_branch = false;
1744 switch (instr->Mask(CompareBranchMask)) {
1745 case CBZ_w:
1746 take_branch = (ReadWRegister(rt) == 0);
1747 break;
1748 case CBZ_x:
1749 take_branch = (ReadXRegister(rt) == 0);
1750 break;
1751 case CBNZ_w:
1752 take_branch = (ReadWRegister(rt) != 0);
1753 break;
1754 case CBNZ_x:
1755 take_branch = (ReadXRegister(rt) != 0);
1756 break;
1757 default:
1758 VIXL_UNIMPLEMENTED();
1759 }
1760 if (take_branch) {
1761 WritePc(instr->GetImmPCOffsetTarget());
1762 }
1763}
1764
1765
1766void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1767 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1768 bool set_flags = instr->GetFlagsUpdate();
1769 int64_t new_val = 0;
1770 Instr operation = instr->Mask(AddSubOpMask);
1771
1772 switch (operation) {
1773 case ADD:
1774 case ADDS: {
1775 new_val = AddWithCarry(reg_size,
1776 set_flags,
1777 ReadRegister(reg_size,
1778 instr->GetRn(),
1779 instr->GetRnMode()),
1780 op2);
1781 break;
1782 }
1783 case SUB:
1784 case SUBS: {
1785 new_val = AddWithCarry(reg_size,
1786 set_flags,
1787 ReadRegister(reg_size,
1788 instr->GetRn(),
1789 instr->GetRnMode()),
1790 ~op2,
1791 1);
1792 break;
1793 }
1794 default:
1795 VIXL_UNREACHABLE();
1796 }
1797
1798 WriteRegister(reg_size,
1799 instr->GetRd(),
1800 new_val,
1801 LogRegWrites,
1802 instr->GetRdMode());
1803}
1804
1805
1806void Simulator::VisitAddSubShifted(const Instruction* instr) {
1807 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1808 int64_t op2 = ShiftOperand(reg_size,
1809 ReadRegister(reg_size, instr->GetRm()),
1810 static_cast<Shift>(instr->GetShiftDP()),
1811 instr->GetImmDPShift());
1812 AddSubHelper(instr, op2);
1813}
1814
1815
1816void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1817 int64_t op2 = instr->GetImmAddSub()
1818 << ((instr->GetShiftAddSub() == 1) ? 12 : 0);
1819 AddSubHelper(instr, op2);
1820}
1821
1822
1823void Simulator::VisitAddSubExtended(const Instruction* instr) {
1824 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1825 int64_t op2 = ExtendValue(reg_size,
1826 ReadRegister(reg_size, instr->GetRm()),
1827 static_cast<Extend>(instr->GetExtendMode()),
1828 instr->GetImmExtendShift());
1829 AddSubHelper(instr, op2);
1830}
1831
1832
1833void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1834 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1835 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1836 int64_t new_val;
1837
1838 if ((instr->Mask(AddSubOpMask) == SUB) ||
1839 (instr->Mask(AddSubOpMask) == SUBS)) {
1840 op2 = ~op2;
1841 }
1842
1843 new_val = AddWithCarry(reg_size,
1844 instr->GetFlagsUpdate(),
1845 ReadRegister(reg_size, instr->GetRn()),
1846 op2,
1847 ReadC());
1848
1849 WriteRegister(reg_size, instr->GetRd(), new_val);
1850}
1851
1852
Alexander Gilday2487f142018-11-05 13:07:27 +00001853void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1854 switch (instr->Mask(RotateRightIntoFlagsMask)) {
1855 case RMIF: {
1856 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1857 unsigned shift = instr->GetImmRMIFRotation();
1858 unsigned mask = instr->GetNzcv();
1859 uint64_t rotated = RotateRight(value, shift, kXRegSize);
1860
1861 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1862 break;
1863 }
1864 }
1865}
1866
1867
1868void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1869 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1870 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1871
1872 unsigned sign_bit = (value >> msb) & 1;
1873 unsigned overflow_bit = (value >> (msb + 1)) & 1;
1874 ReadNzcv().SetN(sign_bit);
1875 ReadNzcv().SetZ((value << (31 - msb)) == 0);
1876 ReadNzcv().SetV(sign_bit ^ overflow_bit);
1877}
1878
1879
Alexandre Ramesd3832962016-07-04 15:03:43 +01001880void Simulator::VisitLogicalShifted(const Instruction* instr) {
1881 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1882 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1883 unsigned shift_amount = instr->GetImmDPShift();
1884 int64_t op2 = ShiftOperand(reg_size,
1885 ReadRegister(reg_size, instr->GetRm()),
1886 shift_type,
1887 shift_amount);
1888 if (instr->Mask(NOT) == NOT) {
1889 op2 = ~op2;
1890 }
1891 LogicalHelper(instr, op2);
1892}
1893
1894
1895void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1896 LogicalHelper(instr, instr->GetImmLogical());
1897}
1898
1899
1900void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1901 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1902 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1903 int64_t result = 0;
1904 bool update_flags = false;
1905
1906 // Switch on the logical operation, stripping out the NOT bit, as it has a
1907 // different meaning for logical immediate instructions.
1908 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1909 case ANDS:
1910 update_flags = true;
1911 VIXL_FALLTHROUGH();
1912 case AND:
1913 result = op1 & op2;
1914 break;
1915 case ORR:
1916 result = op1 | op2;
1917 break;
1918 case EOR:
1919 result = op1 ^ op2;
1920 break;
1921 default:
1922 VIXL_UNIMPLEMENTED();
1923 }
1924
1925 if (update_flags) {
1926 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1927 ReadNzcv().SetZ(CalcZFlag(result));
1928 ReadNzcv().SetC(0);
1929 ReadNzcv().SetV(0);
1930 LogSystemRegister(NZCV);
1931 }
1932
1933 WriteRegister(reg_size,
1934 instr->GetRd(),
1935 result,
1936 LogRegWrites,
1937 instr->GetRdMode());
1938}
1939
1940
1941void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1942 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1943 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1944}
1945
1946
1947void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1948 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1949}
1950
1951
1952void Simulator::ConditionalCompareHelper(const Instruction* instr,
1953 int64_t op2) {
1954 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1955 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1956
1957 if (ConditionPassed(instr->GetCondition())) {
1958 // If the condition passes, set the status flags to the result of comparing
1959 // the operands.
1960 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1961 AddWithCarry(reg_size, true, op1, ~op2, 1);
1962 } else {
1963 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1964 AddWithCarry(reg_size, true, op1, op2, 0);
1965 }
1966 } else {
1967 // If the condition fails, set the status flags to the nzcv immediate.
1968 ReadNzcv().SetFlags(instr->GetNzcv());
1969 LogSystemRegister(NZCV);
1970 }
1971}
1972
1973
1974void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1975 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1976 LoadStoreHelper(instr, offset, Offset);
1977}
1978
1979
1980void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1981 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1982}
1983
1984
1985void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1986 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1987}
1988
1989
1990void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1991 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1992}
1993
1994
Alexander Gilday311edf22018-10-29 13:41:41 +00001995template <typename T1, typename T2>
1996void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1997 unsigned rt = instr->GetRt();
1998 unsigned rn = instr->GetRn();
1999
2000 unsigned element_size = sizeof(T2);
2001 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2002 int offset = instr->GetImmLS();
2003 address += offset;
2004
2005 // Verify that the address is available to the host.
2006 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2007
2008 // Check the alignment of `address`.
2009 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2010 VIXL_ALIGNMENT_EXCEPTION();
2011 }
2012
2013 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
2014
2015 // Approximate load-acquire by issuing a full barrier after the load.
2016 __sync_synchronize();
2017
Jacob Bramley423e5422019-11-13 19:15:55 +00002018 LogRead(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00002019}
2020
2021
2022template <typename T>
2023void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
2024 unsigned rt = instr->GetRt();
2025 unsigned rn = instr->GetRn();
2026
2027 unsigned element_size = sizeof(T);
2028 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2029 int offset = instr->GetImmLS();
2030 address += offset;
2031
2032 // Verify that the address is available to the host.
2033 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2034
2035 // Check the alignment of `address`.
2036 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2037 VIXL_ALIGNMENT_EXCEPTION();
2038 }
2039
2040 // Approximate store-release by issuing a full barrier after the load.
2041 __sync_synchronize();
2042
2043 Memory::Write<T>(address, ReadRegister<T>(rt));
2044
Jacob Bramley423e5422019-11-13 19:15:55 +00002045 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
Alexander Gilday311edf22018-10-29 13:41:41 +00002046}
2047
2048
2049void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
2050 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
2051 case LDAPURB:
2052 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
2053 break;
2054 case LDAPURH:
2055 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
2056 break;
2057 case LDAPUR_w:
2058 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
2059 break;
2060 case LDAPUR_x:
2061 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
2062 break;
2063 case LDAPURSB_w:
2064 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
2065 break;
2066 case LDAPURSB_x:
2067 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
2068 break;
2069 case LDAPURSH_w:
2070 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
2071 break;
2072 case LDAPURSH_x:
2073 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
2074 break;
2075 case LDAPURSW:
2076 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
2077 break;
2078 case STLURB:
2079 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
2080 break;
2081 case STLURH:
2082 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
2083 break;
2084 case STLUR_w:
2085 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
2086 break;
2087 case STLUR_x:
2088 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
2089 break;
2090 }
2091}
2092
2093
Alexander Gilday75605592018-11-01 09:30:29 +00002094void Simulator::VisitLoadStorePAC(const Instruction* instr) {
2095 unsigned dst = instr->GetRt();
2096 unsigned addr_reg = instr->GetRn();
2097
2098 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2099
2100 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
2101 address = AuthPAC(address, 0, key, kDataPointer);
2102
2103 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
2104 if (((address >> error_lsb) & 0x3) != 0x0) {
2105 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
2106 }
2107
2108
2109 if ((addr_reg == 31) && ((address % 16) != 0)) {
2110 // When the base register is SP the stack pointer is required to be
2111 // quadword aligned prior to the address calculation and write-backs.
2112 // Misalignment will cause a stack alignment fault.
2113 VIXL_ALIGNMENT_EXCEPTION();
2114 }
2115
2116 int64_t offset = instr->GetImmLSPAC();
2117 address += offset;
2118
2119 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
2120 // Pre-index mode.
2121 VIXL_ASSERT(offset != 0);
2122 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
2123 }
2124
2125 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
2126
2127 // Verify that the calculated address is available to the host.
2128 VIXL_ASSERT(address == addr_ptr);
2129
2130 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
2131 unsigned access_size = 1 << 3;
Jacob Bramley423e5422019-11-13 19:15:55 +00002132 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
Alexander Gilday75605592018-11-01 09:30:29 +00002133}
2134
2135
Alexandre Ramesd3832962016-07-04 15:03:43 +01002136void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
2137 Extend ext = static_cast<Extend>(instr->GetExtendMode());
2138 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
2139 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
2140
2141 int64_t offset =
2142 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
2143 LoadStoreHelper(instr, offset, Offset);
2144}
2145
2146
2147void Simulator::LoadStoreHelper(const Instruction* instr,
2148 int64_t offset,
2149 AddrMode addrmode) {
2150 unsigned srcdst = instr->GetRt();
2151 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2152
Jacob Bramley423e5422019-11-13 19:15:55 +00002153 bool rt_is_vreg = false;
2154 int extend_to_size = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002155 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
2156 switch (op) {
2157 case LDRB_w:
2158 WriteWRegister(srcdst, Memory::Read<uint8_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 LDRH_w:
2162 WriteWRegister(srcdst, Memory::Read<uint16_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_w:
2166 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002167 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002168 break;
2169 case LDR_x:
2170 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002171 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002172 break;
2173 case LDRSB_w:
2174 WriteWRegister(srcdst, Memory::Read<int8_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 LDRSH_w:
2178 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002179 extend_to_size = kWRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002180 break;
2181 case LDRSB_x:
2182 WriteXRegister(srcdst, Memory::Read<int8_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 LDRSH_x:
2186 WriteXRegister(srcdst, Memory::Read<int16_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 LDRSW_x:
2190 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002191 extend_to_size = kXRegSizeInBytes;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002192 break;
2193 case LDR_b:
2194 WriteBRegister(srcdst, Memory::Read<uint8_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_h:
2198 WriteHRegister(srcdst, Memory::Read<uint16_t>(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_s:
2202 WriteSRegister(srcdst, Memory::Read<float>(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_d:
2206 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002207 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002208 break;
2209 case LDR_q:
2210 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002211 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002212 break;
2213
2214 case STRB_w:
2215 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
2216 break;
2217 case STRH_w:
2218 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
2219 break;
2220 case STR_w:
2221 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
2222 break;
2223 case STR_x:
2224 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
2225 break;
2226 case STR_b:
2227 Memory::Write<uint8_t>(address, ReadBRegister(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_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01002231 Memory::Write<uint16_t>(address, ReadHRegisterBits(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_s:
2235 Memory::Write<float>(address, ReadSRegister(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_d:
2239 Memory::Write<double>(address, ReadDRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002240 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002241 break;
2242 case STR_q:
2243 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
Jacob Bramley423e5422019-11-13 19:15:55 +00002244 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002245 break;
2246
2247 // Ignore prfm hint instructions.
2248 case PRFM:
2249 break;
2250
2251 default:
2252 VIXL_UNIMPLEMENTED();
2253 }
2254
Jacob Bramley423e5422019-11-13 19:15:55 +00002255 // Print a detailed trace (including the memory address).
2256 bool extend = (extend_to_size != 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002257 unsigned access_size = 1 << instr->GetSizeLS();
Jacob Bramley423e5422019-11-13 19:15:55 +00002258 unsigned result_size = extend ? extend_to_size : access_size;
2259 PrintRegisterFormat print_format =
2260 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2261 : GetPrintRegisterFormatForSize(result_size);
2262
Alexandre Ramesd3832962016-07-04 15:03:43 +01002263 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002264 if (rt_is_vreg) {
2265 LogVRead(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002266 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002267 LogExtendingRead(srcdst, print_format, access_size, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002268 }
2269 } else if (instr->IsStore()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002270 if (rt_is_vreg) {
2271 LogVWrite(srcdst, print_format, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002272 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002273 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002274 }
2275 } else {
2276 VIXL_ASSERT(op == PRFM);
2277 }
2278
2279 local_monitor_.MaybeClear();
2280}
2281
2282
2283void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
2284 LoadStorePairHelper(instr, Offset);
2285}
2286
2287
2288void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
2289 LoadStorePairHelper(instr, PreIndex);
2290}
2291
2292
2293void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
2294 LoadStorePairHelper(instr, PostIndex);
2295}
2296
2297
2298void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
2299 LoadStorePairHelper(instr, Offset);
2300}
2301
2302
2303void Simulator::LoadStorePairHelper(const Instruction* instr,
2304 AddrMode addrmode) {
2305 unsigned rt = instr->GetRt();
2306 unsigned rt2 = instr->GetRt2();
2307 int element_size = 1 << instr->GetSizeLSPair();
2308 int64_t offset = instr->GetImmLSPair() * element_size;
2309 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2310 uintptr_t address2 = address + element_size;
2311
2312 LoadStorePairOp op =
2313 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
2314
2315 // 'rt' and 'rt2' can only be aliased for stores.
2316 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2317
Jacob Bramley423e5422019-11-13 19:15:55 +00002318 bool rt_is_vreg = false;
2319 bool sign_extend = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002320 switch (op) {
2321 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
2322 // will print a more detailed log.
2323 case LDP_w: {
2324 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2325 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
2326 break;
2327 }
2328 case LDP_s: {
2329 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2330 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002331 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002332 break;
2333 }
2334 case LDP_x: {
2335 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2336 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
2337 break;
2338 }
2339 case LDP_d: {
2340 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2341 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002342 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002343 break;
2344 }
2345 case LDP_q: {
2346 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2347 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002348 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002349 break;
2350 }
2351 case LDPSW_x: {
2352 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2353 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002354 sign_extend = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002355 break;
2356 }
2357 case STP_w: {
2358 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2359 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
2360 break;
2361 }
2362 case STP_s: {
2363 Memory::Write<float>(address, ReadSRegister(rt));
2364 Memory::Write<float>(address2, ReadSRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002365 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002366 break;
2367 }
2368 case STP_x: {
2369 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2370 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
2371 break;
2372 }
2373 case STP_d: {
2374 Memory::Write<double>(address, ReadDRegister(rt));
2375 Memory::Write<double>(address2, ReadDRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002376 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002377 break;
2378 }
2379 case STP_q: {
2380 Memory::Write<qreg_t>(address, ReadQRegister(rt));
2381 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
Jacob Bramley423e5422019-11-13 19:15:55 +00002382 rt_is_vreg = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002383 break;
2384 }
2385 default:
2386 VIXL_UNREACHABLE();
2387 }
2388
Jacob Bramley423e5422019-11-13 19:15:55 +00002389 // Print a detailed trace (including the memory address).
2390 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
2391 PrintRegisterFormat print_format =
2392 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2393 : GetPrintRegisterFormatForSize(result_size);
2394
Alexandre Ramesd3832962016-07-04 15:03:43 +01002395 if (instr->IsLoad()) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002396 if (rt_is_vreg) {
2397 LogVRead(rt, print_format, address);
2398 LogVRead(rt2, print_format, address2);
2399 } else if (sign_extend) {
2400 LogExtendingRead(rt, print_format, element_size, address);
2401 LogExtendingRead(rt2, print_format, element_size, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002402 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002403 LogRead(rt, print_format, address);
2404 LogRead(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002405 }
2406 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002407 if (rt_is_vreg) {
2408 LogVWrite(rt, print_format, address);
2409 LogVWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002410 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00002411 LogWrite(rt, print_format, address);
2412 LogWrite(rt2, print_format, address2);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002413 }
2414 }
2415
2416 local_monitor_.MaybeClear();
2417}
2418
2419
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002420template <typename T>
2421void Simulator::CompareAndSwapHelper(const Instruction* instr) {
2422 unsigned rs = instr->GetRs();
2423 unsigned rt = instr->GetRt();
2424 unsigned rn = instr->GetRn();
2425
2426 unsigned element_size = sizeof(T);
2427 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2428
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002429 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2430
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002431 bool is_acquire = instr->ExtractBit(22) == 1;
2432 bool is_release = instr->ExtractBit(15) == 1;
2433
2434 T comparevalue = ReadRegister<T>(rs);
2435 T newvalue = ReadRegister<T>(rt);
2436
2437 // The architecture permits that the data read clears any exclusive monitors
2438 // associated with that location, even if the compare subsequently fails.
2439 local_monitor_.Clear();
2440
2441 T data = Memory::Read<T>(address);
2442 if (is_acquire) {
2443 // Approximate load-acquire by issuing a full barrier after the load.
2444 __sync_synchronize();
2445 }
2446
2447 if (data == comparevalue) {
2448 if (is_release) {
2449 // Approximate store-release by issuing a full barrier before the store.
2450 __sync_synchronize();
2451 }
2452 Memory::Write<T>(address, newvalue);
Jacob Bramley423e5422019-11-13 19:15:55 +00002453 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002454 }
2455 WriteRegister<T>(rs, data);
Jacob Bramley423e5422019-11-13 19:15:55 +00002456 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002457}
2458
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002459
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002460template <typename T>
2461void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
2462 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
2463 unsigned rs = instr->GetRs();
2464 unsigned rt = instr->GetRt();
2465 unsigned rn = instr->GetRn();
2466
2467 VIXL_ASSERT((rs % 2 == 0) && (rs % 2 == 0));
2468
2469 unsigned element_size = sizeof(T);
2470 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002471
2472 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
2473
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002474 uint64_t address2 = address + element_size;
2475
2476 bool is_acquire = instr->ExtractBit(22) == 1;
2477 bool is_release = instr->ExtractBit(15) == 1;
2478
2479 T comparevalue_high = ReadRegister<T>(rs + 1);
2480 T comparevalue_low = ReadRegister<T>(rs);
2481 T newvalue_high = ReadRegister<T>(rt + 1);
2482 T newvalue_low = ReadRegister<T>(rt);
2483
2484 // The architecture permits that the data read clears any exclusive monitors
2485 // associated with that location, even if the compare subsequently fails.
2486 local_monitor_.Clear();
2487
2488 T data_high = Memory::Read<T>(address);
2489 T data_low = Memory::Read<T>(address2);
2490
2491 if (is_acquire) {
2492 // Approximate load-acquire by issuing a full barrier after the load.
2493 __sync_synchronize();
2494 }
2495
2496 bool same =
2497 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2498 if (same) {
2499 if (is_release) {
2500 // Approximate store-release by issuing a full barrier before the store.
2501 __sync_synchronize();
2502 }
2503
2504 Memory::Write<T>(address, newvalue_high);
2505 Memory::Write<T>(address2, newvalue_low);
2506 }
2507
2508 WriteRegister<T>(rs + 1, data_high);
2509 WriteRegister<T>(rs, data_low);
2510
Jacob Bramley423e5422019-11-13 19:15:55 +00002511 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2512 LogRead(rs + 1, format, address);
2513 LogRead(rs, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002514
2515 if (same) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002516 LogWrite(rt + 1, format, address);
2517 LogWrite(rt, format, address2);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002518 }
2519}
2520
Jacob Bramley85a9c102019-12-09 17:48:29 +00002521bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
2522 // To simulate fault-tolerant loads, we need to know what host addresses we
2523 // can access without generating a real fault. One way to do that is to
2524 // attempt to `write()` the memory to a dummy pipe[1]. This is more portable
2525 // and less intrusive than using (global) signal handlers.
2526 //
2527 // [1]: https://stackoverflow.com/questions/7134590
2528
2529 size_t written = 0;
2530 bool can_read = true;
2531 // `write` will normally return after one invocation, but it is allowed to
2532 // handle only part of the operation, so wrap it in a loop.
2533 while (can_read && (written < size)) {
2534 ssize_t result = write(dummy_pipe_fd_[1],
2535 reinterpret_cast<void*>(address + written),
2536 size - written);
2537 if (result > 0) {
2538 written += result;
2539 } else {
2540 switch (result) {
2541 case -EPERM:
2542 case -EFAULT:
2543 // The address range is not accessible.
2544 // `write` is supposed to return -EFAULT in this case, but in practice
2545 // it seems to return -EPERM, so we accept that too.
2546 can_read = false;
2547 break;
2548 case -EINTR:
2549 // The call was interrupted by a signal. Just try again.
2550 break;
2551 default:
2552 // Any other error is fatal.
2553 VIXL_ABORT();
2554 }
2555 }
2556 }
2557 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
2558 // the dummy data is buffered. As before, we expect to drain the whole write
2559 // in one invocation, but cannot guarantee that, so we wrap it in a loop. This
2560 // function is primarily intended to implement SVE fault-tolerant loads, so
2561 // the maximum Z register size is a good default buffer size.
2562 char buffer[kZRegMaxSizeInBytes];
2563 while (written > 0) {
2564 ssize_t result = read(dummy_pipe_fd_[0],
2565 reinterpret_cast<void*>(buffer),
2566 sizeof(buffer));
2567 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
2568 // we've read everything that was written, so treat 0 as an error.
2569 if (result > 0) {
2570 VIXL_ASSERT(static_cast<size_t>(result) <= written);
2571 written -= result;
2572 } else {
2573 // For -EINTR, just try again. We can't handle any other error.
2574 VIXL_CHECK(result == -EINTR);
2575 }
2576 }
2577
2578 return can_read;
2579}
Alexandre Ramesd3832962016-07-04 15:03:43 +01002580
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002581void Simulator::PrintExclusiveAccessWarning() {
2582 if (print_exclusive_access_warning_) {
2583 fprintf(stderr,
2584 "%sWARNING:%s VIXL simulator support for "
2585 "load-/store-/clear-exclusive "
2586 "instructions is limited. Refer to the README for details.%s\n",
2587 clr_warning,
2588 clr_warning_message,
2589 clr_normal);
2590 print_exclusive_access_warning_ = false;
2591 }
2592}
2593
Alexandre Ramesd3832962016-07-04 15:03:43 +01002594void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002595 LoadStoreExclusive op =
2596 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
2597
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002598 switch (op) {
2599 case CAS_w:
2600 case CASA_w:
2601 case CASL_w:
2602 case CASAL_w:
2603 CompareAndSwapHelper<uint32_t>(instr);
2604 break;
2605 case CAS_x:
2606 case CASA_x:
2607 case CASL_x:
2608 case CASAL_x:
2609 CompareAndSwapHelper<uint64_t>(instr);
2610 break;
2611 case CASB:
2612 case CASAB:
2613 case CASLB:
2614 case CASALB:
2615 CompareAndSwapHelper<uint8_t>(instr);
2616 break;
2617 case CASH:
2618 case CASAH:
2619 case CASLH:
2620 case CASALH:
2621 CompareAndSwapHelper<uint16_t>(instr);
2622 break;
2623 case CASP_w:
2624 case CASPA_w:
2625 case CASPL_w:
2626 case CASPAL_w:
2627 CompareAndSwapPairHelper<uint32_t>(instr);
2628 break;
2629 case CASP_x:
2630 case CASPA_x:
2631 case CASPL_x:
2632 case CASPAL_x:
2633 CompareAndSwapPairHelper<uint64_t>(instr);
2634 break;
2635 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002636 PrintExclusiveAccessWarning();
2637
2638 unsigned rs = instr->GetRs();
2639 unsigned rt = instr->GetRt();
2640 unsigned rt2 = instr->GetRt2();
2641 unsigned rn = instr->GetRn();
2642
2643 bool is_exclusive = !instr->GetLdStXNotExclusive();
2644 bool is_acquire_release =
2645 !is_exclusive || instr->GetLdStXAcquireRelease();
2646 bool is_load = instr->GetLdStXLoad();
2647 bool is_pair = instr->GetLdStXPair();
2648
2649 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2650 unsigned access_size = is_pair ? element_size * 2 : element_size;
2651 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2652
2653 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2654
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002655 if (is_load) {
2656 if (is_exclusive) {
2657 local_monitor_.MarkExclusive(address, access_size);
2658 } else {
2659 // Any non-exclusive load can clear the local monitor as a side
2660 // effect. We don't need to do this, but it is useful to stress the
2661 // simulated code.
2662 local_monitor_.Clear();
2663 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002664
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002665 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2666 // We will print a more detailed log.
Jacob Bramley423e5422019-11-13 19:15:55 +00002667 unsigned reg_size = 0;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002668 switch (op) {
2669 case LDXRB_w:
2670 case LDAXRB_w:
2671 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002672 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002673 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002674 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002675 break;
2676 case LDXRH_w:
2677 case LDAXRH_w:
2678 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002679 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002680 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002681 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002682 break;
2683 case LDXR_w:
2684 case LDAXR_w:
2685 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002686 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002687 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002688 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002689 break;
2690 case LDXR_x:
2691 case LDAXR_x:
2692 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002693 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002694 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002695 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002696 break;
2697 case LDXP_w:
2698 case LDAXP_w:
2699 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2700 WriteWRegister(rt2,
2701 Memory::Read<uint32_t>(address + element_size),
2702 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002703 reg_size = kWRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002704 break;
2705 case LDXP_x:
2706 case LDAXP_x:
2707 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2708 WriteXRegister(rt2,
2709 Memory::Read<uint64_t>(address + element_size),
2710 NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00002711 reg_size = kXRegSizeInBytes;
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002712 break;
2713 default:
2714 VIXL_UNREACHABLE();
2715 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002716
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002717 if (is_acquire_release) {
2718 // Approximate load-acquire by issuing a full barrier after the load.
2719 __sync_synchronize();
2720 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002721
Jacob Bramley423e5422019-11-13 19:15:55 +00002722 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
2723 LogExtendingRead(rt, format, element_size, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002724 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002725 LogExtendingRead(rt2, format, element_size, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002726 }
2727 } else {
2728 if (is_acquire_release) {
2729 // Approximate store-release by issuing a full barrier before the
2730 // store.
2731 __sync_synchronize();
2732 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002733
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002734 bool do_store = true;
2735 if (is_exclusive) {
2736 do_store = local_monitor_.IsExclusive(address, access_size) &&
2737 global_monitor_.IsExclusive(address, access_size);
2738 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002739
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002740 // - All exclusive stores explicitly clear the local monitor.
2741 local_monitor_.Clear();
2742 } else {
2743 // - Any other store can clear the local monitor as a side effect.
2744 local_monitor_.MaybeClear();
2745 }
2746
2747 if (do_store) {
2748 switch (op) {
2749 case STXRB_w:
2750 case STLXRB_w:
2751 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002752 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002753 Memory::Write<uint8_t>(address, ReadWRegister(rt));
2754 break;
2755 case STXRH_w:
2756 case STLXRH_w:
2757 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002758 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002759 Memory::Write<uint16_t>(address, ReadWRegister(rt));
2760 break;
2761 case STXR_w:
2762 case STLXR_w:
2763 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002764 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002765 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2766 break;
2767 case STXR_x:
2768 case STLXR_x:
2769 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002770 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002771 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2772 break;
2773 case STXP_w:
2774 case STLXP_w:
2775 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2776 Memory::Write<uint32_t>(address + element_size,
2777 ReadWRegister(rt2));
2778 break;
2779 case STXP_x:
2780 case STLXP_x:
2781 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2782 Memory::Write<uint64_t>(address + element_size,
2783 ReadXRegister(rt2));
2784 break;
2785 default:
2786 VIXL_UNREACHABLE();
2787 }
2788
Jacob Bramley423e5422019-11-13 19:15:55 +00002789 PrintRegisterFormat format =
2790 GetPrintRegisterFormatForSize(element_size);
2791 LogWrite(rt, format, address);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002792 if (is_pair) {
Jacob Bramley423e5422019-11-13 19:15:55 +00002793 LogWrite(rt2, format, address + element_size);
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002794 }
2795 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002796 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002797 }
2798}
2799
Jacob Bramleyca789742018-09-13 14:25:46 +01002800template <typename T>
2801void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2802 unsigned rs = instr->GetRs();
2803 unsigned rt = instr->GetRt();
2804 unsigned rn = instr->GetRn();
2805
2806 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2807 bool is_release = instr->ExtractBit(22) == 1;
2808
2809 unsigned element_size = sizeof(T);
2810 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2811
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002812 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002813
2814 T value = ReadRegister<T>(rs);
2815
2816 T data = Memory::Read<T>(address);
2817
2818 if (is_acquire) {
2819 // Approximate load-acquire by issuing a full barrier after the load.
2820 __sync_synchronize();
2821 }
2822
2823 T result = 0;
2824 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2825 case LDADDOp:
2826 result = data + value;
2827 break;
2828 case LDCLROp:
2829 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2830 result = data & ~value;
2831 break;
2832 case LDEOROp:
2833 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2834 result = data ^ value;
2835 break;
2836 case LDSETOp:
2837 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2838 result = data | value;
2839 break;
2840
2841 // Signed/Unsigned difference is done via the templated type T.
2842 case LDSMAXOp:
2843 case LDUMAXOp:
2844 result = (data > value) ? data : value;
2845 break;
2846 case LDSMINOp:
2847 case LDUMINOp:
2848 result = (data > value) ? value : data;
2849 break;
2850 }
2851
2852 if (is_release) {
2853 // Approximate store-release by issuing a full barrier before the store.
2854 __sync_synchronize();
2855 }
2856
2857 Memory::Write<T>(address, result);
2858 WriteRegister<T>(rt, data, NoRegLog);
2859
Jacob Bramley423e5422019-11-13 19:15:55 +00002860 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2861 LogRead(rt, format, address);
2862 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002863}
2864
2865template <typename T>
2866void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2867 unsigned rs = instr->GetRs();
2868 unsigned rt = instr->GetRt();
2869 unsigned rn = instr->GetRn();
2870
2871 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2872 bool is_release = instr->ExtractBit(22) == 1;
2873
2874 unsigned element_size = sizeof(T);
2875 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2876
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002877 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002878
2879 T data = Memory::Read<T>(address);
2880 if (is_acquire) {
2881 // Approximate load-acquire by issuing a full barrier after the load.
2882 __sync_synchronize();
2883 }
2884
2885 if (is_release) {
2886 // Approximate store-release by issuing a full barrier before the store.
2887 __sync_synchronize();
2888 }
2889 Memory::Write<T>(address, ReadRegister<T>(rs));
2890
2891 WriteRegister<T>(rt, data);
2892
Jacob Bramley423e5422019-11-13 19:15:55 +00002893 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2894 LogRead(rt, format, address);
2895 LogWrite(rs, format, address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002896}
2897
2898template <typename T>
2899void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2900 unsigned rt = instr->GetRt();
2901 unsigned rn = instr->GetRn();
2902
2903 unsigned element_size = sizeof(T);
2904 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2905
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002906 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2907
Jacob Bramleyca789742018-09-13 14:25:46 +01002908 WriteRegister<T>(rt, Memory::Read<T>(address));
2909
2910 // Approximate load-acquire by issuing a full barrier after the load.
2911 __sync_synchronize();
2912
Jacob Bramley423e5422019-11-13 19:15:55 +00002913 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
Jacob Bramleyca789742018-09-13 14:25:46 +01002914}
2915
2916#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2917 V(LDADD) \
2918 V(LDCLR) \
2919 V(LDEOR) \
2920 V(LDSET) \
2921 V(LDUMAX) \
2922 V(LDUMIN)
2923
2924#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2925 V(LDSMAX) \
2926 V(LDSMIN)
2927
2928void Simulator::VisitAtomicMemory(const Instruction* instr) {
2929 switch (instr->Mask(AtomicMemoryMask)) {
2930// clang-format off
2931#define SIM_FUNC_B(A) \
2932 case A##B: \
2933 case A##AB: \
2934 case A##LB: \
2935 case A##ALB:
2936#define SIM_FUNC_H(A) \
2937 case A##H: \
2938 case A##AH: \
2939 case A##LH: \
2940 case A##ALH:
2941#define SIM_FUNC_w(A) \
2942 case A##_w: \
2943 case A##A_w: \
2944 case A##L_w: \
2945 case A##AL_w:
2946#define SIM_FUNC_x(A) \
2947 case A##_x: \
2948 case A##A_x: \
2949 case A##L_x: \
2950 case A##AL_x:
2951
2952 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2953 AtomicMemorySimpleHelper<uint8_t>(instr);
2954 break;
2955 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2956 AtomicMemorySimpleHelper<int8_t>(instr);
2957 break;
2958 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2959 AtomicMemorySimpleHelper<uint16_t>(instr);
2960 break;
2961 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2962 AtomicMemorySimpleHelper<int16_t>(instr);
2963 break;
2964 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2965 AtomicMemorySimpleHelper<uint32_t>(instr);
2966 break;
2967 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2968 AtomicMemorySimpleHelper<int32_t>(instr);
2969 break;
2970 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2971 AtomicMemorySimpleHelper<uint64_t>(instr);
2972 break;
2973 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2974 AtomicMemorySimpleHelper<int64_t>(instr);
2975 break;
2976 // clang-format on
2977
2978 case SWPB:
2979 case SWPAB:
2980 case SWPLB:
2981 case SWPALB:
2982 AtomicMemorySwapHelper<uint8_t>(instr);
2983 break;
2984 case SWPH:
2985 case SWPAH:
2986 case SWPLH:
2987 case SWPALH:
2988 AtomicMemorySwapHelper<uint16_t>(instr);
2989 break;
2990 case SWP_w:
2991 case SWPA_w:
2992 case SWPL_w:
2993 case SWPAL_w:
2994 AtomicMemorySwapHelper<uint32_t>(instr);
2995 break;
2996 case SWP_x:
2997 case SWPA_x:
2998 case SWPL_x:
2999 case SWPAL_x:
3000 AtomicMemorySwapHelper<uint64_t>(instr);
3001 break;
3002 case LDAPRB:
3003 LoadAcquireRCpcHelper<uint8_t>(instr);
3004 break;
3005 case LDAPRH:
3006 LoadAcquireRCpcHelper<uint16_t>(instr);
3007 break;
3008 case LDAPR_w:
3009 LoadAcquireRCpcHelper<uint32_t>(instr);
3010 break;
3011 case LDAPR_x:
3012 LoadAcquireRCpcHelper<uint64_t>(instr);
3013 break;
3014 }
3015}
3016
Alexandre Ramesd3832962016-07-04 15:03:43 +01003017
3018void Simulator::VisitLoadLiteral(const Instruction* instr) {
3019 unsigned rt = instr->GetRt();
3020 uint64_t address = instr->GetLiteralAddress<uint64_t>();
3021
3022 // Verify that the calculated address is available to the host.
3023 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3024
3025 switch (instr->Mask(LoadLiteralMask)) {
3026 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
3027 // print a more detailed log.
3028 case LDR_w_lit:
3029 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003030 LogRead(rt, kPrintWReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003031 break;
3032 case LDR_x_lit:
3033 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003034 LogRead(rt, kPrintXReg, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003035 break;
3036 case LDR_s_lit:
3037 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003038 LogVRead(rt, kPrintSRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003039 break;
3040 case LDR_d_lit:
3041 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003042 LogVRead(rt, kPrintDRegFP, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003043 break;
3044 case LDR_q_lit:
3045 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003046 LogVRead(rt, kPrintReg1Q, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003047 break;
3048 case LDRSW_x_lit:
3049 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
Jacob Bramley423e5422019-11-13 19:15:55 +00003050 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003051 break;
3052
3053 // Ignore prfm hint instructions.
3054 case PRFM_lit:
3055 break;
3056
3057 default:
3058 VIXL_UNREACHABLE();
3059 }
3060
3061 local_monitor_.MaybeClear();
3062}
3063
3064
3065uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
3066 int64_t offset,
3067 AddrMode addrmode) {
3068 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
3069
3070 if ((addr_reg == 31) && ((address % 16) != 0)) {
3071 // When the base register is SP the stack pointer is required to be
3072 // quadword aligned prior to the address calculation and write-backs.
3073 // Misalignment will cause a stack alignment fault.
3074 VIXL_ALIGNMENT_EXCEPTION();
3075 }
3076
3077 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
3078 VIXL_ASSERT(offset != 0);
3079 // Only preindex should log the register update here. For Postindex, the
3080 // update will be printed automatically by LogWrittenRegisters _after_ the
3081 // memory access itself is logged.
3082 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
3083 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
3084 }
3085
3086 if ((addrmode == Offset) || (addrmode == PreIndex)) {
3087 address += offset;
3088 }
3089
3090 // Verify that the calculated address is available to the host.
3091 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3092
3093 return static_cast<uintptr_t>(address);
3094}
3095
3096
3097void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
3098 MoveWideImmediateOp mov_op =
3099 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
3100 int64_t new_xn_val = 0;
3101
3102 bool is_64_bits = instr->GetSixtyFourBits() == 1;
3103 // Shift is limited for W operations.
3104 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
3105
3106 // Get the shifted immediate.
3107 int64_t shift = instr->GetShiftMoveWide() * 16;
3108 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
3109 << shift;
3110
3111 // Compute the new value.
3112 switch (mov_op) {
3113 case MOVN_w:
3114 case MOVN_x: {
3115 new_xn_val = ~shifted_imm16;
3116 if (!is_64_bits) new_xn_val &= kWRegMask;
3117 break;
3118 }
3119 case MOVK_w:
3120 case MOVK_x: {
3121 unsigned reg_code = instr->GetRd();
3122 int64_t prev_xn_val =
3123 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
3124 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
3125 break;
3126 }
3127 case MOVZ_w:
3128 case MOVZ_x: {
3129 new_xn_val = shifted_imm16;
3130 break;
3131 }
3132 default:
3133 VIXL_UNREACHABLE();
3134 }
3135
3136 // Update the destination register.
3137 WriteXRegister(instr->GetRd(), new_xn_val);
3138}
3139
3140
3141void Simulator::VisitConditionalSelect(const Instruction* instr) {
3142 uint64_t new_val = ReadXRegister(instr->GetRn());
3143
3144 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
3145 new_val = ReadXRegister(instr->GetRm());
3146 switch (instr->Mask(ConditionalSelectMask)) {
3147 case CSEL_w:
3148 case CSEL_x:
3149 break;
3150 case CSINC_w:
3151 case CSINC_x:
3152 new_val++;
3153 break;
3154 case CSINV_w:
3155 case CSINV_x:
3156 new_val = ~new_val;
3157 break;
3158 case CSNEG_w:
3159 case CSNEG_x:
3160 new_val = -new_val;
3161 break;
3162 default:
3163 VIXL_UNIMPLEMENTED();
3164 }
3165 }
3166 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3167 WriteRegister(reg_size, instr->GetRd(), new_val);
3168}
3169
3170
Jacob Bramleyca789742018-09-13 14:25:46 +01003171// clang-format off
3172#define PAUTH_MODES(V) \
3173 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
3174 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
3175 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
3176 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
3177 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
3178 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
3179 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
3180 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
3181// clang-format on
3182
Alexandre Ramesd3832962016-07-04 15:03:43 +01003183void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
3184 unsigned dst = instr->GetRd();
3185 unsigned src = instr->GetRn();
3186
3187 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003188#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
3189 case PAC##SUFFIX: { \
3190 uint64_t ptr = ReadXRegister(dst); \
3191 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
3192 break; \
3193 } \
3194 case AUT##SUFFIX: { \
3195 uint64_t ptr = ReadXRegister(dst); \
3196 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
3197 break; \
3198 }
3199
3200 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
3201#undef DEFINE_PAUTH_FUNCS
3202
3203 case XPACI:
3204 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
3205 break;
3206 case XPACD:
3207 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
3208 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003209 case RBIT_w:
3210 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
3211 break;
3212 case RBIT_x:
3213 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
3214 break;
3215 case REV16_w:
3216 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
3217 break;
3218 case REV16_x:
3219 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
3220 break;
3221 case REV_w:
3222 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
3223 break;
3224 case REV32_x:
3225 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
3226 break;
3227 case REV_x:
3228 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
3229 break;
3230 case CLZ_w:
3231 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
3232 break;
3233 case CLZ_x:
3234 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
3235 break;
3236 case CLS_w:
3237 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
3238 break;
3239 case CLS_x:
3240 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
3241 break;
3242 default:
3243 VIXL_UNIMPLEMENTED();
3244 }
3245}
3246
3247
3248uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
3249 VIXL_ASSERT((n > 32) && (n <= 64));
3250 for (unsigned i = (n - 1); i >= 32; i--) {
3251 if (((data >> i) & 1) != 0) {
3252 uint64_t polysh32 = (uint64_t)poly << (i - 32);
3253 uint64_t mask = (UINT64_C(1) << i) - 1;
3254 data = ((data & mask) ^ polysh32);
3255 }
3256 }
3257 return data & 0xffffffff;
3258}
3259
3260
3261template <typename T>
3262uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
3263 unsigned size = sizeof(val) * 8; // Number of bits in type T.
3264 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
3265 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
3266 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
3267 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
3268}
3269
3270
3271uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
3272 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
3273 // the CRC of each 32-bit word sequentially.
3274 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
3275 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
3276}
3277
3278
3279void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
3280 Shift shift_op = NO_SHIFT;
3281 int64_t result = 0;
3282 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3283
3284 switch (instr->Mask(DataProcessing2SourceMask)) {
3285 case SDIV_w: {
3286 int32_t rn = ReadWRegister(instr->GetRn());
3287 int32_t rm = ReadWRegister(instr->GetRm());
3288 if ((rn == kWMinInt) && (rm == -1)) {
3289 result = kWMinInt;
3290 } else if (rm == 0) {
3291 // Division by zero can be trapped, but not on A-class processors.
3292 result = 0;
3293 } else {
3294 result = rn / rm;
3295 }
3296 break;
3297 }
3298 case SDIV_x: {
3299 int64_t rn = ReadXRegister(instr->GetRn());
3300 int64_t rm = ReadXRegister(instr->GetRm());
3301 if ((rn == kXMinInt) && (rm == -1)) {
3302 result = kXMinInt;
3303 } else if (rm == 0) {
3304 // Division by zero can be trapped, but not on A-class processors.
3305 result = 0;
3306 } else {
3307 result = rn / rm;
3308 }
3309 break;
3310 }
3311 case UDIV_w: {
3312 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
3313 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
3314 if (rm == 0) {
3315 // Division by zero can be trapped, but not on A-class processors.
3316 result = 0;
3317 } else {
3318 result = rn / rm;
3319 }
3320 break;
3321 }
3322 case UDIV_x: {
3323 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3324 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
3325 if (rm == 0) {
3326 // Division by zero can be trapped, but not on A-class processors.
3327 result = 0;
3328 } else {
3329 result = rn / rm;
3330 }
3331 break;
3332 }
3333 case LSLV_w:
3334 case LSLV_x:
3335 shift_op = LSL;
3336 break;
3337 case LSRV_w:
3338 case LSRV_x:
3339 shift_op = LSR;
3340 break;
3341 case ASRV_w:
3342 case ASRV_x:
3343 shift_op = ASR;
3344 break;
3345 case RORV_w:
3346 case RORV_x:
3347 shift_op = ROR;
3348 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003349 case PACGA: {
3350 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3351 uint64_t src = static_cast<uint64_t>(
3352 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
3353 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
3354 result = code & 0xffffffff00000000;
3355 break;
3356 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003357 case CRC32B: {
3358 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3359 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3360 result = Crc32Checksum(acc, val, CRC32_POLY);
3361 break;
3362 }
3363 case CRC32H: {
3364 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3365 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3366 result = Crc32Checksum(acc, val, CRC32_POLY);
3367 break;
3368 }
3369 case CRC32W: {
3370 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3371 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3372 result = Crc32Checksum(acc, val, CRC32_POLY);
3373 break;
3374 }
3375 case CRC32X: {
3376 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3377 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3378 result = Crc32Checksum(acc, val, CRC32_POLY);
3379 reg_size = kWRegSize;
3380 break;
3381 }
3382 case CRC32CB: {
3383 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3384 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3385 result = Crc32Checksum(acc, val, CRC32C_POLY);
3386 break;
3387 }
3388 case CRC32CH: {
3389 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3390 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3391 result = Crc32Checksum(acc, val, CRC32C_POLY);
3392 break;
3393 }
3394 case CRC32CW: {
3395 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3396 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3397 result = Crc32Checksum(acc, val, CRC32C_POLY);
3398 break;
3399 }
3400 case CRC32CX: {
3401 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3402 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3403 result = Crc32Checksum(acc, val, CRC32C_POLY);
3404 reg_size = kWRegSize;
3405 break;
3406 }
3407 default:
3408 VIXL_UNIMPLEMENTED();
3409 }
3410
3411 if (shift_op != NO_SHIFT) {
3412 // Shift distance encoded in the least-significant five/six bits of the
3413 // register.
3414 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
3415 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
3416 result = ShiftOperand(reg_size,
3417 ReadRegister(reg_size, instr->GetRn()),
3418 shift_op,
3419 shift);
3420 }
3421 WriteRegister(reg_size, instr->GetRd(), result);
3422}
3423
3424
Alexandre Ramesd3832962016-07-04 15:03:43 +01003425void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
3426 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3427
3428 uint64_t result = 0;
3429 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
3430 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
3431 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
3432 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
3433 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003434 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
3435 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003436 switch (instr->Mask(DataProcessing3SourceMask)) {
3437 case MADD_w:
3438 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003439 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003440 break;
3441 case MSUB_w:
3442 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003443 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003444 break;
3445 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003446 result = ReadXRegister(instr->GetRa()) +
3447 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003448 break;
3449 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003450 result = ReadXRegister(instr->GetRa()) -
3451 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003452 break;
3453 case UMADDL_x:
3454 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
3455 break;
3456 case UMSUBL_x:
3457 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
3458 break;
3459 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003460 result =
3461 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
3462 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003463 break;
3464 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003465 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
3466 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003467 break;
3468 default:
3469 VIXL_UNIMPLEMENTED();
3470 }
3471 WriteRegister(reg_size, instr->GetRd(), result);
3472}
3473
3474
3475void Simulator::VisitBitfield(const Instruction* instr) {
3476 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3477 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003478 int R = instr->GetImmR();
3479 int S = instr->GetImmS();
3480 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003481 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003482 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003483 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003484 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003485 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003486 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003487 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003488 diff += reg_size;
3489 }
3490
3491 // inzero indicates if the extracted bitfield is inserted into the
3492 // destination register value or in zero.
3493 // If extend is true, extend the sign of the extracted bitfield.
3494 bool inzero = false;
3495 bool extend = false;
3496 switch (instr->Mask(BitfieldMask)) {
3497 case BFM_x:
3498 case BFM_w:
3499 break;
3500 case SBFM_x:
3501 case SBFM_w:
3502 inzero = true;
3503 extend = true;
3504 break;
3505 case UBFM_x:
3506 case UBFM_w:
3507 inzero = true;
3508 break;
3509 default:
3510 VIXL_UNIMPLEMENTED();
3511 }
3512
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003513 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
3514 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003515 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003516 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003517 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003518 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
3519 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003520
3521 // Merge sign extension, dest/zero and bitfield.
3522 result = signbits | (result & mask) | (dst & ~mask);
3523
3524 WriteRegister(reg_size, instr->GetRd(), result);
3525}
3526
3527
3528void Simulator::VisitExtract(const Instruction* instr) {
3529 unsigned lsb = instr->GetImmS();
3530 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3531 uint64_t low_res =
3532 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003533 uint64_t high_res =
3534 (lsb == 0) ? 0 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
3535 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003536 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
3537}
3538
3539
3540void Simulator::VisitFPImmediate(const Instruction* instr) {
3541 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01003542 unsigned dest = instr->GetRd();
3543 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003544 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01003545 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01003546 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003547 case FMOV_s_imm:
3548 WriteSRegister(dest, instr->GetImmFP32());
3549 break;
3550 case FMOV_d_imm:
3551 WriteDRegister(dest, instr->GetImmFP64());
3552 break;
3553 default:
3554 VIXL_UNREACHABLE();
3555 }
3556}
3557
3558
3559void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
3560 AssertSupportedFPCR();
3561
3562 unsigned dst = instr->GetRd();
3563 unsigned src = instr->GetRn();
3564
3565 FPRounding round = ReadRMode();
3566
3567 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003568 case FCVTAS_wh:
3569 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
3570 break;
3571 case FCVTAS_xh:
3572 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
3573 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003574 case FCVTAS_ws:
3575 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
3576 break;
3577 case FCVTAS_xs:
3578 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
3579 break;
3580 case FCVTAS_wd:
3581 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
3582 break;
3583 case FCVTAS_xd:
3584 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
3585 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003586 case FCVTAU_wh:
3587 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
3588 break;
3589 case FCVTAU_xh:
3590 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
3591 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003592 case FCVTAU_ws:
3593 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3594 break;
3595 case FCVTAU_xs:
3596 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3597 break;
3598 case FCVTAU_wd:
3599 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3600 break;
3601 case FCVTAU_xd:
3602 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3603 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003604 case FCVTMS_wh:
3605 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3606 break;
3607 case FCVTMS_xh:
3608 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3609 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003610 case FCVTMS_ws:
3611 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3612 break;
3613 case FCVTMS_xs:
3614 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3615 break;
3616 case FCVTMS_wd:
3617 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3618 break;
3619 case FCVTMS_xd:
3620 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3621 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003622 case FCVTMU_wh:
3623 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3624 break;
3625 case FCVTMU_xh:
3626 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3627 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003628 case FCVTMU_ws:
3629 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3630 break;
3631 case FCVTMU_xs:
3632 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3633 break;
3634 case FCVTMU_wd:
3635 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3636 break;
3637 case FCVTMU_xd:
3638 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3639 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003640 case FCVTPS_wh:
3641 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3642 break;
3643 case FCVTPS_xh:
3644 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3645 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003646 case FCVTPS_ws:
3647 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3648 break;
3649 case FCVTPS_xs:
3650 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3651 break;
3652 case FCVTPS_wd:
3653 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3654 break;
3655 case FCVTPS_xd:
3656 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3657 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003658 case FCVTPU_wh:
3659 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3660 break;
3661 case FCVTPU_xh:
3662 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3663 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003664 case FCVTPU_ws:
3665 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3666 break;
3667 case FCVTPU_xs:
3668 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3669 break;
3670 case FCVTPU_wd:
3671 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3672 break;
3673 case FCVTPU_xd:
3674 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3675 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003676 case FCVTNS_wh:
3677 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3678 break;
3679 case FCVTNS_xh:
3680 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3681 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003682 case FCVTNS_ws:
3683 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3684 break;
3685 case FCVTNS_xs:
3686 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3687 break;
3688 case FCVTNS_wd:
3689 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3690 break;
3691 case FCVTNS_xd:
3692 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3693 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003694 case FCVTNU_wh:
3695 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3696 break;
3697 case FCVTNU_xh:
3698 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3699 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003700 case FCVTNU_ws:
3701 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3702 break;
3703 case FCVTNU_xs:
3704 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3705 break;
3706 case FCVTNU_wd:
3707 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3708 break;
3709 case FCVTNU_xd:
3710 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3711 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003712 case FCVTZS_wh:
3713 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3714 break;
3715 case FCVTZS_xh:
3716 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3717 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003718 case FCVTZS_ws:
3719 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3720 break;
3721 case FCVTZS_xs:
3722 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3723 break;
3724 case FCVTZS_wd:
3725 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3726 break;
3727 case FCVTZS_xd:
3728 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3729 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003730 case FCVTZU_wh:
3731 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3732 break;
3733 case FCVTZU_xh:
3734 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3735 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003736 case FCVTZU_ws:
3737 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3738 break;
3739 case FCVTZU_xs:
3740 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3741 break;
3742 case FCVTZU_wd:
3743 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3744 break;
3745 case FCVTZU_xd:
3746 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3747 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003748 case FJCVTZS:
3749 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3750 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003751 case FMOV_hw:
3752 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3753 break;
3754 case FMOV_wh:
3755 WriteWRegister(dst, ReadHRegisterBits(src));
3756 break;
3757 case FMOV_xh:
3758 WriteXRegister(dst, ReadHRegisterBits(src));
3759 break;
3760 case FMOV_hx:
3761 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3762 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003763 case FMOV_ws:
3764 WriteWRegister(dst, ReadSRegisterBits(src));
3765 break;
3766 case FMOV_xd:
3767 WriteXRegister(dst, ReadDRegisterBits(src));
3768 break;
3769 case FMOV_sw:
3770 WriteSRegisterBits(dst, ReadWRegister(src));
3771 break;
3772 case FMOV_dx:
3773 WriteDRegisterBits(dst, ReadXRegister(src));
3774 break;
3775 case FMOV_d1_x:
3776 LogicVRegister(ReadVRegister(dst))
3777 .SetUint(kFormatD, 1, ReadXRegister(src));
3778 break;
3779 case FMOV_x_d1:
3780 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3781 break;
3782
3783 // A 32-bit input can be handled in the same way as a 64-bit input, since
3784 // the sign- or zero-extension will not affect the conversion.
3785 case SCVTF_dx:
3786 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3787 break;
3788 case SCVTF_dw:
3789 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3790 break;
3791 case UCVTF_dx:
3792 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3793 break;
3794 case UCVTF_dw: {
3795 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003796 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003797 break;
3798 }
3799 case SCVTF_sx:
3800 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3801 break;
3802 case SCVTF_sw:
3803 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3804 break;
3805 case UCVTF_sx:
3806 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3807 break;
3808 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01003809 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3810 break;
3811 }
3812 case SCVTF_hx:
3813 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3814 break;
3815 case SCVTF_hw:
3816 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3817 break;
3818 case UCVTF_hx:
3819 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3820 break;
3821 case UCVTF_hw: {
3822 WriteHRegister(dst,
3823 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003824 break;
3825 }
3826
3827 default:
3828 VIXL_UNREACHABLE();
3829 }
3830}
3831
3832
3833void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3834 AssertSupportedFPCR();
3835
3836 unsigned dst = instr->GetRd();
3837 unsigned src = instr->GetRn();
3838 int fbits = 64 - instr->GetFPScale();
3839
3840 FPRounding round = ReadRMode();
3841
3842 switch (instr->Mask(FPFixedPointConvertMask)) {
3843 // A 32-bit input can be handled in the same way as a 64-bit input, since
3844 // the sign- or zero-extension will not affect the conversion.
3845 case SCVTF_dx_fixed:
3846 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3847 break;
3848 case SCVTF_dw_fixed:
3849 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3850 break;
3851 case UCVTF_dx_fixed:
3852 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3853 break;
3854 case UCVTF_dw_fixed: {
3855 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003856 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003857 break;
3858 }
3859 case SCVTF_sx_fixed:
3860 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3861 break;
3862 case SCVTF_sw_fixed:
3863 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3864 break;
3865 case UCVTF_sx_fixed:
3866 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3867 break;
3868 case UCVTF_sw_fixed: {
3869 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003870 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3871 break;
3872 }
3873 case SCVTF_hx_fixed:
3874 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3875 break;
3876 case SCVTF_hw_fixed:
3877 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3878 break;
3879 case UCVTF_hx_fixed:
3880 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3881 break;
3882 case UCVTF_hw_fixed: {
3883 WriteHRegister(dst,
3884 UFixedToFloat16(ReadRegister<uint32_t>(src),
3885 fbits,
3886 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003887 break;
3888 }
3889 case FCVTZS_xd_fixed:
3890 WriteXRegister(dst,
3891 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3892 FPZero));
3893 break;
3894 case FCVTZS_wd_fixed:
3895 WriteWRegister(dst,
3896 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3897 FPZero));
3898 break;
3899 case FCVTZU_xd_fixed:
3900 WriteXRegister(dst,
3901 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3902 FPZero));
3903 break;
3904 case FCVTZU_wd_fixed:
3905 WriteWRegister(dst,
3906 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3907 FPZero));
3908 break;
3909 case FCVTZS_xs_fixed:
3910 WriteXRegister(dst,
3911 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3912 FPZero));
3913 break;
3914 case FCVTZS_ws_fixed:
3915 WriteWRegister(dst,
3916 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3917 FPZero));
3918 break;
3919 case FCVTZU_xs_fixed:
3920 WriteXRegister(dst,
3921 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3922 FPZero));
3923 break;
3924 case FCVTZU_ws_fixed:
3925 WriteWRegister(dst,
3926 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3927 FPZero));
3928 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003929 case FCVTZS_xh_fixed: {
3930 double output =
3931 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3932 WriteXRegister(dst, FPToInt64(output, FPZero));
3933 break;
3934 }
3935 case FCVTZS_wh_fixed: {
3936 double output =
3937 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3938 WriteWRegister(dst, FPToInt32(output, FPZero));
3939 break;
3940 }
3941 case FCVTZU_xh_fixed: {
3942 double output =
3943 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3944 WriteXRegister(dst, FPToUInt64(output, FPZero));
3945 break;
3946 }
3947 case FCVTZU_wh_fixed: {
3948 double output =
3949 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3950 WriteWRegister(dst, FPToUInt32(output, FPZero));
3951 break;
3952 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003953 default:
3954 VIXL_UNREACHABLE();
3955 }
3956}
3957
3958
3959void Simulator::VisitFPCompare(const Instruction* instr) {
3960 AssertSupportedFPCR();
3961
3962 FPTrapFlags trap = DisableTrap;
3963 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003964 case FCMPE_h:
3965 trap = EnableTrap;
3966 VIXL_FALLTHROUGH();
3967 case FCMP_h:
3968 FPCompare(ReadHRegister(instr->GetRn()),
3969 ReadHRegister(instr->GetRm()),
3970 trap);
3971 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003972 case FCMPE_s:
3973 trap = EnableTrap;
3974 VIXL_FALLTHROUGH();
3975 case FCMP_s:
3976 FPCompare(ReadSRegister(instr->GetRn()),
3977 ReadSRegister(instr->GetRm()),
3978 trap);
3979 break;
3980 case FCMPE_d:
3981 trap = EnableTrap;
3982 VIXL_FALLTHROUGH();
3983 case FCMP_d:
3984 FPCompare(ReadDRegister(instr->GetRn()),
3985 ReadDRegister(instr->GetRm()),
3986 trap);
3987 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003988 case FCMPE_h_zero:
3989 trap = EnableTrap;
3990 VIXL_FALLTHROUGH();
3991 case FCMP_h_zero:
3992 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3993 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003994 case FCMPE_s_zero:
3995 trap = EnableTrap;
3996 VIXL_FALLTHROUGH();
3997 case FCMP_s_zero:
3998 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3999 break;
4000 case FCMPE_d_zero:
4001 trap = EnableTrap;
4002 VIXL_FALLTHROUGH();
4003 case FCMP_d_zero:
4004 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
4005 break;
4006 default:
4007 VIXL_UNIMPLEMENTED();
4008 }
4009}
4010
4011
4012void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
4013 AssertSupportedFPCR();
4014
4015 FPTrapFlags trap = DisableTrap;
4016 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004017 case FCCMPE_h:
4018 trap = EnableTrap;
4019 VIXL_FALLTHROUGH();
4020 case FCCMP_h:
4021 if (ConditionPassed(instr->GetCondition())) {
4022 FPCompare(ReadHRegister(instr->GetRn()),
4023 ReadHRegister(instr->GetRm()),
4024 trap);
4025 } else {
4026 ReadNzcv().SetFlags(instr->GetNzcv());
4027 LogSystemRegister(NZCV);
4028 }
4029 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004030 case FCCMPE_s:
4031 trap = EnableTrap;
4032 VIXL_FALLTHROUGH();
4033 case FCCMP_s:
4034 if (ConditionPassed(instr->GetCondition())) {
4035 FPCompare(ReadSRegister(instr->GetRn()),
4036 ReadSRegister(instr->GetRm()),
4037 trap);
4038 } else {
4039 ReadNzcv().SetFlags(instr->GetNzcv());
4040 LogSystemRegister(NZCV);
4041 }
4042 break;
4043 case FCCMPE_d:
4044 trap = EnableTrap;
4045 VIXL_FALLTHROUGH();
4046 case FCCMP_d:
4047 if (ConditionPassed(instr->GetCondition())) {
4048 FPCompare(ReadDRegister(instr->GetRn()),
4049 ReadDRegister(instr->GetRm()),
4050 trap);
4051 } else {
4052 ReadNzcv().SetFlags(instr->GetNzcv());
4053 LogSystemRegister(NZCV);
4054 }
4055 break;
4056 default:
4057 VIXL_UNIMPLEMENTED();
4058 }
4059}
4060
4061
4062void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
4063 AssertSupportedFPCR();
4064
4065 Instr selected;
4066 if (ConditionPassed(instr->GetCondition())) {
4067 selected = instr->GetRn();
4068 } else {
4069 selected = instr->GetRm();
4070 }
4071
4072 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004073 case FCSEL_h:
4074 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
4075 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004076 case FCSEL_s:
4077 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
4078 break;
4079 case FCSEL_d:
4080 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
4081 break;
4082 default:
4083 VIXL_UNIMPLEMENTED();
4084 }
4085}
4086
4087
4088void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
4089 AssertSupportedFPCR();
4090
4091 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01004092 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01004093 switch (instr->Mask(FPTypeMask)) {
4094 default:
4095 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4096 case FP64:
4097 vform = kFormatD;
4098 break;
4099 case FP32:
4100 vform = kFormatS;
4101 break;
4102 case FP16:
4103 vform = kFormatH;
4104 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004105 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004106
Alexandre Ramesd3832962016-07-04 15:03:43 +01004107 SimVRegister& rd = ReadVRegister(instr->GetRd());
4108 SimVRegister& rn = ReadVRegister(instr->GetRn());
4109 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004110 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004111
4112 unsigned fd = instr->GetRd();
4113 unsigned fn = instr->GetRn();
4114
4115 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01004116 case FMOV_h:
4117 WriteHRegister(fd, ReadHRegister(fn));
4118 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004119 case FMOV_s:
4120 WriteSRegister(fd, ReadSRegister(fn));
4121 return;
4122 case FMOV_d:
4123 WriteDRegister(fd, ReadDRegister(fn));
4124 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004125 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004126 case FABS_s:
4127 case FABS_d:
4128 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
4129 // Explicitly log the register update whilst we have type information.
4130 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4131 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004132 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004133 case FNEG_s:
4134 case FNEG_d:
4135 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
4136 // Explicitly log the register update whilst we have type information.
4137 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4138 return;
4139 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01004140 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004141 return;
4142 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01004143 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004144 return;
4145 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01004146 WriteHRegister(fd,
4147 Float16ToRawbits(
4148 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004149 return;
4150 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01004151 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004152 return;
4153 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01004154 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004155 return;
4156 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01004157 WriteHRegister(fd,
4158 Float16ToRawbits(
4159 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004160 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01004161 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004162 case FSQRT_s:
4163 case FSQRT_d:
4164 fsqrt(vform, rd, rn);
4165 // Explicitly log the register update whilst we have type information.
4166 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4167 return;
TatWai Chong04471812019-03-19 14:29:00 -07004168 case FRINT32X_s:
4169 case FRINT32X_d:
4170 inexact_exception = true;
4171 frint_mode = kFrintToInt32;
4172 break; // Use FPCR rounding mode.
4173 case FRINT64X_s:
4174 case FRINT64X_d:
4175 inexact_exception = true;
4176 frint_mode = kFrintToInt64;
4177 break; // Use FPCR rounding mode.
4178 case FRINT32Z_s:
4179 case FRINT32Z_d:
4180 inexact_exception = true;
4181 frint_mode = kFrintToInt32;
4182 fpcr_rounding = FPZero;
4183 break;
4184 case FRINT64Z_s:
4185 case FRINT64Z_d:
4186 inexact_exception = true;
4187 frint_mode = kFrintToInt64;
4188 fpcr_rounding = FPZero;
4189 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004190 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004191 case FRINTI_s:
4192 case FRINTI_d:
4193 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01004194 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004195 case FRINTX_s:
4196 case FRINTX_d:
4197 inexact_exception = true;
4198 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004199 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004200 case FRINTA_s:
4201 case FRINTA_d:
4202 fpcr_rounding = FPTieAway;
4203 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004204 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004205 case FRINTM_s:
4206 case FRINTM_d:
4207 fpcr_rounding = FPNegativeInfinity;
4208 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004209 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004210 case FRINTN_s:
4211 case FRINTN_d:
4212 fpcr_rounding = FPTieEven;
4213 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004214 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004215 case FRINTP_s:
4216 case FRINTP_d:
4217 fpcr_rounding = FPPositiveInfinity;
4218 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004219 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004220 case FRINTZ_s:
4221 case FRINTZ_d:
4222 fpcr_rounding = FPZero;
4223 break;
4224 default:
4225 VIXL_UNIMPLEMENTED();
4226 }
4227
4228 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004229 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004230 // Explicitly log the register update whilst we have type information.
4231 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4232}
4233
4234
4235void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
4236 AssertSupportedFPCR();
4237
Carey Williamsd8bb3572018-04-10 11:58:07 +01004238 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01004239 switch (instr->Mask(FPTypeMask)) {
4240 default:
4241 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4242 case FP64:
4243 vform = kFormatD;
4244 break;
4245 case FP32:
4246 vform = kFormatS;
4247 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004248 case FP16:
4249 vform = kFormatH;
4250 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004251 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004252 SimVRegister& rd = ReadVRegister(instr->GetRd());
4253 SimVRegister& rn = ReadVRegister(instr->GetRn());
4254 SimVRegister& rm = ReadVRegister(instr->GetRm());
4255
4256 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004257 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004258 case FADD_s:
4259 case FADD_d:
4260 fadd(vform, rd, rn, rm);
4261 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004262 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004263 case FSUB_s:
4264 case FSUB_d:
4265 fsub(vform, rd, rn, rm);
4266 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004267 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004268 case FMUL_s:
4269 case FMUL_d:
4270 fmul(vform, rd, rn, rm);
4271 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004272 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004273 case FNMUL_s:
4274 case FNMUL_d:
4275 fnmul(vform, rd, rn, rm);
4276 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004277 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004278 case FDIV_s:
4279 case FDIV_d:
4280 fdiv(vform, rd, rn, rm);
4281 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004282 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004283 case FMAX_s:
4284 case FMAX_d:
4285 fmax(vform, rd, rn, rm);
4286 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004287 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004288 case FMIN_s:
4289 case FMIN_d:
4290 fmin(vform, rd, rn, rm);
4291 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004292 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004293 case FMAXNM_s:
4294 case FMAXNM_d:
4295 fmaxnm(vform, rd, rn, rm);
4296 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004297 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004298 case FMINNM_s:
4299 case FMINNM_d:
4300 fminnm(vform, rd, rn, rm);
4301 break;
4302 default:
4303 VIXL_UNREACHABLE();
4304 }
4305 // Explicitly log the register update whilst we have type information.
4306 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
4307}
4308
4309
4310void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
4311 AssertSupportedFPCR();
4312
4313 unsigned fd = instr->GetRd();
4314 unsigned fn = instr->GetRn();
4315 unsigned fm = instr->GetRm();
4316 unsigned fa = instr->GetRa();
4317
4318 switch (instr->Mask(FPDataProcessing3SourceMask)) {
4319 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01004320 case FMADD_h:
4321 WriteHRegister(fd,
4322 FPMulAdd(ReadHRegister(fa),
4323 ReadHRegister(fn),
4324 ReadHRegister(fm)));
4325 break;
4326 case FMSUB_h:
4327 WriteHRegister(fd,
4328 FPMulAdd(ReadHRegister(fa),
4329 -ReadHRegister(fn),
4330 ReadHRegister(fm)));
4331 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004332 case FMADD_s:
4333 WriteSRegister(fd,
4334 FPMulAdd(ReadSRegister(fa),
4335 ReadSRegister(fn),
4336 ReadSRegister(fm)));
4337 break;
4338 case FMSUB_s:
4339 WriteSRegister(fd,
4340 FPMulAdd(ReadSRegister(fa),
4341 -ReadSRegister(fn),
4342 ReadSRegister(fm)));
4343 break;
4344 case FMADD_d:
4345 WriteDRegister(fd,
4346 FPMulAdd(ReadDRegister(fa),
4347 ReadDRegister(fn),
4348 ReadDRegister(fm)));
4349 break;
4350 case FMSUB_d:
4351 WriteDRegister(fd,
4352 FPMulAdd(ReadDRegister(fa),
4353 -ReadDRegister(fn),
4354 ReadDRegister(fm)));
4355 break;
4356 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01004357 case FNMADD_h:
4358 WriteHRegister(fd,
4359 FPMulAdd(-ReadHRegister(fa),
4360 -ReadHRegister(fn),
4361 ReadHRegister(fm)));
4362 break;
4363 case FNMSUB_h:
4364 WriteHRegister(fd,
4365 FPMulAdd(-ReadHRegister(fa),
4366 ReadHRegister(fn),
4367 ReadHRegister(fm)));
4368 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004369 case FNMADD_s:
4370 WriteSRegister(fd,
4371 FPMulAdd(-ReadSRegister(fa),
4372 -ReadSRegister(fn),
4373 ReadSRegister(fm)));
4374 break;
4375 case FNMSUB_s:
4376 WriteSRegister(fd,
4377 FPMulAdd(-ReadSRegister(fa),
4378 ReadSRegister(fn),
4379 ReadSRegister(fm)));
4380 break;
4381 case FNMADD_d:
4382 WriteDRegister(fd,
4383 FPMulAdd(-ReadDRegister(fa),
4384 -ReadDRegister(fn),
4385 ReadDRegister(fm)));
4386 break;
4387 case FNMSUB_d:
4388 WriteDRegister(fd,
4389 FPMulAdd(-ReadDRegister(fa),
4390 ReadDRegister(fn),
4391 ReadDRegister(fm)));
4392 break;
4393 default:
4394 VIXL_UNIMPLEMENTED();
4395 }
4396}
4397
4398
4399bool Simulator::FPProcessNaNs(const Instruction* instr) {
4400 unsigned fd = instr->GetRd();
4401 unsigned fn = instr->GetRn();
4402 unsigned fm = instr->GetRm();
4403 bool done = false;
4404
4405 if (instr->Mask(FP64) == FP64) {
4406 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004407 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004408 WriteDRegister(fd, result);
4409 done = true;
4410 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004411 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004412 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004413 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004414 WriteSRegister(fd, result);
4415 done = true;
4416 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004417 } else {
4418 VIXL_ASSERT(instr->Mask(FP16) == FP16);
4419 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01004420 }
4421
4422 return done;
4423}
4424
4425
4426void Simulator::SysOp_W(int op, int64_t val) {
4427 switch (op) {
4428 case IVAU:
4429 case CVAC:
4430 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01004431 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08004432 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004433 case CIVAC: {
4434 // Perform a dummy memory access to ensure that we have read access
4435 // to the specified address.
4436 volatile uint8_t y = Memory::Read<uint8_t>(val);
4437 USE(y);
4438 // TODO: Implement "case ZVA:".
4439 break;
4440 }
4441 default:
4442 VIXL_UNIMPLEMENTED();
4443 }
4444}
4445
4446
Jacob Bramleyca789742018-09-13 14:25:46 +01004447// clang-format off
4448#define PAUTH_SYSTEM_MODES(V) \
4449 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
4450 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
4451 V(AZ, 30, 0x00000000, kPACKeyIA) \
4452 V(BZ, 30, 0x00000000, kPACKeyIB) \
4453 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
4454 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
4455// clang-format on
4456
4457
Alexandre Ramesd3832962016-07-04 15:03:43 +01004458void Simulator::VisitSystem(const Instruction* instr) {
4459 // Some system instructions hijack their Op and Cp fields to represent a
4460 // range of immediates instead of indicating a different instruction. This
4461 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01004462 if (instr->GetInstructionBits() == XPACLRI) {
4463 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00004464 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
4465 switch (instr->Mask(SystemPStateMask)) {
4466 case CFINV:
4467 ReadNzcv().SetC(!ReadC());
4468 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00004469 case AXFLAG:
4470 ReadNzcv().SetN(0);
4471 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
4472 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
4473 ReadNzcv().SetV(0);
4474 break;
4475 case XAFLAG: {
4476 // Can't set the flags in place due to the logical dependencies.
4477 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
4478 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
4479 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
4480 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
4481 ReadNzcv().SetN(n);
4482 ReadNzcv().SetZ(z);
4483 ReadNzcv().SetC(c);
4484 ReadNzcv().SetV(v);
4485 break;
4486 }
Alexander Gilday2487f142018-11-05 13:07:27 +00004487 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004488 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004489 // Check BType allows PACI[AB]SP instructions.
4490 if (PcIsInGuardedPage()) {
4491 Instr i = instr->Mask(SystemPAuthMask);
4492 if ((i == PACIASP) || (i == PACIBSP)) {
4493 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004494 case BranchFromGuardedNotToIP:
4495 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
4496 // assume here to be zero. This allows execution of PACI[AB]SP when
4497 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00004498 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004499 case BranchFromUnguardedOrToIP:
4500 case BranchAndLink:
4501 break;
4502 }
4503 }
4504 }
4505
Jacob Bramleyca789742018-09-13 14:25:46 +01004506 switch (instr->Mask(SystemPAuthMask)) {
4507#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
4508 case PACI##SUFFIX: \
4509 WriteXRegister(DST, \
4510 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
4511 break; \
4512 case AUTI##SUFFIX: \
4513 WriteXRegister(DST, \
4514 AuthPAC(ReadXRegister(DST), \
4515 MOD, \
4516 KEY, \
4517 kInstructionPointer)); \
4518 break;
4519
4520 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
4521#undef DEFINE_PAUTH_FUNCS
4522 }
4523 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
4524 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004525 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
4526 switch (instr->Mask(SystemExclusiveMonitorMask)) {
4527 case CLREX: {
4528 PrintExclusiveAccessWarning();
4529 ClearLocalMonitor();
4530 break;
4531 }
4532 }
4533 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
4534 switch (instr->Mask(SystemSysRegMask)) {
4535 case MRS: {
4536 switch (instr->GetImmSystemRegister()) {
4537 case NZCV:
4538 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
4539 break;
4540 case FPCR:
4541 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
4542 break;
TatWai Chong04edf682018-12-27 16:01:02 -08004543 case RNDR:
4544 case RNDRRS: {
Jacob Bramley85a9c102019-12-09 17:48:29 +00004545 uint64_t high = jrand48(rand_state_);
4546 uint64_t low = jrand48(rand_state_);
TatWai Chong04edf682018-12-27 16:01:02 -08004547 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
4548 WriteXRegister(instr->GetRt(), rand_num);
4549 // Simulate successful random number generation.
4550 // TODO: Return failure occasionally as a random number cannot be
4551 // returned in a period of time.
4552 ReadNzcv().SetRawValue(NoFlag);
4553 LogSystemRegister(NZCV);
4554 break;
4555 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004556 default:
4557 VIXL_UNIMPLEMENTED();
4558 }
4559 break;
4560 }
4561 case MSR: {
4562 switch (instr->GetImmSystemRegister()) {
4563 case NZCV:
4564 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
4565 LogSystemRegister(NZCV);
4566 break;
4567 case FPCR:
4568 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
4569 LogSystemRegister(FPCR);
4570 break;
4571 default:
4572 VIXL_UNIMPLEMENTED();
4573 }
4574 break;
4575 }
4576 }
4577 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
4578 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
4579 switch (instr->GetImmHint()) {
4580 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01004581 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00004582 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004583 case BTI_jc:
4584 break;
4585 case BTI:
4586 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
4587 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
4588 }
4589 break;
4590 case BTI_c:
4591 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
4592 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
4593 }
4594 break;
4595 case BTI_j:
4596 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4597 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4598 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004599 break;
4600 default:
4601 VIXL_UNIMPLEMENTED();
4602 }
4603 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4604 __sync_synchronize();
4605 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4606 switch (instr->Mask(SystemSysMask)) {
4607 case SYS:
4608 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4609 break;
4610 default:
4611 VIXL_UNIMPLEMENTED();
4612 }
4613 } else {
4614 VIXL_UNIMPLEMENTED();
4615 }
4616}
4617
4618
4619void Simulator::VisitException(const Instruction* instr) {
4620 switch (instr->Mask(ExceptionMask)) {
4621 case HLT:
4622 switch (instr->GetImmException()) {
4623 case kUnreachableOpcode:
4624 DoUnreachable(instr);
4625 return;
4626 case kTraceOpcode:
4627 DoTrace(instr);
4628 return;
4629 case kLogOpcode:
4630 DoLog(instr);
4631 return;
4632 case kPrintfOpcode:
4633 DoPrintf(instr);
4634 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01004635 case kRuntimeCallOpcode:
4636 DoRuntimeCall(instr);
4637 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01004638 case kSetCPUFeaturesOpcode:
4639 case kEnableCPUFeaturesOpcode:
4640 case kDisableCPUFeaturesOpcode:
4641 DoConfigureCPUFeatures(instr);
4642 return;
4643 case kSaveCPUFeaturesOpcode:
4644 DoSaveCPUFeatures(instr);
4645 return;
4646 case kRestoreCPUFeaturesOpcode:
4647 DoRestoreCPUFeatures(instr);
4648 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004649 default:
4650 HostBreakpoint();
4651 return;
4652 }
4653 case BRK:
4654 HostBreakpoint();
4655 return;
4656 default:
4657 VIXL_UNIMPLEMENTED();
4658 }
4659}
4660
4661
4662void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4663 VisitUnimplemented(instr);
4664}
4665
4666
4667void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4668 VisitUnimplemented(instr);
4669}
4670
4671
4672void Simulator::VisitCryptoAES(const Instruction* instr) {
4673 VisitUnimplemented(instr);
4674}
4675
4676
4677void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4678 NEONFormatDecoder nfd(instr);
4679 VectorFormat vf = nfd.GetVectorFormat();
4680
4681 static const NEONFormatMap map_lp =
4682 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4683 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4684
4685 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4686 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4687
4688 static const NEONFormatMap map_fcvtn = {{22, 30},
4689 {NF_4H, NF_8H, NF_2S, NF_4S}};
4690 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4691
4692 SimVRegister& rd = ReadVRegister(instr->GetRd());
4693 SimVRegister& rn = ReadVRegister(instr->GetRn());
4694
4695 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4696 // These instructions all use a two bit size field, except NOT and RBIT,
4697 // which use the field to encode the operation.
4698 switch (instr->Mask(NEON2RegMiscMask)) {
4699 case NEON_REV64:
4700 rev64(vf, rd, rn);
4701 break;
4702 case NEON_REV32:
4703 rev32(vf, rd, rn);
4704 break;
4705 case NEON_REV16:
4706 rev16(vf, rd, rn);
4707 break;
4708 case NEON_SUQADD:
4709 suqadd(vf, rd, rn);
4710 break;
4711 case NEON_USQADD:
4712 usqadd(vf, rd, rn);
4713 break;
4714 case NEON_CLS:
4715 cls(vf, rd, rn);
4716 break;
4717 case NEON_CLZ:
4718 clz(vf, rd, rn);
4719 break;
4720 case NEON_CNT:
4721 cnt(vf, rd, rn);
4722 break;
4723 case NEON_SQABS:
4724 abs(vf, rd, rn).SignedSaturate(vf);
4725 break;
4726 case NEON_SQNEG:
4727 neg(vf, rd, rn).SignedSaturate(vf);
4728 break;
4729 case NEON_CMGT_zero:
4730 cmp(vf, rd, rn, 0, gt);
4731 break;
4732 case NEON_CMGE_zero:
4733 cmp(vf, rd, rn, 0, ge);
4734 break;
4735 case NEON_CMEQ_zero:
4736 cmp(vf, rd, rn, 0, eq);
4737 break;
4738 case NEON_CMLE_zero:
4739 cmp(vf, rd, rn, 0, le);
4740 break;
4741 case NEON_CMLT_zero:
4742 cmp(vf, rd, rn, 0, lt);
4743 break;
4744 case NEON_ABS:
4745 abs(vf, rd, rn);
4746 break;
4747 case NEON_NEG:
4748 neg(vf, rd, rn);
4749 break;
4750 case NEON_SADDLP:
4751 saddlp(vf_lp, rd, rn);
4752 break;
4753 case NEON_UADDLP:
4754 uaddlp(vf_lp, rd, rn);
4755 break;
4756 case NEON_SADALP:
4757 sadalp(vf_lp, rd, rn);
4758 break;
4759 case NEON_UADALP:
4760 uadalp(vf_lp, rd, rn);
4761 break;
4762 case NEON_RBIT_NOT:
4763 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4764 switch (instr->GetFPType()) {
4765 case 0:
4766 not_(vf, rd, rn);
4767 break;
4768 case 1:
4769 rbit(vf, rd, rn);
4770 break;
4771 default:
4772 VIXL_UNIMPLEMENTED();
4773 }
4774 break;
4775 }
4776 } else {
4777 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4778 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4779 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004780 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004781
4782 // These instructions all use a one bit size field, except XTN, SQXTUN,
4783 // SHLL, SQXTN and UQXTN, which use a two bit size field.
4784 switch (instr->Mask(NEON2RegMiscFPMask)) {
4785 case NEON_FABS:
4786 fabs_(fpf, rd, rn);
4787 return;
4788 case NEON_FNEG:
4789 fneg(fpf, rd, rn);
4790 return;
4791 case NEON_FSQRT:
4792 fsqrt(fpf, rd, rn);
4793 return;
4794 case NEON_FCVTL:
4795 if (instr->Mask(NEON_Q)) {
4796 fcvtl2(vf_fcvtl, rd, rn);
4797 } else {
4798 fcvtl(vf_fcvtl, rd, rn);
4799 }
4800 return;
4801 case NEON_FCVTN:
4802 if (instr->Mask(NEON_Q)) {
4803 fcvtn2(vf_fcvtn, rd, rn);
4804 } else {
4805 fcvtn(vf_fcvtn, rd, rn);
4806 }
4807 return;
4808 case NEON_FCVTXN:
4809 if (instr->Mask(NEON_Q)) {
4810 fcvtxn2(vf_fcvtn, rd, rn);
4811 } else {
4812 fcvtxn(vf_fcvtn, rd, rn);
4813 }
4814 return;
4815
4816 // The following instructions break from the switch statement, rather
4817 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07004818 case NEON_FRINT32X:
4819 inexact_exception = true;
4820 frint_mode = kFrintToInt32;
4821 break; // Use FPCR rounding mode.
4822 case NEON_FRINT32Z:
4823 inexact_exception = true;
4824 frint_mode = kFrintToInt32;
4825 fpcr_rounding = FPZero;
4826 break;
4827 case NEON_FRINT64X:
4828 inexact_exception = true;
4829 frint_mode = kFrintToInt64;
4830 break; // Use FPCR rounding mode.
4831 case NEON_FRINT64Z:
4832 inexact_exception = true;
4833 frint_mode = kFrintToInt64;
4834 fpcr_rounding = FPZero;
4835 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004836 case NEON_FRINTI:
4837 break; // Use FPCR rounding mode.
4838 case NEON_FRINTX:
4839 inexact_exception = true;
4840 break;
4841 case NEON_FRINTA:
4842 fpcr_rounding = FPTieAway;
4843 break;
4844 case NEON_FRINTM:
4845 fpcr_rounding = FPNegativeInfinity;
4846 break;
4847 case NEON_FRINTN:
4848 fpcr_rounding = FPTieEven;
4849 break;
4850 case NEON_FRINTP:
4851 fpcr_rounding = FPPositiveInfinity;
4852 break;
4853 case NEON_FRINTZ:
4854 fpcr_rounding = FPZero;
4855 break;
4856
4857 case NEON_FCVTNS:
4858 fcvts(fpf, rd, rn, FPTieEven);
4859 return;
4860 case NEON_FCVTNU:
4861 fcvtu(fpf, rd, rn, FPTieEven);
4862 return;
4863 case NEON_FCVTPS:
4864 fcvts(fpf, rd, rn, FPPositiveInfinity);
4865 return;
4866 case NEON_FCVTPU:
4867 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4868 return;
4869 case NEON_FCVTMS:
4870 fcvts(fpf, rd, rn, FPNegativeInfinity);
4871 return;
4872 case NEON_FCVTMU:
4873 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4874 return;
4875 case NEON_FCVTZS:
4876 fcvts(fpf, rd, rn, FPZero);
4877 return;
4878 case NEON_FCVTZU:
4879 fcvtu(fpf, rd, rn, FPZero);
4880 return;
4881 case NEON_FCVTAS:
4882 fcvts(fpf, rd, rn, FPTieAway);
4883 return;
4884 case NEON_FCVTAU:
4885 fcvtu(fpf, rd, rn, FPTieAway);
4886 return;
4887 case NEON_SCVTF:
4888 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4889 return;
4890 case NEON_UCVTF:
4891 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4892 return;
4893 case NEON_URSQRTE:
4894 ursqrte(fpf, rd, rn);
4895 return;
4896 case NEON_URECPE:
4897 urecpe(fpf, rd, rn);
4898 return;
4899 case NEON_FRSQRTE:
4900 frsqrte(fpf, rd, rn);
4901 return;
4902 case NEON_FRECPE:
4903 frecpe(fpf, rd, rn, fpcr_rounding);
4904 return;
4905 case NEON_FCMGT_zero:
4906 fcmp_zero(fpf, rd, rn, gt);
4907 return;
4908 case NEON_FCMGE_zero:
4909 fcmp_zero(fpf, rd, rn, ge);
4910 return;
4911 case NEON_FCMEQ_zero:
4912 fcmp_zero(fpf, rd, rn, eq);
4913 return;
4914 case NEON_FCMLE_zero:
4915 fcmp_zero(fpf, rd, rn, le);
4916 return;
4917 case NEON_FCMLT_zero:
4918 fcmp_zero(fpf, rd, rn, lt);
4919 return;
4920 default:
4921 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4922 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4923 switch (instr->Mask(NEON2RegMiscMask)) {
4924 case NEON_XTN:
4925 xtn(vf, rd, rn);
4926 return;
4927 case NEON_SQXTN:
4928 sqxtn(vf, rd, rn);
4929 return;
4930 case NEON_UQXTN:
4931 uqxtn(vf, rd, rn);
4932 return;
4933 case NEON_SQXTUN:
4934 sqxtun(vf, rd, rn);
4935 return;
4936 case NEON_SHLL:
4937 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4938 if (instr->Mask(NEON_Q)) {
4939 shll2(vf, rd, rn);
4940 } else {
4941 shll(vf, rd, rn);
4942 }
4943 return;
4944 default:
4945 VIXL_UNIMPLEMENTED();
4946 }
4947 } else {
4948 VIXL_UNIMPLEMENTED();
4949 }
4950 }
4951
4952 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004953 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004954 }
4955}
4956
4957
Jacob Bramleyca789742018-09-13 14:25:46 +01004958void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4959 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4960 NEONFormatDecoder nfd(instr);
4961 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4962
4963 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4964
4965 SimVRegister& rd = ReadVRegister(instr->GetRd());
4966 SimVRegister& rn = ReadVRegister(instr->GetRn());
4967
4968 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4969 case NEON_SCVTF_H:
4970 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4971 return;
4972 case NEON_UCVTF_H:
4973 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4974 return;
4975 case NEON_FCVTNS_H:
4976 fcvts(fpf, rd, rn, FPTieEven);
4977 return;
4978 case NEON_FCVTNU_H:
4979 fcvtu(fpf, rd, rn, FPTieEven);
4980 return;
4981 case NEON_FCVTPS_H:
4982 fcvts(fpf, rd, rn, FPPositiveInfinity);
4983 return;
4984 case NEON_FCVTPU_H:
4985 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4986 return;
4987 case NEON_FCVTMS_H:
4988 fcvts(fpf, rd, rn, FPNegativeInfinity);
4989 return;
4990 case NEON_FCVTMU_H:
4991 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4992 return;
4993 case NEON_FCVTZS_H:
4994 fcvts(fpf, rd, rn, FPZero);
4995 return;
4996 case NEON_FCVTZU_H:
4997 fcvtu(fpf, rd, rn, FPZero);
4998 return;
4999 case NEON_FCVTAS_H:
5000 fcvts(fpf, rd, rn, FPTieAway);
5001 return;
5002 case NEON_FCVTAU_H:
5003 fcvtu(fpf, rd, rn, FPTieAway);
5004 return;
5005 case NEON_FRINTI_H:
5006 frint(fpf, rd, rn, fpcr_rounding, false);
5007 return;
5008 case NEON_FRINTX_H:
5009 frint(fpf, rd, rn, fpcr_rounding, true);
5010 return;
5011 case NEON_FRINTA_H:
5012 frint(fpf, rd, rn, FPTieAway, false);
5013 return;
5014 case NEON_FRINTM_H:
5015 frint(fpf, rd, rn, FPNegativeInfinity, false);
5016 return;
5017 case NEON_FRINTN_H:
5018 frint(fpf, rd, rn, FPTieEven, false);
5019 return;
5020 case NEON_FRINTP_H:
5021 frint(fpf, rd, rn, FPPositiveInfinity, false);
5022 return;
5023 case NEON_FRINTZ_H:
5024 frint(fpf, rd, rn, FPZero, false);
5025 return;
5026 case NEON_FABS_H:
5027 fabs_(fpf, rd, rn);
5028 return;
5029 case NEON_FNEG_H:
5030 fneg(fpf, rd, rn);
5031 return;
5032 case NEON_FSQRT_H:
5033 fsqrt(fpf, rd, rn);
5034 return;
5035 case NEON_FRSQRTE_H:
5036 frsqrte(fpf, rd, rn);
5037 return;
5038 case NEON_FRECPE_H:
5039 frecpe(fpf, rd, rn, fpcr_rounding);
5040 return;
5041 case NEON_FCMGT_H_zero:
5042 fcmp_zero(fpf, rd, rn, gt);
5043 return;
5044 case NEON_FCMGE_H_zero:
5045 fcmp_zero(fpf, rd, rn, ge);
5046 return;
5047 case NEON_FCMEQ_H_zero:
5048 fcmp_zero(fpf, rd, rn, eq);
5049 return;
5050 case NEON_FCMLE_H_zero:
5051 fcmp_zero(fpf, rd, rn, le);
5052 return;
5053 case NEON_FCMLT_H_zero:
5054 fcmp_zero(fpf, rd, rn, lt);
5055 return;
5056 default:
5057 VIXL_UNIMPLEMENTED();
5058 return;
5059 }
5060}
5061
5062
Alexandre Ramesd3832962016-07-04 15:03:43 +01005063void Simulator::VisitNEON3Same(const Instruction* instr) {
5064 NEONFormatDecoder nfd(instr);
5065 SimVRegister& rd = ReadVRegister(instr->GetRd());
5066 SimVRegister& rn = ReadVRegister(instr->GetRn());
5067 SimVRegister& rm = ReadVRegister(instr->GetRm());
5068
5069 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
5070 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
5071 switch (instr->Mask(NEON3SameLogicalMask)) {
5072 case NEON_AND:
5073 and_(vf, rd, rn, rm);
5074 break;
5075 case NEON_ORR:
5076 orr(vf, rd, rn, rm);
5077 break;
5078 case NEON_ORN:
5079 orn(vf, rd, rn, rm);
5080 break;
5081 case NEON_EOR:
5082 eor(vf, rd, rn, rm);
5083 break;
5084 case NEON_BIC:
5085 bic(vf, rd, rn, rm);
5086 break;
5087 case NEON_BIF:
5088 bif(vf, rd, rn, rm);
5089 break;
5090 case NEON_BIT:
5091 bit(vf, rd, rn, rm);
5092 break;
5093 case NEON_BSL:
5094 bsl(vf, rd, rn, rm);
5095 break;
5096 default:
5097 VIXL_UNIMPLEMENTED();
5098 }
5099 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
5100 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5101 switch (instr->Mask(NEON3SameFPMask)) {
5102 case NEON_FADD:
5103 fadd(vf, rd, rn, rm);
5104 break;
5105 case NEON_FSUB:
5106 fsub(vf, rd, rn, rm);
5107 break;
5108 case NEON_FMUL:
5109 fmul(vf, rd, rn, rm);
5110 break;
5111 case NEON_FDIV:
5112 fdiv(vf, rd, rn, rm);
5113 break;
5114 case NEON_FMAX:
5115 fmax(vf, rd, rn, rm);
5116 break;
5117 case NEON_FMIN:
5118 fmin(vf, rd, rn, rm);
5119 break;
5120 case NEON_FMAXNM:
5121 fmaxnm(vf, rd, rn, rm);
5122 break;
5123 case NEON_FMINNM:
5124 fminnm(vf, rd, rn, rm);
5125 break;
5126 case NEON_FMLA:
5127 fmla(vf, rd, rn, rm);
5128 break;
5129 case NEON_FMLS:
5130 fmls(vf, rd, rn, rm);
5131 break;
5132 case NEON_FMULX:
5133 fmulx(vf, rd, rn, rm);
5134 break;
5135 case NEON_FACGE:
5136 fabscmp(vf, rd, rn, rm, ge);
5137 break;
5138 case NEON_FACGT:
5139 fabscmp(vf, rd, rn, rm, gt);
5140 break;
5141 case NEON_FCMEQ:
5142 fcmp(vf, rd, rn, rm, eq);
5143 break;
5144 case NEON_FCMGE:
5145 fcmp(vf, rd, rn, rm, ge);
5146 break;
5147 case NEON_FCMGT:
5148 fcmp(vf, rd, rn, rm, gt);
5149 break;
5150 case NEON_FRECPS:
5151 frecps(vf, rd, rn, rm);
5152 break;
5153 case NEON_FRSQRTS:
5154 frsqrts(vf, rd, rn, rm);
5155 break;
5156 case NEON_FABD:
5157 fabd(vf, rd, rn, rm);
5158 break;
5159 case NEON_FADDP:
5160 faddp(vf, rd, rn, rm);
5161 break;
5162 case NEON_FMAXP:
5163 fmaxp(vf, rd, rn, rm);
5164 break;
5165 case NEON_FMAXNMP:
5166 fmaxnmp(vf, rd, rn, rm);
5167 break;
5168 case NEON_FMINP:
5169 fminp(vf, rd, rn, rm);
5170 break;
5171 case NEON_FMINNMP:
5172 fminnmp(vf, rd, rn, rm);
5173 break;
5174 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005175 // FMLAL{2} and FMLSL{2} have special-case encodings.
5176 switch (instr->Mask(NEON3SameFHMMask)) {
5177 case NEON_FMLAL:
5178 fmlal(vf, rd, rn, rm);
5179 break;
5180 case NEON_FMLAL2:
5181 fmlal2(vf, rd, rn, rm);
5182 break;
5183 case NEON_FMLSL:
5184 fmlsl(vf, rd, rn, rm);
5185 break;
5186 case NEON_FMLSL2:
5187 fmlsl2(vf, rd, rn, rm);
5188 break;
5189 default:
5190 VIXL_UNIMPLEMENTED();
5191 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005192 }
5193 } else {
5194 VectorFormat vf = nfd.GetVectorFormat();
5195 switch (instr->Mask(NEON3SameMask)) {
5196 case NEON_ADD:
5197 add(vf, rd, rn, rm);
5198 break;
5199 case NEON_ADDP:
5200 addp(vf, rd, rn, rm);
5201 break;
5202 case NEON_CMEQ:
5203 cmp(vf, rd, rn, rm, eq);
5204 break;
5205 case NEON_CMGE:
5206 cmp(vf, rd, rn, rm, ge);
5207 break;
5208 case NEON_CMGT:
5209 cmp(vf, rd, rn, rm, gt);
5210 break;
5211 case NEON_CMHI:
5212 cmp(vf, rd, rn, rm, hi);
5213 break;
5214 case NEON_CMHS:
5215 cmp(vf, rd, rn, rm, hs);
5216 break;
5217 case NEON_CMTST:
5218 cmptst(vf, rd, rn, rm);
5219 break;
5220 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01005221 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005222 break;
5223 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01005224 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005225 break;
5226 case NEON_MUL:
5227 mul(vf, rd, rn, rm);
5228 break;
5229 case NEON_PMUL:
5230 pmul(vf, rd, rn, rm);
5231 break;
5232 case NEON_SMAX:
5233 smax(vf, rd, rn, rm);
5234 break;
5235 case NEON_SMAXP:
5236 smaxp(vf, rd, rn, rm);
5237 break;
5238 case NEON_SMIN:
5239 smin(vf, rd, rn, rm);
5240 break;
5241 case NEON_SMINP:
5242 sminp(vf, rd, rn, rm);
5243 break;
5244 case NEON_SUB:
5245 sub(vf, rd, rn, rm);
5246 break;
5247 case NEON_UMAX:
5248 umax(vf, rd, rn, rm);
5249 break;
5250 case NEON_UMAXP:
5251 umaxp(vf, rd, rn, rm);
5252 break;
5253 case NEON_UMIN:
5254 umin(vf, rd, rn, rm);
5255 break;
5256 case NEON_UMINP:
5257 uminp(vf, rd, rn, rm);
5258 break;
5259 case NEON_SSHL:
5260 sshl(vf, rd, rn, rm);
5261 break;
5262 case NEON_USHL:
5263 ushl(vf, rd, rn, rm);
5264 break;
5265 case NEON_SABD:
5266 absdiff(vf, rd, rn, rm, true);
5267 break;
5268 case NEON_UABD:
5269 absdiff(vf, rd, rn, rm, false);
5270 break;
5271 case NEON_SABA:
5272 saba(vf, rd, rn, rm);
5273 break;
5274 case NEON_UABA:
5275 uaba(vf, rd, rn, rm);
5276 break;
5277 case NEON_UQADD:
5278 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5279 break;
5280 case NEON_SQADD:
5281 add(vf, rd, rn, rm).SignedSaturate(vf);
5282 break;
5283 case NEON_UQSUB:
5284 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5285 break;
5286 case NEON_SQSUB:
5287 sub(vf, rd, rn, rm).SignedSaturate(vf);
5288 break;
5289 case NEON_SQDMULH:
5290 sqdmulh(vf, rd, rn, rm);
5291 break;
5292 case NEON_SQRDMULH:
5293 sqrdmulh(vf, rd, rn, rm);
5294 break;
5295 case NEON_UQSHL:
5296 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5297 break;
5298 case NEON_SQSHL:
5299 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5300 break;
5301 case NEON_URSHL:
5302 ushl(vf, rd, rn, rm).Round(vf);
5303 break;
5304 case NEON_SRSHL:
5305 sshl(vf, rd, rn, rm).Round(vf);
5306 break;
5307 case NEON_UQRSHL:
5308 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5309 break;
5310 case NEON_SQRSHL:
5311 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5312 break;
5313 case NEON_UHADD:
5314 add(vf, rd, rn, rm).Uhalve(vf);
5315 break;
5316 case NEON_URHADD:
5317 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
5318 break;
5319 case NEON_SHADD:
5320 add(vf, rd, rn, rm).Halve(vf);
5321 break;
5322 case NEON_SRHADD:
5323 add(vf, rd, rn, rm).Halve(vf).Round(vf);
5324 break;
5325 case NEON_UHSUB:
5326 sub(vf, rd, rn, rm).Uhalve(vf);
5327 break;
5328 case NEON_SHSUB:
5329 sub(vf, rd, rn, rm).Halve(vf);
5330 break;
5331 default:
5332 VIXL_UNIMPLEMENTED();
5333 }
5334 }
5335}
5336
5337
Jacob Bramleyca789742018-09-13 14:25:46 +01005338void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
5339 NEONFormatDecoder nfd(instr);
5340 SimVRegister& rd = ReadVRegister(instr->GetRd());
5341 SimVRegister& rn = ReadVRegister(instr->GetRn());
5342 SimVRegister& rm = ReadVRegister(instr->GetRm());
5343
5344 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
5345 switch (instr->Mask(NEON3SameFP16Mask)) {
5346#define SIM_FUNC(A, B) \
5347 case NEON_##A##_H: \
5348 B(vf, rd, rn, rm); \
5349 break;
5350 SIM_FUNC(FMAXNM, fmaxnm);
5351 SIM_FUNC(FMLA, fmla);
5352 SIM_FUNC(FADD, fadd);
5353 SIM_FUNC(FMULX, fmulx);
5354 SIM_FUNC(FMAX, fmax);
5355 SIM_FUNC(FRECPS, frecps);
5356 SIM_FUNC(FMINNM, fminnm);
5357 SIM_FUNC(FMLS, fmls);
5358 SIM_FUNC(FSUB, fsub);
5359 SIM_FUNC(FMIN, fmin);
5360 SIM_FUNC(FRSQRTS, frsqrts);
5361 SIM_FUNC(FMAXNMP, fmaxnmp);
5362 SIM_FUNC(FADDP, faddp);
5363 SIM_FUNC(FMUL, fmul);
5364 SIM_FUNC(FMAXP, fmaxp);
5365 SIM_FUNC(FDIV, fdiv);
5366 SIM_FUNC(FMINNMP, fminnmp);
5367 SIM_FUNC(FABD, fabd);
5368 SIM_FUNC(FMINP, fminp);
5369#undef SIM_FUNC
5370 case NEON_FCMEQ_H:
5371 fcmp(vf, rd, rn, rm, eq);
5372 break;
5373 case NEON_FCMGE_H:
5374 fcmp(vf, rd, rn, rm, ge);
5375 break;
5376 case NEON_FACGE_H:
5377 fabscmp(vf, rd, rn, rm, ge);
5378 break;
5379 case NEON_FCMGT_H:
5380 fcmp(vf, rd, rn, rm, gt);
5381 break;
5382 case NEON_FACGT_H:
5383 fabscmp(vf, rd, rn, rm, gt);
5384 break;
5385 default:
5386 VIXL_UNIMPLEMENTED();
5387 break;
5388 }
5389}
5390
Carey Williams2809e6c2018-03-13 12:24:16 +00005391void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
5392 NEONFormatDecoder nfd(instr);
5393 SimVRegister& rd = ReadVRegister(instr->GetRd());
5394 SimVRegister& rn = ReadVRegister(instr->GetRn());
5395 SimVRegister& rm = ReadVRegister(instr->GetRm());
5396 int rot = 0;
5397 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01005398 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
5399 rot = instr->GetImmRotFcmlaVec();
5400 fcmla(vf, rd, rn, rm, rot);
5401 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
5402 rot = instr->GetImmRotFcadd();
5403 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01005404 } else {
5405 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01005406 case NEON_SDOT:
5407 sdot(vf, rd, rn, rm);
5408 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005409 case NEON_SQRDMLAH:
5410 sqrdmlah(vf, rd, rn, rm);
5411 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005412 case NEON_UDOT:
5413 udot(vf, rd, rn, rm);
5414 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005415 case NEON_SQRDMLSH:
5416 sqrdmlsh(vf, rd, rn, rm);
5417 break;
5418 default:
5419 VIXL_UNIMPLEMENTED();
5420 break;
5421 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005422 }
5423}
5424
5425
Alexandre Ramesd3832962016-07-04 15:03:43 +01005426void Simulator::VisitNEON3Different(const Instruction* instr) {
5427 NEONFormatDecoder nfd(instr);
5428 VectorFormat vf = nfd.GetVectorFormat();
5429 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5430
5431 SimVRegister& rd = ReadVRegister(instr->GetRd());
5432 SimVRegister& rn = ReadVRegister(instr->GetRn());
5433 SimVRegister& rm = ReadVRegister(instr->GetRm());
5434
5435 switch (instr->Mask(NEON3DifferentMask)) {
5436 case NEON_PMULL:
5437 pmull(vf_l, rd, rn, rm);
5438 break;
5439 case NEON_PMULL2:
5440 pmull2(vf_l, rd, rn, rm);
5441 break;
5442 case NEON_UADDL:
5443 uaddl(vf_l, rd, rn, rm);
5444 break;
5445 case NEON_UADDL2:
5446 uaddl2(vf_l, rd, rn, rm);
5447 break;
5448 case NEON_SADDL:
5449 saddl(vf_l, rd, rn, rm);
5450 break;
5451 case NEON_SADDL2:
5452 saddl2(vf_l, rd, rn, rm);
5453 break;
5454 case NEON_USUBL:
5455 usubl(vf_l, rd, rn, rm);
5456 break;
5457 case NEON_USUBL2:
5458 usubl2(vf_l, rd, rn, rm);
5459 break;
5460 case NEON_SSUBL:
5461 ssubl(vf_l, rd, rn, rm);
5462 break;
5463 case NEON_SSUBL2:
5464 ssubl2(vf_l, rd, rn, rm);
5465 break;
5466 case NEON_SABAL:
5467 sabal(vf_l, rd, rn, rm);
5468 break;
5469 case NEON_SABAL2:
5470 sabal2(vf_l, rd, rn, rm);
5471 break;
5472 case NEON_UABAL:
5473 uabal(vf_l, rd, rn, rm);
5474 break;
5475 case NEON_UABAL2:
5476 uabal2(vf_l, rd, rn, rm);
5477 break;
5478 case NEON_SABDL:
5479 sabdl(vf_l, rd, rn, rm);
5480 break;
5481 case NEON_SABDL2:
5482 sabdl2(vf_l, rd, rn, rm);
5483 break;
5484 case NEON_UABDL:
5485 uabdl(vf_l, rd, rn, rm);
5486 break;
5487 case NEON_UABDL2:
5488 uabdl2(vf_l, rd, rn, rm);
5489 break;
5490 case NEON_SMLAL:
5491 smlal(vf_l, rd, rn, rm);
5492 break;
5493 case NEON_SMLAL2:
5494 smlal2(vf_l, rd, rn, rm);
5495 break;
5496 case NEON_UMLAL:
5497 umlal(vf_l, rd, rn, rm);
5498 break;
5499 case NEON_UMLAL2:
5500 umlal2(vf_l, rd, rn, rm);
5501 break;
5502 case NEON_SMLSL:
5503 smlsl(vf_l, rd, rn, rm);
5504 break;
5505 case NEON_SMLSL2:
5506 smlsl2(vf_l, rd, rn, rm);
5507 break;
5508 case NEON_UMLSL:
5509 umlsl(vf_l, rd, rn, rm);
5510 break;
5511 case NEON_UMLSL2:
5512 umlsl2(vf_l, rd, rn, rm);
5513 break;
5514 case NEON_SMULL:
5515 smull(vf_l, rd, rn, rm);
5516 break;
5517 case NEON_SMULL2:
5518 smull2(vf_l, rd, rn, rm);
5519 break;
5520 case NEON_UMULL:
5521 umull(vf_l, rd, rn, rm);
5522 break;
5523 case NEON_UMULL2:
5524 umull2(vf_l, rd, rn, rm);
5525 break;
5526 case NEON_SQDMLAL:
5527 sqdmlal(vf_l, rd, rn, rm);
5528 break;
5529 case NEON_SQDMLAL2:
5530 sqdmlal2(vf_l, rd, rn, rm);
5531 break;
5532 case NEON_SQDMLSL:
5533 sqdmlsl(vf_l, rd, rn, rm);
5534 break;
5535 case NEON_SQDMLSL2:
5536 sqdmlsl2(vf_l, rd, rn, rm);
5537 break;
5538 case NEON_SQDMULL:
5539 sqdmull(vf_l, rd, rn, rm);
5540 break;
5541 case NEON_SQDMULL2:
5542 sqdmull2(vf_l, rd, rn, rm);
5543 break;
5544 case NEON_UADDW:
5545 uaddw(vf_l, rd, rn, rm);
5546 break;
5547 case NEON_UADDW2:
5548 uaddw2(vf_l, rd, rn, rm);
5549 break;
5550 case NEON_SADDW:
5551 saddw(vf_l, rd, rn, rm);
5552 break;
5553 case NEON_SADDW2:
5554 saddw2(vf_l, rd, rn, rm);
5555 break;
5556 case NEON_USUBW:
5557 usubw(vf_l, rd, rn, rm);
5558 break;
5559 case NEON_USUBW2:
5560 usubw2(vf_l, rd, rn, rm);
5561 break;
5562 case NEON_SSUBW:
5563 ssubw(vf_l, rd, rn, rm);
5564 break;
5565 case NEON_SSUBW2:
5566 ssubw2(vf_l, rd, rn, rm);
5567 break;
5568 case NEON_ADDHN:
5569 addhn(vf, rd, rn, rm);
5570 break;
5571 case NEON_ADDHN2:
5572 addhn2(vf, rd, rn, rm);
5573 break;
5574 case NEON_RADDHN:
5575 raddhn(vf, rd, rn, rm);
5576 break;
5577 case NEON_RADDHN2:
5578 raddhn2(vf, rd, rn, rm);
5579 break;
5580 case NEON_SUBHN:
5581 subhn(vf, rd, rn, rm);
5582 break;
5583 case NEON_SUBHN2:
5584 subhn2(vf, rd, rn, rm);
5585 break;
5586 case NEON_RSUBHN:
5587 rsubhn(vf, rd, rn, rm);
5588 break;
5589 case NEON_RSUBHN2:
5590 rsubhn2(vf, rd, rn, rm);
5591 break;
5592 default:
5593 VIXL_UNIMPLEMENTED();
5594 }
5595}
5596
5597
5598void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5599 NEONFormatDecoder nfd(instr);
5600
Jacob Bramleyca789742018-09-13 14:25:46 +01005601 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5602
Alexandre Ramesd3832962016-07-04 15:03:43 +01005603 SimVRegister& rd = ReadVRegister(instr->GetRd());
5604 SimVRegister& rn = ReadVRegister(instr->GetRn());
5605
Jacob Bramleyca789742018-09-13 14:25:46 +01005606 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5607 VectorFormat vf = nfd.GetVectorFormat(&map_half);
5608 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5609 case NEON_FMAXV_H:
5610 fmaxv(vf, rd, rn);
5611 break;
5612 case NEON_FMINV_H:
5613 fminv(vf, rd, rn);
5614 break;
5615 case NEON_FMAXNMV_H:
5616 fmaxnmv(vf, rd, rn);
5617 break;
5618 case NEON_FMINNMV_H:
5619 fminnmv(vf, rd, rn);
5620 break;
5621 default:
5622 VIXL_UNIMPLEMENTED();
5623 }
5624 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5625 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01005626 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5627
5628 switch (instr->Mask(NEONAcrossLanesFPMask)) {
5629 case NEON_FMAXV:
5630 fmaxv(vf, rd, rn);
5631 break;
5632 case NEON_FMINV:
5633 fminv(vf, rd, rn);
5634 break;
5635 case NEON_FMAXNMV:
5636 fmaxnmv(vf, rd, rn);
5637 break;
5638 case NEON_FMINNMV:
5639 fminnmv(vf, rd, rn);
5640 break;
5641 default:
5642 VIXL_UNIMPLEMENTED();
5643 }
5644 } else {
5645 VectorFormat vf = nfd.GetVectorFormat();
5646
5647 switch (instr->Mask(NEONAcrossLanesMask)) {
5648 case NEON_ADDV:
5649 addv(vf, rd, rn);
5650 break;
5651 case NEON_SMAXV:
5652 smaxv(vf, rd, rn);
5653 break;
5654 case NEON_SMINV:
5655 sminv(vf, rd, rn);
5656 break;
5657 case NEON_UMAXV:
5658 umaxv(vf, rd, rn);
5659 break;
5660 case NEON_UMINV:
5661 uminv(vf, rd, rn);
5662 break;
5663 case NEON_SADDLV:
5664 saddlv(vf, rd, rn);
5665 break;
5666 case NEON_UADDLV:
5667 uaddlv(vf, rd, rn);
5668 break;
5669 default:
5670 VIXL_UNIMPLEMENTED();
5671 }
5672 }
5673}
5674
5675
5676void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5677 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01005678 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01005679 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01005680 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005681 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5682
5683 SimVRegister& rd = ReadVRegister(instr->GetRd());
5684 SimVRegister& rn = ReadVRegister(instr->GetRn());
5685
5686 ByElementOp Op = NULL;
5687
5688 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005689 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005690 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005691 int index_hlm = (index << 1) | instr->GetNEONM();
5692
5693 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5694 // These are oddballs and are best handled as special cases.
5695 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5696 // - The index is always H:L:M.
5697 case NEON_FMLAL_H_byelement:
5698 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5699 return;
5700 case NEON_FMLAL2_H_byelement:
5701 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5702 return;
5703 case NEON_FMLSL_H_byelement:
5704 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5705 return;
5706 case NEON_FMLSL2_H_byelement:
5707 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5708 return;
5709 }
5710
Alexandre Ramesd3832962016-07-04 15:03:43 +01005711 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005712 rm_reg = rm_low_reg;
5713 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005714 }
5715
5716 switch (instr->Mask(NEONByIndexedElementMask)) {
5717 case NEON_MUL_byelement:
5718 Op = &Simulator::mul;
5719 vf = vf_r;
5720 break;
5721 case NEON_MLA_byelement:
5722 Op = &Simulator::mla;
5723 vf = vf_r;
5724 break;
5725 case NEON_MLS_byelement:
5726 Op = &Simulator::mls;
5727 vf = vf_r;
5728 break;
5729 case NEON_SQDMULH_byelement:
5730 Op = &Simulator::sqdmulh;
5731 vf = vf_r;
5732 break;
5733 case NEON_SQRDMULH_byelement:
5734 Op = &Simulator::sqrdmulh;
5735 vf = vf_r;
5736 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005737 case NEON_SDOT_byelement:
5738 Op = &Simulator::sdot;
5739 vf = vf_r;
5740 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005741 case NEON_SQRDMLAH_byelement:
5742 Op = &Simulator::sqrdmlah;
5743 vf = vf_r;
5744 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005745 case NEON_UDOT_byelement:
5746 Op = &Simulator::udot;
5747 vf = vf_r;
5748 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005749 case NEON_SQRDMLSH_byelement:
5750 Op = &Simulator::sqrdmlsh;
5751 vf = vf_r;
5752 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005753 case NEON_SMULL_byelement:
5754 if (instr->Mask(NEON_Q)) {
5755 Op = &Simulator::smull2;
5756 } else {
5757 Op = &Simulator::smull;
5758 }
5759 break;
5760 case NEON_UMULL_byelement:
5761 if (instr->Mask(NEON_Q)) {
5762 Op = &Simulator::umull2;
5763 } else {
5764 Op = &Simulator::umull;
5765 }
5766 break;
5767 case NEON_SMLAL_byelement:
5768 if (instr->Mask(NEON_Q)) {
5769 Op = &Simulator::smlal2;
5770 } else {
5771 Op = &Simulator::smlal;
5772 }
5773 break;
5774 case NEON_UMLAL_byelement:
5775 if (instr->Mask(NEON_Q)) {
5776 Op = &Simulator::umlal2;
5777 } else {
5778 Op = &Simulator::umlal;
5779 }
5780 break;
5781 case NEON_SMLSL_byelement:
5782 if (instr->Mask(NEON_Q)) {
5783 Op = &Simulator::smlsl2;
5784 } else {
5785 Op = &Simulator::smlsl;
5786 }
5787 break;
5788 case NEON_UMLSL_byelement:
5789 if (instr->Mask(NEON_Q)) {
5790 Op = &Simulator::umlsl2;
5791 } else {
5792 Op = &Simulator::umlsl;
5793 }
5794 break;
5795 case NEON_SQDMULL_byelement:
5796 if (instr->Mask(NEON_Q)) {
5797 Op = &Simulator::sqdmull2;
5798 } else {
5799 Op = &Simulator::sqdmull;
5800 }
5801 break;
5802 case NEON_SQDMLAL_byelement:
5803 if (instr->Mask(NEON_Q)) {
5804 Op = &Simulator::sqdmlal2;
5805 } else {
5806 Op = &Simulator::sqdmlal;
5807 }
5808 break;
5809 case NEON_SQDMLSL_byelement:
5810 if (instr->Mask(NEON_Q)) {
5811 Op = &Simulator::sqdmlsl2;
5812 } else {
5813 Op = &Simulator::sqdmlsl;
5814 }
5815 break;
5816 default:
5817 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01005818 if (instr->GetFPType() == 0) {
5819 rm_reg &= 0xf;
5820 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5821 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005822 index = (index << 1) | instr->GetNEONL();
5823 }
5824
5825 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5826
5827 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005828 case NEON_FMUL_H_byelement:
5829 vf = vf_half;
5830 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005831 case NEON_FMUL_byelement:
5832 Op = &Simulator::fmul;
5833 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005834 case NEON_FMLA_H_byelement:
5835 vf = vf_half;
5836 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005837 case NEON_FMLA_byelement:
5838 Op = &Simulator::fmla;
5839 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005840 case NEON_FMLS_H_byelement:
5841 vf = vf_half;
5842 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005843 case NEON_FMLS_byelement:
5844 Op = &Simulator::fmls;
5845 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005846 case NEON_FMULX_H_byelement:
5847 vf = vf_half;
5848 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005849 case NEON_FMULX_byelement:
5850 Op = &Simulator::fmulx;
5851 break;
5852 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005853 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00005854 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005855 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00005856 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005857 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005858 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5859 case NEON_FCMLA_byelement:
5860 vf = vf_r;
5861 fcmla(vf,
5862 rd,
5863 rn,
5864 ReadVRegister(instr->GetRm()),
5865 index,
5866 instr->GetImmRotFcmlaSca());
5867 return;
5868 default:
5869 VIXL_UNIMPLEMENTED();
5870 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005871 }
5872 }
5873
5874 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5875}
5876
5877
5878void Simulator::VisitNEONCopy(const Instruction* instr) {
5879 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5880 VectorFormat vf = nfd.GetVectorFormat();
5881
5882 SimVRegister& rd = ReadVRegister(instr->GetRd());
5883 SimVRegister& rn = ReadVRegister(instr->GetRn());
5884 int imm5 = instr->GetImmNEON5();
5885 int tz = CountTrailingZeros(imm5, 32);
5886 int reg_index = imm5 >> (tz + 1);
5887
5888 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5889 int imm4 = instr->GetImmNEON4();
5890 int rn_index = imm4 >> tz;
5891 ins_element(vf, rd, reg_index, rn, rn_index);
5892 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5893 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5894 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5895 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5896 value &= MaxUintFromFormat(vf);
5897 WriteXRegister(instr->GetRd(), value);
5898 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5899 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5900 if (instr->GetNEONQ()) {
5901 WriteXRegister(instr->GetRd(), value);
5902 } else {
5903 WriteWRegister(instr->GetRd(), (int32_t)value);
5904 }
5905 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5906 dup_element(vf, rd, rn, reg_index);
5907 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5908 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5909 } else {
5910 VIXL_UNIMPLEMENTED();
5911 }
5912}
5913
5914
5915void Simulator::VisitNEONExtract(const Instruction* instr) {
5916 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5917 VectorFormat vf = nfd.GetVectorFormat();
5918 SimVRegister& rd = ReadVRegister(instr->GetRd());
5919 SimVRegister& rn = ReadVRegister(instr->GetRn());
5920 SimVRegister& rm = ReadVRegister(instr->GetRm());
5921 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5922 int index = instr->GetImmNEONExt();
5923 ext(vf, rd, rn, rm, index);
5924 } else {
5925 VIXL_UNIMPLEMENTED();
5926 }
5927}
5928
5929
5930void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5931 AddrMode addr_mode) {
5932 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5933 VectorFormat vf = nfd.GetVectorFormat();
5934
5935 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5936 int reg_size = RegisterSizeInBytesFromFormat(vf);
5937
5938 int reg[4];
5939 uint64_t addr[4];
5940 for (int i = 0; i < 4; i++) {
5941 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5942 addr[i] = addr_base + (i * reg_size);
5943 }
Jacob Bramley423e5422019-11-13 19:15:55 +00005944 int struct_parts = 1;
5945 int reg_count = 1;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005946 bool log_read = true;
5947
Martyn Capewell32009e32016-10-27 11:00:37 +01005948 // Bit 23 determines whether this is an offset or post-index addressing mode.
5949 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5950 // register or immediate in post-index mode.
5951 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005952 VIXL_UNREACHABLE();
5953 }
5954
5955 // We use the PostIndex mask here, as it works in this case for both Offset
5956 // and PostIndex addressing.
5957 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5958 case NEON_LD1_4v:
5959 case NEON_LD1_4v_post:
5960 ld1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005961 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005962 VIXL_FALLTHROUGH();
5963 case NEON_LD1_3v:
5964 case NEON_LD1_3v_post:
5965 ld1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005966 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005967 VIXL_FALLTHROUGH();
5968 case NEON_LD1_2v:
5969 case NEON_LD1_2v_post:
5970 ld1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005971 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005972 VIXL_FALLTHROUGH();
5973 case NEON_LD1_1v:
5974 case NEON_LD1_1v_post:
5975 ld1(vf, ReadVRegister(reg[0]), addr[0]);
5976 break;
5977 case NEON_ST1_4v:
5978 case NEON_ST1_4v_post:
5979 st1(vf, ReadVRegister(reg[3]), addr[3]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005980 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005981 VIXL_FALLTHROUGH();
5982 case NEON_ST1_3v:
5983 case NEON_ST1_3v_post:
5984 st1(vf, ReadVRegister(reg[2]), addr[2]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005985 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005986 VIXL_FALLTHROUGH();
5987 case NEON_ST1_2v:
5988 case NEON_ST1_2v_post:
5989 st1(vf, ReadVRegister(reg[1]), addr[1]);
Jacob Bramley423e5422019-11-13 19:15:55 +00005990 reg_count++;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005991 VIXL_FALLTHROUGH();
5992 case NEON_ST1_1v:
5993 case NEON_ST1_1v_post:
5994 st1(vf, ReadVRegister(reg[0]), addr[0]);
5995 log_read = false;
5996 break;
5997 case NEON_LD2_post:
5998 case NEON_LD2:
5999 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006000 struct_parts = 2;
6001 reg_count = 2;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006002 break;
6003 case NEON_ST2:
6004 case NEON_ST2_post:
6005 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006006 struct_parts = 2;
6007 reg_count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01006008 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006009 break;
6010 case NEON_LD3_post:
6011 case NEON_LD3:
6012 ld3(vf,
6013 ReadVRegister(reg[0]),
6014 ReadVRegister(reg[1]),
6015 ReadVRegister(reg[2]),
6016 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006017 struct_parts = 3;
6018 reg_count = 3;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006019 break;
6020 case NEON_ST3:
6021 case NEON_ST3_post:
6022 st3(vf,
6023 ReadVRegister(reg[0]),
6024 ReadVRegister(reg[1]),
6025 ReadVRegister(reg[2]),
6026 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006027 struct_parts = 3;
6028 reg_count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01006029 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006030 break;
6031 case NEON_ST4:
6032 case NEON_ST4_post:
6033 st4(vf,
6034 ReadVRegister(reg[0]),
6035 ReadVRegister(reg[1]),
6036 ReadVRegister(reg[2]),
6037 ReadVRegister(reg[3]),
6038 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006039 struct_parts = 4;
6040 reg_count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01006041 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006042 break;
6043 case NEON_LD4_post:
6044 case NEON_LD4:
6045 ld4(vf,
6046 ReadVRegister(reg[0]),
6047 ReadVRegister(reg[1]),
6048 ReadVRegister(reg[2]),
6049 ReadVRegister(reg[3]),
6050 addr[0]);
Jacob Bramley423e5422019-11-13 19:15:55 +00006051 struct_parts = 4;
6052 reg_count = 4;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006053 break;
6054 default:
6055 VIXL_UNIMPLEMENTED();
6056 }
6057
Jacob Bramley7eb3e212019-11-22 17:28:05 +00006058 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
Jacob Bramley423e5422019-11-13 19:15:55 +00006059 if (do_trace) {
6060 PrintRegisterFormat print_format =
6061 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
6062 const char* op;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006063 if (log_read) {
Jacob Bramley423e5422019-11-13 19:15:55 +00006064 op = "<-";
Alexandre Ramesd3832962016-07-04 15:03:43 +01006065 } else {
Jacob Bramley423e5422019-11-13 19:15:55 +00006066 op = "->";
6067 // Stores don't represent a change to the source register's value, so only
6068 // print the relevant part of the value.
6069 print_format = GetPrintRegPartial(print_format);
6070 }
6071
6072 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
6073 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
6074 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
6075 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006076 }
6077 }
6078
6079 if (addr_mode == PostIndex) {
6080 int rm = instr->GetRm();
6081 // The immediate post index addressing mode is indicated by rm = 31.
6082 // The immediate is implied by the number of vector registers used.
Jacob Bramley423e5422019-11-13 19:15:55 +00006083 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
Alexandre Ramesd3832962016-07-04 15:03:43 +01006084 : ReadXRegister(rm);
6085 WriteXRegister(instr->GetRn(), addr_base);
6086 } else {
6087 VIXL_ASSERT(addr_mode == Offset);
6088 }
6089}
6090
6091
6092void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
6093 NEONLoadStoreMultiStructHelper(instr, Offset);
6094}
6095
6096
6097void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
6098 const Instruction* instr) {
6099 NEONLoadStoreMultiStructHelper(instr, PostIndex);
6100}
6101
6102
6103void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
6104 AddrMode addr_mode) {
6105 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
6106 int rt = instr->GetRt();
6107
Martyn Capewell32009e32016-10-27 11:00:37 +01006108 // Bit 23 determines whether this is an offset or post-index addressing mode.
6109 // In offset mode, bits 20 to 16 should be zero; these bits encode the
6110 // register or immediate in post-index mode.
6111 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006112 VIXL_UNREACHABLE();
6113 }
6114
6115 // We use the PostIndex mask here, as it works in this case for both Offset
6116 // and PostIndex addressing.
6117 bool do_load = false;
6118
Jacob Bramley423e5422019-11-13 19:15:55 +00006119 bool replicating = false;
6120
Alexandre Ramesd3832962016-07-04 15:03:43 +01006121 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
6122 VectorFormat vf_t = nfd.GetVectorFormat();
6123
6124 VectorFormat vf = kFormat16B;
6125 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
6126 case NEON_LD1_b:
6127 case NEON_LD1_b_post:
6128 case NEON_LD2_b:
6129 case NEON_LD2_b_post:
6130 case NEON_LD3_b:
6131 case NEON_LD3_b_post:
6132 case NEON_LD4_b:
6133 case NEON_LD4_b_post:
6134 do_load = true;
6135 VIXL_FALLTHROUGH();
6136 case NEON_ST1_b:
6137 case NEON_ST1_b_post:
6138 case NEON_ST2_b:
6139 case NEON_ST2_b_post:
6140 case NEON_ST3_b:
6141 case NEON_ST3_b_post:
6142 case NEON_ST4_b:
6143 case NEON_ST4_b_post:
6144 break;
6145
6146 case NEON_LD1_h:
6147 case NEON_LD1_h_post:
6148 case NEON_LD2_h:
6149 case NEON_LD2_h_post:
6150 case NEON_LD3_h:
6151 case NEON_LD3_h_post:
6152 case NEON_LD4_h:
6153 case NEON_LD4_h_post:
6154 do_load = true;
6155 VIXL_FALLTHROUGH();
6156 case NEON_ST1_h:
6157 case NEON_ST1_h_post:
6158 case NEON_ST2_h:
6159 case NEON_ST2_h_post:
6160 case NEON_ST3_h:
6161 case NEON_ST3_h_post:
6162 case NEON_ST4_h:
6163 case NEON_ST4_h_post:
6164 vf = kFormat8H;
6165 break;
6166 case NEON_LD1_s:
6167 case NEON_LD1_s_post:
6168 case NEON_LD2_s:
6169 case NEON_LD2_s_post:
6170 case NEON_LD3_s:
6171 case NEON_LD3_s_post:
6172 case NEON_LD4_s:
6173 case NEON_LD4_s_post:
6174 do_load = true;
6175 VIXL_FALLTHROUGH();
6176 case NEON_ST1_s:
6177 case NEON_ST1_s_post:
6178 case NEON_ST2_s:
6179 case NEON_ST2_s_post:
6180 case NEON_ST3_s:
6181 case NEON_ST3_s_post:
6182 case NEON_ST4_s:
6183 case NEON_ST4_s_post: {
6184 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
6185 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
6186 NEON_LD1_d_post);
6187 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
6188 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
6189 NEON_ST1_d_post);
6190 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
6191 break;
6192 }
6193
6194 case NEON_LD1R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006195 case NEON_LD1R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006196 case NEON_LD2R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006197 case NEON_LD2R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006198 case NEON_LD3R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006199 case NEON_LD3R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006200 case NEON_LD4R:
Jacob Bramley423e5422019-11-13 19:15:55 +00006201 case NEON_LD4R_post:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006202 vf = vf_t;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006203 do_load = true;
Jacob Bramley423e5422019-11-13 19:15:55 +00006204 replicating = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006205 break;
Jacob Bramley423e5422019-11-13 19:15:55 +00006206
Alexandre Ramesd3832962016-07-04 15:03:43 +01006207 default:
6208 VIXL_UNIMPLEMENTED();
6209 }
6210
Alexandre Ramesd3832962016-07-04 15:03:43 +01006211 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
6212 int lane = instr->GetNEONLSIndex(index_shift);
Jacob Bramley423e5422019-11-13 19:15:55 +00006213 int reg_count = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006214 int rt2 = (rt + 1) % kNumberOfVRegisters;
6215 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
6216 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
6217 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
6218 case NEONLoadStoreSingle1:
Jacob Bramley423e5422019-11-13 19:15:55 +00006219 reg_count = 1;
6220 if (replicating) {
6221 VIXL_ASSERT(do_load);
6222 ld1r(vf, ReadVRegister(rt), addr);
6223 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006224 ld1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006225 } else {
6226 st1(vf, ReadVRegister(rt), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006227 }
6228 break;
6229 case NEONLoadStoreSingle2:
Jacob Bramley423e5422019-11-13 19:15:55 +00006230 reg_count = 2;
6231 if (replicating) {
6232 VIXL_ASSERT(do_load);
6233 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
6234 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006235 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006236 } else {
6237 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006238 }
6239 break;
6240 case NEONLoadStoreSingle3:
Jacob Bramley423e5422019-11-13 19:15:55 +00006241 reg_count = 3;
6242 if (replicating) {
6243 VIXL_ASSERT(do_load);
6244 ld3r(vf,
6245 ReadVRegister(rt),
6246 ReadVRegister(rt2),
6247 ReadVRegister(rt3),
6248 addr);
6249 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006250 ld3(vf,
6251 ReadVRegister(rt),
6252 ReadVRegister(rt2),
6253 ReadVRegister(rt3),
6254 lane,
6255 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006256 } else {
6257 st3(vf,
6258 ReadVRegister(rt),
6259 ReadVRegister(rt2),
6260 ReadVRegister(rt3),
6261 lane,
6262 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006263 }
6264 break;
6265 case NEONLoadStoreSingle4:
Jacob Bramley423e5422019-11-13 19:15:55 +00006266 reg_count = 4;
6267 if (replicating) {
6268 VIXL_ASSERT(do_load);
6269 ld4r(vf,
6270 ReadVRegister(rt),
6271 ReadVRegister(rt2),
6272 ReadVRegister(rt3),
6273 ReadVRegister(rt4),
6274 addr);
6275 } else if (do_load) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006276 ld4(vf,
6277 ReadVRegister(rt),
6278 ReadVRegister(rt2),
6279 ReadVRegister(rt3),
6280 ReadVRegister(rt4),
6281 lane,
6282 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006283 } else {
6284 st4(vf,
6285 ReadVRegister(rt),
6286 ReadVRegister(rt2),
6287 ReadVRegister(rt3),
6288 ReadVRegister(rt4),
6289 lane,
6290 addr);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006291 }
6292 break;
6293 default:
6294 VIXL_UNIMPLEMENTED();
6295 }
6296
Jacob Bramley423e5422019-11-13 19:15:55 +00006297 // Trace registers and/or memory writes.
6298 PrintRegisterFormat print_format =
6299 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
6300 if (do_load) {
6301 if (ShouldTraceVRegs()) {
6302 if (replicating) {
6303 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
6304 } else {
6305 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
6306 }
6307 }
6308 } else {
6309 if (ShouldTraceWrites()) {
6310 // Stores don't represent a change to the source register's value, so only
6311 // print the relevant part of the value.
6312 print_format = GetPrintRegPartial(print_format);
6313 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
6314 }
6315 }
6316
Alexandre Ramesd3832962016-07-04 15:03:43 +01006317 if (addr_mode == PostIndex) {
6318 int rm = instr->GetRm();
6319 int lane_size = LaneSizeInBytesFromFormat(vf);
6320 WriteXRegister(instr->GetRn(),
Jacob Bramley423e5422019-11-13 19:15:55 +00006321 addr + ((rm == 31) ? (reg_count * lane_size)
6322 : ReadXRegister(rm)));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006323 }
6324}
6325
6326
6327void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
6328 NEONLoadStoreSingleStructHelper(instr, Offset);
6329}
6330
6331
6332void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
6333 const Instruction* instr) {
6334 NEONLoadStoreSingleStructHelper(instr, PostIndex);
6335}
6336
6337
6338void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
6339 SimVRegister& rd = ReadVRegister(instr->GetRd());
6340 int cmode = instr->GetNEONCmode();
6341 int cmode_3_1 = (cmode >> 1) & 7;
6342 int cmode_3 = (cmode >> 3) & 1;
6343 int cmode_2 = (cmode >> 2) & 1;
6344 int cmode_1 = (cmode >> 1) & 1;
6345 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006346 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006347 int q = instr->GetNEONQ();
6348 int op_bit = instr->GetNEONModImmOp();
6349 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006350 // Find the format and immediate value
6351 uint64_t imm = 0;
6352 VectorFormat vform = kFormatUndefined;
6353 switch (cmode_3_1) {
6354 case 0x0:
6355 case 0x1:
6356 case 0x2:
6357 case 0x3:
6358 vform = (q == 1) ? kFormat4S : kFormat2S;
6359 imm = imm8 << (8 * cmode_3_1);
6360 break;
6361 case 0x4:
6362 case 0x5:
6363 vform = (q == 1) ? kFormat8H : kFormat4H;
6364 imm = imm8 << (8 * cmode_1);
6365 break;
6366 case 0x6:
6367 vform = (q == 1) ? kFormat4S : kFormat2S;
6368 if (cmode_0 == 0) {
6369 imm = imm8 << 8 | 0x000000ff;
6370 } else {
6371 imm = imm8 << 16 | 0x0000ffff;
6372 }
6373 break;
6374 case 0x7:
6375 if (cmode_0 == 0 && op_bit == 0) {
6376 vform = q ? kFormat16B : kFormat8B;
6377 imm = imm8;
6378 } else if (cmode_0 == 0 && op_bit == 1) {
6379 vform = q ? kFormat2D : kFormat1D;
6380 imm = 0;
6381 for (int i = 0; i < 8; ++i) {
6382 if (imm8 & (1 << i)) {
6383 imm |= (UINT64_C(0xff) << (8 * i));
6384 }
6385 }
6386 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01006387 if (half_enc == 1) {
6388 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01006389 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006390 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006391 vform = q ? kFormat4S : kFormat2S;
6392 imm = FloatToRawbits(instr->GetImmNEONFP32());
6393 } else if (q == 1) {
6394 vform = kFormat2D;
6395 imm = DoubleToRawbits(instr->GetImmNEONFP64());
6396 } else {
6397 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
6398 VisitUnallocated(instr);
6399 }
6400 }
6401 break;
6402 default:
6403 VIXL_UNREACHABLE();
6404 break;
6405 }
6406
6407 // Find the operation
6408 NEONModifiedImmediateOp op;
6409 if (cmode_3 == 0) {
6410 if (cmode_0 == 0) {
6411 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6412 } else { // cmode<0> == '1'
6413 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6414 }
6415 } else { // cmode<3> == '1'
6416 if (cmode_2 == 0) {
6417 if (cmode_0 == 0) {
6418 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6419 } else { // cmode<0> == '1'
6420 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6421 }
6422 } else { // cmode<2> == '1'
6423 if (cmode_1 == 0) {
6424 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6425 } else { // cmode<1> == '1'
6426 if (cmode_0 == 0) {
6427 op = NEONModifiedImmediate_MOVI;
6428 } else { // cmode<0> == '1'
6429 op = NEONModifiedImmediate_MOVI;
6430 }
6431 }
6432 }
6433 }
6434
6435 // Call the logic function
6436 if (op == NEONModifiedImmediate_ORR) {
6437 orr(vform, rd, rd, imm);
6438 } else if (op == NEONModifiedImmediate_BIC) {
6439 bic(vform, rd, rd, imm);
6440 } else if (op == NEONModifiedImmediate_MOVI) {
6441 movi(vform, rd, imm);
6442 } else if (op == NEONModifiedImmediate_MVNI) {
6443 mvni(vform, rd, imm);
6444 } else {
6445 VisitUnimplemented(instr);
6446 }
6447}
6448
6449
6450void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
6451 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6452 VectorFormat vf = nfd.GetVectorFormat();
6453
6454 SimVRegister& rd = ReadVRegister(instr->GetRd());
6455 SimVRegister& rn = ReadVRegister(instr->GetRn());
6456
6457 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
6458 // These instructions all use a two bit size field, except NOT and RBIT,
6459 // which use the field to encode the operation.
6460 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6461 case NEON_CMEQ_zero_scalar:
6462 cmp(vf, rd, rn, 0, eq);
6463 break;
6464 case NEON_CMGE_zero_scalar:
6465 cmp(vf, rd, rn, 0, ge);
6466 break;
6467 case NEON_CMGT_zero_scalar:
6468 cmp(vf, rd, rn, 0, gt);
6469 break;
6470 case NEON_CMLT_zero_scalar:
6471 cmp(vf, rd, rn, 0, lt);
6472 break;
6473 case NEON_CMLE_zero_scalar:
6474 cmp(vf, rd, rn, 0, le);
6475 break;
6476 case NEON_ABS_scalar:
6477 abs(vf, rd, rn);
6478 break;
6479 case NEON_SQABS_scalar:
6480 abs(vf, rd, rn).SignedSaturate(vf);
6481 break;
6482 case NEON_NEG_scalar:
6483 neg(vf, rd, rn);
6484 break;
6485 case NEON_SQNEG_scalar:
6486 neg(vf, rd, rn).SignedSaturate(vf);
6487 break;
6488 case NEON_SUQADD_scalar:
6489 suqadd(vf, rd, rn);
6490 break;
6491 case NEON_USQADD_scalar:
6492 usqadd(vf, rd, rn);
6493 break;
6494 default:
6495 VIXL_UNIMPLEMENTED();
6496 break;
6497 }
6498 } else {
6499 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6500 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6501
6502 // These instructions all use a one bit size field, except SQXTUN, SQXTN
6503 // and UQXTN, which use a two bit size field.
6504 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
6505 case NEON_FRECPE_scalar:
6506 frecpe(fpf, rd, rn, fpcr_rounding);
6507 break;
6508 case NEON_FRECPX_scalar:
6509 frecpx(fpf, rd, rn);
6510 break;
6511 case NEON_FRSQRTE_scalar:
6512 frsqrte(fpf, rd, rn);
6513 break;
6514 case NEON_FCMGT_zero_scalar:
6515 fcmp_zero(fpf, rd, rn, gt);
6516 break;
6517 case NEON_FCMGE_zero_scalar:
6518 fcmp_zero(fpf, rd, rn, ge);
6519 break;
6520 case NEON_FCMEQ_zero_scalar:
6521 fcmp_zero(fpf, rd, rn, eq);
6522 break;
6523 case NEON_FCMLE_zero_scalar:
6524 fcmp_zero(fpf, rd, rn, le);
6525 break;
6526 case NEON_FCMLT_zero_scalar:
6527 fcmp_zero(fpf, rd, rn, lt);
6528 break;
6529 case NEON_SCVTF_scalar:
6530 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6531 break;
6532 case NEON_UCVTF_scalar:
6533 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6534 break;
6535 case NEON_FCVTNS_scalar:
6536 fcvts(fpf, rd, rn, FPTieEven);
6537 break;
6538 case NEON_FCVTNU_scalar:
6539 fcvtu(fpf, rd, rn, FPTieEven);
6540 break;
6541 case NEON_FCVTPS_scalar:
6542 fcvts(fpf, rd, rn, FPPositiveInfinity);
6543 break;
6544 case NEON_FCVTPU_scalar:
6545 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6546 break;
6547 case NEON_FCVTMS_scalar:
6548 fcvts(fpf, rd, rn, FPNegativeInfinity);
6549 break;
6550 case NEON_FCVTMU_scalar:
6551 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6552 break;
6553 case NEON_FCVTZS_scalar:
6554 fcvts(fpf, rd, rn, FPZero);
6555 break;
6556 case NEON_FCVTZU_scalar:
6557 fcvtu(fpf, rd, rn, FPZero);
6558 break;
6559 case NEON_FCVTAS_scalar:
6560 fcvts(fpf, rd, rn, FPTieAway);
6561 break;
6562 case NEON_FCVTAU_scalar:
6563 fcvtu(fpf, rd, rn, FPTieAway);
6564 break;
6565 case NEON_FCVTXN_scalar:
6566 // Unlike all of the other FP instructions above, fcvtxn encodes dest
6567 // size S as size<0>=1. There's only one case, so we ignore the form.
6568 VIXL_ASSERT(instr->ExtractBit(22) == 1);
6569 fcvtxn(kFormatS, rd, rn);
6570 break;
6571 default:
6572 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6573 case NEON_SQXTN_scalar:
6574 sqxtn(vf, rd, rn);
6575 break;
6576 case NEON_UQXTN_scalar:
6577 uqxtn(vf, rd, rn);
6578 break;
6579 case NEON_SQXTUN_scalar:
6580 sqxtun(vf, rd, rn);
6581 break;
6582 default:
6583 VIXL_UNIMPLEMENTED();
6584 }
6585 }
6586 }
6587}
6588
6589
Jacob Bramleyca789742018-09-13 14:25:46 +01006590void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
6591 VectorFormat fpf = kFormatH;
6592 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6593
6594 SimVRegister& rd = ReadVRegister(instr->GetRd());
6595 SimVRegister& rn = ReadVRegister(instr->GetRn());
6596
6597 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6598 case NEON_FRECPE_H_scalar:
6599 frecpe(fpf, rd, rn, fpcr_rounding);
6600 break;
6601 case NEON_FRECPX_H_scalar:
6602 frecpx(fpf, rd, rn);
6603 break;
6604 case NEON_FRSQRTE_H_scalar:
6605 frsqrte(fpf, rd, rn);
6606 break;
6607 case NEON_FCMGT_H_zero_scalar:
6608 fcmp_zero(fpf, rd, rn, gt);
6609 break;
6610 case NEON_FCMGE_H_zero_scalar:
6611 fcmp_zero(fpf, rd, rn, ge);
6612 break;
6613 case NEON_FCMEQ_H_zero_scalar:
6614 fcmp_zero(fpf, rd, rn, eq);
6615 break;
6616 case NEON_FCMLE_H_zero_scalar:
6617 fcmp_zero(fpf, rd, rn, le);
6618 break;
6619 case NEON_FCMLT_H_zero_scalar:
6620 fcmp_zero(fpf, rd, rn, lt);
6621 break;
6622 case NEON_SCVTF_H_scalar:
6623 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6624 break;
6625 case NEON_UCVTF_H_scalar:
6626 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6627 break;
6628 case NEON_FCVTNS_H_scalar:
6629 fcvts(fpf, rd, rn, FPTieEven);
6630 break;
6631 case NEON_FCVTNU_H_scalar:
6632 fcvtu(fpf, rd, rn, FPTieEven);
6633 break;
6634 case NEON_FCVTPS_H_scalar:
6635 fcvts(fpf, rd, rn, FPPositiveInfinity);
6636 break;
6637 case NEON_FCVTPU_H_scalar:
6638 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6639 break;
6640 case NEON_FCVTMS_H_scalar:
6641 fcvts(fpf, rd, rn, FPNegativeInfinity);
6642 break;
6643 case NEON_FCVTMU_H_scalar:
6644 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6645 break;
6646 case NEON_FCVTZS_H_scalar:
6647 fcvts(fpf, rd, rn, FPZero);
6648 break;
6649 case NEON_FCVTZU_H_scalar:
6650 fcvtu(fpf, rd, rn, FPZero);
6651 break;
6652 case NEON_FCVTAS_H_scalar:
6653 fcvts(fpf, rd, rn, FPTieAway);
6654 break;
6655 case NEON_FCVTAU_H_scalar:
6656 fcvtu(fpf, rd, rn, FPTieAway);
6657 break;
6658 }
6659}
6660
6661
Alexandre Ramesd3832962016-07-04 15:03:43 +01006662void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6663 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6664 VectorFormat vf = nfd.GetVectorFormat();
6665
6666 SimVRegister& rd = ReadVRegister(instr->GetRd());
6667 SimVRegister& rn = ReadVRegister(instr->GetRn());
6668 SimVRegister& rm = ReadVRegister(instr->GetRm());
6669 switch (instr->Mask(NEONScalar3DiffMask)) {
6670 case NEON_SQDMLAL_scalar:
6671 sqdmlal(vf, rd, rn, rm);
6672 break;
6673 case NEON_SQDMLSL_scalar:
6674 sqdmlsl(vf, rd, rn, rm);
6675 break;
6676 case NEON_SQDMULL_scalar:
6677 sqdmull(vf, rd, rn, rm);
6678 break;
6679 default:
6680 VIXL_UNIMPLEMENTED();
6681 }
6682}
6683
6684
6685void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6686 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6687 VectorFormat vf = nfd.GetVectorFormat();
6688
6689 SimVRegister& rd = ReadVRegister(instr->GetRd());
6690 SimVRegister& rn = ReadVRegister(instr->GetRn());
6691 SimVRegister& rm = ReadVRegister(instr->GetRm());
6692
6693 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6694 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6695 switch (instr->Mask(NEONScalar3SameFPMask)) {
6696 case NEON_FMULX_scalar:
6697 fmulx(vf, rd, rn, rm);
6698 break;
6699 case NEON_FACGE_scalar:
6700 fabscmp(vf, rd, rn, rm, ge);
6701 break;
6702 case NEON_FACGT_scalar:
6703 fabscmp(vf, rd, rn, rm, gt);
6704 break;
6705 case NEON_FCMEQ_scalar:
6706 fcmp(vf, rd, rn, rm, eq);
6707 break;
6708 case NEON_FCMGE_scalar:
6709 fcmp(vf, rd, rn, rm, ge);
6710 break;
6711 case NEON_FCMGT_scalar:
6712 fcmp(vf, rd, rn, rm, gt);
6713 break;
6714 case NEON_FRECPS_scalar:
6715 frecps(vf, rd, rn, rm);
6716 break;
6717 case NEON_FRSQRTS_scalar:
6718 frsqrts(vf, rd, rn, rm);
6719 break;
6720 case NEON_FABD_scalar:
6721 fabd(vf, rd, rn, rm);
6722 break;
6723 default:
6724 VIXL_UNIMPLEMENTED();
6725 }
6726 } else {
6727 switch (instr->Mask(NEONScalar3SameMask)) {
6728 case NEON_ADD_scalar:
6729 add(vf, rd, rn, rm);
6730 break;
6731 case NEON_SUB_scalar:
6732 sub(vf, rd, rn, rm);
6733 break;
6734 case NEON_CMEQ_scalar:
6735 cmp(vf, rd, rn, rm, eq);
6736 break;
6737 case NEON_CMGE_scalar:
6738 cmp(vf, rd, rn, rm, ge);
6739 break;
6740 case NEON_CMGT_scalar:
6741 cmp(vf, rd, rn, rm, gt);
6742 break;
6743 case NEON_CMHI_scalar:
6744 cmp(vf, rd, rn, rm, hi);
6745 break;
6746 case NEON_CMHS_scalar:
6747 cmp(vf, rd, rn, rm, hs);
6748 break;
6749 case NEON_CMTST_scalar:
6750 cmptst(vf, rd, rn, rm);
6751 break;
6752 case NEON_USHL_scalar:
6753 ushl(vf, rd, rn, rm);
6754 break;
6755 case NEON_SSHL_scalar:
6756 sshl(vf, rd, rn, rm);
6757 break;
6758 case NEON_SQDMULH_scalar:
6759 sqdmulh(vf, rd, rn, rm);
6760 break;
6761 case NEON_SQRDMULH_scalar:
6762 sqrdmulh(vf, rd, rn, rm);
6763 break;
6764 case NEON_UQADD_scalar:
6765 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6766 break;
6767 case NEON_SQADD_scalar:
6768 add(vf, rd, rn, rm).SignedSaturate(vf);
6769 break;
6770 case NEON_UQSUB_scalar:
6771 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6772 break;
6773 case NEON_SQSUB_scalar:
6774 sub(vf, rd, rn, rm).SignedSaturate(vf);
6775 break;
6776 case NEON_UQSHL_scalar:
6777 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6778 break;
6779 case NEON_SQSHL_scalar:
6780 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6781 break;
6782 case NEON_URSHL_scalar:
6783 ushl(vf, rd, rn, rm).Round(vf);
6784 break;
6785 case NEON_SRSHL_scalar:
6786 sshl(vf, rd, rn, rm).Round(vf);
6787 break;
6788 case NEON_UQRSHL_scalar:
6789 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6790 break;
6791 case NEON_SQRSHL_scalar:
6792 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6793 break;
6794 default:
6795 VIXL_UNIMPLEMENTED();
6796 }
6797 }
6798}
6799
Jacob Bramleyca789742018-09-13 14:25:46 +01006800void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6801 SimVRegister& rd = ReadVRegister(instr->GetRd());
6802 SimVRegister& rn = ReadVRegister(instr->GetRn());
6803 SimVRegister& rm = ReadVRegister(instr->GetRm());
6804
6805 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6806 case NEON_FABD_H_scalar:
6807 fabd(kFormatH, rd, rn, rm);
6808 break;
6809 case NEON_FMULX_H_scalar:
6810 fmulx(kFormatH, rd, rn, rm);
6811 break;
6812 case NEON_FCMEQ_H_scalar:
6813 fcmp(kFormatH, rd, rn, rm, eq);
6814 break;
6815 case NEON_FCMGE_H_scalar:
6816 fcmp(kFormatH, rd, rn, rm, ge);
6817 break;
6818 case NEON_FCMGT_H_scalar:
6819 fcmp(kFormatH, rd, rn, rm, gt);
6820 break;
6821 case NEON_FACGE_H_scalar:
6822 fabscmp(kFormatH, rd, rn, rm, ge);
6823 break;
6824 case NEON_FACGT_H_scalar:
6825 fabscmp(kFormatH, rd, rn, rm, gt);
6826 break;
6827 case NEON_FRECPS_H_scalar:
6828 frecps(kFormatH, rd, rn, rm);
6829 break;
6830 case NEON_FRSQRTS_H_scalar:
6831 frsqrts(kFormatH, rd, rn, rm);
6832 break;
6833 default:
6834 VIXL_UNREACHABLE();
6835 }
6836}
6837
Alexandre Ramesd3832962016-07-04 15:03:43 +01006838
Alexander Gilday43785642018-04-04 13:42:33 +01006839void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6840 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6841 VectorFormat vf = nfd.GetVectorFormat();
6842
6843 SimVRegister& rd = ReadVRegister(instr->GetRd());
6844 SimVRegister& rn = ReadVRegister(instr->GetRn());
6845 SimVRegister& rm = ReadVRegister(instr->GetRm());
6846
6847 switch (instr->Mask(NEONScalar3SameExtraMask)) {
6848 case NEON_SQRDMLAH_scalar:
6849 sqrdmlah(vf, rd, rn, rm);
6850 break;
6851 case NEON_SQRDMLSH_scalar:
6852 sqrdmlsh(vf, rd, rn, rm);
6853 break;
6854 default:
6855 VIXL_UNIMPLEMENTED();
6856 }
6857}
6858
Alexandre Ramesd3832962016-07-04 15:03:43 +01006859void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6860 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6861 VectorFormat vf = nfd.GetVectorFormat();
6862 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6863
6864 SimVRegister& rd = ReadVRegister(instr->GetRd());
6865 SimVRegister& rn = ReadVRegister(instr->GetRn());
6866 ByElementOp Op = NULL;
6867
6868 int rm_reg = instr->GetRm();
6869 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6870 if (instr->GetNEONSize() == 1) {
6871 rm_reg &= 0xf;
6872 index = (index << 1) | instr->GetNEONM();
6873 }
6874
6875 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6876 case NEON_SQDMULL_byelement_scalar:
6877 Op = &Simulator::sqdmull;
6878 break;
6879 case NEON_SQDMLAL_byelement_scalar:
6880 Op = &Simulator::sqdmlal;
6881 break;
6882 case NEON_SQDMLSL_byelement_scalar:
6883 Op = &Simulator::sqdmlsl;
6884 break;
6885 case NEON_SQDMULH_byelement_scalar:
6886 Op = &Simulator::sqdmulh;
6887 vf = vf_r;
6888 break;
6889 case NEON_SQRDMULH_byelement_scalar:
6890 Op = &Simulator::sqrdmulh;
6891 vf = vf_r;
6892 break;
Alexander Gilday43785642018-04-04 13:42:33 +01006893 case NEON_SQRDMLAH_byelement_scalar:
6894 Op = &Simulator::sqrdmlah;
6895 vf = vf_r;
6896 break;
6897 case NEON_SQRDMLSH_byelement_scalar:
6898 Op = &Simulator::sqrdmlsh;
6899 vf = vf_r;
6900 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006901 default:
6902 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6903 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01006904 if (instr->GetFPType() == 0) {
6905 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6906 rm_reg &= 0xf;
6907 vf = kFormatH;
6908 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006909 index = (index << 1) | instr->GetNEONL();
6910 }
6911 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006912 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006913 case NEON_FMUL_byelement_scalar:
6914 Op = &Simulator::fmul;
6915 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006916 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006917 case NEON_FMLA_byelement_scalar:
6918 Op = &Simulator::fmla;
6919 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006920 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006921 case NEON_FMLS_byelement_scalar:
6922 Op = &Simulator::fmls;
6923 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006924 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006925 case NEON_FMULX_byelement_scalar:
6926 Op = &Simulator::fmulx;
6927 break;
6928 default:
6929 VIXL_UNIMPLEMENTED();
6930 }
6931 }
6932
6933 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6934}
6935
6936
6937void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6938 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6939 VectorFormat vf = nfd.GetVectorFormat();
6940
6941 SimVRegister& rd = ReadVRegister(instr->GetRd());
6942 SimVRegister& rn = ReadVRegister(instr->GetRn());
6943
6944 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6945 int imm5 = instr->GetImmNEON5();
6946 int tz = CountTrailingZeros(imm5, 32);
6947 int rn_index = imm5 >> (tz + 1);
6948 dup_element(vf, rd, rn, rn_index);
6949 } else {
6950 VIXL_UNIMPLEMENTED();
6951 }
6952}
6953
6954
6955void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006956 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006957 VectorFormat vf = nfd.GetVectorFormat();
6958
6959 SimVRegister& rd = ReadVRegister(instr->GetRd());
6960 SimVRegister& rn = ReadVRegister(instr->GetRn());
6961 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006962 case NEON_ADDP_scalar: {
6963 // All pairwise operations except ADDP use bit U to differentiate FP16
6964 // from FP32/FP64 variations.
6965 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6966 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006967 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006968 }
6969 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006970 case NEON_FADDP_scalar:
6971 faddp(vf, rd, rn);
6972 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006973 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006974 case NEON_FMAXP_scalar:
6975 fmaxp(vf, rd, rn);
6976 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006977 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006978 case NEON_FMAXNMP_scalar:
6979 fmaxnmp(vf, rd, rn);
6980 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006981 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006982 case NEON_FMINP_scalar:
6983 fminp(vf, rd, rn);
6984 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006985 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006986 case NEON_FMINNMP_scalar:
6987 fminnmp(vf, rd, rn);
6988 break;
6989 default:
6990 VIXL_UNIMPLEMENTED();
6991 }
6992}
6993
6994
6995void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6996 SimVRegister& rd = ReadVRegister(instr->GetRd());
6997 SimVRegister& rn = ReadVRegister(instr->GetRn());
6998 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6999
7000 static const NEONFormatMap map = {{22, 21, 20, 19},
7001 {NF_UNDEF,
7002 NF_B,
7003 NF_H,
7004 NF_H,
7005 NF_S,
7006 NF_S,
7007 NF_S,
7008 NF_S,
7009 NF_D,
7010 NF_D,
7011 NF_D,
7012 NF_D,
7013 NF_D,
7014 NF_D,
7015 NF_D,
7016 NF_D}};
7017 NEONFormatDecoder nfd(instr, &map);
7018 VectorFormat vf = nfd.GetVectorFormat();
7019
7020 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
7021 int immhimmb = instr->GetImmNEONImmhImmb();
7022 int right_shift = (16 << highestSetBit) - immhimmb;
7023 int left_shift = immhimmb - (8 << highestSetBit);
7024 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
7025 case NEON_SHL_scalar:
7026 shl(vf, rd, rn, left_shift);
7027 break;
7028 case NEON_SLI_scalar:
7029 sli(vf, rd, rn, left_shift);
7030 break;
7031 case NEON_SQSHL_imm_scalar:
7032 sqshl(vf, rd, rn, left_shift);
7033 break;
7034 case NEON_UQSHL_imm_scalar:
7035 uqshl(vf, rd, rn, left_shift);
7036 break;
7037 case NEON_SQSHLU_scalar:
7038 sqshlu(vf, rd, rn, left_shift);
7039 break;
7040 case NEON_SRI_scalar:
7041 sri(vf, rd, rn, right_shift);
7042 break;
7043 case NEON_SSHR_scalar:
7044 sshr(vf, rd, rn, right_shift);
7045 break;
7046 case NEON_USHR_scalar:
7047 ushr(vf, rd, rn, right_shift);
7048 break;
7049 case NEON_SRSHR_scalar:
7050 sshr(vf, rd, rn, right_shift).Round(vf);
7051 break;
7052 case NEON_URSHR_scalar:
7053 ushr(vf, rd, rn, right_shift).Round(vf);
7054 break;
7055 case NEON_SSRA_scalar:
7056 ssra(vf, rd, rn, right_shift);
7057 break;
7058 case NEON_USRA_scalar:
7059 usra(vf, rd, rn, right_shift);
7060 break;
7061 case NEON_SRSRA_scalar:
7062 srsra(vf, rd, rn, right_shift);
7063 break;
7064 case NEON_URSRA_scalar:
7065 ursra(vf, rd, rn, right_shift);
7066 break;
7067 case NEON_UQSHRN_scalar:
7068 uqshrn(vf, rd, rn, right_shift);
7069 break;
7070 case NEON_UQRSHRN_scalar:
7071 uqrshrn(vf, rd, rn, right_shift);
7072 break;
7073 case NEON_SQSHRN_scalar:
7074 sqshrn(vf, rd, rn, right_shift);
7075 break;
7076 case NEON_SQRSHRN_scalar:
7077 sqrshrn(vf, rd, rn, right_shift);
7078 break;
7079 case NEON_SQSHRUN_scalar:
7080 sqshrun(vf, rd, rn, right_shift);
7081 break;
7082 case NEON_SQRSHRUN_scalar:
7083 sqrshrun(vf, rd, rn, right_shift);
7084 break;
7085 case NEON_FCVTZS_imm_scalar:
7086 fcvts(vf, rd, rn, FPZero, right_shift);
7087 break;
7088 case NEON_FCVTZU_imm_scalar:
7089 fcvtu(vf, rd, rn, FPZero, right_shift);
7090 break;
7091 case NEON_SCVTF_imm_scalar:
7092 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7093 break;
7094 case NEON_UCVTF_imm_scalar:
7095 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7096 break;
7097 default:
7098 VIXL_UNIMPLEMENTED();
7099 }
7100}
7101
7102
7103void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
7104 SimVRegister& rd = ReadVRegister(instr->GetRd());
7105 SimVRegister& rn = ReadVRegister(instr->GetRn());
7106 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
7107
7108 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
7109 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
7110 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01007111 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
7112 NF_4H, NF_8H, NF_4H, NF_8H,
7113 NF_2S, NF_4S, NF_2S, NF_4S,
7114 NF_2S, NF_4S, NF_2S, NF_4S,
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,
7118 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01007119 NEONFormatDecoder nfd(instr, &map);
7120 VectorFormat vf = nfd.GetVectorFormat();
7121
7122 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
7123 static const NEONFormatMap map_l =
7124 {{22, 21, 20, 19},
7125 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
7126 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
7127
7128 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
7129 int immhimmb = instr->GetImmNEONImmhImmb();
7130 int right_shift = (16 << highestSetBit) - immhimmb;
7131 int left_shift = immhimmb - (8 << highestSetBit);
7132
7133 switch (instr->Mask(NEONShiftImmediateMask)) {
7134 case NEON_SHL:
7135 shl(vf, rd, rn, left_shift);
7136 break;
7137 case NEON_SLI:
7138 sli(vf, rd, rn, left_shift);
7139 break;
7140 case NEON_SQSHLU:
7141 sqshlu(vf, rd, rn, left_shift);
7142 break;
7143 case NEON_SRI:
7144 sri(vf, rd, rn, right_shift);
7145 break;
7146 case NEON_SSHR:
7147 sshr(vf, rd, rn, right_shift);
7148 break;
7149 case NEON_USHR:
7150 ushr(vf, rd, rn, right_shift);
7151 break;
7152 case NEON_SRSHR:
7153 sshr(vf, rd, rn, right_shift).Round(vf);
7154 break;
7155 case NEON_URSHR:
7156 ushr(vf, rd, rn, right_shift).Round(vf);
7157 break;
7158 case NEON_SSRA:
7159 ssra(vf, rd, rn, right_shift);
7160 break;
7161 case NEON_USRA:
7162 usra(vf, rd, rn, right_shift);
7163 break;
7164 case NEON_SRSRA:
7165 srsra(vf, rd, rn, right_shift);
7166 break;
7167 case NEON_URSRA:
7168 ursra(vf, rd, rn, right_shift);
7169 break;
7170 case NEON_SQSHL_imm:
7171 sqshl(vf, rd, rn, left_shift);
7172 break;
7173 case NEON_UQSHL_imm:
7174 uqshl(vf, rd, rn, left_shift);
7175 break;
7176 case NEON_SCVTF_imm:
7177 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7178 break;
7179 case NEON_UCVTF_imm:
7180 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7181 break;
7182 case NEON_FCVTZS_imm:
7183 fcvts(vf, rd, rn, FPZero, right_shift);
7184 break;
7185 case NEON_FCVTZU_imm:
7186 fcvtu(vf, rd, rn, FPZero, right_shift);
7187 break;
7188 case NEON_SSHLL:
7189 vf = vf_l;
7190 if (instr->Mask(NEON_Q)) {
7191 sshll2(vf, rd, rn, left_shift);
7192 } else {
7193 sshll(vf, rd, rn, left_shift);
7194 }
7195 break;
7196 case NEON_USHLL:
7197 vf = vf_l;
7198 if (instr->Mask(NEON_Q)) {
7199 ushll2(vf, rd, rn, left_shift);
7200 } else {
7201 ushll(vf, rd, rn, left_shift);
7202 }
7203 break;
7204 case NEON_SHRN:
7205 if (instr->Mask(NEON_Q)) {
7206 shrn2(vf, rd, rn, right_shift);
7207 } else {
7208 shrn(vf, rd, rn, right_shift);
7209 }
7210 break;
7211 case NEON_RSHRN:
7212 if (instr->Mask(NEON_Q)) {
7213 rshrn2(vf, rd, rn, right_shift);
7214 } else {
7215 rshrn(vf, rd, rn, right_shift);
7216 }
7217 break;
7218 case NEON_UQSHRN:
7219 if (instr->Mask(NEON_Q)) {
7220 uqshrn2(vf, rd, rn, right_shift);
7221 } else {
7222 uqshrn(vf, rd, rn, right_shift);
7223 }
7224 break;
7225 case NEON_UQRSHRN:
7226 if (instr->Mask(NEON_Q)) {
7227 uqrshrn2(vf, rd, rn, right_shift);
7228 } else {
7229 uqrshrn(vf, rd, rn, right_shift);
7230 }
7231 break;
7232 case NEON_SQSHRN:
7233 if (instr->Mask(NEON_Q)) {
7234 sqshrn2(vf, rd, rn, right_shift);
7235 } else {
7236 sqshrn(vf, rd, rn, right_shift);
7237 }
7238 break;
7239 case NEON_SQRSHRN:
7240 if (instr->Mask(NEON_Q)) {
7241 sqrshrn2(vf, rd, rn, right_shift);
7242 } else {
7243 sqrshrn(vf, rd, rn, right_shift);
7244 }
7245 break;
7246 case NEON_SQSHRUN:
7247 if (instr->Mask(NEON_Q)) {
7248 sqshrun2(vf, rd, rn, right_shift);
7249 } else {
7250 sqshrun(vf, rd, rn, right_shift);
7251 }
7252 break;
7253 case NEON_SQRSHRUN:
7254 if (instr->Mask(NEON_Q)) {
7255 sqrshrun2(vf, rd, rn, right_shift);
7256 } else {
7257 sqrshrun(vf, rd, rn, right_shift);
7258 }
7259 break;
7260 default:
7261 VIXL_UNIMPLEMENTED();
7262 }
7263}
7264
7265
7266void Simulator::VisitNEONTable(const Instruction* instr) {
7267 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7268 VectorFormat vf = nfd.GetVectorFormat();
7269
7270 SimVRegister& rd = ReadVRegister(instr->GetRd());
7271 SimVRegister& rn = ReadVRegister(instr->GetRn());
7272 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
7273 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
7274 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
7275 SimVRegister& rm = ReadVRegister(instr->GetRm());
7276
7277 switch (instr->Mask(NEONTableMask)) {
7278 case NEON_TBL_1v:
7279 tbl(vf, rd, rn, rm);
7280 break;
7281 case NEON_TBL_2v:
7282 tbl(vf, rd, rn, rn2, rm);
7283 break;
7284 case NEON_TBL_3v:
7285 tbl(vf, rd, rn, rn2, rn3, rm);
7286 break;
7287 case NEON_TBL_4v:
7288 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
7289 break;
7290 case NEON_TBX_1v:
7291 tbx(vf, rd, rn, rm);
7292 break;
7293 case NEON_TBX_2v:
7294 tbx(vf, rd, rn, rn2, rm);
7295 break;
7296 case NEON_TBX_3v:
7297 tbx(vf, rd, rn, rn2, rn3, rm);
7298 break;
7299 case NEON_TBX_4v:
7300 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
7301 break;
7302 default:
7303 VIXL_UNIMPLEMENTED();
7304 }
7305}
7306
7307
7308void Simulator::VisitNEONPerm(const Instruction* instr) {
7309 NEONFormatDecoder nfd(instr);
7310 VectorFormat vf = nfd.GetVectorFormat();
7311
7312 SimVRegister& rd = ReadVRegister(instr->GetRd());
7313 SimVRegister& rn = ReadVRegister(instr->GetRn());
7314 SimVRegister& rm = ReadVRegister(instr->GetRm());
7315
7316 switch (instr->Mask(NEONPermMask)) {
7317 case NEON_TRN1:
7318 trn1(vf, rd, rn, rm);
7319 break;
7320 case NEON_TRN2:
7321 trn2(vf, rd, rn, rm);
7322 break;
7323 case NEON_UZP1:
7324 uzp1(vf, rd, rn, rm);
7325 break;
7326 case NEON_UZP2:
7327 uzp2(vf, rd, rn, rm);
7328 break;
7329 case NEON_ZIP1:
7330 zip1(vf, rd, rn, rm);
7331 break;
7332 case NEON_ZIP2:
7333 zip2(vf, rd, rn, rm);
7334 break;
7335 default:
7336 VIXL_UNIMPLEMENTED();
7337 }
7338}
7339
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007340void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
7341 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007342 switch (instr->Mask(SVEAddressGenerationMask)) {
7343 case ADR_z_az_d_s32_scaled:
7344 VIXL_UNIMPLEMENTED();
7345 break;
7346 case ADR_z_az_d_u32_scaled:
7347 VIXL_UNIMPLEMENTED();
7348 break;
7349 case ADR_z_az_sd_same_scaled:
7350 VIXL_UNIMPLEMENTED();
7351 break;
7352 default:
7353 VIXL_UNIMPLEMENTED();
7354 break;
7355 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007356}
7357
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007358void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
7359 const Instruction* instr) {
7360 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07007361 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007362 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007363 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07007364 case ORR_z_zi: {
7365 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7366 uint64_t imm = instr->GetSVEImmLogical();
7367 // Valid immediate is a non-zero bits
7368 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007369 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
7370 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07007371 SVEFormatFromLaneSizeInBytesLog2(lane_size),
7372 ReadVRegister(instr->GetRd()),
7373 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007374 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07007375 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007376 default:
7377 VIXL_UNIMPLEMENTED();
7378 break;
7379 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007380}
7381
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007382void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
7383 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
7384 case DUPM_z_i: {
7385 /* DUPM uses the same lane size and immediate encoding as bitwise logical
7386 * immediate instructions. */
7387 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7388 uint64_t imm = instr->GetSVEImmLogical();
7389 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7390 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
7391 break;
7392 }
7393 default:
7394 VIXL_UNIMPLEMENTED();
7395 break;
7396 }
7397}
7398
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007399void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
7400 USE(instr);
TatWai Chongcfb94212019-05-16 13:30:09 -07007401 SimVRegister& zd = ReadVRegister(instr->GetRd());
7402 SimVRegister& zn = ReadVRegister(instr->GetRn());
7403 SimVRegister& zm = ReadVRegister(instr->GetRm());
7404 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
7405
TatWai Chong13634762019-07-16 16:20:45 -07007406 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07007407 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007408 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007409 logical_op = AND;
7410 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007411 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007412 logical_op = BIC;
7413 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007414 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007415 logical_op = EOR;
7416 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07007417 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007418 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007419 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007420 default:
TatWai Chong13634762019-07-16 16:20:45 -07007421 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007422 VIXL_UNIMPLEMENTED();
7423 break;
7424 }
TatWai Chong13634762019-07-16 16:20:45 -07007425 // Lane size of registers is irrelevant to the bitwise operations, so perform
7426 // the operation on D-sized lanes.
7427 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007428}
7429
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007430void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007431 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007432 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007433 case ASRD_z_p_zi:
7434 VIXL_UNIMPLEMENTED();
7435 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007436 case ASR_z_p_zi:
7437 VIXL_UNIMPLEMENTED();
7438 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007439 case LSL_z_p_zi:
7440 VIXL_UNIMPLEMENTED();
7441 break;
7442 case LSR_z_p_zi:
7443 VIXL_UNIMPLEMENTED();
7444 break;
7445 default:
7446 VIXL_UNIMPLEMENTED();
7447 break;
7448 }
7449}
7450
7451void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
7452 const Instruction* instr) {
7453 USE(instr);
7454 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
7455 case ASRR_z_p_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007456 VIXL_UNIMPLEMENTED();
7457 break;
7458 case ASR_z_p_zz:
7459 VIXL_UNIMPLEMENTED();
7460 break;
7461 case LSLR_z_p_zz:
7462 VIXL_UNIMPLEMENTED();
7463 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007464 case LSL_z_p_zz:
7465 VIXL_UNIMPLEMENTED();
7466 break;
7467 case LSRR_z_p_zz:
7468 VIXL_UNIMPLEMENTED();
7469 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007470 case LSR_z_p_zz:
7471 VIXL_UNIMPLEMENTED();
7472 break;
7473 default:
7474 VIXL_UNIMPLEMENTED();
7475 break;
7476 }
7477}
7478
7479void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
7480 const Instruction* instr) {
7481 USE(instr);
7482 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
7483 case ASR_z_p_zw:
7484 VIXL_UNIMPLEMENTED();
7485 break;
7486 case LSL_z_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007487 VIXL_UNIMPLEMENTED();
7488 break;
7489 case LSR_z_p_zw:
7490 VIXL_UNIMPLEMENTED();
7491 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007492 default:
7493 VIXL_UNIMPLEMENTED();
7494 break;
7495 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007496}
7497
7498void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
7499 USE(instr);
TatWai Chong29a0c432019-11-06 22:20:44 -08007500
7501 SimVRegister& zd = ReadVRegister(instr->GetRd());
7502 SimVRegister& zn = ReadVRegister(instr->GetRn());
7503
7504 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007505 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7506 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007507 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007508 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007509 break;
7510 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007511 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007512 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007513 break;
7514 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08007515 case LSR_z_zw:
7516 shift_op = LSR;
7517 break;
7518 default:
7519 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007520 VIXL_UNIMPLEMENTED();
7521 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08007522 }
7523
7524 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7525 case ASR_z_zi:
7526 case LSL_z_zi:
7527 case LSR_z_zi: {
7528 SimVRegister scratch;
7529 std::pair<int, int> shift_and_lane_size =
7530 instr->GetSVEImmShiftAndLaneSizeLog2();
7531 unsigned lane_size = shift_and_lane_size.second;
7532 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
7533 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7534 dup_immediate(vform, scratch, shift_and_lane_size.first);
7535 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
7536 break;
7537 }
7538 case ASR_z_zw:
7539 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007540 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007541 SVEBitwiseShiftHelper(shift_op,
7542 instr->GetSVEVectorFormat(),
7543 zd,
7544 zn,
7545 ReadVRegister(instr->GetRm()),
7546 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007547 break;
7548 default:
7549 VIXL_UNIMPLEMENTED();
7550 break;
7551 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007552}
7553
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007554void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00007555 // Although the instructions have a separate encoding class, the lane size is
7556 // encoded in the same way as most other SVE instructions.
7557 VectorFormat vform = instr->GetSVEVectorFormat();
7558
7559 int pattern = instr->GetImmSVEPredicateConstraint();
7560 int count = GetPredicateConstraintLaneCount(vform, pattern);
7561 int multiplier = instr->ExtractBits(19, 16) + 1;
7562
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007563 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007564 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007565 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007566 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007567 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007568 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007569 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007570 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007571 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007572 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007573 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007574 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007575 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007576 default:
7577 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00007578 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007579 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00007580
7581 WriteXRegister(instr->GetRd(),
7582 IncDecN(ReadXRegister(instr->GetRd()),
7583 count * multiplier,
7584 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007585}
7586
7587void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007588 VectorFormat vform = instr->GetSVEVectorFormat();
7589 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7590 VIXL_UNIMPLEMENTED();
7591 }
7592
7593 int pattern = instr->GetImmSVEPredicateConstraint();
7594 int count = GetPredicateConstraintLaneCount(vform, pattern);
7595 int multiplier = instr->ExtractBits(19, 16) + 1;
7596
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007597 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
7598 case DECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007599 case DECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007600 case DECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007601 count = -count;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007602 break;
7603 case INCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007604 case INCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007605 case INCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007606 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007607 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007608 default:
7609 VIXL_UNIMPLEMENTED();
7610 break;
7611 }
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007612
7613 SimVRegister& zd = ReadVRegister(instr->GetRd());
7614 SimVRegister scratch;
7615 dup_immediate(vform,
7616 scratch,
7617 IncDecN(0,
7618 count * multiplier,
7619 LaneSizeInBitsFromFormat(vform)));
7620 add(vform, zd, zd, scratch);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007621}
7622
7623void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
7624 const Instruction* instr) {
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007625 // Although the instructions have a separate encoding class, the lane size is
7626 // encoded in the same way as most other SVE instructions.
7627 VectorFormat vform = instr->GetSVEVectorFormat();
7628
7629 int pattern = instr->GetImmSVEPredicateConstraint();
7630 int count = GetPredicateConstraintLaneCount(vform, pattern);
7631 int multiplier = instr->ExtractBits(19, 16) + 1;
7632
7633 unsigned width = kXRegSize;
7634 bool is_signed = false;
7635
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007636 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007637 case SQDECB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007638 case SQDECD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007639 case SQDECH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007640 case SQDECW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007641 width = kWRegSize;
7642 VIXL_FALLTHROUGH();
7643 case SQDECB_r_rs_x:
7644 case SQDECD_r_rs_x:
7645 case SQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007646 case SQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007647 is_signed = true;
7648 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007649 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007650 case SQINCB_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007651 case SQINCD_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007652 case SQINCH_r_rs_sx:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007653 case SQINCW_r_rs_sx:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007654 width = kWRegSize;
7655 VIXL_FALLTHROUGH();
7656 case SQINCB_r_rs_x:
7657 case SQINCD_r_rs_x:
7658 case SQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007659 case SQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007660 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007661 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007662 case UQDECB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007663 case UQDECD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007664 case UQDECH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007665 case UQDECW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007666 width = kWRegSize;
7667 VIXL_FALLTHROUGH();
7668 case UQDECB_r_rs_x:
7669 case UQDECD_r_rs_x:
7670 case UQDECH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007671 case UQDECW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007672 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007673 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007674 case UQINCB_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007675 case UQINCD_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007676 case UQINCH_r_rs_uw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007677 case UQINCW_r_rs_uw:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007678 width = kWRegSize;
7679 VIXL_FALLTHROUGH();
7680 case UQINCB_r_rs_x:
7681 case UQINCD_r_rs_x:
7682 case UQINCH_r_rs_x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007683 case UQINCW_r_rs_x:
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007684 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007685 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007686 default:
7687 VIXL_UNIMPLEMENTED();
7688 break;
7689 }
Martyn Capewell91d5ba32019-11-01 18:11:23 +00007690
7691 WriteXRegister(instr->GetRd(),
7692 IncDecN(ReadXRegister(instr->GetRd()),
7693 count * multiplier,
7694 width,
7695 true,
7696 is_signed));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007697}
7698
7699void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
7700 const Instruction* instr) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007701 VectorFormat vform = instr->GetSVEVectorFormat();
7702 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7703 VIXL_UNIMPLEMENTED();
7704 }
7705
7706 int pattern = instr->GetImmSVEPredicateConstraint();
7707 int count = GetPredicateConstraintLaneCount(vform, pattern);
7708 int multiplier = instr->ExtractBits(19, 16) + 1;
7709
7710 SimVRegister& zd = ReadVRegister(instr->GetRd());
7711 SimVRegister scratch;
7712 dup_immediate(vform,
7713 scratch,
7714 IncDecN(0,
7715 count * multiplier,
7716 LaneSizeInBitsFromFormat(vform)));
7717
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007718 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7719 case SQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007720 case SQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007721 case SQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007722 sub(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007723 break;
7724 case SQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007725 case SQINCH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007726 case SQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007727 add(vform, zd, zd, scratch).SignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007728 break;
7729 case UQDECD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007730 case UQDECH_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007731 case UQDECW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007732 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007733 break;
7734 case UQINCD_z_zs:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007735 case UQINCH_z_zs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007736 case UQINCW_z_zs:
Martyn Capewell8188ddf2019-11-21 17:09:34 +00007737 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007738 break;
7739 default:
7740 VIXL_UNIMPLEMENTED();
7741 break;
7742 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007743}
7744
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007745void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007746 switch (instr->Mask(SVEElementCountMask)) {
7747 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007748 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007749 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007750 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00007751 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007752 break;
7753 default:
7754 VIXL_UNIMPLEMENTED();
7755 break;
7756 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00007757
7758 // Although the instructions are separated, the lane size is encoded in the
7759 // same way as most other SVE instructions.
7760 VectorFormat vform = instr->GetSVEVectorFormat();
7761
7762 int pattern = instr->GetImmSVEPredicateConstraint();
7763 int count = GetPredicateConstraintLaneCount(vform, pattern);
7764 int multiplier = instr->ExtractBits(19, 16) + 1;
7765 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007766}
7767
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007768void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
Martyn Capewell4a9829f2020-01-30 17:41:01 +00007769 VectorFormat vform = instr->GetSVEVectorFormat();
7770 SimVRegister& vdn = ReadVRegister(instr->GetRd());
7771 SimVRegister& zm = ReadVRegister(instr->GetRn());
7772 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7773
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007774 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7775 case FADDA_v_p_z:
Martyn Capewell4a9829f2020-01-30 17:41:01 +00007776 fadda(vform, vdn, pg, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007777 break;
7778 default:
7779 VIXL_UNIMPLEMENTED();
7780 break;
7781 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007782}
7783
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007784void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007785 USE(instr);
TatWai Chongd316c5e2019-10-16 12:22:10 -07007786 VectorFormat vform = instr->GetSVEVectorFormat();
7787 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7788 SimVRegister& zm = ReadVRegister(instr->GetRn());
7789 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7790
7791 SimVRegister result;
7792
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007793 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007794 case FABD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007795 fabd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007796 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007797 case FADD_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007798 fadd(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007799 break;
7800 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007801 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007802 break;
7803 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007804 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007805 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007806 case FMAXNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007807 fmaxnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007808 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007809 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007810 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007811 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007812 case FMINNM_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007813 fminnm(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007814 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007815 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007816 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007817 break;
7818 case FMULX_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007819 fmulx(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007820 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007821 case FMUL_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007822 fmul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007823 break;
7824 case FSCALE_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007825 fscale(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007826 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007827 case FSUBR_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007828 fsub(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007829 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007830 case FSUB_z_p_zz:
Martyn Capewell37f28182020-01-14 10:15:10 +00007831 fsub(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007832 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007833 default:
7834 VIXL_UNIMPLEMENTED();
7835 break;
7836 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07007837 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007838}
7839
7840void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
7841 const Instruction* instr) {
7842 USE(instr);
7843 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
7844 case FADD_z_p_zs:
7845 VIXL_UNIMPLEMENTED();
7846 break;
7847 case FMAXNM_z_p_zs:
7848 VIXL_UNIMPLEMENTED();
7849 break;
7850 case FMAX_z_p_zs:
7851 VIXL_UNIMPLEMENTED();
7852 break;
7853 case FMINNM_z_p_zs:
7854 VIXL_UNIMPLEMENTED();
7855 break;
7856 case FMIN_z_p_zs:
7857 VIXL_UNIMPLEMENTED();
7858 break;
7859 case FMUL_z_p_zs:
7860 VIXL_UNIMPLEMENTED();
7861 break;
7862 case FSUBR_z_p_zs:
7863 VIXL_UNIMPLEMENTED();
7864 break;
7865 case FSUB_z_p_zs:
7866 VIXL_UNIMPLEMENTED();
7867 break;
7868 default:
7869 VIXL_UNIMPLEMENTED();
7870 break;
7871 }
7872}
7873
7874void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00007875 VectorFormat vform = instr->GetSVEVectorFormat();
7876 SimVRegister& zd = ReadVRegister(instr->GetRd());
7877 SimVRegister& zm = ReadVRegister(instr->GetRn());
7878
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007879 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007880 case FTMAD_z_zzi:
Martyn Capewell5fb2ad62020-01-10 14:08:27 +00007881 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007882 break;
7883 default:
7884 VIXL_UNIMPLEMENTED();
7885 break;
7886 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007887}
7888
7889void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
7890 USE(instr);
TatWai Chongfe536042019-10-23 16:34:11 -07007891
7892 VectorFormat vform = instr->GetSVEVectorFormat();
7893 SimVRegister& zd = ReadVRegister(instr->GetRd());
7894 SimVRegister& zn = ReadVRegister(instr->GetRn());
7895 SimVRegister& zm = ReadVRegister(instr->GetRm());
7896
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007897 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7898 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007899 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007900 break;
7901 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007902 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007903 break;
7904 case FRECPS_z_zz:
7905 VIXL_UNIMPLEMENTED();
7906 break;
7907 case FRSQRTS_z_zz:
7908 VIXL_UNIMPLEMENTED();
7909 break;
7910 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007911 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007912 break;
7913 case FTSMUL_z_zz:
7914 VIXL_UNIMPLEMENTED();
7915 break;
7916 default:
7917 VIXL_UNIMPLEMENTED();
7918 break;
7919 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007920}
7921
7922void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
7923 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007924 switch (instr->Mask(SVEFPCompareVectorsMask)) {
7925 case FACGE_p_p_zz:
7926 VIXL_UNIMPLEMENTED();
7927 break;
7928 case FACGT_p_p_zz:
7929 VIXL_UNIMPLEMENTED();
7930 break;
7931 case FCMEQ_p_p_zz:
7932 VIXL_UNIMPLEMENTED();
7933 break;
7934 case FCMGE_p_p_zz:
7935 VIXL_UNIMPLEMENTED();
7936 break;
7937 case FCMGT_p_p_zz:
7938 VIXL_UNIMPLEMENTED();
7939 break;
7940 case FCMNE_p_p_zz:
7941 VIXL_UNIMPLEMENTED();
7942 break;
7943 case FCMUO_p_p_zz:
7944 VIXL_UNIMPLEMENTED();
7945 break;
7946 default:
7947 VIXL_UNIMPLEMENTED();
7948 break;
7949 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007950}
7951
7952void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
7953 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007954 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
7955 case FCMEQ_p_p_z0:
7956 VIXL_UNIMPLEMENTED();
7957 break;
7958 case FCMGE_p_p_z0:
7959 VIXL_UNIMPLEMENTED();
7960 break;
7961 case FCMGT_p_p_z0:
7962 VIXL_UNIMPLEMENTED();
7963 break;
7964 case FCMLE_p_p_z0:
7965 VIXL_UNIMPLEMENTED();
7966 break;
7967 case FCMLT_p_p_z0:
7968 VIXL_UNIMPLEMENTED();
7969 break;
7970 case FCMNE_p_p_z0:
7971 VIXL_UNIMPLEMENTED();
7972 break;
7973 default:
7974 VIXL_UNIMPLEMENTED();
7975 break;
7976 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007977}
7978
7979void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
7980 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007981 switch (instr->Mask(SVEFPComplexAdditionMask)) {
7982 case FCADD_z_p_zz:
7983 VIXL_UNIMPLEMENTED();
7984 break;
7985 default:
7986 VIXL_UNIMPLEMENTED();
7987 break;
7988 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007989}
7990
7991void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
7992 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007993 switch (instr->Mask(SVEFPComplexMulAddMask)) {
7994 case FCMLA_z_p_zzz:
7995 VIXL_UNIMPLEMENTED();
7996 break;
7997 default:
7998 VIXL_UNIMPLEMENTED();
7999 break;
8000 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008001}
8002
8003void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
8004 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008005 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
8006 case FCMLA_z_zzzi_h:
8007 VIXL_UNIMPLEMENTED();
8008 break;
8009 case FCMLA_z_zzzi_s:
8010 VIXL_UNIMPLEMENTED();
8011 break;
8012 default:
8013 VIXL_UNIMPLEMENTED();
8014 break;
8015 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008016}
8017
8018void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
8019 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008020 switch (instr->Mask(SVEFPFastReductionMask)) {
8021 case FADDV_v_p_z:
8022 VIXL_UNIMPLEMENTED();
8023 break;
8024 case FMAXNMV_v_p_z:
8025 VIXL_UNIMPLEMENTED();
8026 break;
8027 case FMAXV_v_p_z:
8028 VIXL_UNIMPLEMENTED();
8029 break;
8030 case FMINNMV_v_p_z:
8031 VIXL_UNIMPLEMENTED();
8032 break;
8033 case FMINV_v_p_z:
8034 VIXL_UNIMPLEMENTED();
8035 break;
8036 default:
8037 VIXL_UNIMPLEMENTED();
8038 break;
8039 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008040}
8041
8042void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
Martyn Capewell50e9f552020-01-07 17:45:03 +00008043 VectorFormat vform = kFormatUndefined;
8044 unsigned zm_code = instr->GetRm() & 0xf;
8045 unsigned index = instr->ExtractBits(20, 19);
8046
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008047 switch (instr->Mask(SVEFPMulIndexMask)) {
8048 case FMUL_z_zzi_d:
Martyn Capewell50e9f552020-01-07 17:45:03 +00008049 vform = kFormatVnD;
8050 index >>= 1; // Only bit 20 is the index for D lanes.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008051 break;
Martyn Capewell50e9f552020-01-07 17:45:03 +00008052 case FMUL_z_zzi_h_i3h:
8053 index += 4; // Bit 22 (i3h) is the top bit of index.
8054 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008055 case FMUL_z_zzi_h:
Martyn Capewell50e9f552020-01-07 17:45:03 +00008056 vform = kFormatVnH;
8057 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008058 break;
8059 case FMUL_z_zzi_s:
Martyn Capewell50e9f552020-01-07 17:45:03 +00008060 vform = kFormatVnS;
8061 zm_code &= 7; // Three bits used for zm.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008062 break;
8063 default:
8064 VIXL_UNIMPLEMENTED();
8065 break;
8066 }
Martyn Capewell50e9f552020-01-07 17:45:03 +00008067
8068 SimVRegister& zd = ReadVRegister(instr->GetRd());
8069 SimVRegister& zn = ReadVRegister(instr->GetRn());
8070 SimVRegister temp;
8071
8072 dup_element(vform, temp, ReadVRegister(zm_code), index);
8073 fmul(vform, zd, zn, temp);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008074}
8075
8076void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
8077 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008078 switch (instr->Mask(SVEFPMulAddMask)) {
8079 case FMAD_z_p_zzz:
8080 VIXL_UNIMPLEMENTED();
8081 break;
8082 case FMLA_z_p_zzz:
8083 VIXL_UNIMPLEMENTED();
8084 break;
8085 case FMLS_z_p_zzz:
8086 VIXL_UNIMPLEMENTED();
8087 break;
8088 case FMSB_z_p_zzz:
8089 VIXL_UNIMPLEMENTED();
8090 break;
8091 case FNMAD_z_p_zzz:
8092 VIXL_UNIMPLEMENTED();
8093 break;
8094 case FNMLA_z_p_zzz:
8095 VIXL_UNIMPLEMENTED();
8096 break;
8097 case FNMLS_z_p_zzz:
8098 VIXL_UNIMPLEMENTED();
8099 break;
8100 case FNMSB_z_p_zzz:
8101 VIXL_UNIMPLEMENTED();
8102 break;
8103 default:
8104 VIXL_UNIMPLEMENTED();
8105 break;
8106 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008107}
8108
8109void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
8110 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008111 switch (instr->Mask(SVEFPMulAddIndexMask)) {
8112 case FMLA_z_zzzi_d:
8113 VIXL_UNIMPLEMENTED();
8114 break;
8115 case FMLA_z_zzzi_h:
8116 VIXL_UNIMPLEMENTED();
8117 break;
8118 case FMLA_z_zzzi_s:
8119 VIXL_UNIMPLEMENTED();
8120 break;
8121 case FMLS_z_zzzi_d:
8122 VIXL_UNIMPLEMENTED();
8123 break;
8124 case FMLS_z_zzzi_h:
8125 VIXL_UNIMPLEMENTED();
8126 break;
8127 case FMLS_z_zzzi_s:
8128 VIXL_UNIMPLEMENTED();
8129 break;
8130 default:
8131 VIXL_UNIMPLEMENTED();
8132 break;
8133 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008134}
8135
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008136void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
TatWai Chongdb7437c2020-01-09 17:44:10 -08008137 SimVRegister& zd = ReadVRegister(instr->GetRd());
8138 SimVRegister& zn = ReadVRegister(instr->GetRn());
8139 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8140 int dst_data_size;
8141 int src_data_size;
8142
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008143 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008144 case FCVTZS_z_p_z_d2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008145 case FCVTZU_z_p_z_d2w:
8146 dst_data_size = kSRegSize;
8147 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008148 break;
8149 case FCVTZS_z_p_z_d2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008150 case FCVTZU_z_p_z_d2x:
8151 dst_data_size = kDRegSize;
8152 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008153 break;
8154 case FCVTZS_z_p_z_fp162h:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008155 case FCVTZU_z_p_z_fp162h:
8156 dst_data_size = kHRegSize;
8157 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008158 break;
8159 case FCVTZS_z_p_z_fp162w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008160 case FCVTZU_z_p_z_fp162w:
8161 dst_data_size = kSRegSize;
8162 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008163 break;
8164 case FCVTZS_z_p_z_fp162x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008165 case FCVTZU_z_p_z_fp162x:
8166 dst_data_size = kDRegSize;
8167 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008168 break;
8169 case FCVTZS_z_p_z_s2w:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008170 case FCVTZU_z_p_z_s2w:
8171 dst_data_size = kSRegSize;
8172 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008173 break;
8174 case FCVTZS_z_p_z_s2x:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008175 case FCVTZU_z_p_z_s2x:
TatWai Chongdb7437c2020-01-09 17:44:10 -08008176 dst_data_size = kDRegSize;
8177 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008178 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008179 default:
8180 VIXL_UNIMPLEMENTED();
TatWai Chongdb7437c2020-01-09 17:44:10 -08008181 dst_data_size = 0;
8182 src_data_size = 0;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008183 break;
8184 }
TatWai Chongdb7437c2020-01-09 17:44:10 -08008185
8186 VectorFormat vform =
8187 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8188 USE(vform);
8189
8190 if (instr->ExtractBit(16) == 0) {
8191 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8192 } else {
8193 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8194 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008195}
8196
8197void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
8198 USE(instr);
8199 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008200 case FCVT_z_p_z_d2h:
8201 VIXL_UNIMPLEMENTED();
8202 break;
8203 case FCVT_z_p_z_d2s:
8204 VIXL_UNIMPLEMENTED();
8205 break;
8206 case FCVT_z_p_z_h2d:
8207 VIXL_UNIMPLEMENTED();
8208 break;
8209 case FCVT_z_p_z_h2s:
8210 VIXL_UNIMPLEMENTED();
8211 break;
8212 case FCVT_z_p_z_s2d:
8213 VIXL_UNIMPLEMENTED();
8214 break;
8215 case FCVT_z_p_z_s2h:
8216 VIXL_UNIMPLEMENTED();
8217 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008218 default:
8219 VIXL_UNIMPLEMENTED();
8220 break;
8221 }
8222}
8223
8224void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
8225 USE(instr);
8226 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008227 case FRECPX_z_p_z:
8228 VIXL_UNIMPLEMENTED();
8229 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008230 case FSQRT_z_p_z:
8231 VIXL_UNIMPLEMENTED();
8232 break;
8233 default:
8234 VIXL_UNIMPLEMENTED();
8235 break;
8236 }
8237}
8238
8239void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
8240 USE(instr);
8241 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008242 case FRINTA_z_p_z:
8243 VIXL_UNIMPLEMENTED();
8244 break;
8245 case FRINTI_z_p_z:
8246 VIXL_UNIMPLEMENTED();
8247 break;
8248 case FRINTM_z_p_z:
8249 VIXL_UNIMPLEMENTED();
8250 break;
8251 case FRINTN_z_p_z:
8252 VIXL_UNIMPLEMENTED();
8253 break;
8254 case FRINTP_z_p_z:
8255 VIXL_UNIMPLEMENTED();
8256 break;
8257 case FRINTX_z_p_z:
8258 VIXL_UNIMPLEMENTED();
8259 break;
8260 case FRINTZ_z_p_z:
8261 VIXL_UNIMPLEMENTED();
8262 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008263 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008264 VIXL_UNIMPLEMENTED();
8265 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008266 }
8267}
8268
8269void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
TatWai Chong31cd6a02020-01-10 13:03:26 -08008270 SimVRegister& zd = ReadVRegister(instr->GetRd());
8271 SimVRegister& zn = ReadVRegister(instr->GetRn());
8272 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8273 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8274 int dst_data_size;
8275 int src_data_size;
8276
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008277 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008278 case SCVTF_z_p_z_h2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008279 case UCVTF_z_p_z_h2fp16:
8280 dst_data_size = kHRegSize;
8281 src_data_size = kHRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008282 break;
8283 case SCVTF_z_p_z_w2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008284 case UCVTF_z_p_z_w2d:
8285 dst_data_size = kDRegSize;
8286 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008287 break;
8288 case SCVTF_z_p_z_w2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008289 case UCVTF_z_p_z_w2fp16:
8290 dst_data_size = kHRegSize;
8291 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008292 break;
8293 case SCVTF_z_p_z_w2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008294 case UCVTF_z_p_z_w2s:
8295 dst_data_size = kSRegSize;
8296 src_data_size = kSRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008297 break;
8298 case SCVTF_z_p_z_x2d:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008299 case UCVTF_z_p_z_x2d:
8300 dst_data_size = kDRegSize;
8301 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008302 break;
8303 case SCVTF_z_p_z_x2fp16:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008304 case UCVTF_z_p_z_x2fp16:
8305 dst_data_size = kHRegSize;
8306 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008307 break;
8308 case SCVTF_z_p_z_x2s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008309 case UCVTF_z_p_z_x2s:
TatWai Chong31cd6a02020-01-10 13:03:26 -08008310 dst_data_size = kSRegSize;
8311 src_data_size = kDRegSize;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008312 break;
8313 default:
8314 VIXL_UNIMPLEMENTED();
TatWai Chong31cd6a02020-01-10 13:03:26 -08008315 dst_data_size = 0;
8316 src_data_size = 0;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008317 break;
8318 }
TatWai Chong31cd6a02020-01-10 13:03:26 -08008319
8320 VectorFormat vform =
8321 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8322
8323 if (instr->ExtractBit(16) == 0) {
8324 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
8325 } else {
8326 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
8327 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008328}
8329
8330void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
8331 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008332 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8333 case FRECPE_z_z:
8334 VIXL_UNIMPLEMENTED();
8335 break;
8336 case FRSQRTE_z_z:
8337 VIXL_UNIMPLEMENTED();
8338 break;
8339 default:
8340 VIXL_UNIMPLEMENTED();
8341 break;
8342 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008343}
8344
8345void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
8346 USE(instr);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008347
8348 VectorFormat vform = instr->GetSVEVectorFormat();
8349 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
8350
8351 int count = CountActiveLanes(vform, pg);
8352
8353 if (instr->ExtractBit(11) == 0) {
8354 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8355 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8356 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008357 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008358 break;
8359 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008360 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008361 break;
8362 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008363 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008364 break;
8365 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008366 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008367 break;
8368 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008369 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008370 break;
8371 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008372 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008373 break;
8374 default:
8375 VIXL_UNIMPLEMENTED();
8376 break;
8377 }
8378 } else {
8379 bool is_saturating = (instr->ExtractBit(18) == 0);
8380 bool decrement =
8381 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
8382 bool is_signed = (instr->ExtractBit(16) == 0);
8383 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
8384 unsigned width = sf ? kXRegSize : kWRegSize;
8385
8386 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8387 case DECP_r_p_r:
8388 case INCP_r_p_r:
8389 case SQDECP_r_p_r_sx:
8390 case SQDECP_r_p_r_x:
8391 case SQINCP_r_p_r_sx:
8392 case SQINCP_r_p_r_x:
8393 case UQDECP_r_p_r_uw:
8394 case UQDECP_r_p_r_x:
8395 case UQINCP_r_p_r_uw:
8396 case UQINCP_r_p_r_x:
8397 WriteXRegister(instr->GetRd(),
8398 IncDecN(ReadXRegister(instr->GetRd()),
8399 decrement ? -count : count,
8400 width,
8401 is_saturating,
8402 is_signed));
8403 break;
8404 default:
8405 VIXL_UNIMPLEMENTED();
8406 break;
8407 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008408 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008409}
8410
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008411uint64_t Simulator::IncDecN(uint64_t acc,
8412 int64_t delta,
8413 unsigned n,
8414 bool is_saturating,
8415 bool is_signed) {
8416 VIXL_ASSERT(n <= 64);
8417 VIXL_ASSERT(IsIntN(n, delta));
8418
8419 uint64_t sign_mask = UINT64_C(1) << (n - 1);
8420 uint64_t mask = GetUintMask(n);
8421
8422 acc &= mask; // Ignore initial accumulator high bits.
8423 uint64_t result = (acc + delta) & mask;
8424
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008425 bool result_negative = ((result & sign_mask) != 0);
8426
8427 if (is_saturating) {
8428 if (is_signed) {
Martyn Capewell8188ddf2019-11-21 17:09:34 +00008429 bool acc_negative = ((acc & sign_mask) != 0);
8430 bool delta_negative = delta < 0;
8431
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008432 // If the signs of the operands are the same, but different from the
8433 // result, there was an overflow.
8434 if ((acc_negative == delta_negative) &&
8435 (acc_negative != result_negative)) {
8436 if (result_negative) {
8437 // Saturate to [..., INT<n>_MAX].
8438 result_negative = false;
8439 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
8440 } else {
8441 // Saturate to [INT<n>_MIN, ...].
8442 result_negative = true;
8443 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
8444 }
8445 }
8446 } else {
8447 if ((delta < 0) && (result > acc)) {
8448 // Saturate to [0, ...].
8449 result = 0;
8450 } else if ((delta > 0) && (result < acc)) {
8451 // Saturate to [..., UINT<n>_MAX].
8452 result = mask;
8453 }
8454 }
8455 }
8456
8457 // Sign-extend if necessary.
8458 if (result_negative && is_signed) result |= ~mask;
8459
8460 return result;
8461}
8462
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008463void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
8464 USE(instr);
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008465 VectorFormat vform = instr->GetSVEVectorFormat();
8466 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008467 switch (instr->Mask(SVEIndexGenerationMask)) {
8468 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008469 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008470 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008471 case INDEX_z_rr: {
8472 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
8473 : instr->ExtractSignedBits(9, 5);
8474 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
8475 : instr->ExtractSignedBits(20, 16);
8476 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008477 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008478 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008479 default:
8480 VIXL_UNIMPLEMENTED();
8481 break;
8482 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008483}
8484
8485void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
TatWai Chong845246b2019-08-08 00:01:58 -07008486 VectorFormat vform = instr->GetSVEVectorFormat();
8487 SimVRegister& zd = ReadVRegister(instr->GetRd());
8488 SimVRegister& zn = ReadVRegister(instr->GetRn());
8489 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008490 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8491 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008492 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008493 break;
8494 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008495 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008496 break;
8497 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008498 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008499 break;
8500 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008501 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008502 break;
8503 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008504 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008505 break;
8506 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008507 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008508 break;
8509 default:
8510 VIXL_UNIMPLEMENTED();
8511 break;
8512 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008513}
8514
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008515void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008516 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -07008517 VectorFormat vform = instr->GetSVEVectorFormat();
8518 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8519 SimVRegister& zm = ReadVRegister(instr->GetRn());
8520 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8521 SimVRegister result;
8522
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008523 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008524 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008525 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008526 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008527 case SUBR_z_p_zz:
8528 sub(vform, result, zm, zdn);
8529 break;
8530 case SUB_z_p_zz:
8531 sub(vform, result, zdn, zm);
8532 break;
8533 default:
8534 VIXL_UNIMPLEMENTED();
8535 break;
8536 }
8537 mov_merging(vform, zdn, pg, result);
8538}
8539
8540void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
8541 VectorFormat vform = instr->GetSVEVectorFormat();
8542 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8543 SimVRegister& zm = ReadVRegister(instr->GetRn());
8544 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8545 SimVRegister result;
8546
8547 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008548 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008549 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008550 break;
8551 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008552 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008553 break;
8554 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008555 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008556 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008557 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008558 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008559 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008560 default:
8561 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008562 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008563 }
8564 mov_merging(vform, zdn, pg, result);
8565}
8566
8567void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
8568 VectorFormat vform = instr->GetSVEVectorFormat();
8569 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8570 SimVRegister& zm = ReadVRegister(instr->GetRn());
8571 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8572 SimVRegister result;
8573
8574 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
8575 case MUL_z_p_zz:
8576 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008577 break;
8578 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008579 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008580 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008581 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008582 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008583 break;
8584 default:
8585 VIXL_UNIMPLEMENTED();
8586 break;
8587 }
TatWai Chong13634762019-07-16 16:20:45 -07008588 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008589}
8590
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008591void Simulator::VisitSVEIntMinMaxDifference_Predicated(
8592 const Instruction* instr) {
8593 VectorFormat vform = instr->GetSVEVectorFormat();
8594 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8595 SimVRegister& zm = ReadVRegister(instr->GetRn());
8596 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8597 SimVRegister result;
8598
8599 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
8600 case SABD_z_p_zz:
8601 absdiff(vform, result, zdn, zm, true);
8602 break;
8603 case SMAX_z_p_zz:
8604 smax(vform, result, zdn, zm);
8605 break;
8606 case SMIN_z_p_zz:
8607 smin(vform, result, zdn, zm);
8608 break;
8609 case UABD_z_p_zz:
8610 absdiff(vform, result, zdn, zm, false);
8611 break;
8612 case UMAX_z_p_zz:
8613 umax(vform, result, zdn, zm);
8614 break;
8615 case UMIN_z_p_zz:
8616 umin(vform, result, zdn, zm);
8617 break;
8618 default:
8619 VIXL_UNIMPLEMENTED();
8620 break;
8621 }
8622 mov_merging(vform, zdn, pg, result);
8623}
8624
8625void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
8626 VectorFormat vform = instr->GetSVEVectorFormat();
8627 SimVRegister& zd = ReadVRegister(instr->GetRd());
8628 SimVRegister scratch;
8629
8630 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
8631 case MUL_z_zi:
8632 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
8633 mul(vform, zd, zd, scratch);
8634 break;
8635 default:
8636 VIXL_UNIMPLEMENTED();
8637 break;
8638 }
8639}
8640
8641void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
8642 VectorFormat vform = instr->GetSVEVectorFormat();
8643 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8644 SimVRegister& zm = ReadVRegister(instr->GetRn());
8645 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8646 SimVRegister result;
8647
8648 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
8649
8650 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
8651 case SDIVR_z_p_zz:
8652 sdiv(vform, result, zm, zdn);
8653 break;
8654 case SDIV_z_p_zz:
8655 sdiv(vform, result, zdn, zm);
8656 break;
8657 case UDIVR_z_p_zz:
8658 udiv(vform, result, zm, zdn);
8659 break;
8660 case UDIV_z_p_zz:
8661 udiv(vform, result, zdn, zm);
8662 break;
8663 default:
8664 VIXL_UNIMPLEMENTED();
8665 break;
8666 }
8667 mov_merging(vform, zdn, pg, result);
8668}
8669
8670void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
8671 VectorFormat vform = instr->GetSVEVectorFormat();
8672 SimVRegister& zd = ReadVRegister(instr->GetRd());
8673 SimVRegister scratch;
8674
8675 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
8676 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
8677
8678 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
8679 case SMAX_z_zi:
8680 dup_immediate(vform, scratch, signed_imm);
8681 smax(vform, zd, zd, scratch);
8682 break;
8683 case SMIN_z_zi:
8684 dup_immediate(vform, scratch, signed_imm);
8685 smin(vform, zd, zd, scratch);
8686 break;
8687 case UMAX_z_zi:
8688 dup_immediate(vform, scratch, unsigned_imm);
8689 umax(vform, zd, zd, scratch);
8690 break;
8691 case UMIN_z_zi:
8692 dup_immediate(vform, scratch, unsigned_imm);
8693 umin(vform, zd, zd, scratch);
8694 break;
8695 default:
8696 VIXL_UNIMPLEMENTED();
8697 break;
8698 }
8699}
8700
8701void Simulator::VisitSVEIntCompareScalarCountAndLimit(
8702 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -07008703 unsigned rn_code = instr->GetRn();
8704 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008705 SimPRegister& pd = ReadPRegister(instr->GetPd());
8706 VectorFormat vform = instr->GetSVEVectorFormat();
8707 bool is_64_bit = instr->ExtractBit(12) == 1;
8708 int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8709 int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
TatWai Chongc844bb22019-06-10 15:32:53 -07008710
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008711 bool last = true;
8712 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
8713 bool cond = false;
8714 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
8715 case WHILELE_p_p_rr:
8716 cond = src1 <= src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008717 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008718 case WHILELO_p_p_rr:
8719 cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
8720 break;
8721 case WHILELS_p_p_rr:
8722 cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
8723 break;
8724 case WHILELT_p_p_rr:
8725 cond = src1 < src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008726 break;
8727 default:
TatWai Chongc844bb22019-06-10 15:32:53 -07008728 VIXL_UNIMPLEMENTED();
8729 break;
8730 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008731 last = last && cond;
8732 LogicPRegister dst(pd);
8733 dst.SetActive(vform, lane, last);
8734 src1 += 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008735 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008736
8737 PredTest(vform, GetPTrue(), pd);
8738 LogSystemRegister(NZCV);
8739}
8740
8741void Simulator::VisitSVEConditionallyTerminateScalars(
8742 const Instruction* instr) {
8743 unsigned rn_code = instr->GetRn();
8744 unsigned rm_code = instr->GetRm();
8745 bool is_64_bit = instr->ExtractBit(22) == 1;
8746 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8747 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
8748 bool term;
8749 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
8750 case CTERMEQ_rr:
8751 term = src1 == src2;
8752 break;
8753 case CTERMNE_rr:
8754 term = src1 != src2;
8755 break;
8756 default:
8757 term = false;
8758 VIXL_UNIMPLEMENTED();
8759 break;
8760 }
8761 ReadNzcv().SetN(term ? 1 : 0);
8762 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -07008763 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008764}
8765
8766void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
8767 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008768 bool commute_inputs = false;
8769 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008770 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8771 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008772 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008773 break;
8774 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008775 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008776 break;
8777 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008778 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008779 break;
8780 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008781 cond = ge;
8782 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008783 break;
8784 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008785 cond = gt;
8786 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008787 break;
8788 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008789 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008790 break;
8791 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008792 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008793 VIXL_UNIMPLEMENTED();
8794 break;
8795 }
TatWai Chong302729c2019-06-14 16:18:51 -07008796
8797 VectorFormat vform = instr->GetSVEVectorFormat();
8798 SimVRegister src2;
8799 dup_immediate(vform,
8800 src2,
8801 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
8802 SVEIntCompareVectorsHelper(cond,
8803 vform,
8804 ReadPRegister(instr->GetPd()),
8805 ReadPRegister(instr->GetPgLow8()),
8806 commute_inputs ? src2
8807 : ReadVRegister(instr->GetRn()),
8808 commute_inputs ? ReadVRegister(instr->GetRn())
8809 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008810}
8811
8812void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
8813 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008814 bool commute_inputs = false;
8815 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008816 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8817 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008818 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008819 break;
8820 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008821 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008822 break;
8823 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008824 cond = hi;
8825 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008826 break;
8827 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008828 cond = hs;
8829 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008830 break;
8831 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008832 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008833 VIXL_UNIMPLEMENTED();
8834 break;
8835 }
TatWai Chong302729c2019-06-14 16:18:51 -07008836
8837 VectorFormat vform = instr->GetSVEVectorFormat();
8838 SimVRegister src2;
8839 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
8840 SVEIntCompareVectorsHelper(cond,
8841 vform,
8842 ReadPRegister(instr->GetPd()),
8843 ReadPRegister(instr->GetPgLow8()),
8844 commute_inputs ? src2
8845 : ReadVRegister(instr->GetRn()),
8846 commute_inputs ? ReadVRegister(instr->GetRn())
8847 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008848}
8849
8850void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
8851 USE(instr);
TatWai Chong96713fe2019-06-04 16:39:37 -07008852
8853 Instr op = instr->Mask(SVEIntCompareVectorsMask);
8854 bool is_wide_elements = false;
8855 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008856 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -07008857 case CMPGE_p_p_zw:
8858 case CMPGT_p_p_zw:
8859 case CMPHI_p_p_zw:
8860 case CMPHS_p_p_zw:
8861 case CMPLE_p_p_zw:
8862 case CMPLO_p_p_zw:
8863 case CMPLS_p_p_zw:
8864 case CMPLT_p_p_zw:
8865 case CMPNE_p_p_zw:
8866 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008867 break;
TatWai Chong96713fe2019-06-04 16:39:37 -07008868 }
8869
TatWai Chong302729c2019-06-14 16:18:51 -07008870 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -07008871 switch (op) {
8872 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008873 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008874 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008875 break;
8876 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008877 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008878 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008879 break;
8880 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008881 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008882 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008883 break;
8884 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008885 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008886 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008887 break;
8888 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008889 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008890 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008891 break;
8892 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008893 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008894 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -07008895 break;
8896 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008897 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -07008898 break;
8899 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008900 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -07008901 break;
8902 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008903 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -07008904 break;
8905 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008906 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008907 break;
8908 default:
8909 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -07008910 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008911 break;
8912 }
TatWai Chong96713fe2019-06-04 16:39:37 -07008913
TatWai Chong302729c2019-06-14 16:18:51 -07008914 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -07008915 instr->GetSVEVectorFormat(),
8916 ReadPRegister(instr->GetPd()),
8917 ReadPRegister(instr->GetPgLow8()),
8918 ReadVRegister(instr->GetRn()),
8919 ReadVRegister(instr->GetRm()),
8920 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008921}
8922
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008923void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00008924 VectorFormat vform = instr->GetSVEVectorFormat();
8925 SimVRegister& zd = ReadVRegister(instr->GetRd());
8926 SimVRegister& zn = ReadVRegister(instr->GetRn());
8927
8928 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
8929 (vform == kFormatVnD));
8930
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008931 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008932 case FEXPA_z_z:
Martyn Capewell43782632019-12-12 13:22:10 +00008933 fexpa(vform, zd, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008934 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008935 default:
8936 VIXL_UNIMPLEMENTED();
8937 break;
8938 }
8939}
8940
8941void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
Martyn Capewell43782632019-12-12 13:22:10 +00008942 VectorFormat vform = instr->GetSVEVectorFormat();
8943 SimVRegister& zd = ReadVRegister(instr->GetRd());
8944 SimVRegister& zn = ReadVRegister(instr->GetRn());
8945 SimVRegister& zm = ReadVRegister(instr->GetRm());
8946
8947 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
8948 (vform == kFormatVnD));
8949
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008950 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008951 case FTSSEL_z_zz:
Martyn Capewell43782632019-12-12 13:22:10 +00008952 ftssel(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008953 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008954 default:
8955 VIXL_UNIMPLEMENTED();
8956 break;
8957 }
8958}
8959
8960void Simulator::VisitSVEConstructivePrefix_Unpredicated(
8961 const Instruction* instr) {
8962 SimVRegister& zd = ReadVRegister(instr->GetRd());
8963 SimVRegister& zn = ReadVRegister(instr->GetRn());
8964
8965 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008966 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008967 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
8968 // Record the movprfx, so the next ExecuteInstruction() can check it.
8969 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008970 break;
8971 default:
8972 VIXL_UNIMPLEMENTED();
8973 break;
8974 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008975}
8976
8977void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
Jacob Bramley22023df2019-05-14 17:55:43 +01008978 VectorFormat vform = instr->GetSVEVectorFormat();
8979
8980 SimVRegister& zd = ReadVRegister(instr->GetRd());
8981 SimVRegister& zm = ReadVRegister(instr->GetRm());
8982
8983 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008984 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008985 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008986 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008987 break;
8988 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008989 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008990 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008991 case MAD_z_p_zzz:
8992 // 'za' is encoded in 'Rn'.
8993 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008994 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008995 case MSB_z_p_zzz: {
8996 // 'za' is encoded in 'Rn'.
8997 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
8998 break;
8999 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009000 default:
9001 VIXL_UNIMPLEMENTED();
9002 break;
9003 }
Jacob Bramley22023df2019-05-14 17:55:43 +01009004 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009005}
9006
9007void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
9008 USE(instr);
TatWai Chong4d2a4e92019-10-23 16:19:32 -07009009
9010 VectorFormat vform = instr->GetSVEVectorFormat();
9011 SimVRegister& zda = ReadVRegister(instr->GetRd());
9012 SimVRegister& zn = ReadVRegister(instr->GetRn());
9013 SimVRegister& zm = ReadVRegister(instr->GetRm());
9014
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009015 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
9016 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07009017 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009018 break;
9019 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07009020 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009021 break;
9022 default:
9023 VIXL_UNIMPLEMENTED();
9024 break;
9025 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009026}
9027
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009028void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009029 VectorFormat vform = instr->GetSVEVectorFormat();
9030 SimVRegister& zn = ReadVRegister(instr->GetRn());
9031 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9032 SimVRegister& zd = ReadVRegister(instr->GetRd());
9033
9034 switch (instr->Mask(SVEMovprfxMask)) {
9035 case MOVPRFX_z_p_z:
9036 if (instr->ExtractBit(16)) {
9037 mov_merging(vform, zd, pg, zn);
9038 } else {
9039 mov_zeroing(vform, zd, pg, zn);
9040 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009041
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009042 // Record the movprfx, so the next ExecuteInstruction() can check it.
9043 movprfx_ = instr;
9044 break;
9045 default:
9046 VIXL_UNIMPLEMENTED();
9047 break;
9048 }
9049}
9050
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009051void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009052 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +01009053 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009054 SimVRegister& zn = ReadVRegister(instr->GetRn());
9055 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9056
9057 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
9058 switch (instr->Mask(SVEIntReductionLogicalMask)) {
9059 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01009060 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009061 break;
9062 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01009063 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009064 break;
9065 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01009066 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009067 break;
9068 default:
9069 VIXL_UNIMPLEMENTED();
9070 break;
9071 }
9072 } else {
9073 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009074 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009075 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009076 break;
9077 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009078 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009079 break;
9080 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009081 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009082 break;
9083 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009084 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009085 break;
9086 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009087 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009088 break;
9089 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07009090 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01009091 break;
9092 default:
9093 VIXL_UNIMPLEMENTED();
9094 break;
9095 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009096 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009097}
9098
9099void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
9100 USE(instr);
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009101
9102 VectorFormat vform = instr->GetSVEVectorFormat();
9103 SimVRegister& zn = ReadVRegister(instr->GetRn());
9104
9105 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009106 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
9107 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009108 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009109 break;
9110 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009111 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009112 break;
9113 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009114 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009115 break;
9116 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009117 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009118 break;
9119 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009120 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009121 break;
9122 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009123 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009124 break;
9125 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009126 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009127 break;
9128 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009129 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009130 break;
9131 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009132 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009133 break;
9134 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009135 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009136 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009137 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009138 break;
9139 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009140 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009141 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009142 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009143 break;
9144 default:
9145 VIXL_UNIMPLEMENTED();
9146 break;
9147 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01009148
9149 SimVRegister& zd = ReadVRegister(instr->GetRd());
9150 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9151 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009152}
9153
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009154void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009155 // There is only one instruction in this group.
9156 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
9157
9158 VectorFormat vform = instr->GetSVEVectorFormat();
9159 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
9160 SimVRegister& zd = ReadVRegister(instr->GetRd());
9161
9162 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009163 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009164 case FCPY_z_p_i: {
9165 int imm8 = instr->ExtractBits(12, 5);
9166 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
9167 Instruction::Imm8ToFP64(imm8));
9168 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009169 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009170 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009171 default:
9172 VIXL_UNIMPLEMENTED();
9173 break;
9174 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +01009175 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009176}
9177
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009178void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
9179 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +01009180 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01009181 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +01009182 SimVRegister scratch;
9183
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009184 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
9185 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009186
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009187 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009188 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009189 add_uint(vform, zd, zd, imm);
9190 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009191 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009192 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
9193 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009194 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009195 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
9196 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009197 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009198 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +01009199 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009200 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009201 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009202 sub_uint(vform, zd, zd, imm);
9203 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009204 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009205 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9206 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009207 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009208 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9209 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009210 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009211 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01009212 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009213}
TatWai Chong6995bfd2019-09-26 10:48:05 +01009214
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009215void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
9216 SimVRegister& zd = ReadVRegister(instr->GetRd());
9217
9218 int64_t imm = instr->GetImmSVEIntWideSigned();
9219 imm <<= instr->ExtractBit(13) * 8;
9220
9221 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
9222 case DUP_z_i:
9223 dup_immediate(instr->GetSVEVectorFormat(), zd, imm);
9224 break;
9225 default:
9226 VIXL_UNIMPLEMENTED();
9227 break;
9228 }
9229}
9230
9231void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
9232 VectorFormat vform = instr->GetSVEVectorFormat();
9233 SimVRegister& zd = ReadVRegister(instr->GetRd());
9234
9235 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009236 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +01009237 switch (vform) {
9238 case kFormatVnH:
9239 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
9240 break;
9241 case kFormatVnS:
9242 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
9243 break;
9244 case kFormatVnD:
9245 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
9246 break;
9247 default:
9248 VIXL_UNIMPLEMENTED();
9249 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009250 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009251 default:
9252 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009253 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009254 }
9255}
9256
9257void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
9258 const Instruction* instr) {
9259 USE(instr);
9260 switch (instr->Mask(
9261 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
9262 case LD1H_z_p_bz_s_x32_scaled:
9263 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009264 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009265 case LD1SH_z_p_bz_s_x32_scaled:
9266 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009267 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009268 case LDFF1H_z_p_bz_s_x32_scaled:
9269 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009270 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009271 case LDFF1SH_z_p_bz_s_x32_scaled:
9272 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009273 break;
9274 default:
9275 VIXL_UNIMPLEMENTED();
9276 break;
9277 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009278}
9279
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009280void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009281 const Instruction* instr) {
9282 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009283 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
9284 case LD1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009285 case LD1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009286 case LD1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009287 case LD1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009288 case LD1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009289 case LDFF1B_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009290 case LDFF1H_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009291 case LDFF1SB_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009292 case LDFF1SH_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009293 case LDFF1W_z_p_bz_s_x32_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009294 break;
9295 default:
9296 VIXL_UNIMPLEMENTED();
9297 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009298 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +00009299 bool is_signed = instr->ExtractBit(14) == 0;
9300 bool is_ff = instr->ExtractBit(13) == 1;
9301 // Note that these instructions don't use the Dtype encoding.
9302 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
9303 uint64_t base = ReadXRegister(instr->GetRn());
9304 LogicSVEAddressVector addr(base, &ReadVRegister(instr->GetRm()), kFormatVnS);
9305 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9306 if (is_ff) {
9307 VIXL_UNIMPLEMENTED();
9308 } else {
9309 SVEStructuredLoadHelper(kFormatVnS,
9310 ReadPRegister(instr->GetPgLow8()),
9311 instr->GetRt(),
9312 addr,
9313 is_signed);
9314 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009315}
9316
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009317void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
9318 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009319 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009320 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
9321 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009322 VIXL_UNIMPLEMENTED();
9323 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009324 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009325 VIXL_UNIMPLEMENTED();
9326 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009327 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009328 VIXL_UNIMPLEMENTED();
9329 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009330 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009331 VIXL_UNIMPLEMENTED();
9332 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009333 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009334 VIXL_UNIMPLEMENTED();
9335 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009336 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009337 VIXL_UNIMPLEMENTED();
9338 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009339 case LDFF1H_z_p_ai_s:
9340 VIXL_UNIMPLEMENTED();
9341 break;
9342 case LDFF1SB_z_p_ai_s:
9343 VIXL_UNIMPLEMENTED();
9344 break;
9345 case LDFF1SH_z_p_ai_s:
9346 VIXL_UNIMPLEMENTED();
9347 break;
9348 case LDFF1W_z_p_ai_s:
9349 VIXL_UNIMPLEMENTED();
9350 break;
9351 default:
9352 VIXL_UNIMPLEMENTED();
9353 break;
9354 }
9355}
9356
9357void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
9358 const Instruction* instr) {
9359 USE(instr);
9360 switch (
9361 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
9362 case LD1W_z_p_bz_s_x32_scaled:
9363 VIXL_UNIMPLEMENTED();
9364 break;
9365 case LDFF1W_z_p_bz_s_x32_scaled:
9366 VIXL_UNIMPLEMENTED();
9367 break;
9368 default:
9369 VIXL_UNIMPLEMENTED();
9370 break;
9371 }
9372}
9373
9374void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
9375 const Instruction* instr) {
9376 USE(instr);
9377 switch (
9378 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
9379 case PRFB_i_p_bz_s_x32_scaled:
9380 VIXL_UNIMPLEMENTED();
9381 break;
9382 case PRFD_i_p_bz_s_x32_scaled:
9383 VIXL_UNIMPLEMENTED();
9384 break;
9385 case PRFH_i_p_bz_s_x32_scaled:
9386 VIXL_UNIMPLEMENTED();
9387 break;
9388 case PRFW_i_p_bz_s_x32_scaled:
9389 VIXL_UNIMPLEMENTED();
9390 break;
9391 default:
9392 VIXL_UNIMPLEMENTED();
9393 break;
9394 }
9395}
9396
9397void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
9398 const Instruction* instr) {
9399 USE(instr);
9400 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
9401 case PRFB_i_p_ai_s:
9402 VIXL_UNIMPLEMENTED();
9403 break;
9404 case PRFD_i_p_ai_s:
9405 VIXL_UNIMPLEMENTED();
9406 break;
9407 case PRFH_i_p_ai_s:
9408 VIXL_UNIMPLEMENTED();
9409 break;
9410 case PRFW_i_p_ai_s:
9411 VIXL_UNIMPLEMENTED();
9412 break;
9413 default:
9414 VIXL_UNIMPLEMENTED();
9415 break;
9416 }
9417}
9418
9419void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
9420 const Instruction* instr) {
9421 USE(instr);
9422 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
9423 case PRFB_i_p_bi_s:
9424 VIXL_UNIMPLEMENTED();
9425 break;
9426 case PRFD_i_p_bi_s:
9427 VIXL_UNIMPLEMENTED();
9428 break;
9429 case PRFH_i_p_bi_s:
9430 VIXL_UNIMPLEMENTED();
9431 break;
9432 case PRFW_i_p_bi_s:
9433 VIXL_UNIMPLEMENTED();
9434 break;
9435 default:
9436 VIXL_UNIMPLEMENTED();
9437 break;
9438 }
9439}
9440
9441void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
9442 const Instruction* instr) {
9443 USE(instr);
9444 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
9445 case PRFB_i_p_br_s:
9446 VIXL_UNIMPLEMENTED();
9447 break;
9448 case PRFD_i_p_br_s:
9449 VIXL_UNIMPLEMENTED();
9450 break;
9451 case PRFH_i_p_br_s:
9452 VIXL_UNIMPLEMENTED();
9453 break;
9454 case PRFW_i_p_br_s:
9455 VIXL_UNIMPLEMENTED();
9456 break;
9457 default:
9458 VIXL_UNIMPLEMENTED();
9459 break;
9460 }
9461}
9462
9463void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
9464 USE(instr);
9465 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
9466 case LD1RB_z_p_bi_u16:
9467 VIXL_UNIMPLEMENTED();
9468 break;
9469 case LD1RB_z_p_bi_u32:
9470 VIXL_UNIMPLEMENTED();
9471 break;
9472 case LD1RB_z_p_bi_u64:
9473 VIXL_UNIMPLEMENTED();
9474 break;
9475 case LD1RB_z_p_bi_u8:
9476 VIXL_UNIMPLEMENTED();
9477 break;
9478 case LD1RD_z_p_bi_u64:
9479 VIXL_UNIMPLEMENTED();
9480 break;
9481 case LD1RH_z_p_bi_u16:
9482 VIXL_UNIMPLEMENTED();
9483 break;
9484 case LD1RH_z_p_bi_u32:
9485 VIXL_UNIMPLEMENTED();
9486 break;
9487 case LD1RH_z_p_bi_u64:
9488 VIXL_UNIMPLEMENTED();
9489 break;
9490 case LD1RSB_z_p_bi_s16:
9491 VIXL_UNIMPLEMENTED();
9492 break;
9493 case LD1RSB_z_p_bi_s32:
9494 VIXL_UNIMPLEMENTED();
9495 break;
9496 case LD1RSB_z_p_bi_s64:
9497 VIXL_UNIMPLEMENTED();
9498 break;
9499 case LD1RSH_z_p_bi_s32:
9500 VIXL_UNIMPLEMENTED();
9501 break;
9502 case LD1RSH_z_p_bi_s64:
9503 VIXL_UNIMPLEMENTED();
9504 break;
9505 case LD1RSW_z_p_bi_s64:
9506 VIXL_UNIMPLEMENTED();
9507 break;
9508 case LD1RW_z_p_bi_u32:
9509 VIXL_UNIMPLEMENTED();
9510 break;
9511 case LD1RW_z_p_bi_u64:
9512 VIXL_UNIMPLEMENTED();
9513 break;
9514 default:
9515 VIXL_UNIMPLEMENTED();
9516 break;
9517 }
9518}
9519
9520void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
9521 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
9522 case LDR_p_bi: {
9523 SimPRegister& pt = ReadPRegister(instr->GetPt());
9524 int pl = GetPredicateLengthInBytes();
9525 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9526 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9527 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
9528 for (int i = 0; i < pl; i++) {
9529 pt.Insert(i, Memory::Read<uint8_t>(address + i));
9530 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009531 LogPRead(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009532 break;
9533 }
9534 default:
9535 VIXL_UNIMPLEMENTED();
9536 break;
9537 }
9538}
9539
9540void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
9541 USE(instr);
9542 switch (instr->Mask(SVELoadVectorRegisterMask)) {
9543 case LDR_z_bi: {
9544 SimVRegister& zt = ReadVRegister(instr->GetRt());
9545 int vl = GetVectorLengthInBytes();
9546 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9547 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9548 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
9549 for (int i = 0; i < vl; i++) {
9550 zt.Insert(i, Memory::Read<uint8_t>(address + i));
9551 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +00009552 LogZRead(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009553 break;
9554 }
9555 default:
9556 VIXL_UNIMPLEMENTED();
9557 break;
9558 }
9559}
9560
9561void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
9562 const Instruction* instr) {
9563 USE(instr);
9564 switch (instr->Mask(
9565 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009566 case LD1D_z_p_bz_d_x32_scaled:
9567 VIXL_UNIMPLEMENTED();
9568 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009569 case LD1H_z_p_bz_d_x32_scaled:
9570 VIXL_UNIMPLEMENTED();
9571 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009572 case LD1SH_z_p_bz_d_x32_scaled:
9573 VIXL_UNIMPLEMENTED();
9574 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009575 case LD1SW_z_p_bz_d_x32_scaled:
9576 VIXL_UNIMPLEMENTED();
9577 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009578 case LD1W_z_p_bz_d_x32_scaled:
9579 VIXL_UNIMPLEMENTED();
9580 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009581 case LDFF1D_z_p_bz_d_x32_scaled:
9582 VIXL_UNIMPLEMENTED();
9583 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009584 case LDFF1H_z_p_bz_d_x32_scaled:
9585 VIXL_UNIMPLEMENTED();
9586 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009587 case LDFF1SH_z_p_bz_d_x32_scaled:
9588 VIXL_UNIMPLEMENTED();
9589 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009590 case LDFF1SW_z_p_bz_d_x32_scaled:
9591 VIXL_UNIMPLEMENTED();
9592 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009593 case LDFF1W_z_p_bz_d_x32_scaled:
9594 VIXL_UNIMPLEMENTED();
9595 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009596 default:
9597 VIXL_UNIMPLEMENTED();
9598 break;
9599 }
9600}
9601
9602void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
9603 const Instruction* instr) {
9604 USE(instr);
9605 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
9606 case LD1D_z_p_bz_d_64_scaled:
9607 VIXL_UNIMPLEMENTED();
9608 break;
9609 case LD1H_z_p_bz_d_64_scaled:
9610 VIXL_UNIMPLEMENTED();
9611 break;
9612 case LD1SH_z_p_bz_d_64_scaled:
9613 VIXL_UNIMPLEMENTED();
9614 break;
9615 case LD1SW_z_p_bz_d_64_scaled:
9616 VIXL_UNIMPLEMENTED();
9617 break;
9618 case LD1W_z_p_bz_d_64_scaled:
9619 VIXL_UNIMPLEMENTED();
9620 break;
9621 case LDFF1D_z_p_bz_d_64_scaled:
9622 VIXL_UNIMPLEMENTED();
9623 break;
9624 case LDFF1H_z_p_bz_d_64_scaled:
9625 VIXL_UNIMPLEMENTED();
9626 break;
9627 case LDFF1SH_z_p_bz_d_64_scaled:
9628 VIXL_UNIMPLEMENTED();
9629 break;
9630 case LDFF1SW_z_p_bz_d_64_scaled:
9631 VIXL_UNIMPLEMENTED();
9632 break;
9633 case LDFF1W_z_p_bz_d_64_scaled:
9634 VIXL_UNIMPLEMENTED();
9635 break;
9636 default:
9637 VIXL_UNIMPLEMENTED();
9638 break;
9639 }
9640}
9641
9642void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
9643 const Instruction* instr) {
9644 USE(instr);
9645 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
9646 case LD1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009647 case LD1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009648 case LD1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009649 case LD1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009650 case LD1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009651 case LD1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009652 case LD1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009653 case LDFF1B_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009654 case LDFF1D_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009655 case LDFF1H_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009656 case LDFF1SB_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009657 case LDFF1SH_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009658 case LDFF1SW_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009659 case LDFF1W_z_p_bz_d_64_unscaled:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009660 break;
9661 default:
9662 VIXL_UNIMPLEMENTED();
9663 break;
9664 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +00009665 bool is_signed = instr->ExtractBit(14) == 0;
9666 bool is_ff = instr->ExtractBit(13) == 1;
9667 // Note that these instructions don't use the Dtype encoding.
9668 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
9669 uint64_t base = ReadXRegister(instr->GetRn());
9670 LogicSVEAddressVector addr(base, &ReadVRegister(instr->GetRm()), kFormatVnD);
9671 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9672 if (is_ff) {
9673 VIXL_UNIMPLEMENTED();
9674 } else {
9675 SVEStructuredLoadHelper(kFormatVnD,
9676 ReadPRegister(instr->GetPgLow8()),
9677 instr->GetRt(),
9678 addr,
9679 is_signed);
9680 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009681}
9682
9683void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
9684 const Instruction* instr) {
9685 USE(instr);
9686 switch (instr->Mask(
9687 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9688 case LD1B_z_p_bz_d_x32_unscaled:
9689 VIXL_UNIMPLEMENTED();
9690 break;
9691 case LD1D_z_p_bz_d_x32_unscaled:
9692 VIXL_UNIMPLEMENTED();
9693 break;
9694 case LD1H_z_p_bz_d_x32_unscaled:
9695 VIXL_UNIMPLEMENTED();
9696 break;
9697 case LD1SB_z_p_bz_d_x32_unscaled:
9698 VIXL_UNIMPLEMENTED();
9699 break;
9700 case LD1SH_z_p_bz_d_x32_unscaled:
9701 VIXL_UNIMPLEMENTED();
9702 break;
9703 case LD1SW_z_p_bz_d_x32_unscaled:
9704 VIXL_UNIMPLEMENTED();
9705 break;
9706 case LD1W_z_p_bz_d_x32_unscaled:
9707 VIXL_UNIMPLEMENTED();
9708 break;
9709 case LDFF1B_z_p_bz_d_x32_unscaled:
9710 VIXL_UNIMPLEMENTED();
9711 break;
9712 case LDFF1D_z_p_bz_d_x32_unscaled:
9713 VIXL_UNIMPLEMENTED();
9714 break;
9715 case LDFF1H_z_p_bz_d_x32_unscaled:
9716 VIXL_UNIMPLEMENTED();
9717 break;
9718 case LDFF1SB_z_p_bz_d_x32_unscaled:
9719 VIXL_UNIMPLEMENTED();
9720 break;
9721 case LDFF1SH_z_p_bz_d_x32_unscaled:
9722 VIXL_UNIMPLEMENTED();
9723 break;
9724 case LDFF1SW_z_p_bz_d_x32_unscaled:
9725 VIXL_UNIMPLEMENTED();
9726 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009727 case LDFF1W_z_p_bz_d_x32_unscaled:
9728 VIXL_UNIMPLEMENTED();
9729 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009730 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009731 VIXL_UNIMPLEMENTED();
9732 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009733 }
9734}
9735
9736void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
9737 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009738 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
9739 case LD1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009740 case LD1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009741 case LD1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009742 case LD1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009743 case LD1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009744 case LD1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009745 case LD1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009746 case LDFF1B_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009747 case LDFF1D_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009748 case LDFF1H_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009749 case LDFF1SB_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009750 case LDFF1SH_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009751 case LDFF1SW_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009752 case LDFF1W_z_p_ai_d:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009753 break;
9754 default:
9755 VIXL_UNIMPLEMENTED();
9756 break;
9757 }
Jacob Bramleydcdbd752020-01-20 11:47:36 +00009758 bool is_signed = instr->ExtractBit(14) == 0;
9759 bool is_ff = instr->ExtractBit(13) == 1;
9760 // Note that these instructions don't use the Dtype encoding.
9761 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
9762 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
9763 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
9764 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9765 if (is_ff) {
9766 VIXL_UNIMPLEMENTED();
9767 } else {
9768 SVEStructuredLoadHelper(kFormatVnD,
9769 ReadPRegister(instr->GetPgLow8()),
9770 instr->GetRt(),
9771 addr,
9772 is_signed);
9773 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009774}
9775
9776void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
9777 const Instruction* instr) {
9778 USE(instr);
9779 switch (
9780 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009781 case PRFB_i_p_bz_d_64_scaled:
9782 VIXL_UNIMPLEMENTED();
9783 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009784 case PRFD_i_p_bz_d_64_scaled:
9785 VIXL_UNIMPLEMENTED();
9786 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009787 case PRFH_i_p_bz_d_64_scaled:
9788 VIXL_UNIMPLEMENTED();
9789 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009790 case PRFW_i_p_bz_d_64_scaled:
9791 VIXL_UNIMPLEMENTED();
9792 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009793 default:
9794 VIXL_UNIMPLEMENTED();
9795 break;
9796 }
9797}
9798
9799void Simulator::
9800 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
9801 const Instruction* instr) {
9802 USE(instr);
9803 switch (instr->Mask(
9804 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9805 case PRFB_i_p_bz_d_x32_scaled:
9806 VIXL_UNIMPLEMENTED();
9807 break;
9808 case PRFD_i_p_bz_d_x32_scaled:
9809 VIXL_UNIMPLEMENTED();
9810 break;
9811 case PRFH_i_p_bz_d_x32_scaled:
9812 VIXL_UNIMPLEMENTED();
9813 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009814 case PRFW_i_p_bz_d_x32_scaled:
9815 VIXL_UNIMPLEMENTED();
9816 break;
9817 default:
9818 VIXL_UNIMPLEMENTED();
9819 break;
9820 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009821}
9822
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009823void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
9824 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009825 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009826 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
9827 case PRFB_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009828 VIXL_UNIMPLEMENTED();
9829 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009830 case PRFD_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009831 VIXL_UNIMPLEMENTED();
9832 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009833 case PRFH_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009834 VIXL_UNIMPLEMENTED();
9835 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009836 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009837 VIXL_UNIMPLEMENTED();
9838 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009839 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009840 VIXL_UNIMPLEMENTED();
9841 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009842 }
9843}
9844
9845void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
9846 const Instruction* instr) {
Jacob Bramley85a9c102019-12-09 17:48:29 +00009847 bool is_signed;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009848 USE(instr);
Jacob Bramley85a9c102019-12-09 17:48:29 +00009849 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009850 case LDFF1B_z_p_br_u8:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009851 case LDFF1B_z_p_br_u16:
9852 case LDFF1B_z_p_br_u32:
9853 case LDFF1B_z_p_br_u64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009854 case LDFF1H_z_p_br_u16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009855 case LDFF1H_z_p_br_u32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009856 case LDFF1H_z_p_br_u64:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009857 case LDFF1W_z_p_br_u32:
9858 case LDFF1W_z_p_br_u64:
9859 case LDFF1D_z_p_br_u64:
9860 is_signed = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009861 break;
9862 case LDFF1SB_z_p_br_s16:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009863 case LDFF1SB_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009864 case LDFF1SB_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009865 case LDFF1SH_z_p_br_s32:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009866 case LDFF1SH_z_p_br_s64:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009867 case LDFF1SW_z_p_br_s64:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009868 is_signed = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009869 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009870 default:
Jacob Bramley85a9c102019-12-09 17:48:29 +00009871 // This encoding group is complete, so no other values should be possible.
9872 VIXL_UNREACHABLE();
9873 is_signed = false;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009874 break;
9875 }
Jacob Bramley85a9c102019-12-09 17:48:29 +00009876
9877 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
9878 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
9879 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
9880 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
9881 uint64_t offset = ReadXRegister(instr->GetRm());
9882 offset <<= msize_in_bytes_log2;
9883 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
9884 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9885 SVEFaultTolerantLoadHelper(vform,
9886 ReadPRegister(instr->GetPgLow8()),
9887 instr->GetRt(),
9888 addr,
9889 kSVEFirstFaultLoad,
9890 is_signed);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009891}
9892
9893void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
9894 const Instruction* instr) {
9895 USE(instr);
9896 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009897 case LDNF1B_z_p_bi_u16:
9898 VIXL_UNIMPLEMENTED();
9899 break;
9900 case LDNF1B_z_p_bi_u32:
9901 VIXL_UNIMPLEMENTED();
9902 break;
9903 case LDNF1B_z_p_bi_u64:
9904 VIXL_UNIMPLEMENTED();
9905 break;
9906 case LDNF1B_z_p_bi_u8:
9907 VIXL_UNIMPLEMENTED();
9908 break;
9909 case LDNF1D_z_p_bi_u64:
9910 VIXL_UNIMPLEMENTED();
9911 break;
9912 case LDNF1H_z_p_bi_u16:
9913 VIXL_UNIMPLEMENTED();
9914 break;
9915 case LDNF1H_z_p_bi_u32:
9916 VIXL_UNIMPLEMENTED();
9917 break;
9918 case LDNF1H_z_p_bi_u64:
9919 VIXL_UNIMPLEMENTED();
9920 break;
9921 case LDNF1SB_z_p_bi_s16:
9922 VIXL_UNIMPLEMENTED();
9923 break;
9924 case LDNF1SB_z_p_bi_s32:
9925 VIXL_UNIMPLEMENTED();
9926 break;
9927 case LDNF1SB_z_p_bi_s64:
9928 VIXL_UNIMPLEMENTED();
9929 break;
9930 case LDNF1SH_z_p_bi_s32:
9931 VIXL_UNIMPLEMENTED();
9932 break;
9933 case LDNF1SH_z_p_bi_s64:
9934 VIXL_UNIMPLEMENTED();
9935 break;
9936 case LDNF1SW_z_p_bi_s64:
9937 VIXL_UNIMPLEMENTED();
9938 break;
9939 case LDNF1W_z_p_bi_u32:
9940 VIXL_UNIMPLEMENTED();
9941 break;
9942 case LDNF1W_z_p_bi_u64:
9943 VIXL_UNIMPLEMENTED();
9944 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009945 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009946 VIXL_UNIMPLEMENTED();
9947 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009948 }
9949}
9950
9951void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
9952 const Instruction* instr) {
9953 USE(instr);
9954 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
9955 case LDNT1B_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009956 VIXL_UNIMPLEMENTED();
9957 break;
9958 case LDNT1D_z_p_bi_contiguous:
9959 VIXL_UNIMPLEMENTED();
9960 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009961 case LDNT1H_z_p_bi_contiguous:
9962 VIXL_UNIMPLEMENTED();
9963 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009964 case LDNT1W_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009965 VIXL_UNIMPLEMENTED();
9966 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009967 default:
9968 VIXL_UNIMPLEMENTED();
9969 break;
9970 }
9971}
9972
9973void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
9974 const Instruction* instr) {
9975 USE(instr);
9976 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
9977 case LDNT1B_z_p_br_contiguous:
9978 VIXL_UNIMPLEMENTED();
9979 break;
9980 case LDNT1D_z_p_br_contiguous:
9981 VIXL_UNIMPLEMENTED();
9982 break;
9983 case LDNT1H_z_p_br_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009984 VIXL_UNIMPLEMENTED();
9985 break;
9986 case LDNT1W_z_p_br_contiguous:
9987 VIXL_UNIMPLEMENTED();
9988 break;
9989 default:
9990 VIXL_UNIMPLEMENTED();
9991 break;
9992 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009993}
9994
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009995void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
9996 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009997 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009998 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
9999 case LD1RQB_z_p_bi_u8:
10000 VIXL_UNIMPLEMENTED();
10001 break;
10002 case LD1RQD_z_p_bi_u64:
10003 VIXL_UNIMPLEMENTED();
10004 break;
10005 case LD1RQH_z_p_bi_u16:
10006 VIXL_UNIMPLEMENTED();
10007 break;
10008 case LD1RQW_z_p_bi_u32:
10009 VIXL_UNIMPLEMENTED();
10010 break;
10011 default:
10012 VIXL_UNIMPLEMENTED();
10013 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010014 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010015}
10016
10017void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
10018 const Instruction* instr) {
10019 USE(instr);
10020 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
10021 case LD1RQB_z_p_br_contiguous:
10022 VIXL_UNIMPLEMENTED();
10023 break;
10024 case LD1RQD_z_p_br_contiguous:
10025 VIXL_UNIMPLEMENTED();
10026 break;
10027 case LD1RQH_z_p_br_contiguous:
10028 VIXL_UNIMPLEMENTED();
10029 break;
10030 case LD1RQW_z_p_br_contiguous:
10031 VIXL_UNIMPLEMENTED();
10032 break;
10033 default:
10034 VIXL_UNIMPLEMENTED();
10035 break;
10036 }
10037}
10038
10039void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
10040 const Instruction* instr) {
10041 USE(instr);
10042 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
10043 case LD2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010044 case LD2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010045 case LD2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010046 case LD2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010047 case LD3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010048 case LD3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010049 case LD3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010050 case LD3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010051 case LD4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010052 case LD4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010053 case LD4H_z_p_bi_contiguous:
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000010054 case LD4W_z_p_bi_contiguous: {
10055 int vl = GetVectorLengthInBytes();
10056 int msz = instr->ExtractBits(24, 23);
10057 int reg_count = instr->ExtractBits(22, 21) + 1;
10058 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10059 LogicSVEAddressVector addr(
10060 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10061 addr.SetMsizeInBytesLog2(msz);
10062 addr.SetRegCount(reg_count);
10063 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10064 ReadPRegister(instr->GetPgLow8()),
10065 instr->GetRt(),
10066 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010067 break;
Jacob Bramleye5ab0fe2019-11-05 16:52:29 +000010068 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010069 default:
10070 VIXL_UNIMPLEMENTED();
10071 break;
10072 }
10073}
10074
10075void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
10076 const Instruction* instr) {
10077 USE(instr);
10078 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
10079 case LD2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010080 case LD2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010081 case LD2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010082 case LD2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010083 case LD3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010084 case LD3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010085 case LD3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010086 case LD3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010087 case LD4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010088 case LD4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010089 case LD4H_z_p_br_contiguous:
Jacob Bramleye483ce52019-11-05 16:52:29 +000010090 case LD4W_z_p_br_contiguous: {
10091 int msz = instr->ExtractBits(24, 23);
10092 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10093 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10094 LogicSVEAddressVector addr(
10095 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10096 addr.SetMsizeInBytesLog2(msz);
10097 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10098 SVEStructuredLoadHelper(vform,
10099 ReadPRegister(instr->GetPgLow8()),
10100 instr->GetRt(),
10101 addr,
10102 false);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010103 break;
Jacob Bramleye483ce52019-11-05 16:52:29 +000010104 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010105 default:
10106 VIXL_UNIMPLEMENTED();
10107 break;
10108 }
10109}
10110
10111void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
10112 const Instruction* instr) {
10113 USE(instr);
10114 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
10115 case ST1H_z_p_bz_s_x32_scaled:
10116 VIXL_UNIMPLEMENTED();
10117 break;
10118 case ST1W_z_p_bz_s_x32_scaled:
10119 VIXL_UNIMPLEMENTED();
10120 break;
10121 default:
10122 VIXL_UNIMPLEMENTED();
10123 break;
10124 }
10125}
10126
10127void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
10128 const Instruction* instr) {
10129 USE(instr);
10130 switch (
10131 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
10132 case ST1B_z_p_bz_s_x32_unscaled:
10133 VIXL_UNIMPLEMENTED();
10134 break;
10135 case ST1H_z_p_bz_s_x32_unscaled:
10136 VIXL_UNIMPLEMENTED();
10137 break;
10138 case ST1W_z_p_bz_s_x32_unscaled:
10139 VIXL_UNIMPLEMENTED();
10140 break;
10141 default:
10142 VIXL_UNIMPLEMENTED();
10143 break;
10144 }
10145}
10146
10147void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
10148 const Instruction* instr) {
10149 USE(instr);
10150 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
10151 case ST1B_z_p_ai_s:
10152 VIXL_UNIMPLEMENTED();
10153 break;
10154 case ST1H_z_p_ai_s:
10155 VIXL_UNIMPLEMENTED();
10156 break;
10157 case ST1W_z_p_ai_s:
10158 VIXL_UNIMPLEMENTED();
10159 break;
10160 default:
10161 VIXL_UNIMPLEMENTED();
10162 break;
10163 }
10164}
10165
10166void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
10167 const Instruction* instr) {
10168 USE(instr);
10169 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
10170 case ST1D_z_p_bz_d_64_scaled:
10171 VIXL_UNIMPLEMENTED();
10172 break;
10173 case ST1H_z_p_bz_d_64_scaled:
10174 VIXL_UNIMPLEMENTED();
10175 break;
10176 case ST1W_z_p_bz_d_64_scaled:
10177 VIXL_UNIMPLEMENTED();
10178 break;
10179 default:
10180 VIXL_UNIMPLEMENTED();
10181 break;
10182 }
10183}
10184
10185void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
10186 const Instruction* instr) {
10187 USE(instr);
10188 switch (
10189 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
10190 case ST1B_z_p_bz_d_64_unscaled:
10191 VIXL_UNIMPLEMENTED();
10192 break;
10193 case ST1D_z_p_bz_d_64_unscaled:
10194 VIXL_UNIMPLEMENTED();
10195 break;
10196 case ST1H_z_p_bz_d_64_unscaled:
10197 VIXL_UNIMPLEMENTED();
10198 break;
10199 case ST1W_z_p_bz_d_64_unscaled:
10200 VIXL_UNIMPLEMENTED();
10201 break;
10202 default:
10203 VIXL_UNIMPLEMENTED();
10204 break;
10205 }
10206}
10207
10208void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
10209 const Instruction* instr) {
10210 USE(instr);
10211 switch (instr->Mask(
10212 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
10213 case ST1D_z_p_bz_d_x32_scaled:
10214 VIXL_UNIMPLEMENTED();
10215 break;
10216 case ST1H_z_p_bz_d_x32_scaled:
10217 VIXL_UNIMPLEMENTED();
10218 break;
10219 case ST1W_z_p_bz_d_x32_scaled:
10220 VIXL_UNIMPLEMENTED();
10221 break;
10222 default:
10223 VIXL_UNIMPLEMENTED();
10224 break;
10225 }
10226}
10227
10228void Simulator::
10229 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
10230 const Instruction* instr) {
10231 USE(instr);
10232 switch (instr->Mask(
10233 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
10234 case ST1B_z_p_bz_d_x32_unscaled:
10235 VIXL_UNIMPLEMENTED();
10236 break;
10237 case ST1D_z_p_bz_d_x32_unscaled:
10238 VIXL_UNIMPLEMENTED();
10239 break;
10240 case ST1H_z_p_bz_d_x32_unscaled:
10241 VIXL_UNIMPLEMENTED();
10242 break;
10243 case ST1W_z_p_bz_d_x32_unscaled:
10244 VIXL_UNIMPLEMENTED();
10245 break;
10246 default:
10247 VIXL_UNIMPLEMENTED();
10248 break;
10249 }
10250}
10251
10252void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
10253 const Instruction* instr) {
10254 USE(instr);
10255 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
10256 case ST1B_z_p_ai_d:
10257 VIXL_UNIMPLEMENTED();
10258 break;
10259 case ST1D_z_p_ai_d:
10260 VIXL_UNIMPLEMENTED();
10261 break;
10262 case ST1H_z_p_ai_d:
10263 VIXL_UNIMPLEMENTED();
10264 break;
10265 case ST1W_z_p_ai_d:
10266 VIXL_UNIMPLEMENTED();
10267 break;
10268 default:
10269 VIXL_UNIMPLEMENTED();
10270 break;
10271 }
10272}
10273
10274void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
10275 const Instruction* instr) {
10276 USE(instr);
10277 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
10278 case STNT1B_z_p_bi_contiguous:
10279 VIXL_UNIMPLEMENTED();
10280 break;
10281 case STNT1D_z_p_bi_contiguous:
10282 VIXL_UNIMPLEMENTED();
10283 break;
10284 case STNT1H_z_p_bi_contiguous:
10285 VIXL_UNIMPLEMENTED();
10286 break;
10287 case STNT1W_z_p_bi_contiguous:
10288 VIXL_UNIMPLEMENTED();
10289 break;
10290 default:
10291 VIXL_UNIMPLEMENTED();
10292 break;
10293 }
10294}
10295
10296void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
10297 const Instruction* instr) {
10298 USE(instr);
10299 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
10300 case STNT1B_z_p_br_contiguous:
10301 VIXL_UNIMPLEMENTED();
10302 break;
10303 case STNT1D_z_p_br_contiguous:
10304 VIXL_UNIMPLEMENTED();
10305 break;
10306 case STNT1H_z_p_br_contiguous:
10307 VIXL_UNIMPLEMENTED();
10308 break;
10309 case STNT1W_z_p_br_contiguous:
10310 VIXL_UNIMPLEMENTED();
10311 break;
10312 default:
10313 VIXL_UNIMPLEMENTED();
10314 break;
10315 }
10316}
10317
10318void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
10319 const Instruction* instr) {
10320 USE(instr);
10321 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
10322 case ST1B_z_p_bi:
10323 case ST1D_z_p_bi:
10324 case ST1H_z_p_bi:
10325 case ST1W_z_p_bi: {
10326 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010327 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10328 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
10329 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10330 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10331 uint64_t offset =
10332 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010333 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010334 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010335 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010336 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10337 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010338 ReadPRegister(instr->GetPgLow8()),
10339 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010340 addr);
10341 break;
10342 }
10343 default:
10344 VIXL_UNIMPLEMENTED();
10345 break;
10346 }
10347}
10348
10349void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
10350 const Instruction* instr) {
10351 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
10352 case ST1B_z_p_br:
10353 case ST1D_z_p_br:
10354 case ST1H_z_p_br:
10355 case ST1W_z_p_br: {
10356 uint64_t offset = ReadXRegister(instr->GetRm());
10357 offset <<= instr->ExtractBits(24, 23);
10358 VectorFormat vform =
10359 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
10360 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010361 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
10362 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010363 ReadPRegister(instr->GetPgLow8()),
10364 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010365 addr);
10366 break;
10367 }
10368 default:
10369 VIXL_UNIMPLEMENTED();
10370 break;
10371 }
10372}
10373
10374void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
10375 const Instruction* instr) {
10376 VectorFormat vform = instr->GetSVEVectorFormat();
10377 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10378 SimVRegister z_result;
10379
10380 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
10381 case CPY_z_p_v:
10382 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
10383 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
10384 break;
10385 default:
10386 VIXL_UNIMPLEMENTED();
10387 break;
10388 }
10389}
10390
10391void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
10392 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010393 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
10394 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010395 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010396 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010397 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010398 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010399 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010400 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010401 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010402 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010403 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010404 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010405 case ST4W_z_p_bi_contiguous: {
10406 int vl = GetVectorLengthInBytes();
10407 int msz = instr->ExtractBits(24, 23);
10408 int reg_count = instr->ExtractBits(22, 21) + 1;
10409 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10410 LogicSVEAddressVector addr(
10411 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10412 addr.SetMsizeInBytesLog2(msz);
10413 addr.SetRegCount(reg_count);
10414 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10415 ReadPRegister(instr->GetPgLow8()),
10416 instr->GetRt(),
10417 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010418 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010419 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010420 default:
10421 VIXL_UNIMPLEMENTED();
10422 break;
10423 }
10424}
10425
10426void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
10427 const Instruction* instr) {
10428 USE(instr);
10429 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
10430 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010431 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010432 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010433 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010434 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010435 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010436 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010437 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010438 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010439 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010440 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010441 case ST4W_z_p_br_contiguous: {
10442 int msz = instr->ExtractBits(24, 23);
10443 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10444 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10445 LogicSVEAddressVector addr(
10446 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10447 addr.SetMsizeInBytesLog2(msz);
10448 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10449 SVEStructuredStoreHelper(vform,
10450 ReadPRegister(instr->GetPgLow8()),
10451 instr->GetRt(),
10452 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010453 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010454 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010455 default:
10456 VIXL_UNIMPLEMENTED();
10457 break;
10458 }
10459}
10460
10461void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
10462 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
10463 case STR_p_bi: {
10464 SimPRegister& pt = ReadPRegister(instr->GetPt());
10465 int pl = GetPredicateLengthInBytes();
10466 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10467 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10468 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
10469 for (int i = 0; i < pl; i++) {
10470 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
10471 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010472 LogPWrite(instr->GetPt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010473 break;
10474 }
10475 default:
10476 VIXL_UNIMPLEMENTED();
10477 break;
10478 }
10479}
10480
10481void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
10482 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
10483 case STR_z_bi: {
10484 SimVRegister& zt = ReadVRegister(instr->GetRt());
10485 int vl = GetVectorLengthInBytes();
10486 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10487 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10488 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
10489 for (int i = 0; i < vl; i++) {
10490 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
10491 }
Jacob Bramley7eb3e212019-11-22 17:28:05 +000010492 LogZWrite(instr->GetRt(), address);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010493 break;
10494 }
10495 default:
10496 VIXL_UNIMPLEMENTED();
10497 break;
10498 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010499}
10500
10501void Simulator::VisitSVEMulIndex(const Instruction* instr) {
10502 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010503 switch (instr->Mask(SVEMulIndexMask)) {
10504 case SDOT_z_zzzi_d:
10505 VIXL_UNIMPLEMENTED();
10506 break;
10507 case SDOT_z_zzzi_s:
10508 VIXL_UNIMPLEMENTED();
10509 break;
10510 case UDOT_z_zzzi_d:
10511 VIXL_UNIMPLEMENTED();
10512 break;
10513 case UDOT_z_zzzi_s:
10514 VIXL_UNIMPLEMENTED();
10515 break;
10516 default:
10517 VIXL_UNIMPLEMENTED();
10518 break;
10519 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010520}
10521
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010522void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010523 SimPRegister& pd = ReadPRegister(instr->GetPd());
10524 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10525 SimPRegister& pn = ReadPRegister(instr->GetPn());
10526 SimPRegister result;
10527
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010528 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010529 case BRKAS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010530 case BRKA_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010531 brka(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010532 break;
10533 case BRKBS_p_p_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010534 case BRKB_p_p_p:
TatWai Chong5d872292020-01-02 15:39:51 -080010535 brkb(result, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010536 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010537 default:
10538 VIXL_UNIMPLEMENTED();
10539 break;
10540 }
TatWai Chong5d872292020-01-02 15:39:51 -080010541
10542 if (instr->ExtractBit(4) == 1) {
10543 mov_merging(pd, pg, result);
10544 } else {
10545 mov_zeroing(pd, pg, result);
10546 }
10547
10548 // Set flag if needed.
10549 if (instr->ExtractBit(22) == 1) {
10550 PredTest(kFormatVnB, pg, pd);
10551 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010552}
10553
10554void Simulator::VisitSVEPropagateBreakToNextPartition(
10555 const Instruction* instr) {
TatWai Chong5d872292020-01-02 15:39:51 -080010556 SimPRegister& pdm = ReadPRegister(instr->GetPd());
10557 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10558 SimPRegister& pn = ReadPRegister(instr->GetPn());
10559
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010560 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010561 case BRKNS_p_p_pp:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010562 case BRKN_p_p_pp:
TatWai Chong5d872292020-01-02 15:39:51 -080010563 brkn(pdm, pg, pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010564 break;
10565 default:
10566 VIXL_UNIMPLEMENTED();
10567 break;
10568 }
TatWai Chong5d872292020-01-02 15:39:51 -080010569
10570 // Set flag if needed.
10571 if (instr->ExtractBit(22) == 1) {
10572 PredTest(kFormatVnB, pg, pdm);
10573 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010574}
10575
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010576void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010577 SimPRegister& pd = ReadPRegister(instr->GetPd());
10578 SimPRegister& pn = ReadPRegister(instr->GetPn());
10579
10580 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10581 SimVRegister zero;
10582 dup_immediate(kFormatVnB, zero, 0);
10583
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010584 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010585 case PUNPKHI_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010586 zip2(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010587 break;
10588 case PUNPKLO_p_p:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010589 zip1(kFormatVnB, temp, temp, zero);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010590 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010591 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010592 VIXL_UNIMPLEMENTED();
10593 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010594 }
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010595 Simulator::ExtractFromSimVRegister(pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010596}
10597
10598void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010599 VectorFormat vform = instr->GetSVEVectorFormat();
10600 SimPRegister& pd = ReadPRegister(instr->GetPd());
10601 SimPRegister& pn = ReadPRegister(instr->GetPn());
10602 SimPRegister& pm = ReadPRegister(instr->GetPm());
10603
10604 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
10605 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
10606
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010607 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010608 case TRN1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010609 trn1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010610 break;
10611 case TRN2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010612 trn2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010613 break;
10614 case UZP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010615 uzp1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010616 break;
10617 case UZP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010618 uzp2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010619 break;
10620 case ZIP1_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010621 zip1(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010622 break;
10623 case ZIP2_p_pp:
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010624 zip2(vform, temp0, temp0, temp1);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010625 break;
10626 default:
10627 VIXL_UNIMPLEMENTED();
10628 break;
10629 }
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010630 Simulator::ExtractFromSimVRegister(pd, temp0);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010631}
10632
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010633void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010634 switch (instr->Mask(SVEReversePredicateElementsMask)) {
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010635 case REV_p_p: {
10636 VectorFormat vform = instr->GetSVEVectorFormat();
10637 SimPRegister& pn = ReadPRegister(instr->GetPn());
10638 SimPRegister& pd = ReadPRegister(instr->GetPd());
10639 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10640 rev(vform, temp, temp);
10641 Simulator::ExtractFromSimVRegister(pd, temp);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010642 break;
Martyn Capewell7fd6fd52019-12-06 14:50:15 +000010643 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010644 default:
10645 VIXL_UNIMPLEMENTED();
10646 break;
10647 }
10648}
10649
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010650void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
Martyn Capewellac07af12019-12-02 14:55:05 +000010651 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10652 // Second source register "Zm" is encoded where "Zn" would usually be.
10653 SimVRegister& zm = ReadVRegister(instr->GetRn());
10654
10655 const int imm8h_mask = 0x001F0000;
10656 const int imm8l_mask = 0x00001C00;
10657 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
10658 int vl = GetVectorLengthInBytes();
10659 index = (index >= vl) ? 0 : index;
10660
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010661 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
10662 case EXT_z_zi_des:
Martyn Capewellac07af12019-12-02 14:55:05 +000010663 ext(kFormatVnB, zdn, zdn, zm, index);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010664 break;
10665 default:
10666 VIXL_UNIMPLEMENTED();
10667 break;
10668 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010669}
10670
10671void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
Martyn Capewell15f89012020-01-09 11:18:30 +000010672 VectorFormat vform = instr->GetSVEVectorFormat();
10673 SimVRegister& zd = ReadVRegister(instr->GetRd());
10674 SimVRegister& zn = ReadVRegister(instr->GetRn());
10675 SimVRegister& zm = ReadVRegister(instr->GetRm());
10676
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010677 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
10678 case TRN1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010679 trn1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010680 break;
10681 case TRN2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010682 trn2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010683 break;
10684 case UZP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010685 uzp1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010686 break;
10687 case UZP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010688 uzp2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010689 break;
10690 case ZIP1_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010691 zip1(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010692 break;
10693 case ZIP2_z_zz:
Martyn Capewell15f89012020-01-09 11:18:30 +000010694 zip2(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010695 break;
10696 default:
10697 VIXL_UNIMPLEMENTED();
10698 break;
10699 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010700}
10701
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010702void Simulator::VisitSVEConditionallyBroadcastElementToVector(
10703 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010704 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010705 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010706 case CLASTA_z_p_zz:
10707 VIXL_UNIMPLEMENTED();
10708 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010709 case CLASTB_z_p_zz:
10710 VIXL_UNIMPLEMENTED();
10711 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010712 default:
10713 VIXL_UNIMPLEMENTED();
10714 break;
10715 }
10716}
10717
10718void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
10719 const Instruction* instr) {
10720 USE(instr);
10721 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
10722 case CLASTA_v_p_z:
10723 VIXL_UNIMPLEMENTED();
10724 break;
10725 case CLASTB_v_p_z:
10726 VIXL_UNIMPLEMENTED();
10727 break;
10728 default:
10729 VIXL_UNIMPLEMENTED();
10730 break;
10731 }
10732}
10733
10734void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
10735 const Instruction* instr) {
10736 USE(instr);
10737 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
10738 case CLASTA_r_p_z:
10739 VIXL_UNIMPLEMENTED();
10740 break;
10741 case CLASTB_r_p_z:
10742 VIXL_UNIMPLEMENTED();
10743 break;
10744 default:
10745 VIXL_UNIMPLEMENTED();
10746 break;
10747 }
10748}
10749
10750void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
10751 const Instruction* instr) {
10752 USE(instr);
10753 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
10754 case LASTA_v_p_z:
10755 VIXL_UNIMPLEMENTED();
10756 break;
10757 case LASTB_v_p_z:
10758 VIXL_UNIMPLEMENTED();
10759 break;
10760 default:
10761 VIXL_UNIMPLEMENTED();
10762 break;
10763 }
10764}
10765
10766void Simulator::VisitSVEExtractElementToGeneralRegister(
10767 const Instruction* instr) {
10768 USE(instr);
10769 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
10770 case LASTA_r_p_z:
10771 VIXL_UNIMPLEMENTED();
10772 break;
10773 case LASTB_r_p_z:
10774 VIXL_UNIMPLEMENTED();
10775 break;
10776 default:
10777 VIXL_UNIMPLEMENTED();
10778 break;
10779 }
10780}
10781
10782void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
10783 USE(instr);
10784 switch (instr->Mask(SVECompressActiveElementsMask)) {
10785 case COMPACT_z_p_z:
10786 VIXL_UNIMPLEMENTED();
10787 break;
10788 default:
10789 VIXL_UNIMPLEMENTED();
10790 break;
10791 }
10792}
10793
10794void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
10795 const Instruction* instr) {
10796 VectorFormat vform = instr->GetSVEVectorFormat();
10797 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10798 SimVRegister z_result;
10799
10800 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010801 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010010802 dup_immediate(vform,
10803 z_result,
10804 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10805 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010806 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010807 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010808 VIXL_UNIMPLEMENTED();
10809 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010810 }
10811}
10812
10813void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010814 VectorFormat vform = instr->GetSVEVectorFormat();
10815 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
10816 SimVRegister& zd = ReadVRegister(instr->GetRd());
10817
10818 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010819 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010820 case CPY_z_p_i: {
10821 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
10822 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
10823 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010824 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010825 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010826 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010827 VIXL_UNIMPLEMENTED();
10828 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010829 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010830
10831 if (instr->ExtractBit(14) != 0) {
10832 mov_merging(vform, zd, pg, result);
10833 } else {
10834 mov_zeroing(vform, zd, pg, result);
10835 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010836}
10837
10838void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
Martyn Capewell77b6d982019-12-02 18:34:59 +000010839 SimVRegister& zd = ReadVRegister(instr->GetRd());
10840 SimVRegister& zn = ReadVRegister(instr->GetRn());
10841 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10842 SimVRegister result;
10843
10844 // In NEON, the chunk size in which elements are REVersed is in the
10845 // instruction mnemonic, and the element size attached to the register.
10846 // SVE reverses the semantics; the mapping to logic functions below is to
10847 // account for this.
10848 VectorFormat chunk_form = instr->GetSVEVectorFormat();
10849 VectorFormat element_form = kFormatUndefined;
10850
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010851 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010852 case RBIT_z_p_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010853 rbit(chunk_form, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010854 break;
10855 case REVB_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010856 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
10857 (chunk_form == kFormatVnD));
10858 element_form = kFormatVnB;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010859 break;
10860 case REVH_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010861 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
10862 element_form = kFormatVnH;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010863 break;
10864 case REVW_z_z:
Martyn Capewell77b6d982019-12-02 18:34:59 +000010865 VIXL_ASSERT(chunk_form == kFormatVnD);
10866 element_form = kFormatVnS;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010867 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010868 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010869 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010870 break;
10871 }
Martyn Capewell77b6d982019-12-02 18:34:59 +000010872
10873 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
10874 VIXL_ASSERT(element_form != kFormatUndefined);
10875 switch (chunk_form) {
10876 case kFormatVnH:
10877 rev16(element_form, result, zn);
10878 break;
10879 case kFormatVnS:
10880 rev32(element_form, result, zn);
10881 break;
10882 case kFormatVnD:
10883 rev64(element_form, result, zn);
10884 break;
10885 default:
10886 VIXL_UNIMPLEMENTED();
10887 }
10888 }
10889
10890 mov_merging(chunk_form, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010891}
10892
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010893void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010894 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010895 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
10896 case SPLICE_z_p_zz_des:
10897 VIXL_UNIMPLEMENTED();
10898 break;
10899 default:
10900 VIXL_UNIMPLEMENTED();
10901 break;
10902 }
10903}
TatWai Chong4f28df72019-08-14 17:50:30 -070010904
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010905void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
10906 SimVRegister& zd = ReadVRegister(instr->GetRd());
10907 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
10908 case DUP_z_r:
10909 dup_immediate(instr->GetSVEVectorFormat(),
10910 zd,
10911 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10912 break;
10913 default:
10914 VIXL_UNIMPLEMENTED();
10915 break;
10916 }
10917}
10918
10919void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
10920 SimVRegister& zd = ReadVRegister(instr->GetRd());
10921 VectorFormat vform = instr->GetSVEVectorFormat();
10922 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
10923 case INSR_z_v:
10924 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
10925 break;
10926 default:
10927 VIXL_UNIMPLEMENTED();
10928 break;
10929 }
10930}
10931
10932void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
10933 SimVRegister& zd = ReadVRegister(instr->GetRd());
10934 VectorFormat vform = instr->GetSVEVectorFormat();
10935 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
10936 case INSR_z_r:
10937 insr(vform, zd, ReadXRegister(instr->GetRn()));
10938 break;
10939 default:
10940 VIXL_UNIMPLEMENTED();
10941 break;
10942 }
10943}
10944
10945void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
10946 SimVRegister& zd = ReadVRegister(instr->GetRd());
10947 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070010948 case DUP_z_zi: {
10949 std::pair<int, int> index_and_lane_size =
10950 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10951 int index = index_and_lane_size.first;
10952 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
10953 VectorFormat vform =
10954 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
10955 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
10956 // Out of bounds, set the destination register to zero.
10957 dup_immediate(kFormatVnD, zd, 0);
10958 } else {
10959 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
10960 }
10961 return;
10962 }
TatWai Chong4f28df72019-08-14 17:50:30 -070010963 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010964 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070010965 break;
10966 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010967}
TatWai Chong4f28df72019-08-14 17:50:30 -070010968
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010969void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
10970 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070010971 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010972 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010973 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010974 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010975 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010976 default:
10977 VIXL_UNIMPLEMENTED();
10978 break;
10979 }
10980}
10981
10982void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
10983 SimVRegister& zd = ReadVRegister(instr->GetRd());
10984 VectorFormat vform = instr->GetSVEVectorFormat();
10985 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010986 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010987 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010988 break;
10989 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010990 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010991 break;
10992 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010993 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010994 break;
10995 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010996 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
10997 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010998 default:
10999 VIXL_UNIMPLEMENTED();
11000 break;
11001 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011002}
11003
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011004void Simulator::VisitSVETableLookup(const Instruction* instr) {
11005 SimVRegister& zd = ReadVRegister(instr->GetRd());
11006 switch (instr->Mask(SVETableLookupMask)) {
11007 case TBL_z_zz_1:
11008 Table(instr->GetSVEVectorFormat(),
11009 zd,
11010 ReadVRegister(instr->GetRn()),
11011 ReadVRegister(instr->GetRm()));
11012 return;
11013 default:
11014 break;
11015 }
11016}
11017
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011018void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
11019 USE(instr);
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010011020
11021 VectorFormat vform = instr->GetSVEVectorFormat();
11022 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11023 SimPRegister& pn = ReadPRegister(instr->GetPn());
11024
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011025 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010011026 case CNTP_r_p_p: {
11027 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011028 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010011029 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011030 default:
11031 VIXL_UNIMPLEMENTED();
11032 break;
11033 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011034}
11035
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011036void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
11037 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chonga3e8b172019-11-22 21:48:56 -080011038 SimPRegister& pd = ReadPRegister(instr->GetPd());
11039 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11040 SimPRegister& pn = ReadPRegister(instr->GetPn());
11041 SimPRegister& pm = ReadPRegister(instr->GetPm());
11042 SimPRegister result;
TatWai Chongf4fa8222019-06-17 12:08:14 -070011043 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011044 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011045 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011046 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011047 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011048 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011049 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011050 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011051 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011052 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011053 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011054 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011055 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011056 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011057 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070011058 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
TatWai Chonga3e8b172019-11-22 21:48:56 -080011059 result,
11060 pn,
11061 pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011062 break;
TatWai Chonga3e8b172019-11-22 21:48:56 -080011063 case SEL_p_p_pp:
11064 sel(pd, pg, pn, pm);
11065 return;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011066 default:
11067 VIXL_UNIMPLEMENTED();
11068 break;
11069 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080011070
11071 mov_zeroing(pd, pg, result);
11072 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
11073 PredTest(kFormatVnB, pg, pd);
11074 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011075}
11076
Jacob Bramley0ce75842019-07-17 18:12:50 +010011077void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011078 USE(instr);
Jacob Bramley0ce75842019-07-17 18:12:50 +010011079 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11080 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11081 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011082 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010011083 pfirst(pdn, pg, pdn);
11084 // TODO: Is this broken when pg == pdn?
11085 PredTest(kFormatVnB, pg, pdn);
11086 break;
11087 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011088 VIXL_UNIMPLEMENTED();
11089 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011090 }
11091}
11092
11093void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
11094 USE(instr);
11095 // This group only contains PTRUE{S}, and there are no unallocated encodings.
11096 VIXL_STATIC_ASSERT(
11097 SVEPredicateInitializeMask ==
11098 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
11099 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
11100 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
11101
11102 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11103 VectorFormat vform = instr->GetSVEVectorFormat();
11104
11105 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
11106 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
11107}
11108
11109void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
11110 USE(instr);
11111 // This group only contains PNEXT, and there are no unallocated encodings.
11112 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
11113 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
11114
11115 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11116 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11117 VectorFormat vform = instr->GetSVEVectorFormat();
11118
11119 pnext(vform, pdn, pg, pdn);
11120 // TODO: Is this broken when pg == pdn?
11121 PredTest(vform, pg, pdn);
11122}
11123
11124void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
11125 const Instruction* instr) {
TatWai Chonga3e8b172019-11-22 21:48:56 -080011126 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11127 LogicPRegister pg(ReadPRegister(instr->GetPn()));
11128 FlagsUpdate flags = LeaveFlags;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011129 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
11130 case RDFFR_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011131 // Do nothing.
11132 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011133 case RDFFRS_p_p_f:
TatWai Chonga3e8b172019-11-22 21:48:56 -080011134 flags = SetFlags;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011135 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011136 default:
11137 VIXL_UNIMPLEMENTED();
11138 break;
11139 }
TatWai Chonga3e8b172019-11-22 21:48:56 -080011140
11141 LogicPRegister ffr(ReadFFR());
11142 mov_zeroing(pd, pg, ffr);
11143
11144 if (flags == SetFlags) {
11145 PredTest(kFormatVnB, pg, pd);
11146 }
Jacob Bramley0ce75842019-07-17 18:12:50 +010011147}
11148
11149void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
11150 const Instruction* instr) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011151 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11152 LogicPRegister ffr(ReadFFR());
Jacob Bramley0ce75842019-07-17 18:12:50 +010011153 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011154 case RDFFR_p_f:
TatWai Chong4023d7a2019-11-18 14:16:28 -080011155 mov(pd, ffr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011156 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011157 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011158 VIXL_UNIMPLEMENTED();
11159 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010011160 }
11161}
11162
11163void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
11164 USE(instr);
11165 switch (instr->Mask(SVEPredicateTestMask)) {
11166 case PTEST_p_p:
11167 PredTest(kFormatVnB,
11168 ReadPRegister(instr->ExtractBits(13, 10)),
11169 ReadPRegister(instr->GetPn()));
11170 break;
11171 default:
11172 VIXL_UNIMPLEMENTED();
11173 break;
11174 }
11175}
11176
11177void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
11178 USE(instr);
11179 switch (instr->Mask(SVEPredicateZeroMask)) {
11180 case PFALSE_p:
11181 pfalse(ReadPRegister(instr->GetPd()));
11182 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011183 default:
11184 VIXL_UNIMPLEMENTED();
11185 break;
11186 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011187}
11188
11189void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
TatWai Chong38303d92019-12-02 15:49:29 -080011190 SimPRegister& pd = ReadPRegister(instr->GetPd());
11191 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11192 SimPRegister& pn = ReadPRegister(instr->GetPn());
11193 SimPRegister& pm = ReadPRegister(instr->GetPm());
11194
11195 bool set_flags = false;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011196 switch (instr->Mask(SVEPropagateBreakMask)) {
11197 case BRKPAS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011198 set_flags = true;
11199 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011200 case BRKPA_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011201 brkpa(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011202 break;
11203 case BRKPBS_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011204 set_flags = true;
11205 VIXL_FALLTHROUGH();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011206 case BRKPB_p_p_pp:
TatWai Chong38303d92019-12-02 15:49:29 -080011207 brkpb(pd, pg, pn, pm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011208 break;
11209 default:
11210 VIXL_UNIMPLEMENTED();
11211 break;
11212 }
TatWai Chong38303d92019-12-02 15:49:29 -080011213
11214 if (set_flags) {
11215 PredTest(kFormatVnB, pg, pd);
11216 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011217}
11218
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011219void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
11220 uint64_t length = 0;
11221 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
11222 case ADDPL_r_ri:
11223 length = GetPredicateLengthInBytes();
11224 break;
11225 case ADDVL_r_ri:
11226 length = GetVectorLengthInBytes();
11227 break;
11228 default:
11229 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011230 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011231 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011232 WriteXRegister(instr->GetRd(),
11233 base + (length * instr->GetImmSVEVLScale()),
11234 LogRegWrites,
11235 Reg31IsStackPointer);
11236}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010011237
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011238void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
11239 int64_t scale = instr->GetImmSVEVLScale();
11240
11241 switch (instr->Mask(SVEStackFrameSizeMask)) {
11242 case RDVL_r_i:
11243 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
11244 break;
11245 default:
11246 VIXL_UNIMPLEMENTED();
11247 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011248}
11249
11250void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
11251 USE(instr);
TatWai Chong6205eb42019-09-24 10:07:20 +010011252
11253 // The only instruction in this group is `sel`, and there are no unused
11254 // encodings.
11255 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
11256
11257 VectorFormat vform = instr->GetSVEVectorFormat();
11258 SimVRegister& zd = ReadVRegister(instr->GetRd());
11259 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11260 SimVRegister& zn = ReadVRegister(instr->GetRn());
11261 SimVRegister& zm = ReadVRegister(instr->GetRm());
11262
11263 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011264}
11265
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011266void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011267 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011268 switch (instr->Mask(SVEFFRInitialiseMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011269 case SETFFR_f: {
11270 LogicPRegister ffr(ReadFFR());
11271 ffr.SetAllBits();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011272 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011273 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010011274 default:
11275 VIXL_UNIMPLEMENTED();
11276 break;
11277 }
11278}
11279
11280void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
11281 USE(instr);
11282 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
TatWai Chong4023d7a2019-11-18 14:16:28 -080011283 case WRFFR_f_p: {
11284 SimPRegister pn(ReadPRegister(instr->GetPn()));
11285 bool last_active = true;
11286 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
11287 bool active = pn.GetBit(i);
11288 if (active && !last_active) {
11289 // `pn` is non-monotonic. This is UNPREDICTABLE.
11290 VIXL_ABORT();
11291 }
11292 last_active = active;
11293 }
11294 mov(ReadFFR(), pn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011295 break;
TatWai Chong4023d7a2019-11-18 14:16:28 -080011296 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000011297 default:
11298 VIXL_UNIMPLEMENTED();
11299 break;
11300 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000011301}
Alexandre Ramesd3832962016-07-04 15:03:43 +010011302
TatWai Chong6205eb42019-09-24 10:07:20 +010011303void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
11304 USE(instr);
11305 bool is_signed;
11306 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
11307 case LD1B_z_p_bi_u8:
11308 case LD1B_z_p_bi_u16:
11309 case LD1B_z_p_bi_u32:
11310 case LD1B_z_p_bi_u64:
11311 case LD1H_z_p_bi_u16:
11312 case LD1H_z_p_bi_u32:
11313 case LD1H_z_p_bi_u64:
11314 case LD1W_z_p_bi_u32:
11315 case LD1W_z_p_bi_u64:
11316 case LD1D_z_p_bi_u64:
11317 is_signed = false;
11318 break;
11319 case LD1SB_z_p_bi_s16:
11320 case LD1SB_z_p_bi_s32:
11321 case LD1SB_z_p_bi_s64:
11322 case LD1SH_z_p_bi_s32:
11323 case LD1SH_z_p_bi_s64:
11324 case LD1SW_z_p_bi_s64:
11325 is_signed = true;
11326 break;
11327 default:
11328 // This encoding group is complete, so no other values should be possible.
11329 VIXL_UNREACHABLE();
11330 is_signed = false;
11331 break;
11332 }
11333
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011334 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010011335 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11336 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010011337 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
11338 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
11339 uint64_t offset =
11340 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011341 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011342 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011343 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11344 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011345 ReadPRegister(instr->GetPgLow8()),
11346 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011347 addr,
11348 is_signed);
11349}
11350
11351void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
11352 const Instruction* instr) {
11353 bool is_signed;
11354 USE(instr);
11355 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
11356 case LD1B_z_p_br_u8:
11357 case LD1B_z_p_br_u16:
11358 case LD1B_z_p_br_u32:
11359 case LD1B_z_p_br_u64:
11360 case LD1H_z_p_br_u16:
11361 case LD1H_z_p_br_u32:
11362 case LD1H_z_p_br_u64:
11363 case LD1W_z_p_br_u32:
11364 case LD1W_z_p_br_u64:
11365 case LD1D_z_p_br_u64:
11366 is_signed = false;
11367 break;
11368 case LD1SB_z_p_br_s16:
11369 case LD1SB_z_p_br_s32:
11370 case LD1SB_z_p_br_s64:
11371 case LD1SH_z_p_br_s32:
11372 case LD1SH_z_p_br_s64:
11373 case LD1SW_z_p_br_s64:
11374 is_signed = true;
11375 break;
11376 default:
11377 // This encoding group is complete, so no other values should be possible.
11378 VIXL_UNREACHABLE();
11379 is_signed = false;
11380 break;
11381 }
11382
11383 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11384 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11385 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11386 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11387 uint64_t offset = ReadXRegister(instr->GetRm());
11388 offset <<= msize_in_bytes_log2;
11389 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011390 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11391 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011392 ReadPRegister(instr->GetPgLow8()),
11393 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011394 addr,
11395 is_signed);
11396}
11397
Alexandre Ramesd3832962016-07-04 15:03:43 +010011398void Simulator::DoUnreachable(const Instruction* instr) {
11399 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11400 (instr->GetImmException() == kUnreachableOpcode));
11401
11402 fprintf(stream_,
11403 "Hit UNREACHABLE marker at pc=%p.\n",
11404 reinterpret_cast<const void*>(instr));
11405 abort();
11406}
11407
11408
11409void Simulator::DoTrace(const Instruction* instr) {
11410 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11411 (instr->GetImmException() == kTraceOpcode));
11412
11413 // Read the arguments encoded inline in the instruction stream.
11414 uint32_t parameters;
11415 uint32_t command;
11416
11417 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11418 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11419 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
11420
11421 switch (command) {
11422 case TRACE_ENABLE:
11423 SetTraceParameters(GetTraceParameters() | parameters);
11424 break;
11425 case TRACE_DISABLE:
11426 SetTraceParameters(GetTraceParameters() & ~parameters);
11427 break;
11428 default:
11429 VIXL_UNREACHABLE();
11430 }
11431
11432 WritePc(instr->GetInstructionAtOffset(kTraceLength));
11433}
11434
11435
11436void Simulator::DoLog(const Instruction* instr) {
11437 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11438 (instr->GetImmException() == kLogOpcode));
11439
11440 // Read the arguments encoded inline in the instruction stream.
11441 uint32_t parameters;
11442
11443 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11444 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11445
11446 // We don't support a one-shot LOG_DISASM.
11447 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
11448 // Print the requested information.
11449 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
11450 if (parameters & LOG_REGS) PrintRegisters();
11451 if (parameters & LOG_VREGS) PrintVRegisters();
11452
11453 WritePc(instr->GetInstructionAtOffset(kLogLength));
11454}
11455
11456
11457void Simulator::DoPrintf(const Instruction* instr) {
11458 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11459 (instr->GetImmException() == kPrintfOpcode));
11460
11461 // Read the arguments encoded inline in the instruction stream.
11462 uint32_t arg_count;
11463 uint32_t arg_pattern_list;
11464 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11465 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
11466 memcpy(&arg_pattern_list,
11467 instr + kPrintfArgPatternListOffset,
11468 sizeof(arg_pattern_list));
11469
11470 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
11471 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
11472
11473 // We need to call the host printf function with a set of arguments defined by
11474 // arg_pattern_list. Because we don't know the types and sizes of the
11475 // arguments, this is very difficult to do in a robust and portable way. To
11476 // work around the problem, we pick apart the format string, and print one
11477 // format placeholder at a time.
11478
11479 // Allocate space for the format string. We take a copy, so we can modify it.
11480 // Leave enough space for one extra character per expected argument (plus the
11481 // '\0' termination).
11482 const char* format_base = ReadRegister<const char*>(0);
11483 VIXL_ASSERT(format_base != NULL);
11484 size_t length = strlen(format_base) + 1;
11485 char* const format = new char[length + arg_count];
11486
11487 // A list of chunks, each with exactly one format placeholder.
11488 const char* chunks[kPrintfMaxArgCount];
11489
11490 // Copy the format string and search for format placeholders.
11491 uint32_t placeholder_count = 0;
11492 char* format_scratch = format;
11493 for (size_t i = 0; i < length; i++) {
11494 if (format_base[i] != '%') {
11495 *format_scratch++ = format_base[i];
11496 } else {
11497 if (format_base[i + 1] == '%') {
11498 // Ignore explicit "%%" sequences.
11499 *format_scratch++ = format_base[i];
11500 i++;
11501 // Chunks after the first are passed as format strings to printf, so we
11502 // need to escape '%' characters in those chunks.
11503 if (placeholder_count > 0) *format_scratch++ = format_base[i];
11504 } else {
11505 VIXL_CHECK(placeholder_count < arg_count);
11506 // Insert '\0' before placeholders, and store their locations.
11507 *format_scratch++ = '\0';
11508 chunks[placeholder_count++] = format_scratch;
11509 *format_scratch++ = format_base[i];
11510 }
11511 }
11512 }
11513 VIXL_CHECK(placeholder_count == arg_count);
11514
11515 // Finally, call printf with each chunk, passing the appropriate register
11516 // argument. Normally, printf returns the number of bytes transmitted, so we
11517 // can emulate a single printf call by adding the result from each chunk. If
11518 // any call returns a negative (error) value, though, just return that value.
11519
11520 printf("%s", clr_printf);
11521
11522 // Because '\0' is inserted before each placeholder, the first string in
11523 // 'format' contains no format placeholders and should be printed literally.
11524 int result = printf("%s", format);
11525 int pcs_r = 1; // Start at x1. x0 holds the format string.
11526 int pcs_f = 0; // Start at d0.
11527 if (result >= 0) {
11528 for (uint32_t i = 0; i < placeholder_count; i++) {
11529 int part_result = -1;
11530
11531 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
11532 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
11533 switch (arg_pattern) {
11534 case kPrintfArgW:
11535 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
11536 break;
11537 case kPrintfArgX:
11538 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
11539 break;
11540 case kPrintfArgD:
11541 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
11542 break;
11543 default:
11544 VIXL_UNREACHABLE();
11545 }
11546
11547 if (part_result < 0) {
11548 // Handle error values.
11549 result = part_result;
11550 break;
11551 }
11552
11553 result += part_result;
11554 }
11555 }
11556
11557 printf("%s", clr_normal);
11558
11559 // Printf returns its result in x0 (just like the C library's printf).
11560 WriteXRegister(0, result);
11561
11562 // The printf parameters are inlined in the code, so skip them.
11563 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
11564
11565 // Set LR as if we'd just called a native printf function.
11566 WriteLr(ReadPc());
11567
11568 delete[] format;
11569}
11570
Alexandre Rames064e02d2016-07-12 11:53:13 +010011571
Alexandre Ramesca73ba02016-07-28 09:16:03 +010011572#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010011573void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011574 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011575 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
11576 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011577 uintptr_t call_wrapper_address =
11578 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
11579 uintptr_t function_address =
11580 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080011581 RuntimeCallType call_type = static_cast<RuntimeCallType>(
11582 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011583 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010011584 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011585
11586 if (call_type == kCallRuntime) {
11587 WriteRegister(kLinkRegCode,
11588 instr->GetInstructionAtOffset(kRuntimeCallLength));
11589 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011590 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011591 // Read the return address from `lr` and write it into `pc`.
11592 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011593}
11594#else
11595void Simulator::DoRuntimeCall(const Instruction* instr) {
11596 USE(instr);
11597 VIXL_UNREACHABLE();
11598}
11599#endif
11600
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011601
11602void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
11603 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
11604
11605 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011606 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011607 std::numeric_limits<ElementType>::max());
11608
11609 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
11610
11611 size_t element_size = sizeof(ElementType);
11612 size_t offset = kConfigureCPUFeaturesListOffset;
11613
11614 // Read the kNone-terminated list of features.
11615 CPUFeatures parameters;
11616 while (true) {
11617 ElementType feature = Memory::Read<ElementType>(instr + offset);
11618 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011619 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011620 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
11621 }
11622
11623 switch (instr->GetImmException()) {
11624 case kSetCPUFeaturesOpcode:
11625 SetCPUFeatures(parameters);
11626 break;
11627 case kEnableCPUFeaturesOpcode:
11628 GetCPUFeatures()->Combine(parameters);
11629 break;
11630 case kDisableCPUFeaturesOpcode:
11631 GetCPUFeatures()->Remove(parameters);
11632 break;
11633 default:
11634 VIXL_UNREACHABLE();
11635 break;
11636 }
11637
11638 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
11639}
11640
11641
11642void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
11643 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11644 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
11645 USE(instr);
11646
11647 saved_cpu_features_.push_back(*GetCPUFeatures());
11648}
11649
11650
11651void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
11652 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11653 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
11654 USE(instr);
11655
11656 SetCPUFeatures(saved_cpu_features_.back());
11657 saved_cpu_features_.pop_back();
11658}
11659
11660
Alexandre Ramesd3832962016-07-04 15:03:43 +010011661} // namespace aarch64
11662} // namespace vixl
11663
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010011664#endif // VIXL_INCLUDE_SIMULATOR_AARCH64