blob: 10353bbc053daa38589d27a169702b9f92af8962 [file] [log] [blame]
Alexandre Ramesd3832962016-07-04 15:03:43 +01001// Copyright 2015, VIXL authors
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// * Neither the name of ARM Limited nor the names of its contributors may be
13// used to endorse or promote products derived from this software without
14// specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010027#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
Alexandre Ramesd3832962016-07-04 15:03:43 +010028
Alexandre Ramesd3832962016-07-04 15:03:43 +010029#include <cmath>
Pierre Langlois1bce0072017-06-06 17:58:58 +010030#include <cstring>
Martyn Capewell5b24fb32016-11-02 18:52:55 +000031#include <limits>
Alexandre Ramesd3832962016-07-04 15:03:43 +010032
Alexandre Ramesb49bdb72016-09-26 12:08:57 +010033#include "simulator-aarch64.h"
Alexandre Ramesd3832962016-07-04 15:03:43 +010034
35namespace vixl {
36namespace aarch64 {
37
Jacob Bramleyca789742018-09-13 14:25:46 +010038using vixl::internal::SimFloat16;
39
Alexandre Ramesd3832962016-07-04 15:03:43 +010040const Instruction* Simulator::kEndOfSimAddress = NULL;
41
42void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
43 int width = msb - lsb + 1;
44 VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
45
46 bits <<= lsb;
47 uint32_t mask = ((1 << width) - 1) << lsb;
48 VIXL_ASSERT((mask & write_ignore_mask_) == 0);
49
50 value_ = (value_ & ~mask) | (bits & mask);
51}
52
53
54SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
55 switch (id) {
56 case NZCV:
57 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
58 case FPCR:
59 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
60 default:
61 VIXL_UNREACHABLE();
62 return SimSystemRegister();
63 }
64}
65
66
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010067Simulator::Simulator(Decoder* decoder, FILE* stream)
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +010068 : movprfx_(NULL), cpu_features_auditor_(decoder, CPUFeatures::All()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010069 // Ensure that shift operations act as the simulator expects.
70 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
71 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
72
73 instruction_stats_ = false;
74
75 // Set up the decoder.
76 decoder_ = decoder;
77 decoder_->AppendVisitor(this);
78
79 stream_ = stream;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010080
Alexandre Ramesd3832962016-07-04 15:03:43 +010081 print_disasm_ = new PrintDisassembler(stream_);
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010082 // The Simulator and Disassembler share the same available list, held by the
83 // auditor. The Disassembler only annotates instructions with features that
84 // are _not_ available, so registering the auditor should have no effect
85 // unless the simulator is about to abort (due to missing features). In
86 // practice, this means that with trace enabled, the simulator will crash just
87 // after the disassembler prints the instruction, with the missing features
88 // enumerated.
89 print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
90
Alexandre Ramesd3832962016-07-04 15:03:43 +010091 SetColouredTrace(false);
92 trace_parameters_ = LOG_NONE;
93
Jacob Bramley9d06c4d2019-05-13 18:15:06 +010094 // We have to configure the SVE vector register length before calling
95 // ResetState().
96 SetVectorLengthInBits(kZRegMinSize);
97
Alexandre Ramesd3832962016-07-04 15:03:43 +010098 ResetState();
99
100 // Allocate and set up the simulator stack.
101 stack_ = new byte[stack_size_];
102 stack_limit_ = stack_ + stack_protection_size_;
103 // Configure the starting stack pointer.
104 // - Find the top of the stack.
105 byte* tos = stack_ + stack_size_;
106 // - There's a protection region at both ends of the stack.
107 tos -= stack_protection_size_;
108 // - The stack pointer must be 16-byte aligned.
109 tos = AlignDown(tos, 16);
110 WriteSp(tos);
111
112 instrumentation_ = NULL;
113
114 // Print a warning about exclusive-access instructions, but only the first
115 // time they are encountered. This warning can be silenced using
116 // SilenceExclusiveAccessWarning().
117 print_exclusive_access_warning_ = true;
Martyn Capewellcb963f72018-10-22 15:25:28 +0100118
119 guard_pages_ = false;
TatWai Chong04edf682018-12-27 16:01:02 -0800120
121 // Initialize the common state of RNDR and RNDRRS.
122 uint16_t seed[3] = {11, 22, 33};
123 VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rndr_state_));
124 memcpy(rndr_state_, seed, sizeof(rndr_state_));
TatWai Chongb2d8d1f2019-10-21 15:19:31 -0700125
126 // Initialize all bits of pseudo predicate register to true.
127 LogicPRegister ones(pregister_all_true_);
128 ones.SetAllBits();
Alexandre Ramesd3832962016-07-04 15:03:43 +0100129}
130
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100131void Simulator::ResetSystemRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100132 // Reset the system registers.
133 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
134 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100135}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100136
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100137void Simulator::ResetRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100138 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
139 WriteXRegister(i, 0xbadbeef);
140 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100141 // Returning to address 0 exits the Simulator.
142 WriteLr(kEndOfSimAddress);
143}
Pierre Langlois23703a72016-08-15 17:23:39 +0100144
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100145void Simulator::ResetVRegisters() {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800146 // 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 +0100147 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
148 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
TatWai Chonge3d059b2019-02-27 15:04:51 -0800149 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100150 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100151 vregisters_[i].NotifyAccessAsZ();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100152 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800153 // Encode the register number and (D-sized) lane into each NaN, to
154 // make them easier to trace.
155 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
156 (0x0000000000000001 * lane);
157 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
158 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100159 vregisters_[i].Insert(lane, nan_bits);
TatWai Chonge3d059b2019-02-27 15:04:51 -0800160 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100161 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100162}
TatWai Chonge3d059b2019-02-27 15:04:51 -0800163
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100164void Simulator::ResetPRegisters() {
165 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
166 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
167 // Ensure the register configuration fits in this bit encoding.
168 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
169 VIXL_ASSERT(lane_count <= UINT8_MAX);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700170 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100171 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
172 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge0590cc2019-03-18 16:23:59 -0700173 // Encode the register number and (H-sized) lane into each lane slot.
174 uint16_t bits = (0x0100 * lane) | i;
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100175 pregisters_[i].Insert(lane, bits);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700176 }
177 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100178}
TatWai Chonge0590cc2019-03-18 16:23:59 -0700179
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100180void Simulator::ResetState() {
181 ResetSystemRegisters();
182 ResetRegisters();
183 ResetVRegisters();
184 ResetPRegisters();
Martyn Capewellcb963f72018-10-22 15:25:28 +0100185
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100186 pc_ = NULL;
187 pc_modified_ = false;
188
189 // BTI state.
Martyn Capewellcb963f72018-10-22 15:25:28 +0100190 btype_ = DefaultBType;
191 next_btype_ = DefaultBType;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100192}
193
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100194void Simulator::SetVectorLengthInBits(unsigned vector_length) {
195 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
196 (vector_length <= kZRegMaxSize));
197 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
198 vector_length_ = vector_length;
199
200 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
201 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
202 }
203 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
204 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
205 }
206
207 ResetVRegisters();
208 ResetPRegisters();
209}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100210
211Simulator::~Simulator() {
212 delete[] stack_;
213 // The decoder may outlive the simulator.
214 decoder_->RemoveVisitor(print_disasm_);
215 delete print_disasm_;
216
217 decoder_->RemoveVisitor(instrumentation_);
218 delete instrumentation_;
219}
220
221
222void Simulator::Run() {
223 // Flush any written registers before executing anything, so that
224 // manually-set registers are logged _before_ the first instruction.
225 LogAllWrittenRegisters();
226
227 while (pc_ != kEndOfSimAddress) {
228 ExecuteInstruction();
229 }
230}
231
232
233void Simulator::RunFrom(const Instruction* first) {
Jacob Bramleye79723a2016-06-07 17:50:47 +0100234 WritePc(first, NoBranchLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100235 Run();
236}
237
238
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100239// clang-format off
Alexandre Ramesd3832962016-07-04 15:03:43 +0100240const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
241 "x6", "x7", "x8", "x9", "x10", "x11",
242 "x12", "x13", "x14", "x15", "x16", "x17",
243 "x18", "x19", "x20", "x21", "x22", "x23",
244 "x24", "x25", "x26", "x27", "x28", "x29",
245 "lr", "xzr", "sp"};
246
247const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
248 "w6", "w7", "w8", "w9", "w10", "w11",
249 "w12", "w13", "w14", "w15", "w16", "w17",
250 "w18", "w19", "w20", "w21", "w22", "w23",
251 "w24", "w25", "w26", "w27", "w28", "w29",
252 "w30", "wzr", "wsp"};
253
Carey Williamsd8bb3572018-04-10 11:58:07 +0100254const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
255 "h6", "h7", "h8", "h9", "h10", "h11",
256 "h12", "h13", "h14", "h15", "h16", "h17",
257 "h18", "h19", "h20", "h21", "h22", "h23",
258 "h24", "h25", "h26", "h27", "h28", "h29",
259 "h30", "h31"};
260
Alexandre Ramesd3832962016-07-04 15:03:43 +0100261const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
262 "s6", "s7", "s8", "s9", "s10", "s11",
263 "s12", "s13", "s14", "s15", "s16", "s17",
264 "s18", "s19", "s20", "s21", "s22", "s23",
265 "s24", "s25", "s26", "s27", "s28", "s29",
266 "s30", "s31"};
267
268const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
269 "d6", "d7", "d8", "d9", "d10", "d11",
270 "d12", "d13", "d14", "d15", "d16", "d17",
271 "d18", "d19", "d20", "d21", "d22", "d23",
272 "d24", "d25", "d26", "d27", "d28", "d29",
273 "d30", "d31"};
274
275const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
276 "v6", "v7", "v8", "v9", "v10", "v11",
277 "v12", "v13", "v14", "v15", "v16", "v17",
278 "v18", "v19", "v20", "v21", "v22", "v23",
279 "v24", "v25", "v26", "v27", "v28", "v29",
280 "v30", "v31"};
281
TatWai Chong72d2e562019-05-16 11:22:22 -0700282const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
283 "z6", "z7", "z8", "z9", "z10", "z11",
284 "z12", "z13", "z14", "z15", "z16", "z17",
285 "z18", "z19", "z20", "z21", "z22", "z23",
286 "z24", "z25", "z26", "z27", "z28", "z29",
287 "z30", "z31"};
288
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100289const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
290 "p6", "p7", "p8", "p9", "p10", "p11",
291 "p12", "p13", "p14", "p15"};
292// clang-format on
293
Alexandre Ramesd3832962016-07-04 15:03:43 +0100294
295const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
296 VIXL_ASSERT(code < kNumberOfRegisters);
297 // If the code represents the stack pointer, index the name after zr.
298 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
299 code = kZeroRegCode + 1;
300 }
301 return wreg_names[code];
302}
303
304
305const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
306 VIXL_ASSERT(code < kNumberOfRegisters);
307 // If the code represents the stack pointer, index the name after zr.
308 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
309 code = kZeroRegCode + 1;
310 }
311 return xreg_names[code];
312}
313
314
Carey Williamsd8bb3572018-04-10 11:58:07 +0100315const char* Simulator::HRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100316 VIXL_ASSERT(code < kNumberOfVRegisters);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100317 return hreg_names[code];
318}
319
320
Alexandre Ramesd3832962016-07-04 15:03:43 +0100321const char* Simulator::SRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100322 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100323 return sreg_names[code];
324}
325
326
327const char* Simulator::DRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100328 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100329 return dreg_names[code];
330}
331
332
333const char* Simulator::VRegNameForCode(unsigned code) {
334 VIXL_ASSERT(code < kNumberOfVRegisters);
335 return vreg_names[code];
336}
337
338
TatWai Chong72d2e562019-05-16 11:22:22 -0700339const char* Simulator::ZRegNameForCode(unsigned code) {
340 VIXL_ASSERT(code < kNumberOfZRegisters);
341 return zreg_names[code];
342}
343
344
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100345const char* Simulator::PRegNameForCode(unsigned code) {
346 VIXL_ASSERT(code < kNumberOfPRegisters);
347 return preg_names[code];
348}
349
350
Alexandre Ramesd3832962016-07-04 15:03:43 +0100351#define COLOUR(colour_code) "\033[0;" colour_code "m"
352#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
Jacob Bramleye79723a2016-06-07 17:50:47 +0100353#define COLOUR_HIGHLIGHT "\033[43m"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100354#define NORMAL ""
355#define GREY "30"
356#define RED "31"
357#define GREEN "32"
358#define YELLOW "33"
359#define BLUE "34"
360#define MAGENTA "35"
361#define CYAN "36"
362#define WHITE "37"
363void Simulator::SetColouredTrace(bool value) {
364 coloured_trace_ = value;
365
366 clr_normal = value ? COLOUR(NORMAL) : "";
367 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
368 clr_flag_value = value ? COLOUR(NORMAL) : "";
369 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
370 clr_reg_value = value ? COLOUR(CYAN) : "";
371 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
372 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100373 clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
374 clr_preg_value = value ? COLOUR(GREEN) : "";
Alexandre Ramesd3832962016-07-04 15:03:43 +0100375 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
376 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
377 clr_warning_message = value ? COLOUR(YELLOW) : "";
378 clr_printf = value ? COLOUR(GREEN) : "";
Jacob Bramleye79723a2016-06-07 17:50:47 +0100379 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100380
381 if (value) {
382 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
383 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
384 } else {
385 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
386 print_disasm_->SetCPUFeaturesSuffix("");
387 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100388}
389
390
391void Simulator::SetTraceParameters(int parameters) {
392 bool disasm_before = trace_parameters_ & LOG_DISASM;
393 trace_parameters_ = parameters;
394 bool disasm_after = trace_parameters_ & LOG_DISASM;
395
396 if (disasm_before != disasm_after) {
397 if (disasm_after) {
398 decoder_->InsertVisitorBefore(print_disasm_, this);
399 } else {
400 decoder_->RemoveVisitor(print_disasm_);
401 }
402 }
403}
404
405
406void Simulator::SetInstructionStats(bool value) {
407 if (value != instruction_stats_) {
408 if (value) {
409 if (instrumentation_ == NULL) {
410 // Set the sample period to 10, as the VIXL examples and tests are
411 // short.
412 instrumentation_ = new Instrument("vixl_stats.csv", 10);
413 }
414 decoder_->AppendVisitor(instrumentation_);
415 } else if (instrumentation_ != NULL) {
416 decoder_->RemoveVisitor(instrumentation_);
417 }
418 instruction_stats_ = value;
419 }
420}
421
422// Helpers ---------------------------------------------------------------------
423uint64_t Simulator::AddWithCarry(unsigned reg_size,
424 bool set_flags,
425 uint64_t left,
426 uint64_t right,
427 int carry_in) {
428 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
429 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
430
431 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
432 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
433 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
434
435 left &= reg_mask;
436 right &= reg_mask;
437 uint64_t result = (left + right + carry_in) & reg_mask;
438
439 if (set_flags) {
440 ReadNzcv().SetN(CalcNFlag(result, reg_size));
441 ReadNzcv().SetZ(CalcZFlag(result));
442
443 // Compute the C flag by comparing the result to the max unsigned integer.
444 uint64_t max_uint_2op = max_uint - carry_in;
445 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
446 ReadNzcv().SetC(C ? 1 : 0);
447
448 // Overflow iff the sign bit is the same for the two inputs and different
449 // for the result.
450 uint64_t left_sign = left & sign_mask;
451 uint64_t right_sign = right & sign_mask;
452 uint64_t result_sign = result & sign_mask;
453 bool V = (left_sign == right_sign) && (left_sign != result_sign);
454 ReadNzcv().SetV(V ? 1 : 0);
455
456 LogSystemRegister(NZCV);
457 }
458 return result;
459}
460
461
462int64_t Simulator::ShiftOperand(unsigned reg_size,
463 int64_t value,
464 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100465 unsigned amount) const {
TatWai Chong29a0c432019-11-06 22:20:44 -0800466 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
467 (reg_size == kSRegSize) || (reg_size == kDRegSize));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100468 if (amount == 0) {
469 return value;
470 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000471
TatWai Chong29a0c432019-11-06 22:20:44 -0800472 uint64_t uvalue = static_cast<uint64_t>(value);
473 uint64_t mask = GetUintMask(reg_size);
474 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
475 // The behavior is undefined in c++ if the shift amount greater than or equal
476 // to the register lane size. Work out the shifted result based on
477 // architectural behavior before performing the c++ type shfit operations.
Alexandre Ramesd3832962016-07-04 15:03:43 +0100478 switch (shift_type) {
479 case LSL:
TatWai Chong29a0c432019-11-06 22:20:44 -0800480 if (amount >= reg_size) {
481 return UINT64_C(0);
482 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000483 uvalue <<= amount;
484 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100485 case LSR:
TatWai Chong29a0c432019-11-06 22:20:44 -0800486 if (amount >= reg_size) {
487 return UINT64_C(0);
488 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000489 uvalue >>= amount;
490 break;
491 case ASR:
TatWai Chong29a0c432019-11-06 22:20:44 -0800492 if (amount >= reg_size) {
493 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
494 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000495 uvalue >>= amount;
496 if (is_negative) {
497 // Simulate sign-extension to 64 bits.
498 uvalue |= ~UINT64_C(0) << (reg_size - amount);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100499 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000500 break;
501 case ROR: {
Martyn Capewellfb8e3df2016-11-03 15:50:19 +0000502 uvalue = RotateRight(uvalue, amount, reg_size);
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000503 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100504 }
505 default:
506 VIXL_UNIMPLEMENTED();
507 return 0;
508 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000509 uvalue &= mask;
510
511 int64_t result;
512 memcpy(&result, &uvalue, sizeof(result));
513 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100514}
515
516
517int64_t Simulator::ExtendValue(unsigned reg_size,
518 int64_t value,
519 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100520 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100521 switch (extend_type) {
522 case UXTB:
523 value &= kByteMask;
524 break;
525 case UXTH:
526 value &= kHalfWordMask;
527 break;
528 case UXTW:
529 value &= kWordMask;
530 break;
531 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000532 value &= kByteMask;
533 if ((value & 0x80) != 0) {
534 value |= ~UINT64_C(0) << 8;
535 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100536 break;
537 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000538 value &= kHalfWordMask;
539 if ((value & 0x8000) != 0) {
540 value |= ~UINT64_C(0) << 16;
541 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100542 break;
543 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000544 value &= kWordMask;
545 if ((value & 0x80000000) != 0) {
546 value |= ~UINT64_C(0) << 32;
547 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100548 break;
549 case UXTX:
550 case SXTX:
551 break;
552 default:
553 VIXL_UNREACHABLE();
554 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000555 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100556}
557
558
559void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
560 AssertSupportedFPCR();
561
562 // TODO: This assumes that the C++ implementation handles comparisons in the
563 // way that we expect (as per AssertSupportedFPCR()).
564 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100565 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100566 ReadNzcv().SetRawValue(FPUnorderedFlag);
567 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
568 (trap == EnableTrap)) {
569 process_exception = true;
570 }
571 } else if (val0 < val1) {
572 ReadNzcv().SetRawValue(FPLessThanFlag);
573 } else if (val0 > val1) {
574 ReadNzcv().SetRawValue(FPGreaterThanFlag);
575 } else if (val0 == val1) {
576 ReadNzcv().SetRawValue(FPEqualFlag);
577 } else {
578 VIXL_UNREACHABLE();
579 }
580 LogSystemRegister(NZCV);
581 if (process_exception) FPProcessException();
582}
583
584
Alexandre Rames868bfc42016-07-19 17:10:48 +0100585uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
586 VIXL_ASSERT(mem_op.IsValid());
587 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
588 if (mem_op.IsImmediateOffset()) {
589 return base + mem_op.GetOffset();
590 } else {
591 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
592 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100593 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100594 if (mem_op.GetShift() != NO_SHIFT) {
595 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
596 }
597 if (mem_op.GetExtend() != NO_EXTEND) {
598 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
599 }
600 return static_cast<uint64_t>(base + offset);
601 }
602}
603
604
Alexandre Ramesd3832962016-07-04 15:03:43 +0100605Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
606 unsigned reg_size, unsigned lane_size) {
607 VIXL_ASSERT(reg_size >= lane_size);
608
609 uint32_t format = 0;
610 if (reg_size != lane_size) {
611 switch (reg_size) {
612 default:
613 VIXL_UNREACHABLE();
614 break;
615 case kQRegSizeInBytes:
616 format = kPrintRegAsQVector;
617 break;
618 case kDRegSizeInBytes:
619 format = kPrintRegAsDVector;
620 break;
621 }
622 }
623
624 switch (lane_size) {
625 default:
626 VIXL_UNREACHABLE();
627 break;
628 case kQRegSizeInBytes:
629 format |= kPrintReg1Q;
630 break;
631 case kDRegSizeInBytes:
632 format |= kPrintReg1D;
633 break;
634 case kSRegSizeInBytes:
635 format |= kPrintReg1S;
636 break;
637 case kHRegSizeInBytes:
638 format |= kPrintReg1H;
639 break;
640 case kBRegSizeInBytes:
641 format |= kPrintReg1B;
642 break;
643 }
644 // These sizes would be duplicate case labels.
645 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
646 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
647 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
648 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
649
650 return static_cast<PrintRegisterFormat>(format);
651}
652
653
654Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
655 VectorFormat vform) {
656 switch (vform) {
657 default:
658 VIXL_UNREACHABLE();
659 return kPrintReg16B;
660 case kFormat16B:
661 return kPrintReg16B;
662 case kFormat8B:
663 return kPrintReg8B;
664 case kFormat8H:
665 return kPrintReg8H;
666 case kFormat4H:
667 return kPrintReg4H;
668 case kFormat4S:
669 return kPrintReg4S;
670 case kFormat2S:
671 return kPrintReg2S;
672 case kFormat2D:
673 return kPrintReg2D;
674 case kFormat1D:
675 return kPrintReg1D;
676
677 case kFormatB:
678 return kPrintReg1B;
679 case kFormatH:
680 return kPrintReg1H;
681 case kFormatS:
682 return kPrintReg1S;
683 case kFormatD:
684 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +0100685
686 case kFormatVnB:
687 return kPrintRegLaneSizeB;
688 case kFormatVnH:
689 return kPrintRegLaneSizeH;
690 case kFormatVnS:
691 return kPrintRegLaneSizeS;
692 case kFormatVnD:
693 return kPrintRegLaneSizeD;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100694 }
695}
696
697
698Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
699 VectorFormat vform) {
700 switch (vform) {
701 default:
702 VIXL_UNREACHABLE();
703 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100704 case kFormat8H:
705 return kPrintReg8HFP;
706 case kFormat4H:
707 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100708 case kFormat4S:
709 return kPrintReg4SFP;
710 case kFormat2S:
711 return kPrintReg2SFP;
712 case kFormat2D:
713 return kPrintReg2DFP;
714 case kFormat1D:
715 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100716 case kFormatH:
717 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100718 case kFormatS:
719 return kPrintReg1SFP;
720 case kFormatD:
721 return kPrintReg1DFP;
722 }
723}
724
725
726void Simulator::PrintWrittenRegisters() {
727 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
728 if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
729 }
730}
731
732
733void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100734 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100735 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
736 // At this point there is no type information, so print as a raw 1Q.
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100737 if (vregisters_[i].WrittenSinceLastLog()) {
738 // Z registers are initialised in the constructor before the user can
739 // configure the CPU features, so we must also check for SVE here.
740 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
741 PrintZRegister(i);
742 } else {
743 PrintVRegister(i, kPrintReg1Q);
744 }
745 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100746 }
747}
748
749
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100750void Simulator::PrintWrittenPRegisters() {
751 // P registers are initialised in the constructor before the user can
752 // configure the CPU features, so we must check for SVE here.
753 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
754 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
755 if (pregisters_[i].WrittenSinceLastLog()) {
756 PrintPRegister(i);
757 }
758 }
759}
760
761
Alexandre Ramesd3832962016-07-04 15:03:43 +0100762void Simulator::PrintSystemRegisters() {
763 PrintSystemRegister(NZCV);
764 PrintSystemRegister(FPCR);
765}
766
767
768void Simulator::PrintRegisters() {
769 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
770 PrintRegister(i);
771 }
772}
773
774
775void Simulator::PrintVRegisters() {
776 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
777 // At this point there is no type information, so print as a raw 1Q.
778 PrintVRegister(i, kPrintReg1Q);
779 }
780}
781
782
TatWai Chong72d2e562019-05-16 11:22:22 -0700783void Simulator::PrintZRegisters() {
784 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
785 PrintZRegister(i);
786 }
787}
788
789
Alexandre Ramesd3832962016-07-04 15:03:43 +0100790// Print a register's name and raw value.
791//
792// Only the least-significant `size_in_bytes` bytes of the register are printed,
793// but the value is aligned as if the whole register had been printed.
794//
795// For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
796// -- the default -- so that the whole register is printed. Other values of
797// size_in_bytes are intended for use when the register hasn't actually been
798// updated (such as in PrintWrite).
799//
800// No newline is printed. This allows the caller to print more details (such as
801// a memory access annotation).
802void Simulator::PrintRegisterRawHelper(unsigned code,
803 Reg31Mode r31mode,
804 int size_in_bytes) {
805 // The template for all supported sizes.
806 // "# x{code}: 0xffeeddccbbaa9988"
807 // "# w{code}: 0xbbaa9988"
808 // "# w{code}<15:0>: 0x9988"
809 // "# w{code}<7:0>: 0x88"
810 unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
811
812 const char* name = "";
813 const char* suffix = "";
814 switch (size_in_bytes) {
815 case kXRegSizeInBytes:
816 name = XRegNameForCode(code, r31mode);
817 break;
818 case kWRegSizeInBytes:
819 name = WRegNameForCode(code, r31mode);
820 break;
821 case 2:
822 name = WRegNameForCode(code, r31mode);
823 suffix = "<15:0>";
824 padding_chars -= strlen(suffix);
825 break;
826 case 1:
827 name = WRegNameForCode(code, r31mode);
828 suffix = "<7:0>";
829 padding_chars -= strlen(suffix);
830 break;
831 default:
832 VIXL_UNREACHABLE();
833 }
834 fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
835
836 // Print leading padding spaces.
837 VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
838 for (unsigned i = 0; i < padding_chars; i++) {
839 putc(' ', stream_);
840 }
841
842 // Print the specified bits in hexadecimal format.
843 uint64_t bits = ReadRegister<uint64_t>(code, r31mode);
844 bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
845 VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
846
847 int chars = size_in_bytes * 2;
848 fprintf(stream_,
849 "%s0x%0*" PRIx64 "%s",
850 clr_reg_value,
851 chars,
852 bits,
853 clr_normal);
854}
855
856
857void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
858 registers_[code].NotifyRegisterLogged();
859
860 // Don't print writes into xzr.
861 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
862 return;
863 }
864
865 // The template for all x and w registers:
866 // "# x{code}: 0x{value}"
867 // "# w{code}: 0x{value}"
868
869 PrintRegisterRawHelper(code, r31mode);
870 fprintf(stream_, "\n");
871}
872
873
874// Print a register's name and raw value.
875//
876// The `bytes` and `lsb` arguments can be used to limit the bytes that are
877// printed. These arguments are intended for use in cases where register hasn't
878// actually been updated (such as in PrintVWrite).
879//
880// No newline is printed. This allows the caller to print more details (such as
881// a floating-point interpretation or a memory access annotation).
882void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
883 // The template for vector types:
884 // "# v{code}: 0xffeeddccbbaa99887766554433221100".
885 // An example with bytes=4 and lsb=8:
886 // "# v{code}: 0xbbaa9988 ".
887 fprintf(stream_,
TatWai Chong72d2e562019-05-16 11:22:22 -0700888 "# %s%13s: %s",
Alexandre Ramesd3832962016-07-04 15:03:43 +0100889 clr_vreg_name,
890 VRegNameForCode(code),
891 clr_vreg_value);
892
893 int msb = lsb + bytes - 1;
894 int byte = kQRegSizeInBytes - 1;
895
896 // Print leading padding spaces. (Two spaces per byte.)
897 while (byte > msb) {
898 fprintf(stream_, " ");
899 byte--;
900 }
901
902 // Print the specified part of the value, byte by byte.
903 qreg_t rawbits = ReadQRegister(code);
904 fprintf(stream_, "0x");
905 while (byte >= lsb) {
906 fprintf(stream_, "%02x", rawbits.val[byte]);
907 byte--;
908 }
909
910 // Print trailing padding spaces.
911 while (byte >= 0) {
912 fprintf(stream_, " ");
913 byte--;
914 }
915 fprintf(stream_, "%s", clr_normal);
916}
917
918
TatWai Chong72d2e562019-05-16 11:22:22 -0700919void Simulator::PrintZRegisterRawHelper(
920 unsigned code, int lane_size, int data_size, int bytes, int start_byte) {
921 VIXL_ASSERT(lane_size >= data_size);
922 // Currently only support printing of 128-bit length value and it must have
923 // 128-bit alignement.
924 VIXL_ASSERT((bytes % kQRegSizeInBytes) == 0);
925 VIXL_ASSERT((start_byte % kQRegSizeInBytes) == 0);
926
927 // The template for vector types:
928 // "# z{code}<m+127:m>: 0x33333333222222221111111100000000",
929 // where m is multiple of 128b.
930 // An example with bytes=16 starting from a bit 128:
931 // "# z{code}<255:128>: 0x77777777666666665555555544444444".
932 // A qlane from a bit zero with lane=4, data=2, and bytes=16:
933 // "# z{code}<127:0>: 0x 3333 2222 1111 0000".
934
935 std::stringstream prefix;
936 prefix << ZRegNameForCode(code) << "<"
937 << ((start_byte + bytes) * kBitsPerByte) - 1 << ":"
938 << (start_byte * kBitsPerByte) << ">";
939
940 fprintf(stream_,
941 "# %s%13s: %s0x",
942 clr_vreg_name,
943 prefix.str().c_str(),
944 clr_vreg_value);
945
946 // Print the 128-bit length of register, lane by lane.
947 for (int i = kQRegSizeInBytes / lane_size; i > 0; i--) {
948 VIXL_ASSERT((kQRegSizeInBytes % lane_size) == 0);
949 // Skip the irrelevant part of value from lane if any.
950 for (int skips = lane_size - data_size; skips > 0; skips--) {
951 fprintf(stream_, " ");
952 bytes--;
953 }
954
955 // [`first_byte`, `last_byte`] represent the interval of bytes that are
956 // printed in each lane.
957 int last_byte = start_byte + bytes - 1;
958 int first_byte = last_byte - data_size + 1;
959 // Print the specified part of the value, byte by byte.
960 int lane_idx = last_byte >> kQRegSizeInBytesLog2;
961 qreg_t rawbits = vregisters_[code].GetLane<qreg_t>(lane_idx);
962 for (int byte = last_byte; byte >= first_byte; --byte) {
963 fprintf(stream_, "%02x", rawbits.val[byte % kQRegSizeInBytes]);
964 bytes--;
965 }
966 }
967 fprintf(stream_, "%s", clr_normal);
968}
969
970
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100971void Simulator::PrintPRegisterRawHelper(unsigned code, int lsb) {
972 // There are no predicated store-predicate instructions, so we can always
973 // print the full register, but this helper prints a single run of 16 bits
974 // (from `lsb`).
975 VIXL_ASSERT(code < kNumberOfPRegisters);
976 int bits = kQRegSize / kZRegBitsPerPRegBit;
977 int msb = lsb + bits - 1;
978 VIXL_ASSERT(static_cast<unsigned>(msb) < pregisters_[code].GetSizeInBits());
979 VIXL_ASSERT((lsb % bits) == 0);
980
981 // The template for P registers:
982 // "# p{code}<m+15:m>: 0b 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 0",
983 // where m is multiple of 16.
984
985 // Each printed bit aligns with the least-significant nibble of the
986 // corresponding Z-register lane, to make predicate behaviour easy to follow.
987
988 std::stringstream prefix;
989 prefix << PRegNameForCode(code) << "<" << msb << ":" << lsb << ">";
990
991 fprintf(stream_,
992 "# %s%13s: %s0b",
993 clr_preg_name,
994 prefix.str().c_str(),
995 clr_preg_value);
996
997 // Print the 16-bit length of register, lane by lane.
998 for (int i = msb; i >= lsb; i--) {
999 fprintf(stream_, " %c", pregisters_[code].GetBit(i) ? '1' : '0');
1000 }
1001 fprintf(stream_, "%s", clr_normal);
1002}
1003
1004
Alexandre Ramesd3832962016-07-04 15:03:43 +01001005// Print each of the specified lanes of a register as a float or double value.
1006//
1007// The `lane_count` and `lslane` arguments can be used to limit the lanes that
1008// are printed. These arguments are intended for use in cases where register
1009// hasn't actually been updated (such as in PrintVWrite).
1010//
1011// No newline is printed. This allows the caller to print more details (such as
1012// a memory access annotation).
1013void Simulator::PrintVRegisterFPHelper(unsigned code,
1014 unsigned lane_size_in_bytes,
1015 int lane_count,
1016 int rightmost_lane) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01001017 VIXL_ASSERT((lane_size_in_bytes == kHRegSizeInBytes) ||
1018 (lane_size_in_bytes == kSRegSizeInBytes) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01001019 (lane_size_in_bytes == kDRegSizeInBytes));
1020
1021 unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
1022 VIXL_ASSERT(msb <= kQRegSizeInBytes);
1023
1024 // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
1025 // name is used:
Carey Williamsd8bb3572018-04-10 11:58:07 +01001026 // " (h{code}: {value})"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001027 // " (s{code}: {value})"
1028 // " (d{code}: {value})"
1029 // For vector types, "..." is used to represent one or more omitted lanes.
1030 // " (..., {value}, {value}, ...)"
Carey Williamsd8bb3572018-04-10 11:58:07 +01001031 if (lane_size_in_bytes == kHRegSizeInBytes) {
1032 // TODO: Trace tests will fail until we regenerate them.
1033 return;
1034 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001035 if ((lane_count == 1) && (rightmost_lane == 0)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01001036 const char* name;
1037 switch (lane_size_in_bytes) {
1038 case kHRegSizeInBytes:
1039 name = HRegNameForCode(code);
1040 break;
1041 case kSRegSizeInBytes:
1042 name = SRegNameForCode(code);
1043 break;
1044 case kDRegSizeInBytes:
1045 name = DRegNameForCode(code);
1046 break;
1047 default:
Pierre Langlois226fbe42018-05-14 11:29:08 +01001048 name = NULL;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001049 VIXL_UNREACHABLE();
1050 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001051 fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
1052 } else {
1053 if (msb < (kQRegSizeInBytes - 1)) {
1054 fprintf(stream_, " (..., ");
1055 } else {
1056 fprintf(stream_, " (");
1057 }
1058 }
1059
1060 // Print the list of values.
1061 const char* separator = "";
1062 int leftmost_lane = rightmost_lane + lane_count - 1;
1063 for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01001064 double value;
1065 switch (lane_size_in_bytes) {
1066 case kHRegSizeInBytes:
Jacob Bramleyca789742018-09-13 14:25:46 +01001067 value = ReadVRegister(code).GetLane<uint16_t>(lane);
Carey Williamsd8bb3572018-04-10 11:58:07 +01001068 break;
1069 case kSRegSizeInBytes:
1070 value = ReadVRegister(code).GetLane<float>(lane);
1071 break;
1072 case kDRegSizeInBytes:
1073 value = ReadVRegister(code).GetLane<double>(lane);
1074 break;
1075 default:
1076 value = 0.0;
1077 VIXL_UNREACHABLE();
1078 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001079 if (IsNaN(value)) {
Alexandre Rames6b5fe942016-07-22 17:17:23 +01001080 // The output for NaNs is implementation defined. Always print `nan`, so
1081 // that traces are coherent across different implementations.
1082 fprintf(stream_, "%s%snan%s", separator, clr_vreg_value, clr_normal);
1083 } else {
1084 fprintf(stream_,
1085 "%s%s%#g%s",
1086 separator,
1087 clr_vreg_value,
1088 value,
1089 clr_normal);
1090 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001091 separator = ", ";
1092 }
1093
1094 if (rightmost_lane > 0) {
1095 fprintf(stream_, ", ...");
1096 }
1097 fprintf(stream_, ")");
1098}
1099
1100
1101void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
1102 vregisters_[code].NotifyRegisterLogged();
1103
1104 int lane_size_log2 = format & kPrintRegLaneSizeMask;
1105
1106 int reg_size_log2;
1107 if (format & kPrintRegAsQVector) {
1108 reg_size_log2 = kQRegSizeInBytesLog2;
1109 } else if (format & kPrintRegAsDVector) {
1110 reg_size_log2 = kDRegSizeInBytesLog2;
1111 } else {
1112 // Scalar types.
1113 reg_size_log2 = lane_size_log2;
1114 }
1115
1116 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
1117 int lane_size = 1 << lane_size_log2;
1118
1119 // The template for vector types:
1120 // "# v{code}: 0x{rawbits} (..., {value}, ...)".
1121 // The template for scalar types:
1122 // "# v{code}: 0x{rawbits} ({reg}:{value})".
1123 // The values in parentheses after the bit representations are floating-point
1124 // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
1125
1126 PrintVRegisterRawHelper(code);
1127 if (format & kPrintRegAsFP) {
1128 PrintVRegisterFPHelper(code, lane_size, lane_count);
1129 }
1130
1131 fprintf(stream_, "\n");
1132}
1133
TatWai Chong72d2e562019-05-16 11:22:22 -07001134void Simulator::PrintZRegister(unsigned code,
1135 PrintRegisterFormat format,
1136 int bytes,
1137 int start_byte) {
1138 vregisters_[code].NotifyRegisterLogged();
1139 if (bytes == 0) {
1140 // If no byte size specified, print the whole length of register.
1141 bytes = GetVectorLengthInBytes();
1142 }
1143
1144 int lane_size;
1145 switch (format) {
1146 case kPrintRegLaneSizeUnknown:
1147 // If no lane size specified, set to 128-bit lane by default.
1148 lane_size = kQRegSizeInBytes;
1149 break;
1150 case kPrintRegLaneSizeB:
1151 case kPrintRegLaneSizeH:
1152 case kPrintRegLaneSizeS:
1153 case kPrintRegLaneSizeD:
1154 lane_size = GetPrintRegLaneSizeInBytes(format);
1155 break;
1156 default:
1157 lane_size = 0;
1158 VIXL_UNIMPLEMENTED();
1159 break;
1160 }
1161
1162 while (bytes > 0) {
1163 PrintZRegisterRawHelper(code,
1164 lane_size,
1165 lane_size,
1166 kQRegSizeInBytes,
1167 start_byte + bytes - kQRegSizeInBytes);
1168 bytes -= kQRegSizeInBytes;
1169 fprintf(stream_, "\n");
1170 }
1171}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001172
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001173void Simulator::PrintPRegister(unsigned code, PrintRegisterFormat format) {
1174 USE(format);
1175 pregisters_[code].NotifyRegisterLogged();
1176 // There are no predicated store-predicate instructions, so we can simply
1177 // print the full register.
1178 int bits_per_chunk = kQRegSize / kZRegBitsPerPRegBit;
1179 int bits = pregisters_[code].GetSizeInBits();
1180 for (int lsb = bits - bits_per_chunk; lsb >= 0; lsb -= bits_per_chunk) {
1181 PrintPRegisterRawHelper(code, lsb);
1182 fprintf(stream_, "\n");
1183 }
1184}
1185
Alexandre Ramesd3832962016-07-04 15:03:43 +01001186void Simulator::PrintSystemRegister(SystemRegister id) {
1187 switch (id) {
1188 case NZCV:
1189 fprintf(stream_,
1190 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1191 clr_flag_name,
1192 clr_flag_value,
1193 ReadNzcv().GetN(),
1194 ReadNzcv().GetZ(),
1195 ReadNzcv().GetC(),
1196 ReadNzcv().GetV(),
1197 clr_normal);
1198 break;
1199 case FPCR: {
1200 static const char* rmode[] = {"0b00 (Round to Nearest)",
1201 "0b01 (Round towards Plus Infinity)",
1202 "0b10 (Round towards Minus Infinity)",
1203 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001204 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001205 fprintf(stream_,
1206 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1207 clr_flag_name,
1208 clr_flag_value,
1209 ReadFpcr().GetAHP(),
1210 ReadFpcr().GetDN(),
1211 ReadFpcr().GetFZ(),
1212 rmode[ReadFpcr().GetRMode()],
1213 clr_normal);
1214 break;
1215 }
1216 default:
1217 VIXL_UNREACHABLE();
1218 }
1219}
1220
1221
1222void Simulator::PrintRead(uintptr_t address,
1223 unsigned reg_code,
1224 PrintRegisterFormat format) {
1225 registers_[reg_code].NotifyRegisterLogged();
1226
1227 USE(format);
1228
1229 // The template is "# {reg}: 0x{value} <- {address}".
1230 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
1231 fprintf(stream_,
1232 " <- %s0x%016" PRIxPTR "%s\n",
1233 clr_memory_address,
1234 address,
1235 clr_normal);
1236}
1237
1238
1239void Simulator::PrintVRead(uintptr_t address,
1240 unsigned reg_code,
1241 PrintRegisterFormat format,
1242 unsigned lane) {
1243 vregisters_[reg_code].NotifyRegisterLogged();
1244
1245 // The template is "# v{code}: 0x{rawbits} <- address".
1246 PrintVRegisterRawHelper(reg_code);
1247 if (format & kPrintRegAsFP) {
1248 PrintVRegisterFPHelper(reg_code,
1249 GetPrintRegLaneSizeInBytes(format),
1250 GetPrintRegLaneCount(format),
1251 lane);
1252 }
1253 fprintf(stream_,
1254 " <- %s0x%016" PRIxPTR "%s\n",
1255 clr_memory_address,
1256 address,
1257 clr_normal);
1258}
1259
TatWai Chong72d2e562019-05-16 11:22:22 -07001260void Simulator::PrintZRead(uintptr_t address,
1261 unsigned reg_code,
1262 PrintRegisterFormat format,
1263 unsigned data_size,
1264 int bytes,
1265 int start_byte) {
1266 vregisters_[reg_code].NotifyRegisterLogged();
1267
1268 // The templates:
1269 // "# v{code}<m:n>: 0x{rawbits} <- {address}"
1270 // An example that prints an unpredicated memory read from a particular memory
1271 // location to the specified portion of Z register.
1272 // 0x00007fff00000000: 0x11110000 0x33332222 0x55554444 0x77776666
1273 // 0x00007fff00000010: 0x99998888 0xbbbbaaaa 0xddddcccc 0xffffeeee
1274 // The corresponding output is:
1275 // Zt<255:128>: 0x77776666555544443333222211110000 <- 0x00007fff00000000
1276 // Zt<383:256>: 0xffffeeeeddddccccbbbbaaaa99998888 <- 0x00007fff00000010
1277
Jacob Bramley199339d2019-08-05 18:49:13 +01001278 if (format == kPrintRegLaneSizeUnknown) format = kPrintRegLaneSizeQ;
TatWai Chong72d2e562019-05-16 11:22:22 -07001279 int lane_size = GetPrintRegLaneSizeInBytes(format);
1280 if (data_size == 0) {
1281 // Let the full lane of value are relevent.
1282 data_size = lane_size;
1283 }
1284 if (bytes == 0) {
1285 // If no byte size specified, print the whole length of register.
1286 bytes = GetVectorLengthInBytes();
1287 }
1288
1289 const int last_byte = start_byte + bytes - 1;
1290 while (start_byte < last_byte) {
1291 PrintZRegisterRawHelper(reg_code,
1292 lane_size,
1293 data_size,
1294 kQRegSizeInBytes,
1295 start_byte);
1296 fprintf(stream_,
1297 " <- %s0x%016" PRIxPTR "%s\n",
1298 clr_memory_address,
1299 address,
1300 clr_normal);
1301 start_byte += kQRegSizeInBytes;
1302 address += kQRegSizeInBytes;
1303 }
1304}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001305
1306void Simulator::PrintWrite(uintptr_t address,
1307 unsigned reg_code,
1308 PrintRegisterFormat format) {
1309 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1310
1311 // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
1312 // and readable, the value is aligned with the values in the register trace.
1313 PrintRegisterRawHelper(reg_code,
1314 Reg31IsZeroRegister,
1315 GetPrintRegSizeInBytes(format));
1316 fprintf(stream_,
1317 " -> %s0x%016" PRIxPTR "%s\n",
1318 clr_memory_address,
1319 address,
1320 clr_normal);
1321}
1322
1323
1324void Simulator::PrintVWrite(uintptr_t address,
1325 unsigned reg_code,
1326 PrintRegisterFormat format,
1327 unsigned lane) {
1328 // The templates:
1329 // "# v{code}: 0x{rawbits} -> {address}"
1330 // "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
1331 // "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
1332 // Because this trace doesn't represent a change to the source register's
1333 // value, only the relevant part of the value is printed. To keep the trace
1334 // tidy and readable, the raw value is aligned with the other values in the
1335 // register trace.
1336 int lane_count = GetPrintRegLaneCount(format);
1337 int lane_size = GetPrintRegLaneSizeInBytes(format);
1338 int reg_size = GetPrintRegSizeInBytes(format);
1339 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1340 if (format & kPrintRegAsFP) {
1341 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1342 }
1343 fprintf(stream_,
1344 " -> %s0x%016" PRIxPTR "%s\n",
1345 clr_memory_address,
1346 address,
1347 clr_normal);
1348}
1349
TatWai Chong72d2e562019-05-16 11:22:22 -07001350void Simulator::PrintZWrite(uintptr_t address,
1351 unsigned reg_code,
1352 PrintRegisterFormat format,
1353 unsigned data_size,
1354 int bytes,
1355 int start_byte) {
1356 // The templates:
1357 // "# v{code}<m:n>: 0x{rawbits} -> {address}"
1358 // An example that prints an unpredicated memory write from the specified
1359 // portion of Z register to a particular memory location.
1360 // Zt<255:128>: 0x77776666555544443333222211110000 -> 0x00007fff00000000
1361 // Zt<383:256>: 0xffffeeeeddddccccbbbbaaaa99998888 -> 0x00007fff00000010
1362
Jacob Bramley199339d2019-08-05 18:49:13 +01001363 if (format == kPrintRegLaneSizeUnknown) format = kPrintRegLaneSizeQ;
TatWai Chong72d2e562019-05-16 11:22:22 -07001364 int lane_size = GetPrintRegLaneSizeInBytes(format);
1365 if (data_size == 0) {
1366 // If no data size was specified, print the whole of each lane.
1367 data_size = lane_size;
1368 }
1369 if (bytes == 0) {
1370 // If no byte size was specified, print the whole register.
1371 bytes = GetVectorLengthInBytes();
1372 }
1373
1374 const int last_byte = start_byte + bytes - 1;
Jacob Bramleye668b202019-08-14 17:57:34 +01001375 while (start_byte <= last_byte) {
TatWai Chong72d2e562019-05-16 11:22:22 -07001376 PrintZRegisterRawHelper(reg_code,
1377 lane_size,
1378 data_size,
1379 kQRegSizeInBytes,
1380 start_byte);
1381 fprintf(stream_,
1382 " -> %s0x%016" PRIxPTR "%s\n",
1383 clr_memory_address,
1384 address,
1385 clr_normal);
1386 start_byte += kQRegSizeInBytes;
1387 address += kQRegSizeInBytes;
1388 }
1389}
1390
Jacob Bramley199339d2019-08-05 18:49:13 +01001391void Simulator::PrintPRead(uintptr_t address, unsigned reg_code) {
1392 pregisters_[reg_code].NotifyRegisterLogged();
1393
1394 // There are no predicated load-predicate instructions, so we can always
1395 // print the full register.
1396 //
1397 // The template for P registers:
1398 // "# p{code}<m+15:m>: 0b 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 0 <- {address}",
1399 // where m is multiple of 16.
1400
1401 int bytes_per_chunk = kQRegSizeInBytes / kZRegBitsPerPRegBit;
1402 int bytes = pregisters_[reg_code].GetSizeInBytes();
1403 for (int byte = bytes - bytes_per_chunk; byte >= 0; byte -= bytes_per_chunk) {
1404 PrintPRegisterRawHelper(reg_code, byte * kBitsPerByte);
1405 fprintf(stream_,
1406 " <- %s0x%016" PRIxPTR "%s\n",
1407 clr_memory_address,
1408 address,
1409 clr_normal);
1410 address += bytes_per_chunk;
1411 }
1412}
1413
1414void Simulator::PrintPWrite(uintptr_t address, unsigned reg_code) {
1415 // There are no predicated store-predicate instructions, so we can always
1416 // print the full register.
1417 //
1418 // The template for P registers:
1419 // "# p{code}<m+15:m>: 0b 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 0 -> {address}",
1420 // where m is multiple of 16.
1421 int bytes_per_chunk = kQRegSizeInBytes / kZRegBitsPerPRegBit;
1422 int bytes = pregisters_[reg_code].GetSizeInBytes();
1423 for (int byte = bytes - bytes_per_chunk; byte >= 0; byte -= bytes_per_chunk) {
1424 PrintPRegisterRawHelper(reg_code, byte * kBitsPerByte);
1425 fprintf(stream_,
1426 " -> %s0x%016" PRIxPTR "%s\n",
1427 clr_memory_address,
1428 address,
1429 clr_normal);
1430 address += bytes_per_chunk;
1431 }
1432}
1433
Alexandre Ramesd3832962016-07-04 15:03:43 +01001434
Jacob Bramleye79723a2016-06-07 17:50:47 +01001435void Simulator::PrintTakenBranch(const Instruction* target) {
1436 fprintf(stream_,
1437 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1438 clr_branch_marker,
1439 clr_normal,
1440 reinterpret_cast<uint64_t>(target));
1441}
1442
1443
Alexandre Ramesd3832962016-07-04 15:03:43 +01001444// Visitors---------------------------------------------------------------------
1445
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001446
1447void Simulator::VisitReserved(const Instruction* instr) {
1448 // UDF is the only instruction in this group, and the Decoder is precise here.
1449 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1450
1451 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1452 reinterpret_cast<const void*>(instr),
1453 instr->GetInstructionBits());
1454 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1455}
1456
1457
Alexandre Ramesd3832962016-07-04 15:03:43 +01001458void Simulator::VisitUnimplemented(const Instruction* instr) {
1459 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1460 reinterpret_cast<const void*>(instr),
1461 instr->GetInstructionBits());
1462 VIXL_UNIMPLEMENTED();
1463}
1464
1465
1466void Simulator::VisitUnallocated(const Instruction* instr) {
1467 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1468 reinterpret_cast<const void*>(instr),
1469 instr->GetInstructionBits());
1470 VIXL_UNIMPLEMENTED();
1471}
1472
1473
1474void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1475 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1476 (instr->Mask(PCRelAddressingMask) == ADRP));
1477
1478 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1479}
1480
1481
1482void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1483 switch (instr->Mask(UnconditionalBranchMask)) {
1484 case BL:
1485 WriteLr(instr->GetNextInstruction());
1486 VIXL_FALLTHROUGH();
1487 case B:
1488 WritePc(instr->GetImmPCOffsetTarget());
1489 break;
1490 default:
1491 VIXL_UNREACHABLE();
1492 }
1493}
1494
1495
1496void Simulator::VisitConditionalBranch(const Instruction* instr) {
1497 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1498 if (ConditionPassed(instr->GetConditionBranch())) {
1499 WritePc(instr->GetImmPCOffsetTarget());
1500 }
1501}
1502
Martyn Capewellcb963f72018-10-22 15:25:28 +01001503BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1504 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1505 case BLR:
1506 case BLRAA:
1507 case BLRAB:
1508 case BLRAAZ:
1509 case BLRABZ:
1510 return BranchAndLink;
1511 case BR:
1512 case BRAA:
1513 case BRAB:
1514 case BRAAZ:
1515 case BRABZ:
1516 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1517 !PcIsInGuardedPage()) {
1518 return BranchFromUnguardedOrToIP;
1519 }
1520 return BranchFromGuardedNotToIP;
1521 }
1522 return DefaultBType;
1523}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001524
1525void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01001526 bool authenticate = false;
1527 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01001528 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01001529 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001530
1531 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1532 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01001533 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001534 VIXL_FALLTHROUGH();
1535 case BR:
1536 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01001537 break;
1538
1539 case BLRAAZ:
1540 case BLRABZ:
1541 link = true;
1542 VIXL_FALLTHROUGH();
1543 case BRAAZ:
1544 case BRABZ:
1545 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001546 break;
1547
1548 case BLRAA:
1549 case BLRAB:
1550 link = true;
1551 VIXL_FALLTHROUGH();
1552 case BRAA:
1553 case BRAB:
1554 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001555 context = ReadXRegister(instr->GetRd());
1556 break;
1557
1558 case RETAA:
1559 case RETAB:
1560 authenticate = true;
1561 addr = ReadXRegister(kLinkRegCode);
1562 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001563 break;
1564 default:
1565 VIXL_UNREACHABLE();
1566 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001567
1568 if (link) {
1569 WriteLr(instr->GetNextInstruction());
1570 }
1571
1572 if (authenticate) {
1573 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1574 addr = AuthPAC(addr, context, key, kInstructionPointer);
1575
1576 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1577 if (((addr >> error_lsb) & 0x3) != 0x0) {
1578 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1579 }
1580 }
1581
Martyn Capewellcb963f72018-10-22 15:25:28 +01001582 WritePc(Instruction::Cast(addr));
1583 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001584}
1585
1586
1587void Simulator::VisitTestBranch(const Instruction* instr) {
1588 unsigned bit_pos =
1589 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1590 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1591 bool take_branch = false;
1592 switch (instr->Mask(TestBranchMask)) {
1593 case TBZ:
1594 take_branch = bit_zero;
1595 break;
1596 case TBNZ:
1597 take_branch = !bit_zero;
1598 break;
1599 default:
1600 VIXL_UNIMPLEMENTED();
1601 }
1602 if (take_branch) {
1603 WritePc(instr->GetImmPCOffsetTarget());
1604 }
1605}
1606
1607
1608void Simulator::VisitCompareBranch(const Instruction* instr) {
1609 unsigned rt = instr->GetRt();
1610 bool take_branch = false;
1611 switch (instr->Mask(CompareBranchMask)) {
1612 case CBZ_w:
1613 take_branch = (ReadWRegister(rt) == 0);
1614 break;
1615 case CBZ_x:
1616 take_branch = (ReadXRegister(rt) == 0);
1617 break;
1618 case CBNZ_w:
1619 take_branch = (ReadWRegister(rt) != 0);
1620 break;
1621 case CBNZ_x:
1622 take_branch = (ReadXRegister(rt) != 0);
1623 break;
1624 default:
1625 VIXL_UNIMPLEMENTED();
1626 }
1627 if (take_branch) {
1628 WritePc(instr->GetImmPCOffsetTarget());
1629 }
1630}
1631
1632
1633void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1634 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1635 bool set_flags = instr->GetFlagsUpdate();
1636 int64_t new_val = 0;
1637 Instr operation = instr->Mask(AddSubOpMask);
1638
1639 switch (operation) {
1640 case ADD:
1641 case ADDS: {
1642 new_val = AddWithCarry(reg_size,
1643 set_flags,
1644 ReadRegister(reg_size,
1645 instr->GetRn(),
1646 instr->GetRnMode()),
1647 op2);
1648 break;
1649 }
1650 case SUB:
1651 case SUBS: {
1652 new_val = AddWithCarry(reg_size,
1653 set_flags,
1654 ReadRegister(reg_size,
1655 instr->GetRn(),
1656 instr->GetRnMode()),
1657 ~op2,
1658 1);
1659 break;
1660 }
1661 default:
1662 VIXL_UNREACHABLE();
1663 }
1664
1665 WriteRegister(reg_size,
1666 instr->GetRd(),
1667 new_val,
1668 LogRegWrites,
1669 instr->GetRdMode());
1670}
1671
1672
1673void Simulator::VisitAddSubShifted(const Instruction* instr) {
1674 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1675 int64_t op2 = ShiftOperand(reg_size,
1676 ReadRegister(reg_size, instr->GetRm()),
1677 static_cast<Shift>(instr->GetShiftDP()),
1678 instr->GetImmDPShift());
1679 AddSubHelper(instr, op2);
1680}
1681
1682
1683void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1684 int64_t op2 = instr->GetImmAddSub()
1685 << ((instr->GetShiftAddSub() == 1) ? 12 : 0);
1686 AddSubHelper(instr, op2);
1687}
1688
1689
1690void Simulator::VisitAddSubExtended(const Instruction* instr) {
1691 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1692 int64_t op2 = ExtendValue(reg_size,
1693 ReadRegister(reg_size, instr->GetRm()),
1694 static_cast<Extend>(instr->GetExtendMode()),
1695 instr->GetImmExtendShift());
1696 AddSubHelper(instr, op2);
1697}
1698
1699
1700void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1701 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1702 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1703 int64_t new_val;
1704
1705 if ((instr->Mask(AddSubOpMask) == SUB) ||
1706 (instr->Mask(AddSubOpMask) == SUBS)) {
1707 op2 = ~op2;
1708 }
1709
1710 new_val = AddWithCarry(reg_size,
1711 instr->GetFlagsUpdate(),
1712 ReadRegister(reg_size, instr->GetRn()),
1713 op2,
1714 ReadC());
1715
1716 WriteRegister(reg_size, instr->GetRd(), new_val);
1717}
1718
1719
Alexander Gilday2487f142018-11-05 13:07:27 +00001720void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1721 switch (instr->Mask(RotateRightIntoFlagsMask)) {
1722 case RMIF: {
1723 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1724 unsigned shift = instr->GetImmRMIFRotation();
1725 unsigned mask = instr->GetNzcv();
1726 uint64_t rotated = RotateRight(value, shift, kXRegSize);
1727
1728 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1729 break;
1730 }
1731 }
1732}
1733
1734
1735void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1736 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1737 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1738
1739 unsigned sign_bit = (value >> msb) & 1;
1740 unsigned overflow_bit = (value >> (msb + 1)) & 1;
1741 ReadNzcv().SetN(sign_bit);
1742 ReadNzcv().SetZ((value << (31 - msb)) == 0);
1743 ReadNzcv().SetV(sign_bit ^ overflow_bit);
1744}
1745
1746
Alexandre Ramesd3832962016-07-04 15:03:43 +01001747void Simulator::VisitLogicalShifted(const Instruction* instr) {
1748 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1749 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1750 unsigned shift_amount = instr->GetImmDPShift();
1751 int64_t op2 = ShiftOperand(reg_size,
1752 ReadRegister(reg_size, instr->GetRm()),
1753 shift_type,
1754 shift_amount);
1755 if (instr->Mask(NOT) == NOT) {
1756 op2 = ~op2;
1757 }
1758 LogicalHelper(instr, op2);
1759}
1760
1761
1762void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1763 LogicalHelper(instr, instr->GetImmLogical());
1764}
1765
1766
1767void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1768 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1769 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1770 int64_t result = 0;
1771 bool update_flags = false;
1772
1773 // Switch on the logical operation, stripping out the NOT bit, as it has a
1774 // different meaning for logical immediate instructions.
1775 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1776 case ANDS:
1777 update_flags = true;
1778 VIXL_FALLTHROUGH();
1779 case AND:
1780 result = op1 & op2;
1781 break;
1782 case ORR:
1783 result = op1 | op2;
1784 break;
1785 case EOR:
1786 result = op1 ^ op2;
1787 break;
1788 default:
1789 VIXL_UNIMPLEMENTED();
1790 }
1791
1792 if (update_flags) {
1793 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1794 ReadNzcv().SetZ(CalcZFlag(result));
1795 ReadNzcv().SetC(0);
1796 ReadNzcv().SetV(0);
1797 LogSystemRegister(NZCV);
1798 }
1799
1800 WriteRegister(reg_size,
1801 instr->GetRd(),
1802 result,
1803 LogRegWrites,
1804 instr->GetRdMode());
1805}
1806
1807
1808void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1809 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1810 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1811}
1812
1813
1814void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1815 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1816}
1817
1818
1819void Simulator::ConditionalCompareHelper(const Instruction* instr,
1820 int64_t op2) {
1821 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1822 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1823
1824 if (ConditionPassed(instr->GetCondition())) {
1825 // If the condition passes, set the status flags to the result of comparing
1826 // the operands.
1827 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1828 AddWithCarry(reg_size, true, op1, ~op2, 1);
1829 } else {
1830 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1831 AddWithCarry(reg_size, true, op1, op2, 0);
1832 }
1833 } else {
1834 // If the condition fails, set the status flags to the nzcv immediate.
1835 ReadNzcv().SetFlags(instr->GetNzcv());
1836 LogSystemRegister(NZCV);
1837 }
1838}
1839
1840
1841void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1842 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1843 LoadStoreHelper(instr, offset, Offset);
1844}
1845
1846
1847void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1848 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1849}
1850
1851
1852void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1853 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1854}
1855
1856
1857void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1858 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1859}
1860
1861
Alexander Gilday311edf22018-10-29 13:41:41 +00001862template <typename T1, typename T2>
1863void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1864 unsigned rt = instr->GetRt();
1865 unsigned rn = instr->GetRn();
1866
1867 unsigned element_size = sizeof(T2);
1868 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1869 int offset = instr->GetImmLS();
1870 address += offset;
1871
1872 // Verify that the address is available to the host.
1873 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1874
1875 // Check the alignment of `address`.
1876 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1877 VIXL_ALIGNMENT_EXCEPTION();
1878 }
1879
1880 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
1881
1882 // Approximate load-acquire by issuing a full barrier after the load.
1883 __sync_synchronize();
1884
1885 LogRead(address, rt, GetPrintRegisterFormat(element_size));
1886}
1887
1888
1889template <typename T>
1890void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
1891 unsigned rt = instr->GetRt();
1892 unsigned rn = instr->GetRn();
1893
1894 unsigned element_size = sizeof(T);
1895 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1896 int offset = instr->GetImmLS();
1897 address += offset;
1898
1899 // Verify that the address is available to the host.
1900 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1901
1902 // Check the alignment of `address`.
1903 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1904 VIXL_ALIGNMENT_EXCEPTION();
1905 }
1906
1907 // Approximate store-release by issuing a full barrier after the load.
1908 __sync_synchronize();
1909
1910 Memory::Write<T>(address, ReadRegister<T>(rt));
1911
1912 LogWrite(address, rt, GetPrintRegisterFormat(element_size));
1913}
1914
1915
1916void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
1917 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
1918 case LDAPURB:
1919 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
1920 break;
1921 case LDAPURH:
1922 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
1923 break;
1924 case LDAPUR_w:
1925 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
1926 break;
1927 case LDAPUR_x:
1928 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
1929 break;
1930 case LDAPURSB_w:
1931 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
1932 break;
1933 case LDAPURSB_x:
1934 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
1935 break;
1936 case LDAPURSH_w:
1937 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
1938 break;
1939 case LDAPURSH_x:
1940 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
1941 break;
1942 case LDAPURSW:
1943 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
1944 break;
1945 case STLURB:
1946 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
1947 break;
1948 case STLURH:
1949 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
1950 break;
1951 case STLUR_w:
1952 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
1953 break;
1954 case STLUR_x:
1955 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
1956 break;
1957 }
1958}
1959
1960
Alexander Gilday75605592018-11-01 09:30:29 +00001961void Simulator::VisitLoadStorePAC(const Instruction* instr) {
1962 unsigned dst = instr->GetRt();
1963 unsigned addr_reg = instr->GetRn();
1964
1965 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
1966
1967 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
1968 address = AuthPAC(address, 0, key, kDataPointer);
1969
1970 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
1971 if (((address >> error_lsb) & 0x3) != 0x0) {
1972 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1973 }
1974
1975
1976 if ((addr_reg == 31) && ((address % 16) != 0)) {
1977 // When the base register is SP the stack pointer is required to be
1978 // quadword aligned prior to the address calculation and write-backs.
1979 // Misalignment will cause a stack alignment fault.
1980 VIXL_ALIGNMENT_EXCEPTION();
1981 }
1982
1983 int64_t offset = instr->GetImmLSPAC();
1984 address += offset;
1985
1986 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
1987 // Pre-index mode.
1988 VIXL_ASSERT(offset != 0);
1989 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
1990 }
1991
1992 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
1993
1994 // Verify that the calculated address is available to the host.
1995 VIXL_ASSERT(address == addr_ptr);
1996
1997 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
1998 unsigned access_size = 1 << 3;
1999 LogRead(addr_ptr, dst, GetPrintRegisterFormatForSize(access_size));
2000}
2001
2002
Alexandre Ramesd3832962016-07-04 15:03:43 +01002003void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
2004 Extend ext = static_cast<Extend>(instr->GetExtendMode());
2005 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
2006 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
2007
2008 int64_t offset =
2009 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
2010 LoadStoreHelper(instr, offset, Offset);
2011}
2012
2013
2014void Simulator::LoadStoreHelper(const Instruction* instr,
2015 int64_t offset,
2016 AddrMode addrmode) {
2017 unsigned srcdst = instr->GetRt();
2018 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2019
2020 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
2021 switch (op) {
2022 case LDRB_w:
2023 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
2024 break;
2025 case LDRH_w:
2026 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
2027 break;
2028 case LDR_w:
2029 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
2030 break;
2031 case LDR_x:
2032 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
2033 break;
2034 case LDRSB_w:
2035 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
2036 break;
2037 case LDRSH_w:
2038 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
2039 break;
2040 case LDRSB_x:
2041 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
2042 break;
2043 case LDRSH_x:
2044 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
2045 break;
2046 case LDRSW_x:
2047 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
2048 break;
2049 case LDR_b:
2050 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
2051 break;
2052 case LDR_h:
2053 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
2054 break;
2055 case LDR_s:
2056 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
2057 break;
2058 case LDR_d:
2059 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
2060 break;
2061 case LDR_q:
2062 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
2063 break;
2064
2065 case STRB_w:
2066 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
2067 break;
2068 case STRH_w:
2069 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
2070 break;
2071 case STR_w:
2072 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
2073 break;
2074 case STR_x:
2075 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
2076 break;
2077 case STR_b:
2078 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
2079 break;
2080 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01002081 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002082 break;
2083 case STR_s:
2084 Memory::Write<float>(address, ReadSRegister(srcdst));
2085 break;
2086 case STR_d:
2087 Memory::Write<double>(address, ReadDRegister(srcdst));
2088 break;
2089 case STR_q:
2090 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
2091 break;
2092
2093 // Ignore prfm hint instructions.
2094 case PRFM:
2095 break;
2096
2097 default:
2098 VIXL_UNIMPLEMENTED();
2099 }
2100
2101 unsigned access_size = 1 << instr->GetSizeLS();
2102 if (instr->IsLoad()) {
2103 if ((op == LDR_s) || (op == LDR_d)) {
2104 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
2105 } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
2106 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2107 } else {
2108 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2109 }
2110 } else if (instr->IsStore()) {
2111 if ((op == STR_s) || (op == STR_d)) {
2112 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
2113 } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
2114 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2115 } else {
2116 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2117 }
2118 } else {
2119 VIXL_ASSERT(op == PRFM);
2120 }
2121
2122 local_monitor_.MaybeClear();
2123}
2124
2125
2126void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
2127 LoadStorePairHelper(instr, Offset);
2128}
2129
2130
2131void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
2132 LoadStorePairHelper(instr, PreIndex);
2133}
2134
2135
2136void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
2137 LoadStorePairHelper(instr, PostIndex);
2138}
2139
2140
2141void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
2142 LoadStorePairHelper(instr, Offset);
2143}
2144
2145
2146void Simulator::LoadStorePairHelper(const Instruction* instr,
2147 AddrMode addrmode) {
2148 unsigned rt = instr->GetRt();
2149 unsigned rt2 = instr->GetRt2();
2150 int element_size = 1 << instr->GetSizeLSPair();
2151 int64_t offset = instr->GetImmLSPair() * element_size;
2152 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2153 uintptr_t address2 = address + element_size;
2154
2155 LoadStorePairOp op =
2156 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
2157
2158 // 'rt' and 'rt2' can only be aliased for stores.
2159 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2160
2161 switch (op) {
2162 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
2163 // will print a more detailed log.
2164 case LDP_w: {
2165 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2166 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
2167 break;
2168 }
2169 case LDP_s: {
2170 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2171 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
2172 break;
2173 }
2174 case LDP_x: {
2175 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2176 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
2177 break;
2178 }
2179 case LDP_d: {
2180 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2181 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
2182 break;
2183 }
2184 case LDP_q: {
2185 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2186 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
2187 break;
2188 }
2189 case LDPSW_x: {
2190 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2191 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
2192 break;
2193 }
2194 case STP_w: {
2195 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2196 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
2197 break;
2198 }
2199 case STP_s: {
2200 Memory::Write<float>(address, ReadSRegister(rt));
2201 Memory::Write<float>(address2, ReadSRegister(rt2));
2202 break;
2203 }
2204 case STP_x: {
2205 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2206 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
2207 break;
2208 }
2209 case STP_d: {
2210 Memory::Write<double>(address, ReadDRegister(rt));
2211 Memory::Write<double>(address2, ReadDRegister(rt2));
2212 break;
2213 }
2214 case STP_q: {
2215 Memory::Write<qreg_t>(address, ReadQRegister(rt));
2216 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
2217 break;
2218 }
2219 default:
2220 VIXL_UNREACHABLE();
2221 }
2222
2223 // Print a detailed trace (including the memory address) instead of the basic
2224 // register:value trace generated by set_*reg().
2225 if (instr->IsLoad()) {
2226 if ((op == LDP_s) || (op == LDP_d)) {
2227 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
2228 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
2229 } else if (op == LDP_q) {
2230 LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2231 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2232 } else {
2233 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2234 LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2235 }
2236 } else {
2237 if ((op == STP_s) || (op == STP_d)) {
2238 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
2239 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
2240 } else if (op == STP_q) {
2241 LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2242 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2243 } else {
2244 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2245 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2246 }
2247 }
2248
2249 local_monitor_.MaybeClear();
2250}
2251
2252
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002253template <typename T>
2254void Simulator::CompareAndSwapHelper(const Instruction* instr) {
2255 unsigned rs = instr->GetRs();
2256 unsigned rt = instr->GetRt();
2257 unsigned rn = instr->GetRn();
2258
2259 unsigned element_size = sizeof(T);
2260 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2261
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002262 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2263
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002264 bool is_acquire = instr->ExtractBit(22) == 1;
2265 bool is_release = instr->ExtractBit(15) == 1;
2266
2267 T comparevalue = ReadRegister<T>(rs);
2268 T newvalue = ReadRegister<T>(rt);
2269
2270 // The architecture permits that the data read clears any exclusive monitors
2271 // associated with that location, even if the compare subsequently fails.
2272 local_monitor_.Clear();
2273
2274 T data = Memory::Read<T>(address);
2275 if (is_acquire) {
2276 // Approximate load-acquire by issuing a full barrier after the load.
2277 __sync_synchronize();
2278 }
2279
2280 if (data == comparevalue) {
2281 if (is_release) {
2282 // Approximate store-release by issuing a full barrier before the store.
2283 __sync_synchronize();
2284 }
2285 Memory::Write<T>(address, newvalue);
2286 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2287 }
2288 WriteRegister<T>(rs, data);
2289 LogRead(address, rs, GetPrintRegisterFormatForSize(element_size));
2290}
2291
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002292
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002293template <typename T>
2294void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
2295 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
2296 unsigned rs = instr->GetRs();
2297 unsigned rt = instr->GetRt();
2298 unsigned rn = instr->GetRn();
2299
2300 VIXL_ASSERT((rs % 2 == 0) && (rs % 2 == 0));
2301
2302 unsigned element_size = sizeof(T);
2303 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002304
2305 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
2306
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002307 uint64_t address2 = address + element_size;
2308
2309 bool is_acquire = instr->ExtractBit(22) == 1;
2310 bool is_release = instr->ExtractBit(15) == 1;
2311
2312 T comparevalue_high = ReadRegister<T>(rs + 1);
2313 T comparevalue_low = ReadRegister<T>(rs);
2314 T newvalue_high = ReadRegister<T>(rt + 1);
2315 T newvalue_low = ReadRegister<T>(rt);
2316
2317 // The architecture permits that the data read clears any exclusive monitors
2318 // associated with that location, even if the compare subsequently fails.
2319 local_monitor_.Clear();
2320
2321 T data_high = Memory::Read<T>(address);
2322 T data_low = Memory::Read<T>(address2);
2323
2324 if (is_acquire) {
2325 // Approximate load-acquire by issuing a full barrier after the load.
2326 __sync_synchronize();
2327 }
2328
2329 bool same =
2330 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2331 if (same) {
2332 if (is_release) {
2333 // Approximate store-release by issuing a full barrier before the store.
2334 __sync_synchronize();
2335 }
2336
2337 Memory::Write<T>(address, newvalue_high);
2338 Memory::Write<T>(address2, newvalue_low);
2339 }
2340
2341 WriteRegister<T>(rs + 1, data_high);
2342 WriteRegister<T>(rs, data_low);
2343
2344 LogRead(address, rs + 1, GetPrintRegisterFormatForSize(element_size));
2345 LogRead(address2, rs, GetPrintRegisterFormatForSize(element_size));
2346
2347 if (same) {
2348 LogWrite(address, rt + 1, GetPrintRegisterFormatForSize(element_size));
2349 LogWrite(address2, rt, GetPrintRegisterFormatForSize(element_size));
2350 }
2351}
2352
Alexandre Ramesd3832962016-07-04 15:03:43 +01002353
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002354void Simulator::PrintExclusiveAccessWarning() {
2355 if (print_exclusive_access_warning_) {
2356 fprintf(stderr,
2357 "%sWARNING:%s VIXL simulator support for "
2358 "load-/store-/clear-exclusive "
2359 "instructions is limited. Refer to the README for details.%s\n",
2360 clr_warning,
2361 clr_warning_message,
2362 clr_normal);
2363 print_exclusive_access_warning_ = false;
2364 }
2365}
2366
2367
Alexandre Ramesd3832962016-07-04 15:03:43 +01002368void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002369 LoadStoreExclusive op =
2370 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
2371
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002372 switch (op) {
2373 case CAS_w:
2374 case CASA_w:
2375 case CASL_w:
2376 case CASAL_w:
2377 CompareAndSwapHelper<uint32_t>(instr);
2378 break;
2379 case CAS_x:
2380 case CASA_x:
2381 case CASL_x:
2382 case CASAL_x:
2383 CompareAndSwapHelper<uint64_t>(instr);
2384 break;
2385 case CASB:
2386 case CASAB:
2387 case CASLB:
2388 case CASALB:
2389 CompareAndSwapHelper<uint8_t>(instr);
2390 break;
2391 case CASH:
2392 case CASAH:
2393 case CASLH:
2394 case CASALH:
2395 CompareAndSwapHelper<uint16_t>(instr);
2396 break;
2397 case CASP_w:
2398 case CASPA_w:
2399 case CASPL_w:
2400 case CASPAL_w:
2401 CompareAndSwapPairHelper<uint32_t>(instr);
2402 break;
2403 case CASP_x:
2404 case CASPA_x:
2405 case CASPL_x:
2406 case CASPAL_x:
2407 CompareAndSwapPairHelper<uint64_t>(instr);
2408 break;
2409 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002410 PrintExclusiveAccessWarning();
2411
2412 unsigned rs = instr->GetRs();
2413 unsigned rt = instr->GetRt();
2414 unsigned rt2 = instr->GetRt2();
2415 unsigned rn = instr->GetRn();
2416
2417 bool is_exclusive = !instr->GetLdStXNotExclusive();
2418 bool is_acquire_release =
2419 !is_exclusive || instr->GetLdStXAcquireRelease();
2420 bool is_load = instr->GetLdStXLoad();
2421 bool is_pair = instr->GetLdStXPair();
2422
2423 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2424 unsigned access_size = is_pair ? element_size * 2 : element_size;
2425 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2426
2427 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2428
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002429 if (is_load) {
2430 if (is_exclusive) {
2431 local_monitor_.MarkExclusive(address, access_size);
2432 } else {
2433 // Any non-exclusive load can clear the local monitor as a side
2434 // effect. We don't need to do this, but it is useful to stress the
2435 // simulated code.
2436 local_monitor_.Clear();
2437 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002438
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002439 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2440 // We will print a more detailed log.
2441 switch (op) {
2442 case LDXRB_w:
2443 case LDAXRB_w:
2444 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002445 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002446 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
2447 break;
2448 case LDXRH_w:
2449 case LDAXRH_w:
2450 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002451 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002452 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
2453 break;
2454 case LDXR_w:
2455 case LDAXR_w:
2456 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002457 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002458 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2459 break;
2460 case LDXR_x:
2461 case LDAXR_x:
2462 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002463 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002464 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2465 break;
2466 case LDXP_w:
2467 case LDAXP_w:
2468 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2469 WriteWRegister(rt2,
2470 Memory::Read<uint32_t>(address + element_size),
2471 NoRegLog);
2472 break;
2473 case LDXP_x:
2474 case LDAXP_x:
2475 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2476 WriteXRegister(rt2,
2477 Memory::Read<uint64_t>(address + element_size),
2478 NoRegLog);
2479 break;
2480 default:
2481 VIXL_UNREACHABLE();
2482 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002483
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002484 if (is_acquire_release) {
2485 // Approximate load-acquire by issuing a full barrier after the load.
2486 __sync_synchronize();
2487 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002488
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002489 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2490 if (is_pair) {
2491 LogRead(address + element_size,
2492 rt2,
2493 GetPrintRegisterFormatForSize(element_size));
2494 }
2495 } else {
2496 if (is_acquire_release) {
2497 // Approximate store-release by issuing a full barrier before the
2498 // store.
2499 __sync_synchronize();
2500 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002501
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002502 bool do_store = true;
2503 if (is_exclusive) {
2504 do_store = local_monitor_.IsExclusive(address, access_size) &&
2505 global_monitor_.IsExclusive(address, access_size);
2506 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002507
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002508 // - All exclusive stores explicitly clear the local monitor.
2509 local_monitor_.Clear();
2510 } else {
2511 // - Any other store can clear the local monitor as a side effect.
2512 local_monitor_.MaybeClear();
2513 }
2514
2515 if (do_store) {
2516 switch (op) {
2517 case STXRB_w:
2518 case STLXRB_w:
2519 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002520 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002521 Memory::Write<uint8_t>(address, ReadWRegister(rt));
2522 break;
2523 case STXRH_w:
2524 case STLXRH_w:
2525 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002526 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002527 Memory::Write<uint16_t>(address, ReadWRegister(rt));
2528 break;
2529 case STXR_w:
2530 case STLXR_w:
2531 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002532 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002533 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2534 break;
2535 case STXR_x:
2536 case STLXR_x:
2537 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002538 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002539 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2540 break;
2541 case STXP_w:
2542 case STLXP_w:
2543 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2544 Memory::Write<uint32_t>(address + element_size,
2545 ReadWRegister(rt2));
2546 break;
2547 case STXP_x:
2548 case STLXP_x:
2549 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2550 Memory::Write<uint64_t>(address + element_size,
2551 ReadXRegister(rt2));
2552 break;
2553 default:
2554 VIXL_UNREACHABLE();
2555 }
2556
2557 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2558 if (is_pair) {
2559 LogWrite(address + element_size,
2560 rt2,
2561 GetPrintRegisterFormatForSize(element_size));
2562 }
2563 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002564 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002565 }
2566}
2567
Jacob Bramleyca789742018-09-13 14:25:46 +01002568template <typename T>
2569void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2570 unsigned rs = instr->GetRs();
2571 unsigned rt = instr->GetRt();
2572 unsigned rn = instr->GetRn();
2573
2574 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2575 bool is_release = instr->ExtractBit(22) == 1;
2576
2577 unsigned element_size = sizeof(T);
2578 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2579
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002580 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002581
2582 T value = ReadRegister<T>(rs);
2583
2584 T data = Memory::Read<T>(address);
2585
2586 if (is_acquire) {
2587 // Approximate load-acquire by issuing a full barrier after the load.
2588 __sync_synchronize();
2589 }
2590
2591 T result = 0;
2592 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2593 case LDADDOp:
2594 result = data + value;
2595 break;
2596 case LDCLROp:
2597 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2598 result = data & ~value;
2599 break;
2600 case LDEOROp:
2601 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2602 result = data ^ value;
2603 break;
2604 case LDSETOp:
2605 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2606 result = data | value;
2607 break;
2608
2609 // Signed/Unsigned difference is done via the templated type T.
2610 case LDSMAXOp:
2611 case LDUMAXOp:
2612 result = (data > value) ? data : value;
2613 break;
2614 case LDSMINOp:
2615 case LDUMINOp:
2616 result = (data > value) ? value : data;
2617 break;
2618 }
2619
2620 if (is_release) {
2621 // Approximate store-release by issuing a full barrier before the store.
2622 __sync_synchronize();
2623 }
2624
2625 Memory::Write<T>(address, result);
2626 WriteRegister<T>(rt, data, NoRegLog);
2627
2628 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2629 LogWrite(address, rs, GetPrintRegisterFormatForSize(element_size));
2630}
2631
2632template <typename T>
2633void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2634 unsigned rs = instr->GetRs();
2635 unsigned rt = instr->GetRt();
2636 unsigned rn = instr->GetRn();
2637
2638 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2639 bool is_release = instr->ExtractBit(22) == 1;
2640
2641 unsigned element_size = sizeof(T);
2642 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2643
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002644 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002645
2646 T data = Memory::Read<T>(address);
2647 if (is_acquire) {
2648 // Approximate load-acquire by issuing a full barrier after the load.
2649 __sync_synchronize();
2650 }
2651
2652 if (is_release) {
2653 // Approximate store-release by issuing a full barrier before the store.
2654 __sync_synchronize();
2655 }
2656 Memory::Write<T>(address, ReadRegister<T>(rs));
2657
2658 WriteRegister<T>(rt, data);
2659
2660 LogRead(address, rt, GetPrintRegisterFormat(element_size));
2661 LogWrite(address, rs, GetPrintRegisterFormat(element_size));
2662}
2663
2664template <typename T>
2665void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2666 unsigned rt = instr->GetRt();
2667 unsigned rn = instr->GetRn();
2668
2669 unsigned element_size = sizeof(T);
2670 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2671
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002672 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2673
Jacob Bramleyca789742018-09-13 14:25:46 +01002674 WriteRegister<T>(rt, Memory::Read<T>(address));
2675
2676 // Approximate load-acquire by issuing a full barrier after the load.
2677 __sync_synchronize();
2678
2679 LogRead(address, rt, GetPrintRegisterFormat(element_size));
2680}
2681
2682#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2683 V(LDADD) \
2684 V(LDCLR) \
2685 V(LDEOR) \
2686 V(LDSET) \
2687 V(LDUMAX) \
2688 V(LDUMIN)
2689
2690#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2691 V(LDSMAX) \
2692 V(LDSMIN)
2693
2694void Simulator::VisitAtomicMemory(const Instruction* instr) {
2695 switch (instr->Mask(AtomicMemoryMask)) {
2696// clang-format off
2697#define SIM_FUNC_B(A) \
2698 case A##B: \
2699 case A##AB: \
2700 case A##LB: \
2701 case A##ALB:
2702#define SIM_FUNC_H(A) \
2703 case A##H: \
2704 case A##AH: \
2705 case A##LH: \
2706 case A##ALH:
2707#define SIM_FUNC_w(A) \
2708 case A##_w: \
2709 case A##A_w: \
2710 case A##L_w: \
2711 case A##AL_w:
2712#define SIM_FUNC_x(A) \
2713 case A##_x: \
2714 case A##A_x: \
2715 case A##L_x: \
2716 case A##AL_x:
2717
2718 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2719 AtomicMemorySimpleHelper<uint8_t>(instr);
2720 break;
2721 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2722 AtomicMemorySimpleHelper<int8_t>(instr);
2723 break;
2724 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2725 AtomicMemorySimpleHelper<uint16_t>(instr);
2726 break;
2727 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2728 AtomicMemorySimpleHelper<int16_t>(instr);
2729 break;
2730 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2731 AtomicMemorySimpleHelper<uint32_t>(instr);
2732 break;
2733 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2734 AtomicMemorySimpleHelper<int32_t>(instr);
2735 break;
2736 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2737 AtomicMemorySimpleHelper<uint64_t>(instr);
2738 break;
2739 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2740 AtomicMemorySimpleHelper<int64_t>(instr);
2741 break;
2742 // clang-format on
2743
2744 case SWPB:
2745 case SWPAB:
2746 case SWPLB:
2747 case SWPALB:
2748 AtomicMemorySwapHelper<uint8_t>(instr);
2749 break;
2750 case SWPH:
2751 case SWPAH:
2752 case SWPLH:
2753 case SWPALH:
2754 AtomicMemorySwapHelper<uint16_t>(instr);
2755 break;
2756 case SWP_w:
2757 case SWPA_w:
2758 case SWPL_w:
2759 case SWPAL_w:
2760 AtomicMemorySwapHelper<uint32_t>(instr);
2761 break;
2762 case SWP_x:
2763 case SWPA_x:
2764 case SWPL_x:
2765 case SWPAL_x:
2766 AtomicMemorySwapHelper<uint64_t>(instr);
2767 break;
2768 case LDAPRB:
2769 LoadAcquireRCpcHelper<uint8_t>(instr);
2770 break;
2771 case LDAPRH:
2772 LoadAcquireRCpcHelper<uint16_t>(instr);
2773 break;
2774 case LDAPR_w:
2775 LoadAcquireRCpcHelper<uint32_t>(instr);
2776 break;
2777 case LDAPR_x:
2778 LoadAcquireRCpcHelper<uint64_t>(instr);
2779 break;
2780 }
2781}
2782
Alexandre Ramesd3832962016-07-04 15:03:43 +01002783
2784void Simulator::VisitLoadLiteral(const Instruction* instr) {
2785 unsigned rt = instr->GetRt();
2786 uint64_t address = instr->GetLiteralAddress<uint64_t>();
2787
2788 // Verify that the calculated address is available to the host.
2789 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2790
2791 switch (instr->Mask(LoadLiteralMask)) {
2792 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
2793 // print a more detailed log.
2794 case LDR_w_lit:
2795 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2796 LogRead(address, rt, kPrintWReg);
2797 break;
2798 case LDR_x_lit:
2799 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2800 LogRead(address, rt, kPrintXReg);
2801 break;
2802 case LDR_s_lit:
2803 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2804 LogVRead(address, rt, kPrintSReg);
2805 break;
2806 case LDR_d_lit:
2807 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2808 LogVRead(address, rt, kPrintDReg);
2809 break;
2810 case LDR_q_lit:
2811 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2812 LogVRead(address, rt, kPrintReg1Q);
2813 break;
2814 case LDRSW_x_lit:
2815 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2816 LogRead(address, rt, kPrintWReg);
2817 break;
2818
2819 // Ignore prfm hint instructions.
2820 case PRFM_lit:
2821 break;
2822
2823 default:
2824 VIXL_UNREACHABLE();
2825 }
2826
2827 local_monitor_.MaybeClear();
2828}
2829
2830
2831uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
2832 int64_t offset,
2833 AddrMode addrmode) {
2834 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2835
2836 if ((addr_reg == 31) && ((address % 16) != 0)) {
2837 // When the base register is SP the stack pointer is required to be
2838 // quadword aligned prior to the address calculation and write-backs.
2839 // Misalignment will cause a stack alignment fault.
2840 VIXL_ALIGNMENT_EXCEPTION();
2841 }
2842
2843 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
2844 VIXL_ASSERT(offset != 0);
2845 // Only preindex should log the register update here. For Postindex, the
2846 // update will be printed automatically by LogWrittenRegisters _after_ the
2847 // memory access itself is logged.
2848 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
2849 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
2850 }
2851
2852 if ((addrmode == Offset) || (addrmode == PreIndex)) {
2853 address += offset;
2854 }
2855
2856 // Verify that the calculated address is available to the host.
2857 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2858
2859 return static_cast<uintptr_t>(address);
2860}
2861
2862
2863void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
2864 MoveWideImmediateOp mov_op =
2865 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
2866 int64_t new_xn_val = 0;
2867
2868 bool is_64_bits = instr->GetSixtyFourBits() == 1;
2869 // Shift is limited for W operations.
2870 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
2871
2872 // Get the shifted immediate.
2873 int64_t shift = instr->GetShiftMoveWide() * 16;
2874 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
2875 << shift;
2876
2877 // Compute the new value.
2878 switch (mov_op) {
2879 case MOVN_w:
2880 case MOVN_x: {
2881 new_xn_val = ~shifted_imm16;
2882 if (!is_64_bits) new_xn_val &= kWRegMask;
2883 break;
2884 }
2885 case MOVK_w:
2886 case MOVK_x: {
2887 unsigned reg_code = instr->GetRd();
2888 int64_t prev_xn_val =
2889 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
2890 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
2891 break;
2892 }
2893 case MOVZ_w:
2894 case MOVZ_x: {
2895 new_xn_val = shifted_imm16;
2896 break;
2897 }
2898 default:
2899 VIXL_UNREACHABLE();
2900 }
2901
2902 // Update the destination register.
2903 WriteXRegister(instr->GetRd(), new_xn_val);
2904}
2905
2906
2907void Simulator::VisitConditionalSelect(const Instruction* instr) {
2908 uint64_t new_val = ReadXRegister(instr->GetRn());
2909
2910 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
2911 new_val = ReadXRegister(instr->GetRm());
2912 switch (instr->Mask(ConditionalSelectMask)) {
2913 case CSEL_w:
2914 case CSEL_x:
2915 break;
2916 case CSINC_w:
2917 case CSINC_x:
2918 new_val++;
2919 break;
2920 case CSINV_w:
2921 case CSINV_x:
2922 new_val = ~new_val;
2923 break;
2924 case CSNEG_w:
2925 case CSNEG_x:
2926 new_val = -new_val;
2927 break;
2928 default:
2929 VIXL_UNIMPLEMENTED();
2930 }
2931 }
2932 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2933 WriteRegister(reg_size, instr->GetRd(), new_val);
2934}
2935
2936
Jacob Bramleyca789742018-09-13 14:25:46 +01002937// clang-format off
2938#define PAUTH_MODES(V) \
2939 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
2940 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
2941 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
2942 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
2943 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
2944 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
2945 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
2946 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
2947// clang-format on
2948
Alexandre Ramesd3832962016-07-04 15:03:43 +01002949void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
2950 unsigned dst = instr->GetRd();
2951 unsigned src = instr->GetRn();
2952
2953 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01002954#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
2955 case PAC##SUFFIX: { \
2956 uint64_t ptr = ReadXRegister(dst); \
2957 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
2958 break; \
2959 } \
2960 case AUT##SUFFIX: { \
2961 uint64_t ptr = ReadXRegister(dst); \
2962 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
2963 break; \
2964 }
2965
2966 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
2967#undef DEFINE_PAUTH_FUNCS
2968
2969 case XPACI:
2970 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
2971 break;
2972 case XPACD:
2973 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
2974 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002975 case RBIT_w:
2976 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
2977 break;
2978 case RBIT_x:
2979 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
2980 break;
2981 case REV16_w:
2982 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
2983 break;
2984 case REV16_x:
2985 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
2986 break;
2987 case REV_w:
2988 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
2989 break;
2990 case REV32_x:
2991 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
2992 break;
2993 case REV_x:
2994 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
2995 break;
2996 case CLZ_w:
2997 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
2998 break;
2999 case CLZ_x:
3000 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
3001 break;
3002 case CLS_w:
3003 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
3004 break;
3005 case CLS_x:
3006 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
3007 break;
3008 default:
3009 VIXL_UNIMPLEMENTED();
3010 }
3011}
3012
3013
3014uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
3015 VIXL_ASSERT((n > 32) && (n <= 64));
3016 for (unsigned i = (n - 1); i >= 32; i--) {
3017 if (((data >> i) & 1) != 0) {
3018 uint64_t polysh32 = (uint64_t)poly << (i - 32);
3019 uint64_t mask = (UINT64_C(1) << i) - 1;
3020 data = ((data & mask) ^ polysh32);
3021 }
3022 }
3023 return data & 0xffffffff;
3024}
3025
3026
3027template <typename T>
3028uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
3029 unsigned size = sizeof(val) * 8; // Number of bits in type T.
3030 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
3031 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
3032 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
3033 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
3034}
3035
3036
3037uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
3038 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
3039 // the CRC of each 32-bit word sequentially.
3040 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
3041 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
3042}
3043
3044
3045void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
3046 Shift shift_op = NO_SHIFT;
3047 int64_t result = 0;
3048 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3049
3050 switch (instr->Mask(DataProcessing2SourceMask)) {
3051 case SDIV_w: {
3052 int32_t rn = ReadWRegister(instr->GetRn());
3053 int32_t rm = ReadWRegister(instr->GetRm());
3054 if ((rn == kWMinInt) && (rm == -1)) {
3055 result = kWMinInt;
3056 } else if (rm == 0) {
3057 // Division by zero can be trapped, but not on A-class processors.
3058 result = 0;
3059 } else {
3060 result = rn / rm;
3061 }
3062 break;
3063 }
3064 case SDIV_x: {
3065 int64_t rn = ReadXRegister(instr->GetRn());
3066 int64_t rm = ReadXRegister(instr->GetRm());
3067 if ((rn == kXMinInt) && (rm == -1)) {
3068 result = kXMinInt;
3069 } else if (rm == 0) {
3070 // Division by zero can be trapped, but not on A-class processors.
3071 result = 0;
3072 } else {
3073 result = rn / rm;
3074 }
3075 break;
3076 }
3077 case UDIV_w: {
3078 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
3079 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
3080 if (rm == 0) {
3081 // Division by zero can be trapped, but not on A-class processors.
3082 result = 0;
3083 } else {
3084 result = rn / rm;
3085 }
3086 break;
3087 }
3088 case UDIV_x: {
3089 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3090 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
3091 if (rm == 0) {
3092 // Division by zero can be trapped, but not on A-class processors.
3093 result = 0;
3094 } else {
3095 result = rn / rm;
3096 }
3097 break;
3098 }
3099 case LSLV_w:
3100 case LSLV_x:
3101 shift_op = LSL;
3102 break;
3103 case LSRV_w:
3104 case LSRV_x:
3105 shift_op = LSR;
3106 break;
3107 case ASRV_w:
3108 case ASRV_x:
3109 shift_op = ASR;
3110 break;
3111 case RORV_w:
3112 case RORV_x:
3113 shift_op = ROR;
3114 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003115 case PACGA: {
3116 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3117 uint64_t src = static_cast<uint64_t>(
3118 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
3119 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
3120 result = code & 0xffffffff00000000;
3121 break;
3122 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003123 case CRC32B: {
3124 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3125 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3126 result = Crc32Checksum(acc, val, CRC32_POLY);
3127 break;
3128 }
3129 case CRC32H: {
3130 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3131 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3132 result = Crc32Checksum(acc, val, CRC32_POLY);
3133 break;
3134 }
3135 case CRC32W: {
3136 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3137 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3138 result = Crc32Checksum(acc, val, CRC32_POLY);
3139 break;
3140 }
3141 case CRC32X: {
3142 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3143 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3144 result = Crc32Checksum(acc, val, CRC32_POLY);
3145 reg_size = kWRegSize;
3146 break;
3147 }
3148 case CRC32CB: {
3149 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3150 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3151 result = Crc32Checksum(acc, val, CRC32C_POLY);
3152 break;
3153 }
3154 case CRC32CH: {
3155 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3156 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3157 result = Crc32Checksum(acc, val, CRC32C_POLY);
3158 break;
3159 }
3160 case CRC32CW: {
3161 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3162 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3163 result = Crc32Checksum(acc, val, CRC32C_POLY);
3164 break;
3165 }
3166 case CRC32CX: {
3167 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3168 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3169 result = Crc32Checksum(acc, val, CRC32C_POLY);
3170 reg_size = kWRegSize;
3171 break;
3172 }
3173 default:
3174 VIXL_UNIMPLEMENTED();
3175 }
3176
3177 if (shift_op != NO_SHIFT) {
3178 // Shift distance encoded in the least-significant five/six bits of the
3179 // register.
3180 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
3181 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
3182 result = ShiftOperand(reg_size,
3183 ReadRegister(reg_size, instr->GetRn()),
3184 shift_op,
3185 shift);
3186 }
3187 WriteRegister(reg_size, instr->GetRd(), result);
3188}
3189
3190
Alexandre Ramesd3832962016-07-04 15:03:43 +01003191void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
3192 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3193
3194 uint64_t result = 0;
3195 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
3196 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
3197 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
3198 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
3199 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003200 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
3201 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003202 switch (instr->Mask(DataProcessing3SourceMask)) {
3203 case MADD_w:
3204 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003205 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003206 break;
3207 case MSUB_w:
3208 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003209 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003210 break;
3211 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003212 result = ReadXRegister(instr->GetRa()) +
3213 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003214 break;
3215 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003216 result = ReadXRegister(instr->GetRa()) -
3217 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003218 break;
3219 case UMADDL_x:
3220 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
3221 break;
3222 case UMSUBL_x:
3223 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
3224 break;
3225 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003226 result =
3227 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
3228 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003229 break;
3230 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003231 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
3232 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003233 break;
3234 default:
3235 VIXL_UNIMPLEMENTED();
3236 }
3237 WriteRegister(reg_size, instr->GetRd(), result);
3238}
3239
3240
3241void Simulator::VisitBitfield(const Instruction* instr) {
3242 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3243 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003244 int R = instr->GetImmR();
3245 int S = instr->GetImmS();
3246 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003247 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003248 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003249 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003250 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003251 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003252 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003253 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003254 diff += reg_size;
3255 }
3256
3257 // inzero indicates if the extracted bitfield is inserted into the
3258 // destination register value or in zero.
3259 // If extend is true, extend the sign of the extracted bitfield.
3260 bool inzero = false;
3261 bool extend = false;
3262 switch (instr->Mask(BitfieldMask)) {
3263 case BFM_x:
3264 case BFM_w:
3265 break;
3266 case SBFM_x:
3267 case SBFM_w:
3268 inzero = true;
3269 extend = true;
3270 break;
3271 case UBFM_x:
3272 case UBFM_w:
3273 inzero = true;
3274 break;
3275 default:
3276 VIXL_UNIMPLEMENTED();
3277 }
3278
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003279 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
3280 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003281 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003282 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003283 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003284 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
3285 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003286
3287 // Merge sign extension, dest/zero and bitfield.
3288 result = signbits | (result & mask) | (dst & ~mask);
3289
3290 WriteRegister(reg_size, instr->GetRd(), result);
3291}
3292
3293
3294void Simulator::VisitExtract(const Instruction* instr) {
3295 unsigned lsb = instr->GetImmS();
3296 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3297 uint64_t low_res =
3298 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003299 uint64_t high_res =
3300 (lsb == 0) ? 0 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
3301 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003302 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
3303}
3304
3305
3306void Simulator::VisitFPImmediate(const Instruction* instr) {
3307 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01003308 unsigned dest = instr->GetRd();
3309 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003310 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01003311 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01003312 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003313 case FMOV_s_imm:
3314 WriteSRegister(dest, instr->GetImmFP32());
3315 break;
3316 case FMOV_d_imm:
3317 WriteDRegister(dest, instr->GetImmFP64());
3318 break;
3319 default:
3320 VIXL_UNREACHABLE();
3321 }
3322}
3323
3324
3325void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
3326 AssertSupportedFPCR();
3327
3328 unsigned dst = instr->GetRd();
3329 unsigned src = instr->GetRn();
3330
3331 FPRounding round = ReadRMode();
3332
3333 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003334 case FCVTAS_wh:
3335 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
3336 break;
3337 case FCVTAS_xh:
3338 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
3339 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003340 case FCVTAS_ws:
3341 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
3342 break;
3343 case FCVTAS_xs:
3344 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
3345 break;
3346 case FCVTAS_wd:
3347 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
3348 break;
3349 case FCVTAS_xd:
3350 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
3351 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003352 case FCVTAU_wh:
3353 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
3354 break;
3355 case FCVTAU_xh:
3356 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
3357 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003358 case FCVTAU_ws:
3359 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3360 break;
3361 case FCVTAU_xs:
3362 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3363 break;
3364 case FCVTAU_wd:
3365 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3366 break;
3367 case FCVTAU_xd:
3368 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3369 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003370 case FCVTMS_wh:
3371 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3372 break;
3373 case FCVTMS_xh:
3374 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3375 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003376 case FCVTMS_ws:
3377 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3378 break;
3379 case FCVTMS_xs:
3380 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3381 break;
3382 case FCVTMS_wd:
3383 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3384 break;
3385 case FCVTMS_xd:
3386 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3387 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003388 case FCVTMU_wh:
3389 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3390 break;
3391 case FCVTMU_xh:
3392 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3393 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003394 case FCVTMU_ws:
3395 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3396 break;
3397 case FCVTMU_xs:
3398 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3399 break;
3400 case FCVTMU_wd:
3401 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3402 break;
3403 case FCVTMU_xd:
3404 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3405 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003406 case FCVTPS_wh:
3407 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3408 break;
3409 case FCVTPS_xh:
3410 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3411 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003412 case FCVTPS_ws:
3413 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3414 break;
3415 case FCVTPS_xs:
3416 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3417 break;
3418 case FCVTPS_wd:
3419 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3420 break;
3421 case FCVTPS_xd:
3422 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3423 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003424 case FCVTPU_wh:
3425 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3426 break;
3427 case FCVTPU_xh:
3428 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3429 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003430 case FCVTPU_ws:
3431 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3432 break;
3433 case FCVTPU_xs:
3434 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3435 break;
3436 case FCVTPU_wd:
3437 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3438 break;
3439 case FCVTPU_xd:
3440 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3441 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003442 case FCVTNS_wh:
3443 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3444 break;
3445 case FCVTNS_xh:
3446 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3447 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003448 case FCVTNS_ws:
3449 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3450 break;
3451 case FCVTNS_xs:
3452 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3453 break;
3454 case FCVTNS_wd:
3455 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3456 break;
3457 case FCVTNS_xd:
3458 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3459 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003460 case FCVTNU_wh:
3461 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3462 break;
3463 case FCVTNU_xh:
3464 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3465 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003466 case FCVTNU_ws:
3467 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3468 break;
3469 case FCVTNU_xs:
3470 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3471 break;
3472 case FCVTNU_wd:
3473 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3474 break;
3475 case FCVTNU_xd:
3476 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3477 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003478 case FCVTZS_wh:
3479 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3480 break;
3481 case FCVTZS_xh:
3482 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3483 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003484 case FCVTZS_ws:
3485 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3486 break;
3487 case FCVTZS_xs:
3488 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3489 break;
3490 case FCVTZS_wd:
3491 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3492 break;
3493 case FCVTZS_xd:
3494 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3495 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003496 case FCVTZU_wh:
3497 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3498 break;
3499 case FCVTZU_xh:
3500 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3501 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003502 case FCVTZU_ws:
3503 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3504 break;
3505 case FCVTZU_xs:
3506 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3507 break;
3508 case FCVTZU_wd:
3509 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3510 break;
3511 case FCVTZU_xd:
3512 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3513 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003514 case FJCVTZS:
3515 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3516 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003517 case FMOV_hw:
3518 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3519 break;
3520 case FMOV_wh:
3521 WriteWRegister(dst, ReadHRegisterBits(src));
3522 break;
3523 case FMOV_xh:
3524 WriteXRegister(dst, ReadHRegisterBits(src));
3525 break;
3526 case FMOV_hx:
3527 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3528 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003529 case FMOV_ws:
3530 WriteWRegister(dst, ReadSRegisterBits(src));
3531 break;
3532 case FMOV_xd:
3533 WriteXRegister(dst, ReadDRegisterBits(src));
3534 break;
3535 case FMOV_sw:
3536 WriteSRegisterBits(dst, ReadWRegister(src));
3537 break;
3538 case FMOV_dx:
3539 WriteDRegisterBits(dst, ReadXRegister(src));
3540 break;
3541 case FMOV_d1_x:
3542 LogicVRegister(ReadVRegister(dst))
3543 .SetUint(kFormatD, 1, ReadXRegister(src));
3544 break;
3545 case FMOV_x_d1:
3546 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3547 break;
3548
3549 // A 32-bit input can be handled in the same way as a 64-bit input, since
3550 // the sign- or zero-extension will not affect the conversion.
3551 case SCVTF_dx:
3552 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3553 break;
3554 case SCVTF_dw:
3555 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3556 break;
3557 case UCVTF_dx:
3558 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3559 break;
3560 case UCVTF_dw: {
3561 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003562 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003563 break;
3564 }
3565 case SCVTF_sx:
3566 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3567 break;
3568 case SCVTF_sw:
3569 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3570 break;
3571 case UCVTF_sx:
3572 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3573 break;
3574 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01003575 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3576 break;
3577 }
3578 case SCVTF_hx:
3579 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3580 break;
3581 case SCVTF_hw:
3582 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3583 break;
3584 case UCVTF_hx:
3585 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3586 break;
3587 case UCVTF_hw: {
3588 WriteHRegister(dst,
3589 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003590 break;
3591 }
3592
3593 default:
3594 VIXL_UNREACHABLE();
3595 }
3596}
3597
3598
3599void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3600 AssertSupportedFPCR();
3601
3602 unsigned dst = instr->GetRd();
3603 unsigned src = instr->GetRn();
3604 int fbits = 64 - instr->GetFPScale();
3605
3606 FPRounding round = ReadRMode();
3607
3608 switch (instr->Mask(FPFixedPointConvertMask)) {
3609 // A 32-bit input can be handled in the same way as a 64-bit input, since
3610 // the sign- or zero-extension will not affect the conversion.
3611 case SCVTF_dx_fixed:
3612 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3613 break;
3614 case SCVTF_dw_fixed:
3615 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3616 break;
3617 case UCVTF_dx_fixed:
3618 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3619 break;
3620 case UCVTF_dw_fixed: {
3621 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003622 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003623 break;
3624 }
3625 case SCVTF_sx_fixed:
3626 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3627 break;
3628 case SCVTF_sw_fixed:
3629 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3630 break;
3631 case UCVTF_sx_fixed:
3632 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3633 break;
3634 case UCVTF_sw_fixed: {
3635 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003636 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3637 break;
3638 }
3639 case SCVTF_hx_fixed:
3640 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3641 break;
3642 case SCVTF_hw_fixed:
3643 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3644 break;
3645 case UCVTF_hx_fixed:
3646 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3647 break;
3648 case UCVTF_hw_fixed: {
3649 WriteHRegister(dst,
3650 UFixedToFloat16(ReadRegister<uint32_t>(src),
3651 fbits,
3652 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003653 break;
3654 }
3655 case FCVTZS_xd_fixed:
3656 WriteXRegister(dst,
3657 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3658 FPZero));
3659 break;
3660 case FCVTZS_wd_fixed:
3661 WriteWRegister(dst,
3662 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3663 FPZero));
3664 break;
3665 case FCVTZU_xd_fixed:
3666 WriteXRegister(dst,
3667 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3668 FPZero));
3669 break;
3670 case FCVTZU_wd_fixed:
3671 WriteWRegister(dst,
3672 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3673 FPZero));
3674 break;
3675 case FCVTZS_xs_fixed:
3676 WriteXRegister(dst,
3677 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3678 FPZero));
3679 break;
3680 case FCVTZS_ws_fixed:
3681 WriteWRegister(dst,
3682 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3683 FPZero));
3684 break;
3685 case FCVTZU_xs_fixed:
3686 WriteXRegister(dst,
3687 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3688 FPZero));
3689 break;
3690 case FCVTZU_ws_fixed:
3691 WriteWRegister(dst,
3692 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3693 FPZero));
3694 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003695 case FCVTZS_xh_fixed: {
3696 double output =
3697 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3698 WriteXRegister(dst, FPToInt64(output, FPZero));
3699 break;
3700 }
3701 case FCVTZS_wh_fixed: {
3702 double output =
3703 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3704 WriteWRegister(dst, FPToInt32(output, FPZero));
3705 break;
3706 }
3707 case FCVTZU_xh_fixed: {
3708 double output =
3709 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3710 WriteXRegister(dst, FPToUInt64(output, FPZero));
3711 break;
3712 }
3713 case FCVTZU_wh_fixed: {
3714 double output =
3715 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3716 WriteWRegister(dst, FPToUInt32(output, FPZero));
3717 break;
3718 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003719 default:
3720 VIXL_UNREACHABLE();
3721 }
3722}
3723
3724
3725void Simulator::VisitFPCompare(const Instruction* instr) {
3726 AssertSupportedFPCR();
3727
3728 FPTrapFlags trap = DisableTrap;
3729 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003730 case FCMPE_h:
3731 trap = EnableTrap;
3732 VIXL_FALLTHROUGH();
3733 case FCMP_h:
3734 FPCompare(ReadHRegister(instr->GetRn()),
3735 ReadHRegister(instr->GetRm()),
3736 trap);
3737 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003738 case FCMPE_s:
3739 trap = EnableTrap;
3740 VIXL_FALLTHROUGH();
3741 case FCMP_s:
3742 FPCompare(ReadSRegister(instr->GetRn()),
3743 ReadSRegister(instr->GetRm()),
3744 trap);
3745 break;
3746 case FCMPE_d:
3747 trap = EnableTrap;
3748 VIXL_FALLTHROUGH();
3749 case FCMP_d:
3750 FPCompare(ReadDRegister(instr->GetRn()),
3751 ReadDRegister(instr->GetRm()),
3752 trap);
3753 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003754 case FCMPE_h_zero:
3755 trap = EnableTrap;
3756 VIXL_FALLTHROUGH();
3757 case FCMP_h_zero:
3758 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3759 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003760 case FCMPE_s_zero:
3761 trap = EnableTrap;
3762 VIXL_FALLTHROUGH();
3763 case FCMP_s_zero:
3764 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3765 break;
3766 case FCMPE_d_zero:
3767 trap = EnableTrap;
3768 VIXL_FALLTHROUGH();
3769 case FCMP_d_zero:
3770 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
3771 break;
3772 default:
3773 VIXL_UNIMPLEMENTED();
3774 }
3775}
3776
3777
3778void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
3779 AssertSupportedFPCR();
3780
3781 FPTrapFlags trap = DisableTrap;
3782 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003783 case FCCMPE_h:
3784 trap = EnableTrap;
3785 VIXL_FALLTHROUGH();
3786 case FCCMP_h:
3787 if (ConditionPassed(instr->GetCondition())) {
3788 FPCompare(ReadHRegister(instr->GetRn()),
3789 ReadHRegister(instr->GetRm()),
3790 trap);
3791 } else {
3792 ReadNzcv().SetFlags(instr->GetNzcv());
3793 LogSystemRegister(NZCV);
3794 }
3795 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003796 case FCCMPE_s:
3797 trap = EnableTrap;
3798 VIXL_FALLTHROUGH();
3799 case FCCMP_s:
3800 if (ConditionPassed(instr->GetCondition())) {
3801 FPCompare(ReadSRegister(instr->GetRn()),
3802 ReadSRegister(instr->GetRm()),
3803 trap);
3804 } else {
3805 ReadNzcv().SetFlags(instr->GetNzcv());
3806 LogSystemRegister(NZCV);
3807 }
3808 break;
3809 case FCCMPE_d:
3810 trap = EnableTrap;
3811 VIXL_FALLTHROUGH();
3812 case FCCMP_d:
3813 if (ConditionPassed(instr->GetCondition())) {
3814 FPCompare(ReadDRegister(instr->GetRn()),
3815 ReadDRegister(instr->GetRm()),
3816 trap);
3817 } else {
3818 ReadNzcv().SetFlags(instr->GetNzcv());
3819 LogSystemRegister(NZCV);
3820 }
3821 break;
3822 default:
3823 VIXL_UNIMPLEMENTED();
3824 }
3825}
3826
3827
3828void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
3829 AssertSupportedFPCR();
3830
3831 Instr selected;
3832 if (ConditionPassed(instr->GetCondition())) {
3833 selected = instr->GetRn();
3834 } else {
3835 selected = instr->GetRm();
3836 }
3837
3838 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003839 case FCSEL_h:
3840 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
3841 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003842 case FCSEL_s:
3843 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
3844 break;
3845 case FCSEL_d:
3846 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
3847 break;
3848 default:
3849 VIXL_UNIMPLEMENTED();
3850 }
3851}
3852
3853
3854void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
3855 AssertSupportedFPCR();
3856
3857 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01003858 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01003859 switch (instr->Mask(FPTypeMask)) {
3860 default:
3861 VIXL_UNREACHABLE_OR_FALLTHROUGH();
3862 case FP64:
3863 vform = kFormatD;
3864 break;
3865 case FP32:
3866 vform = kFormatS;
3867 break;
3868 case FP16:
3869 vform = kFormatH;
3870 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003871 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003872
Alexandre Ramesd3832962016-07-04 15:03:43 +01003873 SimVRegister& rd = ReadVRegister(instr->GetRd());
3874 SimVRegister& rn = ReadVRegister(instr->GetRn());
3875 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07003876 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003877
3878 unsigned fd = instr->GetRd();
3879 unsigned fn = instr->GetRn();
3880
3881 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003882 case FMOV_h:
3883 WriteHRegister(fd, ReadHRegister(fn));
3884 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003885 case FMOV_s:
3886 WriteSRegister(fd, ReadSRegister(fn));
3887 return;
3888 case FMOV_d:
3889 WriteDRegister(fd, ReadDRegister(fn));
3890 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003891 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003892 case FABS_s:
3893 case FABS_d:
3894 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
3895 // Explicitly log the register update whilst we have type information.
3896 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3897 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003898 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003899 case FNEG_s:
3900 case FNEG_d:
3901 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
3902 // Explicitly log the register update whilst we have type information.
3903 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3904 return;
3905 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01003906 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003907 return;
3908 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01003909 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003910 return;
3911 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01003912 WriteHRegister(fd,
3913 Float16ToRawbits(
3914 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003915 return;
3916 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01003917 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003918 return;
3919 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01003920 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003921 return;
3922 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01003923 WriteHRegister(fd,
3924 Float16ToRawbits(
3925 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003926 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003927 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003928 case FSQRT_s:
3929 case FSQRT_d:
3930 fsqrt(vform, rd, rn);
3931 // Explicitly log the register update whilst we have type information.
3932 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3933 return;
TatWai Chong04471812019-03-19 14:29:00 -07003934 case FRINT32X_s:
3935 case FRINT32X_d:
3936 inexact_exception = true;
3937 frint_mode = kFrintToInt32;
3938 break; // Use FPCR rounding mode.
3939 case FRINT64X_s:
3940 case FRINT64X_d:
3941 inexact_exception = true;
3942 frint_mode = kFrintToInt64;
3943 break; // Use FPCR rounding mode.
3944 case FRINT32Z_s:
3945 case FRINT32Z_d:
3946 inexact_exception = true;
3947 frint_mode = kFrintToInt32;
3948 fpcr_rounding = FPZero;
3949 break;
3950 case FRINT64Z_s:
3951 case FRINT64Z_d:
3952 inexact_exception = true;
3953 frint_mode = kFrintToInt64;
3954 fpcr_rounding = FPZero;
3955 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003956 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003957 case FRINTI_s:
3958 case FRINTI_d:
3959 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01003960 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003961 case FRINTX_s:
3962 case FRINTX_d:
3963 inexact_exception = true;
3964 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003965 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003966 case FRINTA_s:
3967 case FRINTA_d:
3968 fpcr_rounding = FPTieAway;
3969 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003970 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003971 case FRINTM_s:
3972 case FRINTM_d:
3973 fpcr_rounding = FPNegativeInfinity;
3974 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003975 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003976 case FRINTN_s:
3977 case FRINTN_d:
3978 fpcr_rounding = FPTieEven;
3979 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003980 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003981 case FRINTP_s:
3982 case FRINTP_d:
3983 fpcr_rounding = FPPositiveInfinity;
3984 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003985 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003986 case FRINTZ_s:
3987 case FRINTZ_d:
3988 fpcr_rounding = FPZero;
3989 break;
3990 default:
3991 VIXL_UNIMPLEMENTED();
3992 }
3993
3994 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07003995 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003996 // Explicitly log the register update whilst we have type information.
3997 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3998}
3999
4000
4001void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
4002 AssertSupportedFPCR();
4003
Carey Williamsd8bb3572018-04-10 11:58:07 +01004004 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01004005 switch (instr->Mask(FPTypeMask)) {
4006 default:
4007 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4008 case FP64:
4009 vform = kFormatD;
4010 break;
4011 case FP32:
4012 vform = kFormatS;
4013 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004014 case FP16:
4015 vform = kFormatH;
4016 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004017 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004018 SimVRegister& rd = ReadVRegister(instr->GetRd());
4019 SimVRegister& rn = ReadVRegister(instr->GetRn());
4020 SimVRegister& rm = ReadVRegister(instr->GetRm());
4021
4022 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004023 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004024 case FADD_s:
4025 case FADD_d:
4026 fadd(vform, rd, rn, rm);
4027 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004028 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004029 case FSUB_s:
4030 case FSUB_d:
4031 fsub(vform, rd, rn, rm);
4032 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004033 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004034 case FMUL_s:
4035 case FMUL_d:
4036 fmul(vform, rd, rn, rm);
4037 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004038 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004039 case FNMUL_s:
4040 case FNMUL_d:
4041 fnmul(vform, rd, rn, rm);
4042 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004043 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004044 case FDIV_s:
4045 case FDIV_d:
4046 fdiv(vform, rd, rn, rm);
4047 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004048 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004049 case FMAX_s:
4050 case FMAX_d:
4051 fmax(vform, rd, rn, rm);
4052 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004053 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004054 case FMIN_s:
4055 case FMIN_d:
4056 fmin(vform, rd, rn, rm);
4057 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004058 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004059 case FMAXNM_s:
4060 case FMAXNM_d:
4061 fmaxnm(vform, rd, rn, rm);
4062 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004063 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004064 case FMINNM_s:
4065 case FMINNM_d:
4066 fminnm(vform, rd, rn, rm);
4067 break;
4068 default:
4069 VIXL_UNREACHABLE();
4070 }
4071 // Explicitly log the register update whilst we have type information.
4072 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
4073}
4074
4075
4076void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
4077 AssertSupportedFPCR();
4078
4079 unsigned fd = instr->GetRd();
4080 unsigned fn = instr->GetRn();
4081 unsigned fm = instr->GetRm();
4082 unsigned fa = instr->GetRa();
4083
4084 switch (instr->Mask(FPDataProcessing3SourceMask)) {
4085 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01004086 case FMADD_h:
4087 WriteHRegister(fd,
4088 FPMulAdd(ReadHRegister(fa),
4089 ReadHRegister(fn),
4090 ReadHRegister(fm)));
4091 break;
4092 case FMSUB_h:
4093 WriteHRegister(fd,
4094 FPMulAdd(ReadHRegister(fa),
4095 -ReadHRegister(fn),
4096 ReadHRegister(fm)));
4097 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004098 case FMADD_s:
4099 WriteSRegister(fd,
4100 FPMulAdd(ReadSRegister(fa),
4101 ReadSRegister(fn),
4102 ReadSRegister(fm)));
4103 break;
4104 case FMSUB_s:
4105 WriteSRegister(fd,
4106 FPMulAdd(ReadSRegister(fa),
4107 -ReadSRegister(fn),
4108 ReadSRegister(fm)));
4109 break;
4110 case FMADD_d:
4111 WriteDRegister(fd,
4112 FPMulAdd(ReadDRegister(fa),
4113 ReadDRegister(fn),
4114 ReadDRegister(fm)));
4115 break;
4116 case FMSUB_d:
4117 WriteDRegister(fd,
4118 FPMulAdd(ReadDRegister(fa),
4119 -ReadDRegister(fn),
4120 ReadDRegister(fm)));
4121 break;
4122 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01004123 case FNMADD_h:
4124 WriteHRegister(fd,
4125 FPMulAdd(-ReadHRegister(fa),
4126 -ReadHRegister(fn),
4127 ReadHRegister(fm)));
4128 break;
4129 case FNMSUB_h:
4130 WriteHRegister(fd,
4131 FPMulAdd(-ReadHRegister(fa),
4132 ReadHRegister(fn),
4133 ReadHRegister(fm)));
4134 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004135 case FNMADD_s:
4136 WriteSRegister(fd,
4137 FPMulAdd(-ReadSRegister(fa),
4138 -ReadSRegister(fn),
4139 ReadSRegister(fm)));
4140 break;
4141 case FNMSUB_s:
4142 WriteSRegister(fd,
4143 FPMulAdd(-ReadSRegister(fa),
4144 ReadSRegister(fn),
4145 ReadSRegister(fm)));
4146 break;
4147 case FNMADD_d:
4148 WriteDRegister(fd,
4149 FPMulAdd(-ReadDRegister(fa),
4150 -ReadDRegister(fn),
4151 ReadDRegister(fm)));
4152 break;
4153 case FNMSUB_d:
4154 WriteDRegister(fd,
4155 FPMulAdd(-ReadDRegister(fa),
4156 ReadDRegister(fn),
4157 ReadDRegister(fm)));
4158 break;
4159 default:
4160 VIXL_UNIMPLEMENTED();
4161 }
4162}
4163
4164
4165bool Simulator::FPProcessNaNs(const Instruction* instr) {
4166 unsigned fd = instr->GetRd();
4167 unsigned fn = instr->GetRn();
4168 unsigned fm = instr->GetRm();
4169 bool done = false;
4170
4171 if (instr->Mask(FP64) == FP64) {
4172 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004173 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004174 WriteDRegister(fd, result);
4175 done = true;
4176 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004177 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004178 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004179 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004180 WriteSRegister(fd, result);
4181 done = true;
4182 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004183 } else {
4184 VIXL_ASSERT(instr->Mask(FP16) == FP16);
4185 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01004186 }
4187
4188 return done;
4189}
4190
4191
4192void Simulator::SysOp_W(int op, int64_t val) {
4193 switch (op) {
4194 case IVAU:
4195 case CVAC:
4196 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01004197 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08004198 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004199 case CIVAC: {
4200 // Perform a dummy memory access to ensure that we have read access
4201 // to the specified address.
4202 volatile uint8_t y = Memory::Read<uint8_t>(val);
4203 USE(y);
4204 // TODO: Implement "case ZVA:".
4205 break;
4206 }
4207 default:
4208 VIXL_UNIMPLEMENTED();
4209 }
4210}
4211
4212
Jacob Bramleyca789742018-09-13 14:25:46 +01004213// clang-format off
4214#define PAUTH_SYSTEM_MODES(V) \
4215 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
4216 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
4217 V(AZ, 30, 0x00000000, kPACKeyIA) \
4218 V(BZ, 30, 0x00000000, kPACKeyIB) \
4219 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
4220 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
4221// clang-format on
4222
4223
Alexandre Ramesd3832962016-07-04 15:03:43 +01004224void Simulator::VisitSystem(const Instruction* instr) {
4225 // Some system instructions hijack their Op and Cp fields to represent a
4226 // range of immediates instead of indicating a different instruction. This
4227 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01004228 if (instr->GetInstructionBits() == XPACLRI) {
4229 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00004230 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
4231 switch (instr->Mask(SystemPStateMask)) {
4232 case CFINV:
4233 ReadNzcv().SetC(!ReadC());
4234 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00004235 case AXFLAG:
4236 ReadNzcv().SetN(0);
4237 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
4238 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
4239 ReadNzcv().SetV(0);
4240 break;
4241 case XAFLAG: {
4242 // Can't set the flags in place due to the logical dependencies.
4243 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
4244 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
4245 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
4246 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
4247 ReadNzcv().SetN(n);
4248 ReadNzcv().SetZ(z);
4249 ReadNzcv().SetC(c);
4250 ReadNzcv().SetV(v);
4251 break;
4252 }
Alexander Gilday2487f142018-11-05 13:07:27 +00004253 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004254 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004255 // Check BType allows PACI[AB]SP instructions.
4256 if (PcIsInGuardedPage()) {
4257 Instr i = instr->Mask(SystemPAuthMask);
4258 if ((i == PACIASP) || (i == PACIBSP)) {
4259 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004260 case BranchFromGuardedNotToIP:
4261 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
4262 // assume here to be zero. This allows execution of PACI[AB]SP when
4263 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00004264 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004265 case BranchFromUnguardedOrToIP:
4266 case BranchAndLink:
4267 break;
4268 }
4269 }
4270 }
4271
Jacob Bramleyca789742018-09-13 14:25:46 +01004272 switch (instr->Mask(SystemPAuthMask)) {
4273#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
4274 case PACI##SUFFIX: \
4275 WriteXRegister(DST, \
4276 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
4277 break; \
4278 case AUTI##SUFFIX: \
4279 WriteXRegister(DST, \
4280 AuthPAC(ReadXRegister(DST), \
4281 MOD, \
4282 KEY, \
4283 kInstructionPointer)); \
4284 break;
4285
4286 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
4287#undef DEFINE_PAUTH_FUNCS
4288 }
4289 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
4290 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004291 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
4292 switch (instr->Mask(SystemExclusiveMonitorMask)) {
4293 case CLREX: {
4294 PrintExclusiveAccessWarning();
4295 ClearLocalMonitor();
4296 break;
4297 }
4298 }
4299 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
4300 switch (instr->Mask(SystemSysRegMask)) {
4301 case MRS: {
4302 switch (instr->GetImmSystemRegister()) {
4303 case NZCV:
4304 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
4305 break;
4306 case FPCR:
4307 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
4308 break;
TatWai Chong04edf682018-12-27 16:01:02 -08004309 case RNDR:
4310 case RNDRRS: {
4311 uint64_t high = jrand48(rndr_state_);
4312 uint64_t low = jrand48(rndr_state_);
4313 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
4314 WriteXRegister(instr->GetRt(), rand_num);
4315 // Simulate successful random number generation.
4316 // TODO: Return failure occasionally as a random number cannot be
4317 // returned in a period of time.
4318 ReadNzcv().SetRawValue(NoFlag);
4319 LogSystemRegister(NZCV);
4320 break;
4321 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004322 default:
4323 VIXL_UNIMPLEMENTED();
4324 }
4325 break;
4326 }
4327 case MSR: {
4328 switch (instr->GetImmSystemRegister()) {
4329 case NZCV:
4330 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
4331 LogSystemRegister(NZCV);
4332 break;
4333 case FPCR:
4334 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
4335 LogSystemRegister(FPCR);
4336 break;
4337 default:
4338 VIXL_UNIMPLEMENTED();
4339 }
4340 break;
4341 }
4342 }
4343 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
4344 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
4345 switch (instr->GetImmHint()) {
4346 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01004347 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00004348 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004349 case BTI_jc:
4350 break;
4351 case BTI:
4352 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
4353 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
4354 }
4355 break;
4356 case BTI_c:
4357 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
4358 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
4359 }
4360 break;
4361 case BTI_j:
4362 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4363 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4364 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004365 break;
4366 default:
4367 VIXL_UNIMPLEMENTED();
4368 }
4369 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4370 __sync_synchronize();
4371 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4372 switch (instr->Mask(SystemSysMask)) {
4373 case SYS:
4374 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4375 break;
4376 default:
4377 VIXL_UNIMPLEMENTED();
4378 }
4379 } else {
4380 VIXL_UNIMPLEMENTED();
4381 }
4382}
4383
4384
4385void Simulator::VisitException(const Instruction* instr) {
4386 switch (instr->Mask(ExceptionMask)) {
4387 case HLT:
4388 switch (instr->GetImmException()) {
4389 case kUnreachableOpcode:
4390 DoUnreachable(instr);
4391 return;
4392 case kTraceOpcode:
4393 DoTrace(instr);
4394 return;
4395 case kLogOpcode:
4396 DoLog(instr);
4397 return;
4398 case kPrintfOpcode:
4399 DoPrintf(instr);
4400 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01004401 case kRuntimeCallOpcode:
4402 DoRuntimeCall(instr);
4403 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01004404 case kSetCPUFeaturesOpcode:
4405 case kEnableCPUFeaturesOpcode:
4406 case kDisableCPUFeaturesOpcode:
4407 DoConfigureCPUFeatures(instr);
4408 return;
4409 case kSaveCPUFeaturesOpcode:
4410 DoSaveCPUFeatures(instr);
4411 return;
4412 case kRestoreCPUFeaturesOpcode:
4413 DoRestoreCPUFeatures(instr);
4414 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004415 default:
4416 HostBreakpoint();
4417 return;
4418 }
4419 case BRK:
4420 HostBreakpoint();
4421 return;
4422 default:
4423 VIXL_UNIMPLEMENTED();
4424 }
4425}
4426
4427
4428void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4429 VisitUnimplemented(instr);
4430}
4431
4432
4433void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4434 VisitUnimplemented(instr);
4435}
4436
4437
4438void Simulator::VisitCryptoAES(const Instruction* instr) {
4439 VisitUnimplemented(instr);
4440}
4441
4442
4443void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4444 NEONFormatDecoder nfd(instr);
4445 VectorFormat vf = nfd.GetVectorFormat();
4446
4447 static const NEONFormatMap map_lp =
4448 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4449 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4450
4451 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4452 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4453
4454 static const NEONFormatMap map_fcvtn = {{22, 30},
4455 {NF_4H, NF_8H, NF_2S, NF_4S}};
4456 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4457
4458 SimVRegister& rd = ReadVRegister(instr->GetRd());
4459 SimVRegister& rn = ReadVRegister(instr->GetRn());
4460
4461 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4462 // These instructions all use a two bit size field, except NOT and RBIT,
4463 // which use the field to encode the operation.
4464 switch (instr->Mask(NEON2RegMiscMask)) {
4465 case NEON_REV64:
4466 rev64(vf, rd, rn);
4467 break;
4468 case NEON_REV32:
4469 rev32(vf, rd, rn);
4470 break;
4471 case NEON_REV16:
4472 rev16(vf, rd, rn);
4473 break;
4474 case NEON_SUQADD:
4475 suqadd(vf, rd, rn);
4476 break;
4477 case NEON_USQADD:
4478 usqadd(vf, rd, rn);
4479 break;
4480 case NEON_CLS:
4481 cls(vf, rd, rn);
4482 break;
4483 case NEON_CLZ:
4484 clz(vf, rd, rn);
4485 break;
4486 case NEON_CNT:
4487 cnt(vf, rd, rn);
4488 break;
4489 case NEON_SQABS:
4490 abs(vf, rd, rn).SignedSaturate(vf);
4491 break;
4492 case NEON_SQNEG:
4493 neg(vf, rd, rn).SignedSaturate(vf);
4494 break;
4495 case NEON_CMGT_zero:
4496 cmp(vf, rd, rn, 0, gt);
4497 break;
4498 case NEON_CMGE_zero:
4499 cmp(vf, rd, rn, 0, ge);
4500 break;
4501 case NEON_CMEQ_zero:
4502 cmp(vf, rd, rn, 0, eq);
4503 break;
4504 case NEON_CMLE_zero:
4505 cmp(vf, rd, rn, 0, le);
4506 break;
4507 case NEON_CMLT_zero:
4508 cmp(vf, rd, rn, 0, lt);
4509 break;
4510 case NEON_ABS:
4511 abs(vf, rd, rn);
4512 break;
4513 case NEON_NEG:
4514 neg(vf, rd, rn);
4515 break;
4516 case NEON_SADDLP:
4517 saddlp(vf_lp, rd, rn);
4518 break;
4519 case NEON_UADDLP:
4520 uaddlp(vf_lp, rd, rn);
4521 break;
4522 case NEON_SADALP:
4523 sadalp(vf_lp, rd, rn);
4524 break;
4525 case NEON_UADALP:
4526 uadalp(vf_lp, rd, rn);
4527 break;
4528 case NEON_RBIT_NOT:
4529 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4530 switch (instr->GetFPType()) {
4531 case 0:
4532 not_(vf, rd, rn);
4533 break;
4534 case 1:
4535 rbit(vf, rd, rn);
4536 break;
4537 default:
4538 VIXL_UNIMPLEMENTED();
4539 }
4540 break;
4541 }
4542 } else {
4543 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4544 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4545 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004546 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004547
4548 // These instructions all use a one bit size field, except XTN, SQXTUN,
4549 // SHLL, SQXTN and UQXTN, which use a two bit size field.
4550 switch (instr->Mask(NEON2RegMiscFPMask)) {
4551 case NEON_FABS:
4552 fabs_(fpf, rd, rn);
4553 return;
4554 case NEON_FNEG:
4555 fneg(fpf, rd, rn);
4556 return;
4557 case NEON_FSQRT:
4558 fsqrt(fpf, rd, rn);
4559 return;
4560 case NEON_FCVTL:
4561 if (instr->Mask(NEON_Q)) {
4562 fcvtl2(vf_fcvtl, rd, rn);
4563 } else {
4564 fcvtl(vf_fcvtl, rd, rn);
4565 }
4566 return;
4567 case NEON_FCVTN:
4568 if (instr->Mask(NEON_Q)) {
4569 fcvtn2(vf_fcvtn, rd, rn);
4570 } else {
4571 fcvtn(vf_fcvtn, rd, rn);
4572 }
4573 return;
4574 case NEON_FCVTXN:
4575 if (instr->Mask(NEON_Q)) {
4576 fcvtxn2(vf_fcvtn, rd, rn);
4577 } else {
4578 fcvtxn(vf_fcvtn, rd, rn);
4579 }
4580 return;
4581
4582 // The following instructions break from the switch statement, rather
4583 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07004584 case NEON_FRINT32X:
4585 inexact_exception = true;
4586 frint_mode = kFrintToInt32;
4587 break; // Use FPCR rounding mode.
4588 case NEON_FRINT32Z:
4589 inexact_exception = true;
4590 frint_mode = kFrintToInt32;
4591 fpcr_rounding = FPZero;
4592 break;
4593 case NEON_FRINT64X:
4594 inexact_exception = true;
4595 frint_mode = kFrintToInt64;
4596 break; // Use FPCR rounding mode.
4597 case NEON_FRINT64Z:
4598 inexact_exception = true;
4599 frint_mode = kFrintToInt64;
4600 fpcr_rounding = FPZero;
4601 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004602 case NEON_FRINTI:
4603 break; // Use FPCR rounding mode.
4604 case NEON_FRINTX:
4605 inexact_exception = true;
4606 break;
4607 case NEON_FRINTA:
4608 fpcr_rounding = FPTieAway;
4609 break;
4610 case NEON_FRINTM:
4611 fpcr_rounding = FPNegativeInfinity;
4612 break;
4613 case NEON_FRINTN:
4614 fpcr_rounding = FPTieEven;
4615 break;
4616 case NEON_FRINTP:
4617 fpcr_rounding = FPPositiveInfinity;
4618 break;
4619 case NEON_FRINTZ:
4620 fpcr_rounding = FPZero;
4621 break;
4622
4623 case NEON_FCVTNS:
4624 fcvts(fpf, rd, rn, FPTieEven);
4625 return;
4626 case NEON_FCVTNU:
4627 fcvtu(fpf, rd, rn, FPTieEven);
4628 return;
4629 case NEON_FCVTPS:
4630 fcvts(fpf, rd, rn, FPPositiveInfinity);
4631 return;
4632 case NEON_FCVTPU:
4633 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4634 return;
4635 case NEON_FCVTMS:
4636 fcvts(fpf, rd, rn, FPNegativeInfinity);
4637 return;
4638 case NEON_FCVTMU:
4639 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4640 return;
4641 case NEON_FCVTZS:
4642 fcvts(fpf, rd, rn, FPZero);
4643 return;
4644 case NEON_FCVTZU:
4645 fcvtu(fpf, rd, rn, FPZero);
4646 return;
4647 case NEON_FCVTAS:
4648 fcvts(fpf, rd, rn, FPTieAway);
4649 return;
4650 case NEON_FCVTAU:
4651 fcvtu(fpf, rd, rn, FPTieAway);
4652 return;
4653 case NEON_SCVTF:
4654 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4655 return;
4656 case NEON_UCVTF:
4657 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4658 return;
4659 case NEON_URSQRTE:
4660 ursqrte(fpf, rd, rn);
4661 return;
4662 case NEON_URECPE:
4663 urecpe(fpf, rd, rn);
4664 return;
4665 case NEON_FRSQRTE:
4666 frsqrte(fpf, rd, rn);
4667 return;
4668 case NEON_FRECPE:
4669 frecpe(fpf, rd, rn, fpcr_rounding);
4670 return;
4671 case NEON_FCMGT_zero:
4672 fcmp_zero(fpf, rd, rn, gt);
4673 return;
4674 case NEON_FCMGE_zero:
4675 fcmp_zero(fpf, rd, rn, ge);
4676 return;
4677 case NEON_FCMEQ_zero:
4678 fcmp_zero(fpf, rd, rn, eq);
4679 return;
4680 case NEON_FCMLE_zero:
4681 fcmp_zero(fpf, rd, rn, le);
4682 return;
4683 case NEON_FCMLT_zero:
4684 fcmp_zero(fpf, rd, rn, lt);
4685 return;
4686 default:
4687 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4688 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4689 switch (instr->Mask(NEON2RegMiscMask)) {
4690 case NEON_XTN:
4691 xtn(vf, rd, rn);
4692 return;
4693 case NEON_SQXTN:
4694 sqxtn(vf, rd, rn);
4695 return;
4696 case NEON_UQXTN:
4697 uqxtn(vf, rd, rn);
4698 return;
4699 case NEON_SQXTUN:
4700 sqxtun(vf, rd, rn);
4701 return;
4702 case NEON_SHLL:
4703 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4704 if (instr->Mask(NEON_Q)) {
4705 shll2(vf, rd, rn);
4706 } else {
4707 shll(vf, rd, rn);
4708 }
4709 return;
4710 default:
4711 VIXL_UNIMPLEMENTED();
4712 }
4713 } else {
4714 VIXL_UNIMPLEMENTED();
4715 }
4716 }
4717
4718 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004719 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004720 }
4721}
4722
4723
Jacob Bramleyca789742018-09-13 14:25:46 +01004724void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4725 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4726 NEONFormatDecoder nfd(instr);
4727 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4728
4729 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4730
4731 SimVRegister& rd = ReadVRegister(instr->GetRd());
4732 SimVRegister& rn = ReadVRegister(instr->GetRn());
4733
4734 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4735 case NEON_SCVTF_H:
4736 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4737 return;
4738 case NEON_UCVTF_H:
4739 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4740 return;
4741 case NEON_FCVTNS_H:
4742 fcvts(fpf, rd, rn, FPTieEven);
4743 return;
4744 case NEON_FCVTNU_H:
4745 fcvtu(fpf, rd, rn, FPTieEven);
4746 return;
4747 case NEON_FCVTPS_H:
4748 fcvts(fpf, rd, rn, FPPositiveInfinity);
4749 return;
4750 case NEON_FCVTPU_H:
4751 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4752 return;
4753 case NEON_FCVTMS_H:
4754 fcvts(fpf, rd, rn, FPNegativeInfinity);
4755 return;
4756 case NEON_FCVTMU_H:
4757 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4758 return;
4759 case NEON_FCVTZS_H:
4760 fcvts(fpf, rd, rn, FPZero);
4761 return;
4762 case NEON_FCVTZU_H:
4763 fcvtu(fpf, rd, rn, FPZero);
4764 return;
4765 case NEON_FCVTAS_H:
4766 fcvts(fpf, rd, rn, FPTieAway);
4767 return;
4768 case NEON_FCVTAU_H:
4769 fcvtu(fpf, rd, rn, FPTieAway);
4770 return;
4771 case NEON_FRINTI_H:
4772 frint(fpf, rd, rn, fpcr_rounding, false);
4773 return;
4774 case NEON_FRINTX_H:
4775 frint(fpf, rd, rn, fpcr_rounding, true);
4776 return;
4777 case NEON_FRINTA_H:
4778 frint(fpf, rd, rn, FPTieAway, false);
4779 return;
4780 case NEON_FRINTM_H:
4781 frint(fpf, rd, rn, FPNegativeInfinity, false);
4782 return;
4783 case NEON_FRINTN_H:
4784 frint(fpf, rd, rn, FPTieEven, false);
4785 return;
4786 case NEON_FRINTP_H:
4787 frint(fpf, rd, rn, FPPositiveInfinity, false);
4788 return;
4789 case NEON_FRINTZ_H:
4790 frint(fpf, rd, rn, FPZero, false);
4791 return;
4792 case NEON_FABS_H:
4793 fabs_(fpf, rd, rn);
4794 return;
4795 case NEON_FNEG_H:
4796 fneg(fpf, rd, rn);
4797 return;
4798 case NEON_FSQRT_H:
4799 fsqrt(fpf, rd, rn);
4800 return;
4801 case NEON_FRSQRTE_H:
4802 frsqrte(fpf, rd, rn);
4803 return;
4804 case NEON_FRECPE_H:
4805 frecpe(fpf, rd, rn, fpcr_rounding);
4806 return;
4807 case NEON_FCMGT_H_zero:
4808 fcmp_zero(fpf, rd, rn, gt);
4809 return;
4810 case NEON_FCMGE_H_zero:
4811 fcmp_zero(fpf, rd, rn, ge);
4812 return;
4813 case NEON_FCMEQ_H_zero:
4814 fcmp_zero(fpf, rd, rn, eq);
4815 return;
4816 case NEON_FCMLE_H_zero:
4817 fcmp_zero(fpf, rd, rn, le);
4818 return;
4819 case NEON_FCMLT_H_zero:
4820 fcmp_zero(fpf, rd, rn, lt);
4821 return;
4822 default:
4823 VIXL_UNIMPLEMENTED();
4824 return;
4825 }
4826}
4827
4828
Alexandre Ramesd3832962016-07-04 15:03:43 +01004829void Simulator::VisitNEON3Same(const Instruction* instr) {
4830 NEONFormatDecoder nfd(instr);
4831 SimVRegister& rd = ReadVRegister(instr->GetRd());
4832 SimVRegister& rn = ReadVRegister(instr->GetRn());
4833 SimVRegister& rm = ReadVRegister(instr->GetRm());
4834
4835 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
4836 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4837 switch (instr->Mask(NEON3SameLogicalMask)) {
4838 case NEON_AND:
4839 and_(vf, rd, rn, rm);
4840 break;
4841 case NEON_ORR:
4842 orr(vf, rd, rn, rm);
4843 break;
4844 case NEON_ORN:
4845 orn(vf, rd, rn, rm);
4846 break;
4847 case NEON_EOR:
4848 eor(vf, rd, rn, rm);
4849 break;
4850 case NEON_BIC:
4851 bic(vf, rd, rn, rm);
4852 break;
4853 case NEON_BIF:
4854 bif(vf, rd, rn, rm);
4855 break;
4856 case NEON_BIT:
4857 bit(vf, rd, rn, rm);
4858 break;
4859 case NEON_BSL:
4860 bsl(vf, rd, rn, rm);
4861 break;
4862 default:
4863 VIXL_UNIMPLEMENTED();
4864 }
4865 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
4866 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4867 switch (instr->Mask(NEON3SameFPMask)) {
4868 case NEON_FADD:
4869 fadd(vf, rd, rn, rm);
4870 break;
4871 case NEON_FSUB:
4872 fsub(vf, rd, rn, rm);
4873 break;
4874 case NEON_FMUL:
4875 fmul(vf, rd, rn, rm);
4876 break;
4877 case NEON_FDIV:
4878 fdiv(vf, rd, rn, rm);
4879 break;
4880 case NEON_FMAX:
4881 fmax(vf, rd, rn, rm);
4882 break;
4883 case NEON_FMIN:
4884 fmin(vf, rd, rn, rm);
4885 break;
4886 case NEON_FMAXNM:
4887 fmaxnm(vf, rd, rn, rm);
4888 break;
4889 case NEON_FMINNM:
4890 fminnm(vf, rd, rn, rm);
4891 break;
4892 case NEON_FMLA:
4893 fmla(vf, rd, rn, rm);
4894 break;
4895 case NEON_FMLS:
4896 fmls(vf, rd, rn, rm);
4897 break;
4898 case NEON_FMULX:
4899 fmulx(vf, rd, rn, rm);
4900 break;
4901 case NEON_FACGE:
4902 fabscmp(vf, rd, rn, rm, ge);
4903 break;
4904 case NEON_FACGT:
4905 fabscmp(vf, rd, rn, rm, gt);
4906 break;
4907 case NEON_FCMEQ:
4908 fcmp(vf, rd, rn, rm, eq);
4909 break;
4910 case NEON_FCMGE:
4911 fcmp(vf, rd, rn, rm, ge);
4912 break;
4913 case NEON_FCMGT:
4914 fcmp(vf, rd, rn, rm, gt);
4915 break;
4916 case NEON_FRECPS:
4917 frecps(vf, rd, rn, rm);
4918 break;
4919 case NEON_FRSQRTS:
4920 frsqrts(vf, rd, rn, rm);
4921 break;
4922 case NEON_FABD:
4923 fabd(vf, rd, rn, rm);
4924 break;
4925 case NEON_FADDP:
4926 faddp(vf, rd, rn, rm);
4927 break;
4928 case NEON_FMAXP:
4929 fmaxp(vf, rd, rn, rm);
4930 break;
4931 case NEON_FMAXNMP:
4932 fmaxnmp(vf, rd, rn, rm);
4933 break;
4934 case NEON_FMINP:
4935 fminp(vf, rd, rn, rm);
4936 break;
4937 case NEON_FMINNMP:
4938 fminnmp(vf, rd, rn, rm);
4939 break;
4940 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01004941 // FMLAL{2} and FMLSL{2} have special-case encodings.
4942 switch (instr->Mask(NEON3SameFHMMask)) {
4943 case NEON_FMLAL:
4944 fmlal(vf, rd, rn, rm);
4945 break;
4946 case NEON_FMLAL2:
4947 fmlal2(vf, rd, rn, rm);
4948 break;
4949 case NEON_FMLSL:
4950 fmlsl(vf, rd, rn, rm);
4951 break;
4952 case NEON_FMLSL2:
4953 fmlsl2(vf, rd, rn, rm);
4954 break;
4955 default:
4956 VIXL_UNIMPLEMENTED();
4957 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004958 }
4959 } else {
4960 VectorFormat vf = nfd.GetVectorFormat();
4961 switch (instr->Mask(NEON3SameMask)) {
4962 case NEON_ADD:
4963 add(vf, rd, rn, rm);
4964 break;
4965 case NEON_ADDP:
4966 addp(vf, rd, rn, rm);
4967 break;
4968 case NEON_CMEQ:
4969 cmp(vf, rd, rn, rm, eq);
4970 break;
4971 case NEON_CMGE:
4972 cmp(vf, rd, rn, rm, ge);
4973 break;
4974 case NEON_CMGT:
4975 cmp(vf, rd, rn, rm, gt);
4976 break;
4977 case NEON_CMHI:
4978 cmp(vf, rd, rn, rm, hi);
4979 break;
4980 case NEON_CMHS:
4981 cmp(vf, rd, rn, rm, hs);
4982 break;
4983 case NEON_CMTST:
4984 cmptst(vf, rd, rn, rm);
4985 break;
4986 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01004987 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004988 break;
4989 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01004990 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004991 break;
4992 case NEON_MUL:
4993 mul(vf, rd, rn, rm);
4994 break;
4995 case NEON_PMUL:
4996 pmul(vf, rd, rn, rm);
4997 break;
4998 case NEON_SMAX:
4999 smax(vf, rd, rn, rm);
5000 break;
5001 case NEON_SMAXP:
5002 smaxp(vf, rd, rn, rm);
5003 break;
5004 case NEON_SMIN:
5005 smin(vf, rd, rn, rm);
5006 break;
5007 case NEON_SMINP:
5008 sminp(vf, rd, rn, rm);
5009 break;
5010 case NEON_SUB:
5011 sub(vf, rd, rn, rm);
5012 break;
5013 case NEON_UMAX:
5014 umax(vf, rd, rn, rm);
5015 break;
5016 case NEON_UMAXP:
5017 umaxp(vf, rd, rn, rm);
5018 break;
5019 case NEON_UMIN:
5020 umin(vf, rd, rn, rm);
5021 break;
5022 case NEON_UMINP:
5023 uminp(vf, rd, rn, rm);
5024 break;
5025 case NEON_SSHL:
5026 sshl(vf, rd, rn, rm);
5027 break;
5028 case NEON_USHL:
5029 ushl(vf, rd, rn, rm);
5030 break;
5031 case NEON_SABD:
5032 absdiff(vf, rd, rn, rm, true);
5033 break;
5034 case NEON_UABD:
5035 absdiff(vf, rd, rn, rm, false);
5036 break;
5037 case NEON_SABA:
5038 saba(vf, rd, rn, rm);
5039 break;
5040 case NEON_UABA:
5041 uaba(vf, rd, rn, rm);
5042 break;
5043 case NEON_UQADD:
5044 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5045 break;
5046 case NEON_SQADD:
5047 add(vf, rd, rn, rm).SignedSaturate(vf);
5048 break;
5049 case NEON_UQSUB:
5050 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5051 break;
5052 case NEON_SQSUB:
5053 sub(vf, rd, rn, rm).SignedSaturate(vf);
5054 break;
5055 case NEON_SQDMULH:
5056 sqdmulh(vf, rd, rn, rm);
5057 break;
5058 case NEON_SQRDMULH:
5059 sqrdmulh(vf, rd, rn, rm);
5060 break;
5061 case NEON_UQSHL:
5062 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5063 break;
5064 case NEON_SQSHL:
5065 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5066 break;
5067 case NEON_URSHL:
5068 ushl(vf, rd, rn, rm).Round(vf);
5069 break;
5070 case NEON_SRSHL:
5071 sshl(vf, rd, rn, rm).Round(vf);
5072 break;
5073 case NEON_UQRSHL:
5074 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5075 break;
5076 case NEON_SQRSHL:
5077 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5078 break;
5079 case NEON_UHADD:
5080 add(vf, rd, rn, rm).Uhalve(vf);
5081 break;
5082 case NEON_URHADD:
5083 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
5084 break;
5085 case NEON_SHADD:
5086 add(vf, rd, rn, rm).Halve(vf);
5087 break;
5088 case NEON_SRHADD:
5089 add(vf, rd, rn, rm).Halve(vf).Round(vf);
5090 break;
5091 case NEON_UHSUB:
5092 sub(vf, rd, rn, rm).Uhalve(vf);
5093 break;
5094 case NEON_SHSUB:
5095 sub(vf, rd, rn, rm).Halve(vf);
5096 break;
5097 default:
5098 VIXL_UNIMPLEMENTED();
5099 }
5100 }
5101}
5102
5103
Jacob Bramleyca789742018-09-13 14:25:46 +01005104void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
5105 NEONFormatDecoder nfd(instr);
5106 SimVRegister& rd = ReadVRegister(instr->GetRd());
5107 SimVRegister& rn = ReadVRegister(instr->GetRn());
5108 SimVRegister& rm = ReadVRegister(instr->GetRm());
5109
5110 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
5111 switch (instr->Mask(NEON3SameFP16Mask)) {
5112#define SIM_FUNC(A, B) \
5113 case NEON_##A##_H: \
5114 B(vf, rd, rn, rm); \
5115 break;
5116 SIM_FUNC(FMAXNM, fmaxnm);
5117 SIM_FUNC(FMLA, fmla);
5118 SIM_FUNC(FADD, fadd);
5119 SIM_FUNC(FMULX, fmulx);
5120 SIM_FUNC(FMAX, fmax);
5121 SIM_FUNC(FRECPS, frecps);
5122 SIM_FUNC(FMINNM, fminnm);
5123 SIM_FUNC(FMLS, fmls);
5124 SIM_FUNC(FSUB, fsub);
5125 SIM_FUNC(FMIN, fmin);
5126 SIM_FUNC(FRSQRTS, frsqrts);
5127 SIM_FUNC(FMAXNMP, fmaxnmp);
5128 SIM_FUNC(FADDP, faddp);
5129 SIM_FUNC(FMUL, fmul);
5130 SIM_FUNC(FMAXP, fmaxp);
5131 SIM_FUNC(FDIV, fdiv);
5132 SIM_FUNC(FMINNMP, fminnmp);
5133 SIM_FUNC(FABD, fabd);
5134 SIM_FUNC(FMINP, fminp);
5135#undef SIM_FUNC
5136 case NEON_FCMEQ_H:
5137 fcmp(vf, rd, rn, rm, eq);
5138 break;
5139 case NEON_FCMGE_H:
5140 fcmp(vf, rd, rn, rm, ge);
5141 break;
5142 case NEON_FACGE_H:
5143 fabscmp(vf, rd, rn, rm, ge);
5144 break;
5145 case NEON_FCMGT_H:
5146 fcmp(vf, rd, rn, rm, gt);
5147 break;
5148 case NEON_FACGT_H:
5149 fabscmp(vf, rd, rn, rm, gt);
5150 break;
5151 default:
5152 VIXL_UNIMPLEMENTED();
5153 break;
5154 }
5155}
5156
Carey Williams2809e6c2018-03-13 12:24:16 +00005157void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
5158 NEONFormatDecoder nfd(instr);
5159 SimVRegister& rd = ReadVRegister(instr->GetRd());
5160 SimVRegister& rn = ReadVRegister(instr->GetRn());
5161 SimVRegister& rm = ReadVRegister(instr->GetRm());
5162 int rot = 0;
5163 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01005164 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
5165 rot = instr->GetImmRotFcmlaVec();
5166 fcmla(vf, rd, rn, rm, rot);
5167 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
5168 rot = instr->GetImmRotFcadd();
5169 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01005170 } else {
5171 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01005172 case NEON_SDOT:
5173 sdot(vf, rd, rn, rm);
5174 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005175 case NEON_SQRDMLAH:
5176 sqrdmlah(vf, rd, rn, rm);
5177 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005178 case NEON_UDOT:
5179 udot(vf, rd, rn, rm);
5180 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005181 case NEON_SQRDMLSH:
5182 sqrdmlsh(vf, rd, rn, rm);
5183 break;
5184 default:
5185 VIXL_UNIMPLEMENTED();
5186 break;
5187 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005188 }
5189}
5190
5191
Alexandre Ramesd3832962016-07-04 15:03:43 +01005192void Simulator::VisitNEON3Different(const Instruction* instr) {
5193 NEONFormatDecoder nfd(instr);
5194 VectorFormat vf = nfd.GetVectorFormat();
5195 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5196
5197 SimVRegister& rd = ReadVRegister(instr->GetRd());
5198 SimVRegister& rn = ReadVRegister(instr->GetRn());
5199 SimVRegister& rm = ReadVRegister(instr->GetRm());
5200
5201 switch (instr->Mask(NEON3DifferentMask)) {
5202 case NEON_PMULL:
5203 pmull(vf_l, rd, rn, rm);
5204 break;
5205 case NEON_PMULL2:
5206 pmull2(vf_l, rd, rn, rm);
5207 break;
5208 case NEON_UADDL:
5209 uaddl(vf_l, rd, rn, rm);
5210 break;
5211 case NEON_UADDL2:
5212 uaddl2(vf_l, rd, rn, rm);
5213 break;
5214 case NEON_SADDL:
5215 saddl(vf_l, rd, rn, rm);
5216 break;
5217 case NEON_SADDL2:
5218 saddl2(vf_l, rd, rn, rm);
5219 break;
5220 case NEON_USUBL:
5221 usubl(vf_l, rd, rn, rm);
5222 break;
5223 case NEON_USUBL2:
5224 usubl2(vf_l, rd, rn, rm);
5225 break;
5226 case NEON_SSUBL:
5227 ssubl(vf_l, rd, rn, rm);
5228 break;
5229 case NEON_SSUBL2:
5230 ssubl2(vf_l, rd, rn, rm);
5231 break;
5232 case NEON_SABAL:
5233 sabal(vf_l, rd, rn, rm);
5234 break;
5235 case NEON_SABAL2:
5236 sabal2(vf_l, rd, rn, rm);
5237 break;
5238 case NEON_UABAL:
5239 uabal(vf_l, rd, rn, rm);
5240 break;
5241 case NEON_UABAL2:
5242 uabal2(vf_l, rd, rn, rm);
5243 break;
5244 case NEON_SABDL:
5245 sabdl(vf_l, rd, rn, rm);
5246 break;
5247 case NEON_SABDL2:
5248 sabdl2(vf_l, rd, rn, rm);
5249 break;
5250 case NEON_UABDL:
5251 uabdl(vf_l, rd, rn, rm);
5252 break;
5253 case NEON_UABDL2:
5254 uabdl2(vf_l, rd, rn, rm);
5255 break;
5256 case NEON_SMLAL:
5257 smlal(vf_l, rd, rn, rm);
5258 break;
5259 case NEON_SMLAL2:
5260 smlal2(vf_l, rd, rn, rm);
5261 break;
5262 case NEON_UMLAL:
5263 umlal(vf_l, rd, rn, rm);
5264 break;
5265 case NEON_UMLAL2:
5266 umlal2(vf_l, rd, rn, rm);
5267 break;
5268 case NEON_SMLSL:
5269 smlsl(vf_l, rd, rn, rm);
5270 break;
5271 case NEON_SMLSL2:
5272 smlsl2(vf_l, rd, rn, rm);
5273 break;
5274 case NEON_UMLSL:
5275 umlsl(vf_l, rd, rn, rm);
5276 break;
5277 case NEON_UMLSL2:
5278 umlsl2(vf_l, rd, rn, rm);
5279 break;
5280 case NEON_SMULL:
5281 smull(vf_l, rd, rn, rm);
5282 break;
5283 case NEON_SMULL2:
5284 smull2(vf_l, rd, rn, rm);
5285 break;
5286 case NEON_UMULL:
5287 umull(vf_l, rd, rn, rm);
5288 break;
5289 case NEON_UMULL2:
5290 umull2(vf_l, rd, rn, rm);
5291 break;
5292 case NEON_SQDMLAL:
5293 sqdmlal(vf_l, rd, rn, rm);
5294 break;
5295 case NEON_SQDMLAL2:
5296 sqdmlal2(vf_l, rd, rn, rm);
5297 break;
5298 case NEON_SQDMLSL:
5299 sqdmlsl(vf_l, rd, rn, rm);
5300 break;
5301 case NEON_SQDMLSL2:
5302 sqdmlsl2(vf_l, rd, rn, rm);
5303 break;
5304 case NEON_SQDMULL:
5305 sqdmull(vf_l, rd, rn, rm);
5306 break;
5307 case NEON_SQDMULL2:
5308 sqdmull2(vf_l, rd, rn, rm);
5309 break;
5310 case NEON_UADDW:
5311 uaddw(vf_l, rd, rn, rm);
5312 break;
5313 case NEON_UADDW2:
5314 uaddw2(vf_l, rd, rn, rm);
5315 break;
5316 case NEON_SADDW:
5317 saddw(vf_l, rd, rn, rm);
5318 break;
5319 case NEON_SADDW2:
5320 saddw2(vf_l, rd, rn, rm);
5321 break;
5322 case NEON_USUBW:
5323 usubw(vf_l, rd, rn, rm);
5324 break;
5325 case NEON_USUBW2:
5326 usubw2(vf_l, rd, rn, rm);
5327 break;
5328 case NEON_SSUBW:
5329 ssubw(vf_l, rd, rn, rm);
5330 break;
5331 case NEON_SSUBW2:
5332 ssubw2(vf_l, rd, rn, rm);
5333 break;
5334 case NEON_ADDHN:
5335 addhn(vf, rd, rn, rm);
5336 break;
5337 case NEON_ADDHN2:
5338 addhn2(vf, rd, rn, rm);
5339 break;
5340 case NEON_RADDHN:
5341 raddhn(vf, rd, rn, rm);
5342 break;
5343 case NEON_RADDHN2:
5344 raddhn2(vf, rd, rn, rm);
5345 break;
5346 case NEON_SUBHN:
5347 subhn(vf, rd, rn, rm);
5348 break;
5349 case NEON_SUBHN2:
5350 subhn2(vf, rd, rn, rm);
5351 break;
5352 case NEON_RSUBHN:
5353 rsubhn(vf, rd, rn, rm);
5354 break;
5355 case NEON_RSUBHN2:
5356 rsubhn2(vf, rd, rn, rm);
5357 break;
5358 default:
5359 VIXL_UNIMPLEMENTED();
5360 }
5361}
5362
5363
5364void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5365 NEONFormatDecoder nfd(instr);
5366
Jacob Bramleyca789742018-09-13 14:25:46 +01005367 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5368
Alexandre Ramesd3832962016-07-04 15:03:43 +01005369 SimVRegister& rd = ReadVRegister(instr->GetRd());
5370 SimVRegister& rn = ReadVRegister(instr->GetRn());
5371
Jacob Bramleyca789742018-09-13 14:25:46 +01005372 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5373 VectorFormat vf = nfd.GetVectorFormat(&map_half);
5374 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5375 case NEON_FMAXV_H:
5376 fmaxv(vf, rd, rn);
5377 break;
5378 case NEON_FMINV_H:
5379 fminv(vf, rd, rn);
5380 break;
5381 case NEON_FMAXNMV_H:
5382 fmaxnmv(vf, rd, rn);
5383 break;
5384 case NEON_FMINNMV_H:
5385 fminnmv(vf, rd, rn);
5386 break;
5387 default:
5388 VIXL_UNIMPLEMENTED();
5389 }
5390 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5391 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01005392 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5393
5394 switch (instr->Mask(NEONAcrossLanesFPMask)) {
5395 case NEON_FMAXV:
5396 fmaxv(vf, rd, rn);
5397 break;
5398 case NEON_FMINV:
5399 fminv(vf, rd, rn);
5400 break;
5401 case NEON_FMAXNMV:
5402 fmaxnmv(vf, rd, rn);
5403 break;
5404 case NEON_FMINNMV:
5405 fminnmv(vf, rd, rn);
5406 break;
5407 default:
5408 VIXL_UNIMPLEMENTED();
5409 }
5410 } else {
5411 VectorFormat vf = nfd.GetVectorFormat();
5412
5413 switch (instr->Mask(NEONAcrossLanesMask)) {
5414 case NEON_ADDV:
5415 addv(vf, rd, rn);
5416 break;
5417 case NEON_SMAXV:
5418 smaxv(vf, rd, rn);
5419 break;
5420 case NEON_SMINV:
5421 sminv(vf, rd, rn);
5422 break;
5423 case NEON_UMAXV:
5424 umaxv(vf, rd, rn);
5425 break;
5426 case NEON_UMINV:
5427 uminv(vf, rd, rn);
5428 break;
5429 case NEON_SADDLV:
5430 saddlv(vf, rd, rn);
5431 break;
5432 case NEON_UADDLV:
5433 uaddlv(vf, rd, rn);
5434 break;
5435 default:
5436 VIXL_UNIMPLEMENTED();
5437 }
5438 }
5439}
5440
5441
5442void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5443 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01005444 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01005445 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01005446 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005447 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5448
5449 SimVRegister& rd = ReadVRegister(instr->GetRd());
5450 SimVRegister& rn = ReadVRegister(instr->GetRn());
5451
5452 ByElementOp Op = NULL;
5453
5454 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005455 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005456 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005457 int index_hlm = (index << 1) | instr->GetNEONM();
5458
5459 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5460 // These are oddballs and are best handled as special cases.
5461 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5462 // - The index is always H:L:M.
5463 case NEON_FMLAL_H_byelement:
5464 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5465 return;
5466 case NEON_FMLAL2_H_byelement:
5467 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5468 return;
5469 case NEON_FMLSL_H_byelement:
5470 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5471 return;
5472 case NEON_FMLSL2_H_byelement:
5473 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5474 return;
5475 }
5476
Alexandre Ramesd3832962016-07-04 15:03:43 +01005477 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005478 rm_reg = rm_low_reg;
5479 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005480 }
5481
5482 switch (instr->Mask(NEONByIndexedElementMask)) {
5483 case NEON_MUL_byelement:
5484 Op = &Simulator::mul;
5485 vf = vf_r;
5486 break;
5487 case NEON_MLA_byelement:
5488 Op = &Simulator::mla;
5489 vf = vf_r;
5490 break;
5491 case NEON_MLS_byelement:
5492 Op = &Simulator::mls;
5493 vf = vf_r;
5494 break;
5495 case NEON_SQDMULH_byelement:
5496 Op = &Simulator::sqdmulh;
5497 vf = vf_r;
5498 break;
5499 case NEON_SQRDMULH_byelement:
5500 Op = &Simulator::sqrdmulh;
5501 vf = vf_r;
5502 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005503 case NEON_SDOT_byelement:
5504 Op = &Simulator::sdot;
5505 vf = vf_r;
5506 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005507 case NEON_SQRDMLAH_byelement:
5508 Op = &Simulator::sqrdmlah;
5509 vf = vf_r;
5510 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005511 case NEON_UDOT_byelement:
5512 Op = &Simulator::udot;
5513 vf = vf_r;
5514 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005515 case NEON_SQRDMLSH_byelement:
5516 Op = &Simulator::sqrdmlsh;
5517 vf = vf_r;
5518 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005519 case NEON_SMULL_byelement:
5520 if (instr->Mask(NEON_Q)) {
5521 Op = &Simulator::smull2;
5522 } else {
5523 Op = &Simulator::smull;
5524 }
5525 break;
5526 case NEON_UMULL_byelement:
5527 if (instr->Mask(NEON_Q)) {
5528 Op = &Simulator::umull2;
5529 } else {
5530 Op = &Simulator::umull;
5531 }
5532 break;
5533 case NEON_SMLAL_byelement:
5534 if (instr->Mask(NEON_Q)) {
5535 Op = &Simulator::smlal2;
5536 } else {
5537 Op = &Simulator::smlal;
5538 }
5539 break;
5540 case NEON_UMLAL_byelement:
5541 if (instr->Mask(NEON_Q)) {
5542 Op = &Simulator::umlal2;
5543 } else {
5544 Op = &Simulator::umlal;
5545 }
5546 break;
5547 case NEON_SMLSL_byelement:
5548 if (instr->Mask(NEON_Q)) {
5549 Op = &Simulator::smlsl2;
5550 } else {
5551 Op = &Simulator::smlsl;
5552 }
5553 break;
5554 case NEON_UMLSL_byelement:
5555 if (instr->Mask(NEON_Q)) {
5556 Op = &Simulator::umlsl2;
5557 } else {
5558 Op = &Simulator::umlsl;
5559 }
5560 break;
5561 case NEON_SQDMULL_byelement:
5562 if (instr->Mask(NEON_Q)) {
5563 Op = &Simulator::sqdmull2;
5564 } else {
5565 Op = &Simulator::sqdmull;
5566 }
5567 break;
5568 case NEON_SQDMLAL_byelement:
5569 if (instr->Mask(NEON_Q)) {
5570 Op = &Simulator::sqdmlal2;
5571 } else {
5572 Op = &Simulator::sqdmlal;
5573 }
5574 break;
5575 case NEON_SQDMLSL_byelement:
5576 if (instr->Mask(NEON_Q)) {
5577 Op = &Simulator::sqdmlsl2;
5578 } else {
5579 Op = &Simulator::sqdmlsl;
5580 }
5581 break;
5582 default:
5583 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01005584 if (instr->GetFPType() == 0) {
5585 rm_reg &= 0xf;
5586 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5587 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005588 index = (index << 1) | instr->GetNEONL();
5589 }
5590
5591 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5592
5593 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005594 case NEON_FMUL_H_byelement:
5595 vf = vf_half;
5596 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005597 case NEON_FMUL_byelement:
5598 Op = &Simulator::fmul;
5599 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005600 case NEON_FMLA_H_byelement:
5601 vf = vf_half;
5602 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005603 case NEON_FMLA_byelement:
5604 Op = &Simulator::fmla;
5605 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005606 case NEON_FMLS_H_byelement:
5607 vf = vf_half;
5608 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005609 case NEON_FMLS_byelement:
5610 Op = &Simulator::fmls;
5611 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005612 case NEON_FMULX_H_byelement:
5613 vf = vf_half;
5614 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005615 case NEON_FMULX_byelement:
5616 Op = &Simulator::fmulx;
5617 break;
5618 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005619 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00005620 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005621 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00005622 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005623 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005624 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5625 case NEON_FCMLA_byelement:
5626 vf = vf_r;
5627 fcmla(vf,
5628 rd,
5629 rn,
5630 ReadVRegister(instr->GetRm()),
5631 index,
5632 instr->GetImmRotFcmlaSca());
5633 return;
5634 default:
5635 VIXL_UNIMPLEMENTED();
5636 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005637 }
5638 }
5639
5640 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5641}
5642
5643
5644void Simulator::VisitNEONCopy(const Instruction* instr) {
5645 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5646 VectorFormat vf = nfd.GetVectorFormat();
5647
5648 SimVRegister& rd = ReadVRegister(instr->GetRd());
5649 SimVRegister& rn = ReadVRegister(instr->GetRn());
5650 int imm5 = instr->GetImmNEON5();
5651 int tz = CountTrailingZeros(imm5, 32);
5652 int reg_index = imm5 >> (tz + 1);
5653
5654 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5655 int imm4 = instr->GetImmNEON4();
5656 int rn_index = imm4 >> tz;
5657 ins_element(vf, rd, reg_index, rn, rn_index);
5658 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5659 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5660 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5661 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5662 value &= MaxUintFromFormat(vf);
5663 WriteXRegister(instr->GetRd(), value);
5664 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5665 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5666 if (instr->GetNEONQ()) {
5667 WriteXRegister(instr->GetRd(), value);
5668 } else {
5669 WriteWRegister(instr->GetRd(), (int32_t)value);
5670 }
5671 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5672 dup_element(vf, rd, rn, reg_index);
5673 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5674 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5675 } else {
5676 VIXL_UNIMPLEMENTED();
5677 }
5678}
5679
5680
5681void Simulator::VisitNEONExtract(const Instruction* instr) {
5682 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5683 VectorFormat vf = nfd.GetVectorFormat();
5684 SimVRegister& rd = ReadVRegister(instr->GetRd());
5685 SimVRegister& rn = ReadVRegister(instr->GetRn());
5686 SimVRegister& rm = ReadVRegister(instr->GetRm());
5687 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5688 int index = instr->GetImmNEONExt();
5689 ext(vf, rd, rn, rm, index);
5690 } else {
5691 VIXL_UNIMPLEMENTED();
5692 }
5693}
5694
5695
5696void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5697 AddrMode addr_mode) {
5698 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5699 VectorFormat vf = nfd.GetVectorFormat();
5700
5701 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5702 int reg_size = RegisterSizeInBytesFromFormat(vf);
5703
5704 int reg[4];
5705 uint64_t addr[4];
5706 for (int i = 0; i < 4; i++) {
5707 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5708 addr[i] = addr_base + (i * reg_size);
5709 }
5710 int count = 1;
5711 bool log_read = true;
5712
Martyn Capewell32009e32016-10-27 11:00:37 +01005713 // Bit 23 determines whether this is an offset or post-index addressing mode.
5714 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5715 // register or immediate in post-index mode.
5716 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005717 VIXL_UNREACHABLE();
5718 }
5719
5720 // We use the PostIndex mask here, as it works in this case for both Offset
5721 // and PostIndex addressing.
5722 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5723 case NEON_LD1_4v:
5724 case NEON_LD1_4v_post:
5725 ld1(vf, ReadVRegister(reg[3]), addr[3]);
5726 count++;
5727 VIXL_FALLTHROUGH();
5728 case NEON_LD1_3v:
5729 case NEON_LD1_3v_post:
5730 ld1(vf, ReadVRegister(reg[2]), addr[2]);
5731 count++;
5732 VIXL_FALLTHROUGH();
5733 case NEON_LD1_2v:
5734 case NEON_LD1_2v_post:
5735 ld1(vf, ReadVRegister(reg[1]), addr[1]);
5736 count++;
5737 VIXL_FALLTHROUGH();
5738 case NEON_LD1_1v:
5739 case NEON_LD1_1v_post:
5740 ld1(vf, ReadVRegister(reg[0]), addr[0]);
5741 break;
5742 case NEON_ST1_4v:
5743 case NEON_ST1_4v_post:
5744 st1(vf, ReadVRegister(reg[3]), addr[3]);
5745 count++;
5746 VIXL_FALLTHROUGH();
5747 case NEON_ST1_3v:
5748 case NEON_ST1_3v_post:
5749 st1(vf, ReadVRegister(reg[2]), addr[2]);
5750 count++;
5751 VIXL_FALLTHROUGH();
5752 case NEON_ST1_2v:
5753 case NEON_ST1_2v_post:
5754 st1(vf, ReadVRegister(reg[1]), addr[1]);
5755 count++;
5756 VIXL_FALLTHROUGH();
5757 case NEON_ST1_1v:
5758 case NEON_ST1_1v_post:
5759 st1(vf, ReadVRegister(reg[0]), addr[0]);
5760 log_read = false;
5761 break;
5762 case NEON_LD2_post:
5763 case NEON_LD2:
5764 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5765 count = 2;
5766 break;
5767 case NEON_ST2:
5768 case NEON_ST2_post:
5769 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5770 count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01005771 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005772 break;
5773 case NEON_LD3_post:
5774 case NEON_LD3:
5775 ld3(vf,
5776 ReadVRegister(reg[0]),
5777 ReadVRegister(reg[1]),
5778 ReadVRegister(reg[2]),
5779 addr[0]);
5780 count = 3;
5781 break;
5782 case NEON_ST3:
5783 case NEON_ST3_post:
5784 st3(vf,
5785 ReadVRegister(reg[0]),
5786 ReadVRegister(reg[1]),
5787 ReadVRegister(reg[2]),
5788 addr[0]);
5789 count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01005790 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005791 break;
5792 case NEON_ST4:
5793 case NEON_ST4_post:
5794 st4(vf,
5795 ReadVRegister(reg[0]),
5796 ReadVRegister(reg[1]),
5797 ReadVRegister(reg[2]),
5798 ReadVRegister(reg[3]),
5799 addr[0]);
5800 count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01005801 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005802 break;
5803 case NEON_LD4_post:
5804 case NEON_LD4:
5805 ld4(vf,
5806 ReadVRegister(reg[0]),
5807 ReadVRegister(reg[1]),
5808 ReadVRegister(reg[2]),
5809 ReadVRegister(reg[3]),
5810 addr[0]);
5811 count = 4;
5812 break;
5813 default:
5814 VIXL_UNIMPLEMENTED();
5815 }
5816
5817 // Explicitly log the register update whilst we have type information.
5818 for (int i = 0; i < count; i++) {
5819 // For de-interleaving loads, only print the base address.
5820 int lane_size = LaneSizeInBytesFromFormat(vf);
5821 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
5822 GetPrintRegisterFormatForSize(reg_size, lane_size));
5823 if (log_read) {
5824 LogVRead(addr_base, reg[i], format);
5825 } else {
5826 LogVWrite(addr_base, reg[i], format);
5827 }
5828 }
5829
5830 if (addr_mode == PostIndex) {
5831 int rm = instr->GetRm();
5832 // The immediate post index addressing mode is indicated by rm = 31.
5833 // The immediate is implied by the number of vector registers used.
5834 addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
5835 : ReadXRegister(rm);
5836 WriteXRegister(instr->GetRn(), addr_base);
5837 } else {
5838 VIXL_ASSERT(addr_mode == Offset);
5839 }
5840}
5841
5842
5843void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
5844 NEONLoadStoreMultiStructHelper(instr, Offset);
5845}
5846
5847
5848void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
5849 const Instruction* instr) {
5850 NEONLoadStoreMultiStructHelper(instr, PostIndex);
5851}
5852
5853
5854void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
5855 AddrMode addr_mode) {
5856 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5857 int rt = instr->GetRt();
5858
Martyn Capewell32009e32016-10-27 11:00:37 +01005859 // Bit 23 determines whether this is an offset or post-index addressing mode.
5860 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5861 // register or immediate in post-index mode.
5862 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005863 VIXL_UNREACHABLE();
5864 }
5865
5866 // We use the PostIndex mask here, as it works in this case for both Offset
5867 // and PostIndex addressing.
5868 bool do_load = false;
5869
5870 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5871 VectorFormat vf_t = nfd.GetVectorFormat();
5872
5873 VectorFormat vf = kFormat16B;
5874 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
5875 case NEON_LD1_b:
5876 case NEON_LD1_b_post:
5877 case NEON_LD2_b:
5878 case NEON_LD2_b_post:
5879 case NEON_LD3_b:
5880 case NEON_LD3_b_post:
5881 case NEON_LD4_b:
5882 case NEON_LD4_b_post:
5883 do_load = true;
5884 VIXL_FALLTHROUGH();
5885 case NEON_ST1_b:
5886 case NEON_ST1_b_post:
5887 case NEON_ST2_b:
5888 case NEON_ST2_b_post:
5889 case NEON_ST3_b:
5890 case NEON_ST3_b_post:
5891 case NEON_ST4_b:
5892 case NEON_ST4_b_post:
5893 break;
5894
5895 case NEON_LD1_h:
5896 case NEON_LD1_h_post:
5897 case NEON_LD2_h:
5898 case NEON_LD2_h_post:
5899 case NEON_LD3_h:
5900 case NEON_LD3_h_post:
5901 case NEON_LD4_h:
5902 case NEON_LD4_h_post:
5903 do_load = true;
5904 VIXL_FALLTHROUGH();
5905 case NEON_ST1_h:
5906 case NEON_ST1_h_post:
5907 case NEON_ST2_h:
5908 case NEON_ST2_h_post:
5909 case NEON_ST3_h:
5910 case NEON_ST3_h_post:
5911 case NEON_ST4_h:
5912 case NEON_ST4_h_post:
5913 vf = kFormat8H;
5914 break;
5915 case NEON_LD1_s:
5916 case NEON_LD1_s_post:
5917 case NEON_LD2_s:
5918 case NEON_LD2_s_post:
5919 case NEON_LD3_s:
5920 case NEON_LD3_s_post:
5921 case NEON_LD4_s:
5922 case NEON_LD4_s_post:
5923 do_load = true;
5924 VIXL_FALLTHROUGH();
5925 case NEON_ST1_s:
5926 case NEON_ST1_s_post:
5927 case NEON_ST2_s:
5928 case NEON_ST2_s_post:
5929 case NEON_ST3_s:
5930 case NEON_ST3_s_post:
5931 case NEON_ST4_s:
5932 case NEON_ST4_s_post: {
5933 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
5934 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
5935 NEON_LD1_d_post);
5936 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
5937 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
5938 NEON_ST1_d_post);
5939 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
5940 break;
5941 }
5942
5943 case NEON_LD1R:
5944 case NEON_LD1R_post: {
5945 vf = vf_t;
5946 ld1r(vf, ReadVRegister(rt), addr);
5947 do_load = true;
5948 break;
5949 }
5950
5951 case NEON_LD2R:
5952 case NEON_LD2R_post: {
5953 vf = vf_t;
5954 int rt2 = (rt + 1) % kNumberOfVRegisters;
5955 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
5956 do_load = true;
5957 break;
5958 }
5959
5960 case NEON_LD3R:
5961 case NEON_LD3R_post: {
5962 vf = vf_t;
5963 int rt2 = (rt + 1) % kNumberOfVRegisters;
5964 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5965 ld3r(vf, ReadVRegister(rt), ReadVRegister(rt2), ReadVRegister(rt3), addr);
5966 do_load = true;
5967 break;
5968 }
5969
5970 case NEON_LD4R:
5971 case NEON_LD4R_post: {
5972 vf = vf_t;
5973 int rt2 = (rt + 1) % kNumberOfVRegisters;
5974 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5975 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5976 ld4r(vf,
5977 ReadVRegister(rt),
5978 ReadVRegister(rt2),
5979 ReadVRegister(rt3),
5980 ReadVRegister(rt4),
5981 addr);
5982 do_load = true;
5983 break;
5984 }
5985 default:
5986 VIXL_UNIMPLEMENTED();
5987 }
5988
5989 PrintRegisterFormat print_format =
5990 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
5991 // Make sure that the print_format only includes a single lane.
5992 print_format =
5993 static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
5994
5995 int esize = LaneSizeInBytesFromFormat(vf);
5996 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
5997 int lane = instr->GetNEONLSIndex(index_shift);
5998 int scale = 0;
5999 int rt2 = (rt + 1) % kNumberOfVRegisters;
6000 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
6001 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
6002 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
6003 case NEONLoadStoreSingle1:
6004 scale = 1;
6005 if (do_load) {
6006 ld1(vf, ReadVRegister(rt), lane, addr);
6007 LogVRead(addr, rt, print_format, lane);
6008 } else {
6009 st1(vf, ReadVRegister(rt), lane, addr);
6010 LogVWrite(addr, rt, print_format, lane);
6011 }
6012 break;
6013 case NEONLoadStoreSingle2:
6014 scale = 2;
6015 if (do_load) {
6016 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
6017 LogVRead(addr, rt, print_format, lane);
6018 LogVRead(addr + esize, rt2, print_format, lane);
6019 } else {
6020 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
6021 LogVWrite(addr, rt, print_format, lane);
6022 LogVWrite(addr + esize, rt2, print_format, lane);
6023 }
6024 break;
6025 case NEONLoadStoreSingle3:
6026 scale = 3;
6027 if (do_load) {
6028 ld3(vf,
6029 ReadVRegister(rt),
6030 ReadVRegister(rt2),
6031 ReadVRegister(rt3),
6032 lane,
6033 addr);
6034 LogVRead(addr, rt, print_format, lane);
6035 LogVRead(addr + esize, rt2, print_format, lane);
6036 LogVRead(addr + (2 * esize), rt3, print_format, lane);
6037 } else {
6038 st3(vf,
6039 ReadVRegister(rt),
6040 ReadVRegister(rt2),
6041 ReadVRegister(rt3),
6042 lane,
6043 addr);
6044 LogVWrite(addr, rt, print_format, lane);
6045 LogVWrite(addr + esize, rt2, print_format, lane);
6046 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
6047 }
6048 break;
6049 case NEONLoadStoreSingle4:
6050 scale = 4;
6051 if (do_load) {
6052 ld4(vf,
6053 ReadVRegister(rt),
6054 ReadVRegister(rt2),
6055 ReadVRegister(rt3),
6056 ReadVRegister(rt4),
6057 lane,
6058 addr);
6059 LogVRead(addr, rt, print_format, lane);
6060 LogVRead(addr + esize, rt2, print_format, lane);
6061 LogVRead(addr + (2 * esize), rt3, print_format, lane);
6062 LogVRead(addr + (3 * esize), rt4, print_format, lane);
6063 } else {
6064 st4(vf,
6065 ReadVRegister(rt),
6066 ReadVRegister(rt2),
6067 ReadVRegister(rt3),
6068 ReadVRegister(rt4),
6069 lane,
6070 addr);
6071 LogVWrite(addr, rt, print_format, lane);
6072 LogVWrite(addr + esize, rt2, print_format, lane);
6073 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
6074 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
6075 }
6076 break;
6077 default:
6078 VIXL_UNIMPLEMENTED();
6079 }
6080
6081 if (addr_mode == PostIndex) {
6082 int rm = instr->GetRm();
6083 int lane_size = LaneSizeInBytesFromFormat(vf);
6084 WriteXRegister(instr->GetRn(),
6085 addr +
6086 ((rm == 31) ? (scale * lane_size) : ReadXRegister(rm)));
6087 }
6088}
6089
6090
6091void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
6092 NEONLoadStoreSingleStructHelper(instr, Offset);
6093}
6094
6095
6096void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
6097 const Instruction* instr) {
6098 NEONLoadStoreSingleStructHelper(instr, PostIndex);
6099}
6100
6101
6102void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
6103 SimVRegister& rd = ReadVRegister(instr->GetRd());
6104 int cmode = instr->GetNEONCmode();
6105 int cmode_3_1 = (cmode >> 1) & 7;
6106 int cmode_3 = (cmode >> 3) & 1;
6107 int cmode_2 = (cmode >> 2) & 1;
6108 int cmode_1 = (cmode >> 1) & 1;
6109 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006110 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006111 int q = instr->GetNEONQ();
6112 int op_bit = instr->GetNEONModImmOp();
6113 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006114 // Find the format and immediate value
6115 uint64_t imm = 0;
6116 VectorFormat vform = kFormatUndefined;
6117 switch (cmode_3_1) {
6118 case 0x0:
6119 case 0x1:
6120 case 0x2:
6121 case 0x3:
6122 vform = (q == 1) ? kFormat4S : kFormat2S;
6123 imm = imm8 << (8 * cmode_3_1);
6124 break;
6125 case 0x4:
6126 case 0x5:
6127 vform = (q == 1) ? kFormat8H : kFormat4H;
6128 imm = imm8 << (8 * cmode_1);
6129 break;
6130 case 0x6:
6131 vform = (q == 1) ? kFormat4S : kFormat2S;
6132 if (cmode_0 == 0) {
6133 imm = imm8 << 8 | 0x000000ff;
6134 } else {
6135 imm = imm8 << 16 | 0x0000ffff;
6136 }
6137 break;
6138 case 0x7:
6139 if (cmode_0 == 0 && op_bit == 0) {
6140 vform = q ? kFormat16B : kFormat8B;
6141 imm = imm8;
6142 } else if (cmode_0 == 0 && op_bit == 1) {
6143 vform = q ? kFormat2D : kFormat1D;
6144 imm = 0;
6145 for (int i = 0; i < 8; ++i) {
6146 if (imm8 & (1 << i)) {
6147 imm |= (UINT64_C(0xff) << (8 * i));
6148 }
6149 }
6150 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01006151 if (half_enc == 1) {
6152 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01006153 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006154 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006155 vform = q ? kFormat4S : kFormat2S;
6156 imm = FloatToRawbits(instr->GetImmNEONFP32());
6157 } else if (q == 1) {
6158 vform = kFormat2D;
6159 imm = DoubleToRawbits(instr->GetImmNEONFP64());
6160 } else {
6161 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
6162 VisitUnallocated(instr);
6163 }
6164 }
6165 break;
6166 default:
6167 VIXL_UNREACHABLE();
6168 break;
6169 }
6170
6171 // Find the operation
6172 NEONModifiedImmediateOp op;
6173 if (cmode_3 == 0) {
6174 if (cmode_0 == 0) {
6175 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6176 } else { // cmode<0> == '1'
6177 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6178 }
6179 } else { // cmode<3> == '1'
6180 if (cmode_2 == 0) {
6181 if (cmode_0 == 0) {
6182 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6183 } else { // cmode<0> == '1'
6184 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6185 }
6186 } else { // cmode<2> == '1'
6187 if (cmode_1 == 0) {
6188 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6189 } else { // cmode<1> == '1'
6190 if (cmode_0 == 0) {
6191 op = NEONModifiedImmediate_MOVI;
6192 } else { // cmode<0> == '1'
6193 op = NEONModifiedImmediate_MOVI;
6194 }
6195 }
6196 }
6197 }
6198
6199 // Call the logic function
6200 if (op == NEONModifiedImmediate_ORR) {
6201 orr(vform, rd, rd, imm);
6202 } else if (op == NEONModifiedImmediate_BIC) {
6203 bic(vform, rd, rd, imm);
6204 } else if (op == NEONModifiedImmediate_MOVI) {
6205 movi(vform, rd, imm);
6206 } else if (op == NEONModifiedImmediate_MVNI) {
6207 mvni(vform, rd, imm);
6208 } else {
6209 VisitUnimplemented(instr);
6210 }
6211}
6212
6213
6214void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
6215 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6216 VectorFormat vf = nfd.GetVectorFormat();
6217
6218 SimVRegister& rd = ReadVRegister(instr->GetRd());
6219 SimVRegister& rn = ReadVRegister(instr->GetRn());
6220
6221 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
6222 // These instructions all use a two bit size field, except NOT and RBIT,
6223 // which use the field to encode the operation.
6224 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6225 case NEON_CMEQ_zero_scalar:
6226 cmp(vf, rd, rn, 0, eq);
6227 break;
6228 case NEON_CMGE_zero_scalar:
6229 cmp(vf, rd, rn, 0, ge);
6230 break;
6231 case NEON_CMGT_zero_scalar:
6232 cmp(vf, rd, rn, 0, gt);
6233 break;
6234 case NEON_CMLT_zero_scalar:
6235 cmp(vf, rd, rn, 0, lt);
6236 break;
6237 case NEON_CMLE_zero_scalar:
6238 cmp(vf, rd, rn, 0, le);
6239 break;
6240 case NEON_ABS_scalar:
6241 abs(vf, rd, rn);
6242 break;
6243 case NEON_SQABS_scalar:
6244 abs(vf, rd, rn).SignedSaturate(vf);
6245 break;
6246 case NEON_NEG_scalar:
6247 neg(vf, rd, rn);
6248 break;
6249 case NEON_SQNEG_scalar:
6250 neg(vf, rd, rn).SignedSaturate(vf);
6251 break;
6252 case NEON_SUQADD_scalar:
6253 suqadd(vf, rd, rn);
6254 break;
6255 case NEON_USQADD_scalar:
6256 usqadd(vf, rd, rn);
6257 break;
6258 default:
6259 VIXL_UNIMPLEMENTED();
6260 break;
6261 }
6262 } else {
6263 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6264 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6265
6266 // These instructions all use a one bit size field, except SQXTUN, SQXTN
6267 // and UQXTN, which use a two bit size field.
6268 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
6269 case NEON_FRECPE_scalar:
6270 frecpe(fpf, rd, rn, fpcr_rounding);
6271 break;
6272 case NEON_FRECPX_scalar:
6273 frecpx(fpf, rd, rn);
6274 break;
6275 case NEON_FRSQRTE_scalar:
6276 frsqrte(fpf, rd, rn);
6277 break;
6278 case NEON_FCMGT_zero_scalar:
6279 fcmp_zero(fpf, rd, rn, gt);
6280 break;
6281 case NEON_FCMGE_zero_scalar:
6282 fcmp_zero(fpf, rd, rn, ge);
6283 break;
6284 case NEON_FCMEQ_zero_scalar:
6285 fcmp_zero(fpf, rd, rn, eq);
6286 break;
6287 case NEON_FCMLE_zero_scalar:
6288 fcmp_zero(fpf, rd, rn, le);
6289 break;
6290 case NEON_FCMLT_zero_scalar:
6291 fcmp_zero(fpf, rd, rn, lt);
6292 break;
6293 case NEON_SCVTF_scalar:
6294 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6295 break;
6296 case NEON_UCVTF_scalar:
6297 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6298 break;
6299 case NEON_FCVTNS_scalar:
6300 fcvts(fpf, rd, rn, FPTieEven);
6301 break;
6302 case NEON_FCVTNU_scalar:
6303 fcvtu(fpf, rd, rn, FPTieEven);
6304 break;
6305 case NEON_FCVTPS_scalar:
6306 fcvts(fpf, rd, rn, FPPositiveInfinity);
6307 break;
6308 case NEON_FCVTPU_scalar:
6309 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6310 break;
6311 case NEON_FCVTMS_scalar:
6312 fcvts(fpf, rd, rn, FPNegativeInfinity);
6313 break;
6314 case NEON_FCVTMU_scalar:
6315 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6316 break;
6317 case NEON_FCVTZS_scalar:
6318 fcvts(fpf, rd, rn, FPZero);
6319 break;
6320 case NEON_FCVTZU_scalar:
6321 fcvtu(fpf, rd, rn, FPZero);
6322 break;
6323 case NEON_FCVTAS_scalar:
6324 fcvts(fpf, rd, rn, FPTieAway);
6325 break;
6326 case NEON_FCVTAU_scalar:
6327 fcvtu(fpf, rd, rn, FPTieAway);
6328 break;
6329 case NEON_FCVTXN_scalar:
6330 // Unlike all of the other FP instructions above, fcvtxn encodes dest
6331 // size S as size<0>=1. There's only one case, so we ignore the form.
6332 VIXL_ASSERT(instr->ExtractBit(22) == 1);
6333 fcvtxn(kFormatS, rd, rn);
6334 break;
6335 default:
6336 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6337 case NEON_SQXTN_scalar:
6338 sqxtn(vf, rd, rn);
6339 break;
6340 case NEON_UQXTN_scalar:
6341 uqxtn(vf, rd, rn);
6342 break;
6343 case NEON_SQXTUN_scalar:
6344 sqxtun(vf, rd, rn);
6345 break;
6346 default:
6347 VIXL_UNIMPLEMENTED();
6348 }
6349 }
6350 }
6351}
6352
6353
Jacob Bramleyca789742018-09-13 14:25:46 +01006354void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
6355 VectorFormat fpf = kFormatH;
6356 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6357
6358 SimVRegister& rd = ReadVRegister(instr->GetRd());
6359 SimVRegister& rn = ReadVRegister(instr->GetRn());
6360
6361 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6362 case NEON_FRECPE_H_scalar:
6363 frecpe(fpf, rd, rn, fpcr_rounding);
6364 break;
6365 case NEON_FRECPX_H_scalar:
6366 frecpx(fpf, rd, rn);
6367 break;
6368 case NEON_FRSQRTE_H_scalar:
6369 frsqrte(fpf, rd, rn);
6370 break;
6371 case NEON_FCMGT_H_zero_scalar:
6372 fcmp_zero(fpf, rd, rn, gt);
6373 break;
6374 case NEON_FCMGE_H_zero_scalar:
6375 fcmp_zero(fpf, rd, rn, ge);
6376 break;
6377 case NEON_FCMEQ_H_zero_scalar:
6378 fcmp_zero(fpf, rd, rn, eq);
6379 break;
6380 case NEON_FCMLE_H_zero_scalar:
6381 fcmp_zero(fpf, rd, rn, le);
6382 break;
6383 case NEON_FCMLT_H_zero_scalar:
6384 fcmp_zero(fpf, rd, rn, lt);
6385 break;
6386 case NEON_SCVTF_H_scalar:
6387 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6388 break;
6389 case NEON_UCVTF_H_scalar:
6390 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6391 break;
6392 case NEON_FCVTNS_H_scalar:
6393 fcvts(fpf, rd, rn, FPTieEven);
6394 break;
6395 case NEON_FCVTNU_H_scalar:
6396 fcvtu(fpf, rd, rn, FPTieEven);
6397 break;
6398 case NEON_FCVTPS_H_scalar:
6399 fcvts(fpf, rd, rn, FPPositiveInfinity);
6400 break;
6401 case NEON_FCVTPU_H_scalar:
6402 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6403 break;
6404 case NEON_FCVTMS_H_scalar:
6405 fcvts(fpf, rd, rn, FPNegativeInfinity);
6406 break;
6407 case NEON_FCVTMU_H_scalar:
6408 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6409 break;
6410 case NEON_FCVTZS_H_scalar:
6411 fcvts(fpf, rd, rn, FPZero);
6412 break;
6413 case NEON_FCVTZU_H_scalar:
6414 fcvtu(fpf, rd, rn, FPZero);
6415 break;
6416 case NEON_FCVTAS_H_scalar:
6417 fcvts(fpf, rd, rn, FPTieAway);
6418 break;
6419 case NEON_FCVTAU_H_scalar:
6420 fcvtu(fpf, rd, rn, FPTieAway);
6421 break;
6422 }
6423}
6424
6425
Alexandre Ramesd3832962016-07-04 15:03:43 +01006426void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6427 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6428 VectorFormat vf = nfd.GetVectorFormat();
6429
6430 SimVRegister& rd = ReadVRegister(instr->GetRd());
6431 SimVRegister& rn = ReadVRegister(instr->GetRn());
6432 SimVRegister& rm = ReadVRegister(instr->GetRm());
6433 switch (instr->Mask(NEONScalar3DiffMask)) {
6434 case NEON_SQDMLAL_scalar:
6435 sqdmlal(vf, rd, rn, rm);
6436 break;
6437 case NEON_SQDMLSL_scalar:
6438 sqdmlsl(vf, rd, rn, rm);
6439 break;
6440 case NEON_SQDMULL_scalar:
6441 sqdmull(vf, rd, rn, rm);
6442 break;
6443 default:
6444 VIXL_UNIMPLEMENTED();
6445 }
6446}
6447
6448
6449void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6450 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6451 VectorFormat vf = nfd.GetVectorFormat();
6452
6453 SimVRegister& rd = ReadVRegister(instr->GetRd());
6454 SimVRegister& rn = ReadVRegister(instr->GetRn());
6455 SimVRegister& rm = ReadVRegister(instr->GetRm());
6456
6457 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6458 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6459 switch (instr->Mask(NEONScalar3SameFPMask)) {
6460 case NEON_FMULX_scalar:
6461 fmulx(vf, rd, rn, rm);
6462 break;
6463 case NEON_FACGE_scalar:
6464 fabscmp(vf, rd, rn, rm, ge);
6465 break;
6466 case NEON_FACGT_scalar:
6467 fabscmp(vf, rd, rn, rm, gt);
6468 break;
6469 case NEON_FCMEQ_scalar:
6470 fcmp(vf, rd, rn, rm, eq);
6471 break;
6472 case NEON_FCMGE_scalar:
6473 fcmp(vf, rd, rn, rm, ge);
6474 break;
6475 case NEON_FCMGT_scalar:
6476 fcmp(vf, rd, rn, rm, gt);
6477 break;
6478 case NEON_FRECPS_scalar:
6479 frecps(vf, rd, rn, rm);
6480 break;
6481 case NEON_FRSQRTS_scalar:
6482 frsqrts(vf, rd, rn, rm);
6483 break;
6484 case NEON_FABD_scalar:
6485 fabd(vf, rd, rn, rm);
6486 break;
6487 default:
6488 VIXL_UNIMPLEMENTED();
6489 }
6490 } else {
6491 switch (instr->Mask(NEONScalar3SameMask)) {
6492 case NEON_ADD_scalar:
6493 add(vf, rd, rn, rm);
6494 break;
6495 case NEON_SUB_scalar:
6496 sub(vf, rd, rn, rm);
6497 break;
6498 case NEON_CMEQ_scalar:
6499 cmp(vf, rd, rn, rm, eq);
6500 break;
6501 case NEON_CMGE_scalar:
6502 cmp(vf, rd, rn, rm, ge);
6503 break;
6504 case NEON_CMGT_scalar:
6505 cmp(vf, rd, rn, rm, gt);
6506 break;
6507 case NEON_CMHI_scalar:
6508 cmp(vf, rd, rn, rm, hi);
6509 break;
6510 case NEON_CMHS_scalar:
6511 cmp(vf, rd, rn, rm, hs);
6512 break;
6513 case NEON_CMTST_scalar:
6514 cmptst(vf, rd, rn, rm);
6515 break;
6516 case NEON_USHL_scalar:
6517 ushl(vf, rd, rn, rm);
6518 break;
6519 case NEON_SSHL_scalar:
6520 sshl(vf, rd, rn, rm);
6521 break;
6522 case NEON_SQDMULH_scalar:
6523 sqdmulh(vf, rd, rn, rm);
6524 break;
6525 case NEON_SQRDMULH_scalar:
6526 sqrdmulh(vf, rd, rn, rm);
6527 break;
6528 case NEON_UQADD_scalar:
6529 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6530 break;
6531 case NEON_SQADD_scalar:
6532 add(vf, rd, rn, rm).SignedSaturate(vf);
6533 break;
6534 case NEON_UQSUB_scalar:
6535 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6536 break;
6537 case NEON_SQSUB_scalar:
6538 sub(vf, rd, rn, rm).SignedSaturate(vf);
6539 break;
6540 case NEON_UQSHL_scalar:
6541 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6542 break;
6543 case NEON_SQSHL_scalar:
6544 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6545 break;
6546 case NEON_URSHL_scalar:
6547 ushl(vf, rd, rn, rm).Round(vf);
6548 break;
6549 case NEON_SRSHL_scalar:
6550 sshl(vf, rd, rn, rm).Round(vf);
6551 break;
6552 case NEON_UQRSHL_scalar:
6553 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6554 break;
6555 case NEON_SQRSHL_scalar:
6556 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6557 break;
6558 default:
6559 VIXL_UNIMPLEMENTED();
6560 }
6561 }
6562}
6563
Jacob Bramleyca789742018-09-13 14:25:46 +01006564void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6565 SimVRegister& rd = ReadVRegister(instr->GetRd());
6566 SimVRegister& rn = ReadVRegister(instr->GetRn());
6567 SimVRegister& rm = ReadVRegister(instr->GetRm());
6568
6569 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6570 case NEON_FABD_H_scalar:
6571 fabd(kFormatH, rd, rn, rm);
6572 break;
6573 case NEON_FMULX_H_scalar:
6574 fmulx(kFormatH, rd, rn, rm);
6575 break;
6576 case NEON_FCMEQ_H_scalar:
6577 fcmp(kFormatH, rd, rn, rm, eq);
6578 break;
6579 case NEON_FCMGE_H_scalar:
6580 fcmp(kFormatH, rd, rn, rm, ge);
6581 break;
6582 case NEON_FCMGT_H_scalar:
6583 fcmp(kFormatH, rd, rn, rm, gt);
6584 break;
6585 case NEON_FACGE_H_scalar:
6586 fabscmp(kFormatH, rd, rn, rm, ge);
6587 break;
6588 case NEON_FACGT_H_scalar:
6589 fabscmp(kFormatH, rd, rn, rm, gt);
6590 break;
6591 case NEON_FRECPS_H_scalar:
6592 frecps(kFormatH, rd, rn, rm);
6593 break;
6594 case NEON_FRSQRTS_H_scalar:
6595 frsqrts(kFormatH, rd, rn, rm);
6596 break;
6597 default:
6598 VIXL_UNREACHABLE();
6599 }
6600}
6601
Alexandre Ramesd3832962016-07-04 15:03:43 +01006602
Alexander Gilday43785642018-04-04 13:42:33 +01006603void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6604 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6605 VectorFormat vf = nfd.GetVectorFormat();
6606
6607 SimVRegister& rd = ReadVRegister(instr->GetRd());
6608 SimVRegister& rn = ReadVRegister(instr->GetRn());
6609 SimVRegister& rm = ReadVRegister(instr->GetRm());
6610
6611 switch (instr->Mask(NEONScalar3SameExtraMask)) {
6612 case NEON_SQRDMLAH_scalar:
6613 sqrdmlah(vf, rd, rn, rm);
6614 break;
6615 case NEON_SQRDMLSH_scalar:
6616 sqrdmlsh(vf, rd, rn, rm);
6617 break;
6618 default:
6619 VIXL_UNIMPLEMENTED();
6620 }
6621}
6622
Alexandre Ramesd3832962016-07-04 15:03:43 +01006623void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6624 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6625 VectorFormat vf = nfd.GetVectorFormat();
6626 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6627
6628 SimVRegister& rd = ReadVRegister(instr->GetRd());
6629 SimVRegister& rn = ReadVRegister(instr->GetRn());
6630 ByElementOp Op = NULL;
6631
6632 int rm_reg = instr->GetRm();
6633 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6634 if (instr->GetNEONSize() == 1) {
6635 rm_reg &= 0xf;
6636 index = (index << 1) | instr->GetNEONM();
6637 }
6638
6639 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6640 case NEON_SQDMULL_byelement_scalar:
6641 Op = &Simulator::sqdmull;
6642 break;
6643 case NEON_SQDMLAL_byelement_scalar:
6644 Op = &Simulator::sqdmlal;
6645 break;
6646 case NEON_SQDMLSL_byelement_scalar:
6647 Op = &Simulator::sqdmlsl;
6648 break;
6649 case NEON_SQDMULH_byelement_scalar:
6650 Op = &Simulator::sqdmulh;
6651 vf = vf_r;
6652 break;
6653 case NEON_SQRDMULH_byelement_scalar:
6654 Op = &Simulator::sqrdmulh;
6655 vf = vf_r;
6656 break;
Alexander Gilday43785642018-04-04 13:42:33 +01006657 case NEON_SQRDMLAH_byelement_scalar:
6658 Op = &Simulator::sqrdmlah;
6659 vf = vf_r;
6660 break;
6661 case NEON_SQRDMLSH_byelement_scalar:
6662 Op = &Simulator::sqrdmlsh;
6663 vf = vf_r;
6664 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006665 default:
6666 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6667 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01006668 if (instr->GetFPType() == 0) {
6669 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6670 rm_reg &= 0xf;
6671 vf = kFormatH;
6672 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006673 index = (index << 1) | instr->GetNEONL();
6674 }
6675 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006676 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006677 case NEON_FMUL_byelement_scalar:
6678 Op = &Simulator::fmul;
6679 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006680 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006681 case NEON_FMLA_byelement_scalar:
6682 Op = &Simulator::fmla;
6683 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006684 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006685 case NEON_FMLS_byelement_scalar:
6686 Op = &Simulator::fmls;
6687 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006688 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006689 case NEON_FMULX_byelement_scalar:
6690 Op = &Simulator::fmulx;
6691 break;
6692 default:
6693 VIXL_UNIMPLEMENTED();
6694 }
6695 }
6696
6697 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6698}
6699
6700
6701void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6702 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6703 VectorFormat vf = nfd.GetVectorFormat();
6704
6705 SimVRegister& rd = ReadVRegister(instr->GetRd());
6706 SimVRegister& rn = ReadVRegister(instr->GetRn());
6707
6708 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6709 int imm5 = instr->GetImmNEON5();
6710 int tz = CountTrailingZeros(imm5, 32);
6711 int rn_index = imm5 >> (tz + 1);
6712 dup_element(vf, rd, rn, rn_index);
6713 } else {
6714 VIXL_UNIMPLEMENTED();
6715 }
6716}
6717
6718
6719void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006720 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006721 VectorFormat vf = nfd.GetVectorFormat();
6722
6723 SimVRegister& rd = ReadVRegister(instr->GetRd());
6724 SimVRegister& rn = ReadVRegister(instr->GetRn());
6725 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006726 case NEON_ADDP_scalar: {
6727 // All pairwise operations except ADDP use bit U to differentiate FP16
6728 // from FP32/FP64 variations.
6729 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6730 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006731 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006732 }
6733 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006734 case NEON_FADDP_scalar:
6735 faddp(vf, rd, rn);
6736 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006737 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006738 case NEON_FMAXP_scalar:
6739 fmaxp(vf, rd, rn);
6740 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006741 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006742 case NEON_FMAXNMP_scalar:
6743 fmaxnmp(vf, rd, rn);
6744 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006745 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006746 case NEON_FMINP_scalar:
6747 fminp(vf, rd, rn);
6748 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006749 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006750 case NEON_FMINNMP_scalar:
6751 fminnmp(vf, rd, rn);
6752 break;
6753 default:
6754 VIXL_UNIMPLEMENTED();
6755 }
6756}
6757
6758
6759void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6760 SimVRegister& rd = ReadVRegister(instr->GetRd());
6761 SimVRegister& rn = ReadVRegister(instr->GetRn());
6762 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6763
6764 static const NEONFormatMap map = {{22, 21, 20, 19},
6765 {NF_UNDEF,
6766 NF_B,
6767 NF_H,
6768 NF_H,
6769 NF_S,
6770 NF_S,
6771 NF_S,
6772 NF_S,
6773 NF_D,
6774 NF_D,
6775 NF_D,
6776 NF_D,
6777 NF_D,
6778 NF_D,
6779 NF_D,
6780 NF_D}};
6781 NEONFormatDecoder nfd(instr, &map);
6782 VectorFormat vf = nfd.GetVectorFormat();
6783
6784 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6785 int immhimmb = instr->GetImmNEONImmhImmb();
6786 int right_shift = (16 << highestSetBit) - immhimmb;
6787 int left_shift = immhimmb - (8 << highestSetBit);
6788 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
6789 case NEON_SHL_scalar:
6790 shl(vf, rd, rn, left_shift);
6791 break;
6792 case NEON_SLI_scalar:
6793 sli(vf, rd, rn, left_shift);
6794 break;
6795 case NEON_SQSHL_imm_scalar:
6796 sqshl(vf, rd, rn, left_shift);
6797 break;
6798 case NEON_UQSHL_imm_scalar:
6799 uqshl(vf, rd, rn, left_shift);
6800 break;
6801 case NEON_SQSHLU_scalar:
6802 sqshlu(vf, rd, rn, left_shift);
6803 break;
6804 case NEON_SRI_scalar:
6805 sri(vf, rd, rn, right_shift);
6806 break;
6807 case NEON_SSHR_scalar:
6808 sshr(vf, rd, rn, right_shift);
6809 break;
6810 case NEON_USHR_scalar:
6811 ushr(vf, rd, rn, right_shift);
6812 break;
6813 case NEON_SRSHR_scalar:
6814 sshr(vf, rd, rn, right_shift).Round(vf);
6815 break;
6816 case NEON_URSHR_scalar:
6817 ushr(vf, rd, rn, right_shift).Round(vf);
6818 break;
6819 case NEON_SSRA_scalar:
6820 ssra(vf, rd, rn, right_shift);
6821 break;
6822 case NEON_USRA_scalar:
6823 usra(vf, rd, rn, right_shift);
6824 break;
6825 case NEON_SRSRA_scalar:
6826 srsra(vf, rd, rn, right_shift);
6827 break;
6828 case NEON_URSRA_scalar:
6829 ursra(vf, rd, rn, right_shift);
6830 break;
6831 case NEON_UQSHRN_scalar:
6832 uqshrn(vf, rd, rn, right_shift);
6833 break;
6834 case NEON_UQRSHRN_scalar:
6835 uqrshrn(vf, rd, rn, right_shift);
6836 break;
6837 case NEON_SQSHRN_scalar:
6838 sqshrn(vf, rd, rn, right_shift);
6839 break;
6840 case NEON_SQRSHRN_scalar:
6841 sqrshrn(vf, rd, rn, right_shift);
6842 break;
6843 case NEON_SQSHRUN_scalar:
6844 sqshrun(vf, rd, rn, right_shift);
6845 break;
6846 case NEON_SQRSHRUN_scalar:
6847 sqrshrun(vf, rd, rn, right_shift);
6848 break;
6849 case NEON_FCVTZS_imm_scalar:
6850 fcvts(vf, rd, rn, FPZero, right_shift);
6851 break;
6852 case NEON_FCVTZU_imm_scalar:
6853 fcvtu(vf, rd, rn, FPZero, right_shift);
6854 break;
6855 case NEON_SCVTF_imm_scalar:
6856 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6857 break;
6858 case NEON_UCVTF_imm_scalar:
6859 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6860 break;
6861 default:
6862 VIXL_UNIMPLEMENTED();
6863 }
6864}
6865
6866
6867void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
6868 SimVRegister& rd = ReadVRegister(instr->GetRd());
6869 SimVRegister& rn = ReadVRegister(instr->GetRn());
6870 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6871
6872 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
6873 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
6874 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01006875 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
6876 NF_4H, NF_8H, NF_4H, NF_8H,
6877 NF_2S, NF_4S, NF_2S, NF_4S,
6878 NF_2S, NF_4S, NF_2S, NF_4S,
6879 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6880 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6881 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6882 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01006883 NEONFormatDecoder nfd(instr, &map);
6884 VectorFormat vf = nfd.GetVectorFormat();
6885
6886 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
6887 static const NEONFormatMap map_l =
6888 {{22, 21, 20, 19},
6889 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
6890 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
6891
6892 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6893 int immhimmb = instr->GetImmNEONImmhImmb();
6894 int right_shift = (16 << highestSetBit) - immhimmb;
6895 int left_shift = immhimmb - (8 << highestSetBit);
6896
6897 switch (instr->Mask(NEONShiftImmediateMask)) {
6898 case NEON_SHL:
6899 shl(vf, rd, rn, left_shift);
6900 break;
6901 case NEON_SLI:
6902 sli(vf, rd, rn, left_shift);
6903 break;
6904 case NEON_SQSHLU:
6905 sqshlu(vf, rd, rn, left_shift);
6906 break;
6907 case NEON_SRI:
6908 sri(vf, rd, rn, right_shift);
6909 break;
6910 case NEON_SSHR:
6911 sshr(vf, rd, rn, right_shift);
6912 break;
6913 case NEON_USHR:
6914 ushr(vf, rd, rn, right_shift);
6915 break;
6916 case NEON_SRSHR:
6917 sshr(vf, rd, rn, right_shift).Round(vf);
6918 break;
6919 case NEON_URSHR:
6920 ushr(vf, rd, rn, right_shift).Round(vf);
6921 break;
6922 case NEON_SSRA:
6923 ssra(vf, rd, rn, right_shift);
6924 break;
6925 case NEON_USRA:
6926 usra(vf, rd, rn, right_shift);
6927 break;
6928 case NEON_SRSRA:
6929 srsra(vf, rd, rn, right_shift);
6930 break;
6931 case NEON_URSRA:
6932 ursra(vf, rd, rn, right_shift);
6933 break;
6934 case NEON_SQSHL_imm:
6935 sqshl(vf, rd, rn, left_shift);
6936 break;
6937 case NEON_UQSHL_imm:
6938 uqshl(vf, rd, rn, left_shift);
6939 break;
6940 case NEON_SCVTF_imm:
6941 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6942 break;
6943 case NEON_UCVTF_imm:
6944 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6945 break;
6946 case NEON_FCVTZS_imm:
6947 fcvts(vf, rd, rn, FPZero, right_shift);
6948 break;
6949 case NEON_FCVTZU_imm:
6950 fcvtu(vf, rd, rn, FPZero, right_shift);
6951 break;
6952 case NEON_SSHLL:
6953 vf = vf_l;
6954 if (instr->Mask(NEON_Q)) {
6955 sshll2(vf, rd, rn, left_shift);
6956 } else {
6957 sshll(vf, rd, rn, left_shift);
6958 }
6959 break;
6960 case NEON_USHLL:
6961 vf = vf_l;
6962 if (instr->Mask(NEON_Q)) {
6963 ushll2(vf, rd, rn, left_shift);
6964 } else {
6965 ushll(vf, rd, rn, left_shift);
6966 }
6967 break;
6968 case NEON_SHRN:
6969 if (instr->Mask(NEON_Q)) {
6970 shrn2(vf, rd, rn, right_shift);
6971 } else {
6972 shrn(vf, rd, rn, right_shift);
6973 }
6974 break;
6975 case NEON_RSHRN:
6976 if (instr->Mask(NEON_Q)) {
6977 rshrn2(vf, rd, rn, right_shift);
6978 } else {
6979 rshrn(vf, rd, rn, right_shift);
6980 }
6981 break;
6982 case NEON_UQSHRN:
6983 if (instr->Mask(NEON_Q)) {
6984 uqshrn2(vf, rd, rn, right_shift);
6985 } else {
6986 uqshrn(vf, rd, rn, right_shift);
6987 }
6988 break;
6989 case NEON_UQRSHRN:
6990 if (instr->Mask(NEON_Q)) {
6991 uqrshrn2(vf, rd, rn, right_shift);
6992 } else {
6993 uqrshrn(vf, rd, rn, right_shift);
6994 }
6995 break;
6996 case NEON_SQSHRN:
6997 if (instr->Mask(NEON_Q)) {
6998 sqshrn2(vf, rd, rn, right_shift);
6999 } else {
7000 sqshrn(vf, rd, rn, right_shift);
7001 }
7002 break;
7003 case NEON_SQRSHRN:
7004 if (instr->Mask(NEON_Q)) {
7005 sqrshrn2(vf, rd, rn, right_shift);
7006 } else {
7007 sqrshrn(vf, rd, rn, right_shift);
7008 }
7009 break;
7010 case NEON_SQSHRUN:
7011 if (instr->Mask(NEON_Q)) {
7012 sqshrun2(vf, rd, rn, right_shift);
7013 } else {
7014 sqshrun(vf, rd, rn, right_shift);
7015 }
7016 break;
7017 case NEON_SQRSHRUN:
7018 if (instr->Mask(NEON_Q)) {
7019 sqrshrun2(vf, rd, rn, right_shift);
7020 } else {
7021 sqrshrun(vf, rd, rn, right_shift);
7022 }
7023 break;
7024 default:
7025 VIXL_UNIMPLEMENTED();
7026 }
7027}
7028
7029
7030void Simulator::VisitNEONTable(const Instruction* instr) {
7031 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7032 VectorFormat vf = nfd.GetVectorFormat();
7033
7034 SimVRegister& rd = ReadVRegister(instr->GetRd());
7035 SimVRegister& rn = ReadVRegister(instr->GetRn());
7036 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
7037 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
7038 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
7039 SimVRegister& rm = ReadVRegister(instr->GetRm());
7040
7041 switch (instr->Mask(NEONTableMask)) {
7042 case NEON_TBL_1v:
7043 tbl(vf, rd, rn, rm);
7044 break;
7045 case NEON_TBL_2v:
7046 tbl(vf, rd, rn, rn2, rm);
7047 break;
7048 case NEON_TBL_3v:
7049 tbl(vf, rd, rn, rn2, rn3, rm);
7050 break;
7051 case NEON_TBL_4v:
7052 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
7053 break;
7054 case NEON_TBX_1v:
7055 tbx(vf, rd, rn, rm);
7056 break;
7057 case NEON_TBX_2v:
7058 tbx(vf, rd, rn, rn2, rm);
7059 break;
7060 case NEON_TBX_3v:
7061 tbx(vf, rd, rn, rn2, rn3, rm);
7062 break;
7063 case NEON_TBX_4v:
7064 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
7065 break;
7066 default:
7067 VIXL_UNIMPLEMENTED();
7068 }
7069}
7070
7071
7072void Simulator::VisitNEONPerm(const Instruction* instr) {
7073 NEONFormatDecoder nfd(instr);
7074 VectorFormat vf = nfd.GetVectorFormat();
7075
7076 SimVRegister& rd = ReadVRegister(instr->GetRd());
7077 SimVRegister& rn = ReadVRegister(instr->GetRn());
7078 SimVRegister& rm = ReadVRegister(instr->GetRm());
7079
7080 switch (instr->Mask(NEONPermMask)) {
7081 case NEON_TRN1:
7082 trn1(vf, rd, rn, rm);
7083 break;
7084 case NEON_TRN2:
7085 trn2(vf, rd, rn, rm);
7086 break;
7087 case NEON_UZP1:
7088 uzp1(vf, rd, rn, rm);
7089 break;
7090 case NEON_UZP2:
7091 uzp2(vf, rd, rn, rm);
7092 break;
7093 case NEON_ZIP1:
7094 zip1(vf, rd, rn, rm);
7095 break;
7096 case NEON_ZIP2:
7097 zip2(vf, rd, rn, rm);
7098 break;
7099 default:
7100 VIXL_UNIMPLEMENTED();
7101 }
7102}
7103
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007104void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
7105 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007106 switch (instr->Mask(SVEAddressGenerationMask)) {
7107 case ADR_z_az_d_s32_scaled:
7108 VIXL_UNIMPLEMENTED();
7109 break;
7110 case ADR_z_az_d_u32_scaled:
7111 VIXL_UNIMPLEMENTED();
7112 break;
7113 case ADR_z_az_sd_same_scaled:
7114 VIXL_UNIMPLEMENTED();
7115 break;
7116 default:
7117 VIXL_UNIMPLEMENTED();
7118 break;
7119 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007120}
7121
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007122void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
7123 const Instruction* instr) {
7124 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07007125 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007126 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007127 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07007128 case ORR_z_zi: {
7129 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7130 uint64_t imm = instr->GetSVEImmLogical();
7131 // Valid immediate is a non-zero bits
7132 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007133 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
7134 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07007135 SVEFormatFromLaneSizeInBytesLog2(lane_size),
7136 ReadVRegister(instr->GetRd()),
7137 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007138 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07007139 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007140 default:
7141 VIXL_UNIMPLEMENTED();
7142 break;
7143 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007144}
7145
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007146void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
7147 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
7148 case DUPM_z_i: {
7149 /* DUPM uses the same lane size and immediate encoding as bitwise logical
7150 * immediate instructions. */
7151 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7152 uint64_t imm = instr->GetSVEImmLogical();
7153 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7154 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
7155 break;
7156 }
7157 default:
7158 VIXL_UNIMPLEMENTED();
7159 break;
7160 }
7161}
7162
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007163void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
7164 USE(instr);
TatWai Chongcfb94212019-05-16 13:30:09 -07007165 SimVRegister& zd = ReadVRegister(instr->GetRd());
7166 SimVRegister& zn = ReadVRegister(instr->GetRn());
7167 SimVRegister& zm = ReadVRegister(instr->GetRm());
7168 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
7169
TatWai Chong13634762019-07-16 16:20:45 -07007170 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07007171 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007172 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007173 logical_op = AND;
7174 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007175 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007176 logical_op = BIC;
7177 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007178 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007179 logical_op = EOR;
7180 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07007181 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007182 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007183 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007184 default:
TatWai Chong13634762019-07-16 16:20:45 -07007185 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007186 VIXL_UNIMPLEMENTED();
7187 break;
7188 }
TatWai Chong13634762019-07-16 16:20:45 -07007189 // Lane size of registers is irrelevant to the bitwise operations, so perform
7190 // the operation on D-sized lanes.
7191 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007192}
7193
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007194void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007195 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007196 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007197 case ASRD_z_p_zi:
7198 VIXL_UNIMPLEMENTED();
7199 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007200 case ASR_z_p_zi:
7201 VIXL_UNIMPLEMENTED();
7202 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007203 case LSL_z_p_zi:
7204 VIXL_UNIMPLEMENTED();
7205 break;
7206 case LSR_z_p_zi:
7207 VIXL_UNIMPLEMENTED();
7208 break;
7209 default:
7210 VIXL_UNIMPLEMENTED();
7211 break;
7212 }
7213}
7214
7215void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
7216 const Instruction* instr) {
7217 USE(instr);
7218 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
7219 case ASRR_z_p_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007220 VIXL_UNIMPLEMENTED();
7221 break;
7222 case ASR_z_p_zz:
7223 VIXL_UNIMPLEMENTED();
7224 break;
7225 case LSLR_z_p_zz:
7226 VIXL_UNIMPLEMENTED();
7227 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007228 case LSL_z_p_zz:
7229 VIXL_UNIMPLEMENTED();
7230 break;
7231 case LSRR_z_p_zz:
7232 VIXL_UNIMPLEMENTED();
7233 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007234 case LSR_z_p_zz:
7235 VIXL_UNIMPLEMENTED();
7236 break;
7237 default:
7238 VIXL_UNIMPLEMENTED();
7239 break;
7240 }
7241}
7242
7243void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
7244 const Instruction* instr) {
7245 USE(instr);
7246 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
7247 case ASR_z_p_zw:
7248 VIXL_UNIMPLEMENTED();
7249 break;
7250 case LSL_z_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007251 VIXL_UNIMPLEMENTED();
7252 break;
7253 case LSR_z_p_zw:
7254 VIXL_UNIMPLEMENTED();
7255 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007256 default:
7257 VIXL_UNIMPLEMENTED();
7258 break;
7259 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007260}
7261
7262void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
7263 USE(instr);
TatWai Chong29a0c432019-11-06 22:20:44 -08007264
7265 SimVRegister& zd = ReadVRegister(instr->GetRd());
7266 SimVRegister& zn = ReadVRegister(instr->GetRn());
7267
7268 Shift shift_op;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007269 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7270 case ASR_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007271 case ASR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007272 shift_op = ASR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007273 break;
7274 case LSL_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007275 case LSL_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007276 shift_op = LSL;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007277 break;
7278 case LSR_z_zi:
TatWai Chong29a0c432019-11-06 22:20:44 -08007279 case LSR_z_zw:
7280 shift_op = LSR;
7281 break;
7282 default:
7283 shift_op = NO_SHIFT;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007284 VIXL_UNIMPLEMENTED();
7285 break;
TatWai Chong29a0c432019-11-06 22:20:44 -08007286 }
7287
7288 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7289 case ASR_z_zi:
7290 case LSL_z_zi:
7291 case LSR_z_zi: {
7292 SimVRegister scratch;
7293 std::pair<int, int> shift_and_lane_size =
7294 instr->GetSVEImmShiftAndLaneSizeLog2();
7295 unsigned lane_size = shift_and_lane_size.second;
7296 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
7297 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7298 dup_immediate(vform, scratch, shift_and_lane_size.first);
7299 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
7300 break;
7301 }
7302 case ASR_z_zw:
7303 case LSL_z_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007304 case LSR_z_zw:
TatWai Chong29a0c432019-11-06 22:20:44 -08007305 SVEBitwiseShiftHelper(shift_op,
7306 instr->GetSVEVectorFormat(),
7307 zd,
7308 zn,
7309 ReadVRegister(instr->GetRm()),
7310 true);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007311 break;
7312 default:
7313 VIXL_UNIMPLEMENTED();
7314 break;
7315 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007316}
7317
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007318void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00007319 // Although the instructions have a separate encoding class, the lane size is
7320 // encoded in the same way as most other SVE instructions.
7321 VectorFormat vform = instr->GetSVEVectorFormat();
7322
7323 int pattern = instr->GetImmSVEPredicateConstraint();
7324 int count = GetPredicateConstraintLaneCount(vform, pattern);
7325 int multiplier = instr->ExtractBits(19, 16) + 1;
7326
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007327 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007328 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007329 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007330 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007331 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007332 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007333 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007334 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007335 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007336 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007337 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007338 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007339 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007340 default:
7341 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00007342 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007343 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00007344
7345 WriteXRegister(instr->GetRd(),
7346 IncDecN(ReadXRegister(instr->GetRd()),
7347 count * multiplier,
7348 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007349}
7350
7351void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
7352 USE(instr);
7353 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
7354 case DECD_z_zs:
7355 VIXL_UNIMPLEMENTED();
7356 break;
7357 case DECH_z_zs:
7358 VIXL_UNIMPLEMENTED();
7359 break;
7360 case DECW_z_zs:
7361 VIXL_UNIMPLEMENTED();
7362 break;
7363 case INCD_z_zs:
7364 VIXL_UNIMPLEMENTED();
7365 break;
7366 case INCH_z_zs:
7367 VIXL_UNIMPLEMENTED();
7368 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007369 case INCW_z_zs:
7370 VIXL_UNIMPLEMENTED();
7371 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007372 default:
7373 VIXL_UNIMPLEMENTED();
7374 break;
7375 }
7376}
7377
7378void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
7379 const Instruction* instr) {
7380 USE(instr);
7381 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007382 case SQDECB_r_rs_sx:
7383 VIXL_UNIMPLEMENTED();
7384 break;
7385 case SQDECB_r_rs_x:
7386 VIXL_UNIMPLEMENTED();
7387 break;
7388 case SQDECD_r_rs_sx:
7389 VIXL_UNIMPLEMENTED();
7390 break;
7391 case SQDECD_r_rs_x:
7392 VIXL_UNIMPLEMENTED();
7393 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007394 case SQDECH_r_rs_sx:
7395 VIXL_UNIMPLEMENTED();
7396 break;
7397 case SQDECH_r_rs_x:
7398 VIXL_UNIMPLEMENTED();
7399 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007400 case SQDECW_r_rs_sx:
7401 VIXL_UNIMPLEMENTED();
7402 break;
7403 case SQDECW_r_rs_x:
7404 VIXL_UNIMPLEMENTED();
7405 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007406 case SQINCB_r_rs_sx:
7407 VIXL_UNIMPLEMENTED();
7408 break;
7409 case SQINCB_r_rs_x:
7410 VIXL_UNIMPLEMENTED();
7411 break;
7412 case SQINCD_r_rs_sx:
7413 VIXL_UNIMPLEMENTED();
7414 break;
7415 case SQINCD_r_rs_x:
7416 VIXL_UNIMPLEMENTED();
7417 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007418 case SQINCH_r_rs_sx:
7419 VIXL_UNIMPLEMENTED();
7420 break;
7421 case SQINCH_r_rs_x:
7422 VIXL_UNIMPLEMENTED();
7423 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007424 case SQINCW_r_rs_sx:
7425 VIXL_UNIMPLEMENTED();
7426 break;
7427 case SQINCW_r_rs_x:
7428 VIXL_UNIMPLEMENTED();
7429 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007430 case UQDECB_r_rs_uw:
7431 VIXL_UNIMPLEMENTED();
7432 break;
7433 case UQDECB_r_rs_x:
7434 VIXL_UNIMPLEMENTED();
7435 break;
7436 case UQDECD_r_rs_uw:
7437 VIXL_UNIMPLEMENTED();
7438 break;
7439 case UQDECD_r_rs_x:
7440 VIXL_UNIMPLEMENTED();
7441 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007442 case UQDECH_r_rs_uw:
7443 VIXL_UNIMPLEMENTED();
7444 break;
7445 case UQDECH_r_rs_x:
7446 VIXL_UNIMPLEMENTED();
7447 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007448 case UQDECW_r_rs_uw:
7449 VIXL_UNIMPLEMENTED();
7450 break;
7451 case UQDECW_r_rs_x:
7452 VIXL_UNIMPLEMENTED();
7453 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007454 case UQINCB_r_rs_uw:
7455 VIXL_UNIMPLEMENTED();
7456 break;
7457 case UQINCB_r_rs_x:
7458 VIXL_UNIMPLEMENTED();
7459 break;
7460 case UQINCD_r_rs_uw:
7461 VIXL_UNIMPLEMENTED();
7462 break;
7463 case UQINCD_r_rs_x:
7464 VIXL_UNIMPLEMENTED();
7465 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007466 case UQINCH_r_rs_uw:
7467 VIXL_UNIMPLEMENTED();
7468 break;
7469 case UQINCH_r_rs_x:
7470 VIXL_UNIMPLEMENTED();
7471 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007472 case UQINCW_r_rs_uw:
7473 VIXL_UNIMPLEMENTED();
7474 break;
7475 case UQINCW_r_rs_x:
7476 VIXL_UNIMPLEMENTED();
7477 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007478 default:
7479 VIXL_UNIMPLEMENTED();
7480 break;
7481 }
7482}
7483
7484void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
7485 const Instruction* instr) {
7486 USE(instr);
7487 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7488 case SQDECD_z_zs:
7489 VIXL_UNIMPLEMENTED();
7490 break;
7491 case SQDECH_z_zs:
7492 VIXL_UNIMPLEMENTED();
7493 break;
7494 case SQDECW_z_zs:
7495 VIXL_UNIMPLEMENTED();
7496 break;
7497 case SQINCD_z_zs:
7498 VIXL_UNIMPLEMENTED();
7499 break;
7500 case SQINCH_z_zs:
7501 VIXL_UNIMPLEMENTED();
7502 break;
7503 case SQINCW_z_zs:
7504 VIXL_UNIMPLEMENTED();
7505 break;
7506 case UQDECD_z_zs:
7507 VIXL_UNIMPLEMENTED();
7508 break;
7509 case UQDECH_z_zs:
7510 VIXL_UNIMPLEMENTED();
7511 break;
7512 case UQDECW_z_zs:
7513 VIXL_UNIMPLEMENTED();
7514 break;
7515 case UQINCD_z_zs:
7516 VIXL_UNIMPLEMENTED();
7517 break;
7518 case UQINCH_z_zs:
7519 VIXL_UNIMPLEMENTED();
7520 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007521 case UQINCW_z_zs:
7522 VIXL_UNIMPLEMENTED();
7523 break;
7524 default:
7525 VIXL_UNIMPLEMENTED();
7526 break;
7527 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007528}
7529
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007530void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007531 switch (instr->Mask(SVEElementCountMask)) {
7532 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007533 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007534 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007535 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00007536 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007537 break;
7538 default:
7539 VIXL_UNIMPLEMENTED();
7540 break;
7541 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00007542
7543 // Although the instructions are separated, the lane size is encoded in the
7544 // same way as most other SVE instructions.
7545 VectorFormat vform = instr->GetSVEVectorFormat();
7546
7547 int pattern = instr->GetImmSVEPredicateConstraint();
7548 int count = GetPredicateConstraintLaneCount(vform, pattern);
7549 int multiplier = instr->ExtractBits(19, 16) + 1;
7550 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007551}
7552
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007553void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
7554 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007555 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7556 case FADDA_v_p_z:
7557 VIXL_UNIMPLEMENTED();
7558 break;
7559 default:
7560 VIXL_UNIMPLEMENTED();
7561 break;
7562 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007563}
7564
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007565void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007566 USE(instr);
TatWai Chongd316c5e2019-10-16 12:22:10 -07007567 VectorFormat vform = instr->GetSVEVectorFormat();
7568 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7569 SimVRegister& zm = ReadVRegister(instr->GetRn());
7570 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7571
7572 SimVRegister result;
7573
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007574 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007575 case FABD_z_p_zz:
7576 VIXL_UNIMPLEMENTED();
7577 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007578 case FADD_z_p_zz:
7579 VIXL_UNIMPLEMENTED();
7580 break;
7581 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007582 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007583 break;
7584 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007585 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007586 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007587 case FMAXNM_z_p_zz:
7588 VIXL_UNIMPLEMENTED();
7589 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007590 case FMAX_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007591 fmax(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007592 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007593 case FMINNM_z_p_zz:
7594 VIXL_UNIMPLEMENTED();
7595 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007596 case FMIN_z_p_zz:
TatWai Chong7a0d3672019-10-23 17:35:18 -07007597 fmin(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007598 break;
7599 case FMULX_z_p_zz:
7600 VIXL_UNIMPLEMENTED();
7601 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007602 case FMUL_z_p_zz:
7603 VIXL_UNIMPLEMENTED();
7604 break;
7605 case FSCALE_z_p_zz:
7606 VIXL_UNIMPLEMENTED();
7607 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007608 case FSUBR_z_p_zz:
7609 VIXL_UNIMPLEMENTED();
7610 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007611 case FSUB_z_p_zz:
7612 VIXL_UNIMPLEMENTED();
7613 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007614 default:
7615 VIXL_UNIMPLEMENTED();
7616 break;
7617 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07007618 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007619}
7620
7621void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
7622 const Instruction* instr) {
7623 USE(instr);
7624 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
7625 case FADD_z_p_zs:
7626 VIXL_UNIMPLEMENTED();
7627 break;
7628 case FMAXNM_z_p_zs:
7629 VIXL_UNIMPLEMENTED();
7630 break;
7631 case FMAX_z_p_zs:
7632 VIXL_UNIMPLEMENTED();
7633 break;
7634 case FMINNM_z_p_zs:
7635 VIXL_UNIMPLEMENTED();
7636 break;
7637 case FMIN_z_p_zs:
7638 VIXL_UNIMPLEMENTED();
7639 break;
7640 case FMUL_z_p_zs:
7641 VIXL_UNIMPLEMENTED();
7642 break;
7643 case FSUBR_z_p_zs:
7644 VIXL_UNIMPLEMENTED();
7645 break;
7646 case FSUB_z_p_zs:
7647 VIXL_UNIMPLEMENTED();
7648 break;
7649 default:
7650 VIXL_UNIMPLEMENTED();
7651 break;
7652 }
7653}
7654
7655void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
7656 USE(instr);
7657 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007658 case FTMAD_z_zzi:
7659 VIXL_UNIMPLEMENTED();
7660 break;
7661 default:
7662 VIXL_UNIMPLEMENTED();
7663 break;
7664 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007665}
7666
7667void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
7668 USE(instr);
TatWai Chongfe536042019-10-23 16:34:11 -07007669
7670 VectorFormat vform = instr->GetSVEVectorFormat();
7671 SimVRegister& zd = ReadVRegister(instr->GetRd());
7672 SimVRegister& zn = ReadVRegister(instr->GetRn());
7673 SimVRegister& zm = ReadVRegister(instr->GetRm());
7674
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007675 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7676 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007677 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007678 break;
7679 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007680 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007681 break;
7682 case FRECPS_z_zz:
7683 VIXL_UNIMPLEMENTED();
7684 break;
7685 case FRSQRTS_z_zz:
7686 VIXL_UNIMPLEMENTED();
7687 break;
7688 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007689 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007690 break;
7691 case FTSMUL_z_zz:
7692 VIXL_UNIMPLEMENTED();
7693 break;
7694 default:
7695 VIXL_UNIMPLEMENTED();
7696 break;
7697 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007698}
7699
7700void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
7701 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007702 switch (instr->Mask(SVEFPCompareVectorsMask)) {
7703 case FACGE_p_p_zz:
7704 VIXL_UNIMPLEMENTED();
7705 break;
7706 case FACGT_p_p_zz:
7707 VIXL_UNIMPLEMENTED();
7708 break;
7709 case FCMEQ_p_p_zz:
7710 VIXL_UNIMPLEMENTED();
7711 break;
7712 case FCMGE_p_p_zz:
7713 VIXL_UNIMPLEMENTED();
7714 break;
7715 case FCMGT_p_p_zz:
7716 VIXL_UNIMPLEMENTED();
7717 break;
7718 case FCMNE_p_p_zz:
7719 VIXL_UNIMPLEMENTED();
7720 break;
7721 case FCMUO_p_p_zz:
7722 VIXL_UNIMPLEMENTED();
7723 break;
7724 default:
7725 VIXL_UNIMPLEMENTED();
7726 break;
7727 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007728}
7729
7730void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
7731 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007732 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
7733 case FCMEQ_p_p_z0:
7734 VIXL_UNIMPLEMENTED();
7735 break;
7736 case FCMGE_p_p_z0:
7737 VIXL_UNIMPLEMENTED();
7738 break;
7739 case FCMGT_p_p_z0:
7740 VIXL_UNIMPLEMENTED();
7741 break;
7742 case FCMLE_p_p_z0:
7743 VIXL_UNIMPLEMENTED();
7744 break;
7745 case FCMLT_p_p_z0:
7746 VIXL_UNIMPLEMENTED();
7747 break;
7748 case FCMNE_p_p_z0:
7749 VIXL_UNIMPLEMENTED();
7750 break;
7751 default:
7752 VIXL_UNIMPLEMENTED();
7753 break;
7754 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007755}
7756
7757void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
7758 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007759 switch (instr->Mask(SVEFPComplexAdditionMask)) {
7760 case FCADD_z_p_zz:
7761 VIXL_UNIMPLEMENTED();
7762 break;
7763 default:
7764 VIXL_UNIMPLEMENTED();
7765 break;
7766 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007767}
7768
7769void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
7770 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007771 switch (instr->Mask(SVEFPComplexMulAddMask)) {
7772 case FCMLA_z_p_zzz:
7773 VIXL_UNIMPLEMENTED();
7774 break;
7775 default:
7776 VIXL_UNIMPLEMENTED();
7777 break;
7778 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007779}
7780
7781void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
7782 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007783 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
7784 case FCMLA_z_zzzi_h:
7785 VIXL_UNIMPLEMENTED();
7786 break;
7787 case FCMLA_z_zzzi_s:
7788 VIXL_UNIMPLEMENTED();
7789 break;
7790 default:
7791 VIXL_UNIMPLEMENTED();
7792 break;
7793 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007794}
7795
7796void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
7797 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007798 switch (instr->Mask(SVEFPFastReductionMask)) {
7799 case FADDV_v_p_z:
7800 VIXL_UNIMPLEMENTED();
7801 break;
7802 case FMAXNMV_v_p_z:
7803 VIXL_UNIMPLEMENTED();
7804 break;
7805 case FMAXV_v_p_z:
7806 VIXL_UNIMPLEMENTED();
7807 break;
7808 case FMINNMV_v_p_z:
7809 VIXL_UNIMPLEMENTED();
7810 break;
7811 case FMINV_v_p_z:
7812 VIXL_UNIMPLEMENTED();
7813 break;
7814 default:
7815 VIXL_UNIMPLEMENTED();
7816 break;
7817 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007818}
7819
7820void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
7821 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007822 switch (instr->Mask(SVEFPMulIndexMask)) {
7823 case FMUL_z_zzi_d:
7824 VIXL_UNIMPLEMENTED();
7825 break;
7826 case FMUL_z_zzi_h:
7827 VIXL_UNIMPLEMENTED();
7828 break;
7829 case FMUL_z_zzi_s:
7830 VIXL_UNIMPLEMENTED();
7831 break;
7832 default:
7833 VIXL_UNIMPLEMENTED();
7834 break;
7835 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007836}
7837
7838void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
7839 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007840 switch (instr->Mask(SVEFPMulAddMask)) {
7841 case FMAD_z_p_zzz:
7842 VIXL_UNIMPLEMENTED();
7843 break;
7844 case FMLA_z_p_zzz:
7845 VIXL_UNIMPLEMENTED();
7846 break;
7847 case FMLS_z_p_zzz:
7848 VIXL_UNIMPLEMENTED();
7849 break;
7850 case FMSB_z_p_zzz:
7851 VIXL_UNIMPLEMENTED();
7852 break;
7853 case FNMAD_z_p_zzz:
7854 VIXL_UNIMPLEMENTED();
7855 break;
7856 case FNMLA_z_p_zzz:
7857 VIXL_UNIMPLEMENTED();
7858 break;
7859 case FNMLS_z_p_zzz:
7860 VIXL_UNIMPLEMENTED();
7861 break;
7862 case FNMSB_z_p_zzz:
7863 VIXL_UNIMPLEMENTED();
7864 break;
7865 default:
7866 VIXL_UNIMPLEMENTED();
7867 break;
7868 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007869}
7870
7871void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
7872 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007873 switch (instr->Mask(SVEFPMulAddIndexMask)) {
7874 case FMLA_z_zzzi_d:
7875 VIXL_UNIMPLEMENTED();
7876 break;
7877 case FMLA_z_zzzi_h:
7878 VIXL_UNIMPLEMENTED();
7879 break;
7880 case FMLA_z_zzzi_s:
7881 VIXL_UNIMPLEMENTED();
7882 break;
7883 case FMLS_z_zzzi_d:
7884 VIXL_UNIMPLEMENTED();
7885 break;
7886 case FMLS_z_zzzi_h:
7887 VIXL_UNIMPLEMENTED();
7888 break;
7889 case FMLS_z_zzzi_s:
7890 VIXL_UNIMPLEMENTED();
7891 break;
7892 default:
7893 VIXL_UNIMPLEMENTED();
7894 break;
7895 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007896}
7897
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007898void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007899 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007900 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007901 case FCVTZS_z_p_z_d2w:
7902 VIXL_UNIMPLEMENTED();
7903 break;
7904 case FCVTZS_z_p_z_d2x:
7905 VIXL_UNIMPLEMENTED();
7906 break;
7907 case FCVTZS_z_p_z_fp162h:
7908 VIXL_UNIMPLEMENTED();
7909 break;
7910 case FCVTZS_z_p_z_fp162w:
7911 VIXL_UNIMPLEMENTED();
7912 break;
7913 case FCVTZS_z_p_z_fp162x:
7914 VIXL_UNIMPLEMENTED();
7915 break;
7916 case FCVTZS_z_p_z_s2w:
7917 VIXL_UNIMPLEMENTED();
7918 break;
7919 case FCVTZS_z_p_z_s2x:
7920 VIXL_UNIMPLEMENTED();
7921 break;
7922 case FCVTZU_z_p_z_d2w:
7923 VIXL_UNIMPLEMENTED();
7924 break;
7925 case FCVTZU_z_p_z_d2x:
7926 VIXL_UNIMPLEMENTED();
7927 break;
7928 case FCVTZU_z_p_z_fp162h:
7929 VIXL_UNIMPLEMENTED();
7930 break;
7931 case FCVTZU_z_p_z_fp162w:
7932 VIXL_UNIMPLEMENTED();
7933 break;
7934 case FCVTZU_z_p_z_fp162x:
7935 VIXL_UNIMPLEMENTED();
7936 break;
7937 case FCVTZU_z_p_z_s2w:
7938 VIXL_UNIMPLEMENTED();
7939 break;
7940 case FCVTZU_z_p_z_s2x:
7941 VIXL_UNIMPLEMENTED();
7942 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007943 default:
7944 VIXL_UNIMPLEMENTED();
7945 break;
7946 }
7947}
7948
7949void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
7950 USE(instr);
7951 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007952 case FCVT_z_p_z_d2h:
7953 VIXL_UNIMPLEMENTED();
7954 break;
7955 case FCVT_z_p_z_d2s:
7956 VIXL_UNIMPLEMENTED();
7957 break;
7958 case FCVT_z_p_z_h2d:
7959 VIXL_UNIMPLEMENTED();
7960 break;
7961 case FCVT_z_p_z_h2s:
7962 VIXL_UNIMPLEMENTED();
7963 break;
7964 case FCVT_z_p_z_s2d:
7965 VIXL_UNIMPLEMENTED();
7966 break;
7967 case FCVT_z_p_z_s2h:
7968 VIXL_UNIMPLEMENTED();
7969 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007970 default:
7971 VIXL_UNIMPLEMENTED();
7972 break;
7973 }
7974}
7975
7976void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
7977 USE(instr);
7978 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007979 case FRECPX_z_p_z:
7980 VIXL_UNIMPLEMENTED();
7981 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007982 case FSQRT_z_p_z:
7983 VIXL_UNIMPLEMENTED();
7984 break;
7985 default:
7986 VIXL_UNIMPLEMENTED();
7987 break;
7988 }
7989}
7990
7991void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
7992 USE(instr);
7993 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007994 case FRINTA_z_p_z:
7995 VIXL_UNIMPLEMENTED();
7996 break;
7997 case FRINTI_z_p_z:
7998 VIXL_UNIMPLEMENTED();
7999 break;
8000 case FRINTM_z_p_z:
8001 VIXL_UNIMPLEMENTED();
8002 break;
8003 case FRINTN_z_p_z:
8004 VIXL_UNIMPLEMENTED();
8005 break;
8006 case FRINTP_z_p_z:
8007 VIXL_UNIMPLEMENTED();
8008 break;
8009 case FRINTX_z_p_z:
8010 VIXL_UNIMPLEMENTED();
8011 break;
8012 case FRINTZ_z_p_z:
8013 VIXL_UNIMPLEMENTED();
8014 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008015 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008016 VIXL_UNIMPLEMENTED();
8017 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008018 }
8019}
8020
8021void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
8022 USE(instr);
8023 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008024 case SCVTF_z_p_z_h2fp16:
8025 VIXL_UNIMPLEMENTED();
8026 break;
8027 case SCVTF_z_p_z_w2d:
8028 VIXL_UNIMPLEMENTED();
8029 break;
8030 case SCVTF_z_p_z_w2fp16:
8031 VIXL_UNIMPLEMENTED();
8032 break;
8033 case SCVTF_z_p_z_w2s:
8034 VIXL_UNIMPLEMENTED();
8035 break;
8036 case SCVTF_z_p_z_x2d:
8037 VIXL_UNIMPLEMENTED();
8038 break;
8039 case SCVTF_z_p_z_x2fp16:
8040 VIXL_UNIMPLEMENTED();
8041 break;
8042 case SCVTF_z_p_z_x2s:
8043 VIXL_UNIMPLEMENTED();
8044 break;
8045 case UCVTF_z_p_z_h2fp16:
8046 VIXL_UNIMPLEMENTED();
8047 break;
8048 case UCVTF_z_p_z_w2d:
8049 VIXL_UNIMPLEMENTED();
8050 break;
8051 case UCVTF_z_p_z_w2fp16:
8052 VIXL_UNIMPLEMENTED();
8053 break;
8054 case UCVTF_z_p_z_w2s:
8055 VIXL_UNIMPLEMENTED();
8056 break;
8057 case UCVTF_z_p_z_x2d:
8058 VIXL_UNIMPLEMENTED();
8059 break;
8060 case UCVTF_z_p_z_x2fp16:
8061 VIXL_UNIMPLEMENTED();
8062 break;
8063 case UCVTF_z_p_z_x2s:
8064 VIXL_UNIMPLEMENTED();
8065 break;
8066 default:
8067 VIXL_UNIMPLEMENTED();
8068 break;
8069 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008070}
8071
8072void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
8073 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008074 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8075 case FRECPE_z_z:
8076 VIXL_UNIMPLEMENTED();
8077 break;
8078 case FRSQRTE_z_z:
8079 VIXL_UNIMPLEMENTED();
8080 break;
8081 default:
8082 VIXL_UNIMPLEMENTED();
8083 break;
8084 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008085}
8086
8087void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
8088 USE(instr);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008089
8090 VectorFormat vform = instr->GetSVEVectorFormat();
8091 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
8092
8093 int count = CountActiveLanes(vform, pg);
8094
8095 if (instr->ExtractBit(11) == 0) {
8096 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8097 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8098 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008099 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008100 break;
8101 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008102 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008103 break;
8104 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008105 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008106 break;
8107 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008108 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008109 break;
8110 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008111 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008112 break;
8113 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008114 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008115 break;
8116 default:
8117 VIXL_UNIMPLEMENTED();
8118 break;
8119 }
8120 } else {
8121 bool is_saturating = (instr->ExtractBit(18) == 0);
8122 bool decrement =
8123 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
8124 bool is_signed = (instr->ExtractBit(16) == 0);
8125 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
8126 unsigned width = sf ? kXRegSize : kWRegSize;
8127
8128 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8129 case DECP_r_p_r:
8130 case INCP_r_p_r:
8131 case SQDECP_r_p_r_sx:
8132 case SQDECP_r_p_r_x:
8133 case SQINCP_r_p_r_sx:
8134 case SQINCP_r_p_r_x:
8135 case UQDECP_r_p_r_uw:
8136 case UQDECP_r_p_r_x:
8137 case UQINCP_r_p_r_uw:
8138 case UQINCP_r_p_r_x:
8139 WriteXRegister(instr->GetRd(),
8140 IncDecN(ReadXRegister(instr->GetRd()),
8141 decrement ? -count : count,
8142 width,
8143 is_saturating,
8144 is_signed));
8145 break;
8146 default:
8147 VIXL_UNIMPLEMENTED();
8148 break;
8149 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008150 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008151}
8152
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008153uint64_t Simulator::IncDecN(uint64_t acc,
8154 int64_t delta,
8155 unsigned n,
8156 bool is_saturating,
8157 bool is_signed) {
8158 VIXL_ASSERT(n <= 64);
8159 VIXL_ASSERT(IsIntN(n, delta));
8160
8161 uint64_t sign_mask = UINT64_C(1) << (n - 1);
8162 uint64_t mask = GetUintMask(n);
8163
8164 acc &= mask; // Ignore initial accumulator high bits.
8165 uint64_t result = (acc + delta) & mask;
8166
8167 bool acc_negative = ((acc & sign_mask) != 0);
8168 bool delta_negative = delta < 0;
8169 bool result_negative = ((result & sign_mask) != 0);
8170
8171 if (is_saturating) {
8172 if (is_signed) {
8173 // If the signs of the operands are the same, but different from the
8174 // result, there was an overflow.
8175 if ((acc_negative == delta_negative) &&
8176 (acc_negative != result_negative)) {
8177 if (result_negative) {
8178 // Saturate to [..., INT<n>_MAX].
8179 result_negative = false;
8180 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
8181 } else {
8182 // Saturate to [INT<n>_MIN, ...].
8183 result_negative = true;
8184 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
8185 }
8186 }
8187 } else {
8188 if ((delta < 0) && (result > acc)) {
8189 // Saturate to [0, ...].
8190 result = 0;
8191 } else if ((delta > 0) && (result < acc)) {
8192 // Saturate to [..., UINT<n>_MAX].
8193 result = mask;
8194 }
8195 }
8196 }
8197
8198 // Sign-extend if necessary.
8199 if (result_negative && is_signed) result |= ~mask;
8200
8201 return result;
8202}
8203
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008204void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
8205 USE(instr);
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008206 VectorFormat vform = instr->GetSVEVectorFormat();
8207 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008208 switch (instr->Mask(SVEIndexGenerationMask)) {
8209 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008210 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008211 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008212 case INDEX_z_rr: {
8213 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
8214 : instr->ExtractSignedBits(9, 5);
8215 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
8216 : instr->ExtractSignedBits(20, 16);
8217 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008218 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008219 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008220 default:
8221 VIXL_UNIMPLEMENTED();
8222 break;
8223 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008224}
8225
8226void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
8227 USE(instr);
TatWai Chong845246b2019-08-08 00:01:58 -07008228 VectorFormat vform = instr->GetSVEVectorFormat();
8229 SimVRegister& zd = ReadVRegister(instr->GetRd());
8230 SimVRegister& zn = ReadVRegister(instr->GetRn());
8231 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008232 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8233 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008234 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008235 break;
8236 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008237 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008238 break;
8239 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008240 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008241 break;
8242 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008243 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008244 break;
8245 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008246 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008247 break;
8248 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008249 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008250 break;
8251 default:
8252 VIXL_UNIMPLEMENTED();
8253 break;
8254 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008255}
8256
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008257void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008258 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -07008259 VectorFormat vform = instr->GetSVEVectorFormat();
8260 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8261 SimVRegister& zm = ReadVRegister(instr->GetRn());
8262 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8263 SimVRegister result;
8264
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008265 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008266 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008267 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008268 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008269 case SUBR_z_p_zz:
8270 sub(vform, result, zm, zdn);
8271 break;
8272 case SUB_z_p_zz:
8273 sub(vform, result, zdn, zm);
8274 break;
8275 default:
8276 VIXL_UNIMPLEMENTED();
8277 break;
8278 }
8279 mov_merging(vform, zdn, pg, result);
8280}
8281
8282void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
8283 VectorFormat vform = instr->GetSVEVectorFormat();
8284 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8285 SimVRegister& zm = ReadVRegister(instr->GetRn());
8286 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8287 SimVRegister result;
8288
8289 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008290 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008291 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008292 break;
8293 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008294 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008295 break;
8296 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008297 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008298 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008299 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008300 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008301 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008302 default:
8303 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008304 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008305 }
8306 mov_merging(vform, zdn, pg, result);
8307}
8308
8309void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
8310 VectorFormat vform = instr->GetSVEVectorFormat();
8311 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8312 SimVRegister& zm = ReadVRegister(instr->GetRn());
8313 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8314 SimVRegister result;
8315
8316 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
8317 case MUL_z_p_zz:
8318 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008319 break;
8320 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008321 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008322 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008323 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008324 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008325 break;
8326 default:
8327 VIXL_UNIMPLEMENTED();
8328 break;
8329 }
TatWai Chong13634762019-07-16 16:20:45 -07008330 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008331}
8332
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008333void Simulator::VisitSVEIntMinMaxDifference_Predicated(
8334 const Instruction* instr) {
8335 VectorFormat vform = instr->GetSVEVectorFormat();
8336 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8337 SimVRegister& zm = ReadVRegister(instr->GetRn());
8338 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8339 SimVRegister result;
8340
8341 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
8342 case SABD_z_p_zz:
8343 absdiff(vform, result, zdn, zm, true);
8344 break;
8345 case SMAX_z_p_zz:
8346 smax(vform, result, zdn, zm);
8347 break;
8348 case SMIN_z_p_zz:
8349 smin(vform, result, zdn, zm);
8350 break;
8351 case UABD_z_p_zz:
8352 absdiff(vform, result, zdn, zm, false);
8353 break;
8354 case UMAX_z_p_zz:
8355 umax(vform, result, zdn, zm);
8356 break;
8357 case UMIN_z_p_zz:
8358 umin(vform, result, zdn, zm);
8359 break;
8360 default:
8361 VIXL_UNIMPLEMENTED();
8362 break;
8363 }
8364 mov_merging(vform, zdn, pg, result);
8365}
8366
8367void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
8368 VectorFormat vform = instr->GetSVEVectorFormat();
8369 SimVRegister& zd = ReadVRegister(instr->GetRd());
8370 SimVRegister scratch;
8371
8372 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
8373 case MUL_z_zi:
8374 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
8375 mul(vform, zd, zd, scratch);
8376 break;
8377 default:
8378 VIXL_UNIMPLEMENTED();
8379 break;
8380 }
8381}
8382
8383void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
8384 VectorFormat vform = instr->GetSVEVectorFormat();
8385 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8386 SimVRegister& zm = ReadVRegister(instr->GetRn());
8387 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8388 SimVRegister result;
8389
8390 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
8391
8392 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
8393 case SDIVR_z_p_zz:
8394 sdiv(vform, result, zm, zdn);
8395 break;
8396 case SDIV_z_p_zz:
8397 sdiv(vform, result, zdn, zm);
8398 break;
8399 case UDIVR_z_p_zz:
8400 udiv(vform, result, zm, zdn);
8401 break;
8402 case UDIV_z_p_zz:
8403 udiv(vform, result, zdn, zm);
8404 break;
8405 default:
8406 VIXL_UNIMPLEMENTED();
8407 break;
8408 }
8409 mov_merging(vform, zdn, pg, result);
8410}
8411
8412void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
8413 VectorFormat vform = instr->GetSVEVectorFormat();
8414 SimVRegister& zd = ReadVRegister(instr->GetRd());
8415 SimVRegister scratch;
8416
8417 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
8418 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
8419
8420 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
8421 case SMAX_z_zi:
8422 dup_immediate(vform, scratch, signed_imm);
8423 smax(vform, zd, zd, scratch);
8424 break;
8425 case SMIN_z_zi:
8426 dup_immediate(vform, scratch, signed_imm);
8427 smin(vform, zd, zd, scratch);
8428 break;
8429 case UMAX_z_zi:
8430 dup_immediate(vform, scratch, unsigned_imm);
8431 umax(vform, zd, zd, scratch);
8432 break;
8433 case UMIN_z_zi:
8434 dup_immediate(vform, scratch, unsigned_imm);
8435 umin(vform, zd, zd, scratch);
8436 break;
8437 default:
8438 VIXL_UNIMPLEMENTED();
8439 break;
8440 }
8441}
8442
8443void Simulator::VisitSVEIntCompareScalarCountAndLimit(
8444 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -07008445 unsigned rn_code = instr->GetRn();
8446 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008447 SimPRegister& pd = ReadPRegister(instr->GetPd());
8448 VectorFormat vform = instr->GetSVEVectorFormat();
8449 bool is_64_bit = instr->ExtractBit(12) == 1;
8450 int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8451 int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
TatWai Chongc844bb22019-06-10 15:32:53 -07008452
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008453 bool last = true;
8454 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
8455 bool cond = false;
8456 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
8457 case WHILELE_p_p_rr:
8458 cond = src1 <= src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008459 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008460 case WHILELO_p_p_rr:
8461 cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
8462 break;
8463 case WHILELS_p_p_rr:
8464 cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
8465 break;
8466 case WHILELT_p_p_rr:
8467 cond = src1 < src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008468 break;
8469 default:
TatWai Chongc844bb22019-06-10 15:32:53 -07008470 VIXL_UNIMPLEMENTED();
8471 break;
8472 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008473 last = last && cond;
8474 LogicPRegister dst(pd);
8475 dst.SetActive(vform, lane, last);
8476 src1 += 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008477 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008478
8479 PredTest(vform, GetPTrue(), pd);
8480 LogSystemRegister(NZCV);
8481}
8482
8483void Simulator::VisitSVEConditionallyTerminateScalars(
8484 const Instruction* instr) {
8485 unsigned rn_code = instr->GetRn();
8486 unsigned rm_code = instr->GetRm();
8487 bool is_64_bit = instr->ExtractBit(22) == 1;
8488 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8489 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
8490 bool term;
8491 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
8492 case CTERMEQ_rr:
8493 term = src1 == src2;
8494 break;
8495 case CTERMNE_rr:
8496 term = src1 != src2;
8497 break;
8498 default:
8499 term = false;
8500 VIXL_UNIMPLEMENTED();
8501 break;
8502 }
8503 ReadNzcv().SetN(term ? 1 : 0);
8504 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -07008505 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008506}
8507
8508void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
8509 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008510 bool commute_inputs = false;
8511 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008512 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8513 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008514 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008515 break;
8516 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008517 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008518 break;
8519 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008520 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008521 break;
8522 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008523 cond = ge;
8524 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008525 break;
8526 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008527 cond = gt;
8528 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008529 break;
8530 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008531 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008532 break;
8533 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008534 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008535 VIXL_UNIMPLEMENTED();
8536 break;
8537 }
TatWai Chong302729c2019-06-14 16:18:51 -07008538
8539 VectorFormat vform = instr->GetSVEVectorFormat();
8540 SimVRegister src2;
8541 dup_immediate(vform,
8542 src2,
8543 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
8544 SVEIntCompareVectorsHelper(cond,
8545 vform,
8546 ReadPRegister(instr->GetPd()),
8547 ReadPRegister(instr->GetPgLow8()),
8548 commute_inputs ? src2
8549 : ReadVRegister(instr->GetRn()),
8550 commute_inputs ? ReadVRegister(instr->GetRn())
8551 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008552}
8553
8554void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
8555 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008556 bool commute_inputs = false;
8557 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008558 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8559 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008560 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008561 break;
8562 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008563 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008564 break;
8565 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008566 cond = hi;
8567 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008568 break;
8569 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008570 cond = hs;
8571 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008572 break;
8573 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008574 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008575 VIXL_UNIMPLEMENTED();
8576 break;
8577 }
TatWai Chong302729c2019-06-14 16:18:51 -07008578
8579 VectorFormat vform = instr->GetSVEVectorFormat();
8580 SimVRegister src2;
8581 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
8582 SVEIntCompareVectorsHelper(cond,
8583 vform,
8584 ReadPRegister(instr->GetPd()),
8585 ReadPRegister(instr->GetPgLow8()),
8586 commute_inputs ? src2
8587 : ReadVRegister(instr->GetRn()),
8588 commute_inputs ? ReadVRegister(instr->GetRn())
8589 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008590}
8591
8592void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
8593 USE(instr);
TatWai Chong96713fe2019-06-04 16:39:37 -07008594
8595 Instr op = instr->Mask(SVEIntCompareVectorsMask);
8596 bool is_wide_elements = false;
8597 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008598 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -07008599 case CMPGE_p_p_zw:
8600 case CMPGT_p_p_zw:
8601 case CMPHI_p_p_zw:
8602 case CMPHS_p_p_zw:
8603 case CMPLE_p_p_zw:
8604 case CMPLO_p_p_zw:
8605 case CMPLS_p_p_zw:
8606 case CMPLT_p_p_zw:
8607 case CMPNE_p_p_zw:
8608 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008609 break;
TatWai Chong96713fe2019-06-04 16:39:37 -07008610 }
8611
TatWai Chong302729c2019-06-14 16:18:51 -07008612 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -07008613 switch (op) {
8614 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008615 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008616 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008617 break;
8618 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008619 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008620 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008621 break;
8622 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008623 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008624 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008625 break;
8626 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008627 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008628 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008629 break;
8630 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008631 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008632 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008633 break;
8634 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008635 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008636 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -07008637 break;
8638 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008639 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -07008640 break;
8641 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008642 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -07008643 break;
8644 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008645 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -07008646 break;
8647 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008648 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008649 break;
8650 default:
8651 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -07008652 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008653 break;
8654 }
TatWai Chong96713fe2019-06-04 16:39:37 -07008655
TatWai Chong302729c2019-06-14 16:18:51 -07008656 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -07008657 instr->GetSVEVectorFormat(),
8658 ReadPRegister(instr->GetPd()),
8659 ReadPRegister(instr->GetPgLow8()),
8660 ReadVRegister(instr->GetRn()),
8661 ReadVRegister(instr->GetRm()),
8662 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008663}
8664
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008665void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008666 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008667 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008668 case FEXPA_z_z:
8669 VIXL_UNIMPLEMENTED();
8670 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008671 default:
8672 VIXL_UNIMPLEMENTED();
8673 break;
8674 }
8675}
8676
8677void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
8678 USE(instr);
8679 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008680 case FTSSEL_z_zz:
8681 VIXL_UNIMPLEMENTED();
8682 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008683 default:
8684 VIXL_UNIMPLEMENTED();
8685 break;
8686 }
8687}
8688
8689void Simulator::VisitSVEConstructivePrefix_Unpredicated(
8690 const Instruction* instr) {
8691 SimVRegister& zd = ReadVRegister(instr->GetRd());
8692 SimVRegister& zn = ReadVRegister(instr->GetRn());
8693
8694 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008695 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008696 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
8697 // Record the movprfx, so the next ExecuteInstruction() can check it.
8698 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008699 break;
8700 default:
8701 VIXL_UNIMPLEMENTED();
8702 break;
8703 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008704}
8705
8706void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
8707 USE(instr);
Jacob Bramley22023df2019-05-14 17:55:43 +01008708 VectorFormat vform = instr->GetSVEVectorFormat();
8709
8710 SimVRegister& zd = ReadVRegister(instr->GetRd());
8711 SimVRegister& zm = ReadVRegister(instr->GetRm());
8712
8713 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008714 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008715 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008716 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008717 break;
8718 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008719 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008720 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008721 case MAD_z_p_zzz:
8722 // 'za' is encoded in 'Rn'.
8723 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008724 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008725 case MSB_z_p_zzz: {
8726 // 'za' is encoded in 'Rn'.
8727 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
8728 break;
8729 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008730 default:
8731 VIXL_UNIMPLEMENTED();
8732 break;
8733 }
Jacob Bramley22023df2019-05-14 17:55:43 +01008734 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008735}
8736
8737void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
8738 USE(instr);
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008739
8740 VectorFormat vform = instr->GetSVEVectorFormat();
8741 SimVRegister& zda = ReadVRegister(instr->GetRd());
8742 SimVRegister& zn = ReadVRegister(instr->GetRn());
8743 SimVRegister& zm = ReadVRegister(instr->GetRm());
8744
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008745 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8746 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008747 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008748 break;
8749 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008750 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008751 break;
8752 default:
8753 VIXL_UNIMPLEMENTED();
8754 break;
8755 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008756}
8757
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008758void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008759 VectorFormat vform = instr->GetSVEVectorFormat();
8760 SimVRegister& zn = ReadVRegister(instr->GetRn());
8761 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8762 SimVRegister& zd = ReadVRegister(instr->GetRd());
8763
8764 switch (instr->Mask(SVEMovprfxMask)) {
8765 case MOVPRFX_z_p_z:
8766 if (instr->ExtractBit(16)) {
8767 mov_merging(vform, zd, pg, zn);
8768 } else {
8769 mov_zeroing(vform, zd, pg, zn);
8770 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008771
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008772 // Record the movprfx, so the next ExecuteInstruction() can check it.
8773 movprfx_ = instr;
8774 break;
8775 default:
8776 VIXL_UNIMPLEMENTED();
8777 break;
8778 }
8779}
8780
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008781void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008782 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +01008783 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008784 SimVRegister& zn = ReadVRegister(instr->GetRn());
8785 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8786
8787 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
8788 switch (instr->Mask(SVEIntReductionLogicalMask)) {
8789 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008790 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008791 break;
8792 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008793 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008794 break;
8795 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008796 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008797 break;
8798 default:
8799 VIXL_UNIMPLEMENTED();
8800 break;
8801 }
8802 } else {
8803 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008804 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008805 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008806 break;
8807 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008808 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008809 break;
8810 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008811 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008812 break;
8813 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008814 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008815 break;
8816 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008817 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008818 break;
8819 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008820 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008821 break;
8822 default:
8823 VIXL_UNIMPLEMENTED();
8824 break;
8825 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008826 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008827}
8828
8829void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
8830 USE(instr);
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008831
8832 VectorFormat vform = instr->GetSVEVectorFormat();
8833 SimVRegister& zn = ReadVRegister(instr->GetRn());
8834
8835 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008836 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
8837 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008838 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008839 break;
8840 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008841 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008842 break;
8843 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008844 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008845 break;
8846 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008847 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008848 break;
8849 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008850 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008851 break;
8852 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008853 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008854 break;
8855 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008856 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008857 break;
8858 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008859 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008860 break;
8861 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008862 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008863 break;
8864 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008865 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008866 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008867 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008868 break;
8869 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008870 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008871 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008872 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008873 break;
8874 default:
8875 VIXL_UNIMPLEMENTED();
8876 break;
8877 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008878
8879 SimVRegister& zd = ReadVRegister(instr->GetRd());
8880 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8881 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008882}
8883
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008884void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008885 // There is only one instruction in this group.
8886 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
8887
8888 VectorFormat vform = instr->GetSVEVectorFormat();
8889 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
8890 SimVRegister& zd = ReadVRegister(instr->GetRd());
8891
8892 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008893 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008894 case FCPY_z_p_i: {
8895 int imm8 = instr->ExtractBits(12, 5);
8896 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
8897 Instruction::Imm8ToFP64(imm8));
8898 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008899 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008900 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008901 default:
8902 VIXL_UNIMPLEMENTED();
8903 break;
8904 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008905 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008906}
8907
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008908void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
8909 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +01008910 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01008911 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +01008912 SimVRegister scratch;
8913
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008914 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
8915 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008916
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008917 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008918 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008919 add_uint(vform, zd, zd, imm);
8920 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008921 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008922 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
8923 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008924 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008925 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
8926 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008927 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008928 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +01008929 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008930 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008931 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008932 sub_uint(vform, zd, zd, imm);
8933 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008934 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008935 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
8936 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008937 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008938 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
8939 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008940 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008941 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008942 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008943}
TatWai Chong6995bfd2019-09-26 10:48:05 +01008944
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008945void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
8946 SimVRegister& zd = ReadVRegister(instr->GetRd());
8947
8948 int64_t imm = instr->GetImmSVEIntWideSigned();
8949 imm <<= instr->ExtractBit(13) * 8;
8950
8951 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
8952 case DUP_z_i:
8953 dup_immediate(instr->GetSVEVectorFormat(), zd, imm);
8954 break;
8955 default:
8956 VIXL_UNIMPLEMENTED();
8957 break;
8958 }
8959}
8960
8961void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
8962 VectorFormat vform = instr->GetSVEVectorFormat();
8963 SimVRegister& zd = ReadVRegister(instr->GetRd());
8964
8965 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008966 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +01008967 switch (vform) {
8968 case kFormatVnH:
8969 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
8970 break;
8971 case kFormatVnS:
8972 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
8973 break;
8974 case kFormatVnD:
8975 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
8976 break;
8977 default:
8978 VIXL_UNIMPLEMENTED();
8979 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008980 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008981 default:
8982 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008983 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008984 }
8985}
8986
8987void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
8988 const Instruction* instr) {
8989 USE(instr);
8990 switch (instr->Mask(
8991 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
8992 case LD1H_z_p_bz_s_x32_scaled:
8993 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008994 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008995 case LD1SH_z_p_bz_s_x32_scaled:
8996 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008997 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008998 case LDFF1H_z_p_bz_s_x32_scaled:
8999 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009000 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009001 case LDFF1SH_z_p_bz_s_x32_scaled:
9002 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009003 break;
9004 default:
9005 VIXL_UNIMPLEMENTED();
9006 break;
9007 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009008}
9009
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009010void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009011 const Instruction* instr) {
9012 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009013 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
9014 case LD1B_z_p_bz_s_x32_unscaled:
9015 VIXL_UNIMPLEMENTED();
9016 break;
9017 case LD1H_z_p_bz_s_x32_unscaled:
9018 VIXL_UNIMPLEMENTED();
9019 break;
9020 case LD1SB_z_p_bz_s_x32_unscaled:
9021 VIXL_UNIMPLEMENTED();
9022 break;
9023 case LD1SH_z_p_bz_s_x32_unscaled:
9024 VIXL_UNIMPLEMENTED();
9025 break;
9026 case LD1W_z_p_bz_s_x32_unscaled:
9027 VIXL_UNIMPLEMENTED();
9028 break;
9029 case LDFF1B_z_p_bz_s_x32_unscaled:
9030 VIXL_UNIMPLEMENTED();
9031 break;
9032 case LDFF1H_z_p_bz_s_x32_unscaled:
9033 VIXL_UNIMPLEMENTED();
9034 break;
9035 case LDFF1SB_z_p_bz_s_x32_unscaled:
9036 VIXL_UNIMPLEMENTED();
9037 break;
9038 case LDFF1SH_z_p_bz_s_x32_unscaled:
9039 VIXL_UNIMPLEMENTED();
9040 break;
9041 case LDFF1W_z_p_bz_s_x32_unscaled:
9042 VIXL_UNIMPLEMENTED();
9043 break;
9044 default:
9045 VIXL_UNIMPLEMENTED();
9046 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009047 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009048}
9049
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009050void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
9051 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009052 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009053 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
9054 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009055 VIXL_UNIMPLEMENTED();
9056 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009057 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009058 VIXL_UNIMPLEMENTED();
9059 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009060 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009061 VIXL_UNIMPLEMENTED();
9062 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009063 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009064 VIXL_UNIMPLEMENTED();
9065 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009066 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009067 VIXL_UNIMPLEMENTED();
9068 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009069 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009070 VIXL_UNIMPLEMENTED();
9071 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009072 case LDFF1H_z_p_ai_s:
9073 VIXL_UNIMPLEMENTED();
9074 break;
9075 case LDFF1SB_z_p_ai_s:
9076 VIXL_UNIMPLEMENTED();
9077 break;
9078 case LDFF1SH_z_p_ai_s:
9079 VIXL_UNIMPLEMENTED();
9080 break;
9081 case LDFF1W_z_p_ai_s:
9082 VIXL_UNIMPLEMENTED();
9083 break;
9084 default:
9085 VIXL_UNIMPLEMENTED();
9086 break;
9087 }
9088}
9089
9090void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
9091 const Instruction* instr) {
9092 USE(instr);
9093 switch (
9094 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
9095 case LD1W_z_p_bz_s_x32_scaled:
9096 VIXL_UNIMPLEMENTED();
9097 break;
9098 case LDFF1W_z_p_bz_s_x32_scaled:
9099 VIXL_UNIMPLEMENTED();
9100 break;
9101 default:
9102 VIXL_UNIMPLEMENTED();
9103 break;
9104 }
9105}
9106
9107void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
9108 const Instruction* instr) {
9109 USE(instr);
9110 switch (
9111 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
9112 case PRFB_i_p_bz_s_x32_scaled:
9113 VIXL_UNIMPLEMENTED();
9114 break;
9115 case PRFD_i_p_bz_s_x32_scaled:
9116 VIXL_UNIMPLEMENTED();
9117 break;
9118 case PRFH_i_p_bz_s_x32_scaled:
9119 VIXL_UNIMPLEMENTED();
9120 break;
9121 case PRFW_i_p_bz_s_x32_scaled:
9122 VIXL_UNIMPLEMENTED();
9123 break;
9124 default:
9125 VIXL_UNIMPLEMENTED();
9126 break;
9127 }
9128}
9129
9130void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
9131 const Instruction* instr) {
9132 USE(instr);
9133 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
9134 case PRFB_i_p_ai_s:
9135 VIXL_UNIMPLEMENTED();
9136 break;
9137 case PRFD_i_p_ai_s:
9138 VIXL_UNIMPLEMENTED();
9139 break;
9140 case PRFH_i_p_ai_s:
9141 VIXL_UNIMPLEMENTED();
9142 break;
9143 case PRFW_i_p_ai_s:
9144 VIXL_UNIMPLEMENTED();
9145 break;
9146 default:
9147 VIXL_UNIMPLEMENTED();
9148 break;
9149 }
9150}
9151
9152void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
9153 const Instruction* instr) {
9154 USE(instr);
9155 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
9156 case PRFB_i_p_bi_s:
9157 VIXL_UNIMPLEMENTED();
9158 break;
9159 case PRFD_i_p_bi_s:
9160 VIXL_UNIMPLEMENTED();
9161 break;
9162 case PRFH_i_p_bi_s:
9163 VIXL_UNIMPLEMENTED();
9164 break;
9165 case PRFW_i_p_bi_s:
9166 VIXL_UNIMPLEMENTED();
9167 break;
9168 default:
9169 VIXL_UNIMPLEMENTED();
9170 break;
9171 }
9172}
9173
9174void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
9175 const Instruction* instr) {
9176 USE(instr);
9177 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
9178 case PRFB_i_p_br_s:
9179 VIXL_UNIMPLEMENTED();
9180 break;
9181 case PRFD_i_p_br_s:
9182 VIXL_UNIMPLEMENTED();
9183 break;
9184 case PRFH_i_p_br_s:
9185 VIXL_UNIMPLEMENTED();
9186 break;
9187 case PRFW_i_p_br_s:
9188 VIXL_UNIMPLEMENTED();
9189 break;
9190 default:
9191 VIXL_UNIMPLEMENTED();
9192 break;
9193 }
9194}
9195
9196void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
9197 USE(instr);
9198 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
9199 case LD1RB_z_p_bi_u16:
9200 VIXL_UNIMPLEMENTED();
9201 break;
9202 case LD1RB_z_p_bi_u32:
9203 VIXL_UNIMPLEMENTED();
9204 break;
9205 case LD1RB_z_p_bi_u64:
9206 VIXL_UNIMPLEMENTED();
9207 break;
9208 case LD1RB_z_p_bi_u8:
9209 VIXL_UNIMPLEMENTED();
9210 break;
9211 case LD1RD_z_p_bi_u64:
9212 VIXL_UNIMPLEMENTED();
9213 break;
9214 case LD1RH_z_p_bi_u16:
9215 VIXL_UNIMPLEMENTED();
9216 break;
9217 case LD1RH_z_p_bi_u32:
9218 VIXL_UNIMPLEMENTED();
9219 break;
9220 case LD1RH_z_p_bi_u64:
9221 VIXL_UNIMPLEMENTED();
9222 break;
9223 case LD1RSB_z_p_bi_s16:
9224 VIXL_UNIMPLEMENTED();
9225 break;
9226 case LD1RSB_z_p_bi_s32:
9227 VIXL_UNIMPLEMENTED();
9228 break;
9229 case LD1RSB_z_p_bi_s64:
9230 VIXL_UNIMPLEMENTED();
9231 break;
9232 case LD1RSH_z_p_bi_s32:
9233 VIXL_UNIMPLEMENTED();
9234 break;
9235 case LD1RSH_z_p_bi_s64:
9236 VIXL_UNIMPLEMENTED();
9237 break;
9238 case LD1RSW_z_p_bi_s64:
9239 VIXL_UNIMPLEMENTED();
9240 break;
9241 case LD1RW_z_p_bi_u32:
9242 VIXL_UNIMPLEMENTED();
9243 break;
9244 case LD1RW_z_p_bi_u64:
9245 VIXL_UNIMPLEMENTED();
9246 break;
9247 default:
9248 VIXL_UNIMPLEMENTED();
9249 break;
9250 }
9251}
9252
9253void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
9254 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
9255 case LDR_p_bi: {
9256 SimPRegister& pt = ReadPRegister(instr->GetPt());
9257 int pl = GetPredicateLengthInBytes();
9258 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9259 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9260 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
9261 for (int i = 0; i < pl; i++) {
9262 pt.Insert(i, Memory::Read<uint8_t>(address + i));
9263 }
9264 LogPRead(address, instr->GetPt());
9265 break;
9266 }
9267 default:
9268 VIXL_UNIMPLEMENTED();
9269 break;
9270 }
9271}
9272
9273void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
9274 USE(instr);
9275 switch (instr->Mask(SVELoadVectorRegisterMask)) {
9276 case LDR_z_bi: {
9277 SimVRegister& zt = ReadVRegister(instr->GetRt());
9278 int vl = GetVectorLengthInBytes();
9279 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9280 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9281 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
9282 for (int i = 0; i < vl; i++) {
9283 zt.Insert(i, Memory::Read<uint8_t>(address + i));
9284 }
9285 LogZRead(address, instr->GetRt());
9286 break;
9287 }
9288 default:
9289 VIXL_UNIMPLEMENTED();
9290 break;
9291 }
9292}
9293
9294void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
9295 const Instruction* instr) {
9296 USE(instr);
9297 switch (instr->Mask(
9298 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009299 case LD1D_z_p_bz_d_x32_scaled:
9300 VIXL_UNIMPLEMENTED();
9301 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009302 case LD1H_z_p_bz_d_x32_scaled:
9303 VIXL_UNIMPLEMENTED();
9304 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009305 case LD1SH_z_p_bz_d_x32_scaled:
9306 VIXL_UNIMPLEMENTED();
9307 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009308 case LD1SW_z_p_bz_d_x32_scaled:
9309 VIXL_UNIMPLEMENTED();
9310 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009311 case LD1W_z_p_bz_d_x32_scaled:
9312 VIXL_UNIMPLEMENTED();
9313 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009314 case LDFF1D_z_p_bz_d_x32_scaled:
9315 VIXL_UNIMPLEMENTED();
9316 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009317 case LDFF1H_z_p_bz_d_x32_scaled:
9318 VIXL_UNIMPLEMENTED();
9319 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009320 case LDFF1SH_z_p_bz_d_x32_scaled:
9321 VIXL_UNIMPLEMENTED();
9322 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009323 case LDFF1SW_z_p_bz_d_x32_scaled:
9324 VIXL_UNIMPLEMENTED();
9325 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009326 case LDFF1W_z_p_bz_d_x32_scaled:
9327 VIXL_UNIMPLEMENTED();
9328 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009329 default:
9330 VIXL_UNIMPLEMENTED();
9331 break;
9332 }
9333}
9334
9335void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
9336 const Instruction* instr) {
9337 USE(instr);
9338 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
9339 case LD1D_z_p_bz_d_64_scaled:
9340 VIXL_UNIMPLEMENTED();
9341 break;
9342 case LD1H_z_p_bz_d_64_scaled:
9343 VIXL_UNIMPLEMENTED();
9344 break;
9345 case LD1SH_z_p_bz_d_64_scaled:
9346 VIXL_UNIMPLEMENTED();
9347 break;
9348 case LD1SW_z_p_bz_d_64_scaled:
9349 VIXL_UNIMPLEMENTED();
9350 break;
9351 case LD1W_z_p_bz_d_64_scaled:
9352 VIXL_UNIMPLEMENTED();
9353 break;
9354 case LDFF1D_z_p_bz_d_64_scaled:
9355 VIXL_UNIMPLEMENTED();
9356 break;
9357 case LDFF1H_z_p_bz_d_64_scaled:
9358 VIXL_UNIMPLEMENTED();
9359 break;
9360 case LDFF1SH_z_p_bz_d_64_scaled:
9361 VIXL_UNIMPLEMENTED();
9362 break;
9363 case LDFF1SW_z_p_bz_d_64_scaled:
9364 VIXL_UNIMPLEMENTED();
9365 break;
9366 case LDFF1W_z_p_bz_d_64_scaled:
9367 VIXL_UNIMPLEMENTED();
9368 break;
9369 default:
9370 VIXL_UNIMPLEMENTED();
9371 break;
9372 }
9373}
9374
9375void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
9376 const Instruction* instr) {
9377 USE(instr);
9378 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
9379 case LD1B_z_p_bz_d_64_unscaled:
9380 VIXL_UNIMPLEMENTED();
9381 break;
9382 case LD1D_z_p_bz_d_64_unscaled:
9383 VIXL_UNIMPLEMENTED();
9384 break;
9385 case LD1H_z_p_bz_d_64_unscaled:
9386 VIXL_UNIMPLEMENTED();
9387 break;
9388 case LD1SB_z_p_bz_d_64_unscaled:
9389 VIXL_UNIMPLEMENTED();
9390 break;
9391 case LD1SH_z_p_bz_d_64_unscaled:
9392 VIXL_UNIMPLEMENTED();
9393 break;
9394 case LD1SW_z_p_bz_d_64_unscaled:
9395 VIXL_UNIMPLEMENTED();
9396 break;
9397 case LD1W_z_p_bz_d_64_unscaled:
9398 VIXL_UNIMPLEMENTED();
9399 break;
9400 case LDFF1B_z_p_bz_d_64_unscaled:
9401 VIXL_UNIMPLEMENTED();
9402 break;
9403 case LDFF1D_z_p_bz_d_64_unscaled:
9404 VIXL_UNIMPLEMENTED();
9405 break;
9406 case LDFF1H_z_p_bz_d_64_unscaled:
9407 VIXL_UNIMPLEMENTED();
9408 break;
9409 case LDFF1SB_z_p_bz_d_64_unscaled:
9410 VIXL_UNIMPLEMENTED();
9411 break;
9412 case LDFF1SH_z_p_bz_d_64_unscaled:
9413 VIXL_UNIMPLEMENTED();
9414 break;
9415 case LDFF1SW_z_p_bz_d_64_unscaled:
9416 VIXL_UNIMPLEMENTED();
9417 break;
9418 case LDFF1W_z_p_bz_d_64_unscaled:
9419 VIXL_UNIMPLEMENTED();
9420 break;
9421 default:
9422 VIXL_UNIMPLEMENTED();
9423 break;
9424 }
9425}
9426
9427void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
9428 const Instruction* instr) {
9429 USE(instr);
9430 switch (instr->Mask(
9431 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9432 case LD1B_z_p_bz_d_x32_unscaled:
9433 VIXL_UNIMPLEMENTED();
9434 break;
9435 case LD1D_z_p_bz_d_x32_unscaled:
9436 VIXL_UNIMPLEMENTED();
9437 break;
9438 case LD1H_z_p_bz_d_x32_unscaled:
9439 VIXL_UNIMPLEMENTED();
9440 break;
9441 case LD1SB_z_p_bz_d_x32_unscaled:
9442 VIXL_UNIMPLEMENTED();
9443 break;
9444 case LD1SH_z_p_bz_d_x32_unscaled:
9445 VIXL_UNIMPLEMENTED();
9446 break;
9447 case LD1SW_z_p_bz_d_x32_unscaled:
9448 VIXL_UNIMPLEMENTED();
9449 break;
9450 case LD1W_z_p_bz_d_x32_unscaled:
9451 VIXL_UNIMPLEMENTED();
9452 break;
9453 case LDFF1B_z_p_bz_d_x32_unscaled:
9454 VIXL_UNIMPLEMENTED();
9455 break;
9456 case LDFF1D_z_p_bz_d_x32_unscaled:
9457 VIXL_UNIMPLEMENTED();
9458 break;
9459 case LDFF1H_z_p_bz_d_x32_unscaled:
9460 VIXL_UNIMPLEMENTED();
9461 break;
9462 case LDFF1SB_z_p_bz_d_x32_unscaled:
9463 VIXL_UNIMPLEMENTED();
9464 break;
9465 case LDFF1SH_z_p_bz_d_x32_unscaled:
9466 VIXL_UNIMPLEMENTED();
9467 break;
9468 case LDFF1SW_z_p_bz_d_x32_unscaled:
9469 VIXL_UNIMPLEMENTED();
9470 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009471 case LDFF1W_z_p_bz_d_x32_unscaled:
9472 VIXL_UNIMPLEMENTED();
9473 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009474 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009475 VIXL_UNIMPLEMENTED();
9476 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009477 }
9478}
9479
9480void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
9481 const Instruction* instr) {
9482 USE(instr);
9483 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
9484 case LD1B_z_p_ai_d:
9485 VIXL_UNIMPLEMENTED();
9486 break;
9487 case LD1D_z_p_ai_d:
9488 VIXL_UNIMPLEMENTED();
9489 break;
9490 case LD1H_z_p_ai_d:
9491 VIXL_UNIMPLEMENTED();
9492 break;
9493 case LD1SB_z_p_ai_d:
9494 VIXL_UNIMPLEMENTED();
9495 break;
9496 case LD1SH_z_p_ai_d:
9497 VIXL_UNIMPLEMENTED();
9498 break;
9499 case LD1SW_z_p_ai_d:
9500 VIXL_UNIMPLEMENTED();
9501 break;
9502 case LD1W_z_p_ai_d:
9503 VIXL_UNIMPLEMENTED();
9504 break;
9505 case LDFF1B_z_p_ai_d:
9506 VIXL_UNIMPLEMENTED();
9507 break;
9508 case LDFF1D_z_p_ai_d:
9509 VIXL_UNIMPLEMENTED();
9510 break;
9511 case LDFF1H_z_p_ai_d:
9512 VIXL_UNIMPLEMENTED();
9513 break;
9514 case LDFF1SB_z_p_ai_d:
9515 VIXL_UNIMPLEMENTED();
9516 break;
9517 case LDFF1SH_z_p_ai_d:
9518 VIXL_UNIMPLEMENTED();
9519 break;
9520 case LDFF1SW_z_p_ai_d:
9521 VIXL_UNIMPLEMENTED();
9522 break;
9523 case LDFF1W_z_p_ai_d:
9524 VIXL_UNIMPLEMENTED();
9525 break;
9526 default:
9527 VIXL_UNIMPLEMENTED();
9528 break;
9529 }
9530}
9531
9532void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
9533 const Instruction* instr) {
9534 USE(instr);
9535 switch (
9536 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009537 case PRFB_i_p_bz_d_64_scaled:
9538 VIXL_UNIMPLEMENTED();
9539 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009540 case PRFD_i_p_bz_d_64_scaled:
9541 VIXL_UNIMPLEMENTED();
9542 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009543 case PRFH_i_p_bz_d_64_scaled:
9544 VIXL_UNIMPLEMENTED();
9545 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009546 case PRFW_i_p_bz_d_64_scaled:
9547 VIXL_UNIMPLEMENTED();
9548 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009549 default:
9550 VIXL_UNIMPLEMENTED();
9551 break;
9552 }
9553}
9554
9555void Simulator::
9556 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
9557 const Instruction* instr) {
9558 USE(instr);
9559 switch (instr->Mask(
9560 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9561 case PRFB_i_p_bz_d_x32_scaled:
9562 VIXL_UNIMPLEMENTED();
9563 break;
9564 case PRFD_i_p_bz_d_x32_scaled:
9565 VIXL_UNIMPLEMENTED();
9566 break;
9567 case PRFH_i_p_bz_d_x32_scaled:
9568 VIXL_UNIMPLEMENTED();
9569 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009570 case PRFW_i_p_bz_d_x32_scaled:
9571 VIXL_UNIMPLEMENTED();
9572 break;
9573 default:
9574 VIXL_UNIMPLEMENTED();
9575 break;
9576 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009577}
9578
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009579void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
9580 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009581 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009582 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
9583 case PRFB_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009584 VIXL_UNIMPLEMENTED();
9585 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009586 case PRFD_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009587 VIXL_UNIMPLEMENTED();
9588 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009589 case PRFH_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009590 VIXL_UNIMPLEMENTED();
9591 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009592 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009593 VIXL_UNIMPLEMENTED();
9594 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009595 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009596 VIXL_UNIMPLEMENTED();
9597 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009598 }
9599}
9600
9601void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
9602 const Instruction* instr) {
9603 USE(instr);
9604 switch (instr->Mask(SVEContiguousFirstFaultLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009605 case LDFF1B_z_p_br_u16:
9606 VIXL_UNIMPLEMENTED();
9607 break;
9608 case LDFF1B_z_p_br_u32:
9609 VIXL_UNIMPLEMENTED();
9610 break;
9611 case LDFF1B_z_p_br_u64:
9612 VIXL_UNIMPLEMENTED();
9613 break;
9614 case LDFF1B_z_p_br_u8:
9615 VIXL_UNIMPLEMENTED();
9616 break;
9617 case LDFF1D_z_p_br_u64:
9618 VIXL_UNIMPLEMENTED();
9619 break;
9620 case LDFF1H_z_p_br_u16:
9621 VIXL_UNIMPLEMENTED();
9622 break;
9623 case LDFF1H_z_p_br_u32:
9624 VIXL_UNIMPLEMENTED();
9625 break;
9626 case LDFF1H_z_p_br_u64:
9627 VIXL_UNIMPLEMENTED();
9628 break;
9629 case LDFF1SB_z_p_br_s16:
9630 VIXL_UNIMPLEMENTED();
9631 break;
9632 case LDFF1SB_z_p_br_s32:
9633 VIXL_UNIMPLEMENTED();
9634 break;
9635 case LDFF1SB_z_p_br_s64:
9636 VIXL_UNIMPLEMENTED();
9637 break;
9638 case LDFF1SH_z_p_br_s32:
9639 VIXL_UNIMPLEMENTED();
9640 break;
9641 case LDFF1SH_z_p_br_s64:
9642 VIXL_UNIMPLEMENTED();
9643 break;
9644 case LDFF1SW_z_p_br_s64:
9645 VIXL_UNIMPLEMENTED();
9646 break;
9647 case LDFF1W_z_p_br_u32:
9648 VIXL_UNIMPLEMENTED();
9649 break;
9650 case LDFF1W_z_p_br_u64:
9651 VIXL_UNIMPLEMENTED();
9652 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009653 default:
9654 VIXL_UNIMPLEMENTED();
9655 break;
9656 }
9657}
9658
9659void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
9660 const Instruction* instr) {
9661 USE(instr);
9662 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009663 case LDNF1B_z_p_bi_u16:
9664 VIXL_UNIMPLEMENTED();
9665 break;
9666 case LDNF1B_z_p_bi_u32:
9667 VIXL_UNIMPLEMENTED();
9668 break;
9669 case LDNF1B_z_p_bi_u64:
9670 VIXL_UNIMPLEMENTED();
9671 break;
9672 case LDNF1B_z_p_bi_u8:
9673 VIXL_UNIMPLEMENTED();
9674 break;
9675 case LDNF1D_z_p_bi_u64:
9676 VIXL_UNIMPLEMENTED();
9677 break;
9678 case LDNF1H_z_p_bi_u16:
9679 VIXL_UNIMPLEMENTED();
9680 break;
9681 case LDNF1H_z_p_bi_u32:
9682 VIXL_UNIMPLEMENTED();
9683 break;
9684 case LDNF1H_z_p_bi_u64:
9685 VIXL_UNIMPLEMENTED();
9686 break;
9687 case LDNF1SB_z_p_bi_s16:
9688 VIXL_UNIMPLEMENTED();
9689 break;
9690 case LDNF1SB_z_p_bi_s32:
9691 VIXL_UNIMPLEMENTED();
9692 break;
9693 case LDNF1SB_z_p_bi_s64:
9694 VIXL_UNIMPLEMENTED();
9695 break;
9696 case LDNF1SH_z_p_bi_s32:
9697 VIXL_UNIMPLEMENTED();
9698 break;
9699 case LDNF1SH_z_p_bi_s64:
9700 VIXL_UNIMPLEMENTED();
9701 break;
9702 case LDNF1SW_z_p_bi_s64:
9703 VIXL_UNIMPLEMENTED();
9704 break;
9705 case LDNF1W_z_p_bi_u32:
9706 VIXL_UNIMPLEMENTED();
9707 break;
9708 case LDNF1W_z_p_bi_u64:
9709 VIXL_UNIMPLEMENTED();
9710 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009711 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009712 VIXL_UNIMPLEMENTED();
9713 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009714 }
9715}
9716
9717void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
9718 const Instruction* instr) {
9719 USE(instr);
9720 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
9721 case LDNT1B_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009722 VIXL_UNIMPLEMENTED();
9723 break;
9724 case LDNT1D_z_p_bi_contiguous:
9725 VIXL_UNIMPLEMENTED();
9726 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009727 case LDNT1H_z_p_bi_contiguous:
9728 VIXL_UNIMPLEMENTED();
9729 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009730 case LDNT1W_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009731 VIXL_UNIMPLEMENTED();
9732 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009733 default:
9734 VIXL_UNIMPLEMENTED();
9735 break;
9736 }
9737}
9738
9739void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
9740 const Instruction* instr) {
9741 USE(instr);
9742 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
9743 case LDNT1B_z_p_br_contiguous:
9744 VIXL_UNIMPLEMENTED();
9745 break;
9746 case LDNT1D_z_p_br_contiguous:
9747 VIXL_UNIMPLEMENTED();
9748 break;
9749 case LDNT1H_z_p_br_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009750 VIXL_UNIMPLEMENTED();
9751 break;
9752 case LDNT1W_z_p_br_contiguous:
9753 VIXL_UNIMPLEMENTED();
9754 break;
9755 default:
9756 VIXL_UNIMPLEMENTED();
9757 break;
9758 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009759}
9760
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009761void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
9762 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009763 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009764 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
9765 case LD1RQB_z_p_bi_u8:
9766 VIXL_UNIMPLEMENTED();
9767 break;
9768 case LD1RQD_z_p_bi_u64:
9769 VIXL_UNIMPLEMENTED();
9770 break;
9771 case LD1RQH_z_p_bi_u16:
9772 VIXL_UNIMPLEMENTED();
9773 break;
9774 case LD1RQW_z_p_bi_u32:
9775 VIXL_UNIMPLEMENTED();
9776 break;
9777 default:
9778 VIXL_UNIMPLEMENTED();
9779 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009780 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009781}
9782
9783void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
9784 const Instruction* instr) {
9785 USE(instr);
9786 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
9787 case LD1RQB_z_p_br_contiguous:
9788 VIXL_UNIMPLEMENTED();
9789 break;
9790 case LD1RQD_z_p_br_contiguous:
9791 VIXL_UNIMPLEMENTED();
9792 break;
9793 case LD1RQH_z_p_br_contiguous:
9794 VIXL_UNIMPLEMENTED();
9795 break;
9796 case LD1RQW_z_p_br_contiguous:
9797 VIXL_UNIMPLEMENTED();
9798 break;
9799 default:
9800 VIXL_UNIMPLEMENTED();
9801 break;
9802 }
9803}
9804
9805void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
9806 const Instruction* instr) {
9807 USE(instr);
9808 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
9809 case LD2B_z_p_bi_contiguous:
9810 VIXL_UNIMPLEMENTED();
9811 break;
9812 case LD2D_z_p_bi_contiguous:
9813 VIXL_UNIMPLEMENTED();
9814 break;
9815 case LD2H_z_p_bi_contiguous:
9816 VIXL_UNIMPLEMENTED();
9817 break;
9818 case LD2W_z_p_bi_contiguous:
9819 VIXL_UNIMPLEMENTED();
9820 break;
9821 case LD3B_z_p_bi_contiguous:
9822 VIXL_UNIMPLEMENTED();
9823 break;
9824 case LD3D_z_p_bi_contiguous:
9825 VIXL_UNIMPLEMENTED();
9826 break;
9827 case LD3H_z_p_bi_contiguous:
9828 VIXL_UNIMPLEMENTED();
9829 break;
9830 case LD3W_z_p_bi_contiguous:
9831 VIXL_UNIMPLEMENTED();
9832 break;
9833 case LD4B_z_p_bi_contiguous:
9834 VIXL_UNIMPLEMENTED();
9835 break;
9836 case LD4D_z_p_bi_contiguous:
9837 VIXL_UNIMPLEMENTED();
9838 break;
9839 case LD4H_z_p_bi_contiguous:
9840 VIXL_UNIMPLEMENTED();
9841 break;
9842 case LD4W_z_p_bi_contiguous:
9843 VIXL_UNIMPLEMENTED();
9844 break;
9845 default:
9846 VIXL_UNIMPLEMENTED();
9847 break;
9848 }
9849}
9850
9851void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
9852 const Instruction* instr) {
9853 USE(instr);
9854 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
9855 case LD2B_z_p_br_contiguous:
9856 VIXL_UNIMPLEMENTED();
9857 break;
9858 case LD2D_z_p_br_contiguous:
9859 VIXL_UNIMPLEMENTED();
9860 break;
9861 case LD2H_z_p_br_contiguous:
9862 VIXL_UNIMPLEMENTED();
9863 break;
9864 case LD2W_z_p_br_contiguous:
9865 VIXL_UNIMPLEMENTED();
9866 break;
9867 case LD3B_z_p_br_contiguous:
9868 VIXL_UNIMPLEMENTED();
9869 break;
9870 case LD3D_z_p_br_contiguous:
9871 VIXL_UNIMPLEMENTED();
9872 break;
9873 case LD3H_z_p_br_contiguous:
9874 VIXL_UNIMPLEMENTED();
9875 break;
9876 case LD3W_z_p_br_contiguous:
9877 VIXL_UNIMPLEMENTED();
9878 break;
9879 case LD4B_z_p_br_contiguous:
9880 VIXL_UNIMPLEMENTED();
9881 break;
9882 case LD4D_z_p_br_contiguous:
9883 VIXL_UNIMPLEMENTED();
9884 break;
9885 case LD4H_z_p_br_contiguous:
9886 VIXL_UNIMPLEMENTED();
9887 break;
9888 case LD4W_z_p_br_contiguous:
9889 VIXL_UNIMPLEMENTED();
9890 break;
9891 default:
9892 VIXL_UNIMPLEMENTED();
9893 break;
9894 }
9895}
9896
9897void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
9898 const Instruction* instr) {
9899 USE(instr);
9900 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
9901 case ST1H_z_p_bz_s_x32_scaled:
9902 VIXL_UNIMPLEMENTED();
9903 break;
9904 case ST1W_z_p_bz_s_x32_scaled:
9905 VIXL_UNIMPLEMENTED();
9906 break;
9907 default:
9908 VIXL_UNIMPLEMENTED();
9909 break;
9910 }
9911}
9912
9913void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
9914 const Instruction* instr) {
9915 USE(instr);
9916 switch (
9917 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
9918 case ST1B_z_p_bz_s_x32_unscaled:
9919 VIXL_UNIMPLEMENTED();
9920 break;
9921 case ST1H_z_p_bz_s_x32_unscaled:
9922 VIXL_UNIMPLEMENTED();
9923 break;
9924 case ST1W_z_p_bz_s_x32_unscaled:
9925 VIXL_UNIMPLEMENTED();
9926 break;
9927 default:
9928 VIXL_UNIMPLEMENTED();
9929 break;
9930 }
9931}
9932
9933void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
9934 const Instruction* instr) {
9935 USE(instr);
9936 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
9937 case ST1B_z_p_ai_s:
9938 VIXL_UNIMPLEMENTED();
9939 break;
9940 case ST1H_z_p_ai_s:
9941 VIXL_UNIMPLEMENTED();
9942 break;
9943 case ST1W_z_p_ai_s:
9944 VIXL_UNIMPLEMENTED();
9945 break;
9946 default:
9947 VIXL_UNIMPLEMENTED();
9948 break;
9949 }
9950}
9951
9952void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
9953 const Instruction* instr) {
9954 USE(instr);
9955 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
9956 case ST1D_z_p_bz_d_64_scaled:
9957 VIXL_UNIMPLEMENTED();
9958 break;
9959 case ST1H_z_p_bz_d_64_scaled:
9960 VIXL_UNIMPLEMENTED();
9961 break;
9962 case ST1W_z_p_bz_d_64_scaled:
9963 VIXL_UNIMPLEMENTED();
9964 break;
9965 default:
9966 VIXL_UNIMPLEMENTED();
9967 break;
9968 }
9969}
9970
9971void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
9972 const Instruction* instr) {
9973 USE(instr);
9974 switch (
9975 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
9976 case ST1B_z_p_bz_d_64_unscaled:
9977 VIXL_UNIMPLEMENTED();
9978 break;
9979 case ST1D_z_p_bz_d_64_unscaled:
9980 VIXL_UNIMPLEMENTED();
9981 break;
9982 case ST1H_z_p_bz_d_64_unscaled:
9983 VIXL_UNIMPLEMENTED();
9984 break;
9985 case ST1W_z_p_bz_d_64_unscaled:
9986 VIXL_UNIMPLEMENTED();
9987 break;
9988 default:
9989 VIXL_UNIMPLEMENTED();
9990 break;
9991 }
9992}
9993
9994void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
9995 const Instruction* instr) {
9996 USE(instr);
9997 switch (instr->Mask(
9998 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9999 case ST1D_z_p_bz_d_x32_scaled:
10000 VIXL_UNIMPLEMENTED();
10001 break;
10002 case ST1H_z_p_bz_d_x32_scaled:
10003 VIXL_UNIMPLEMENTED();
10004 break;
10005 case ST1W_z_p_bz_d_x32_scaled:
10006 VIXL_UNIMPLEMENTED();
10007 break;
10008 default:
10009 VIXL_UNIMPLEMENTED();
10010 break;
10011 }
10012}
10013
10014void Simulator::
10015 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
10016 const Instruction* instr) {
10017 USE(instr);
10018 switch (instr->Mask(
10019 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
10020 case ST1B_z_p_bz_d_x32_unscaled:
10021 VIXL_UNIMPLEMENTED();
10022 break;
10023 case ST1D_z_p_bz_d_x32_unscaled:
10024 VIXL_UNIMPLEMENTED();
10025 break;
10026 case ST1H_z_p_bz_d_x32_unscaled:
10027 VIXL_UNIMPLEMENTED();
10028 break;
10029 case ST1W_z_p_bz_d_x32_unscaled:
10030 VIXL_UNIMPLEMENTED();
10031 break;
10032 default:
10033 VIXL_UNIMPLEMENTED();
10034 break;
10035 }
10036}
10037
10038void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
10039 const Instruction* instr) {
10040 USE(instr);
10041 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
10042 case ST1B_z_p_ai_d:
10043 VIXL_UNIMPLEMENTED();
10044 break;
10045 case ST1D_z_p_ai_d:
10046 VIXL_UNIMPLEMENTED();
10047 break;
10048 case ST1H_z_p_ai_d:
10049 VIXL_UNIMPLEMENTED();
10050 break;
10051 case ST1W_z_p_ai_d:
10052 VIXL_UNIMPLEMENTED();
10053 break;
10054 default:
10055 VIXL_UNIMPLEMENTED();
10056 break;
10057 }
10058}
10059
10060void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
10061 const Instruction* instr) {
10062 USE(instr);
10063 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
10064 case STNT1B_z_p_bi_contiguous:
10065 VIXL_UNIMPLEMENTED();
10066 break;
10067 case STNT1D_z_p_bi_contiguous:
10068 VIXL_UNIMPLEMENTED();
10069 break;
10070 case STNT1H_z_p_bi_contiguous:
10071 VIXL_UNIMPLEMENTED();
10072 break;
10073 case STNT1W_z_p_bi_contiguous:
10074 VIXL_UNIMPLEMENTED();
10075 break;
10076 default:
10077 VIXL_UNIMPLEMENTED();
10078 break;
10079 }
10080}
10081
10082void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
10083 const Instruction* instr) {
10084 USE(instr);
10085 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
10086 case STNT1B_z_p_br_contiguous:
10087 VIXL_UNIMPLEMENTED();
10088 break;
10089 case STNT1D_z_p_br_contiguous:
10090 VIXL_UNIMPLEMENTED();
10091 break;
10092 case STNT1H_z_p_br_contiguous:
10093 VIXL_UNIMPLEMENTED();
10094 break;
10095 case STNT1W_z_p_br_contiguous:
10096 VIXL_UNIMPLEMENTED();
10097 break;
10098 default:
10099 VIXL_UNIMPLEMENTED();
10100 break;
10101 }
10102}
10103
10104void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
10105 const Instruction* instr) {
10106 USE(instr);
10107 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
10108 case ST1B_z_p_bi:
10109 case ST1D_z_p_bi:
10110 case ST1H_z_p_bi:
10111 case ST1W_z_p_bi: {
10112 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010113 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10114 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
10115 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10116 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10117 uint64_t offset =
10118 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010119 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010120 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010121 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010122 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10123 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010124 ReadPRegister(instr->GetPgLow8()),
10125 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010126 addr);
10127 break;
10128 }
10129 default:
10130 VIXL_UNIMPLEMENTED();
10131 break;
10132 }
10133}
10134
10135void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
10136 const Instruction* instr) {
10137 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
10138 case ST1B_z_p_br:
10139 case ST1D_z_p_br:
10140 case ST1H_z_p_br:
10141 case ST1W_z_p_br: {
10142 uint64_t offset = ReadXRegister(instr->GetRm());
10143 offset <<= instr->ExtractBits(24, 23);
10144 VectorFormat vform =
10145 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
10146 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010147 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
10148 SVEStructuredStoreHelper(vform,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010149 ReadPRegister(instr->GetPgLow8()),
10150 instr->GetRt(),
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010151 addr);
10152 break;
10153 }
10154 default:
10155 VIXL_UNIMPLEMENTED();
10156 break;
10157 }
10158}
10159
10160void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
10161 const Instruction* instr) {
10162 VectorFormat vform = instr->GetSVEVectorFormat();
10163 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10164 SimVRegister z_result;
10165
10166 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
10167 case CPY_z_p_v:
10168 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
10169 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
10170 break;
10171 default:
10172 VIXL_UNIMPLEMENTED();
10173 break;
10174 }
10175}
10176
10177void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
10178 const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010179 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
10180 case ST2B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010181 case ST2D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010182 case ST2H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010183 case ST2W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010184 case ST3B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010185 case ST3D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010186 case ST3H_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010187 case ST3W_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010188 case ST4B_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010189 case ST4D_z_p_bi_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010190 case ST4H_z_p_bi_contiguous:
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010191 case ST4W_z_p_bi_contiguous: {
10192 int vl = GetVectorLengthInBytes();
10193 int msz = instr->ExtractBits(24, 23);
10194 int reg_count = instr->ExtractBits(22, 21) + 1;
10195 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10196 LogicSVEAddressVector addr(
10197 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10198 addr.SetMsizeInBytesLog2(msz);
10199 addr.SetRegCount(reg_count);
10200 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10201 ReadPRegister(instr->GetPgLow8()),
10202 instr->GetRt(),
10203 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010204 break;
Jacob Bramleyd4dd9c22019-11-04 16:44:01 +000010205 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010206 default:
10207 VIXL_UNIMPLEMENTED();
10208 break;
10209 }
10210}
10211
10212void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
10213 const Instruction* instr) {
10214 USE(instr);
10215 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
10216 case ST2B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010217 case ST2D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010218 case ST2H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010219 case ST2W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010220 case ST3B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010221 case ST3D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010222 case ST3H_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010223 case ST3W_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010224 case ST4B_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010225 case ST4D_z_p_br_contiguous:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010226 case ST4H_z_p_br_contiguous:
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010227 case ST4W_z_p_br_contiguous: {
10228 int msz = instr->ExtractBits(24, 23);
10229 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10230 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10231 LogicSVEAddressVector addr(
10232 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10233 addr.SetMsizeInBytesLog2(msz);
10234 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10235 SVEStructuredStoreHelper(vform,
10236 ReadPRegister(instr->GetPgLow8()),
10237 instr->GetRt(),
10238 addr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010239 break;
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000010240 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010241 default:
10242 VIXL_UNIMPLEMENTED();
10243 break;
10244 }
10245}
10246
10247void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
10248 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
10249 case STR_p_bi: {
10250 SimPRegister& pt = ReadPRegister(instr->GetPt());
10251 int pl = GetPredicateLengthInBytes();
10252 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10253 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10254 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
10255 for (int i = 0; i < pl; i++) {
10256 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
10257 }
10258 LogPWrite(address, instr->GetPt());
10259 break;
10260 }
10261 default:
10262 VIXL_UNIMPLEMENTED();
10263 break;
10264 }
10265}
10266
10267void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
10268 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
10269 case STR_z_bi: {
10270 SimVRegister& zt = ReadVRegister(instr->GetRt());
10271 int vl = GetVectorLengthInBytes();
10272 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10273 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10274 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
10275 for (int i = 0; i < vl; i++) {
10276 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
10277 }
10278 LogZWrite(address, instr->GetRt());
10279 break;
10280 }
10281 default:
10282 VIXL_UNIMPLEMENTED();
10283 break;
10284 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010285}
10286
10287void Simulator::VisitSVEMulIndex(const Instruction* instr) {
10288 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010289 switch (instr->Mask(SVEMulIndexMask)) {
10290 case SDOT_z_zzzi_d:
10291 VIXL_UNIMPLEMENTED();
10292 break;
10293 case SDOT_z_zzzi_s:
10294 VIXL_UNIMPLEMENTED();
10295 break;
10296 case UDOT_z_zzzi_d:
10297 VIXL_UNIMPLEMENTED();
10298 break;
10299 case UDOT_z_zzzi_s:
10300 VIXL_UNIMPLEMENTED();
10301 break;
10302 default:
10303 VIXL_UNIMPLEMENTED();
10304 break;
10305 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010306}
10307
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010308void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010309 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010310 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010311 case BRKAS_p_p_p_z:
10312 VIXL_UNIMPLEMENTED();
10313 break;
10314 case BRKA_p_p_p:
10315 VIXL_UNIMPLEMENTED();
10316 break;
10317 case BRKBS_p_p_p_z:
10318 VIXL_UNIMPLEMENTED();
10319 break;
10320 case BRKB_p_p_p:
10321 VIXL_UNIMPLEMENTED();
10322 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010323 default:
10324 VIXL_UNIMPLEMENTED();
10325 break;
10326 }
10327}
10328
10329void Simulator::VisitSVEPropagateBreakToNextPartition(
10330 const Instruction* instr) {
10331 USE(instr);
10332 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010333 case BRKNS_p_p_pp:
10334 VIXL_UNIMPLEMENTED();
10335 break;
10336 case BRKN_p_p_pp:
10337 VIXL_UNIMPLEMENTED();
10338 break;
10339 default:
10340 VIXL_UNIMPLEMENTED();
10341 break;
10342 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010343}
10344
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010345void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010346 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010347 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010348 case PUNPKHI_p_p:
10349 VIXL_UNIMPLEMENTED();
10350 break;
10351 case PUNPKLO_p_p:
10352 VIXL_UNIMPLEMENTED();
10353 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010354 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010355 VIXL_UNIMPLEMENTED();
10356 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010357 }
10358}
10359
10360void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
10361 USE(instr);
10362 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010363 case TRN1_p_pp:
10364 VIXL_UNIMPLEMENTED();
10365 break;
10366 case TRN2_p_pp:
10367 VIXL_UNIMPLEMENTED();
10368 break;
10369 case UZP1_p_pp:
10370 VIXL_UNIMPLEMENTED();
10371 break;
10372 case UZP2_p_pp:
10373 VIXL_UNIMPLEMENTED();
10374 break;
10375 case ZIP1_p_pp:
10376 VIXL_UNIMPLEMENTED();
10377 break;
10378 case ZIP2_p_pp:
10379 VIXL_UNIMPLEMENTED();
10380 break;
10381 default:
10382 VIXL_UNIMPLEMENTED();
10383 break;
10384 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010385}
10386
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010387void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
10388 USE(instr);
10389 switch (instr->Mask(SVEReversePredicateElementsMask)) {
10390 case REV_p_p:
10391 VIXL_UNIMPLEMENTED();
10392 break;
10393 default:
10394 VIXL_UNIMPLEMENTED();
10395 break;
10396 }
10397}
10398
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010399void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
10400 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010401 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
10402 case EXT_z_zi_des:
10403 VIXL_UNIMPLEMENTED();
10404 break;
10405 default:
10406 VIXL_UNIMPLEMENTED();
10407 break;
10408 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010409}
10410
10411void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
10412 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010413 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
10414 case TRN1_z_zz:
10415 VIXL_UNIMPLEMENTED();
10416 break;
10417 case TRN2_z_zz:
10418 VIXL_UNIMPLEMENTED();
10419 break;
10420 case UZP1_z_zz:
10421 VIXL_UNIMPLEMENTED();
10422 break;
10423 case UZP2_z_zz:
10424 VIXL_UNIMPLEMENTED();
10425 break;
10426 case ZIP1_z_zz:
10427 VIXL_UNIMPLEMENTED();
10428 break;
10429 case ZIP2_z_zz:
10430 VIXL_UNIMPLEMENTED();
10431 break;
10432 default:
10433 VIXL_UNIMPLEMENTED();
10434 break;
10435 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010436}
10437
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010438void Simulator::VisitSVEConditionallyBroadcastElementToVector(
10439 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010440 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010441 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010442 case CLASTA_z_p_zz:
10443 VIXL_UNIMPLEMENTED();
10444 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010445 case CLASTB_z_p_zz:
10446 VIXL_UNIMPLEMENTED();
10447 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010448 default:
10449 VIXL_UNIMPLEMENTED();
10450 break;
10451 }
10452}
10453
10454void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
10455 const Instruction* instr) {
10456 USE(instr);
10457 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
10458 case CLASTA_v_p_z:
10459 VIXL_UNIMPLEMENTED();
10460 break;
10461 case CLASTB_v_p_z:
10462 VIXL_UNIMPLEMENTED();
10463 break;
10464 default:
10465 VIXL_UNIMPLEMENTED();
10466 break;
10467 }
10468}
10469
10470void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
10471 const Instruction* instr) {
10472 USE(instr);
10473 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
10474 case CLASTA_r_p_z:
10475 VIXL_UNIMPLEMENTED();
10476 break;
10477 case CLASTB_r_p_z:
10478 VIXL_UNIMPLEMENTED();
10479 break;
10480 default:
10481 VIXL_UNIMPLEMENTED();
10482 break;
10483 }
10484}
10485
10486void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
10487 const Instruction* instr) {
10488 USE(instr);
10489 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
10490 case LASTA_v_p_z:
10491 VIXL_UNIMPLEMENTED();
10492 break;
10493 case LASTB_v_p_z:
10494 VIXL_UNIMPLEMENTED();
10495 break;
10496 default:
10497 VIXL_UNIMPLEMENTED();
10498 break;
10499 }
10500}
10501
10502void Simulator::VisitSVEExtractElementToGeneralRegister(
10503 const Instruction* instr) {
10504 USE(instr);
10505 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
10506 case LASTA_r_p_z:
10507 VIXL_UNIMPLEMENTED();
10508 break;
10509 case LASTB_r_p_z:
10510 VIXL_UNIMPLEMENTED();
10511 break;
10512 default:
10513 VIXL_UNIMPLEMENTED();
10514 break;
10515 }
10516}
10517
10518void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
10519 USE(instr);
10520 switch (instr->Mask(SVECompressActiveElementsMask)) {
10521 case COMPACT_z_p_z:
10522 VIXL_UNIMPLEMENTED();
10523 break;
10524 default:
10525 VIXL_UNIMPLEMENTED();
10526 break;
10527 }
10528}
10529
10530void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
10531 const Instruction* instr) {
10532 VectorFormat vform = instr->GetSVEVectorFormat();
10533 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10534 SimVRegister z_result;
10535
10536 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010537 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010010538 dup_immediate(vform,
10539 z_result,
10540 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10541 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010542 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010543 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010544 VIXL_UNIMPLEMENTED();
10545 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010546 }
10547}
10548
10549void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010550 VectorFormat vform = instr->GetSVEVectorFormat();
10551 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
10552 SimVRegister& zd = ReadVRegister(instr->GetRd());
10553
10554 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010555 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010556 case CPY_z_p_i: {
10557 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
10558 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
10559 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010560 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010561 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010562 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010563 VIXL_UNIMPLEMENTED();
10564 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010565 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010566
10567 if (instr->ExtractBit(14) != 0) {
10568 mov_merging(vform, zd, pg, result);
10569 } else {
10570 mov_zeroing(vform, zd, pg, result);
10571 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010572}
10573
10574void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
10575 USE(instr);
10576 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010577 case RBIT_z_p_z:
10578 VIXL_UNIMPLEMENTED();
10579 break;
10580 case REVB_z_z:
10581 VIXL_UNIMPLEMENTED();
10582 break;
10583 case REVH_z_z:
10584 VIXL_UNIMPLEMENTED();
10585 break;
10586 case REVW_z_z:
10587 VIXL_UNIMPLEMENTED();
10588 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010589 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010590 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010591 break;
10592 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010593}
10594
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010595void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010596 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010597 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
10598 case SPLICE_z_p_zz_des:
10599 VIXL_UNIMPLEMENTED();
10600 break;
10601 default:
10602 VIXL_UNIMPLEMENTED();
10603 break;
10604 }
10605}
TatWai Chong4f28df72019-08-14 17:50:30 -070010606
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010607void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
10608 SimVRegister& zd = ReadVRegister(instr->GetRd());
10609 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
10610 case DUP_z_r:
10611 dup_immediate(instr->GetSVEVectorFormat(),
10612 zd,
10613 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10614 break;
10615 default:
10616 VIXL_UNIMPLEMENTED();
10617 break;
10618 }
10619}
10620
10621void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
10622 SimVRegister& zd = ReadVRegister(instr->GetRd());
10623 VectorFormat vform = instr->GetSVEVectorFormat();
10624 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
10625 case INSR_z_v:
10626 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
10627 break;
10628 default:
10629 VIXL_UNIMPLEMENTED();
10630 break;
10631 }
10632}
10633
10634void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
10635 SimVRegister& zd = ReadVRegister(instr->GetRd());
10636 VectorFormat vform = instr->GetSVEVectorFormat();
10637 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
10638 case INSR_z_r:
10639 insr(vform, zd, ReadXRegister(instr->GetRn()));
10640 break;
10641 default:
10642 VIXL_UNIMPLEMENTED();
10643 break;
10644 }
10645}
10646
10647void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
10648 SimVRegister& zd = ReadVRegister(instr->GetRd());
10649 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070010650 case DUP_z_zi: {
10651 std::pair<int, int> index_and_lane_size =
10652 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10653 int index = index_and_lane_size.first;
10654 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
10655 VectorFormat vform =
10656 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
10657 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
10658 // Out of bounds, set the destination register to zero.
10659 dup_immediate(kFormatVnD, zd, 0);
10660 } else {
10661 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
10662 }
10663 return;
10664 }
TatWai Chong4f28df72019-08-14 17:50:30 -070010665 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010666 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070010667 break;
10668 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010669}
TatWai Chong4f28df72019-08-14 17:50:30 -070010670
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010671void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
10672 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070010673 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010674 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010675 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010676 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010677 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010678 default:
10679 VIXL_UNIMPLEMENTED();
10680 break;
10681 }
10682}
10683
10684void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
10685 SimVRegister& zd = ReadVRegister(instr->GetRd());
10686 VectorFormat vform = instr->GetSVEVectorFormat();
10687 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010688 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010689 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010690 break;
10691 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010692 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010693 break;
10694 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010695 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010696 break;
10697 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010698 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
10699 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010700 default:
10701 VIXL_UNIMPLEMENTED();
10702 break;
10703 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010704}
10705
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010706void Simulator::VisitSVETableLookup(const Instruction* instr) {
10707 SimVRegister& zd = ReadVRegister(instr->GetRd());
10708 switch (instr->Mask(SVETableLookupMask)) {
10709 case TBL_z_zz_1:
10710 Table(instr->GetSVEVectorFormat(),
10711 zd,
10712 ReadVRegister(instr->GetRn()),
10713 ReadVRegister(instr->GetRm()));
10714 return;
10715 default:
10716 break;
10717 }
10718}
10719
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010720void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
10721 USE(instr);
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010722
10723 VectorFormat vform = instr->GetSVEVectorFormat();
10724 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10725 SimPRegister& pn = ReadPRegister(instr->GetPn());
10726
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010727 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010728 case CNTP_r_p_p: {
10729 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010730 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010731 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010732 default:
10733 VIXL_UNIMPLEMENTED();
10734 break;
10735 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010736}
10737
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010738void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
10739 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chongf4fa8222019-06-17 12:08:14 -070010740 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010741 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010742 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010743 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010744 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010745 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010746 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010747 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010748 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010749 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010750 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010751 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010752 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010753 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010754 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070010755 case SEL_p_p_pp: {
10756 FlagsUpdate flags =
10757 instr->Mask(SVEPredicateLogicalSetFlagsBit) ? SetFlags : LeaveFlags;
10758 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
10759 ReadPRegister(instr->GetPd()),
10760 ReadPRegister(instr->ExtractBits(13, 10)),
10761 ReadPRegister(instr->GetPn()),
10762 ReadPRegister(instr->GetPm()),
10763 flags);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010764 break;
TatWai Chongf4fa8222019-06-17 12:08:14 -070010765 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010766 default:
10767 VIXL_UNIMPLEMENTED();
10768 break;
10769 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010770}
10771
Jacob Bramley0ce75842019-07-17 18:12:50 +010010772void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010773 USE(instr);
Jacob Bramley0ce75842019-07-17 18:12:50 +010010774 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
10775 LogicPRegister pdn = ReadPRegister(instr->GetPd());
10776 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010777 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010010778 pfirst(pdn, pg, pdn);
10779 // TODO: Is this broken when pg == pdn?
10780 PredTest(kFormatVnB, pg, pdn);
10781 break;
10782 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010783 VIXL_UNIMPLEMENTED();
10784 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010785 }
10786}
10787
10788void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
10789 USE(instr);
10790 // This group only contains PTRUE{S}, and there are no unallocated encodings.
10791 VIXL_STATIC_ASSERT(
10792 SVEPredicateInitializeMask ==
10793 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
10794 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
10795 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
10796
10797 LogicPRegister pdn = ReadPRegister(instr->GetPd());
10798 VectorFormat vform = instr->GetSVEVectorFormat();
10799
10800 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
10801 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
10802}
10803
10804void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
10805 USE(instr);
10806 // This group only contains PNEXT, and there are no unallocated encodings.
10807 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
10808 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
10809
10810 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
10811 LogicPRegister pdn = ReadPRegister(instr->GetPd());
10812 VectorFormat vform = instr->GetSVEVectorFormat();
10813
10814 pnext(vform, pdn, pg, pdn);
10815 // TODO: Is this broken when pg == pdn?
10816 PredTest(vform, pg, pdn);
10817}
10818
10819void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
10820 const Instruction* instr) {
10821 USE(instr);
10822 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
10823 case RDFFR_p_p_f:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010824 case RDFFRS_p_p_f:
10825 VIXL_UNIMPLEMENTED();
10826 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010827 default:
10828 VIXL_UNIMPLEMENTED();
10829 break;
10830 }
10831}
10832
10833void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
10834 const Instruction* instr) {
10835 USE(instr);
10836 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010837 case RDFFR_p_f:
10838 VIXL_UNIMPLEMENTED();
10839 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010840 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010841 VIXL_UNIMPLEMENTED();
10842 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010843 }
10844}
10845
10846void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
10847 USE(instr);
10848 switch (instr->Mask(SVEPredicateTestMask)) {
10849 case PTEST_p_p:
10850 PredTest(kFormatVnB,
10851 ReadPRegister(instr->ExtractBits(13, 10)),
10852 ReadPRegister(instr->GetPn()));
10853 break;
10854 default:
10855 VIXL_UNIMPLEMENTED();
10856 break;
10857 }
10858}
10859
10860void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
10861 USE(instr);
10862 switch (instr->Mask(SVEPredicateZeroMask)) {
10863 case PFALSE_p:
10864 pfalse(ReadPRegister(instr->GetPd()));
10865 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010866 default:
10867 VIXL_UNIMPLEMENTED();
10868 break;
10869 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010870}
10871
10872void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
10873 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010874 switch (instr->Mask(SVEPropagateBreakMask)) {
10875 case BRKPAS_p_p_pp:
10876 VIXL_UNIMPLEMENTED();
10877 break;
10878 case BRKPA_p_p_pp:
10879 VIXL_UNIMPLEMENTED();
10880 break;
10881 case BRKPBS_p_p_pp:
10882 VIXL_UNIMPLEMENTED();
10883 break;
10884 case BRKPB_p_p_pp:
10885 VIXL_UNIMPLEMENTED();
10886 break;
10887 default:
10888 VIXL_UNIMPLEMENTED();
10889 break;
10890 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010891}
10892
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010893void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
10894 uint64_t length = 0;
10895 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
10896 case ADDPL_r_ri:
10897 length = GetPredicateLengthInBytes();
10898 break;
10899 case ADDVL_r_ri:
10900 length = GetVectorLengthInBytes();
10901 break;
10902 default:
10903 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010904 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010010905 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010906 WriteXRegister(instr->GetRd(),
10907 base + (length * instr->GetImmSVEVLScale()),
10908 LogRegWrites,
10909 Reg31IsStackPointer);
10910}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010010911
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010912void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
10913 int64_t scale = instr->GetImmSVEVLScale();
10914
10915 switch (instr->Mask(SVEStackFrameSizeMask)) {
10916 case RDVL_r_i:
10917 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
10918 break;
10919 default:
10920 VIXL_UNIMPLEMENTED();
10921 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010922}
10923
10924void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
10925 USE(instr);
TatWai Chong6205eb42019-09-24 10:07:20 +010010926
10927 // The only instruction in this group is `sel`, and there are no unused
10928 // encodings.
10929 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
10930
10931 VectorFormat vform = instr->GetSVEVectorFormat();
10932 SimVRegister& zd = ReadVRegister(instr->GetRd());
10933 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10934 SimVRegister& zn = ReadVRegister(instr->GetRn());
10935 SimVRegister& zm = ReadVRegister(instr->GetRm());
10936
10937 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010938}
10939
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010940void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010941 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010942 switch (instr->Mask(SVEFFRInitialiseMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010943 case SETFFR_f:
10944 VIXL_UNIMPLEMENTED();
10945 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010946 default:
10947 VIXL_UNIMPLEMENTED();
10948 break;
10949 }
10950}
10951
10952void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
10953 USE(instr);
10954 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010955 case WRFFR_f_p:
10956 VIXL_UNIMPLEMENTED();
10957 break;
10958 default:
10959 VIXL_UNIMPLEMENTED();
10960 break;
10961 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010962}
Alexandre Ramesd3832962016-07-04 15:03:43 +010010963
TatWai Chong6205eb42019-09-24 10:07:20 +010010964void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
10965 USE(instr);
10966 bool is_signed;
10967 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
10968 case LD1B_z_p_bi_u8:
10969 case LD1B_z_p_bi_u16:
10970 case LD1B_z_p_bi_u32:
10971 case LD1B_z_p_bi_u64:
10972 case LD1H_z_p_bi_u16:
10973 case LD1H_z_p_bi_u32:
10974 case LD1H_z_p_bi_u64:
10975 case LD1W_z_p_bi_u32:
10976 case LD1W_z_p_bi_u64:
10977 case LD1D_z_p_bi_u64:
10978 is_signed = false;
10979 break;
10980 case LD1SB_z_p_bi_s16:
10981 case LD1SB_z_p_bi_s32:
10982 case LD1SB_z_p_bi_s64:
10983 case LD1SH_z_p_bi_s32:
10984 case LD1SH_z_p_bi_s64:
10985 case LD1SW_z_p_bi_s64:
10986 is_signed = true;
10987 break;
10988 default:
10989 // This encoding group is complete, so no other values should be possible.
10990 VIXL_UNREACHABLE();
10991 is_signed = false;
10992 break;
10993 }
10994
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010995 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010010996 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
10997 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010998 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10999 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
11000 uint64_t offset =
11001 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011002 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010011003 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011004 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11005 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011006 ReadPRegister(instr->GetPgLow8()),
11007 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011008 addr,
11009 is_signed);
11010}
11011
11012void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
11013 const Instruction* instr) {
11014 bool is_signed;
11015 USE(instr);
11016 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
11017 case LD1B_z_p_br_u8:
11018 case LD1B_z_p_br_u16:
11019 case LD1B_z_p_br_u32:
11020 case LD1B_z_p_br_u64:
11021 case LD1H_z_p_br_u16:
11022 case LD1H_z_p_br_u32:
11023 case LD1H_z_p_br_u64:
11024 case LD1W_z_p_br_u32:
11025 case LD1W_z_p_br_u64:
11026 case LD1D_z_p_br_u64:
11027 is_signed = false;
11028 break;
11029 case LD1SB_z_p_br_s16:
11030 case LD1SB_z_p_br_s32:
11031 case LD1SB_z_p_br_s64:
11032 case LD1SH_z_p_br_s32:
11033 case LD1SH_z_p_br_s64:
11034 case LD1SW_z_p_br_s64:
11035 is_signed = true;
11036 break;
11037 default:
11038 // This encoding group is complete, so no other values should be possible.
11039 VIXL_UNREACHABLE();
11040 is_signed = false;
11041 break;
11042 }
11043
11044 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11045 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11046 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11047 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11048 uint64_t offset = ReadXRegister(instr->GetRm());
11049 offset <<= msize_in_bytes_log2;
11050 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramleybc4a54f2019-11-04 16:44:01 +000011051 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11052 SVEStructuredLoadHelper(vform,
TatWai Chong6205eb42019-09-24 10:07:20 +010011053 ReadPRegister(instr->GetPgLow8()),
11054 instr->GetRt(),
TatWai Chong6205eb42019-09-24 10:07:20 +010011055 addr,
11056 is_signed);
11057}
11058
Alexandre Ramesd3832962016-07-04 15:03:43 +010011059void Simulator::DoUnreachable(const Instruction* instr) {
11060 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11061 (instr->GetImmException() == kUnreachableOpcode));
11062
11063 fprintf(stream_,
11064 "Hit UNREACHABLE marker at pc=%p.\n",
11065 reinterpret_cast<const void*>(instr));
11066 abort();
11067}
11068
11069
11070void Simulator::DoTrace(const Instruction* instr) {
11071 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11072 (instr->GetImmException() == kTraceOpcode));
11073
11074 // Read the arguments encoded inline in the instruction stream.
11075 uint32_t parameters;
11076 uint32_t command;
11077
11078 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11079 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11080 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
11081
11082 switch (command) {
11083 case TRACE_ENABLE:
11084 SetTraceParameters(GetTraceParameters() | parameters);
11085 break;
11086 case TRACE_DISABLE:
11087 SetTraceParameters(GetTraceParameters() & ~parameters);
11088 break;
11089 default:
11090 VIXL_UNREACHABLE();
11091 }
11092
11093 WritePc(instr->GetInstructionAtOffset(kTraceLength));
11094}
11095
11096
11097void Simulator::DoLog(const Instruction* instr) {
11098 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11099 (instr->GetImmException() == kLogOpcode));
11100
11101 // Read the arguments encoded inline in the instruction stream.
11102 uint32_t parameters;
11103
11104 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11105 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11106
11107 // We don't support a one-shot LOG_DISASM.
11108 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
11109 // Print the requested information.
11110 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
11111 if (parameters & LOG_REGS) PrintRegisters();
11112 if (parameters & LOG_VREGS) PrintVRegisters();
11113
11114 WritePc(instr->GetInstructionAtOffset(kLogLength));
11115}
11116
11117
11118void Simulator::DoPrintf(const Instruction* instr) {
11119 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11120 (instr->GetImmException() == kPrintfOpcode));
11121
11122 // Read the arguments encoded inline in the instruction stream.
11123 uint32_t arg_count;
11124 uint32_t arg_pattern_list;
11125 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11126 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
11127 memcpy(&arg_pattern_list,
11128 instr + kPrintfArgPatternListOffset,
11129 sizeof(arg_pattern_list));
11130
11131 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
11132 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
11133
11134 // We need to call the host printf function with a set of arguments defined by
11135 // arg_pattern_list. Because we don't know the types and sizes of the
11136 // arguments, this is very difficult to do in a robust and portable way. To
11137 // work around the problem, we pick apart the format string, and print one
11138 // format placeholder at a time.
11139
11140 // Allocate space for the format string. We take a copy, so we can modify it.
11141 // Leave enough space for one extra character per expected argument (plus the
11142 // '\0' termination).
11143 const char* format_base = ReadRegister<const char*>(0);
11144 VIXL_ASSERT(format_base != NULL);
11145 size_t length = strlen(format_base) + 1;
11146 char* const format = new char[length + arg_count];
11147
11148 // A list of chunks, each with exactly one format placeholder.
11149 const char* chunks[kPrintfMaxArgCount];
11150
11151 // Copy the format string and search for format placeholders.
11152 uint32_t placeholder_count = 0;
11153 char* format_scratch = format;
11154 for (size_t i = 0; i < length; i++) {
11155 if (format_base[i] != '%') {
11156 *format_scratch++ = format_base[i];
11157 } else {
11158 if (format_base[i + 1] == '%') {
11159 // Ignore explicit "%%" sequences.
11160 *format_scratch++ = format_base[i];
11161 i++;
11162 // Chunks after the first are passed as format strings to printf, so we
11163 // need to escape '%' characters in those chunks.
11164 if (placeholder_count > 0) *format_scratch++ = format_base[i];
11165 } else {
11166 VIXL_CHECK(placeholder_count < arg_count);
11167 // Insert '\0' before placeholders, and store their locations.
11168 *format_scratch++ = '\0';
11169 chunks[placeholder_count++] = format_scratch;
11170 *format_scratch++ = format_base[i];
11171 }
11172 }
11173 }
11174 VIXL_CHECK(placeholder_count == arg_count);
11175
11176 // Finally, call printf with each chunk, passing the appropriate register
11177 // argument. Normally, printf returns the number of bytes transmitted, so we
11178 // can emulate a single printf call by adding the result from each chunk. If
11179 // any call returns a negative (error) value, though, just return that value.
11180
11181 printf("%s", clr_printf);
11182
11183 // Because '\0' is inserted before each placeholder, the first string in
11184 // 'format' contains no format placeholders and should be printed literally.
11185 int result = printf("%s", format);
11186 int pcs_r = 1; // Start at x1. x0 holds the format string.
11187 int pcs_f = 0; // Start at d0.
11188 if (result >= 0) {
11189 for (uint32_t i = 0; i < placeholder_count; i++) {
11190 int part_result = -1;
11191
11192 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
11193 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
11194 switch (arg_pattern) {
11195 case kPrintfArgW:
11196 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
11197 break;
11198 case kPrintfArgX:
11199 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
11200 break;
11201 case kPrintfArgD:
11202 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
11203 break;
11204 default:
11205 VIXL_UNREACHABLE();
11206 }
11207
11208 if (part_result < 0) {
11209 // Handle error values.
11210 result = part_result;
11211 break;
11212 }
11213
11214 result += part_result;
11215 }
11216 }
11217
11218 printf("%s", clr_normal);
11219
11220 // Printf returns its result in x0 (just like the C library's printf).
11221 WriteXRegister(0, result);
11222
11223 // The printf parameters are inlined in the code, so skip them.
11224 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
11225
11226 // Set LR as if we'd just called a native printf function.
11227 WriteLr(ReadPc());
11228
11229 delete[] format;
11230}
11231
Alexandre Rames064e02d2016-07-12 11:53:13 +010011232
Alexandre Ramesca73ba02016-07-28 09:16:03 +010011233#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010011234void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011235 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011236 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
11237 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011238 uintptr_t call_wrapper_address =
11239 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
11240 uintptr_t function_address =
11241 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080011242 RuntimeCallType call_type = static_cast<RuntimeCallType>(
11243 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011244 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010011245 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011246
11247 if (call_type == kCallRuntime) {
11248 WriteRegister(kLinkRegCode,
11249 instr->GetInstructionAtOffset(kRuntimeCallLength));
11250 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011251 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011252 // Read the return address from `lr` and write it into `pc`.
11253 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011254}
11255#else
11256void Simulator::DoRuntimeCall(const Instruction* instr) {
11257 USE(instr);
11258 VIXL_UNREACHABLE();
11259}
11260#endif
11261
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011262
11263void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
11264 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
11265
11266 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011267 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011268 std::numeric_limits<ElementType>::max());
11269
11270 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
11271
11272 size_t element_size = sizeof(ElementType);
11273 size_t offset = kConfigureCPUFeaturesListOffset;
11274
11275 // Read the kNone-terminated list of features.
11276 CPUFeatures parameters;
11277 while (true) {
11278 ElementType feature = Memory::Read<ElementType>(instr + offset);
11279 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011280 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011281 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
11282 }
11283
11284 switch (instr->GetImmException()) {
11285 case kSetCPUFeaturesOpcode:
11286 SetCPUFeatures(parameters);
11287 break;
11288 case kEnableCPUFeaturesOpcode:
11289 GetCPUFeatures()->Combine(parameters);
11290 break;
11291 case kDisableCPUFeaturesOpcode:
11292 GetCPUFeatures()->Remove(parameters);
11293 break;
11294 default:
11295 VIXL_UNREACHABLE();
11296 break;
11297 }
11298
11299 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
11300}
11301
11302
11303void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
11304 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11305 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
11306 USE(instr);
11307
11308 saved_cpu_features_.push_back(*GetCPUFeatures());
11309}
11310
11311
11312void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
11313 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11314 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
11315 USE(instr);
11316
11317 SetCPUFeatures(saved_cpu_features_.back());
11318 saved_cpu_features_.pop_back();
11319}
11320
11321
Alexandre Ramesd3832962016-07-04 15:03:43 +010011322} // namespace aarch64
11323} // namespace vixl
11324
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010011325#endif // VIXL_INCLUDE_SIMULATOR_AARCH64