blob: dc0904c22f59bc326eeba99c418f907cc0bb778e [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 {
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000466 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100467 if (amount == 0) {
468 return value;
469 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000470 uint64_t uvalue = static_cast<uint64_t>(value);
471 uint64_t mask = kWRegMask;
472 bool is_negative = (uvalue & kWSignMask) != 0;
473 if (reg_size == kXRegSize) {
474 mask = kXRegMask;
475 is_negative = (uvalue & kXSignMask) != 0;
476 }
477
Alexandre Ramesd3832962016-07-04 15:03:43 +0100478 switch (shift_type) {
479 case LSL:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000480 uvalue <<= amount;
481 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100482 case LSR:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000483 uvalue >>= amount;
484 break;
485 case ASR:
486 uvalue >>= amount;
487 if (is_negative) {
488 // Simulate sign-extension to 64 bits.
489 uvalue |= ~UINT64_C(0) << (reg_size - amount);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100490 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000491 break;
492 case ROR: {
Martyn Capewellfb8e3df2016-11-03 15:50:19 +0000493 uvalue = RotateRight(uvalue, amount, reg_size);
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000494 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100495 }
496 default:
497 VIXL_UNIMPLEMENTED();
498 return 0;
499 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000500 uvalue &= mask;
501
502 int64_t result;
503 memcpy(&result, &uvalue, sizeof(result));
504 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100505}
506
507
508int64_t Simulator::ExtendValue(unsigned reg_size,
509 int64_t value,
510 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100511 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100512 switch (extend_type) {
513 case UXTB:
514 value &= kByteMask;
515 break;
516 case UXTH:
517 value &= kHalfWordMask;
518 break;
519 case UXTW:
520 value &= kWordMask;
521 break;
522 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000523 value &= kByteMask;
524 if ((value & 0x80) != 0) {
525 value |= ~UINT64_C(0) << 8;
526 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100527 break;
528 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000529 value &= kHalfWordMask;
530 if ((value & 0x8000) != 0) {
531 value |= ~UINT64_C(0) << 16;
532 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100533 break;
534 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000535 value &= kWordMask;
536 if ((value & 0x80000000) != 0) {
537 value |= ~UINT64_C(0) << 32;
538 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100539 break;
540 case UXTX:
541 case SXTX:
542 break;
543 default:
544 VIXL_UNREACHABLE();
545 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000546 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100547}
548
549
550void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
551 AssertSupportedFPCR();
552
553 // TODO: This assumes that the C++ implementation handles comparisons in the
554 // way that we expect (as per AssertSupportedFPCR()).
555 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100556 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100557 ReadNzcv().SetRawValue(FPUnorderedFlag);
558 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
559 (trap == EnableTrap)) {
560 process_exception = true;
561 }
562 } else if (val0 < val1) {
563 ReadNzcv().SetRawValue(FPLessThanFlag);
564 } else if (val0 > val1) {
565 ReadNzcv().SetRawValue(FPGreaterThanFlag);
566 } else if (val0 == val1) {
567 ReadNzcv().SetRawValue(FPEqualFlag);
568 } else {
569 VIXL_UNREACHABLE();
570 }
571 LogSystemRegister(NZCV);
572 if (process_exception) FPProcessException();
573}
574
575
Alexandre Rames868bfc42016-07-19 17:10:48 +0100576uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
577 VIXL_ASSERT(mem_op.IsValid());
578 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
579 if (mem_op.IsImmediateOffset()) {
580 return base + mem_op.GetOffset();
581 } else {
582 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
583 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100584 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100585 if (mem_op.GetShift() != NO_SHIFT) {
586 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
587 }
588 if (mem_op.GetExtend() != NO_EXTEND) {
589 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
590 }
591 return static_cast<uint64_t>(base + offset);
592 }
593}
594
595
Alexandre Ramesd3832962016-07-04 15:03:43 +0100596Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
597 unsigned reg_size, unsigned lane_size) {
598 VIXL_ASSERT(reg_size >= lane_size);
599
600 uint32_t format = 0;
601 if (reg_size != lane_size) {
602 switch (reg_size) {
603 default:
604 VIXL_UNREACHABLE();
605 break;
606 case kQRegSizeInBytes:
607 format = kPrintRegAsQVector;
608 break;
609 case kDRegSizeInBytes:
610 format = kPrintRegAsDVector;
611 break;
612 }
613 }
614
615 switch (lane_size) {
616 default:
617 VIXL_UNREACHABLE();
618 break;
619 case kQRegSizeInBytes:
620 format |= kPrintReg1Q;
621 break;
622 case kDRegSizeInBytes:
623 format |= kPrintReg1D;
624 break;
625 case kSRegSizeInBytes:
626 format |= kPrintReg1S;
627 break;
628 case kHRegSizeInBytes:
629 format |= kPrintReg1H;
630 break;
631 case kBRegSizeInBytes:
632 format |= kPrintReg1B;
633 break;
634 }
635 // These sizes would be duplicate case labels.
636 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
637 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
638 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
639 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
640
641 return static_cast<PrintRegisterFormat>(format);
642}
643
644
645Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
646 VectorFormat vform) {
647 switch (vform) {
648 default:
649 VIXL_UNREACHABLE();
650 return kPrintReg16B;
651 case kFormat16B:
652 return kPrintReg16B;
653 case kFormat8B:
654 return kPrintReg8B;
655 case kFormat8H:
656 return kPrintReg8H;
657 case kFormat4H:
658 return kPrintReg4H;
659 case kFormat4S:
660 return kPrintReg4S;
661 case kFormat2S:
662 return kPrintReg2S;
663 case kFormat2D:
664 return kPrintReg2D;
665 case kFormat1D:
666 return kPrintReg1D;
667
668 case kFormatB:
669 return kPrintReg1B;
670 case kFormatH:
671 return kPrintReg1H;
672 case kFormatS:
673 return kPrintReg1S;
674 case kFormatD:
675 return kPrintReg1D;
Jacob Bramleye668b202019-08-14 17:57:34 +0100676
677 case kFormatVnB:
678 return kPrintRegLaneSizeB;
679 case kFormatVnH:
680 return kPrintRegLaneSizeH;
681 case kFormatVnS:
682 return kPrintRegLaneSizeS;
683 case kFormatVnD:
684 return kPrintRegLaneSizeD;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100685 }
686}
687
688
689Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
690 VectorFormat vform) {
691 switch (vform) {
692 default:
693 VIXL_UNREACHABLE();
694 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100695 case kFormat8H:
696 return kPrintReg8HFP;
697 case kFormat4H:
698 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100699 case kFormat4S:
700 return kPrintReg4SFP;
701 case kFormat2S:
702 return kPrintReg2SFP;
703 case kFormat2D:
704 return kPrintReg2DFP;
705 case kFormat1D:
706 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100707 case kFormatH:
708 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100709 case kFormatS:
710 return kPrintReg1SFP;
711 case kFormatD:
712 return kPrintReg1DFP;
713 }
714}
715
716
717void Simulator::PrintWrittenRegisters() {
718 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
719 if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
720 }
721}
722
723
724void Simulator::PrintWrittenVRegisters() {
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100725 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100726 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
727 // At this point there is no type information, so print as a raw 1Q.
Jacob Bramleyfad4dff2019-07-02 17:09:11 +0100728 if (vregisters_[i].WrittenSinceLastLog()) {
729 // Z registers are initialised in the constructor before the user can
730 // configure the CPU features, so we must also check for SVE here.
731 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
732 PrintZRegister(i);
733 } else {
734 PrintVRegister(i, kPrintReg1Q);
735 }
736 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100737 }
738}
739
740
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100741void Simulator::PrintWrittenPRegisters() {
742 // P registers are initialised in the constructor before the user can
743 // configure the CPU features, so we must check for SVE here.
744 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
745 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
746 if (pregisters_[i].WrittenSinceLastLog()) {
747 PrintPRegister(i);
748 }
749 }
750}
751
752
Alexandre Ramesd3832962016-07-04 15:03:43 +0100753void Simulator::PrintSystemRegisters() {
754 PrintSystemRegister(NZCV);
755 PrintSystemRegister(FPCR);
756}
757
758
759void Simulator::PrintRegisters() {
760 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
761 PrintRegister(i);
762 }
763}
764
765
766void Simulator::PrintVRegisters() {
767 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
768 // At this point there is no type information, so print as a raw 1Q.
769 PrintVRegister(i, kPrintReg1Q);
770 }
771}
772
773
TatWai Chong72d2e562019-05-16 11:22:22 -0700774void Simulator::PrintZRegisters() {
775 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
776 PrintZRegister(i);
777 }
778}
779
780
Alexandre Ramesd3832962016-07-04 15:03:43 +0100781// Print a register's name and raw value.
782//
783// Only the least-significant `size_in_bytes` bytes of the register are printed,
784// but the value is aligned as if the whole register had been printed.
785//
786// For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
787// -- the default -- so that the whole register is printed. Other values of
788// size_in_bytes are intended for use when the register hasn't actually been
789// updated (such as in PrintWrite).
790//
791// No newline is printed. This allows the caller to print more details (such as
792// a memory access annotation).
793void Simulator::PrintRegisterRawHelper(unsigned code,
794 Reg31Mode r31mode,
795 int size_in_bytes) {
796 // The template for all supported sizes.
797 // "# x{code}: 0xffeeddccbbaa9988"
798 // "# w{code}: 0xbbaa9988"
799 // "# w{code}<15:0>: 0x9988"
800 // "# w{code}<7:0>: 0x88"
801 unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
802
803 const char* name = "";
804 const char* suffix = "";
805 switch (size_in_bytes) {
806 case kXRegSizeInBytes:
807 name = XRegNameForCode(code, r31mode);
808 break;
809 case kWRegSizeInBytes:
810 name = WRegNameForCode(code, r31mode);
811 break;
812 case 2:
813 name = WRegNameForCode(code, r31mode);
814 suffix = "<15:0>";
815 padding_chars -= strlen(suffix);
816 break;
817 case 1:
818 name = WRegNameForCode(code, r31mode);
819 suffix = "<7:0>";
820 padding_chars -= strlen(suffix);
821 break;
822 default:
823 VIXL_UNREACHABLE();
824 }
825 fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
826
827 // Print leading padding spaces.
828 VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
829 for (unsigned i = 0; i < padding_chars; i++) {
830 putc(' ', stream_);
831 }
832
833 // Print the specified bits in hexadecimal format.
834 uint64_t bits = ReadRegister<uint64_t>(code, r31mode);
835 bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
836 VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
837
838 int chars = size_in_bytes * 2;
839 fprintf(stream_,
840 "%s0x%0*" PRIx64 "%s",
841 clr_reg_value,
842 chars,
843 bits,
844 clr_normal);
845}
846
847
848void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
849 registers_[code].NotifyRegisterLogged();
850
851 // Don't print writes into xzr.
852 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
853 return;
854 }
855
856 // The template for all x and w registers:
857 // "# x{code}: 0x{value}"
858 // "# w{code}: 0x{value}"
859
860 PrintRegisterRawHelper(code, r31mode);
861 fprintf(stream_, "\n");
862}
863
864
865// Print a register's name and raw value.
866//
867// The `bytes` and `lsb` arguments can be used to limit the bytes that are
868// printed. These arguments are intended for use in cases where register hasn't
869// actually been updated (such as in PrintVWrite).
870//
871// No newline is printed. This allows the caller to print more details (such as
872// a floating-point interpretation or a memory access annotation).
873void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
874 // The template for vector types:
875 // "# v{code}: 0xffeeddccbbaa99887766554433221100".
876 // An example with bytes=4 and lsb=8:
877 // "# v{code}: 0xbbaa9988 ".
878 fprintf(stream_,
TatWai Chong72d2e562019-05-16 11:22:22 -0700879 "# %s%13s: %s",
Alexandre Ramesd3832962016-07-04 15:03:43 +0100880 clr_vreg_name,
881 VRegNameForCode(code),
882 clr_vreg_value);
883
884 int msb = lsb + bytes - 1;
885 int byte = kQRegSizeInBytes - 1;
886
887 // Print leading padding spaces. (Two spaces per byte.)
888 while (byte > msb) {
889 fprintf(stream_, " ");
890 byte--;
891 }
892
893 // Print the specified part of the value, byte by byte.
894 qreg_t rawbits = ReadQRegister(code);
895 fprintf(stream_, "0x");
896 while (byte >= lsb) {
897 fprintf(stream_, "%02x", rawbits.val[byte]);
898 byte--;
899 }
900
901 // Print trailing padding spaces.
902 while (byte >= 0) {
903 fprintf(stream_, " ");
904 byte--;
905 }
906 fprintf(stream_, "%s", clr_normal);
907}
908
909
TatWai Chong72d2e562019-05-16 11:22:22 -0700910void Simulator::PrintZRegisterRawHelper(
911 unsigned code, int lane_size, int data_size, int bytes, int start_byte) {
912 VIXL_ASSERT(lane_size >= data_size);
913 // Currently only support printing of 128-bit length value and it must have
914 // 128-bit alignement.
915 VIXL_ASSERT((bytes % kQRegSizeInBytes) == 0);
916 VIXL_ASSERT((start_byte % kQRegSizeInBytes) == 0);
917
918 // The template for vector types:
919 // "# z{code}<m+127:m>: 0x33333333222222221111111100000000",
920 // where m is multiple of 128b.
921 // An example with bytes=16 starting from a bit 128:
922 // "# z{code}<255:128>: 0x77777777666666665555555544444444".
923 // A qlane from a bit zero with lane=4, data=2, and bytes=16:
924 // "# z{code}<127:0>: 0x 3333 2222 1111 0000".
925
926 std::stringstream prefix;
927 prefix << ZRegNameForCode(code) << "<"
928 << ((start_byte + bytes) * kBitsPerByte) - 1 << ":"
929 << (start_byte * kBitsPerByte) << ">";
930
931 fprintf(stream_,
932 "# %s%13s: %s0x",
933 clr_vreg_name,
934 prefix.str().c_str(),
935 clr_vreg_value);
936
937 // Print the 128-bit length of register, lane by lane.
938 for (int i = kQRegSizeInBytes / lane_size; i > 0; i--) {
939 VIXL_ASSERT((kQRegSizeInBytes % lane_size) == 0);
940 // Skip the irrelevant part of value from lane if any.
941 for (int skips = lane_size - data_size; skips > 0; skips--) {
942 fprintf(stream_, " ");
943 bytes--;
944 }
945
946 // [`first_byte`, `last_byte`] represent the interval of bytes that are
947 // printed in each lane.
948 int last_byte = start_byte + bytes - 1;
949 int first_byte = last_byte - data_size + 1;
950 // Print the specified part of the value, byte by byte.
951 int lane_idx = last_byte >> kQRegSizeInBytesLog2;
952 qreg_t rawbits = vregisters_[code].GetLane<qreg_t>(lane_idx);
953 for (int byte = last_byte; byte >= first_byte; --byte) {
954 fprintf(stream_, "%02x", rawbits.val[byte % kQRegSizeInBytes]);
955 bytes--;
956 }
957 }
958 fprintf(stream_, "%s", clr_normal);
959}
960
961
Jacob Bramleyf5659ff2019-08-02 11:19:04 +0100962void Simulator::PrintPRegisterRawHelper(unsigned code, int lsb) {
963 // There are no predicated store-predicate instructions, so we can always
964 // print the full register, but this helper prints a single run of 16 bits
965 // (from `lsb`).
966 VIXL_ASSERT(code < kNumberOfPRegisters);
967 int bits = kQRegSize / kZRegBitsPerPRegBit;
968 int msb = lsb + bits - 1;
969 VIXL_ASSERT(static_cast<unsigned>(msb) < pregisters_[code].GetSizeInBits());
970 VIXL_ASSERT((lsb % bits) == 0);
971
972 // The template for P registers:
973 // "# p{code}<m+15:m>: 0b 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 0",
974 // where m is multiple of 16.
975
976 // Each printed bit aligns with the least-significant nibble of the
977 // corresponding Z-register lane, to make predicate behaviour easy to follow.
978
979 std::stringstream prefix;
980 prefix << PRegNameForCode(code) << "<" << msb << ":" << lsb << ">";
981
982 fprintf(stream_,
983 "# %s%13s: %s0b",
984 clr_preg_name,
985 prefix.str().c_str(),
986 clr_preg_value);
987
988 // Print the 16-bit length of register, lane by lane.
989 for (int i = msb; i >= lsb; i--) {
990 fprintf(stream_, " %c", pregisters_[code].GetBit(i) ? '1' : '0');
991 }
992 fprintf(stream_, "%s", clr_normal);
993}
994
995
Alexandre Ramesd3832962016-07-04 15:03:43 +0100996// Print each of the specified lanes of a register as a float or double value.
997//
998// The `lane_count` and `lslane` arguments can be used to limit the lanes that
999// are printed. These arguments are intended for use in cases where register
1000// hasn't actually been updated (such as in PrintVWrite).
1001//
1002// No newline is printed. This allows the caller to print more details (such as
1003// a memory access annotation).
1004void Simulator::PrintVRegisterFPHelper(unsigned code,
1005 unsigned lane_size_in_bytes,
1006 int lane_count,
1007 int rightmost_lane) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01001008 VIXL_ASSERT((lane_size_in_bytes == kHRegSizeInBytes) ||
1009 (lane_size_in_bytes == kSRegSizeInBytes) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01001010 (lane_size_in_bytes == kDRegSizeInBytes));
1011
1012 unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
1013 VIXL_ASSERT(msb <= kQRegSizeInBytes);
1014
1015 // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
1016 // name is used:
Carey Williamsd8bb3572018-04-10 11:58:07 +01001017 // " (h{code}: {value})"
Alexandre Ramesd3832962016-07-04 15:03:43 +01001018 // " (s{code}: {value})"
1019 // " (d{code}: {value})"
1020 // For vector types, "..." is used to represent one or more omitted lanes.
1021 // " (..., {value}, {value}, ...)"
Carey Williamsd8bb3572018-04-10 11:58:07 +01001022 if (lane_size_in_bytes == kHRegSizeInBytes) {
1023 // TODO: Trace tests will fail until we regenerate them.
1024 return;
1025 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001026 if ((lane_count == 1) && (rightmost_lane == 0)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01001027 const char* name;
1028 switch (lane_size_in_bytes) {
1029 case kHRegSizeInBytes:
1030 name = HRegNameForCode(code);
1031 break;
1032 case kSRegSizeInBytes:
1033 name = SRegNameForCode(code);
1034 break;
1035 case kDRegSizeInBytes:
1036 name = DRegNameForCode(code);
1037 break;
1038 default:
Pierre Langlois226fbe42018-05-14 11:29:08 +01001039 name = NULL;
Carey Williamsd8bb3572018-04-10 11:58:07 +01001040 VIXL_UNREACHABLE();
1041 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001042 fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
1043 } else {
1044 if (msb < (kQRegSizeInBytes - 1)) {
1045 fprintf(stream_, " (..., ");
1046 } else {
1047 fprintf(stream_, " (");
1048 }
1049 }
1050
1051 // Print the list of values.
1052 const char* separator = "";
1053 int leftmost_lane = rightmost_lane + lane_count - 1;
1054 for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01001055 double value;
1056 switch (lane_size_in_bytes) {
1057 case kHRegSizeInBytes:
Jacob Bramleyca789742018-09-13 14:25:46 +01001058 value = ReadVRegister(code).GetLane<uint16_t>(lane);
Carey Williamsd8bb3572018-04-10 11:58:07 +01001059 break;
1060 case kSRegSizeInBytes:
1061 value = ReadVRegister(code).GetLane<float>(lane);
1062 break;
1063 case kDRegSizeInBytes:
1064 value = ReadVRegister(code).GetLane<double>(lane);
1065 break;
1066 default:
1067 value = 0.0;
1068 VIXL_UNREACHABLE();
1069 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001070 if (IsNaN(value)) {
Alexandre Rames6b5fe942016-07-22 17:17:23 +01001071 // The output for NaNs is implementation defined. Always print `nan`, so
1072 // that traces are coherent across different implementations.
1073 fprintf(stream_, "%s%snan%s", separator, clr_vreg_value, clr_normal);
1074 } else {
1075 fprintf(stream_,
1076 "%s%s%#g%s",
1077 separator,
1078 clr_vreg_value,
1079 value,
1080 clr_normal);
1081 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01001082 separator = ", ";
1083 }
1084
1085 if (rightmost_lane > 0) {
1086 fprintf(stream_, ", ...");
1087 }
1088 fprintf(stream_, ")");
1089}
1090
1091
1092void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
1093 vregisters_[code].NotifyRegisterLogged();
1094
1095 int lane_size_log2 = format & kPrintRegLaneSizeMask;
1096
1097 int reg_size_log2;
1098 if (format & kPrintRegAsQVector) {
1099 reg_size_log2 = kQRegSizeInBytesLog2;
1100 } else if (format & kPrintRegAsDVector) {
1101 reg_size_log2 = kDRegSizeInBytesLog2;
1102 } else {
1103 // Scalar types.
1104 reg_size_log2 = lane_size_log2;
1105 }
1106
1107 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
1108 int lane_size = 1 << lane_size_log2;
1109
1110 // The template for vector types:
1111 // "# v{code}: 0x{rawbits} (..., {value}, ...)".
1112 // The template for scalar types:
1113 // "# v{code}: 0x{rawbits} ({reg}:{value})".
1114 // The values in parentheses after the bit representations are floating-point
1115 // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
1116
1117 PrintVRegisterRawHelper(code);
1118 if (format & kPrintRegAsFP) {
1119 PrintVRegisterFPHelper(code, lane_size, lane_count);
1120 }
1121
1122 fprintf(stream_, "\n");
1123}
1124
TatWai Chong72d2e562019-05-16 11:22:22 -07001125void Simulator::PrintZRegister(unsigned code,
1126 PrintRegisterFormat format,
1127 int bytes,
1128 int start_byte) {
1129 vregisters_[code].NotifyRegisterLogged();
1130 if (bytes == 0) {
1131 // If no byte size specified, print the whole length of register.
1132 bytes = GetVectorLengthInBytes();
1133 }
1134
1135 int lane_size;
1136 switch (format) {
1137 case kPrintRegLaneSizeUnknown:
1138 // If no lane size specified, set to 128-bit lane by default.
1139 lane_size = kQRegSizeInBytes;
1140 break;
1141 case kPrintRegLaneSizeB:
1142 case kPrintRegLaneSizeH:
1143 case kPrintRegLaneSizeS:
1144 case kPrintRegLaneSizeD:
1145 lane_size = GetPrintRegLaneSizeInBytes(format);
1146 break;
1147 default:
1148 lane_size = 0;
1149 VIXL_UNIMPLEMENTED();
1150 break;
1151 }
1152
1153 while (bytes > 0) {
1154 PrintZRegisterRawHelper(code,
1155 lane_size,
1156 lane_size,
1157 kQRegSizeInBytes,
1158 start_byte + bytes - kQRegSizeInBytes);
1159 bytes -= kQRegSizeInBytes;
1160 fprintf(stream_, "\n");
1161 }
1162}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001163
Jacob Bramleyf5659ff2019-08-02 11:19:04 +01001164void Simulator::PrintPRegister(unsigned code, PrintRegisterFormat format) {
1165 USE(format);
1166 pregisters_[code].NotifyRegisterLogged();
1167 // There are no predicated store-predicate instructions, so we can simply
1168 // print the full register.
1169 int bits_per_chunk = kQRegSize / kZRegBitsPerPRegBit;
1170 int bits = pregisters_[code].GetSizeInBits();
1171 for (int lsb = bits - bits_per_chunk; lsb >= 0; lsb -= bits_per_chunk) {
1172 PrintPRegisterRawHelper(code, lsb);
1173 fprintf(stream_, "\n");
1174 }
1175}
1176
Alexandre Ramesd3832962016-07-04 15:03:43 +01001177void Simulator::PrintSystemRegister(SystemRegister id) {
1178 switch (id) {
1179 case NZCV:
1180 fprintf(stream_,
1181 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1182 clr_flag_name,
1183 clr_flag_value,
1184 ReadNzcv().GetN(),
1185 ReadNzcv().GetZ(),
1186 ReadNzcv().GetC(),
1187 ReadNzcv().GetV(),
1188 clr_normal);
1189 break;
1190 case FPCR: {
1191 static const char* rmode[] = {"0b00 (Round to Nearest)",
1192 "0b01 (Round towards Plus Infinity)",
1193 "0b10 (Round towards Minus Infinity)",
1194 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001195 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001196 fprintf(stream_,
1197 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1198 clr_flag_name,
1199 clr_flag_value,
1200 ReadFpcr().GetAHP(),
1201 ReadFpcr().GetDN(),
1202 ReadFpcr().GetFZ(),
1203 rmode[ReadFpcr().GetRMode()],
1204 clr_normal);
1205 break;
1206 }
1207 default:
1208 VIXL_UNREACHABLE();
1209 }
1210}
1211
1212
1213void Simulator::PrintRead(uintptr_t address,
1214 unsigned reg_code,
1215 PrintRegisterFormat format) {
1216 registers_[reg_code].NotifyRegisterLogged();
1217
1218 USE(format);
1219
1220 // The template is "# {reg}: 0x{value} <- {address}".
1221 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
1222 fprintf(stream_,
1223 " <- %s0x%016" PRIxPTR "%s\n",
1224 clr_memory_address,
1225 address,
1226 clr_normal);
1227}
1228
1229
1230void Simulator::PrintVRead(uintptr_t address,
1231 unsigned reg_code,
1232 PrintRegisterFormat format,
1233 unsigned lane) {
1234 vregisters_[reg_code].NotifyRegisterLogged();
1235
1236 // The template is "# v{code}: 0x{rawbits} <- address".
1237 PrintVRegisterRawHelper(reg_code);
1238 if (format & kPrintRegAsFP) {
1239 PrintVRegisterFPHelper(reg_code,
1240 GetPrintRegLaneSizeInBytes(format),
1241 GetPrintRegLaneCount(format),
1242 lane);
1243 }
1244 fprintf(stream_,
1245 " <- %s0x%016" PRIxPTR "%s\n",
1246 clr_memory_address,
1247 address,
1248 clr_normal);
1249}
1250
TatWai Chong72d2e562019-05-16 11:22:22 -07001251void Simulator::PrintZRead(uintptr_t address,
1252 unsigned reg_code,
1253 PrintRegisterFormat format,
1254 unsigned data_size,
1255 int bytes,
1256 int start_byte) {
1257 vregisters_[reg_code].NotifyRegisterLogged();
1258
1259 // The templates:
1260 // "# v{code}<m:n>: 0x{rawbits} <- {address}"
1261 // An example that prints an unpredicated memory read from a particular memory
1262 // location to the specified portion of Z register.
1263 // 0x00007fff00000000: 0x11110000 0x33332222 0x55554444 0x77776666
1264 // 0x00007fff00000010: 0x99998888 0xbbbbaaaa 0xddddcccc 0xffffeeee
1265 // The corresponding output is:
1266 // Zt<255:128>: 0x77776666555544443333222211110000 <- 0x00007fff00000000
1267 // Zt<383:256>: 0xffffeeeeddddccccbbbbaaaa99998888 <- 0x00007fff00000010
1268
Jacob Bramley199339d2019-08-05 18:49:13 +01001269 if (format == kPrintRegLaneSizeUnknown) format = kPrintRegLaneSizeQ;
TatWai Chong72d2e562019-05-16 11:22:22 -07001270 int lane_size = GetPrintRegLaneSizeInBytes(format);
1271 if (data_size == 0) {
1272 // Let the full lane of value are relevent.
1273 data_size = lane_size;
1274 }
1275 if (bytes == 0) {
1276 // If no byte size specified, print the whole length of register.
1277 bytes = GetVectorLengthInBytes();
1278 }
1279
1280 const int last_byte = start_byte + bytes - 1;
1281 while (start_byte < last_byte) {
1282 PrintZRegisterRawHelper(reg_code,
1283 lane_size,
1284 data_size,
1285 kQRegSizeInBytes,
1286 start_byte);
1287 fprintf(stream_,
1288 " <- %s0x%016" PRIxPTR "%s\n",
1289 clr_memory_address,
1290 address,
1291 clr_normal);
1292 start_byte += kQRegSizeInBytes;
1293 address += kQRegSizeInBytes;
1294 }
1295}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001296
1297void Simulator::PrintWrite(uintptr_t address,
1298 unsigned reg_code,
1299 PrintRegisterFormat format) {
1300 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1301
1302 // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
1303 // and readable, the value is aligned with the values in the register trace.
1304 PrintRegisterRawHelper(reg_code,
1305 Reg31IsZeroRegister,
1306 GetPrintRegSizeInBytes(format));
1307 fprintf(stream_,
1308 " -> %s0x%016" PRIxPTR "%s\n",
1309 clr_memory_address,
1310 address,
1311 clr_normal);
1312}
1313
1314
1315void Simulator::PrintVWrite(uintptr_t address,
1316 unsigned reg_code,
1317 PrintRegisterFormat format,
1318 unsigned lane) {
1319 // The templates:
1320 // "# v{code}: 0x{rawbits} -> {address}"
1321 // "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
1322 // "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
1323 // Because this trace doesn't represent a change to the source register's
1324 // value, only the relevant part of the value is printed. To keep the trace
1325 // tidy and readable, the raw value is aligned with the other values in the
1326 // register trace.
1327 int lane_count = GetPrintRegLaneCount(format);
1328 int lane_size = GetPrintRegLaneSizeInBytes(format);
1329 int reg_size = GetPrintRegSizeInBytes(format);
1330 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1331 if (format & kPrintRegAsFP) {
1332 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1333 }
1334 fprintf(stream_,
1335 " -> %s0x%016" PRIxPTR "%s\n",
1336 clr_memory_address,
1337 address,
1338 clr_normal);
1339}
1340
TatWai Chong72d2e562019-05-16 11:22:22 -07001341void Simulator::PrintZWrite(uintptr_t address,
1342 unsigned reg_code,
1343 PrintRegisterFormat format,
1344 unsigned data_size,
1345 int bytes,
1346 int start_byte) {
1347 // The templates:
1348 // "# v{code}<m:n>: 0x{rawbits} -> {address}"
1349 // An example that prints an unpredicated memory write from the specified
1350 // portion of Z register to a particular memory location.
1351 // Zt<255:128>: 0x77776666555544443333222211110000 -> 0x00007fff00000000
1352 // Zt<383:256>: 0xffffeeeeddddccccbbbbaaaa99998888 -> 0x00007fff00000010
1353
Jacob Bramley199339d2019-08-05 18:49:13 +01001354 if (format == kPrintRegLaneSizeUnknown) format = kPrintRegLaneSizeQ;
TatWai Chong72d2e562019-05-16 11:22:22 -07001355 int lane_size = GetPrintRegLaneSizeInBytes(format);
1356 if (data_size == 0) {
1357 // If no data size was specified, print the whole of each lane.
1358 data_size = lane_size;
1359 }
1360 if (bytes == 0) {
1361 // If no byte size was specified, print the whole register.
1362 bytes = GetVectorLengthInBytes();
1363 }
1364
1365 const int last_byte = start_byte + bytes - 1;
Jacob Bramleye668b202019-08-14 17:57:34 +01001366 while (start_byte <= last_byte) {
TatWai Chong72d2e562019-05-16 11:22:22 -07001367 PrintZRegisterRawHelper(reg_code,
1368 lane_size,
1369 data_size,
1370 kQRegSizeInBytes,
1371 start_byte);
1372 fprintf(stream_,
1373 " -> %s0x%016" PRIxPTR "%s\n",
1374 clr_memory_address,
1375 address,
1376 clr_normal);
1377 start_byte += kQRegSizeInBytes;
1378 address += kQRegSizeInBytes;
1379 }
1380}
1381
Jacob Bramley199339d2019-08-05 18:49:13 +01001382void Simulator::PrintPRead(uintptr_t address, unsigned reg_code) {
1383 pregisters_[reg_code].NotifyRegisterLogged();
1384
1385 // There are no predicated load-predicate instructions, so we can always
1386 // print the full register.
1387 //
1388 // The template for P registers:
1389 // "# p{code}<m+15:m>: 0b 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 0 <- {address}",
1390 // where m is multiple of 16.
1391
1392 int bytes_per_chunk = kQRegSizeInBytes / kZRegBitsPerPRegBit;
1393 int bytes = pregisters_[reg_code].GetSizeInBytes();
1394 for (int byte = bytes - bytes_per_chunk; byte >= 0; byte -= bytes_per_chunk) {
1395 PrintPRegisterRawHelper(reg_code, byte * kBitsPerByte);
1396 fprintf(stream_,
1397 " <- %s0x%016" PRIxPTR "%s\n",
1398 clr_memory_address,
1399 address,
1400 clr_normal);
1401 address += bytes_per_chunk;
1402 }
1403}
1404
1405void Simulator::PrintPWrite(uintptr_t address, unsigned reg_code) {
1406 // There are no predicated store-predicate instructions, so we can always
1407 // print the full register.
1408 //
1409 // The template for P registers:
1410 // "# p{code}<m+15:m>: 0b 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 0 -> {address}",
1411 // where m is multiple of 16.
1412 int bytes_per_chunk = kQRegSizeInBytes / kZRegBitsPerPRegBit;
1413 int bytes = pregisters_[reg_code].GetSizeInBytes();
1414 for (int byte = bytes - bytes_per_chunk; byte >= 0; byte -= bytes_per_chunk) {
1415 PrintPRegisterRawHelper(reg_code, byte * kBitsPerByte);
1416 fprintf(stream_,
1417 " -> %s0x%016" PRIxPTR "%s\n",
1418 clr_memory_address,
1419 address,
1420 clr_normal);
1421 address += bytes_per_chunk;
1422 }
1423}
1424
Alexandre Ramesd3832962016-07-04 15:03:43 +01001425
Jacob Bramleye79723a2016-06-07 17:50:47 +01001426void Simulator::PrintTakenBranch(const Instruction* target) {
1427 fprintf(stream_,
1428 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1429 clr_branch_marker,
1430 clr_normal,
1431 reinterpret_cast<uint64_t>(target));
1432}
1433
1434
Alexandre Ramesd3832962016-07-04 15:03:43 +01001435// Visitors---------------------------------------------------------------------
1436
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001437
1438void Simulator::VisitReserved(const Instruction* instr) {
1439 // UDF is the only instruction in this group, and the Decoder is precise here.
1440 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1441
1442 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1443 reinterpret_cast<const void*>(instr),
1444 instr->GetInstructionBits());
1445 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1446}
1447
1448
Alexandre Ramesd3832962016-07-04 15:03:43 +01001449void Simulator::VisitUnimplemented(const Instruction* instr) {
1450 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1451 reinterpret_cast<const void*>(instr),
1452 instr->GetInstructionBits());
1453 VIXL_UNIMPLEMENTED();
1454}
1455
1456
1457void Simulator::VisitUnallocated(const Instruction* instr) {
1458 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1459 reinterpret_cast<const void*>(instr),
1460 instr->GetInstructionBits());
1461 VIXL_UNIMPLEMENTED();
1462}
1463
1464
1465void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1466 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1467 (instr->Mask(PCRelAddressingMask) == ADRP));
1468
1469 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1470}
1471
1472
1473void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1474 switch (instr->Mask(UnconditionalBranchMask)) {
1475 case BL:
1476 WriteLr(instr->GetNextInstruction());
1477 VIXL_FALLTHROUGH();
1478 case B:
1479 WritePc(instr->GetImmPCOffsetTarget());
1480 break;
1481 default:
1482 VIXL_UNREACHABLE();
1483 }
1484}
1485
1486
1487void Simulator::VisitConditionalBranch(const Instruction* instr) {
1488 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1489 if (ConditionPassed(instr->GetConditionBranch())) {
1490 WritePc(instr->GetImmPCOffsetTarget());
1491 }
1492}
1493
Martyn Capewellcb963f72018-10-22 15:25:28 +01001494BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1495 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1496 case BLR:
1497 case BLRAA:
1498 case BLRAB:
1499 case BLRAAZ:
1500 case BLRABZ:
1501 return BranchAndLink;
1502 case BR:
1503 case BRAA:
1504 case BRAB:
1505 case BRAAZ:
1506 case BRABZ:
1507 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1508 !PcIsInGuardedPage()) {
1509 return BranchFromUnguardedOrToIP;
1510 }
1511 return BranchFromGuardedNotToIP;
1512 }
1513 return DefaultBType;
1514}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001515
1516void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01001517 bool authenticate = false;
1518 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01001519 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01001520 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001521
1522 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1523 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01001524 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001525 VIXL_FALLTHROUGH();
1526 case BR:
1527 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01001528 break;
1529
1530 case BLRAAZ:
1531 case BLRABZ:
1532 link = true;
1533 VIXL_FALLTHROUGH();
1534 case BRAAZ:
1535 case BRABZ:
1536 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001537 break;
1538
1539 case BLRAA:
1540 case BLRAB:
1541 link = true;
1542 VIXL_FALLTHROUGH();
1543 case BRAA:
1544 case BRAB:
1545 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001546 context = ReadXRegister(instr->GetRd());
1547 break;
1548
1549 case RETAA:
1550 case RETAB:
1551 authenticate = true;
1552 addr = ReadXRegister(kLinkRegCode);
1553 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001554 break;
1555 default:
1556 VIXL_UNREACHABLE();
1557 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001558
1559 if (link) {
1560 WriteLr(instr->GetNextInstruction());
1561 }
1562
1563 if (authenticate) {
1564 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1565 addr = AuthPAC(addr, context, key, kInstructionPointer);
1566
1567 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1568 if (((addr >> error_lsb) & 0x3) != 0x0) {
1569 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1570 }
1571 }
1572
Martyn Capewellcb963f72018-10-22 15:25:28 +01001573 WritePc(Instruction::Cast(addr));
1574 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001575}
1576
1577
1578void Simulator::VisitTestBranch(const Instruction* instr) {
1579 unsigned bit_pos =
1580 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1581 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1582 bool take_branch = false;
1583 switch (instr->Mask(TestBranchMask)) {
1584 case TBZ:
1585 take_branch = bit_zero;
1586 break;
1587 case TBNZ:
1588 take_branch = !bit_zero;
1589 break;
1590 default:
1591 VIXL_UNIMPLEMENTED();
1592 }
1593 if (take_branch) {
1594 WritePc(instr->GetImmPCOffsetTarget());
1595 }
1596}
1597
1598
1599void Simulator::VisitCompareBranch(const Instruction* instr) {
1600 unsigned rt = instr->GetRt();
1601 bool take_branch = false;
1602 switch (instr->Mask(CompareBranchMask)) {
1603 case CBZ_w:
1604 take_branch = (ReadWRegister(rt) == 0);
1605 break;
1606 case CBZ_x:
1607 take_branch = (ReadXRegister(rt) == 0);
1608 break;
1609 case CBNZ_w:
1610 take_branch = (ReadWRegister(rt) != 0);
1611 break;
1612 case CBNZ_x:
1613 take_branch = (ReadXRegister(rt) != 0);
1614 break;
1615 default:
1616 VIXL_UNIMPLEMENTED();
1617 }
1618 if (take_branch) {
1619 WritePc(instr->GetImmPCOffsetTarget());
1620 }
1621}
1622
1623
1624void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1625 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1626 bool set_flags = instr->GetFlagsUpdate();
1627 int64_t new_val = 0;
1628 Instr operation = instr->Mask(AddSubOpMask);
1629
1630 switch (operation) {
1631 case ADD:
1632 case ADDS: {
1633 new_val = AddWithCarry(reg_size,
1634 set_flags,
1635 ReadRegister(reg_size,
1636 instr->GetRn(),
1637 instr->GetRnMode()),
1638 op2);
1639 break;
1640 }
1641 case SUB:
1642 case SUBS: {
1643 new_val = AddWithCarry(reg_size,
1644 set_flags,
1645 ReadRegister(reg_size,
1646 instr->GetRn(),
1647 instr->GetRnMode()),
1648 ~op2,
1649 1);
1650 break;
1651 }
1652 default:
1653 VIXL_UNREACHABLE();
1654 }
1655
1656 WriteRegister(reg_size,
1657 instr->GetRd(),
1658 new_val,
1659 LogRegWrites,
1660 instr->GetRdMode());
1661}
1662
1663
1664void Simulator::VisitAddSubShifted(const Instruction* instr) {
1665 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1666 int64_t op2 = ShiftOperand(reg_size,
1667 ReadRegister(reg_size, instr->GetRm()),
1668 static_cast<Shift>(instr->GetShiftDP()),
1669 instr->GetImmDPShift());
1670 AddSubHelper(instr, op2);
1671}
1672
1673
1674void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1675 int64_t op2 = instr->GetImmAddSub()
1676 << ((instr->GetShiftAddSub() == 1) ? 12 : 0);
1677 AddSubHelper(instr, op2);
1678}
1679
1680
1681void Simulator::VisitAddSubExtended(const Instruction* instr) {
1682 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1683 int64_t op2 = ExtendValue(reg_size,
1684 ReadRegister(reg_size, instr->GetRm()),
1685 static_cast<Extend>(instr->GetExtendMode()),
1686 instr->GetImmExtendShift());
1687 AddSubHelper(instr, op2);
1688}
1689
1690
1691void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1692 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1693 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1694 int64_t new_val;
1695
1696 if ((instr->Mask(AddSubOpMask) == SUB) ||
1697 (instr->Mask(AddSubOpMask) == SUBS)) {
1698 op2 = ~op2;
1699 }
1700
1701 new_val = AddWithCarry(reg_size,
1702 instr->GetFlagsUpdate(),
1703 ReadRegister(reg_size, instr->GetRn()),
1704 op2,
1705 ReadC());
1706
1707 WriteRegister(reg_size, instr->GetRd(), new_val);
1708}
1709
1710
Alexander Gilday2487f142018-11-05 13:07:27 +00001711void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1712 switch (instr->Mask(RotateRightIntoFlagsMask)) {
1713 case RMIF: {
1714 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1715 unsigned shift = instr->GetImmRMIFRotation();
1716 unsigned mask = instr->GetNzcv();
1717 uint64_t rotated = RotateRight(value, shift, kXRegSize);
1718
1719 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1720 break;
1721 }
1722 }
1723}
1724
1725
1726void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1727 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1728 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1729
1730 unsigned sign_bit = (value >> msb) & 1;
1731 unsigned overflow_bit = (value >> (msb + 1)) & 1;
1732 ReadNzcv().SetN(sign_bit);
1733 ReadNzcv().SetZ((value << (31 - msb)) == 0);
1734 ReadNzcv().SetV(sign_bit ^ overflow_bit);
1735}
1736
1737
Alexandre Ramesd3832962016-07-04 15:03:43 +01001738void Simulator::VisitLogicalShifted(const Instruction* instr) {
1739 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1740 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1741 unsigned shift_amount = instr->GetImmDPShift();
1742 int64_t op2 = ShiftOperand(reg_size,
1743 ReadRegister(reg_size, instr->GetRm()),
1744 shift_type,
1745 shift_amount);
1746 if (instr->Mask(NOT) == NOT) {
1747 op2 = ~op2;
1748 }
1749 LogicalHelper(instr, op2);
1750}
1751
1752
1753void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1754 LogicalHelper(instr, instr->GetImmLogical());
1755}
1756
1757
1758void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1759 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1760 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1761 int64_t result = 0;
1762 bool update_flags = false;
1763
1764 // Switch on the logical operation, stripping out the NOT bit, as it has a
1765 // different meaning for logical immediate instructions.
1766 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1767 case ANDS:
1768 update_flags = true;
1769 VIXL_FALLTHROUGH();
1770 case AND:
1771 result = op1 & op2;
1772 break;
1773 case ORR:
1774 result = op1 | op2;
1775 break;
1776 case EOR:
1777 result = op1 ^ op2;
1778 break;
1779 default:
1780 VIXL_UNIMPLEMENTED();
1781 }
1782
1783 if (update_flags) {
1784 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1785 ReadNzcv().SetZ(CalcZFlag(result));
1786 ReadNzcv().SetC(0);
1787 ReadNzcv().SetV(0);
1788 LogSystemRegister(NZCV);
1789 }
1790
1791 WriteRegister(reg_size,
1792 instr->GetRd(),
1793 result,
1794 LogRegWrites,
1795 instr->GetRdMode());
1796}
1797
1798
1799void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1800 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1801 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1802}
1803
1804
1805void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1806 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1807}
1808
1809
1810void Simulator::ConditionalCompareHelper(const Instruction* instr,
1811 int64_t op2) {
1812 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1813 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1814
1815 if (ConditionPassed(instr->GetCondition())) {
1816 // If the condition passes, set the status flags to the result of comparing
1817 // the operands.
1818 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1819 AddWithCarry(reg_size, true, op1, ~op2, 1);
1820 } else {
1821 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1822 AddWithCarry(reg_size, true, op1, op2, 0);
1823 }
1824 } else {
1825 // If the condition fails, set the status flags to the nzcv immediate.
1826 ReadNzcv().SetFlags(instr->GetNzcv());
1827 LogSystemRegister(NZCV);
1828 }
1829}
1830
1831
1832void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1833 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1834 LoadStoreHelper(instr, offset, Offset);
1835}
1836
1837
1838void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1839 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1840}
1841
1842
1843void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1844 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1845}
1846
1847
1848void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1849 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1850}
1851
1852
Alexander Gilday311edf22018-10-29 13:41:41 +00001853template <typename T1, typename T2>
1854void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1855 unsigned rt = instr->GetRt();
1856 unsigned rn = instr->GetRn();
1857
1858 unsigned element_size = sizeof(T2);
1859 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1860 int offset = instr->GetImmLS();
1861 address += offset;
1862
1863 // Verify that the address is available to the host.
1864 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1865
1866 // Check the alignment of `address`.
1867 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1868 VIXL_ALIGNMENT_EXCEPTION();
1869 }
1870
1871 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
1872
1873 // Approximate load-acquire by issuing a full barrier after the load.
1874 __sync_synchronize();
1875
1876 LogRead(address, rt, GetPrintRegisterFormat(element_size));
1877}
1878
1879
1880template <typename T>
1881void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
1882 unsigned rt = instr->GetRt();
1883 unsigned rn = instr->GetRn();
1884
1885 unsigned element_size = sizeof(T);
1886 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1887 int offset = instr->GetImmLS();
1888 address += offset;
1889
1890 // Verify that the address is available to the host.
1891 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1892
1893 // Check the alignment of `address`.
1894 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1895 VIXL_ALIGNMENT_EXCEPTION();
1896 }
1897
1898 // Approximate store-release by issuing a full barrier after the load.
1899 __sync_synchronize();
1900
1901 Memory::Write<T>(address, ReadRegister<T>(rt));
1902
1903 LogWrite(address, rt, GetPrintRegisterFormat(element_size));
1904}
1905
1906
1907void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
1908 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
1909 case LDAPURB:
1910 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
1911 break;
1912 case LDAPURH:
1913 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
1914 break;
1915 case LDAPUR_w:
1916 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
1917 break;
1918 case LDAPUR_x:
1919 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
1920 break;
1921 case LDAPURSB_w:
1922 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
1923 break;
1924 case LDAPURSB_x:
1925 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
1926 break;
1927 case LDAPURSH_w:
1928 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
1929 break;
1930 case LDAPURSH_x:
1931 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
1932 break;
1933 case LDAPURSW:
1934 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
1935 break;
1936 case STLURB:
1937 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
1938 break;
1939 case STLURH:
1940 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
1941 break;
1942 case STLUR_w:
1943 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
1944 break;
1945 case STLUR_x:
1946 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
1947 break;
1948 }
1949}
1950
1951
Alexander Gilday75605592018-11-01 09:30:29 +00001952void Simulator::VisitLoadStorePAC(const Instruction* instr) {
1953 unsigned dst = instr->GetRt();
1954 unsigned addr_reg = instr->GetRn();
1955
1956 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
1957
1958 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
1959 address = AuthPAC(address, 0, key, kDataPointer);
1960
1961 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
1962 if (((address >> error_lsb) & 0x3) != 0x0) {
1963 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1964 }
1965
1966
1967 if ((addr_reg == 31) && ((address % 16) != 0)) {
1968 // When the base register is SP the stack pointer is required to be
1969 // quadword aligned prior to the address calculation and write-backs.
1970 // Misalignment will cause a stack alignment fault.
1971 VIXL_ALIGNMENT_EXCEPTION();
1972 }
1973
1974 int64_t offset = instr->GetImmLSPAC();
1975 address += offset;
1976
1977 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
1978 // Pre-index mode.
1979 VIXL_ASSERT(offset != 0);
1980 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
1981 }
1982
1983 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
1984
1985 // Verify that the calculated address is available to the host.
1986 VIXL_ASSERT(address == addr_ptr);
1987
1988 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
1989 unsigned access_size = 1 << 3;
1990 LogRead(addr_ptr, dst, GetPrintRegisterFormatForSize(access_size));
1991}
1992
1993
Alexandre Ramesd3832962016-07-04 15:03:43 +01001994void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
1995 Extend ext = static_cast<Extend>(instr->GetExtendMode());
1996 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1997 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
1998
1999 int64_t offset =
2000 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
2001 LoadStoreHelper(instr, offset, Offset);
2002}
2003
2004
2005void Simulator::LoadStoreHelper(const Instruction* instr,
2006 int64_t offset,
2007 AddrMode addrmode) {
2008 unsigned srcdst = instr->GetRt();
2009 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2010
2011 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
2012 switch (op) {
2013 case LDRB_w:
2014 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
2015 break;
2016 case LDRH_w:
2017 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
2018 break;
2019 case LDR_w:
2020 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
2021 break;
2022 case LDR_x:
2023 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
2024 break;
2025 case LDRSB_w:
2026 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
2027 break;
2028 case LDRSH_w:
2029 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
2030 break;
2031 case LDRSB_x:
2032 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
2033 break;
2034 case LDRSH_x:
2035 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
2036 break;
2037 case LDRSW_x:
2038 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
2039 break;
2040 case LDR_b:
2041 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
2042 break;
2043 case LDR_h:
2044 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
2045 break;
2046 case LDR_s:
2047 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
2048 break;
2049 case LDR_d:
2050 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
2051 break;
2052 case LDR_q:
2053 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
2054 break;
2055
2056 case STRB_w:
2057 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
2058 break;
2059 case STRH_w:
2060 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
2061 break;
2062 case STR_w:
2063 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
2064 break;
2065 case STR_x:
2066 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
2067 break;
2068 case STR_b:
2069 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
2070 break;
2071 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01002072 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002073 break;
2074 case STR_s:
2075 Memory::Write<float>(address, ReadSRegister(srcdst));
2076 break;
2077 case STR_d:
2078 Memory::Write<double>(address, ReadDRegister(srcdst));
2079 break;
2080 case STR_q:
2081 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
2082 break;
2083
2084 // Ignore prfm hint instructions.
2085 case PRFM:
2086 break;
2087
2088 default:
2089 VIXL_UNIMPLEMENTED();
2090 }
2091
2092 unsigned access_size = 1 << instr->GetSizeLS();
2093 if (instr->IsLoad()) {
2094 if ((op == LDR_s) || (op == LDR_d)) {
2095 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
2096 } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
2097 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2098 } else {
2099 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2100 }
2101 } else if (instr->IsStore()) {
2102 if ((op == STR_s) || (op == STR_d)) {
2103 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
2104 } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
2105 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2106 } else {
2107 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
2108 }
2109 } else {
2110 VIXL_ASSERT(op == PRFM);
2111 }
2112
2113 local_monitor_.MaybeClear();
2114}
2115
2116
2117void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
2118 LoadStorePairHelper(instr, Offset);
2119}
2120
2121
2122void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
2123 LoadStorePairHelper(instr, PreIndex);
2124}
2125
2126
2127void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
2128 LoadStorePairHelper(instr, PostIndex);
2129}
2130
2131
2132void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
2133 LoadStorePairHelper(instr, Offset);
2134}
2135
2136
2137void Simulator::LoadStorePairHelper(const Instruction* instr,
2138 AddrMode addrmode) {
2139 unsigned rt = instr->GetRt();
2140 unsigned rt2 = instr->GetRt2();
2141 int element_size = 1 << instr->GetSizeLSPair();
2142 int64_t offset = instr->GetImmLSPair() * element_size;
2143 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2144 uintptr_t address2 = address + element_size;
2145
2146 LoadStorePairOp op =
2147 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
2148
2149 // 'rt' and 'rt2' can only be aliased for stores.
2150 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2151
2152 switch (op) {
2153 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
2154 // will print a more detailed log.
2155 case LDP_w: {
2156 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2157 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
2158 break;
2159 }
2160 case LDP_s: {
2161 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2162 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
2163 break;
2164 }
2165 case LDP_x: {
2166 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2167 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
2168 break;
2169 }
2170 case LDP_d: {
2171 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2172 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
2173 break;
2174 }
2175 case LDP_q: {
2176 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2177 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
2178 break;
2179 }
2180 case LDPSW_x: {
2181 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2182 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
2183 break;
2184 }
2185 case STP_w: {
2186 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2187 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
2188 break;
2189 }
2190 case STP_s: {
2191 Memory::Write<float>(address, ReadSRegister(rt));
2192 Memory::Write<float>(address2, ReadSRegister(rt2));
2193 break;
2194 }
2195 case STP_x: {
2196 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2197 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
2198 break;
2199 }
2200 case STP_d: {
2201 Memory::Write<double>(address, ReadDRegister(rt));
2202 Memory::Write<double>(address2, ReadDRegister(rt2));
2203 break;
2204 }
2205 case STP_q: {
2206 Memory::Write<qreg_t>(address, ReadQRegister(rt));
2207 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
2208 break;
2209 }
2210 default:
2211 VIXL_UNREACHABLE();
2212 }
2213
2214 // Print a detailed trace (including the memory address) instead of the basic
2215 // register:value trace generated by set_*reg().
2216 if (instr->IsLoad()) {
2217 if ((op == LDP_s) || (op == LDP_d)) {
2218 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
2219 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
2220 } else if (op == LDP_q) {
2221 LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2222 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2223 } else {
2224 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2225 LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2226 }
2227 } else {
2228 if ((op == STP_s) || (op == STP_d)) {
2229 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
2230 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
2231 } else if (op == STP_q) {
2232 LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2233 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2234 } else {
2235 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2236 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2237 }
2238 }
2239
2240 local_monitor_.MaybeClear();
2241}
2242
2243
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002244template <typename T>
2245void Simulator::CompareAndSwapHelper(const Instruction* instr) {
2246 unsigned rs = instr->GetRs();
2247 unsigned rt = instr->GetRt();
2248 unsigned rn = instr->GetRn();
2249
2250 unsigned element_size = sizeof(T);
2251 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2252
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002253 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2254
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002255 bool is_acquire = instr->ExtractBit(22) == 1;
2256 bool is_release = instr->ExtractBit(15) == 1;
2257
2258 T comparevalue = ReadRegister<T>(rs);
2259 T newvalue = ReadRegister<T>(rt);
2260
2261 // The architecture permits that the data read clears any exclusive monitors
2262 // associated with that location, even if the compare subsequently fails.
2263 local_monitor_.Clear();
2264
2265 T data = Memory::Read<T>(address);
2266 if (is_acquire) {
2267 // Approximate load-acquire by issuing a full barrier after the load.
2268 __sync_synchronize();
2269 }
2270
2271 if (data == comparevalue) {
2272 if (is_release) {
2273 // Approximate store-release by issuing a full barrier before the store.
2274 __sync_synchronize();
2275 }
2276 Memory::Write<T>(address, newvalue);
2277 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2278 }
2279 WriteRegister<T>(rs, data);
2280 LogRead(address, rs, GetPrintRegisterFormatForSize(element_size));
2281}
2282
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002283
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002284template <typename T>
2285void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
2286 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
2287 unsigned rs = instr->GetRs();
2288 unsigned rt = instr->GetRt();
2289 unsigned rn = instr->GetRn();
2290
2291 VIXL_ASSERT((rs % 2 == 0) && (rs % 2 == 0));
2292
2293 unsigned element_size = sizeof(T);
2294 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002295
2296 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
2297
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002298 uint64_t address2 = address + element_size;
2299
2300 bool is_acquire = instr->ExtractBit(22) == 1;
2301 bool is_release = instr->ExtractBit(15) == 1;
2302
2303 T comparevalue_high = ReadRegister<T>(rs + 1);
2304 T comparevalue_low = ReadRegister<T>(rs);
2305 T newvalue_high = ReadRegister<T>(rt + 1);
2306 T newvalue_low = ReadRegister<T>(rt);
2307
2308 // The architecture permits that the data read clears any exclusive monitors
2309 // associated with that location, even if the compare subsequently fails.
2310 local_monitor_.Clear();
2311
2312 T data_high = Memory::Read<T>(address);
2313 T data_low = Memory::Read<T>(address2);
2314
2315 if (is_acquire) {
2316 // Approximate load-acquire by issuing a full barrier after the load.
2317 __sync_synchronize();
2318 }
2319
2320 bool same =
2321 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2322 if (same) {
2323 if (is_release) {
2324 // Approximate store-release by issuing a full barrier before the store.
2325 __sync_synchronize();
2326 }
2327
2328 Memory::Write<T>(address, newvalue_high);
2329 Memory::Write<T>(address2, newvalue_low);
2330 }
2331
2332 WriteRegister<T>(rs + 1, data_high);
2333 WriteRegister<T>(rs, data_low);
2334
2335 LogRead(address, rs + 1, GetPrintRegisterFormatForSize(element_size));
2336 LogRead(address2, rs, GetPrintRegisterFormatForSize(element_size));
2337
2338 if (same) {
2339 LogWrite(address, rt + 1, GetPrintRegisterFormatForSize(element_size));
2340 LogWrite(address2, rt, GetPrintRegisterFormatForSize(element_size));
2341 }
2342}
2343
Alexandre Ramesd3832962016-07-04 15:03:43 +01002344
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002345void Simulator::PrintExclusiveAccessWarning() {
2346 if (print_exclusive_access_warning_) {
2347 fprintf(stderr,
2348 "%sWARNING:%s VIXL simulator support for "
2349 "load-/store-/clear-exclusive "
2350 "instructions is limited. Refer to the README for details.%s\n",
2351 clr_warning,
2352 clr_warning_message,
2353 clr_normal);
2354 print_exclusive_access_warning_ = false;
2355 }
2356}
2357
2358
Alexandre Ramesd3832962016-07-04 15:03:43 +01002359void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002360 LoadStoreExclusive op =
2361 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
2362
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002363 switch (op) {
2364 case CAS_w:
2365 case CASA_w:
2366 case CASL_w:
2367 case CASAL_w:
2368 CompareAndSwapHelper<uint32_t>(instr);
2369 break;
2370 case CAS_x:
2371 case CASA_x:
2372 case CASL_x:
2373 case CASAL_x:
2374 CompareAndSwapHelper<uint64_t>(instr);
2375 break;
2376 case CASB:
2377 case CASAB:
2378 case CASLB:
2379 case CASALB:
2380 CompareAndSwapHelper<uint8_t>(instr);
2381 break;
2382 case CASH:
2383 case CASAH:
2384 case CASLH:
2385 case CASALH:
2386 CompareAndSwapHelper<uint16_t>(instr);
2387 break;
2388 case CASP_w:
2389 case CASPA_w:
2390 case CASPL_w:
2391 case CASPAL_w:
2392 CompareAndSwapPairHelper<uint32_t>(instr);
2393 break;
2394 case CASP_x:
2395 case CASPA_x:
2396 case CASPL_x:
2397 case CASPAL_x:
2398 CompareAndSwapPairHelper<uint64_t>(instr);
2399 break;
2400 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002401 PrintExclusiveAccessWarning();
2402
2403 unsigned rs = instr->GetRs();
2404 unsigned rt = instr->GetRt();
2405 unsigned rt2 = instr->GetRt2();
2406 unsigned rn = instr->GetRn();
2407
2408 bool is_exclusive = !instr->GetLdStXNotExclusive();
2409 bool is_acquire_release =
2410 !is_exclusive || instr->GetLdStXAcquireRelease();
2411 bool is_load = instr->GetLdStXLoad();
2412 bool is_pair = instr->GetLdStXPair();
2413
2414 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2415 unsigned access_size = is_pair ? element_size * 2 : element_size;
2416 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2417
2418 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2419
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002420 if (is_load) {
2421 if (is_exclusive) {
2422 local_monitor_.MarkExclusive(address, access_size);
2423 } else {
2424 // Any non-exclusive load can clear the local monitor as a side
2425 // effect. We don't need to do this, but it is useful to stress the
2426 // simulated code.
2427 local_monitor_.Clear();
2428 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002429
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002430 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2431 // We will print a more detailed log.
2432 switch (op) {
2433 case LDXRB_w:
2434 case LDAXRB_w:
2435 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002436 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002437 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
2438 break;
2439 case LDXRH_w:
2440 case LDAXRH_w:
2441 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002442 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002443 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
2444 break;
2445 case LDXR_w:
2446 case LDAXR_w:
2447 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002448 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002449 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2450 break;
2451 case LDXR_x:
2452 case LDAXR_x:
2453 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002454 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002455 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2456 break;
2457 case LDXP_w:
2458 case LDAXP_w:
2459 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2460 WriteWRegister(rt2,
2461 Memory::Read<uint32_t>(address + element_size),
2462 NoRegLog);
2463 break;
2464 case LDXP_x:
2465 case LDAXP_x:
2466 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2467 WriteXRegister(rt2,
2468 Memory::Read<uint64_t>(address + element_size),
2469 NoRegLog);
2470 break;
2471 default:
2472 VIXL_UNREACHABLE();
2473 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002474
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002475 if (is_acquire_release) {
2476 // Approximate load-acquire by issuing a full barrier after the load.
2477 __sync_synchronize();
2478 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002479
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002480 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2481 if (is_pair) {
2482 LogRead(address + element_size,
2483 rt2,
2484 GetPrintRegisterFormatForSize(element_size));
2485 }
2486 } else {
2487 if (is_acquire_release) {
2488 // Approximate store-release by issuing a full barrier before the
2489 // store.
2490 __sync_synchronize();
2491 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002492
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002493 bool do_store = true;
2494 if (is_exclusive) {
2495 do_store = local_monitor_.IsExclusive(address, access_size) &&
2496 global_monitor_.IsExclusive(address, access_size);
2497 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002498
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002499 // - All exclusive stores explicitly clear the local monitor.
2500 local_monitor_.Clear();
2501 } else {
2502 // - Any other store can clear the local monitor as a side effect.
2503 local_monitor_.MaybeClear();
2504 }
2505
2506 if (do_store) {
2507 switch (op) {
2508 case STXRB_w:
2509 case STLXRB_w:
2510 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002511 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002512 Memory::Write<uint8_t>(address, ReadWRegister(rt));
2513 break;
2514 case STXRH_w:
2515 case STLXRH_w:
2516 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002517 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002518 Memory::Write<uint16_t>(address, ReadWRegister(rt));
2519 break;
2520 case STXR_w:
2521 case STLXR_w:
2522 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002523 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002524 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2525 break;
2526 case STXR_x:
2527 case STLXR_x:
2528 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002529 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002530 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2531 break;
2532 case STXP_w:
2533 case STLXP_w:
2534 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2535 Memory::Write<uint32_t>(address + element_size,
2536 ReadWRegister(rt2));
2537 break;
2538 case STXP_x:
2539 case STLXP_x:
2540 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2541 Memory::Write<uint64_t>(address + element_size,
2542 ReadXRegister(rt2));
2543 break;
2544 default:
2545 VIXL_UNREACHABLE();
2546 }
2547
2548 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2549 if (is_pair) {
2550 LogWrite(address + element_size,
2551 rt2,
2552 GetPrintRegisterFormatForSize(element_size));
2553 }
2554 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002555 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002556 }
2557}
2558
Jacob Bramleyca789742018-09-13 14:25:46 +01002559template <typename T>
2560void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2561 unsigned rs = instr->GetRs();
2562 unsigned rt = instr->GetRt();
2563 unsigned rn = instr->GetRn();
2564
2565 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2566 bool is_release = instr->ExtractBit(22) == 1;
2567
2568 unsigned element_size = sizeof(T);
2569 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2570
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002571 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002572
2573 T value = ReadRegister<T>(rs);
2574
2575 T data = Memory::Read<T>(address);
2576
2577 if (is_acquire) {
2578 // Approximate load-acquire by issuing a full barrier after the load.
2579 __sync_synchronize();
2580 }
2581
2582 T result = 0;
2583 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2584 case LDADDOp:
2585 result = data + value;
2586 break;
2587 case LDCLROp:
2588 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2589 result = data & ~value;
2590 break;
2591 case LDEOROp:
2592 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2593 result = data ^ value;
2594 break;
2595 case LDSETOp:
2596 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2597 result = data | value;
2598 break;
2599
2600 // Signed/Unsigned difference is done via the templated type T.
2601 case LDSMAXOp:
2602 case LDUMAXOp:
2603 result = (data > value) ? data : value;
2604 break;
2605 case LDSMINOp:
2606 case LDUMINOp:
2607 result = (data > value) ? value : data;
2608 break;
2609 }
2610
2611 if (is_release) {
2612 // Approximate store-release by issuing a full barrier before the store.
2613 __sync_synchronize();
2614 }
2615
2616 Memory::Write<T>(address, result);
2617 WriteRegister<T>(rt, data, NoRegLog);
2618
2619 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2620 LogWrite(address, rs, GetPrintRegisterFormatForSize(element_size));
2621}
2622
2623template <typename T>
2624void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2625 unsigned rs = instr->GetRs();
2626 unsigned rt = instr->GetRt();
2627 unsigned rn = instr->GetRn();
2628
2629 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2630 bool is_release = instr->ExtractBit(22) == 1;
2631
2632 unsigned element_size = sizeof(T);
2633 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2634
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002635 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002636
2637 T data = Memory::Read<T>(address);
2638 if (is_acquire) {
2639 // Approximate load-acquire by issuing a full barrier after the load.
2640 __sync_synchronize();
2641 }
2642
2643 if (is_release) {
2644 // Approximate store-release by issuing a full barrier before the store.
2645 __sync_synchronize();
2646 }
2647 Memory::Write<T>(address, ReadRegister<T>(rs));
2648
2649 WriteRegister<T>(rt, data);
2650
2651 LogRead(address, rt, GetPrintRegisterFormat(element_size));
2652 LogWrite(address, rs, GetPrintRegisterFormat(element_size));
2653}
2654
2655template <typename T>
2656void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2657 unsigned rt = instr->GetRt();
2658 unsigned rn = instr->GetRn();
2659
2660 unsigned element_size = sizeof(T);
2661 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2662
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002663 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2664
Jacob Bramleyca789742018-09-13 14:25:46 +01002665 WriteRegister<T>(rt, Memory::Read<T>(address));
2666
2667 // Approximate load-acquire by issuing a full barrier after the load.
2668 __sync_synchronize();
2669
2670 LogRead(address, rt, GetPrintRegisterFormat(element_size));
2671}
2672
2673#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2674 V(LDADD) \
2675 V(LDCLR) \
2676 V(LDEOR) \
2677 V(LDSET) \
2678 V(LDUMAX) \
2679 V(LDUMIN)
2680
2681#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2682 V(LDSMAX) \
2683 V(LDSMIN)
2684
2685void Simulator::VisitAtomicMemory(const Instruction* instr) {
2686 switch (instr->Mask(AtomicMemoryMask)) {
2687// clang-format off
2688#define SIM_FUNC_B(A) \
2689 case A##B: \
2690 case A##AB: \
2691 case A##LB: \
2692 case A##ALB:
2693#define SIM_FUNC_H(A) \
2694 case A##H: \
2695 case A##AH: \
2696 case A##LH: \
2697 case A##ALH:
2698#define SIM_FUNC_w(A) \
2699 case A##_w: \
2700 case A##A_w: \
2701 case A##L_w: \
2702 case A##AL_w:
2703#define SIM_FUNC_x(A) \
2704 case A##_x: \
2705 case A##A_x: \
2706 case A##L_x: \
2707 case A##AL_x:
2708
2709 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2710 AtomicMemorySimpleHelper<uint8_t>(instr);
2711 break;
2712 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2713 AtomicMemorySimpleHelper<int8_t>(instr);
2714 break;
2715 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2716 AtomicMemorySimpleHelper<uint16_t>(instr);
2717 break;
2718 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2719 AtomicMemorySimpleHelper<int16_t>(instr);
2720 break;
2721 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2722 AtomicMemorySimpleHelper<uint32_t>(instr);
2723 break;
2724 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2725 AtomicMemorySimpleHelper<int32_t>(instr);
2726 break;
2727 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2728 AtomicMemorySimpleHelper<uint64_t>(instr);
2729 break;
2730 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2731 AtomicMemorySimpleHelper<int64_t>(instr);
2732 break;
2733 // clang-format on
2734
2735 case SWPB:
2736 case SWPAB:
2737 case SWPLB:
2738 case SWPALB:
2739 AtomicMemorySwapHelper<uint8_t>(instr);
2740 break;
2741 case SWPH:
2742 case SWPAH:
2743 case SWPLH:
2744 case SWPALH:
2745 AtomicMemorySwapHelper<uint16_t>(instr);
2746 break;
2747 case SWP_w:
2748 case SWPA_w:
2749 case SWPL_w:
2750 case SWPAL_w:
2751 AtomicMemorySwapHelper<uint32_t>(instr);
2752 break;
2753 case SWP_x:
2754 case SWPA_x:
2755 case SWPL_x:
2756 case SWPAL_x:
2757 AtomicMemorySwapHelper<uint64_t>(instr);
2758 break;
2759 case LDAPRB:
2760 LoadAcquireRCpcHelper<uint8_t>(instr);
2761 break;
2762 case LDAPRH:
2763 LoadAcquireRCpcHelper<uint16_t>(instr);
2764 break;
2765 case LDAPR_w:
2766 LoadAcquireRCpcHelper<uint32_t>(instr);
2767 break;
2768 case LDAPR_x:
2769 LoadAcquireRCpcHelper<uint64_t>(instr);
2770 break;
2771 }
2772}
2773
Alexandre Ramesd3832962016-07-04 15:03:43 +01002774
2775void Simulator::VisitLoadLiteral(const Instruction* instr) {
2776 unsigned rt = instr->GetRt();
2777 uint64_t address = instr->GetLiteralAddress<uint64_t>();
2778
2779 // Verify that the calculated address is available to the host.
2780 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2781
2782 switch (instr->Mask(LoadLiteralMask)) {
2783 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
2784 // print a more detailed log.
2785 case LDR_w_lit:
2786 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2787 LogRead(address, rt, kPrintWReg);
2788 break;
2789 case LDR_x_lit:
2790 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2791 LogRead(address, rt, kPrintXReg);
2792 break;
2793 case LDR_s_lit:
2794 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2795 LogVRead(address, rt, kPrintSReg);
2796 break;
2797 case LDR_d_lit:
2798 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2799 LogVRead(address, rt, kPrintDReg);
2800 break;
2801 case LDR_q_lit:
2802 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2803 LogVRead(address, rt, kPrintReg1Q);
2804 break;
2805 case LDRSW_x_lit:
2806 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2807 LogRead(address, rt, kPrintWReg);
2808 break;
2809
2810 // Ignore prfm hint instructions.
2811 case PRFM_lit:
2812 break;
2813
2814 default:
2815 VIXL_UNREACHABLE();
2816 }
2817
2818 local_monitor_.MaybeClear();
2819}
2820
2821
2822uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
2823 int64_t offset,
2824 AddrMode addrmode) {
2825 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2826
2827 if ((addr_reg == 31) && ((address % 16) != 0)) {
2828 // When the base register is SP the stack pointer is required to be
2829 // quadword aligned prior to the address calculation and write-backs.
2830 // Misalignment will cause a stack alignment fault.
2831 VIXL_ALIGNMENT_EXCEPTION();
2832 }
2833
2834 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
2835 VIXL_ASSERT(offset != 0);
2836 // Only preindex should log the register update here. For Postindex, the
2837 // update will be printed automatically by LogWrittenRegisters _after_ the
2838 // memory access itself is logged.
2839 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
2840 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
2841 }
2842
2843 if ((addrmode == Offset) || (addrmode == PreIndex)) {
2844 address += offset;
2845 }
2846
2847 // Verify that the calculated address is available to the host.
2848 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2849
2850 return static_cast<uintptr_t>(address);
2851}
2852
2853
2854void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
2855 MoveWideImmediateOp mov_op =
2856 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
2857 int64_t new_xn_val = 0;
2858
2859 bool is_64_bits = instr->GetSixtyFourBits() == 1;
2860 // Shift is limited for W operations.
2861 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
2862
2863 // Get the shifted immediate.
2864 int64_t shift = instr->GetShiftMoveWide() * 16;
2865 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
2866 << shift;
2867
2868 // Compute the new value.
2869 switch (mov_op) {
2870 case MOVN_w:
2871 case MOVN_x: {
2872 new_xn_val = ~shifted_imm16;
2873 if (!is_64_bits) new_xn_val &= kWRegMask;
2874 break;
2875 }
2876 case MOVK_w:
2877 case MOVK_x: {
2878 unsigned reg_code = instr->GetRd();
2879 int64_t prev_xn_val =
2880 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
2881 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
2882 break;
2883 }
2884 case MOVZ_w:
2885 case MOVZ_x: {
2886 new_xn_val = shifted_imm16;
2887 break;
2888 }
2889 default:
2890 VIXL_UNREACHABLE();
2891 }
2892
2893 // Update the destination register.
2894 WriteXRegister(instr->GetRd(), new_xn_val);
2895}
2896
2897
2898void Simulator::VisitConditionalSelect(const Instruction* instr) {
2899 uint64_t new_val = ReadXRegister(instr->GetRn());
2900
2901 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
2902 new_val = ReadXRegister(instr->GetRm());
2903 switch (instr->Mask(ConditionalSelectMask)) {
2904 case CSEL_w:
2905 case CSEL_x:
2906 break;
2907 case CSINC_w:
2908 case CSINC_x:
2909 new_val++;
2910 break;
2911 case CSINV_w:
2912 case CSINV_x:
2913 new_val = ~new_val;
2914 break;
2915 case CSNEG_w:
2916 case CSNEG_x:
2917 new_val = -new_val;
2918 break;
2919 default:
2920 VIXL_UNIMPLEMENTED();
2921 }
2922 }
2923 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2924 WriteRegister(reg_size, instr->GetRd(), new_val);
2925}
2926
2927
Jacob Bramleyca789742018-09-13 14:25:46 +01002928// clang-format off
2929#define PAUTH_MODES(V) \
2930 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
2931 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
2932 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
2933 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
2934 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
2935 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
2936 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
2937 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
2938// clang-format on
2939
Alexandre Ramesd3832962016-07-04 15:03:43 +01002940void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
2941 unsigned dst = instr->GetRd();
2942 unsigned src = instr->GetRn();
2943
2944 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01002945#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
2946 case PAC##SUFFIX: { \
2947 uint64_t ptr = ReadXRegister(dst); \
2948 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
2949 break; \
2950 } \
2951 case AUT##SUFFIX: { \
2952 uint64_t ptr = ReadXRegister(dst); \
2953 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
2954 break; \
2955 }
2956
2957 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
2958#undef DEFINE_PAUTH_FUNCS
2959
2960 case XPACI:
2961 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
2962 break;
2963 case XPACD:
2964 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
2965 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002966 case RBIT_w:
2967 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
2968 break;
2969 case RBIT_x:
2970 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
2971 break;
2972 case REV16_w:
2973 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
2974 break;
2975 case REV16_x:
2976 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
2977 break;
2978 case REV_w:
2979 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
2980 break;
2981 case REV32_x:
2982 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
2983 break;
2984 case REV_x:
2985 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
2986 break;
2987 case CLZ_w:
2988 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
2989 break;
2990 case CLZ_x:
2991 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
2992 break;
2993 case CLS_w:
2994 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
2995 break;
2996 case CLS_x:
2997 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
2998 break;
2999 default:
3000 VIXL_UNIMPLEMENTED();
3001 }
3002}
3003
3004
3005uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
3006 VIXL_ASSERT((n > 32) && (n <= 64));
3007 for (unsigned i = (n - 1); i >= 32; i--) {
3008 if (((data >> i) & 1) != 0) {
3009 uint64_t polysh32 = (uint64_t)poly << (i - 32);
3010 uint64_t mask = (UINT64_C(1) << i) - 1;
3011 data = ((data & mask) ^ polysh32);
3012 }
3013 }
3014 return data & 0xffffffff;
3015}
3016
3017
3018template <typename T>
3019uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
3020 unsigned size = sizeof(val) * 8; // Number of bits in type T.
3021 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
3022 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
3023 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
3024 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
3025}
3026
3027
3028uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
3029 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
3030 // the CRC of each 32-bit word sequentially.
3031 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
3032 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
3033}
3034
3035
3036void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
3037 Shift shift_op = NO_SHIFT;
3038 int64_t result = 0;
3039 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3040
3041 switch (instr->Mask(DataProcessing2SourceMask)) {
3042 case SDIV_w: {
3043 int32_t rn = ReadWRegister(instr->GetRn());
3044 int32_t rm = ReadWRegister(instr->GetRm());
3045 if ((rn == kWMinInt) && (rm == -1)) {
3046 result = kWMinInt;
3047 } else if (rm == 0) {
3048 // Division by zero can be trapped, but not on A-class processors.
3049 result = 0;
3050 } else {
3051 result = rn / rm;
3052 }
3053 break;
3054 }
3055 case SDIV_x: {
3056 int64_t rn = ReadXRegister(instr->GetRn());
3057 int64_t rm = ReadXRegister(instr->GetRm());
3058 if ((rn == kXMinInt) && (rm == -1)) {
3059 result = kXMinInt;
3060 } else if (rm == 0) {
3061 // Division by zero can be trapped, but not on A-class processors.
3062 result = 0;
3063 } else {
3064 result = rn / rm;
3065 }
3066 break;
3067 }
3068 case UDIV_w: {
3069 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
3070 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
3071 if (rm == 0) {
3072 // Division by zero can be trapped, but not on A-class processors.
3073 result = 0;
3074 } else {
3075 result = rn / rm;
3076 }
3077 break;
3078 }
3079 case UDIV_x: {
3080 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3081 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
3082 if (rm == 0) {
3083 // Division by zero can be trapped, but not on A-class processors.
3084 result = 0;
3085 } else {
3086 result = rn / rm;
3087 }
3088 break;
3089 }
3090 case LSLV_w:
3091 case LSLV_x:
3092 shift_op = LSL;
3093 break;
3094 case LSRV_w:
3095 case LSRV_x:
3096 shift_op = LSR;
3097 break;
3098 case ASRV_w:
3099 case ASRV_x:
3100 shift_op = ASR;
3101 break;
3102 case RORV_w:
3103 case RORV_x:
3104 shift_op = ROR;
3105 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003106 case PACGA: {
3107 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3108 uint64_t src = static_cast<uint64_t>(
3109 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
3110 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
3111 result = code & 0xffffffff00000000;
3112 break;
3113 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003114 case CRC32B: {
3115 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3116 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3117 result = Crc32Checksum(acc, val, CRC32_POLY);
3118 break;
3119 }
3120 case CRC32H: {
3121 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3122 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3123 result = Crc32Checksum(acc, val, CRC32_POLY);
3124 break;
3125 }
3126 case CRC32W: {
3127 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3128 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3129 result = Crc32Checksum(acc, val, CRC32_POLY);
3130 break;
3131 }
3132 case CRC32X: {
3133 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3134 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3135 result = Crc32Checksum(acc, val, CRC32_POLY);
3136 reg_size = kWRegSize;
3137 break;
3138 }
3139 case CRC32CB: {
3140 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3141 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3142 result = Crc32Checksum(acc, val, CRC32C_POLY);
3143 break;
3144 }
3145 case CRC32CH: {
3146 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3147 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3148 result = Crc32Checksum(acc, val, CRC32C_POLY);
3149 break;
3150 }
3151 case CRC32CW: {
3152 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3153 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3154 result = Crc32Checksum(acc, val, CRC32C_POLY);
3155 break;
3156 }
3157 case CRC32CX: {
3158 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3159 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3160 result = Crc32Checksum(acc, val, CRC32C_POLY);
3161 reg_size = kWRegSize;
3162 break;
3163 }
3164 default:
3165 VIXL_UNIMPLEMENTED();
3166 }
3167
3168 if (shift_op != NO_SHIFT) {
3169 // Shift distance encoded in the least-significant five/six bits of the
3170 // register.
3171 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
3172 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
3173 result = ShiftOperand(reg_size,
3174 ReadRegister(reg_size, instr->GetRn()),
3175 shift_op,
3176 shift);
3177 }
3178 WriteRegister(reg_size, instr->GetRd(), result);
3179}
3180
3181
Alexandre Ramesd3832962016-07-04 15:03:43 +01003182void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
3183 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3184
3185 uint64_t result = 0;
3186 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
3187 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
3188 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
3189 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
3190 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003191 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
3192 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003193 switch (instr->Mask(DataProcessing3SourceMask)) {
3194 case MADD_w:
3195 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003196 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003197 break;
3198 case MSUB_w:
3199 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003200 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003201 break;
3202 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003203 result = ReadXRegister(instr->GetRa()) +
3204 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003205 break;
3206 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003207 result = ReadXRegister(instr->GetRa()) -
3208 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003209 break;
3210 case UMADDL_x:
3211 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
3212 break;
3213 case UMSUBL_x:
3214 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
3215 break;
3216 case UMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003217 result =
3218 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
3219 ReadRegister<uint64_t>(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003220 break;
3221 case SMULH_x:
TatWai Chong13634762019-07-16 16:20:45 -07003222 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
3223 ReadXRegister(instr->GetRm()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003224 break;
3225 default:
3226 VIXL_UNIMPLEMENTED();
3227 }
3228 WriteRegister(reg_size, instr->GetRd(), result);
3229}
3230
3231
3232void Simulator::VisitBitfield(const Instruction* instr) {
3233 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3234 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003235 int R = instr->GetImmR();
3236 int S = instr->GetImmS();
3237 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003238 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003239 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003240 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003241 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003242 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003243 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003244 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003245 diff += reg_size;
3246 }
3247
3248 // inzero indicates if the extracted bitfield is inserted into the
3249 // destination register value or in zero.
3250 // If extend is true, extend the sign of the extracted bitfield.
3251 bool inzero = false;
3252 bool extend = false;
3253 switch (instr->Mask(BitfieldMask)) {
3254 case BFM_x:
3255 case BFM_w:
3256 break;
3257 case SBFM_x:
3258 case SBFM_w:
3259 inzero = true;
3260 extend = true;
3261 break;
3262 case UBFM_x:
3263 case UBFM_w:
3264 inzero = true;
3265 break;
3266 default:
3267 VIXL_UNIMPLEMENTED();
3268 }
3269
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003270 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
3271 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003272 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003273 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003274 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003275 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
3276 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003277
3278 // Merge sign extension, dest/zero and bitfield.
3279 result = signbits | (result & mask) | (dst & ~mask);
3280
3281 WriteRegister(reg_size, instr->GetRd(), result);
3282}
3283
3284
3285void Simulator::VisitExtract(const Instruction* instr) {
3286 unsigned lsb = instr->GetImmS();
3287 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3288 uint64_t low_res =
3289 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003290 uint64_t high_res =
3291 (lsb == 0) ? 0 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
3292 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003293 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
3294}
3295
3296
3297void Simulator::VisitFPImmediate(const Instruction* instr) {
3298 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01003299 unsigned dest = instr->GetRd();
3300 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003301 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01003302 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01003303 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003304 case FMOV_s_imm:
3305 WriteSRegister(dest, instr->GetImmFP32());
3306 break;
3307 case FMOV_d_imm:
3308 WriteDRegister(dest, instr->GetImmFP64());
3309 break;
3310 default:
3311 VIXL_UNREACHABLE();
3312 }
3313}
3314
3315
3316void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
3317 AssertSupportedFPCR();
3318
3319 unsigned dst = instr->GetRd();
3320 unsigned src = instr->GetRn();
3321
3322 FPRounding round = ReadRMode();
3323
3324 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003325 case FCVTAS_wh:
3326 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
3327 break;
3328 case FCVTAS_xh:
3329 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
3330 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003331 case FCVTAS_ws:
3332 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
3333 break;
3334 case FCVTAS_xs:
3335 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
3336 break;
3337 case FCVTAS_wd:
3338 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
3339 break;
3340 case FCVTAS_xd:
3341 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
3342 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003343 case FCVTAU_wh:
3344 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
3345 break;
3346 case FCVTAU_xh:
3347 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
3348 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003349 case FCVTAU_ws:
3350 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3351 break;
3352 case FCVTAU_xs:
3353 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3354 break;
3355 case FCVTAU_wd:
3356 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3357 break;
3358 case FCVTAU_xd:
3359 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3360 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003361 case FCVTMS_wh:
3362 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3363 break;
3364 case FCVTMS_xh:
3365 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3366 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003367 case FCVTMS_ws:
3368 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3369 break;
3370 case FCVTMS_xs:
3371 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3372 break;
3373 case FCVTMS_wd:
3374 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3375 break;
3376 case FCVTMS_xd:
3377 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3378 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003379 case FCVTMU_wh:
3380 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3381 break;
3382 case FCVTMU_xh:
3383 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3384 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003385 case FCVTMU_ws:
3386 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3387 break;
3388 case FCVTMU_xs:
3389 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3390 break;
3391 case FCVTMU_wd:
3392 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3393 break;
3394 case FCVTMU_xd:
3395 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3396 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003397 case FCVTPS_wh:
3398 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3399 break;
3400 case FCVTPS_xh:
3401 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3402 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003403 case FCVTPS_ws:
3404 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3405 break;
3406 case FCVTPS_xs:
3407 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3408 break;
3409 case FCVTPS_wd:
3410 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3411 break;
3412 case FCVTPS_xd:
3413 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3414 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003415 case FCVTPU_wh:
3416 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3417 break;
3418 case FCVTPU_xh:
3419 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3420 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003421 case FCVTPU_ws:
3422 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3423 break;
3424 case FCVTPU_xs:
3425 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3426 break;
3427 case FCVTPU_wd:
3428 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3429 break;
3430 case FCVTPU_xd:
3431 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3432 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003433 case FCVTNS_wh:
3434 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3435 break;
3436 case FCVTNS_xh:
3437 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3438 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003439 case FCVTNS_ws:
3440 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3441 break;
3442 case FCVTNS_xs:
3443 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3444 break;
3445 case FCVTNS_wd:
3446 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3447 break;
3448 case FCVTNS_xd:
3449 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3450 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003451 case FCVTNU_wh:
3452 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3453 break;
3454 case FCVTNU_xh:
3455 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3456 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003457 case FCVTNU_ws:
3458 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3459 break;
3460 case FCVTNU_xs:
3461 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3462 break;
3463 case FCVTNU_wd:
3464 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3465 break;
3466 case FCVTNU_xd:
3467 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3468 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003469 case FCVTZS_wh:
3470 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3471 break;
3472 case FCVTZS_xh:
3473 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3474 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003475 case FCVTZS_ws:
3476 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3477 break;
3478 case FCVTZS_xs:
3479 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3480 break;
3481 case FCVTZS_wd:
3482 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3483 break;
3484 case FCVTZS_xd:
3485 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3486 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003487 case FCVTZU_wh:
3488 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3489 break;
3490 case FCVTZU_xh:
3491 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3492 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003493 case FCVTZU_ws:
3494 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3495 break;
3496 case FCVTZU_xs:
3497 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3498 break;
3499 case FCVTZU_wd:
3500 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3501 break;
3502 case FCVTZU_xd:
3503 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3504 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003505 case FJCVTZS:
3506 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3507 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003508 case FMOV_hw:
3509 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3510 break;
3511 case FMOV_wh:
3512 WriteWRegister(dst, ReadHRegisterBits(src));
3513 break;
3514 case FMOV_xh:
3515 WriteXRegister(dst, ReadHRegisterBits(src));
3516 break;
3517 case FMOV_hx:
3518 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3519 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003520 case FMOV_ws:
3521 WriteWRegister(dst, ReadSRegisterBits(src));
3522 break;
3523 case FMOV_xd:
3524 WriteXRegister(dst, ReadDRegisterBits(src));
3525 break;
3526 case FMOV_sw:
3527 WriteSRegisterBits(dst, ReadWRegister(src));
3528 break;
3529 case FMOV_dx:
3530 WriteDRegisterBits(dst, ReadXRegister(src));
3531 break;
3532 case FMOV_d1_x:
3533 LogicVRegister(ReadVRegister(dst))
3534 .SetUint(kFormatD, 1, ReadXRegister(src));
3535 break;
3536 case FMOV_x_d1:
3537 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3538 break;
3539
3540 // A 32-bit input can be handled in the same way as a 64-bit input, since
3541 // the sign- or zero-extension will not affect the conversion.
3542 case SCVTF_dx:
3543 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3544 break;
3545 case SCVTF_dw:
3546 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3547 break;
3548 case UCVTF_dx:
3549 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3550 break;
3551 case UCVTF_dw: {
3552 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003553 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003554 break;
3555 }
3556 case SCVTF_sx:
3557 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3558 break;
3559 case SCVTF_sw:
3560 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3561 break;
3562 case UCVTF_sx:
3563 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3564 break;
3565 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01003566 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3567 break;
3568 }
3569 case SCVTF_hx:
3570 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3571 break;
3572 case SCVTF_hw:
3573 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3574 break;
3575 case UCVTF_hx:
3576 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3577 break;
3578 case UCVTF_hw: {
3579 WriteHRegister(dst,
3580 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003581 break;
3582 }
3583
3584 default:
3585 VIXL_UNREACHABLE();
3586 }
3587}
3588
3589
3590void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3591 AssertSupportedFPCR();
3592
3593 unsigned dst = instr->GetRd();
3594 unsigned src = instr->GetRn();
3595 int fbits = 64 - instr->GetFPScale();
3596
3597 FPRounding round = ReadRMode();
3598
3599 switch (instr->Mask(FPFixedPointConvertMask)) {
3600 // A 32-bit input can be handled in the same way as a 64-bit input, since
3601 // the sign- or zero-extension will not affect the conversion.
3602 case SCVTF_dx_fixed:
3603 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3604 break;
3605 case SCVTF_dw_fixed:
3606 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3607 break;
3608 case UCVTF_dx_fixed:
3609 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3610 break;
3611 case UCVTF_dw_fixed: {
3612 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003613 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003614 break;
3615 }
3616 case SCVTF_sx_fixed:
3617 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3618 break;
3619 case SCVTF_sw_fixed:
3620 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3621 break;
3622 case UCVTF_sx_fixed:
3623 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3624 break;
3625 case UCVTF_sw_fixed: {
3626 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003627 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3628 break;
3629 }
3630 case SCVTF_hx_fixed:
3631 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3632 break;
3633 case SCVTF_hw_fixed:
3634 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3635 break;
3636 case UCVTF_hx_fixed:
3637 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3638 break;
3639 case UCVTF_hw_fixed: {
3640 WriteHRegister(dst,
3641 UFixedToFloat16(ReadRegister<uint32_t>(src),
3642 fbits,
3643 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003644 break;
3645 }
3646 case FCVTZS_xd_fixed:
3647 WriteXRegister(dst,
3648 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3649 FPZero));
3650 break;
3651 case FCVTZS_wd_fixed:
3652 WriteWRegister(dst,
3653 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3654 FPZero));
3655 break;
3656 case FCVTZU_xd_fixed:
3657 WriteXRegister(dst,
3658 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3659 FPZero));
3660 break;
3661 case FCVTZU_wd_fixed:
3662 WriteWRegister(dst,
3663 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3664 FPZero));
3665 break;
3666 case FCVTZS_xs_fixed:
3667 WriteXRegister(dst,
3668 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3669 FPZero));
3670 break;
3671 case FCVTZS_ws_fixed:
3672 WriteWRegister(dst,
3673 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3674 FPZero));
3675 break;
3676 case FCVTZU_xs_fixed:
3677 WriteXRegister(dst,
3678 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3679 FPZero));
3680 break;
3681 case FCVTZU_ws_fixed:
3682 WriteWRegister(dst,
3683 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3684 FPZero));
3685 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003686 case FCVTZS_xh_fixed: {
3687 double output =
3688 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3689 WriteXRegister(dst, FPToInt64(output, FPZero));
3690 break;
3691 }
3692 case FCVTZS_wh_fixed: {
3693 double output =
3694 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3695 WriteWRegister(dst, FPToInt32(output, FPZero));
3696 break;
3697 }
3698 case FCVTZU_xh_fixed: {
3699 double output =
3700 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3701 WriteXRegister(dst, FPToUInt64(output, FPZero));
3702 break;
3703 }
3704 case FCVTZU_wh_fixed: {
3705 double output =
3706 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3707 WriteWRegister(dst, FPToUInt32(output, FPZero));
3708 break;
3709 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003710 default:
3711 VIXL_UNREACHABLE();
3712 }
3713}
3714
3715
3716void Simulator::VisitFPCompare(const Instruction* instr) {
3717 AssertSupportedFPCR();
3718
3719 FPTrapFlags trap = DisableTrap;
3720 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003721 case FCMPE_h:
3722 trap = EnableTrap;
3723 VIXL_FALLTHROUGH();
3724 case FCMP_h:
3725 FPCompare(ReadHRegister(instr->GetRn()),
3726 ReadHRegister(instr->GetRm()),
3727 trap);
3728 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003729 case FCMPE_s:
3730 trap = EnableTrap;
3731 VIXL_FALLTHROUGH();
3732 case FCMP_s:
3733 FPCompare(ReadSRegister(instr->GetRn()),
3734 ReadSRegister(instr->GetRm()),
3735 trap);
3736 break;
3737 case FCMPE_d:
3738 trap = EnableTrap;
3739 VIXL_FALLTHROUGH();
3740 case FCMP_d:
3741 FPCompare(ReadDRegister(instr->GetRn()),
3742 ReadDRegister(instr->GetRm()),
3743 trap);
3744 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003745 case FCMPE_h_zero:
3746 trap = EnableTrap;
3747 VIXL_FALLTHROUGH();
3748 case FCMP_h_zero:
3749 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3750 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003751 case FCMPE_s_zero:
3752 trap = EnableTrap;
3753 VIXL_FALLTHROUGH();
3754 case FCMP_s_zero:
3755 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3756 break;
3757 case FCMPE_d_zero:
3758 trap = EnableTrap;
3759 VIXL_FALLTHROUGH();
3760 case FCMP_d_zero:
3761 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
3762 break;
3763 default:
3764 VIXL_UNIMPLEMENTED();
3765 }
3766}
3767
3768
3769void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
3770 AssertSupportedFPCR();
3771
3772 FPTrapFlags trap = DisableTrap;
3773 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003774 case FCCMPE_h:
3775 trap = EnableTrap;
3776 VIXL_FALLTHROUGH();
3777 case FCCMP_h:
3778 if (ConditionPassed(instr->GetCondition())) {
3779 FPCompare(ReadHRegister(instr->GetRn()),
3780 ReadHRegister(instr->GetRm()),
3781 trap);
3782 } else {
3783 ReadNzcv().SetFlags(instr->GetNzcv());
3784 LogSystemRegister(NZCV);
3785 }
3786 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003787 case FCCMPE_s:
3788 trap = EnableTrap;
3789 VIXL_FALLTHROUGH();
3790 case FCCMP_s:
3791 if (ConditionPassed(instr->GetCondition())) {
3792 FPCompare(ReadSRegister(instr->GetRn()),
3793 ReadSRegister(instr->GetRm()),
3794 trap);
3795 } else {
3796 ReadNzcv().SetFlags(instr->GetNzcv());
3797 LogSystemRegister(NZCV);
3798 }
3799 break;
3800 case FCCMPE_d:
3801 trap = EnableTrap;
3802 VIXL_FALLTHROUGH();
3803 case FCCMP_d:
3804 if (ConditionPassed(instr->GetCondition())) {
3805 FPCompare(ReadDRegister(instr->GetRn()),
3806 ReadDRegister(instr->GetRm()),
3807 trap);
3808 } else {
3809 ReadNzcv().SetFlags(instr->GetNzcv());
3810 LogSystemRegister(NZCV);
3811 }
3812 break;
3813 default:
3814 VIXL_UNIMPLEMENTED();
3815 }
3816}
3817
3818
3819void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
3820 AssertSupportedFPCR();
3821
3822 Instr selected;
3823 if (ConditionPassed(instr->GetCondition())) {
3824 selected = instr->GetRn();
3825 } else {
3826 selected = instr->GetRm();
3827 }
3828
3829 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003830 case FCSEL_h:
3831 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
3832 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003833 case FCSEL_s:
3834 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
3835 break;
3836 case FCSEL_d:
3837 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
3838 break;
3839 default:
3840 VIXL_UNIMPLEMENTED();
3841 }
3842}
3843
3844
3845void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
3846 AssertSupportedFPCR();
3847
3848 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01003849 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01003850 switch (instr->Mask(FPTypeMask)) {
3851 default:
3852 VIXL_UNREACHABLE_OR_FALLTHROUGH();
3853 case FP64:
3854 vform = kFormatD;
3855 break;
3856 case FP32:
3857 vform = kFormatS;
3858 break;
3859 case FP16:
3860 vform = kFormatH;
3861 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003862 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003863
Alexandre Ramesd3832962016-07-04 15:03:43 +01003864 SimVRegister& rd = ReadVRegister(instr->GetRd());
3865 SimVRegister& rn = ReadVRegister(instr->GetRn());
3866 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07003867 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003868
3869 unsigned fd = instr->GetRd();
3870 unsigned fn = instr->GetRn();
3871
3872 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003873 case FMOV_h:
3874 WriteHRegister(fd, ReadHRegister(fn));
3875 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003876 case FMOV_s:
3877 WriteSRegister(fd, ReadSRegister(fn));
3878 return;
3879 case FMOV_d:
3880 WriteDRegister(fd, ReadDRegister(fn));
3881 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003882 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003883 case FABS_s:
3884 case FABS_d:
3885 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
3886 // Explicitly log the register update whilst we have type information.
3887 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3888 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003889 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003890 case FNEG_s:
3891 case FNEG_d:
3892 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
3893 // Explicitly log the register update whilst we have type information.
3894 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3895 return;
3896 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01003897 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003898 return;
3899 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01003900 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003901 return;
3902 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01003903 WriteHRegister(fd,
3904 Float16ToRawbits(
3905 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003906 return;
3907 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01003908 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003909 return;
3910 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01003911 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003912 return;
3913 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01003914 WriteHRegister(fd,
3915 Float16ToRawbits(
3916 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003917 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003918 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003919 case FSQRT_s:
3920 case FSQRT_d:
3921 fsqrt(vform, rd, rn);
3922 // Explicitly log the register update whilst we have type information.
3923 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3924 return;
TatWai Chong04471812019-03-19 14:29:00 -07003925 case FRINT32X_s:
3926 case FRINT32X_d:
3927 inexact_exception = true;
3928 frint_mode = kFrintToInt32;
3929 break; // Use FPCR rounding mode.
3930 case FRINT64X_s:
3931 case FRINT64X_d:
3932 inexact_exception = true;
3933 frint_mode = kFrintToInt64;
3934 break; // Use FPCR rounding mode.
3935 case FRINT32Z_s:
3936 case FRINT32Z_d:
3937 inexact_exception = true;
3938 frint_mode = kFrintToInt32;
3939 fpcr_rounding = FPZero;
3940 break;
3941 case FRINT64Z_s:
3942 case FRINT64Z_d:
3943 inexact_exception = true;
3944 frint_mode = kFrintToInt64;
3945 fpcr_rounding = FPZero;
3946 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003947 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003948 case FRINTI_s:
3949 case FRINTI_d:
3950 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01003951 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003952 case FRINTX_s:
3953 case FRINTX_d:
3954 inexact_exception = true;
3955 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003956 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003957 case FRINTA_s:
3958 case FRINTA_d:
3959 fpcr_rounding = FPTieAway;
3960 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003961 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003962 case FRINTM_s:
3963 case FRINTM_d:
3964 fpcr_rounding = FPNegativeInfinity;
3965 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003966 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003967 case FRINTN_s:
3968 case FRINTN_d:
3969 fpcr_rounding = FPTieEven;
3970 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003971 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003972 case FRINTP_s:
3973 case FRINTP_d:
3974 fpcr_rounding = FPPositiveInfinity;
3975 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003976 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003977 case FRINTZ_s:
3978 case FRINTZ_d:
3979 fpcr_rounding = FPZero;
3980 break;
3981 default:
3982 VIXL_UNIMPLEMENTED();
3983 }
3984
3985 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07003986 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003987 // Explicitly log the register update whilst we have type information.
3988 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3989}
3990
3991
3992void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
3993 AssertSupportedFPCR();
3994
Carey Williamsd8bb3572018-04-10 11:58:07 +01003995 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01003996 switch (instr->Mask(FPTypeMask)) {
3997 default:
3998 VIXL_UNREACHABLE_OR_FALLTHROUGH();
3999 case FP64:
4000 vform = kFormatD;
4001 break;
4002 case FP32:
4003 vform = kFormatS;
4004 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004005 case FP16:
4006 vform = kFormatH;
4007 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01004008 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004009 SimVRegister& rd = ReadVRegister(instr->GetRd());
4010 SimVRegister& rn = ReadVRegister(instr->GetRn());
4011 SimVRegister& rm = ReadVRegister(instr->GetRm());
4012
4013 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01004014 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004015 case FADD_s:
4016 case FADD_d:
4017 fadd(vform, rd, rn, rm);
4018 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004019 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004020 case FSUB_s:
4021 case FSUB_d:
4022 fsub(vform, rd, rn, rm);
4023 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004024 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004025 case FMUL_s:
4026 case FMUL_d:
4027 fmul(vform, rd, rn, rm);
4028 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004029 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004030 case FNMUL_s:
4031 case FNMUL_d:
4032 fnmul(vform, rd, rn, rm);
4033 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004034 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004035 case FDIV_s:
4036 case FDIV_d:
4037 fdiv(vform, rd, rn, rm);
4038 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004039 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004040 case FMAX_s:
4041 case FMAX_d:
4042 fmax(vform, rd, rn, rm);
4043 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004044 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004045 case FMIN_s:
4046 case FMIN_d:
4047 fmin(vform, rd, rn, rm);
4048 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004049 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004050 case FMAXNM_s:
4051 case FMAXNM_d:
4052 fmaxnm(vform, rd, rn, rm);
4053 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01004054 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004055 case FMINNM_s:
4056 case FMINNM_d:
4057 fminnm(vform, rd, rn, rm);
4058 break;
4059 default:
4060 VIXL_UNREACHABLE();
4061 }
4062 // Explicitly log the register update whilst we have type information.
4063 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
4064}
4065
4066
4067void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
4068 AssertSupportedFPCR();
4069
4070 unsigned fd = instr->GetRd();
4071 unsigned fn = instr->GetRn();
4072 unsigned fm = instr->GetRm();
4073 unsigned fa = instr->GetRa();
4074
4075 switch (instr->Mask(FPDataProcessing3SourceMask)) {
4076 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01004077 case FMADD_h:
4078 WriteHRegister(fd,
4079 FPMulAdd(ReadHRegister(fa),
4080 ReadHRegister(fn),
4081 ReadHRegister(fm)));
4082 break;
4083 case FMSUB_h:
4084 WriteHRegister(fd,
4085 FPMulAdd(ReadHRegister(fa),
4086 -ReadHRegister(fn),
4087 ReadHRegister(fm)));
4088 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004089 case FMADD_s:
4090 WriteSRegister(fd,
4091 FPMulAdd(ReadSRegister(fa),
4092 ReadSRegister(fn),
4093 ReadSRegister(fm)));
4094 break;
4095 case FMSUB_s:
4096 WriteSRegister(fd,
4097 FPMulAdd(ReadSRegister(fa),
4098 -ReadSRegister(fn),
4099 ReadSRegister(fm)));
4100 break;
4101 case FMADD_d:
4102 WriteDRegister(fd,
4103 FPMulAdd(ReadDRegister(fa),
4104 ReadDRegister(fn),
4105 ReadDRegister(fm)));
4106 break;
4107 case FMSUB_d:
4108 WriteDRegister(fd,
4109 FPMulAdd(ReadDRegister(fa),
4110 -ReadDRegister(fn),
4111 ReadDRegister(fm)));
4112 break;
4113 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01004114 case FNMADD_h:
4115 WriteHRegister(fd,
4116 FPMulAdd(-ReadHRegister(fa),
4117 -ReadHRegister(fn),
4118 ReadHRegister(fm)));
4119 break;
4120 case FNMSUB_h:
4121 WriteHRegister(fd,
4122 FPMulAdd(-ReadHRegister(fa),
4123 ReadHRegister(fn),
4124 ReadHRegister(fm)));
4125 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004126 case FNMADD_s:
4127 WriteSRegister(fd,
4128 FPMulAdd(-ReadSRegister(fa),
4129 -ReadSRegister(fn),
4130 ReadSRegister(fm)));
4131 break;
4132 case FNMSUB_s:
4133 WriteSRegister(fd,
4134 FPMulAdd(-ReadSRegister(fa),
4135 ReadSRegister(fn),
4136 ReadSRegister(fm)));
4137 break;
4138 case FNMADD_d:
4139 WriteDRegister(fd,
4140 FPMulAdd(-ReadDRegister(fa),
4141 -ReadDRegister(fn),
4142 ReadDRegister(fm)));
4143 break;
4144 case FNMSUB_d:
4145 WriteDRegister(fd,
4146 FPMulAdd(-ReadDRegister(fa),
4147 ReadDRegister(fn),
4148 ReadDRegister(fm)));
4149 break;
4150 default:
4151 VIXL_UNIMPLEMENTED();
4152 }
4153}
4154
4155
4156bool Simulator::FPProcessNaNs(const Instruction* instr) {
4157 unsigned fd = instr->GetRd();
4158 unsigned fn = instr->GetRn();
4159 unsigned fm = instr->GetRm();
4160 bool done = false;
4161
4162 if (instr->Mask(FP64) == FP64) {
4163 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004164 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004165 WriteDRegister(fd, result);
4166 done = true;
4167 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004168 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004169 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004170 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004171 WriteSRegister(fd, result);
4172 done = true;
4173 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004174 } else {
4175 VIXL_ASSERT(instr->Mask(FP16) == FP16);
4176 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01004177 }
4178
4179 return done;
4180}
4181
4182
4183void Simulator::SysOp_W(int op, int64_t val) {
4184 switch (op) {
4185 case IVAU:
4186 case CVAC:
4187 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01004188 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08004189 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004190 case CIVAC: {
4191 // Perform a dummy memory access to ensure that we have read access
4192 // to the specified address.
4193 volatile uint8_t y = Memory::Read<uint8_t>(val);
4194 USE(y);
4195 // TODO: Implement "case ZVA:".
4196 break;
4197 }
4198 default:
4199 VIXL_UNIMPLEMENTED();
4200 }
4201}
4202
4203
Jacob Bramleyca789742018-09-13 14:25:46 +01004204// clang-format off
4205#define PAUTH_SYSTEM_MODES(V) \
4206 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
4207 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
4208 V(AZ, 30, 0x00000000, kPACKeyIA) \
4209 V(BZ, 30, 0x00000000, kPACKeyIB) \
4210 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
4211 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
4212// clang-format on
4213
4214
Alexandre Ramesd3832962016-07-04 15:03:43 +01004215void Simulator::VisitSystem(const Instruction* instr) {
4216 // Some system instructions hijack their Op and Cp fields to represent a
4217 // range of immediates instead of indicating a different instruction. This
4218 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01004219 if (instr->GetInstructionBits() == XPACLRI) {
4220 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00004221 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
4222 switch (instr->Mask(SystemPStateMask)) {
4223 case CFINV:
4224 ReadNzcv().SetC(!ReadC());
4225 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00004226 case AXFLAG:
4227 ReadNzcv().SetN(0);
4228 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
4229 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
4230 ReadNzcv().SetV(0);
4231 break;
4232 case XAFLAG: {
4233 // Can't set the flags in place due to the logical dependencies.
4234 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
4235 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
4236 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
4237 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
4238 ReadNzcv().SetN(n);
4239 ReadNzcv().SetZ(z);
4240 ReadNzcv().SetC(c);
4241 ReadNzcv().SetV(v);
4242 break;
4243 }
Alexander Gilday2487f142018-11-05 13:07:27 +00004244 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004245 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004246 // Check BType allows PACI[AB]SP instructions.
4247 if (PcIsInGuardedPage()) {
4248 Instr i = instr->Mask(SystemPAuthMask);
4249 if ((i == PACIASP) || (i == PACIBSP)) {
4250 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004251 case BranchFromGuardedNotToIP:
4252 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
4253 // assume here to be zero. This allows execution of PACI[AB]SP when
4254 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00004255 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004256 case BranchFromUnguardedOrToIP:
4257 case BranchAndLink:
4258 break;
4259 }
4260 }
4261 }
4262
Jacob Bramleyca789742018-09-13 14:25:46 +01004263 switch (instr->Mask(SystemPAuthMask)) {
4264#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
4265 case PACI##SUFFIX: \
4266 WriteXRegister(DST, \
4267 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
4268 break; \
4269 case AUTI##SUFFIX: \
4270 WriteXRegister(DST, \
4271 AuthPAC(ReadXRegister(DST), \
4272 MOD, \
4273 KEY, \
4274 kInstructionPointer)); \
4275 break;
4276
4277 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
4278#undef DEFINE_PAUTH_FUNCS
4279 }
4280 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
4281 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004282 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
4283 switch (instr->Mask(SystemExclusiveMonitorMask)) {
4284 case CLREX: {
4285 PrintExclusiveAccessWarning();
4286 ClearLocalMonitor();
4287 break;
4288 }
4289 }
4290 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
4291 switch (instr->Mask(SystemSysRegMask)) {
4292 case MRS: {
4293 switch (instr->GetImmSystemRegister()) {
4294 case NZCV:
4295 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
4296 break;
4297 case FPCR:
4298 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
4299 break;
TatWai Chong04edf682018-12-27 16:01:02 -08004300 case RNDR:
4301 case RNDRRS: {
4302 uint64_t high = jrand48(rndr_state_);
4303 uint64_t low = jrand48(rndr_state_);
4304 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
4305 WriteXRegister(instr->GetRt(), rand_num);
4306 // Simulate successful random number generation.
4307 // TODO: Return failure occasionally as a random number cannot be
4308 // returned in a period of time.
4309 ReadNzcv().SetRawValue(NoFlag);
4310 LogSystemRegister(NZCV);
4311 break;
4312 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004313 default:
4314 VIXL_UNIMPLEMENTED();
4315 }
4316 break;
4317 }
4318 case MSR: {
4319 switch (instr->GetImmSystemRegister()) {
4320 case NZCV:
4321 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
4322 LogSystemRegister(NZCV);
4323 break;
4324 case FPCR:
4325 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
4326 LogSystemRegister(FPCR);
4327 break;
4328 default:
4329 VIXL_UNIMPLEMENTED();
4330 }
4331 break;
4332 }
4333 }
4334 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
4335 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
4336 switch (instr->GetImmHint()) {
4337 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01004338 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00004339 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004340 case BTI_jc:
4341 break;
4342 case BTI:
4343 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
4344 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
4345 }
4346 break;
4347 case BTI_c:
4348 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
4349 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
4350 }
4351 break;
4352 case BTI_j:
4353 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4354 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4355 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004356 break;
4357 default:
4358 VIXL_UNIMPLEMENTED();
4359 }
4360 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4361 __sync_synchronize();
4362 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4363 switch (instr->Mask(SystemSysMask)) {
4364 case SYS:
4365 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4366 break;
4367 default:
4368 VIXL_UNIMPLEMENTED();
4369 }
4370 } else {
4371 VIXL_UNIMPLEMENTED();
4372 }
4373}
4374
4375
4376void Simulator::VisitException(const Instruction* instr) {
4377 switch (instr->Mask(ExceptionMask)) {
4378 case HLT:
4379 switch (instr->GetImmException()) {
4380 case kUnreachableOpcode:
4381 DoUnreachable(instr);
4382 return;
4383 case kTraceOpcode:
4384 DoTrace(instr);
4385 return;
4386 case kLogOpcode:
4387 DoLog(instr);
4388 return;
4389 case kPrintfOpcode:
4390 DoPrintf(instr);
4391 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01004392 case kRuntimeCallOpcode:
4393 DoRuntimeCall(instr);
4394 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01004395 case kSetCPUFeaturesOpcode:
4396 case kEnableCPUFeaturesOpcode:
4397 case kDisableCPUFeaturesOpcode:
4398 DoConfigureCPUFeatures(instr);
4399 return;
4400 case kSaveCPUFeaturesOpcode:
4401 DoSaveCPUFeatures(instr);
4402 return;
4403 case kRestoreCPUFeaturesOpcode:
4404 DoRestoreCPUFeatures(instr);
4405 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004406 default:
4407 HostBreakpoint();
4408 return;
4409 }
4410 case BRK:
4411 HostBreakpoint();
4412 return;
4413 default:
4414 VIXL_UNIMPLEMENTED();
4415 }
4416}
4417
4418
4419void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4420 VisitUnimplemented(instr);
4421}
4422
4423
4424void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4425 VisitUnimplemented(instr);
4426}
4427
4428
4429void Simulator::VisitCryptoAES(const Instruction* instr) {
4430 VisitUnimplemented(instr);
4431}
4432
4433
4434void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4435 NEONFormatDecoder nfd(instr);
4436 VectorFormat vf = nfd.GetVectorFormat();
4437
4438 static const NEONFormatMap map_lp =
4439 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4440 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4441
4442 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4443 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4444
4445 static const NEONFormatMap map_fcvtn = {{22, 30},
4446 {NF_4H, NF_8H, NF_2S, NF_4S}};
4447 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4448
4449 SimVRegister& rd = ReadVRegister(instr->GetRd());
4450 SimVRegister& rn = ReadVRegister(instr->GetRn());
4451
4452 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4453 // These instructions all use a two bit size field, except NOT and RBIT,
4454 // which use the field to encode the operation.
4455 switch (instr->Mask(NEON2RegMiscMask)) {
4456 case NEON_REV64:
4457 rev64(vf, rd, rn);
4458 break;
4459 case NEON_REV32:
4460 rev32(vf, rd, rn);
4461 break;
4462 case NEON_REV16:
4463 rev16(vf, rd, rn);
4464 break;
4465 case NEON_SUQADD:
4466 suqadd(vf, rd, rn);
4467 break;
4468 case NEON_USQADD:
4469 usqadd(vf, rd, rn);
4470 break;
4471 case NEON_CLS:
4472 cls(vf, rd, rn);
4473 break;
4474 case NEON_CLZ:
4475 clz(vf, rd, rn);
4476 break;
4477 case NEON_CNT:
4478 cnt(vf, rd, rn);
4479 break;
4480 case NEON_SQABS:
4481 abs(vf, rd, rn).SignedSaturate(vf);
4482 break;
4483 case NEON_SQNEG:
4484 neg(vf, rd, rn).SignedSaturate(vf);
4485 break;
4486 case NEON_CMGT_zero:
4487 cmp(vf, rd, rn, 0, gt);
4488 break;
4489 case NEON_CMGE_zero:
4490 cmp(vf, rd, rn, 0, ge);
4491 break;
4492 case NEON_CMEQ_zero:
4493 cmp(vf, rd, rn, 0, eq);
4494 break;
4495 case NEON_CMLE_zero:
4496 cmp(vf, rd, rn, 0, le);
4497 break;
4498 case NEON_CMLT_zero:
4499 cmp(vf, rd, rn, 0, lt);
4500 break;
4501 case NEON_ABS:
4502 abs(vf, rd, rn);
4503 break;
4504 case NEON_NEG:
4505 neg(vf, rd, rn);
4506 break;
4507 case NEON_SADDLP:
4508 saddlp(vf_lp, rd, rn);
4509 break;
4510 case NEON_UADDLP:
4511 uaddlp(vf_lp, rd, rn);
4512 break;
4513 case NEON_SADALP:
4514 sadalp(vf_lp, rd, rn);
4515 break;
4516 case NEON_UADALP:
4517 uadalp(vf_lp, rd, rn);
4518 break;
4519 case NEON_RBIT_NOT:
4520 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4521 switch (instr->GetFPType()) {
4522 case 0:
4523 not_(vf, rd, rn);
4524 break;
4525 case 1:
4526 rbit(vf, rd, rn);
4527 break;
4528 default:
4529 VIXL_UNIMPLEMENTED();
4530 }
4531 break;
4532 }
4533 } else {
4534 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4535 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4536 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004537 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004538
4539 // These instructions all use a one bit size field, except XTN, SQXTUN,
4540 // SHLL, SQXTN and UQXTN, which use a two bit size field.
4541 switch (instr->Mask(NEON2RegMiscFPMask)) {
4542 case NEON_FABS:
4543 fabs_(fpf, rd, rn);
4544 return;
4545 case NEON_FNEG:
4546 fneg(fpf, rd, rn);
4547 return;
4548 case NEON_FSQRT:
4549 fsqrt(fpf, rd, rn);
4550 return;
4551 case NEON_FCVTL:
4552 if (instr->Mask(NEON_Q)) {
4553 fcvtl2(vf_fcvtl, rd, rn);
4554 } else {
4555 fcvtl(vf_fcvtl, rd, rn);
4556 }
4557 return;
4558 case NEON_FCVTN:
4559 if (instr->Mask(NEON_Q)) {
4560 fcvtn2(vf_fcvtn, rd, rn);
4561 } else {
4562 fcvtn(vf_fcvtn, rd, rn);
4563 }
4564 return;
4565 case NEON_FCVTXN:
4566 if (instr->Mask(NEON_Q)) {
4567 fcvtxn2(vf_fcvtn, rd, rn);
4568 } else {
4569 fcvtxn(vf_fcvtn, rd, rn);
4570 }
4571 return;
4572
4573 // The following instructions break from the switch statement, rather
4574 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07004575 case NEON_FRINT32X:
4576 inexact_exception = true;
4577 frint_mode = kFrintToInt32;
4578 break; // Use FPCR rounding mode.
4579 case NEON_FRINT32Z:
4580 inexact_exception = true;
4581 frint_mode = kFrintToInt32;
4582 fpcr_rounding = FPZero;
4583 break;
4584 case NEON_FRINT64X:
4585 inexact_exception = true;
4586 frint_mode = kFrintToInt64;
4587 break; // Use FPCR rounding mode.
4588 case NEON_FRINT64Z:
4589 inexact_exception = true;
4590 frint_mode = kFrintToInt64;
4591 fpcr_rounding = FPZero;
4592 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004593 case NEON_FRINTI:
4594 break; // Use FPCR rounding mode.
4595 case NEON_FRINTX:
4596 inexact_exception = true;
4597 break;
4598 case NEON_FRINTA:
4599 fpcr_rounding = FPTieAway;
4600 break;
4601 case NEON_FRINTM:
4602 fpcr_rounding = FPNegativeInfinity;
4603 break;
4604 case NEON_FRINTN:
4605 fpcr_rounding = FPTieEven;
4606 break;
4607 case NEON_FRINTP:
4608 fpcr_rounding = FPPositiveInfinity;
4609 break;
4610 case NEON_FRINTZ:
4611 fpcr_rounding = FPZero;
4612 break;
4613
4614 case NEON_FCVTNS:
4615 fcvts(fpf, rd, rn, FPTieEven);
4616 return;
4617 case NEON_FCVTNU:
4618 fcvtu(fpf, rd, rn, FPTieEven);
4619 return;
4620 case NEON_FCVTPS:
4621 fcvts(fpf, rd, rn, FPPositiveInfinity);
4622 return;
4623 case NEON_FCVTPU:
4624 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4625 return;
4626 case NEON_FCVTMS:
4627 fcvts(fpf, rd, rn, FPNegativeInfinity);
4628 return;
4629 case NEON_FCVTMU:
4630 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4631 return;
4632 case NEON_FCVTZS:
4633 fcvts(fpf, rd, rn, FPZero);
4634 return;
4635 case NEON_FCVTZU:
4636 fcvtu(fpf, rd, rn, FPZero);
4637 return;
4638 case NEON_FCVTAS:
4639 fcvts(fpf, rd, rn, FPTieAway);
4640 return;
4641 case NEON_FCVTAU:
4642 fcvtu(fpf, rd, rn, FPTieAway);
4643 return;
4644 case NEON_SCVTF:
4645 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4646 return;
4647 case NEON_UCVTF:
4648 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4649 return;
4650 case NEON_URSQRTE:
4651 ursqrte(fpf, rd, rn);
4652 return;
4653 case NEON_URECPE:
4654 urecpe(fpf, rd, rn);
4655 return;
4656 case NEON_FRSQRTE:
4657 frsqrte(fpf, rd, rn);
4658 return;
4659 case NEON_FRECPE:
4660 frecpe(fpf, rd, rn, fpcr_rounding);
4661 return;
4662 case NEON_FCMGT_zero:
4663 fcmp_zero(fpf, rd, rn, gt);
4664 return;
4665 case NEON_FCMGE_zero:
4666 fcmp_zero(fpf, rd, rn, ge);
4667 return;
4668 case NEON_FCMEQ_zero:
4669 fcmp_zero(fpf, rd, rn, eq);
4670 return;
4671 case NEON_FCMLE_zero:
4672 fcmp_zero(fpf, rd, rn, le);
4673 return;
4674 case NEON_FCMLT_zero:
4675 fcmp_zero(fpf, rd, rn, lt);
4676 return;
4677 default:
4678 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4679 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4680 switch (instr->Mask(NEON2RegMiscMask)) {
4681 case NEON_XTN:
4682 xtn(vf, rd, rn);
4683 return;
4684 case NEON_SQXTN:
4685 sqxtn(vf, rd, rn);
4686 return;
4687 case NEON_UQXTN:
4688 uqxtn(vf, rd, rn);
4689 return;
4690 case NEON_SQXTUN:
4691 sqxtun(vf, rd, rn);
4692 return;
4693 case NEON_SHLL:
4694 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4695 if (instr->Mask(NEON_Q)) {
4696 shll2(vf, rd, rn);
4697 } else {
4698 shll(vf, rd, rn);
4699 }
4700 return;
4701 default:
4702 VIXL_UNIMPLEMENTED();
4703 }
4704 } else {
4705 VIXL_UNIMPLEMENTED();
4706 }
4707 }
4708
4709 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004710 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004711 }
4712}
4713
4714
Jacob Bramleyca789742018-09-13 14:25:46 +01004715void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4716 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4717 NEONFormatDecoder nfd(instr);
4718 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4719
4720 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4721
4722 SimVRegister& rd = ReadVRegister(instr->GetRd());
4723 SimVRegister& rn = ReadVRegister(instr->GetRn());
4724
4725 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4726 case NEON_SCVTF_H:
4727 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4728 return;
4729 case NEON_UCVTF_H:
4730 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4731 return;
4732 case NEON_FCVTNS_H:
4733 fcvts(fpf, rd, rn, FPTieEven);
4734 return;
4735 case NEON_FCVTNU_H:
4736 fcvtu(fpf, rd, rn, FPTieEven);
4737 return;
4738 case NEON_FCVTPS_H:
4739 fcvts(fpf, rd, rn, FPPositiveInfinity);
4740 return;
4741 case NEON_FCVTPU_H:
4742 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4743 return;
4744 case NEON_FCVTMS_H:
4745 fcvts(fpf, rd, rn, FPNegativeInfinity);
4746 return;
4747 case NEON_FCVTMU_H:
4748 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4749 return;
4750 case NEON_FCVTZS_H:
4751 fcvts(fpf, rd, rn, FPZero);
4752 return;
4753 case NEON_FCVTZU_H:
4754 fcvtu(fpf, rd, rn, FPZero);
4755 return;
4756 case NEON_FCVTAS_H:
4757 fcvts(fpf, rd, rn, FPTieAway);
4758 return;
4759 case NEON_FCVTAU_H:
4760 fcvtu(fpf, rd, rn, FPTieAway);
4761 return;
4762 case NEON_FRINTI_H:
4763 frint(fpf, rd, rn, fpcr_rounding, false);
4764 return;
4765 case NEON_FRINTX_H:
4766 frint(fpf, rd, rn, fpcr_rounding, true);
4767 return;
4768 case NEON_FRINTA_H:
4769 frint(fpf, rd, rn, FPTieAway, false);
4770 return;
4771 case NEON_FRINTM_H:
4772 frint(fpf, rd, rn, FPNegativeInfinity, false);
4773 return;
4774 case NEON_FRINTN_H:
4775 frint(fpf, rd, rn, FPTieEven, false);
4776 return;
4777 case NEON_FRINTP_H:
4778 frint(fpf, rd, rn, FPPositiveInfinity, false);
4779 return;
4780 case NEON_FRINTZ_H:
4781 frint(fpf, rd, rn, FPZero, false);
4782 return;
4783 case NEON_FABS_H:
4784 fabs_(fpf, rd, rn);
4785 return;
4786 case NEON_FNEG_H:
4787 fneg(fpf, rd, rn);
4788 return;
4789 case NEON_FSQRT_H:
4790 fsqrt(fpf, rd, rn);
4791 return;
4792 case NEON_FRSQRTE_H:
4793 frsqrte(fpf, rd, rn);
4794 return;
4795 case NEON_FRECPE_H:
4796 frecpe(fpf, rd, rn, fpcr_rounding);
4797 return;
4798 case NEON_FCMGT_H_zero:
4799 fcmp_zero(fpf, rd, rn, gt);
4800 return;
4801 case NEON_FCMGE_H_zero:
4802 fcmp_zero(fpf, rd, rn, ge);
4803 return;
4804 case NEON_FCMEQ_H_zero:
4805 fcmp_zero(fpf, rd, rn, eq);
4806 return;
4807 case NEON_FCMLE_H_zero:
4808 fcmp_zero(fpf, rd, rn, le);
4809 return;
4810 case NEON_FCMLT_H_zero:
4811 fcmp_zero(fpf, rd, rn, lt);
4812 return;
4813 default:
4814 VIXL_UNIMPLEMENTED();
4815 return;
4816 }
4817}
4818
4819
Alexandre Ramesd3832962016-07-04 15:03:43 +01004820void Simulator::VisitNEON3Same(const Instruction* instr) {
4821 NEONFormatDecoder nfd(instr);
4822 SimVRegister& rd = ReadVRegister(instr->GetRd());
4823 SimVRegister& rn = ReadVRegister(instr->GetRn());
4824 SimVRegister& rm = ReadVRegister(instr->GetRm());
4825
4826 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
4827 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4828 switch (instr->Mask(NEON3SameLogicalMask)) {
4829 case NEON_AND:
4830 and_(vf, rd, rn, rm);
4831 break;
4832 case NEON_ORR:
4833 orr(vf, rd, rn, rm);
4834 break;
4835 case NEON_ORN:
4836 orn(vf, rd, rn, rm);
4837 break;
4838 case NEON_EOR:
4839 eor(vf, rd, rn, rm);
4840 break;
4841 case NEON_BIC:
4842 bic(vf, rd, rn, rm);
4843 break;
4844 case NEON_BIF:
4845 bif(vf, rd, rn, rm);
4846 break;
4847 case NEON_BIT:
4848 bit(vf, rd, rn, rm);
4849 break;
4850 case NEON_BSL:
4851 bsl(vf, rd, rn, rm);
4852 break;
4853 default:
4854 VIXL_UNIMPLEMENTED();
4855 }
4856 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
4857 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4858 switch (instr->Mask(NEON3SameFPMask)) {
4859 case NEON_FADD:
4860 fadd(vf, rd, rn, rm);
4861 break;
4862 case NEON_FSUB:
4863 fsub(vf, rd, rn, rm);
4864 break;
4865 case NEON_FMUL:
4866 fmul(vf, rd, rn, rm);
4867 break;
4868 case NEON_FDIV:
4869 fdiv(vf, rd, rn, rm);
4870 break;
4871 case NEON_FMAX:
4872 fmax(vf, rd, rn, rm);
4873 break;
4874 case NEON_FMIN:
4875 fmin(vf, rd, rn, rm);
4876 break;
4877 case NEON_FMAXNM:
4878 fmaxnm(vf, rd, rn, rm);
4879 break;
4880 case NEON_FMINNM:
4881 fminnm(vf, rd, rn, rm);
4882 break;
4883 case NEON_FMLA:
4884 fmla(vf, rd, rn, rm);
4885 break;
4886 case NEON_FMLS:
4887 fmls(vf, rd, rn, rm);
4888 break;
4889 case NEON_FMULX:
4890 fmulx(vf, rd, rn, rm);
4891 break;
4892 case NEON_FACGE:
4893 fabscmp(vf, rd, rn, rm, ge);
4894 break;
4895 case NEON_FACGT:
4896 fabscmp(vf, rd, rn, rm, gt);
4897 break;
4898 case NEON_FCMEQ:
4899 fcmp(vf, rd, rn, rm, eq);
4900 break;
4901 case NEON_FCMGE:
4902 fcmp(vf, rd, rn, rm, ge);
4903 break;
4904 case NEON_FCMGT:
4905 fcmp(vf, rd, rn, rm, gt);
4906 break;
4907 case NEON_FRECPS:
4908 frecps(vf, rd, rn, rm);
4909 break;
4910 case NEON_FRSQRTS:
4911 frsqrts(vf, rd, rn, rm);
4912 break;
4913 case NEON_FABD:
4914 fabd(vf, rd, rn, rm);
4915 break;
4916 case NEON_FADDP:
4917 faddp(vf, rd, rn, rm);
4918 break;
4919 case NEON_FMAXP:
4920 fmaxp(vf, rd, rn, rm);
4921 break;
4922 case NEON_FMAXNMP:
4923 fmaxnmp(vf, rd, rn, rm);
4924 break;
4925 case NEON_FMINP:
4926 fminp(vf, rd, rn, rm);
4927 break;
4928 case NEON_FMINNMP:
4929 fminnmp(vf, rd, rn, rm);
4930 break;
4931 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01004932 // FMLAL{2} and FMLSL{2} have special-case encodings.
4933 switch (instr->Mask(NEON3SameFHMMask)) {
4934 case NEON_FMLAL:
4935 fmlal(vf, rd, rn, rm);
4936 break;
4937 case NEON_FMLAL2:
4938 fmlal2(vf, rd, rn, rm);
4939 break;
4940 case NEON_FMLSL:
4941 fmlsl(vf, rd, rn, rm);
4942 break;
4943 case NEON_FMLSL2:
4944 fmlsl2(vf, rd, rn, rm);
4945 break;
4946 default:
4947 VIXL_UNIMPLEMENTED();
4948 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004949 }
4950 } else {
4951 VectorFormat vf = nfd.GetVectorFormat();
4952 switch (instr->Mask(NEON3SameMask)) {
4953 case NEON_ADD:
4954 add(vf, rd, rn, rm);
4955 break;
4956 case NEON_ADDP:
4957 addp(vf, rd, rn, rm);
4958 break;
4959 case NEON_CMEQ:
4960 cmp(vf, rd, rn, rm, eq);
4961 break;
4962 case NEON_CMGE:
4963 cmp(vf, rd, rn, rm, ge);
4964 break;
4965 case NEON_CMGT:
4966 cmp(vf, rd, rn, rm, gt);
4967 break;
4968 case NEON_CMHI:
4969 cmp(vf, rd, rn, rm, hi);
4970 break;
4971 case NEON_CMHS:
4972 cmp(vf, rd, rn, rm, hs);
4973 break;
4974 case NEON_CMTST:
4975 cmptst(vf, rd, rn, rm);
4976 break;
4977 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01004978 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004979 break;
4980 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01004981 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004982 break;
4983 case NEON_MUL:
4984 mul(vf, rd, rn, rm);
4985 break;
4986 case NEON_PMUL:
4987 pmul(vf, rd, rn, rm);
4988 break;
4989 case NEON_SMAX:
4990 smax(vf, rd, rn, rm);
4991 break;
4992 case NEON_SMAXP:
4993 smaxp(vf, rd, rn, rm);
4994 break;
4995 case NEON_SMIN:
4996 smin(vf, rd, rn, rm);
4997 break;
4998 case NEON_SMINP:
4999 sminp(vf, rd, rn, rm);
5000 break;
5001 case NEON_SUB:
5002 sub(vf, rd, rn, rm);
5003 break;
5004 case NEON_UMAX:
5005 umax(vf, rd, rn, rm);
5006 break;
5007 case NEON_UMAXP:
5008 umaxp(vf, rd, rn, rm);
5009 break;
5010 case NEON_UMIN:
5011 umin(vf, rd, rn, rm);
5012 break;
5013 case NEON_UMINP:
5014 uminp(vf, rd, rn, rm);
5015 break;
5016 case NEON_SSHL:
5017 sshl(vf, rd, rn, rm);
5018 break;
5019 case NEON_USHL:
5020 ushl(vf, rd, rn, rm);
5021 break;
5022 case NEON_SABD:
5023 absdiff(vf, rd, rn, rm, true);
5024 break;
5025 case NEON_UABD:
5026 absdiff(vf, rd, rn, rm, false);
5027 break;
5028 case NEON_SABA:
5029 saba(vf, rd, rn, rm);
5030 break;
5031 case NEON_UABA:
5032 uaba(vf, rd, rn, rm);
5033 break;
5034 case NEON_UQADD:
5035 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5036 break;
5037 case NEON_SQADD:
5038 add(vf, rd, rn, rm).SignedSaturate(vf);
5039 break;
5040 case NEON_UQSUB:
5041 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5042 break;
5043 case NEON_SQSUB:
5044 sub(vf, rd, rn, rm).SignedSaturate(vf);
5045 break;
5046 case NEON_SQDMULH:
5047 sqdmulh(vf, rd, rn, rm);
5048 break;
5049 case NEON_SQRDMULH:
5050 sqrdmulh(vf, rd, rn, rm);
5051 break;
5052 case NEON_UQSHL:
5053 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5054 break;
5055 case NEON_SQSHL:
5056 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5057 break;
5058 case NEON_URSHL:
5059 ushl(vf, rd, rn, rm).Round(vf);
5060 break;
5061 case NEON_SRSHL:
5062 sshl(vf, rd, rn, rm).Round(vf);
5063 break;
5064 case NEON_UQRSHL:
5065 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5066 break;
5067 case NEON_SQRSHL:
5068 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5069 break;
5070 case NEON_UHADD:
5071 add(vf, rd, rn, rm).Uhalve(vf);
5072 break;
5073 case NEON_URHADD:
5074 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
5075 break;
5076 case NEON_SHADD:
5077 add(vf, rd, rn, rm).Halve(vf);
5078 break;
5079 case NEON_SRHADD:
5080 add(vf, rd, rn, rm).Halve(vf).Round(vf);
5081 break;
5082 case NEON_UHSUB:
5083 sub(vf, rd, rn, rm).Uhalve(vf);
5084 break;
5085 case NEON_SHSUB:
5086 sub(vf, rd, rn, rm).Halve(vf);
5087 break;
5088 default:
5089 VIXL_UNIMPLEMENTED();
5090 }
5091 }
5092}
5093
5094
Jacob Bramleyca789742018-09-13 14:25:46 +01005095void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
5096 NEONFormatDecoder nfd(instr);
5097 SimVRegister& rd = ReadVRegister(instr->GetRd());
5098 SimVRegister& rn = ReadVRegister(instr->GetRn());
5099 SimVRegister& rm = ReadVRegister(instr->GetRm());
5100
5101 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
5102 switch (instr->Mask(NEON3SameFP16Mask)) {
5103#define SIM_FUNC(A, B) \
5104 case NEON_##A##_H: \
5105 B(vf, rd, rn, rm); \
5106 break;
5107 SIM_FUNC(FMAXNM, fmaxnm);
5108 SIM_FUNC(FMLA, fmla);
5109 SIM_FUNC(FADD, fadd);
5110 SIM_FUNC(FMULX, fmulx);
5111 SIM_FUNC(FMAX, fmax);
5112 SIM_FUNC(FRECPS, frecps);
5113 SIM_FUNC(FMINNM, fminnm);
5114 SIM_FUNC(FMLS, fmls);
5115 SIM_FUNC(FSUB, fsub);
5116 SIM_FUNC(FMIN, fmin);
5117 SIM_FUNC(FRSQRTS, frsqrts);
5118 SIM_FUNC(FMAXNMP, fmaxnmp);
5119 SIM_FUNC(FADDP, faddp);
5120 SIM_FUNC(FMUL, fmul);
5121 SIM_FUNC(FMAXP, fmaxp);
5122 SIM_FUNC(FDIV, fdiv);
5123 SIM_FUNC(FMINNMP, fminnmp);
5124 SIM_FUNC(FABD, fabd);
5125 SIM_FUNC(FMINP, fminp);
5126#undef SIM_FUNC
5127 case NEON_FCMEQ_H:
5128 fcmp(vf, rd, rn, rm, eq);
5129 break;
5130 case NEON_FCMGE_H:
5131 fcmp(vf, rd, rn, rm, ge);
5132 break;
5133 case NEON_FACGE_H:
5134 fabscmp(vf, rd, rn, rm, ge);
5135 break;
5136 case NEON_FCMGT_H:
5137 fcmp(vf, rd, rn, rm, gt);
5138 break;
5139 case NEON_FACGT_H:
5140 fabscmp(vf, rd, rn, rm, gt);
5141 break;
5142 default:
5143 VIXL_UNIMPLEMENTED();
5144 break;
5145 }
5146}
5147
Carey Williams2809e6c2018-03-13 12:24:16 +00005148void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
5149 NEONFormatDecoder nfd(instr);
5150 SimVRegister& rd = ReadVRegister(instr->GetRd());
5151 SimVRegister& rn = ReadVRegister(instr->GetRn());
5152 SimVRegister& rm = ReadVRegister(instr->GetRm());
5153 int rot = 0;
5154 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01005155 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
5156 rot = instr->GetImmRotFcmlaVec();
5157 fcmla(vf, rd, rn, rm, rot);
5158 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
5159 rot = instr->GetImmRotFcadd();
5160 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01005161 } else {
5162 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01005163 case NEON_SDOT:
5164 sdot(vf, rd, rn, rm);
5165 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005166 case NEON_SQRDMLAH:
5167 sqrdmlah(vf, rd, rn, rm);
5168 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005169 case NEON_UDOT:
5170 udot(vf, rd, rn, rm);
5171 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005172 case NEON_SQRDMLSH:
5173 sqrdmlsh(vf, rd, rn, rm);
5174 break;
5175 default:
5176 VIXL_UNIMPLEMENTED();
5177 break;
5178 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005179 }
5180}
5181
5182
Alexandre Ramesd3832962016-07-04 15:03:43 +01005183void Simulator::VisitNEON3Different(const Instruction* instr) {
5184 NEONFormatDecoder nfd(instr);
5185 VectorFormat vf = nfd.GetVectorFormat();
5186 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5187
5188 SimVRegister& rd = ReadVRegister(instr->GetRd());
5189 SimVRegister& rn = ReadVRegister(instr->GetRn());
5190 SimVRegister& rm = ReadVRegister(instr->GetRm());
5191
5192 switch (instr->Mask(NEON3DifferentMask)) {
5193 case NEON_PMULL:
5194 pmull(vf_l, rd, rn, rm);
5195 break;
5196 case NEON_PMULL2:
5197 pmull2(vf_l, rd, rn, rm);
5198 break;
5199 case NEON_UADDL:
5200 uaddl(vf_l, rd, rn, rm);
5201 break;
5202 case NEON_UADDL2:
5203 uaddl2(vf_l, rd, rn, rm);
5204 break;
5205 case NEON_SADDL:
5206 saddl(vf_l, rd, rn, rm);
5207 break;
5208 case NEON_SADDL2:
5209 saddl2(vf_l, rd, rn, rm);
5210 break;
5211 case NEON_USUBL:
5212 usubl(vf_l, rd, rn, rm);
5213 break;
5214 case NEON_USUBL2:
5215 usubl2(vf_l, rd, rn, rm);
5216 break;
5217 case NEON_SSUBL:
5218 ssubl(vf_l, rd, rn, rm);
5219 break;
5220 case NEON_SSUBL2:
5221 ssubl2(vf_l, rd, rn, rm);
5222 break;
5223 case NEON_SABAL:
5224 sabal(vf_l, rd, rn, rm);
5225 break;
5226 case NEON_SABAL2:
5227 sabal2(vf_l, rd, rn, rm);
5228 break;
5229 case NEON_UABAL:
5230 uabal(vf_l, rd, rn, rm);
5231 break;
5232 case NEON_UABAL2:
5233 uabal2(vf_l, rd, rn, rm);
5234 break;
5235 case NEON_SABDL:
5236 sabdl(vf_l, rd, rn, rm);
5237 break;
5238 case NEON_SABDL2:
5239 sabdl2(vf_l, rd, rn, rm);
5240 break;
5241 case NEON_UABDL:
5242 uabdl(vf_l, rd, rn, rm);
5243 break;
5244 case NEON_UABDL2:
5245 uabdl2(vf_l, rd, rn, rm);
5246 break;
5247 case NEON_SMLAL:
5248 smlal(vf_l, rd, rn, rm);
5249 break;
5250 case NEON_SMLAL2:
5251 smlal2(vf_l, rd, rn, rm);
5252 break;
5253 case NEON_UMLAL:
5254 umlal(vf_l, rd, rn, rm);
5255 break;
5256 case NEON_UMLAL2:
5257 umlal2(vf_l, rd, rn, rm);
5258 break;
5259 case NEON_SMLSL:
5260 smlsl(vf_l, rd, rn, rm);
5261 break;
5262 case NEON_SMLSL2:
5263 smlsl2(vf_l, rd, rn, rm);
5264 break;
5265 case NEON_UMLSL:
5266 umlsl(vf_l, rd, rn, rm);
5267 break;
5268 case NEON_UMLSL2:
5269 umlsl2(vf_l, rd, rn, rm);
5270 break;
5271 case NEON_SMULL:
5272 smull(vf_l, rd, rn, rm);
5273 break;
5274 case NEON_SMULL2:
5275 smull2(vf_l, rd, rn, rm);
5276 break;
5277 case NEON_UMULL:
5278 umull(vf_l, rd, rn, rm);
5279 break;
5280 case NEON_UMULL2:
5281 umull2(vf_l, rd, rn, rm);
5282 break;
5283 case NEON_SQDMLAL:
5284 sqdmlal(vf_l, rd, rn, rm);
5285 break;
5286 case NEON_SQDMLAL2:
5287 sqdmlal2(vf_l, rd, rn, rm);
5288 break;
5289 case NEON_SQDMLSL:
5290 sqdmlsl(vf_l, rd, rn, rm);
5291 break;
5292 case NEON_SQDMLSL2:
5293 sqdmlsl2(vf_l, rd, rn, rm);
5294 break;
5295 case NEON_SQDMULL:
5296 sqdmull(vf_l, rd, rn, rm);
5297 break;
5298 case NEON_SQDMULL2:
5299 sqdmull2(vf_l, rd, rn, rm);
5300 break;
5301 case NEON_UADDW:
5302 uaddw(vf_l, rd, rn, rm);
5303 break;
5304 case NEON_UADDW2:
5305 uaddw2(vf_l, rd, rn, rm);
5306 break;
5307 case NEON_SADDW:
5308 saddw(vf_l, rd, rn, rm);
5309 break;
5310 case NEON_SADDW2:
5311 saddw2(vf_l, rd, rn, rm);
5312 break;
5313 case NEON_USUBW:
5314 usubw(vf_l, rd, rn, rm);
5315 break;
5316 case NEON_USUBW2:
5317 usubw2(vf_l, rd, rn, rm);
5318 break;
5319 case NEON_SSUBW:
5320 ssubw(vf_l, rd, rn, rm);
5321 break;
5322 case NEON_SSUBW2:
5323 ssubw2(vf_l, rd, rn, rm);
5324 break;
5325 case NEON_ADDHN:
5326 addhn(vf, rd, rn, rm);
5327 break;
5328 case NEON_ADDHN2:
5329 addhn2(vf, rd, rn, rm);
5330 break;
5331 case NEON_RADDHN:
5332 raddhn(vf, rd, rn, rm);
5333 break;
5334 case NEON_RADDHN2:
5335 raddhn2(vf, rd, rn, rm);
5336 break;
5337 case NEON_SUBHN:
5338 subhn(vf, rd, rn, rm);
5339 break;
5340 case NEON_SUBHN2:
5341 subhn2(vf, rd, rn, rm);
5342 break;
5343 case NEON_RSUBHN:
5344 rsubhn(vf, rd, rn, rm);
5345 break;
5346 case NEON_RSUBHN2:
5347 rsubhn2(vf, rd, rn, rm);
5348 break;
5349 default:
5350 VIXL_UNIMPLEMENTED();
5351 }
5352}
5353
5354
5355void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5356 NEONFormatDecoder nfd(instr);
5357
Jacob Bramleyca789742018-09-13 14:25:46 +01005358 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5359
Alexandre Ramesd3832962016-07-04 15:03:43 +01005360 SimVRegister& rd = ReadVRegister(instr->GetRd());
5361 SimVRegister& rn = ReadVRegister(instr->GetRn());
5362
Jacob Bramleyca789742018-09-13 14:25:46 +01005363 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5364 VectorFormat vf = nfd.GetVectorFormat(&map_half);
5365 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5366 case NEON_FMAXV_H:
5367 fmaxv(vf, rd, rn);
5368 break;
5369 case NEON_FMINV_H:
5370 fminv(vf, rd, rn);
5371 break;
5372 case NEON_FMAXNMV_H:
5373 fmaxnmv(vf, rd, rn);
5374 break;
5375 case NEON_FMINNMV_H:
5376 fminnmv(vf, rd, rn);
5377 break;
5378 default:
5379 VIXL_UNIMPLEMENTED();
5380 }
5381 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5382 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01005383 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5384
5385 switch (instr->Mask(NEONAcrossLanesFPMask)) {
5386 case NEON_FMAXV:
5387 fmaxv(vf, rd, rn);
5388 break;
5389 case NEON_FMINV:
5390 fminv(vf, rd, rn);
5391 break;
5392 case NEON_FMAXNMV:
5393 fmaxnmv(vf, rd, rn);
5394 break;
5395 case NEON_FMINNMV:
5396 fminnmv(vf, rd, rn);
5397 break;
5398 default:
5399 VIXL_UNIMPLEMENTED();
5400 }
5401 } else {
5402 VectorFormat vf = nfd.GetVectorFormat();
5403
5404 switch (instr->Mask(NEONAcrossLanesMask)) {
5405 case NEON_ADDV:
5406 addv(vf, rd, rn);
5407 break;
5408 case NEON_SMAXV:
5409 smaxv(vf, rd, rn);
5410 break;
5411 case NEON_SMINV:
5412 sminv(vf, rd, rn);
5413 break;
5414 case NEON_UMAXV:
5415 umaxv(vf, rd, rn);
5416 break;
5417 case NEON_UMINV:
5418 uminv(vf, rd, rn);
5419 break;
5420 case NEON_SADDLV:
5421 saddlv(vf, rd, rn);
5422 break;
5423 case NEON_UADDLV:
5424 uaddlv(vf, rd, rn);
5425 break;
5426 default:
5427 VIXL_UNIMPLEMENTED();
5428 }
5429 }
5430}
5431
5432
5433void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5434 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01005435 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01005436 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01005437 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005438 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5439
5440 SimVRegister& rd = ReadVRegister(instr->GetRd());
5441 SimVRegister& rn = ReadVRegister(instr->GetRn());
5442
5443 ByElementOp Op = NULL;
5444
5445 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005446 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005447 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005448 int index_hlm = (index << 1) | instr->GetNEONM();
5449
5450 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5451 // These are oddballs and are best handled as special cases.
5452 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5453 // - The index is always H:L:M.
5454 case NEON_FMLAL_H_byelement:
5455 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5456 return;
5457 case NEON_FMLAL2_H_byelement:
5458 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5459 return;
5460 case NEON_FMLSL_H_byelement:
5461 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5462 return;
5463 case NEON_FMLSL2_H_byelement:
5464 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5465 return;
5466 }
5467
Alexandre Ramesd3832962016-07-04 15:03:43 +01005468 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005469 rm_reg = rm_low_reg;
5470 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005471 }
5472
5473 switch (instr->Mask(NEONByIndexedElementMask)) {
5474 case NEON_MUL_byelement:
5475 Op = &Simulator::mul;
5476 vf = vf_r;
5477 break;
5478 case NEON_MLA_byelement:
5479 Op = &Simulator::mla;
5480 vf = vf_r;
5481 break;
5482 case NEON_MLS_byelement:
5483 Op = &Simulator::mls;
5484 vf = vf_r;
5485 break;
5486 case NEON_SQDMULH_byelement:
5487 Op = &Simulator::sqdmulh;
5488 vf = vf_r;
5489 break;
5490 case NEON_SQRDMULH_byelement:
5491 Op = &Simulator::sqrdmulh;
5492 vf = vf_r;
5493 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005494 case NEON_SDOT_byelement:
5495 Op = &Simulator::sdot;
5496 vf = vf_r;
5497 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005498 case NEON_SQRDMLAH_byelement:
5499 Op = &Simulator::sqrdmlah;
5500 vf = vf_r;
5501 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005502 case NEON_UDOT_byelement:
5503 Op = &Simulator::udot;
5504 vf = vf_r;
5505 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005506 case NEON_SQRDMLSH_byelement:
5507 Op = &Simulator::sqrdmlsh;
5508 vf = vf_r;
5509 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005510 case NEON_SMULL_byelement:
5511 if (instr->Mask(NEON_Q)) {
5512 Op = &Simulator::smull2;
5513 } else {
5514 Op = &Simulator::smull;
5515 }
5516 break;
5517 case NEON_UMULL_byelement:
5518 if (instr->Mask(NEON_Q)) {
5519 Op = &Simulator::umull2;
5520 } else {
5521 Op = &Simulator::umull;
5522 }
5523 break;
5524 case NEON_SMLAL_byelement:
5525 if (instr->Mask(NEON_Q)) {
5526 Op = &Simulator::smlal2;
5527 } else {
5528 Op = &Simulator::smlal;
5529 }
5530 break;
5531 case NEON_UMLAL_byelement:
5532 if (instr->Mask(NEON_Q)) {
5533 Op = &Simulator::umlal2;
5534 } else {
5535 Op = &Simulator::umlal;
5536 }
5537 break;
5538 case NEON_SMLSL_byelement:
5539 if (instr->Mask(NEON_Q)) {
5540 Op = &Simulator::smlsl2;
5541 } else {
5542 Op = &Simulator::smlsl;
5543 }
5544 break;
5545 case NEON_UMLSL_byelement:
5546 if (instr->Mask(NEON_Q)) {
5547 Op = &Simulator::umlsl2;
5548 } else {
5549 Op = &Simulator::umlsl;
5550 }
5551 break;
5552 case NEON_SQDMULL_byelement:
5553 if (instr->Mask(NEON_Q)) {
5554 Op = &Simulator::sqdmull2;
5555 } else {
5556 Op = &Simulator::sqdmull;
5557 }
5558 break;
5559 case NEON_SQDMLAL_byelement:
5560 if (instr->Mask(NEON_Q)) {
5561 Op = &Simulator::sqdmlal2;
5562 } else {
5563 Op = &Simulator::sqdmlal;
5564 }
5565 break;
5566 case NEON_SQDMLSL_byelement:
5567 if (instr->Mask(NEON_Q)) {
5568 Op = &Simulator::sqdmlsl2;
5569 } else {
5570 Op = &Simulator::sqdmlsl;
5571 }
5572 break;
5573 default:
5574 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01005575 if (instr->GetFPType() == 0) {
5576 rm_reg &= 0xf;
5577 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5578 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005579 index = (index << 1) | instr->GetNEONL();
5580 }
5581
5582 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5583
5584 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005585 case NEON_FMUL_H_byelement:
5586 vf = vf_half;
5587 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005588 case NEON_FMUL_byelement:
5589 Op = &Simulator::fmul;
5590 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005591 case NEON_FMLA_H_byelement:
5592 vf = vf_half;
5593 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005594 case NEON_FMLA_byelement:
5595 Op = &Simulator::fmla;
5596 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005597 case NEON_FMLS_H_byelement:
5598 vf = vf_half;
5599 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005600 case NEON_FMLS_byelement:
5601 Op = &Simulator::fmls;
5602 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005603 case NEON_FMULX_H_byelement:
5604 vf = vf_half;
5605 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005606 case NEON_FMULX_byelement:
5607 Op = &Simulator::fmulx;
5608 break;
5609 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005610 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00005611 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005612 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00005613 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005614 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005615 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5616 case NEON_FCMLA_byelement:
5617 vf = vf_r;
5618 fcmla(vf,
5619 rd,
5620 rn,
5621 ReadVRegister(instr->GetRm()),
5622 index,
5623 instr->GetImmRotFcmlaSca());
5624 return;
5625 default:
5626 VIXL_UNIMPLEMENTED();
5627 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005628 }
5629 }
5630
5631 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5632}
5633
5634
5635void Simulator::VisitNEONCopy(const Instruction* instr) {
5636 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5637 VectorFormat vf = nfd.GetVectorFormat();
5638
5639 SimVRegister& rd = ReadVRegister(instr->GetRd());
5640 SimVRegister& rn = ReadVRegister(instr->GetRn());
5641 int imm5 = instr->GetImmNEON5();
5642 int tz = CountTrailingZeros(imm5, 32);
5643 int reg_index = imm5 >> (tz + 1);
5644
5645 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5646 int imm4 = instr->GetImmNEON4();
5647 int rn_index = imm4 >> tz;
5648 ins_element(vf, rd, reg_index, rn, rn_index);
5649 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5650 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5651 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5652 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5653 value &= MaxUintFromFormat(vf);
5654 WriteXRegister(instr->GetRd(), value);
5655 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5656 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5657 if (instr->GetNEONQ()) {
5658 WriteXRegister(instr->GetRd(), value);
5659 } else {
5660 WriteWRegister(instr->GetRd(), (int32_t)value);
5661 }
5662 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5663 dup_element(vf, rd, rn, reg_index);
5664 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5665 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5666 } else {
5667 VIXL_UNIMPLEMENTED();
5668 }
5669}
5670
5671
5672void Simulator::VisitNEONExtract(const Instruction* instr) {
5673 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5674 VectorFormat vf = nfd.GetVectorFormat();
5675 SimVRegister& rd = ReadVRegister(instr->GetRd());
5676 SimVRegister& rn = ReadVRegister(instr->GetRn());
5677 SimVRegister& rm = ReadVRegister(instr->GetRm());
5678 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5679 int index = instr->GetImmNEONExt();
5680 ext(vf, rd, rn, rm, index);
5681 } else {
5682 VIXL_UNIMPLEMENTED();
5683 }
5684}
5685
5686
5687void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5688 AddrMode addr_mode) {
5689 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5690 VectorFormat vf = nfd.GetVectorFormat();
5691
5692 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5693 int reg_size = RegisterSizeInBytesFromFormat(vf);
5694
5695 int reg[4];
5696 uint64_t addr[4];
5697 for (int i = 0; i < 4; i++) {
5698 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5699 addr[i] = addr_base + (i * reg_size);
5700 }
5701 int count = 1;
5702 bool log_read = true;
5703
Martyn Capewell32009e32016-10-27 11:00:37 +01005704 // Bit 23 determines whether this is an offset or post-index addressing mode.
5705 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5706 // register or immediate in post-index mode.
5707 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005708 VIXL_UNREACHABLE();
5709 }
5710
5711 // We use the PostIndex mask here, as it works in this case for both Offset
5712 // and PostIndex addressing.
5713 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5714 case NEON_LD1_4v:
5715 case NEON_LD1_4v_post:
5716 ld1(vf, ReadVRegister(reg[3]), addr[3]);
5717 count++;
5718 VIXL_FALLTHROUGH();
5719 case NEON_LD1_3v:
5720 case NEON_LD1_3v_post:
5721 ld1(vf, ReadVRegister(reg[2]), addr[2]);
5722 count++;
5723 VIXL_FALLTHROUGH();
5724 case NEON_LD1_2v:
5725 case NEON_LD1_2v_post:
5726 ld1(vf, ReadVRegister(reg[1]), addr[1]);
5727 count++;
5728 VIXL_FALLTHROUGH();
5729 case NEON_LD1_1v:
5730 case NEON_LD1_1v_post:
5731 ld1(vf, ReadVRegister(reg[0]), addr[0]);
5732 break;
5733 case NEON_ST1_4v:
5734 case NEON_ST1_4v_post:
5735 st1(vf, ReadVRegister(reg[3]), addr[3]);
5736 count++;
5737 VIXL_FALLTHROUGH();
5738 case NEON_ST1_3v:
5739 case NEON_ST1_3v_post:
5740 st1(vf, ReadVRegister(reg[2]), addr[2]);
5741 count++;
5742 VIXL_FALLTHROUGH();
5743 case NEON_ST1_2v:
5744 case NEON_ST1_2v_post:
5745 st1(vf, ReadVRegister(reg[1]), addr[1]);
5746 count++;
5747 VIXL_FALLTHROUGH();
5748 case NEON_ST1_1v:
5749 case NEON_ST1_1v_post:
5750 st1(vf, ReadVRegister(reg[0]), addr[0]);
5751 log_read = false;
5752 break;
5753 case NEON_LD2_post:
5754 case NEON_LD2:
5755 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5756 count = 2;
5757 break;
5758 case NEON_ST2:
5759 case NEON_ST2_post:
5760 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5761 count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01005762 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005763 break;
5764 case NEON_LD3_post:
5765 case NEON_LD3:
5766 ld3(vf,
5767 ReadVRegister(reg[0]),
5768 ReadVRegister(reg[1]),
5769 ReadVRegister(reg[2]),
5770 addr[0]);
5771 count = 3;
5772 break;
5773 case NEON_ST3:
5774 case NEON_ST3_post:
5775 st3(vf,
5776 ReadVRegister(reg[0]),
5777 ReadVRegister(reg[1]),
5778 ReadVRegister(reg[2]),
5779 addr[0]);
5780 count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01005781 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005782 break;
5783 case NEON_ST4:
5784 case NEON_ST4_post:
5785 st4(vf,
5786 ReadVRegister(reg[0]),
5787 ReadVRegister(reg[1]),
5788 ReadVRegister(reg[2]),
5789 ReadVRegister(reg[3]),
5790 addr[0]);
5791 count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01005792 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005793 break;
5794 case NEON_LD4_post:
5795 case NEON_LD4:
5796 ld4(vf,
5797 ReadVRegister(reg[0]),
5798 ReadVRegister(reg[1]),
5799 ReadVRegister(reg[2]),
5800 ReadVRegister(reg[3]),
5801 addr[0]);
5802 count = 4;
5803 break;
5804 default:
5805 VIXL_UNIMPLEMENTED();
5806 }
5807
5808 // Explicitly log the register update whilst we have type information.
5809 for (int i = 0; i < count; i++) {
5810 // For de-interleaving loads, only print the base address.
5811 int lane_size = LaneSizeInBytesFromFormat(vf);
5812 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
5813 GetPrintRegisterFormatForSize(reg_size, lane_size));
5814 if (log_read) {
5815 LogVRead(addr_base, reg[i], format);
5816 } else {
5817 LogVWrite(addr_base, reg[i], format);
5818 }
5819 }
5820
5821 if (addr_mode == PostIndex) {
5822 int rm = instr->GetRm();
5823 // The immediate post index addressing mode is indicated by rm = 31.
5824 // The immediate is implied by the number of vector registers used.
5825 addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
5826 : ReadXRegister(rm);
5827 WriteXRegister(instr->GetRn(), addr_base);
5828 } else {
5829 VIXL_ASSERT(addr_mode == Offset);
5830 }
5831}
5832
5833
5834void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
5835 NEONLoadStoreMultiStructHelper(instr, Offset);
5836}
5837
5838
5839void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
5840 const Instruction* instr) {
5841 NEONLoadStoreMultiStructHelper(instr, PostIndex);
5842}
5843
5844
5845void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
5846 AddrMode addr_mode) {
5847 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5848 int rt = instr->GetRt();
5849
Martyn Capewell32009e32016-10-27 11:00:37 +01005850 // Bit 23 determines whether this is an offset or post-index addressing mode.
5851 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5852 // register or immediate in post-index mode.
5853 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005854 VIXL_UNREACHABLE();
5855 }
5856
5857 // We use the PostIndex mask here, as it works in this case for both Offset
5858 // and PostIndex addressing.
5859 bool do_load = false;
5860
5861 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5862 VectorFormat vf_t = nfd.GetVectorFormat();
5863
5864 VectorFormat vf = kFormat16B;
5865 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
5866 case NEON_LD1_b:
5867 case NEON_LD1_b_post:
5868 case NEON_LD2_b:
5869 case NEON_LD2_b_post:
5870 case NEON_LD3_b:
5871 case NEON_LD3_b_post:
5872 case NEON_LD4_b:
5873 case NEON_LD4_b_post:
5874 do_load = true;
5875 VIXL_FALLTHROUGH();
5876 case NEON_ST1_b:
5877 case NEON_ST1_b_post:
5878 case NEON_ST2_b:
5879 case NEON_ST2_b_post:
5880 case NEON_ST3_b:
5881 case NEON_ST3_b_post:
5882 case NEON_ST4_b:
5883 case NEON_ST4_b_post:
5884 break;
5885
5886 case NEON_LD1_h:
5887 case NEON_LD1_h_post:
5888 case NEON_LD2_h:
5889 case NEON_LD2_h_post:
5890 case NEON_LD3_h:
5891 case NEON_LD3_h_post:
5892 case NEON_LD4_h:
5893 case NEON_LD4_h_post:
5894 do_load = true;
5895 VIXL_FALLTHROUGH();
5896 case NEON_ST1_h:
5897 case NEON_ST1_h_post:
5898 case NEON_ST2_h:
5899 case NEON_ST2_h_post:
5900 case NEON_ST3_h:
5901 case NEON_ST3_h_post:
5902 case NEON_ST4_h:
5903 case NEON_ST4_h_post:
5904 vf = kFormat8H;
5905 break;
5906 case NEON_LD1_s:
5907 case NEON_LD1_s_post:
5908 case NEON_LD2_s:
5909 case NEON_LD2_s_post:
5910 case NEON_LD3_s:
5911 case NEON_LD3_s_post:
5912 case NEON_LD4_s:
5913 case NEON_LD4_s_post:
5914 do_load = true;
5915 VIXL_FALLTHROUGH();
5916 case NEON_ST1_s:
5917 case NEON_ST1_s_post:
5918 case NEON_ST2_s:
5919 case NEON_ST2_s_post:
5920 case NEON_ST3_s:
5921 case NEON_ST3_s_post:
5922 case NEON_ST4_s:
5923 case NEON_ST4_s_post: {
5924 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
5925 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
5926 NEON_LD1_d_post);
5927 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
5928 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
5929 NEON_ST1_d_post);
5930 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
5931 break;
5932 }
5933
5934 case NEON_LD1R:
5935 case NEON_LD1R_post: {
5936 vf = vf_t;
5937 ld1r(vf, ReadVRegister(rt), addr);
5938 do_load = true;
5939 break;
5940 }
5941
5942 case NEON_LD2R:
5943 case NEON_LD2R_post: {
5944 vf = vf_t;
5945 int rt2 = (rt + 1) % kNumberOfVRegisters;
5946 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
5947 do_load = true;
5948 break;
5949 }
5950
5951 case NEON_LD3R:
5952 case NEON_LD3R_post: {
5953 vf = vf_t;
5954 int rt2 = (rt + 1) % kNumberOfVRegisters;
5955 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5956 ld3r(vf, ReadVRegister(rt), ReadVRegister(rt2), ReadVRegister(rt3), addr);
5957 do_load = true;
5958 break;
5959 }
5960
5961 case NEON_LD4R:
5962 case NEON_LD4R_post: {
5963 vf = vf_t;
5964 int rt2 = (rt + 1) % kNumberOfVRegisters;
5965 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5966 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5967 ld4r(vf,
5968 ReadVRegister(rt),
5969 ReadVRegister(rt2),
5970 ReadVRegister(rt3),
5971 ReadVRegister(rt4),
5972 addr);
5973 do_load = true;
5974 break;
5975 }
5976 default:
5977 VIXL_UNIMPLEMENTED();
5978 }
5979
5980 PrintRegisterFormat print_format =
5981 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
5982 // Make sure that the print_format only includes a single lane.
5983 print_format =
5984 static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
5985
5986 int esize = LaneSizeInBytesFromFormat(vf);
5987 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
5988 int lane = instr->GetNEONLSIndex(index_shift);
5989 int scale = 0;
5990 int rt2 = (rt + 1) % kNumberOfVRegisters;
5991 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5992 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5993 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
5994 case NEONLoadStoreSingle1:
5995 scale = 1;
5996 if (do_load) {
5997 ld1(vf, ReadVRegister(rt), lane, addr);
5998 LogVRead(addr, rt, print_format, lane);
5999 } else {
6000 st1(vf, ReadVRegister(rt), lane, addr);
6001 LogVWrite(addr, rt, print_format, lane);
6002 }
6003 break;
6004 case NEONLoadStoreSingle2:
6005 scale = 2;
6006 if (do_load) {
6007 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
6008 LogVRead(addr, rt, print_format, lane);
6009 LogVRead(addr + esize, rt2, print_format, lane);
6010 } else {
6011 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
6012 LogVWrite(addr, rt, print_format, lane);
6013 LogVWrite(addr + esize, rt2, print_format, lane);
6014 }
6015 break;
6016 case NEONLoadStoreSingle3:
6017 scale = 3;
6018 if (do_load) {
6019 ld3(vf,
6020 ReadVRegister(rt),
6021 ReadVRegister(rt2),
6022 ReadVRegister(rt3),
6023 lane,
6024 addr);
6025 LogVRead(addr, rt, print_format, lane);
6026 LogVRead(addr + esize, rt2, print_format, lane);
6027 LogVRead(addr + (2 * esize), rt3, print_format, lane);
6028 } else {
6029 st3(vf,
6030 ReadVRegister(rt),
6031 ReadVRegister(rt2),
6032 ReadVRegister(rt3),
6033 lane,
6034 addr);
6035 LogVWrite(addr, rt, print_format, lane);
6036 LogVWrite(addr + esize, rt2, print_format, lane);
6037 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
6038 }
6039 break;
6040 case NEONLoadStoreSingle4:
6041 scale = 4;
6042 if (do_load) {
6043 ld4(vf,
6044 ReadVRegister(rt),
6045 ReadVRegister(rt2),
6046 ReadVRegister(rt3),
6047 ReadVRegister(rt4),
6048 lane,
6049 addr);
6050 LogVRead(addr, rt, print_format, lane);
6051 LogVRead(addr + esize, rt2, print_format, lane);
6052 LogVRead(addr + (2 * esize), rt3, print_format, lane);
6053 LogVRead(addr + (3 * esize), rt4, print_format, lane);
6054 } else {
6055 st4(vf,
6056 ReadVRegister(rt),
6057 ReadVRegister(rt2),
6058 ReadVRegister(rt3),
6059 ReadVRegister(rt4),
6060 lane,
6061 addr);
6062 LogVWrite(addr, rt, print_format, lane);
6063 LogVWrite(addr + esize, rt2, print_format, lane);
6064 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
6065 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
6066 }
6067 break;
6068 default:
6069 VIXL_UNIMPLEMENTED();
6070 }
6071
6072 if (addr_mode == PostIndex) {
6073 int rm = instr->GetRm();
6074 int lane_size = LaneSizeInBytesFromFormat(vf);
6075 WriteXRegister(instr->GetRn(),
6076 addr +
6077 ((rm == 31) ? (scale * lane_size) : ReadXRegister(rm)));
6078 }
6079}
6080
6081
6082void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
6083 NEONLoadStoreSingleStructHelper(instr, Offset);
6084}
6085
6086
6087void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
6088 const Instruction* instr) {
6089 NEONLoadStoreSingleStructHelper(instr, PostIndex);
6090}
6091
6092
6093void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
6094 SimVRegister& rd = ReadVRegister(instr->GetRd());
6095 int cmode = instr->GetNEONCmode();
6096 int cmode_3_1 = (cmode >> 1) & 7;
6097 int cmode_3 = (cmode >> 3) & 1;
6098 int cmode_2 = (cmode >> 2) & 1;
6099 int cmode_1 = (cmode >> 1) & 1;
6100 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01006101 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006102 int q = instr->GetNEONQ();
6103 int op_bit = instr->GetNEONModImmOp();
6104 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01006105 // Find the format and immediate value
6106 uint64_t imm = 0;
6107 VectorFormat vform = kFormatUndefined;
6108 switch (cmode_3_1) {
6109 case 0x0:
6110 case 0x1:
6111 case 0x2:
6112 case 0x3:
6113 vform = (q == 1) ? kFormat4S : kFormat2S;
6114 imm = imm8 << (8 * cmode_3_1);
6115 break;
6116 case 0x4:
6117 case 0x5:
6118 vform = (q == 1) ? kFormat8H : kFormat4H;
6119 imm = imm8 << (8 * cmode_1);
6120 break;
6121 case 0x6:
6122 vform = (q == 1) ? kFormat4S : kFormat2S;
6123 if (cmode_0 == 0) {
6124 imm = imm8 << 8 | 0x000000ff;
6125 } else {
6126 imm = imm8 << 16 | 0x0000ffff;
6127 }
6128 break;
6129 case 0x7:
6130 if (cmode_0 == 0 && op_bit == 0) {
6131 vform = q ? kFormat16B : kFormat8B;
6132 imm = imm8;
6133 } else if (cmode_0 == 0 && op_bit == 1) {
6134 vform = q ? kFormat2D : kFormat1D;
6135 imm = 0;
6136 for (int i = 0; i < 8; ++i) {
6137 if (imm8 & (1 << i)) {
6138 imm |= (UINT64_C(0xff) << (8 * i));
6139 }
6140 }
6141 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01006142 if (half_enc == 1) {
6143 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01006144 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006145 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006146 vform = q ? kFormat4S : kFormat2S;
6147 imm = FloatToRawbits(instr->GetImmNEONFP32());
6148 } else if (q == 1) {
6149 vform = kFormat2D;
6150 imm = DoubleToRawbits(instr->GetImmNEONFP64());
6151 } else {
6152 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
6153 VisitUnallocated(instr);
6154 }
6155 }
6156 break;
6157 default:
6158 VIXL_UNREACHABLE();
6159 break;
6160 }
6161
6162 // Find the operation
6163 NEONModifiedImmediateOp op;
6164 if (cmode_3 == 0) {
6165 if (cmode_0 == 0) {
6166 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6167 } else { // cmode<0> == '1'
6168 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6169 }
6170 } else { // cmode<3> == '1'
6171 if (cmode_2 == 0) {
6172 if (cmode_0 == 0) {
6173 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6174 } else { // cmode<0> == '1'
6175 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6176 }
6177 } else { // cmode<2> == '1'
6178 if (cmode_1 == 0) {
6179 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6180 } else { // cmode<1> == '1'
6181 if (cmode_0 == 0) {
6182 op = NEONModifiedImmediate_MOVI;
6183 } else { // cmode<0> == '1'
6184 op = NEONModifiedImmediate_MOVI;
6185 }
6186 }
6187 }
6188 }
6189
6190 // Call the logic function
6191 if (op == NEONModifiedImmediate_ORR) {
6192 orr(vform, rd, rd, imm);
6193 } else if (op == NEONModifiedImmediate_BIC) {
6194 bic(vform, rd, rd, imm);
6195 } else if (op == NEONModifiedImmediate_MOVI) {
6196 movi(vform, rd, imm);
6197 } else if (op == NEONModifiedImmediate_MVNI) {
6198 mvni(vform, rd, imm);
6199 } else {
6200 VisitUnimplemented(instr);
6201 }
6202}
6203
6204
6205void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
6206 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6207 VectorFormat vf = nfd.GetVectorFormat();
6208
6209 SimVRegister& rd = ReadVRegister(instr->GetRd());
6210 SimVRegister& rn = ReadVRegister(instr->GetRn());
6211
6212 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
6213 // These instructions all use a two bit size field, except NOT and RBIT,
6214 // which use the field to encode the operation.
6215 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6216 case NEON_CMEQ_zero_scalar:
6217 cmp(vf, rd, rn, 0, eq);
6218 break;
6219 case NEON_CMGE_zero_scalar:
6220 cmp(vf, rd, rn, 0, ge);
6221 break;
6222 case NEON_CMGT_zero_scalar:
6223 cmp(vf, rd, rn, 0, gt);
6224 break;
6225 case NEON_CMLT_zero_scalar:
6226 cmp(vf, rd, rn, 0, lt);
6227 break;
6228 case NEON_CMLE_zero_scalar:
6229 cmp(vf, rd, rn, 0, le);
6230 break;
6231 case NEON_ABS_scalar:
6232 abs(vf, rd, rn);
6233 break;
6234 case NEON_SQABS_scalar:
6235 abs(vf, rd, rn).SignedSaturate(vf);
6236 break;
6237 case NEON_NEG_scalar:
6238 neg(vf, rd, rn);
6239 break;
6240 case NEON_SQNEG_scalar:
6241 neg(vf, rd, rn).SignedSaturate(vf);
6242 break;
6243 case NEON_SUQADD_scalar:
6244 suqadd(vf, rd, rn);
6245 break;
6246 case NEON_USQADD_scalar:
6247 usqadd(vf, rd, rn);
6248 break;
6249 default:
6250 VIXL_UNIMPLEMENTED();
6251 break;
6252 }
6253 } else {
6254 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6255 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6256
6257 // These instructions all use a one bit size field, except SQXTUN, SQXTN
6258 // and UQXTN, which use a two bit size field.
6259 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
6260 case NEON_FRECPE_scalar:
6261 frecpe(fpf, rd, rn, fpcr_rounding);
6262 break;
6263 case NEON_FRECPX_scalar:
6264 frecpx(fpf, rd, rn);
6265 break;
6266 case NEON_FRSQRTE_scalar:
6267 frsqrte(fpf, rd, rn);
6268 break;
6269 case NEON_FCMGT_zero_scalar:
6270 fcmp_zero(fpf, rd, rn, gt);
6271 break;
6272 case NEON_FCMGE_zero_scalar:
6273 fcmp_zero(fpf, rd, rn, ge);
6274 break;
6275 case NEON_FCMEQ_zero_scalar:
6276 fcmp_zero(fpf, rd, rn, eq);
6277 break;
6278 case NEON_FCMLE_zero_scalar:
6279 fcmp_zero(fpf, rd, rn, le);
6280 break;
6281 case NEON_FCMLT_zero_scalar:
6282 fcmp_zero(fpf, rd, rn, lt);
6283 break;
6284 case NEON_SCVTF_scalar:
6285 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6286 break;
6287 case NEON_UCVTF_scalar:
6288 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6289 break;
6290 case NEON_FCVTNS_scalar:
6291 fcvts(fpf, rd, rn, FPTieEven);
6292 break;
6293 case NEON_FCVTNU_scalar:
6294 fcvtu(fpf, rd, rn, FPTieEven);
6295 break;
6296 case NEON_FCVTPS_scalar:
6297 fcvts(fpf, rd, rn, FPPositiveInfinity);
6298 break;
6299 case NEON_FCVTPU_scalar:
6300 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6301 break;
6302 case NEON_FCVTMS_scalar:
6303 fcvts(fpf, rd, rn, FPNegativeInfinity);
6304 break;
6305 case NEON_FCVTMU_scalar:
6306 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6307 break;
6308 case NEON_FCVTZS_scalar:
6309 fcvts(fpf, rd, rn, FPZero);
6310 break;
6311 case NEON_FCVTZU_scalar:
6312 fcvtu(fpf, rd, rn, FPZero);
6313 break;
6314 case NEON_FCVTAS_scalar:
6315 fcvts(fpf, rd, rn, FPTieAway);
6316 break;
6317 case NEON_FCVTAU_scalar:
6318 fcvtu(fpf, rd, rn, FPTieAway);
6319 break;
6320 case NEON_FCVTXN_scalar:
6321 // Unlike all of the other FP instructions above, fcvtxn encodes dest
6322 // size S as size<0>=1. There's only one case, so we ignore the form.
6323 VIXL_ASSERT(instr->ExtractBit(22) == 1);
6324 fcvtxn(kFormatS, rd, rn);
6325 break;
6326 default:
6327 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6328 case NEON_SQXTN_scalar:
6329 sqxtn(vf, rd, rn);
6330 break;
6331 case NEON_UQXTN_scalar:
6332 uqxtn(vf, rd, rn);
6333 break;
6334 case NEON_SQXTUN_scalar:
6335 sqxtun(vf, rd, rn);
6336 break;
6337 default:
6338 VIXL_UNIMPLEMENTED();
6339 }
6340 }
6341 }
6342}
6343
6344
Jacob Bramleyca789742018-09-13 14:25:46 +01006345void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
6346 VectorFormat fpf = kFormatH;
6347 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6348
6349 SimVRegister& rd = ReadVRegister(instr->GetRd());
6350 SimVRegister& rn = ReadVRegister(instr->GetRn());
6351
6352 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6353 case NEON_FRECPE_H_scalar:
6354 frecpe(fpf, rd, rn, fpcr_rounding);
6355 break;
6356 case NEON_FRECPX_H_scalar:
6357 frecpx(fpf, rd, rn);
6358 break;
6359 case NEON_FRSQRTE_H_scalar:
6360 frsqrte(fpf, rd, rn);
6361 break;
6362 case NEON_FCMGT_H_zero_scalar:
6363 fcmp_zero(fpf, rd, rn, gt);
6364 break;
6365 case NEON_FCMGE_H_zero_scalar:
6366 fcmp_zero(fpf, rd, rn, ge);
6367 break;
6368 case NEON_FCMEQ_H_zero_scalar:
6369 fcmp_zero(fpf, rd, rn, eq);
6370 break;
6371 case NEON_FCMLE_H_zero_scalar:
6372 fcmp_zero(fpf, rd, rn, le);
6373 break;
6374 case NEON_FCMLT_H_zero_scalar:
6375 fcmp_zero(fpf, rd, rn, lt);
6376 break;
6377 case NEON_SCVTF_H_scalar:
6378 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6379 break;
6380 case NEON_UCVTF_H_scalar:
6381 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6382 break;
6383 case NEON_FCVTNS_H_scalar:
6384 fcvts(fpf, rd, rn, FPTieEven);
6385 break;
6386 case NEON_FCVTNU_H_scalar:
6387 fcvtu(fpf, rd, rn, FPTieEven);
6388 break;
6389 case NEON_FCVTPS_H_scalar:
6390 fcvts(fpf, rd, rn, FPPositiveInfinity);
6391 break;
6392 case NEON_FCVTPU_H_scalar:
6393 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6394 break;
6395 case NEON_FCVTMS_H_scalar:
6396 fcvts(fpf, rd, rn, FPNegativeInfinity);
6397 break;
6398 case NEON_FCVTMU_H_scalar:
6399 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6400 break;
6401 case NEON_FCVTZS_H_scalar:
6402 fcvts(fpf, rd, rn, FPZero);
6403 break;
6404 case NEON_FCVTZU_H_scalar:
6405 fcvtu(fpf, rd, rn, FPZero);
6406 break;
6407 case NEON_FCVTAS_H_scalar:
6408 fcvts(fpf, rd, rn, FPTieAway);
6409 break;
6410 case NEON_FCVTAU_H_scalar:
6411 fcvtu(fpf, rd, rn, FPTieAway);
6412 break;
6413 }
6414}
6415
6416
Alexandre Ramesd3832962016-07-04 15:03:43 +01006417void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6418 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6419 VectorFormat vf = nfd.GetVectorFormat();
6420
6421 SimVRegister& rd = ReadVRegister(instr->GetRd());
6422 SimVRegister& rn = ReadVRegister(instr->GetRn());
6423 SimVRegister& rm = ReadVRegister(instr->GetRm());
6424 switch (instr->Mask(NEONScalar3DiffMask)) {
6425 case NEON_SQDMLAL_scalar:
6426 sqdmlal(vf, rd, rn, rm);
6427 break;
6428 case NEON_SQDMLSL_scalar:
6429 sqdmlsl(vf, rd, rn, rm);
6430 break;
6431 case NEON_SQDMULL_scalar:
6432 sqdmull(vf, rd, rn, rm);
6433 break;
6434 default:
6435 VIXL_UNIMPLEMENTED();
6436 }
6437}
6438
6439
6440void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6441 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6442 VectorFormat vf = nfd.GetVectorFormat();
6443
6444 SimVRegister& rd = ReadVRegister(instr->GetRd());
6445 SimVRegister& rn = ReadVRegister(instr->GetRn());
6446 SimVRegister& rm = ReadVRegister(instr->GetRm());
6447
6448 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6449 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6450 switch (instr->Mask(NEONScalar3SameFPMask)) {
6451 case NEON_FMULX_scalar:
6452 fmulx(vf, rd, rn, rm);
6453 break;
6454 case NEON_FACGE_scalar:
6455 fabscmp(vf, rd, rn, rm, ge);
6456 break;
6457 case NEON_FACGT_scalar:
6458 fabscmp(vf, rd, rn, rm, gt);
6459 break;
6460 case NEON_FCMEQ_scalar:
6461 fcmp(vf, rd, rn, rm, eq);
6462 break;
6463 case NEON_FCMGE_scalar:
6464 fcmp(vf, rd, rn, rm, ge);
6465 break;
6466 case NEON_FCMGT_scalar:
6467 fcmp(vf, rd, rn, rm, gt);
6468 break;
6469 case NEON_FRECPS_scalar:
6470 frecps(vf, rd, rn, rm);
6471 break;
6472 case NEON_FRSQRTS_scalar:
6473 frsqrts(vf, rd, rn, rm);
6474 break;
6475 case NEON_FABD_scalar:
6476 fabd(vf, rd, rn, rm);
6477 break;
6478 default:
6479 VIXL_UNIMPLEMENTED();
6480 }
6481 } else {
6482 switch (instr->Mask(NEONScalar3SameMask)) {
6483 case NEON_ADD_scalar:
6484 add(vf, rd, rn, rm);
6485 break;
6486 case NEON_SUB_scalar:
6487 sub(vf, rd, rn, rm);
6488 break;
6489 case NEON_CMEQ_scalar:
6490 cmp(vf, rd, rn, rm, eq);
6491 break;
6492 case NEON_CMGE_scalar:
6493 cmp(vf, rd, rn, rm, ge);
6494 break;
6495 case NEON_CMGT_scalar:
6496 cmp(vf, rd, rn, rm, gt);
6497 break;
6498 case NEON_CMHI_scalar:
6499 cmp(vf, rd, rn, rm, hi);
6500 break;
6501 case NEON_CMHS_scalar:
6502 cmp(vf, rd, rn, rm, hs);
6503 break;
6504 case NEON_CMTST_scalar:
6505 cmptst(vf, rd, rn, rm);
6506 break;
6507 case NEON_USHL_scalar:
6508 ushl(vf, rd, rn, rm);
6509 break;
6510 case NEON_SSHL_scalar:
6511 sshl(vf, rd, rn, rm);
6512 break;
6513 case NEON_SQDMULH_scalar:
6514 sqdmulh(vf, rd, rn, rm);
6515 break;
6516 case NEON_SQRDMULH_scalar:
6517 sqrdmulh(vf, rd, rn, rm);
6518 break;
6519 case NEON_UQADD_scalar:
6520 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6521 break;
6522 case NEON_SQADD_scalar:
6523 add(vf, rd, rn, rm).SignedSaturate(vf);
6524 break;
6525 case NEON_UQSUB_scalar:
6526 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6527 break;
6528 case NEON_SQSUB_scalar:
6529 sub(vf, rd, rn, rm).SignedSaturate(vf);
6530 break;
6531 case NEON_UQSHL_scalar:
6532 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6533 break;
6534 case NEON_SQSHL_scalar:
6535 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6536 break;
6537 case NEON_URSHL_scalar:
6538 ushl(vf, rd, rn, rm).Round(vf);
6539 break;
6540 case NEON_SRSHL_scalar:
6541 sshl(vf, rd, rn, rm).Round(vf);
6542 break;
6543 case NEON_UQRSHL_scalar:
6544 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6545 break;
6546 case NEON_SQRSHL_scalar:
6547 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6548 break;
6549 default:
6550 VIXL_UNIMPLEMENTED();
6551 }
6552 }
6553}
6554
Jacob Bramleyca789742018-09-13 14:25:46 +01006555void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6556 SimVRegister& rd = ReadVRegister(instr->GetRd());
6557 SimVRegister& rn = ReadVRegister(instr->GetRn());
6558 SimVRegister& rm = ReadVRegister(instr->GetRm());
6559
6560 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6561 case NEON_FABD_H_scalar:
6562 fabd(kFormatH, rd, rn, rm);
6563 break;
6564 case NEON_FMULX_H_scalar:
6565 fmulx(kFormatH, rd, rn, rm);
6566 break;
6567 case NEON_FCMEQ_H_scalar:
6568 fcmp(kFormatH, rd, rn, rm, eq);
6569 break;
6570 case NEON_FCMGE_H_scalar:
6571 fcmp(kFormatH, rd, rn, rm, ge);
6572 break;
6573 case NEON_FCMGT_H_scalar:
6574 fcmp(kFormatH, rd, rn, rm, gt);
6575 break;
6576 case NEON_FACGE_H_scalar:
6577 fabscmp(kFormatH, rd, rn, rm, ge);
6578 break;
6579 case NEON_FACGT_H_scalar:
6580 fabscmp(kFormatH, rd, rn, rm, gt);
6581 break;
6582 case NEON_FRECPS_H_scalar:
6583 frecps(kFormatH, rd, rn, rm);
6584 break;
6585 case NEON_FRSQRTS_H_scalar:
6586 frsqrts(kFormatH, rd, rn, rm);
6587 break;
6588 default:
6589 VIXL_UNREACHABLE();
6590 }
6591}
6592
Alexandre Ramesd3832962016-07-04 15:03:43 +01006593
Alexander Gilday43785642018-04-04 13:42:33 +01006594void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6595 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6596 VectorFormat vf = nfd.GetVectorFormat();
6597
6598 SimVRegister& rd = ReadVRegister(instr->GetRd());
6599 SimVRegister& rn = ReadVRegister(instr->GetRn());
6600 SimVRegister& rm = ReadVRegister(instr->GetRm());
6601
6602 switch (instr->Mask(NEONScalar3SameExtraMask)) {
6603 case NEON_SQRDMLAH_scalar:
6604 sqrdmlah(vf, rd, rn, rm);
6605 break;
6606 case NEON_SQRDMLSH_scalar:
6607 sqrdmlsh(vf, rd, rn, rm);
6608 break;
6609 default:
6610 VIXL_UNIMPLEMENTED();
6611 }
6612}
6613
Alexandre Ramesd3832962016-07-04 15:03:43 +01006614void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6615 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6616 VectorFormat vf = nfd.GetVectorFormat();
6617 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6618
6619 SimVRegister& rd = ReadVRegister(instr->GetRd());
6620 SimVRegister& rn = ReadVRegister(instr->GetRn());
6621 ByElementOp Op = NULL;
6622
6623 int rm_reg = instr->GetRm();
6624 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6625 if (instr->GetNEONSize() == 1) {
6626 rm_reg &= 0xf;
6627 index = (index << 1) | instr->GetNEONM();
6628 }
6629
6630 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6631 case NEON_SQDMULL_byelement_scalar:
6632 Op = &Simulator::sqdmull;
6633 break;
6634 case NEON_SQDMLAL_byelement_scalar:
6635 Op = &Simulator::sqdmlal;
6636 break;
6637 case NEON_SQDMLSL_byelement_scalar:
6638 Op = &Simulator::sqdmlsl;
6639 break;
6640 case NEON_SQDMULH_byelement_scalar:
6641 Op = &Simulator::sqdmulh;
6642 vf = vf_r;
6643 break;
6644 case NEON_SQRDMULH_byelement_scalar:
6645 Op = &Simulator::sqrdmulh;
6646 vf = vf_r;
6647 break;
Alexander Gilday43785642018-04-04 13:42:33 +01006648 case NEON_SQRDMLAH_byelement_scalar:
6649 Op = &Simulator::sqrdmlah;
6650 vf = vf_r;
6651 break;
6652 case NEON_SQRDMLSH_byelement_scalar:
6653 Op = &Simulator::sqrdmlsh;
6654 vf = vf_r;
6655 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006656 default:
6657 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6658 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01006659 if (instr->GetFPType() == 0) {
6660 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6661 rm_reg &= 0xf;
6662 vf = kFormatH;
6663 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006664 index = (index << 1) | instr->GetNEONL();
6665 }
6666 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006667 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006668 case NEON_FMUL_byelement_scalar:
6669 Op = &Simulator::fmul;
6670 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006671 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006672 case NEON_FMLA_byelement_scalar:
6673 Op = &Simulator::fmla;
6674 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006675 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006676 case NEON_FMLS_byelement_scalar:
6677 Op = &Simulator::fmls;
6678 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006679 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006680 case NEON_FMULX_byelement_scalar:
6681 Op = &Simulator::fmulx;
6682 break;
6683 default:
6684 VIXL_UNIMPLEMENTED();
6685 }
6686 }
6687
6688 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6689}
6690
6691
6692void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6693 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6694 VectorFormat vf = nfd.GetVectorFormat();
6695
6696 SimVRegister& rd = ReadVRegister(instr->GetRd());
6697 SimVRegister& rn = ReadVRegister(instr->GetRn());
6698
6699 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6700 int imm5 = instr->GetImmNEON5();
6701 int tz = CountTrailingZeros(imm5, 32);
6702 int rn_index = imm5 >> (tz + 1);
6703 dup_element(vf, rd, rn, rn_index);
6704 } else {
6705 VIXL_UNIMPLEMENTED();
6706 }
6707}
6708
6709
6710void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006711 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006712 VectorFormat vf = nfd.GetVectorFormat();
6713
6714 SimVRegister& rd = ReadVRegister(instr->GetRd());
6715 SimVRegister& rn = ReadVRegister(instr->GetRn());
6716 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006717 case NEON_ADDP_scalar: {
6718 // All pairwise operations except ADDP use bit U to differentiate FP16
6719 // from FP32/FP64 variations.
6720 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6721 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006722 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006723 }
6724 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006725 case NEON_FADDP_scalar:
6726 faddp(vf, rd, rn);
6727 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006728 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006729 case NEON_FMAXP_scalar:
6730 fmaxp(vf, rd, rn);
6731 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006732 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006733 case NEON_FMAXNMP_scalar:
6734 fmaxnmp(vf, rd, rn);
6735 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006736 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006737 case NEON_FMINP_scalar:
6738 fminp(vf, rd, rn);
6739 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006740 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006741 case NEON_FMINNMP_scalar:
6742 fminnmp(vf, rd, rn);
6743 break;
6744 default:
6745 VIXL_UNIMPLEMENTED();
6746 }
6747}
6748
6749
6750void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6751 SimVRegister& rd = ReadVRegister(instr->GetRd());
6752 SimVRegister& rn = ReadVRegister(instr->GetRn());
6753 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6754
6755 static const NEONFormatMap map = {{22, 21, 20, 19},
6756 {NF_UNDEF,
6757 NF_B,
6758 NF_H,
6759 NF_H,
6760 NF_S,
6761 NF_S,
6762 NF_S,
6763 NF_S,
6764 NF_D,
6765 NF_D,
6766 NF_D,
6767 NF_D,
6768 NF_D,
6769 NF_D,
6770 NF_D,
6771 NF_D}};
6772 NEONFormatDecoder nfd(instr, &map);
6773 VectorFormat vf = nfd.GetVectorFormat();
6774
6775 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6776 int immhimmb = instr->GetImmNEONImmhImmb();
6777 int right_shift = (16 << highestSetBit) - immhimmb;
6778 int left_shift = immhimmb - (8 << highestSetBit);
6779 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
6780 case NEON_SHL_scalar:
6781 shl(vf, rd, rn, left_shift);
6782 break;
6783 case NEON_SLI_scalar:
6784 sli(vf, rd, rn, left_shift);
6785 break;
6786 case NEON_SQSHL_imm_scalar:
6787 sqshl(vf, rd, rn, left_shift);
6788 break;
6789 case NEON_UQSHL_imm_scalar:
6790 uqshl(vf, rd, rn, left_shift);
6791 break;
6792 case NEON_SQSHLU_scalar:
6793 sqshlu(vf, rd, rn, left_shift);
6794 break;
6795 case NEON_SRI_scalar:
6796 sri(vf, rd, rn, right_shift);
6797 break;
6798 case NEON_SSHR_scalar:
6799 sshr(vf, rd, rn, right_shift);
6800 break;
6801 case NEON_USHR_scalar:
6802 ushr(vf, rd, rn, right_shift);
6803 break;
6804 case NEON_SRSHR_scalar:
6805 sshr(vf, rd, rn, right_shift).Round(vf);
6806 break;
6807 case NEON_URSHR_scalar:
6808 ushr(vf, rd, rn, right_shift).Round(vf);
6809 break;
6810 case NEON_SSRA_scalar:
6811 ssra(vf, rd, rn, right_shift);
6812 break;
6813 case NEON_USRA_scalar:
6814 usra(vf, rd, rn, right_shift);
6815 break;
6816 case NEON_SRSRA_scalar:
6817 srsra(vf, rd, rn, right_shift);
6818 break;
6819 case NEON_URSRA_scalar:
6820 ursra(vf, rd, rn, right_shift);
6821 break;
6822 case NEON_UQSHRN_scalar:
6823 uqshrn(vf, rd, rn, right_shift);
6824 break;
6825 case NEON_UQRSHRN_scalar:
6826 uqrshrn(vf, rd, rn, right_shift);
6827 break;
6828 case NEON_SQSHRN_scalar:
6829 sqshrn(vf, rd, rn, right_shift);
6830 break;
6831 case NEON_SQRSHRN_scalar:
6832 sqrshrn(vf, rd, rn, right_shift);
6833 break;
6834 case NEON_SQSHRUN_scalar:
6835 sqshrun(vf, rd, rn, right_shift);
6836 break;
6837 case NEON_SQRSHRUN_scalar:
6838 sqrshrun(vf, rd, rn, right_shift);
6839 break;
6840 case NEON_FCVTZS_imm_scalar:
6841 fcvts(vf, rd, rn, FPZero, right_shift);
6842 break;
6843 case NEON_FCVTZU_imm_scalar:
6844 fcvtu(vf, rd, rn, FPZero, right_shift);
6845 break;
6846 case NEON_SCVTF_imm_scalar:
6847 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6848 break;
6849 case NEON_UCVTF_imm_scalar:
6850 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6851 break;
6852 default:
6853 VIXL_UNIMPLEMENTED();
6854 }
6855}
6856
6857
6858void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
6859 SimVRegister& rd = ReadVRegister(instr->GetRd());
6860 SimVRegister& rn = ReadVRegister(instr->GetRn());
6861 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6862
6863 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
6864 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
6865 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01006866 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
6867 NF_4H, NF_8H, NF_4H, NF_8H,
6868 NF_2S, NF_4S, NF_2S, NF_4S,
6869 NF_2S, NF_4S, NF_2S, NF_4S,
6870 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6871 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6872 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6873 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01006874 NEONFormatDecoder nfd(instr, &map);
6875 VectorFormat vf = nfd.GetVectorFormat();
6876
6877 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
6878 static const NEONFormatMap map_l =
6879 {{22, 21, 20, 19},
6880 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
6881 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
6882
6883 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6884 int immhimmb = instr->GetImmNEONImmhImmb();
6885 int right_shift = (16 << highestSetBit) - immhimmb;
6886 int left_shift = immhimmb - (8 << highestSetBit);
6887
6888 switch (instr->Mask(NEONShiftImmediateMask)) {
6889 case NEON_SHL:
6890 shl(vf, rd, rn, left_shift);
6891 break;
6892 case NEON_SLI:
6893 sli(vf, rd, rn, left_shift);
6894 break;
6895 case NEON_SQSHLU:
6896 sqshlu(vf, rd, rn, left_shift);
6897 break;
6898 case NEON_SRI:
6899 sri(vf, rd, rn, right_shift);
6900 break;
6901 case NEON_SSHR:
6902 sshr(vf, rd, rn, right_shift);
6903 break;
6904 case NEON_USHR:
6905 ushr(vf, rd, rn, right_shift);
6906 break;
6907 case NEON_SRSHR:
6908 sshr(vf, rd, rn, right_shift).Round(vf);
6909 break;
6910 case NEON_URSHR:
6911 ushr(vf, rd, rn, right_shift).Round(vf);
6912 break;
6913 case NEON_SSRA:
6914 ssra(vf, rd, rn, right_shift);
6915 break;
6916 case NEON_USRA:
6917 usra(vf, rd, rn, right_shift);
6918 break;
6919 case NEON_SRSRA:
6920 srsra(vf, rd, rn, right_shift);
6921 break;
6922 case NEON_URSRA:
6923 ursra(vf, rd, rn, right_shift);
6924 break;
6925 case NEON_SQSHL_imm:
6926 sqshl(vf, rd, rn, left_shift);
6927 break;
6928 case NEON_UQSHL_imm:
6929 uqshl(vf, rd, rn, left_shift);
6930 break;
6931 case NEON_SCVTF_imm:
6932 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6933 break;
6934 case NEON_UCVTF_imm:
6935 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6936 break;
6937 case NEON_FCVTZS_imm:
6938 fcvts(vf, rd, rn, FPZero, right_shift);
6939 break;
6940 case NEON_FCVTZU_imm:
6941 fcvtu(vf, rd, rn, FPZero, right_shift);
6942 break;
6943 case NEON_SSHLL:
6944 vf = vf_l;
6945 if (instr->Mask(NEON_Q)) {
6946 sshll2(vf, rd, rn, left_shift);
6947 } else {
6948 sshll(vf, rd, rn, left_shift);
6949 }
6950 break;
6951 case NEON_USHLL:
6952 vf = vf_l;
6953 if (instr->Mask(NEON_Q)) {
6954 ushll2(vf, rd, rn, left_shift);
6955 } else {
6956 ushll(vf, rd, rn, left_shift);
6957 }
6958 break;
6959 case NEON_SHRN:
6960 if (instr->Mask(NEON_Q)) {
6961 shrn2(vf, rd, rn, right_shift);
6962 } else {
6963 shrn(vf, rd, rn, right_shift);
6964 }
6965 break;
6966 case NEON_RSHRN:
6967 if (instr->Mask(NEON_Q)) {
6968 rshrn2(vf, rd, rn, right_shift);
6969 } else {
6970 rshrn(vf, rd, rn, right_shift);
6971 }
6972 break;
6973 case NEON_UQSHRN:
6974 if (instr->Mask(NEON_Q)) {
6975 uqshrn2(vf, rd, rn, right_shift);
6976 } else {
6977 uqshrn(vf, rd, rn, right_shift);
6978 }
6979 break;
6980 case NEON_UQRSHRN:
6981 if (instr->Mask(NEON_Q)) {
6982 uqrshrn2(vf, rd, rn, right_shift);
6983 } else {
6984 uqrshrn(vf, rd, rn, right_shift);
6985 }
6986 break;
6987 case NEON_SQSHRN:
6988 if (instr->Mask(NEON_Q)) {
6989 sqshrn2(vf, rd, rn, right_shift);
6990 } else {
6991 sqshrn(vf, rd, rn, right_shift);
6992 }
6993 break;
6994 case NEON_SQRSHRN:
6995 if (instr->Mask(NEON_Q)) {
6996 sqrshrn2(vf, rd, rn, right_shift);
6997 } else {
6998 sqrshrn(vf, rd, rn, right_shift);
6999 }
7000 break;
7001 case NEON_SQSHRUN:
7002 if (instr->Mask(NEON_Q)) {
7003 sqshrun2(vf, rd, rn, right_shift);
7004 } else {
7005 sqshrun(vf, rd, rn, right_shift);
7006 }
7007 break;
7008 case NEON_SQRSHRUN:
7009 if (instr->Mask(NEON_Q)) {
7010 sqrshrun2(vf, rd, rn, right_shift);
7011 } else {
7012 sqrshrun(vf, rd, rn, right_shift);
7013 }
7014 break;
7015 default:
7016 VIXL_UNIMPLEMENTED();
7017 }
7018}
7019
7020
7021void Simulator::VisitNEONTable(const Instruction* instr) {
7022 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7023 VectorFormat vf = nfd.GetVectorFormat();
7024
7025 SimVRegister& rd = ReadVRegister(instr->GetRd());
7026 SimVRegister& rn = ReadVRegister(instr->GetRn());
7027 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
7028 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
7029 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
7030 SimVRegister& rm = ReadVRegister(instr->GetRm());
7031
7032 switch (instr->Mask(NEONTableMask)) {
7033 case NEON_TBL_1v:
7034 tbl(vf, rd, rn, rm);
7035 break;
7036 case NEON_TBL_2v:
7037 tbl(vf, rd, rn, rn2, rm);
7038 break;
7039 case NEON_TBL_3v:
7040 tbl(vf, rd, rn, rn2, rn3, rm);
7041 break;
7042 case NEON_TBL_4v:
7043 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
7044 break;
7045 case NEON_TBX_1v:
7046 tbx(vf, rd, rn, rm);
7047 break;
7048 case NEON_TBX_2v:
7049 tbx(vf, rd, rn, rn2, rm);
7050 break;
7051 case NEON_TBX_3v:
7052 tbx(vf, rd, rn, rn2, rn3, rm);
7053 break;
7054 case NEON_TBX_4v:
7055 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
7056 break;
7057 default:
7058 VIXL_UNIMPLEMENTED();
7059 }
7060}
7061
7062
7063void Simulator::VisitNEONPerm(const Instruction* instr) {
7064 NEONFormatDecoder nfd(instr);
7065 VectorFormat vf = nfd.GetVectorFormat();
7066
7067 SimVRegister& rd = ReadVRegister(instr->GetRd());
7068 SimVRegister& rn = ReadVRegister(instr->GetRn());
7069 SimVRegister& rm = ReadVRegister(instr->GetRm());
7070
7071 switch (instr->Mask(NEONPermMask)) {
7072 case NEON_TRN1:
7073 trn1(vf, rd, rn, rm);
7074 break;
7075 case NEON_TRN2:
7076 trn2(vf, rd, rn, rm);
7077 break;
7078 case NEON_UZP1:
7079 uzp1(vf, rd, rn, rm);
7080 break;
7081 case NEON_UZP2:
7082 uzp2(vf, rd, rn, rm);
7083 break;
7084 case NEON_ZIP1:
7085 zip1(vf, rd, rn, rm);
7086 break;
7087 case NEON_ZIP2:
7088 zip2(vf, rd, rn, rm);
7089 break;
7090 default:
7091 VIXL_UNIMPLEMENTED();
7092 }
7093}
7094
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007095void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
7096 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007097 switch (instr->Mask(SVEAddressGenerationMask)) {
7098 case ADR_z_az_d_s32_scaled:
7099 VIXL_UNIMPLEMENTED();
7100 break;
7101 case ADR_z_az_d_u32_scaled:
7102 VIXL_UNIMPLEMENTED();
7103 break;
7104 case ADR_z_az_sd_same_scaled:
7105 VIXL_UNIMPLEMENTED();
7106 break;
7107 default:
7108 VIXL_UNIMPLEMENTED();
7109 break;
7110 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007111}
7112
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007113void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
7114 const Instruction* instr) {
7115 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
TatWai Chonga1885a52019-04-15 17:19:14 -07007116 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007117 case AND_z_zi:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007118 case EOR_z_zi:
TatWai Chonga1885a52019-04-15 17:19:14 -07007119 case ORR_z_zi: {
7120 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7121 uint64_t imm = instr->GetSVEImmLogical();
7122 // Valid immediate is a non-zero bits
7123 VIXL_ASSERT(imm != 0);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007124 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
7125 op),
TatWai Chonga1885a52019-04-15 17:19:14 -07007126 SVEFormatFromLaneSizeInBytesLog2(lane_size),
7127 ReadVRegister(instr->GetRd()),
7128 imm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007129 break;
TatWai Chonga1885a52019-04-15 17:19:14 -07007130 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007131 default:
7132 VIXL_UNIMPLEMENTED();
7133 break;
7134 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007135}
7136
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007137void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
7138 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
7139 case DUPM_z_i: {
7140 /* DUPM uses the same lane size and immediate encoding as bitwise logical
7141 * immediate instructions. */
7142 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7143 uint64_t imm = instr->GetSVEImmLogical();
7144 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7145 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
7146 break;
7147 }
7148 default:
7149 VIXL_UNIMPLEMENTED();
7150 break;
7151 }
7152}
7153
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007154void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
7155 USE(instr);
TatWai Chongcfb94212019-05-16 13:30:09 -07007156 SimVRegister& zd = ReadVRegister(instr->GetRd());
7157 SimVRegister& zn = ReadVRegister(instr->GetRn());
7158 SimVRegister& zm = ReadVRegister(instr->GetRm());
7159 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
7160
TatWai Chong13634762019-07-16 16:20:45 -07007161 LogicalOp logical_op;
TatWai Chongcfb94212019-05-16 13:30:09 -07007162 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007163 case AND_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007164 logical_op = AND;
7165 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007166 case BIC_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007167 logical_op = BIC;
7168 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007169 case EOR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007170 logical_op = EOR;
7171 break;
TatWai Chongcfb94212019-05-16 13:30:09 -07007172 case ORR_z_zz:
TatWai Chong13634762019-07-16 16:20:45 -07007173 logical_op = ORR;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007174 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007175 default:
TatWai Chong13634762019-07-16 16:20:45 -07007176 logical_op = LogicalOpMask;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007177 VIXL_UNIMPLEMENTED();
7178 break;
7179 }
TatWai Chong13634762019-07-16 16:20:45 -07007180 // Lane size of registers is irrelevant to the bitwise operations, so perform
7181 // the operation on D-sized lanes.
7182 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007183}
7184
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007185void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007186 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007187 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007188 case ASRD_z_p_zi:
7189 VIXL_UNIMPLEMENTED();
7190 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007191 case ASR_z_p_zi:
7192 VIXL_UNIMPLEMENTED();
7193 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007194 case LSL_z_p_zi:
7195 VIXL_UNIMPLEMENTED();
7196 break;
7197 case LSR_z_p_zi:
7198 VIXL_UNIMPLEMENTED();
7199 break;
7200 default:
7201 VIXL_UNIMPLEMENTED();
7202 break;
7203 }
7204}
7205
7206void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
7207 const Instruction* instr) {
7208 USE(instr);
7209 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
7210 case ASRR_z_p_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007211 VIXL_UNIMPLEMENTED();
7212 break;
7213 case ASR_z_p_zz:
7214 VIXL_UNIMPLEMENTED();
7215 break;
7216 case LSLR_z_p_zz:
7217 VIXL_UNIMPLEMENTED();
7218 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007219 case LSL_z_p_zz:
7220 VIXL_UNIMPLEMENTED();
7221 break;
7222 case LSRR_z_p_zz:
7223 VIXL_UNIMPLEMENTED();
7224 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007225 case LSR_z_p_zz:
7226 VIXL_UNIMPLEMENTED();
7227 break;
7228 default:
7229 VIXL_UNIMPLEMENTED();
7230 break;
7231 }
7232}
7233
7234void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
7235 const Instruction* instr) {
7236 USE(instr);
7237 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
7238 case ASR_z_p_zw:
7239 VIXL_UNIMPLEMENTED();
7240 break;
7241 case LSL_z_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007242 VIXL_UNIMPLEMENTED();
7243 break;
7244 case LSR_z_p_zw:
7245 VIXL_UNIMPLEMENTED();
7246 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007247 default:
7248 VIXL_UNIMPLEMENTED();
7249 break;
7250 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007251}
7252
7253void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
7254 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007255 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7256 case ASR_z_zi:
7257 VIXL_UNIMPLEMENTED();
7258 break;
7259 case ASR_z_zw:
7260 VIXL_UNIMPLEMENTED();
7261 break;
7262 case LSL_z_zi:
7263 VIXL_UNIMPLEMENTED();
7264 break;
7265 case LSL_z_zw:
7266 VIXL_UNIMPLEMENTED();
7267 break;
7268 case LSR_z_zi:
7269 VIXL_UNIMPLEMENTED();
7270 break;
7271 case LSR_z_zw:
7272 VIXL_UNIMPLEMENTED();
7273 break;
7274 default:
7275 VIXL_UNIMPLEMENTED();
7276 break;
7277 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007278}
7279
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007280void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
Martyn Capewell579c92d2019-10-30 17:48:52 +00007281 // Although the instructions have a separate encoding class, the lane size is
7282 // encoded in the same way as most other SVE instructions.
7283 VectorFormat vform = instr->GetSVEVectorFormat();
7284
7285 int pattern = instr->GetImmSVEPredicateConstraint();
7286 int count = GetPredicateConstraintLaneCount(vform, pattern);
7287 int multiplier = instr->ExtractBits(19, 16) + 1;
7288
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007289 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007290 case DECB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007291 case DECD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007292 case DECH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007293 case DECW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007294 count = -count;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007295 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007296 case INCB_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007297 case INCD_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007298 case INCH_r_rs:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007299 case INCW_r_rs:
Martyn Capewell579c92d2019-10-30 17:48:52 +00007300 // Nothing to do.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007301 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007302 default:
7303 VIXL_UNIMPLEMENTED();
Martyn Capewell579c92d2019-10-30 17:48:52 +00007304 return;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007305 }
Martyn Capewell579c92d2019-10-30 17:48:52 +00007306
7307 WriteXRegister(instr->GetRd(),
7308 IncDecN(ReadXRegister(instr->GetRd()),
7309 count * multiplier,
7310 kXRegSize));
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007311}
7312
7313void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
7314 USE(instr);
7315 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
7316 case DECD_z_zs:
7317 VIXL_UNIMPLEMENTED();
7318 break;
7319 case DECH_z_zs:
7320 VIXL_UNIMPLEMENTED();
7321 break;
7322 case DECW_z_zs:
7323 VIXL_UNIMPLEMENTED();
7324 break;
7325 case INCD_z_zs:
7326 VIXL_UNIMPLEMENTED();
7327 break;
7328 case INCH_z_zs:
7329 VIXL_UNIMPLEMENTED();
7330 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007331 case INCW_z_zs:
7332 VIXL_UNIMPLEMENTED();
7333 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007334 default:
7335 VIXL_UNIMPLEMENTED();
7336 break;
7337 }
7338}
7339
7340void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
7341 const Instruction* instr) {
7342 USE(instr);
7343 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007344 case SQDECB_r_rs_sx:
7345 VIXL_UNIMPLEMENTED();
7346 break;
7347 case SQDECB_r_rs_x:
7348 VIXL_UNIMPLEMENTED();
7349 break;
7350 case SQDECD_r_rs_sx:
7351 VIXL_UNIMPLEMENTED();
7352 break;
7353 case SQDECD_r_rs_x:
7354 VIXL_UNIMPLEMENTED();
7355 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007356 case SQDECH_r_rs_sx:
7357 VIXL_UNIMPLEMENTED();
7358 break;
7359 case SQDECH_r_rs_x:
7360 VIXL_UNIMPLEMENTED();
7361 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007362 case SQDECW_r_rs_sx:
7363 VIXL_UNIMPLEMENTED();
7364 break;
7365 case SQDECW_r_rs_x:
7366 VIXL_UNIMPLEMENTED();
7367 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007368 case SQINCB_r_rs_sx:
7369 VIXL_UNIMPLEMENTED();
7370 break;
7371 case SQINCB_r_rs_x:
7372 VIXL_UNIMPLEMENTED();
7373 break;
7374 case SQINCD_r_rs_sx:
7375 VIXL_UNIMPLEMENTED();
7376 break;
7377 case SQINCD_r_rs_x:
7378 VIXL_UNIMPLEMENTED();
7379 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007380 case SQINCH_r_rs_sx:
7381 VIXL_UNIMPLEMENTED();
7382 break;
7383 case SQINCH_r_rs_x:
7384 VIXL_UNIMPLEMENTED();
7385 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007386 case SQINCW_r_rs_sx:
7387 VIXL_UNIMPLEMENTED();
7388 break;
7389 case SQINCW_r_rs_x:
7390 VIXL_UNIMPLEMENTED();
7391 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007392 case UQDECB_r_rs_uw:
7393 VIXL_UNIMPLEMENTED();
7394 break;
7395 case UQDECB_r_rs_x:
7396 VIXL_UNIMPLEMENTED();
7397 break;
7398 case UQDECD_r_rs_uw:
7399 VIXL_UNIMPLEMENTED();
7400 break;
7401 case UQDECD_r_rs_x:
7402 VIXL_UNIMPLEMENTED();
7403 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007404 case UQDECH_r_rs_uw:
7405 VIXL_UNIMPLEMENTED();
7406 break;
7407 case UQDECH_r_rs_x:
7408 VIXL_UNIMPLEMENTED();
7409 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007410 case UQDECW_r_rs_uw:
7411 VIXL_UNIMPLEMENTED();
7412 break;
7413 case UQDECW_r_rs_x:
7414 VIXL_UNIMPLEMENTED();
7415 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007416 case UQINCB_r_rs_uw:
7417 VIXL_UNIMPLEMENTED();
7418 break;
7419 case UQINCB_r_rs_x:
7420 VIXL_UNIMPLEMENTED();
7421 break;
7422 case UQINCD_r_rs_uw:
7423 VIXL_UNIMPLEMENTED();
7424 break;
7425 case UQINCD_r_rs_x:
7426 VIXL_UNIMPLEMENTED();
7427 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007428 case UQINCH_r_rs_uw:
7429 VIXL_UNIMPLEMENTED();
7430 break;
7431 case UQINCH_r_rs_x:
7432 VIXL_UNIMPLEMENTED();
7433 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007434 case UQINCW_r_rs_uw:
7435 VIXL_UNIMPLEMENTED();
7436 break;
7437 case UQINCW_r_rs_x:
7438 VIXL_UNIMPLEMENTED();
7439 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007440 default:
7441 VIXL_UNIMPLEMENTED();
7442 break;
7443 }
7444}
7445
7446void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
7447 const Instruction* instr) {
7448 USE(instr);
7449 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7450 case SQDECD_z_zs:
7451 VIXL_UNIMPLEMENTED();
7452 break;
7453 case SQDECH_z_zs:
7454 VIXL_UNIMPLEMENTED();
7455 break;
7456 case SQDECW_z_zs:
7457 VIXL_UNIMPLEMENTED();
7458 break;
7459 case SQINCD_z_zs:
7460 VIXL_UNIMPLEMENTED();
7461 break;
7462 case SQINCH_z_zs:
7463 VIXL_UNIMPLEMENTED();
7464 break;
7465 case SQINCW_z_zs:
7466 VIXL_UNIMPLEMENTED();
7467 break;
7468 case UQDECD_z_zs:
7469 VIXL_UNIMPLEMENTED();
7470 break;
7471 case UQDECH_z_zs:
7472 VIXL_UNIMPLEMENTED();
7473 break;
7474 case UQDECW_z_zs:
7475 VIXL_UNIMPLEMENTED();
7476 break;
7477 case UQINCD_z_zs:
7478 VIXL_UNIMPLEMENTED();
7479 break;
7480 case UQINCH_z_zs:
7481 VIXL_UNIMPLEMENTED();
7482 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007483 case UQINCW_z_zs:
7484 VIXL_UNIMPLEMENTED();
7485 break;
7486 default:
7487 VIXL_UNIMPLEMENTED();
7488 break;
7489 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007490}
7491
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007492void Simulator::VisitSVEElementCount(const Instruction* instr) {
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007493 switch (instr->Mask(SVEElementCountMask)) {
7494 case CNTB_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007495 case CNTD_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007496 case CNTH_r_s:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007497 case CNTW_r_s:
Martyn Capewell74f84f62019-10-30 15:30:44 +00007498 // All handled below.
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007499 break;
7500 default:
7501 VIXL_UNIMPLEMENTED();
7502 break;
7503 }
Martyn Capewell74f84f62019-10-30 15:30:44 +00007504
7505 // Although the instructions are separated, the lane size is encoded in the
7506 // same way as most other SVE instructions.
7507 VectorFormat vform = instr->GetSVEVectorFormat();
7508
7509 int pattern = instr->GetImmSVEPredicateConstraint();
7510 int count = GetPredicateConstraintLaneCount(vform, pattern);
7511 int multiplier = instr->ExtractBits(19, 16) + 1;
7512 WriteXRegister(instr->GetRd(), count * multiplier);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007513}
7514
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007515void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
7516 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007517 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7518 case FADDA_v_p_z:
7519 VIXL_UNIMPLEMENTED();
7520 break;
7521 default:
7522 VIXL_UNIMPLEMENTED();
7523 break;
7524 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007525}
7526
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007527void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007528 USE(instr);
TatWai Chongd316c5e2019-10-16 12:22:10 -07007529 VectorFormat vform = instr->GetSVEVectorFormat();
7530 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7531 SimVRegister& zm = ReadVRegister(instr->GetRn());
7532 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7533
7534 SimVRegister result;
7535
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007536 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007537 case FABD_z_p_zz:
7538 VIXL_UNIMPLEMENTED();
7539 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007540 case FADD_z_p_zz:
7541 VIXL_UNIMPLEMENTED();
7542 break;
7543 case FDIVR_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007544 fdiv(vform, result, zm, zdn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007545 break;
7546 case FDIV_z_p_zz:
TatWai Chongd316c5e2019-10-16 12:22:10 -07007547 fdiv(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007548 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007549 case FMAXNM_z_p_zz:
7550 VIXL_UNIMPLEMENTED();
7551 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007552 case FMAX_z_p_zz:
7553 VIXL_UNIMPLEMENTED();
7554 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007555 case FMINNM_z_p_zz:
7556 VIXL_UNIMPLEMENTED();
7557 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007558 case FMIN_z_p_zz:
7559 VIXL_UNIMPLEMENTED();
7560 break;
7561 case FMULX_z_p_zz:
7562 VIXL_UNIMPLEMENTED();
7563 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007564 case FMUL_z_p_zz:
7565 VIXL_UNIMPLEMENTED();
7566 break;
7567 case FSCALE_z_p_zz:
7568 VIXL_UNIMPLEMENTED();
7569 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007570 case FSUBR_z_p_zz:
7571 VIXL_UNIMPLEMENTED();
7572 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007573 case FSUB_z_p_zz:
7574 VIXL_UNIMPLEMENTED();
7575 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007576 default:
7577 VIXL_UNIMPLEMENTED();
7578 break;
7579 }
TatWai Chongd316c5e2019-10-16 12:22:10 -07007580 mov_merging(vform, zdn, pg, result);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007581}
7582
7583void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
7584 const Instruction* instr) {
7585 USE(instr);
7586 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
7587 case FADD_z_p_zs:
7588 VIXL_UNIMPLEMENTED();
7589 break;
7590 case FMAXNM_z_p_zs:
7591 VIXL_UNIMPLEMENTED();
7592 break;
7593 case FMAX_z_p_zs:
7594 VIXL_UNIMPLEMENTED();
7595 break;
7596 case FMINNM_z_p_zs:
7597 VIXL_UNIMPLEMENTED();
7598 break;
7599 case FMIN_z_p_zs:
7600 VIXL_UNIMPLEMENTED();
7601 break;
7602 case FMUL_z_p_zs:
7603 VIXL_UNIMPLEMENTED();
7604 break;
7605 case FSUBR_z_p_zs:
7606 VIXL_UNIMPLEMENTED();
7607 break;
7608 case FSUB_z_p_zs:
7609 VIXL_UNIMPLEMENTED();
7610 break;
7611 default:
7612 VIXL_UNIMPLEMENTED();
7613 break;
7614 }
7615}
7616
7617void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
7618 USE(instr);
7619 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007620 case FTMAD_z_zzi:
7621 VIXL_UNIMPLEMENTED();
7622 break;
7623 default:
7624 VIXL_UNIMPLEMENTED();
7625 break;
7626 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007627}
7628
7629void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
7630 USE(instr);
TatWai Chongfe536042019-10-23 16:34:11 -07007631
7632 VectorFormat vform = instr->GetSVEVectorFormat();
7633 SimVRegister& zd = ReadVRegister(instr->GetRd());
7634 SimVRegister& zn = ReadVRegister(instr->GetRn());
7635 SimVRegister& zm = ReadVRegister(instr->GetRm());
7636
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007637 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7638 case FADD_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007639 fadd(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007640 break;
7641 case FMUL_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007642 fmul(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007643 break;
7644 case FRECPS_z_zz:
7645 VIXL_UNIMPLEMENTED();
7646 break;
7647 case FRSQRTS_z_zz:
7648 VIXL_UNIMPLEMENTED();
7649 break;
7650 case FSUB_z_zz:
TatWai Chongfe536042019-10-23 16:34:11 -07007651 fsub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007652 break;
7653 case FTSMUL_z_zz:
7654 VIXL_UNIMPLEMENTED();
7655 break;
7656 default:
7657 VIXL_UNIMPLEMENTED();
7658 break;
7659 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007660}
7661
7662void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
7663 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007664 switch (instr->Mask(SVEFPCompareVectorsMask)) {
7665 case FACGE_p_p_zz:
7666 VIXL_UNIMPLEMENTED();
7667 break;
7668 case FACGT_p_p_zz:
7669 VIXL_UNIMPLEMENTED();
7670 break;
7671 case FCMEQ_p_p_zz:
7672 VIXL_UNIMPLEMENTED();
7673 break;
7674 case FCMGE_p_p_zz:
7675 VIXL_UNIMPLEMENTED();
7676 break;
7677 case FCMGT_p_p_zz:
7678 VIXL_UNIMPLEMENTED();
7679 break;
7680 case FCMNE_p_p_zz:
7681 VIXL_UNIMPLEMENTED();
7682 break;
7683 case FCMUO_p_p_zz:
7684 VIXL_UNIMPLEMENTED();
7685 break;
7686 default:
7687 VIXL_UNIMPLEMENTED();
7688 break;
7689 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007690}
7691
7692void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
7693 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007694 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
7695 case FCMEQ_p_p_z0:
7696 VIXL_UNIMPLEMENTED();
7697 break;
7698 case FCMGE_p_p_z0:
7699 VIXL_UNIMPLEMENTED();
7700 break;
7701 case FCMGT_p_p_z0:
7702 VIXL_UNIMPLEMENTED();
7703 break;
7704 case FCMLE_p_p_z0:
7705 VIXL_UNIMPLEMENTED();
7706 break;
7707 case FCMLT_p_p_z0:
7708 VIXL_UNIMPLEMENTED();
7709 break;
7710 case FCMNE_p_p_z0:
7711 VIXL_UNIMPLEMENTED();
7712 break;
7713 default:
7714 VIXL_UNIMPLEMENTED();
7715 break;
7716 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007717}
7718
7719void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
7720 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007721 switch (instr->Mask(SVEFPComplexAdditionMask)) {
7722 case FCADD_z_p_zz:
7723 VIXL_UNIMPLEMENTED();
7724 break;
7725 default:
7726 VIXL_UNIMPLEMENTED();
7727 break;
7728 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007729}
7730
7731void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
7732 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007733 switch (instr->Mask(SVEFPComplexMulAddMask)) {
7734 case FCMLA_z_p_zzz:
7735 VIXL_UNIMPLEMENTED();
7736 break;
7737 default:
7738 VIXL_UNIMPLEMENTED();
7739 break;
7740 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007741}
7742
7743void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
7744 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007745 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
7746 case FCMLA_z_zzzi_h:
7747 VIXL_UNIMPLEMENTED();
7748 break;
7749 case FCMLA_z_zzzi_s:
7750 VIXL_UNIMPLEMENTED();
7751 break;
7752 default:
7753 VIXL_UNIMPLEMENTED();
7754 break;
7755 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007756}
7757
7758void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
7759 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007760 switch (instr->Mask(SVEFPFastReductionMask)) {
7761 case FADDV_v_p_z:
7762 VIXL_UNIMPLEMENTED();
7763 break;
7764 case FMAXNMV_v_p_z:
7765 VIXL_UNIMPLEMENTED();
7766 break;
7767 case FMAXV_v_p_z:
7768 VIXL_UNIMPLEMENTED();
7769 break;
7770 case FMINNMV_v_p_z:
7771 VIXL_UNIMPLEMENTED();
7772 break;
7773 case FMINV_v_p_z:
7774 VIXL_UNIMPLEMENTED();
7775 break;
7776 default:
7777 VIXL_UNIMPLEMENTED();
7778 break;
7779 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007780}
7781
7782void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
7783 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007784 switch (instr->Mask(SVEFPMulIndexMask)) {
7785 case FMUL_z_zzi_d:
7786 VIXL_UNIMPLEMENTED();
7787 break;
7788 case FMUL_z_zzi_h:
7789 VIXL_UNIMPLEMENTED();
7790 break;
7791 case FMUL_z_zzi_s:
7792 VIXL_UNIMPLEMENTED();
7793 break;
7794 default:
7795 VIXL_UNIMPLEMENTED();
7796 break;
7797 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007798}
7799
7800void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
7801 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007802 switch (instr->Mask(SVEFPMulAddMask)) {
7803 case FMAD_z_p_zzz:
7804 VIXL_UNIMPLEMENTED();
7805 break;
7806 case FMLA_z_p_zzz:
7807 VIXL_UNIMPLEMENTED();
7808 break;
7809 case FMLS_z_p_zzz:
7810 VIXL_UNIMPLEMENTED();
7811 break;
7812 case FMSB_z_p_zzz:
7813 VIXL_UNIMPLEMENTED();
7814 break;
7815 case FNMAD_z_p_zzz:
7816 VIXL_UNIMPLEMENTED();
7817 break;
7818 case FNMLA_z_p_zzz:
7819 VIXL_UNIMPLEMENTED();
7820 break;
7821 case FNMLS_z_p_zzz:
7822 VIXL_UNIMPLEMENTED();
7823 break;
7824 case FNMSB_z_p_zzz:
7825 VIXL_UNIMPLEMENTED();
7826 break;
7827 default:
7828 VIXL_UNIMPLEMENTED();
7829 break;
7830 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007831}
7832
7833void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
7834 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007835 switch (instr->Mask(SVEFPMulAddIndexMask)) {
7836 case FMLA_z_zzzi_d:
7837 VIXL_UNIMPLEMENTED();
7838 break;
7839 case FMLA_z_zzzi_h:
7840 VIXL_UNIMPLEMENTED();
7841 break;
7842 case FMLA_z_zzzi_s:
7843 VIXL_UNIMPLEMENTED();
7844 break;
7845 case FMLS_z_zzzi_d:
7846 VIXL_UNIMPLEMENTED();
7847 break;
7848 case FMLS_z_zzzi_h:
7849 VIXL_UNIMPLEMENTED();
7850 break;
7851 case FMLS_z_zzzi_s:
7852 VIXL_UNIMPLEMENTED();
7853 break;
7854 default:
7855 VIXL_UNIMPLEMENTED();
7856 break;
7857 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007858}
7859
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007860void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007861 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007862 switch (instr->Mask(SVEFPConvertToIntMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007863 case FCVTZS_z_p_z_d2w:
7864 VIXL_UNIMPLEMENTED();
7865 break;
7866 case FCVTZS_z_p_z_d2x:
7867 VIXL_UNIMPLEMENTED();
7868 break;
7869 case FCVTZS_z_p_z_fp162h:
7870 VIXL_UNIMPLEMENTED();
7871 break;
7872 case FCVTZS_z_p_z_fp162w:
7873 VIXL_UNIMPLEMENTED();
7874 break;
7875 case FCVTZS_z_p_z_fp162x:
7876 VIXL_UNIMPLEMENTED();
7877 break;
7878 case FCVTZS_z_p_z_s2w:
7879 VIXL_UNIMPLEMENTED();
7880 break;
7881 case FCVTZS_z_p_z_s2x:
7882 VIXL_UNIMPLEMENTED();
7883 break;
7884 case FCVTZU_z_p_z_d2w:
7885 VIXL_UNIMPLEMENTED();
7886 break;
7887 case FCVTZU_z_p_z_d2x:
7888 VIXL_UNIMPLEMENTED();
7889 break;
7890 case FCVTZU_z_p_z_fp162h:
7891 VIXL_UNIMPLEMENTED();
7892 break;
7893 case FCVTZU_z_p_z_fp162w:
7894 VIXL_UNIMPLEMENTED();
7895 break;
7896 case FCVTZU_z_p_z_fp162x:
7897 VIXL_UNIMPLEMENTED();
7898 break;
7899 case FCVTZU_z_p_z_s2w:
7900 VIXL_UNIMPLEMENTED();
7901 break;
7902 case FCVTZU_z_p_z_s2x:
7903 VIXL_UNIMPLEMENTED();
7904 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007905 default:
7906 VIXL_UNIMPLEMENTED();
7907 break;
7908 }
7909}
7910
7911void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
7912 USE(instr);
7913 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007914 case FCVT_z_p_z_d2h:
7915 VIXL_UNIMPLEMENTED();
7916 break;
7917 case FCVT_z_p_z_d2s:
7918 VIXL_UNIMPLEMENTED();
7919 break;
7920 case FCVT_z_p_z_h2d:
7921 VIXL_UNIMPLEMENTED();
7922 break;
7923 case FCVT_z_p_z_h2s:
7924 VIXL_UNIMPLEMENTED();
7925 break;
7926 case FCVT_z_p_z_s2d:
7927 VIXL_UNIMPLEMENTED();
7928 break;
7929 case FCVT_z_p_z_s2h:
7930 VIXL_UNIMPLEMENTED();
7931 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007932 default:
7933 VIXL_UNIMPLEMENTED();
7934 break;
7935 }
7936}
7937
7938void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
7939 USE(instr);
7940 switch (instr->Mask(SVEFPUnaryOpMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007941 case FRECPX_z_p_z:
7942 VIXL_UNIMPLEMENTED();
7943 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007944 case FSQRT_z_p_z:
7945 VIXL_UNIMPLEMENTED();
7946 break;
7947 default:
7948 VIXL_UNIMPLEMENTED();
7949 break;
7950 }
7951}
7952
7953void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
7954 USE(instr);
7955 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007956 case FRINTA_z_p_z:
7957 VIXL_UNIMPLEMENTED();
7958 break;
7959 case FRINTI_z_p_z:
7960 VIXL_UNIMPLEMENTED();
7961 break;
7962 case FRINTM_z_p_z:
7963 VIXL_UNIMPLEMENTED();
7964 break;
7965 case FRINTN_z_p_z:
7966 VIXL_UNIMPLEMENTED();
7967 break;
7968 case FRINTP_z_p_z:
7969 VIXL_UNIMPLEMENTED();
7970 break;
7971 case FRINTX_z_p_z:
7972 VIXL_UNIMPLEMENTED();
7973 break;
7974 case FRINTZ_z_p_z:
7975 VIXL_UNIMPLEMENTED();
7976 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007977 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007978 VIXL_UNIMPLEMENTED();
7979 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01007980 }
7981}
7982
7983void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
7984 USE(instr);
7985 switch (instr->Mask(SVEIntConvertToFPMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007986 case SCVTF_z_p_z_h2fp16:
7987 VIXL_UNIMPLEMENTED();
7988 break;
7989 case SCVTF_z_p_z_w2d:
7990 VIXL_UNIMPLEMENTED();
7991 break;
7992 case SCVTF_z_p_z_w2fp16:
7993 VIXL_UNIMPLEMENTED();
7994 break;
7995 case SCVTF_z_p_z_w2s:
7996 VIXL_UNIMPLEMENTED();
7997 break;
7998 case SCVTF_z_p_z_x2d:
7999 VIXL_UNIMPLEMENTED();
8000 break;
8001 case SCVTF_z_p_z_x2fp16:
8002 VIXL_UNIMPLEMENTED();
8003 break;
8004 case SCVTF_z_p_z_x2s:
8005 VIXL_UNIMPLEMENTED();
8006 break;
8007 case UCVTF_z_p_z_h2fp16:
8008 VIXL_UNIMPLEMENTED();
8009 break;
8010 case UCVTF_z_p_z_w2d:
8011 VIXL_UNIMPLEMENTED();
8012 break;
8013 case UCVTF_z_p_z_w2fp16:
8014 VIXL_UNIMPLEMENTED();
8015 break;
8016 case UCVTF_z_p_z_w2s:
8017 VIXL_UNIMPLEMENTED();
8018 break;
8019 case UCVTF_z_p_z_x2d:
8020 VIXL_UNIMPLEMENTED();
8021 break;
8022 case UCVTF_z_p_z_x2fp16:
8023 VIXL_UNIMPLEMENTED();
8024 break;
8025 case UCVTF_z_p_z_x2s:
8026 VIXL_UNIMPLEMENTED();
8027 break;
8028 default:
8029 VIXL_UNIMPLEMENTED();
8030 break;
8031 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008032}
8033
8034void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
8035 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008036 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8037 case FRECPE_z_z:
8038 VIXL_UNIMPLEMENTED();
8039 break;
8040 case FRSQRTE_z_z:
8041 VIXL_UNIMPLEMENTED();
8042 break;
8043 default:
8044 VIXL_UNIMPLEMENTED();
8045 break;
8046 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008047}
8048
8049void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
8050 USE(instr);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008051
8052 VectorFormat vform = instr->GetSVEVectorFormat();
8053 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
8054
8055 int count = CountActiveLanes(vform, pg);
8056
8057 if (instr->ExtractBit(11) == 0) {
8058 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8059 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8060 case DECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008061 sub_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008062 break;
8063 case INCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008064 add_uint(vform, zdn, zdn, count);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008065 break;
8066 case SQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008067 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008068 break;
8069 case SQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008070 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008071 break;
8072 case UQDECP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008073 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008074 break;
8075 case UQINCP_z_p_z:
Jacob Bramleyb28f6172019-10-02 12:12:35 +01008076 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008077 break;
8078 default:
8079 VIXL_UNIMPLEMENTED();
8080 break;
8081 }
8082 } else {
8083 bool is_saturating = (instr->ExtractBit(18) == 0);
8084 bool decrement =
8085 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
8086 bool is_signed = (instr->ExtractBit(16) == 0);
8087 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
8088 unsigned width = sf ? kXRegSize : kWRegSize;
8089
8090 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8091 case DECP_r_p_r:
8092 case INCP_r_p_r:
8093 case SQDECP_r_p_r_sx:
8094 case SQDECP_r_p_r_x:
8095 case SQINCP_r_p_r_sx:
8096 case SQINCP_r_p_r_x:
8097 case UQDECP_r_p_r_uw:
8098 case UQDECP_r_p_r_x:
8099 case UQINCP_r_p_r_uw:
8100 case UQINCP_r_p_r_x:
8101 WriteXRegister(instr->GetRd(),
8102 IncDecN(ReadXRegister(instr->GetRd()),
8103 decrement ? -count : count,
8104 width,
8105 is_saturating,
8106 is_signed));
8107 break;
8108 default:
8109 VIXL_UNIMPLEMENTED();
8110 break;
8111 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008112 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008113}
8114
Jacob Bramleyd1686cb2019-05-28 17:39:05 +01008115uint64_t Simulator::IncDecN(uint64_t acc,
8116 int64_t delta,
8117 unsigned n,
8118 bool is_saturating,
8119 bool is_signed) {
8120 VIXL_ASSERT(n <= 64);
8121 VIXL_ASSERT(IsIntN(n, delta));
8122
8123 uint64_t sign_mask = UINT64_C(1) << (n - 1);
8124 uint64_t mask = GetUintMask(n);
8125
8126 acc &= mask; // Ignore initial accumulator high bits.
8127 uint64_t result = (acc + delta) & mask;
8128
8129 bool acc_negative = ((acc & sign_mask) != 0);
8130 bool delta_negative = delta < 0;
8131 bool result_negative = ((result & sign_mask) != 0);
8132
8133 if (is_saturating) {
8134 if (is_signed) {
8135 // If the signs of the operands are the same, but different from the
8136 // result, there was an overflow.
8137 if ((acc_negative == delta_negative) &&
8138 (acc_negative != result_negative)) {
8139 if (result_negative) {
8140 // Saturate to [..., INT<n>_MAX].
8141 result_negative = false;
8142 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
8143 } else {
8144 // Saturate to [INT<n>_MIN, ...].
8145 result_negative = true;
8146 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
8147 }
8148 }
8149 } else {
8150 if ((delta < 0) && (result > acc)) {
8151 // Saturate to [0, ...].
8152 result = 0;
8153 } else if ((delta > 0) && (result < acc)) {
8154 // Saturate to [..., UINT<n>_MAX].
8155 result = mask;
8156 }
8157 }
8158 }
8159
8160 // Sign-extend if necessary.
8161 if (result_negative && is_signed) result |= ~mask;
8162
8163 return result;
8164}
8165
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008166void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
8167 USE(instr);
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008168 VectorFormat vform = instr->GetSVEVectorFormat();
8169 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008170 switch (instr->Mask(SVEIndexGenerationMask)) {
8171 case INDEX_z_ii:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008172 case INDEX_z_ir:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008173 case INDEX_z_ri:
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008174 case INDEX_z_rr: {
8175 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
8176 : instr->ExtractSignedBits(9, 5);
8177 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
8178 : instr->ExtractSignedBits(20, 16);
8179 index(vform, zd, start, step);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008180 break;
Jacob Bramleycd8148c2019-07-11 18:43:20 +01008181 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008182 default:
8183 VIXL_UNIMPLEMENTED();
8184 break;
8185 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008186}
8187
8188void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
8189 USE(instr);
TatWai Chong845246b2019-08-08 00:01:58 -07008190 VectorFormat vform = instr->GetSVEVectorFormat();
8191 SimVRegister& zd = ReadVRegister(instr->GetRd());
8192 SimVRegister& zn = ReadVRegister(instr->GetRn());
8193 SimVRegister& zm = ReadVRegister(instr->GetRm());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008194 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8195 case ADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008196 add(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008197 break;
8198 case SQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008199 add(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008200 break;
8201 case SQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008202 sub(vform, zd, zn, zm).SignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008203 break;
8204 case SUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008205 sub(vform, zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008206 break;
8207 case UQADD_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008208 add(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008209 break;
8210 case UQSUB_z_zz:
TatWai Chong845246b2019-08-08 00:01:58 -07008211 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008212 break;
8213 default:
8214 VIXL_UNIMPLEMENTED();
8215 break;
8216 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008217}
8218
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008219void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008220 const Instruction* instr) {
TatWai Chong13634762019-07-16 16:20:45 -07008221 VectorFormat vform = instr->GetSVEVectorFormat();
8222 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8223 SimVRegister& zm = ReadVRegister(instr->GetRn());
8224 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8225 SimVRegister result;
8226
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008227 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008228 case ADD_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008229 add(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008230 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008231 case SUBR_z_p_zz:
8232 sub(vform, result, zm, zdn);
8233 break;
8234 case SUB_z_p_zz:
8235 sub(vform, result, zdn, zm);
8236 break;
8237 default:
8238 VIXL_UNIMPLEMENTED();
8239 break;
8240 }
8241 mov_merging(vform, zdn, pg, result);
8242}
8243
8244void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
8245 VectorFormat vform = instr->GetSVEVectorFormat();
8246 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8247 SimVRegister& zm = ReadVRegister(instr->GetRn());
8248 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8249 SimVRegister result;
8250
8251 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008252 case AND_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008253 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008254 break;
8255 case BIC_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008256 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008257 break;
8258 case EOR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008259 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008260 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008261 case ORR_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008262 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008263 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008264 default:
8265 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008266 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008267 }
8268 mov_merging(vform, zdn, pg, result);
8269}
8270
8271void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
8272 VectorFormat vform = instr->GetSVEVectorFormat();
8273 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8274 SimVRegister& zm = ReadVRegister(instr->GetRn());
8275 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8276 SimVRegister result;
8277
8278 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
8279 case MUL_z_p_zz:
8280 mul(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008281 break;
8282 case SMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008283 smulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008284 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008285 case UMULH_z_p_zz:
TatWai Chong13634762019-07-16 16:20:45 -07008286 umulh(vform, result, zdn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008287 break;
8288 default:
8289 VIXL_UNIMPLEMENTED();
8290 break;
8291 }
TatWai Chong13634762019-07-16 16:20:45 -07008292 mov_merging(vform, zdn, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008293}
8294
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008295void Simulator::VisitSVEIntMinMaxDifference_Predicated(
8296 const Instruction* instr) {
8297 VectorFormat vform = instr->GetSVEVectorFormat();
8298 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8299 SimVRegister& zm = ReadVRegister(instr->GetRn());
8300 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8301 SimVRegister result;
8302
8303 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
8304 case SABD_z_p_zz:
8305 absdiff(vform, result, zdn, zm, true);
8306 break;
8307 case SMAX_z_p_zz:
8308 smax(vform, result, zdn, zm);
8309 break;
8310 case SMIN_z_p_zz:
8311 smin(vform, result, zdn, zm);
8312 break;
8313 case UABD_z_p_zz:
8314 absdiff(vform, result, zdn, zm, false);
8315 break;
8316 case UMAX_z_p_zz:
8317 umax(vform, result, zdn, zm);
8318 break;
8319 case UMIN_z_p_zz:
8320 umin(vform, result, zdn, zm);
8321 break;
8322 default:
8323 VIXL_UNIMPLEMENTED();
8324 break;
8325 }
8326 mov_merging(vform, zdn, pg, result);
8327}
8328
8329void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
8330 VectorFormat vform = instr->GetSVEVectorFormat();
8331 SimVRegister& zd = ReadVRegister(instr->GetRd());
8332 SimVRegister scratch;
8333
8334 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
8335 case MUL_z_zi:
8336 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
8337 mul(vform, zd, zd, scratch);
8338 break;
8339 default:
8340 VIXL_UNIMPLEMENTED();
8341 break;
8342 }
8343}
8344
8345void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
8346 VectorFormat vform = instr->GetSVEVectorFormat();
8347 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8348 SimVRegister& zm = ReadVRegister(instr->GetRn());
8349 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8350 SimVRegister result;
8351
8352 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
8353
8354 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
8355 case SDIVR_z_p_zz:
8356 sdiv(vform, result, zm, zdn);
8357 break;
8358 case SDIV_z_p_zz:
8359 sdiv(vform, result, zdn, zm);
8360 break;
8361 case UDIVR_z_p_zz:
8362 udiv(vform, result, zm, zdn);
8363 break;
8364 case UDIV_z_p_zz:
8365 udiv(vform, result, zdn, zm);
8366 break;
8367 default:
8368 VIXL_UNIMPLEMENTED();
8369 break;
8370 }
8371 mov_merging(vform, zdn, pg, result);
8372}
8373
8374void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
8375 VectorFormat vform = instr->GetSVEVectorFormat();
8376 SimVRegister& zd = ReadVRegister(instr->GetRd());
8377 SimVRegister scratch;
8378
8379 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
8380 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
8381
8382 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
8383 case SMAX_z_zi:
8384 dup_immediate(vform, scratch, signed_imm);
8385 smax(vform, zd, zd, scratch);
8386 break;
8387 case SMIN_z_zi:
8388 dup_immediate(vform, scratch, signed_imm);
8389 smin(vform, zd, zd, scratch);
8390 break;
8391 case UMAX_z_zi:
8392 dup_immediate(vform, scratch, unsigned_imm);
8393 umax(vform, zd, zd, scratch);
8394 break;
8395 case UMIN_z_zi:
8396 dup_immediate(vform, scratch, unsigned_imm);
8397 umin(vform, zd, zd, scratch);
8398 break;
8399 default:
8400 VIXL_UNIMPLEMENTED();
8401 break;
8402 }
8403}
8404
8405void Simulator::VisitSVEIntCompareScalarCountAndLimit(
8406 const Instruction* instr) {
TatWai Chongc844bb22019-06-10 15:32:53 -07008407 unsigned rn_code = instr->GetRn();
8408 unsigned rm_code = instr->GetRm();
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008409 SimPRegister& pd = ReadPRegister(instr->GetPd());
8410 VectorFormat vform = instr->GetSVEVectorFormat();
8411 bool is_64_bit = instr->ExtractBit(12) == 1;
8412 int64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8413 int64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
TatWai Chongc844bb22019-06-10 15:32:53 -07008414
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008415 bool last = true;
8416 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
8417 bool cond = false;
8418 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
8419 case WHILELE_p_p_rr:
8420 cond = src1 <= src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008421 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008422 case WHILELO_p_p_rr:
8423 cond = static_cast<uint64_t>(src1) < static_cast<uint64_t>(src2);
8424 break;
8425 case WHILELS_p_p_rr:
8426 cond = static_cast<uint64_t>(src1) <= static_cast<uint64_t>(src2);
8427 break;
8428 case WHILELT_p_p_rr:
8429 cond = src1 < src2;
TatWai Chongc844bb22019-06-10 15:32:53 -07008430 break;
8431 default:
TatWai Chongc844bb22019-06-10 15:32:53 -07008432 VIXL_UNIMPLEMENTED();
8433 break;
8434 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008435 last = last && cond;
8436 LogicPRegister dst(pd);
8437 dst.SetActive(vform, lane, last);
8438 src1 += 1;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008439 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008440
8441 PredTest(vform, GetPTrue(), pd);
8442 LogSystemRegister(NZCV);
8443}
8444
8445void Simulator::VisitSVEConditionallyTerminateScalars(
8446 const Instruction* instr) {
8447 unsigned rn_code = instr->GetRn();
8448 unsigned rm_code = instr->GetRm();
8449 bool is_64_bit = instr->ExtractBit(22) == 1;
8450 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
8451 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
8452 bool term;
8453 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
8454 case CTERMEQ_rr:
8455 term = src1 == src2;
8456 break;
8457 case CTERMNE_rr:
8458 term = src1 != src2;
8459 break;
8460 default:
8461 term = false;
8462 VIXL_UNIMPLEMENTED();
8463 break;
8464 }
8465 ReadNzcv().SetN(term ? 1 : 0);
8466 ReadNzcv().SetV(term ? 0 : !ReadC());
TatWai Chongc844bb22019-06-10 15:32:53 -07008467 LogSystemRegister(NZCV);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008468}
8469
8470void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
8471 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008472 bool commute_inputs = false;
8473 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008474 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
8475 case CMPEQ_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008476 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008477 break;
8478 case CMPGE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008479 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008480 break;
8481 case CMPGT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008482 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008483 break;
8484 case CMPLE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008485 cond = ge;
8486 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008487 break;
8488 case CMPLT_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008489 cond = gt;
8490 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008491 break;
8492 case CMPNE_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008493 cond = ne;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008494 break;
8495 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008496 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008497 VIXL_UNIMPLEMENTED();
8498 break;
8499 }
TatWai Chong302729c2019-06-14 16:18:51 -07008500
8501 VectorFormat vform = instr->GetSVEVectorFormat();
8502 SimVRegister src2;
8503 dup_immediate(vform,
8504 src2,
8505 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
8506 SVEIntCompareVectorsHelper(cond,
8507 vform,
8508 ReadPRegister(instr->GetPd()),
8509 ReadPRegister(instr->GetPgLow8()),
8510 commute_inputs ? src2
8511 : ReadVRegister(instr->GetRn()),
8512 commute_inputs ? ReadVRegister(instr->GetRn())
8513 : src2);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008514}
8515
8516void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
8517 USE(instr);
TatWai Chong302729c2019-06-14 16:18:51 -07008518 bool commute_inputs = false;
8519 Condition cond;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008520 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8521 case CMPHI_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008522 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008523 break;
8524 case CMPHS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008525 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008526 break;
8527 case CMPLO_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008528 cond = hi;
8529 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008530 break;
8531 case CMPLS_p_p_zi:
TatWai Chong302729c2019-06-14 16:18:51 -07008532 cond = hs;
8533 commute_inputs = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008534 break;
8535 default:
TatWai Chong302729c2019-06-14 16:18:51 -07008536 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008537 VIXL_UNIMPLEMENTED();
8538 break;
8539 }
TatWai Chong302729c2019-06-14 16:18:51 -07008540
8541 VectorFormat vform = instr->GetSVEVectorFormat();
8542 SimVRegister src2;
8543 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
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::VisitSVEIntCompareVectors(const Instruction* instr) {
8555 USE(instr);
TatWai Chong96713fe2019-06-04 16:39:37 -07008556
8557 Instr op = instr->Mask(SVEIntCompareVectorsMask);
8558 bool is_wide_elements = false;
8559 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008560 case CMPEQ_p_p_zw:
TatWai Chong96713fe2019-06-04 16:39:37 -07008561 case CMPGE_p_p_zw:
8562 case CMPGT_p_p_zw:
8563 case CMPHI_p_p_zw:
8564 case CMPHS_p_p_zw:
8565 case CMPLE_p_p_zw:
8566 case CMPLO_p_p_zw:
8567 case CMPLS_p_p_zw:
8568 case CMPLT_p_p_zw:
8569 case CMPNE_p_p_zw:
8570 is_wide_elements = true;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008571 break;
TatWai Chong96713fe2019-06-04 16:39:37 -07008572 }
8573
TatWai Chong302729c2019-06-14 16:18:51 -07008574 Condition cond;
TatWai Chong96713fe2019-06-04 16:39:37 -07008575 switch (op) {
8576 case CMPEQ_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008577 case CMPEQ_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008578 cond = eq;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008579 break;
8580 case CMPGE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008581 case CMPGE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008582 cond = ge;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008583 break;
8584 case CMPGT_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008585 case CMPGT_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008586 cond = gt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008587 break;
8588 case CMPHI_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008589 case CMPHI_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008590 cond = hi;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008591 break;
8592 case CMPHS_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008593 case CMPHS_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008594 cond = hs;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008595 break;
8596 case CMPNE_p_p_zw:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008597 case CMPNE_p_p_zz:
TatWai Chong302729c2019-06-14 16:18:51 -07008598 cond = ne;
TatWai Chong96713fe2019-06-04 16:39:37 -07008599 break;
8600 case CMPLE_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008601 cond = le;
TatWai Chong96713fe2019-06-04 16:39:37 -07008602 break;
8603 case CMPLO_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008604 cond = lo;
TatWai Chong96713fe2019-06-04 16:39:37 -07008605 break;
8606 case CMPLS_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008607 cond = ls;
TatWai Chong96713fe2019-06-04 16:39:37 -07008608 break;
8609 case CMPLT_p_p_zw:
TatWai Chong302729c2019-06-14 16:18:51 -07008610 cond = lt;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008611 break;
8612 default:
8613 VIXL_UNIMPLEMENTED();
TatWai Chong302729c2019-06-14 16:18:51 -07008614 cond = al;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008615 break;
8616 }
TatWai Chong96713fe2019-06-04 16:39:37 -07008617
TatWai Chong302729c2019-06-14 16:18:51 -07008618 SVEIntCompareVectorsHelper(cond,
TatWai Chong96713fe2019-06-04 16:39:37 -07008619 instr->GetSVEVectorFormat(),
8620 ReadPRegister(instr->GetPd()),
8621 ReadPRegister(instr->GetPgLow8()),
8622 ReadVRegister(instr->GetRn()),
8623 ReadVRegister(instr->GetRm()),
8624 is_wide_elements);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008625}
8626
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008627void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008628 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008629 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008630 case FEXPA_z_z:
8631 VIXL_UNIMPLEMENTED();
8632 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008633 default:
8634 VIXL_UNIMPLEMENTED();
8635 break;
8636 }
8637}
8638
8639void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
8640 USE(instr);
8641 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008642 case FTSSEL_z_zz:
8643 VIXL_UNIMPLEMENTED();
8644 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008645 default:
8646 VIXL_UNIMPLEMENTED();
8647 break;
8648 }
8649}
8650
8651void Simulator::VisitSVEConstructivePrefix_Unpredicated(
8652 const Instruction* instr) {
8653 SimVRegister& zd = ReadVRegister(instr->GetRd());
8654 SimVRegister& zn = ReadVRegister(instr->GetRn());
8655
8656 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008657 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008658 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
8659 // Record the movprfx, so the next ExecuteInstruction() can check it.
8660 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008661 break;
8662 default:
8663 VIXL_UNIMPLEMENTED();
8664 break;
8665 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008666}
8667
8668void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
8669 USE(instr);
Jacob Bramley22023df2019-05-14 17:55:43 +01008670 VectorFormat vform = instr->GetSVEVectorFormat();
8671
8672 SimVRegister& zd = ReadVRegister(instr->GetRd());
8673 SimVRegister& zm = ReadVRegister(instr->GetRm());
8674
8675 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008676 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008677 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008678 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008679 break;
8680 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008681 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008682 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008683 case MAD_z_p_zzz:
8684 // 'za' is encoded in 'Rn'.
8685 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008686 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008687 case MSB_z_p_zzz: {
8688 // 'za' is encoded in 'Rn'.
8689 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
8690 break;
8691 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008692 default:
8693 VIXL_UNIMPLEMENTED();
8694 break;
8695 }
Jacob Bramley22023df2019-05-14 17:55:43 +01008696 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008697}
8698
8699void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
8700 USE(instr);
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008701
8702 VectorFormat vform = instr->GetSVEVectorFormat();
8703 SimVRegister& zda = ReadVRegister(instr->GetRd());
8704 SimVRegister& zn = ReadVRegister(instr->GetRn());
8705 SimVRegister& zm = ReadVRegister(instr->GetRm());
8706
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008707 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8708 case SDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008709 sdot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008710 break;
8711 case UDOT_z_zzz:
TatWai Chong4d2a4e92019-10-23 16:19:32 -07008712 udot(vform, zda, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008713 break;
8714 default:
8715 VIXL_UNIMPLEMENTED();
8716 break;
8717 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008718}
8719
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008720void Simulator::VisitSVEMovprfx(const Instruction* instr) {
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008721 VectorFormat vform = instr->GetSVEVectorFormat();
8722 SimVRegister& zn = ReadVRegister(instr->GetRn());
8723 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8724 SimVRegister& zd = ReadVRegister(instr->GetRd());
8725
8726 switch (instr->Mask(SVEMovprfxMask)) {
8727 case MOVPRFX_z_p_z:
8728 if (instr->ExtractBit(16)) {
8729 mov_merging(vform, zd, pg, zn);
8730 } else {
8731 mov_zeroing(vform, zd, pg, zn);
8732 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008733
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008734 // Record the movprfx, so the next ExecuteInstruction() can check it.
8735 movprfx_ = instr;
8736 break;
8737 default:
8738 VIXL_UNIMPLEMENTED();
8739 break;
8740 }
8741}
8742
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008743void Simulator::VisitSVEIntReduction(const Instruction* instr) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008744 VectorFormat vform = instr->GetSVEVectorFormat();
TatWai Chong6f111bc2019-10-07 09:20:37 +01008745 SimVRegister& vd = ReadVRegister(instr->GetRd());
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008746 SimVRegister& zn = ReadVRegister(instr->GetRn());
8747 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8748
8749 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
8750 switch (instr->Mask(SVEIntReductionLogicalMask)) {
8751 case ANDV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008752 andv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008753 break;
8754 case EORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008755 eorv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008756 break;
8757 case ORV_r_p_z:
TatWai Chong6f111bc2019-10-07 09:20:37 +01008758 orv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008759 break;
8760 default:
8761 VIXL_UNIMPLEMENTED();
8762 break;
8763 }
8764 } else {
8765 switch (instr->Mask(SVEIntReductionMask)) {
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008766 case SADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008767 saddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008768 break;
8769 case SMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008770 smaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008771 break;
8772 case SMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008773 sminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008774 break;
8775 case UADDV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008776 uaddv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008777 break;
8778 case UMAXV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008779 umaxv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008780 break;
8781 case UMINV_r_p_z:
TatWai Chongb2d8d1f2019-10-21 15:19:31 -07008782 uminv(vform, vd, pg, zn);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008783 break;
8784 default:
8785 VIXL_UNIMPLEMENTED();
8786 break;
8787 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008788 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008789}
8790
8791void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
8792 USE(instr);
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008793
8794 VectorFormat vform = instr->GetSVEVectorFormat();
8795 SimVRegister& zn = ReadVRegister(instr->GetRn());
8796
8797 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008798 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
8799 case ABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008800 abs(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008801 break;
8802 case CLS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008803 cls(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008804 break;
8805 case CLZ_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008806 clz(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008807 break;
8808 case CNOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008809 cnot(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008810 break;
8811 case CNT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008812 cnt(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008813 break;
8814 case FABS_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008815 fabs_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008816 break;
8817 case FNEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008818 fneg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008819 break;
8820 case NEG_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008821 neg(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008822 break;
8823 case NOT_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008824 not_(vform, result, zn);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008825 break;
8826 case SXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008827 case SXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008828 case SXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008829 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008830 break;
8831 case UXTB_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008832 case UXTH_z_p_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008833 case UXTW_z_p_z:
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008834 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008835 break;
8836 default:
8837 VIXL_UNIMPLEMENTED();
8838 break;
8839 }
Jacob Bramleybc21a0d2019-09-20 18:49:15 +01008840
8841 SimVRegister& zd = ReadVRegister(instr->GetRd());
8842 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8843 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008844}
8845
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008846void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008847 // There is only one instruction in this group.
8848 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
8849
8850 VectorFormat vform = instr->GetSVEVectorFormat();
8851 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
8852 SimVRegister& zd = ReadVRegister(instr->GetRd());
8853
8854 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008855 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008856 case FCPY_z_p_i: {
8857 int imm8 = instr->ExtractBits(12, 5);
8858 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
8859 Instruction::Imm8ToFP64(imm8));
8860 dup_immediate(vform, result, value);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008861 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008862 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008863 default:
8864 VIXL_UNIMPLEMENTED();
8865 break;
8866 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +01008867 mov_merging(vform, zd, pg, result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008868}
8869
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008870void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
8871 const Instruction* instr) {
TatWai Chong6995bfd2019-09-26 10:48:05 +01008872 VectorFormat vform = instr->GetSVEVectorFormat();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01008873 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong6995bfd2019-09-26 10:48:05 +01008874 SimVRegister scratch;
8875
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008876 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
8877 imm <<= instr->ExtractBit(13) * 8;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008878
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008879 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008880 case ADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008881 add_uint(vform, zd, zd, imm);
8882 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008883 case SQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008884 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
8885 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008886 case SQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008887 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
8888 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008889 case SUBR_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008890 dup_immediate(vform, scratch, imm);
TatWai Chong6995bfd2019-09-26 10:48:05 +01008891 sub(vform, zd, scratch, zd);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008892 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008893 case SUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008894 sub_uint(vform, zd, zd, imm);
8895 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008896 case UQADD_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008897 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
8898 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008899 case UQSUB_z_zi:
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008900 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
8901 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008902 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008903 break;
TatWai Chong6995bfd2019-09-26 10:48:05 +01008904 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008905}
TatWai Chong6995bfd2019-09-26 10:48:05 +01008906
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008907void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
8908 SimVRegister& zd = ReadVRegister(instr->GetRd());
8909
8910 int64_t imm = instr->GetImmSVEIntWideSigned();
8911 imm <<= instr->ExtractBit(13) * 8;
8912
8913 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
8914 case DUP_z_i:
8915 dup_immediate(instr->GetSVEVectorFormat(), zd, imm);
8916 break;
8917 default:
8918 VIXL_UNIMPLEMENTED();
8919 break;
8920 }
8921}
8922
8923void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
8924 VectorFormat vform = instr->GetSVEVectorFormat();
8925 SimVRegister& zd = ReadVRegister(instr->GetRd());
8926
8927 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008928 case FDUP_z_i:
TatWai Chong6995bfd2019-09-26 10:48:05 +01008929 switch (vform) {
8930 case kFormatVnH:
8931 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
8932 break;
8933 case kFormatVnS:
8934 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
8935 break;
8936 case kFormatVnD:
8937 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
8938 break;
8939 default:
8940 VIXL_UNIMPLEMENTED();
8941 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008942 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008943 default:
8944 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008945 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008946 }
8947}
8948
8949void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
8950 const Instruction* instr) {
8951 USE(instr);
8952 switch (instr->Mask(
8953 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
8954 case LD1H_z_p_bz_s_x32_scaled:
8955 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008956 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008957 case LD1SH_z_p_bz_s_x32_scaled:
8958 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008959 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008960 case LDFF1H_z_p_bz_s_x32_scaled:
8961 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008962 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008963 case LDFF1SH_z_p_bz_s_x32_scaled:
8964 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008965 break;
8966 default:
8967 VIXL_UNIMPLEMENTED();
8968 break;
8969 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008970}
8971
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008972void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008973 const Instruction* instr) {
8974 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01008975 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
8976 case LD1B_z_p_bz_s_x32_unscaled:
8977 VIXL_UNIMPLEMENTED();
8978 break;
8979 case LD1H_z_p_bz_s_x32_unscaled:
8980 VIXL_UNIMPLEMENTED();
8981 break;
8982 case LD1SB_z_p_bz_s_x32_unscaled:
8983 VIXL_UNIMPLEMENTED();
8984 break;
8985 case LD1SH_z_p_bz_s_x32_unscaled:
8986 VIXL_UNIMPLEMENTED();
8987 break;
8988 case LD1W_z_p_bz_s_x32_unscaled:
8989 VIXL_UNIMPLEMENTED();
8990 break;
8991 case LDFF1B_z_p_bz_s_x32_unscaled:
8992 VIXL_UNIMPLEMENTED();
8993 break;
8994 case LDFF1H_z_p_bz_s_x32_unscaled:
8995 VIXL_UNIMPLEMENTED();
8996 break;
8997 case LDFF1SB_z_p_bz_s_x32_unscaled:
8998 VIXL_UNIMPLEMENTED();
8999 break;
9000 case LDFF1SH_z_p_bz_s_x32_unscaled:
9001 VIXL_UNIMPLEMENTED();
9002 break;
9003 case LDFF1W_z_p_bz_s_x32_unscaled:
9004 VIXL_UNIMPLEMENTED();
9005 break;
9006 default:
9007 VIXL_UNIMPLEMENTED();
9008 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009009 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009010}
9011
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009012void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
9013 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009014 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009015 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
9016 case LD1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009017 VIXL_UNIMPLEMENTED();
9018 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009019 case LD1H_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009020 VIXL_UNIMPLEMENTED();
9021 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009022 case LD1SB_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009023 VIXL_UNIMPLEMENTED();
9024 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009025 case LD1SH_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009026 VIXL_UNIMPLEMENTED();
9027 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009028 case LD1W_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009029 VIXL_UNIMPLEMENTED();
9030 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009031 case LDFF1B_z_p_ai_s:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009032 VIXL_UNIMPLEMENTED();
9033 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009034 case LDFF1H_z_p_ai_s:
9035 VIXL_UNIMPLEMENTED();
9036 break;
9037 case LDFF1SB_z_p_ai_s:
9038 VIXL_UNIMPLEMENTED();
9039 break;
9040 case LDFF1SH_z_p_ai_s:
9041 VIXL_UNIMPLEMENTED();
9042 break;
9043 case LDFF1W_z_p_ai_s:
9044 VIXL_UNIMPLEMENTED();
9045 break;
9046 default:
9047 VIXL_UNIMPLEMENTED();
9048 break;
9049 }
9050}
9051
9052void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
9053 const Instruction* instr) {
9054 USE(instr);
9055 switch (
9056 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
9057 case LD1W_z_p_bz_s_x32_scaled:
9058 VIXL_UNIMPLEMENTED();
9059 break;
9060 case LDFF1W_z_p_bz_s_x32_scaled:
9061 VIXL_UNIMPLEMENTED();
9062 break;
9063 default:
9064 VIXL_UNIMPLEMENTED();
9065 break;
9066 }
9067}
9068
9069void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
9070 const Instruction* instr) {
9071 USE(instr);
9072 switch (
9073 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
9074 case PRFB_i_p_bz_s_x32_scaled:
9075 VIXL_UNIMPLEMENTED();
9076 break;
9077 case PRFD_i_p_bz_s_x32_scaled:
9078 VIXL_UNIMPLEMENTED();
9079 break;
9080 case PRFH_i_p_bz_s_x32_scaled:
9081 VIXL_UNIMPLEMENTED();
9082 break;
9083 case PRFW_i_p_bz_s_x32_scaled:
9084 VIXL_UNIMPLEMENTED();
9085 break;
9086 default:
9087 VIXL_UNIMPLEMENTED();
9088 break;
9089 }
9090}
9091
9092void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
9093 const Instruction* instr) {
9094 USE(instr);
9095 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
9096 case PRFB_i_p_ai_s:
9097 VIXL_UNIMPLEMENTED();
9098 break;
9099 case PRFD_i_p_ai_s:
9100 VIXL_UNIMPLEMENTED();
9101 break;
9102 case PRFH_i_p_ai_s:
9103 VIXL_UNIMPLEMENTED();
9104 break;
9105 case PRFW_i_p_ai_s:
9106 VIXL_UNIMPLEMENTED();
9107 break;
9108 default:
9109 VIXL_UNIMPLEMENTED();
9110 break;
9111 }
9112}
9113
9114void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
9115 const Instruction* instr) {
9116 USE(instr);
9117 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
9118 case PRFB_i_p_bi_s:
9119 VIXL_UNIMPLEMENTED();
9120 break;
9121 case PRFD_i_p_bi_s:
9122 VIXL_UNIMPLEMENTED();
9123 break;
9124 case PRFH_i_p_bi_s:
9125 VIXL_UNIMPLEMENTED();
9126 break;
9127 case PRFW_i_p_bi_s:
9128 VIXL_UNIMPLEMENTED();
9129 break;
9130 default:
9131 VIXL_UNIMPLEMENTED();
9132 break;
9133 }
9134}
9135
9136void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
9137 const Instruction* instr) {
9138 USE(instr);
9139 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
9140 case PRFB_i_p_br_s:
9141 VIXL_UNIMPLEMENTED();
9142 break;
9143 case PRFD_i_p_br_s:
9144 VIXL_UNIMPLEMENTED();
9145 break;
9146 case PRFH_i_p_br_s:
9147 VIXL_UNIMPLEMENTED();
9148 break;
9149 case PRFW_i_p_br_s:
9150 VIXL_UNIMPLEMENTED();
9151 break;
9152 default:
9153 VIXL_UNIMPLEMENTED();
9154 break;
9155 }
9156}
9157
9158void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
9159 USE(instr);
9160 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
9161 case LD1RB_z_p_bi_u16:
9162 VIXL_UNIMPLEMENTED();
9163 break;
9164 case LD1RB_z_p_bi_u32:
9165 VIXL_UNIMPLEMENTED();
9166 break;
9167 case LD1RB_z_p_bi_u64:
9168 VIXL_UNIMPLEMENTED();
9169 break;
9170 case LD1RB_z_p_bi_u8:
9171 VIXL_UNIMPLEMENTED();
9172 break;
9173 case LD1RD_z_p_bi_u64:
9174 VIXL_UNIMPLEMENTED();
9175 break;
9176 case LD1RH_z_p_bi_u16:
9177 VIXL_UNIMPLEMENTED();
9178 break;
9179 case LD1RH_z_p_bi_u32:
9180 VIXL_UNIMPLEMENTED();
9181 break;
9182 case LD1RH_z_p_bi_u64:
9183 VIXL_UNIMPLEMENTED();
9184 break;
9185 case LD1RSB_z_p_bi_s16:
9186 VIXL_UNIMPLEMENTED();
9187 break;
9188 case LD1RSB_z_p_bi_s32:
9189 VIXL_UNIMPLEMENTED();
9190 break;
9191 case LD1RSB_z_p_bi_s64:
9192 VIXL_UNIMPLEMENTED();
9193 break;
9194 case LD1RSH_z_p_bi_s32:
9195 VIXL_UNIMPLEMENTED();
9196 break;
9197 case LD1RSH_z_p_bi_s64:
9198 VIXL_UNIMPLEMENTED();
9199 break;
9200 case LD1RSW_z_p_bi_s64:
9201 VIXL_UNIMPLEMENTED();
9202 break;
9203 case LD1RW_z_p_bi_u32:
9204 VIXL_UNIMPLEMENTED();
9205 break;
9206 case LD1RW_z_p_bi_u64:
9207 VIXL_UNIMPLEMENTED();
9208 break;
9209 default:
9210 VIXL_UNIMPLEMENTED();
9211 break;
9212 }
9213}
9214
9215void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
9216 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
9217 case LDR_p_bi: {
9218 SimPRegister& pt = ReadPRegister(instr->GetPt());
9219 int pl = GetPredicateLengthInBytes();
9220 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9221 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9222 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
9223 for (int i = 0; i < pl; i++) {
9224 pt.Insert(i, Memory::Read<uint8_t>(address + i));
9225 }
9226 LogPRead(address, instr->GetPt());
9227 break;
9228 }
9229 default:
9230 VIXL_UNIMPLEMENTED();
9231 break;
9232 }
9233}
9234
9235void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
9236 USE(instr);
9237 switch (instr->Mask(SVELoadVectorRegisterMask)) {
9238 case LDR_z_bi: {
9239 SimVRegister& zt = ReadVRegister(instr->GetRt());
9240 int vl = GetVectorLengthInBytes();
9241 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9242 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9243 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
9244 for (int i = 0; i < vl; i++) {
9245 zt.Insert(i, Memory::Read<uint8_t>(address + i));
9246 }
9247 LogZRead(address, instr->GetRt());
9248 break;
9249 }
9250 default:
9251 VIXL_UNIMPLEMENTED();
9252 break;
9253 }
9254}
9255
9256void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
9257 const Instruction* instr) {
9258 USE(instr);
9259 switch (instr->Mask(
9260 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009261 case LD1D_z_p_bz_d_x32_scaled:
9262 VIXL_UNIMPLEMENTED();
9263 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009264 case LD1H_z_p_bz_d_x32_scaled:
9265 VIXL_UNIMPLEMENTED();
9266 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009267 case LD1SH_z_p_bz_d_x32_scaled:
9268 VIXL_UNIMPLEMENTED();
9269 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009270 case LD1SW_z_p_bz_d_x32_scaled:
9271 VIXL_UNIMPLEMENTED();
9272 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009273 case LD1W_z_p_bz_d_x32_scaled:
9274 VIXL_UNIMPLEMENTED();
9275 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009276 case LDFF1D_z_p_bz_d_x32_scaled:
9277 VIXL_UNIMPLEMENTED();
9278 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009279 case LDFF1H_z_p_bz_d_x32_scaled:
9280 VIXL_UNIMPLEMENTED();
9281 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009282 case LDFF1SH_z_p_bz_d_x32_scaled:
9283 VIXL_UNIMPLEMENTED();
9284 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009285 case LDFF1SW_z_p_bz_d_x32_scaled:
9286 VIXL_UNIMPLEMENTED();
9287 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009288 case LDFF1W_z_p_bz_d_x32_scaled:
9289 VIXL_UNIMPLEMENTED();
9290 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009291 default:
9292 VIXL_UNIMPLEMENTED();
9293 break;
9294 }
9295}
9296
9297void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
9298 const Instruction* instr) {
9299 USE(instr);
9300 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
9301 case LD1D_z_p_bz_d_64_scaled:
9302 VIXL_UNIMPLEMENTED();
9303 break;
9304 case LD1H_z_p_bz_d_64_scaled:
9305 VIXL_UNIMPLEMENTED();
9306 break;
9307 case LD1SH_z_p_bz_d_64_scaled:
9308 VIXL_UNIMPLEMENTED();
9309 break;
9310 case LD1SW_z_p_bz_d_64_scaled:
9311 VIXL_UNIMPLEMENTED();
9312 break;
9313 case LD1W_z_p_bz_d_64_scaled:
9314 VIXL_UNIMPLEMENTED();
9315 break;
9316 case LDFF1D_z_p_bz_d_64_scaled:
9317 VIXL_UNIMPLEMENTED();
9318 break;
9319 case LDFF1H_z_p_bz_d_64_scaled:
9320 VIXL_UNIMPLEMENTED();
9321 break;
9322 case LDFF1SH_z_p_bz_d_64_scaled:
9323 VIXL_UNIMPLEMENTED();
9324 break;
9325 case LDFF1SW_z_p_bz_d_64_scaled:
9326 VIXL_UNIMPLEMENTED();
9327 break;
9328 case LDFF1W_z_p_bz_d_64_scaled:
9329 VIXL_UNIMPLEMENTED();
9330 break;
9331 default:
9332 VIXL_UNIMPLEMENTED();
9333 break;
9334 }
9335}
9336
9337void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
9338 const Instruction* instr) {
9339 USE(instr);
9340 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
9341 case LD1B_z_p_bz_d_64_unscaled:
9342 VIXL_UNIMPLEMENTED();
9343 break;
9344 case LD1D_z_p_bz_d_64_unscaled:
9345 VIXL_UNIMPLEMENTED();
9346 break;
9347 case LD1H_z_p_bz_d_64_unscaled:
9348 VIXL_UNIMPLEMENTED();
9349 break;
9350 case LD1SB_z_p_bz_d_64_unscaled:
9351 VIXL_UNIMPLEMENTED();
9352 break;
9353 case LD1SH_z_p_bz_d_64_unscaled:
9354 VIXL_UNIMPLEMENTED();
9355 break;
9356 case LD1SW_z_p_bz_d_64_unscaled:
9357 VIXL_UNIMPLEMENTED();
9358 break;
9359 case LD1W_z_p_bz_d_64_unscaled:
9360 VIXL_UNIMPLEMENTED();
9361 break;
9362 case LDFF1B_z_p_bz_d_64_unscaled:
9363 VIXL_UNIMPLEMENTED();
9364 break;
9365 case LDFF1D_z_p_bz_d_64_unscaled:
9366 VIXL_UNIMPLEMENTED();
9367 break;
9368 case LDFF1H_z_p_bz_d_64_unscaled:
9369 VIXL_UNIMPLEMENTED();
9370 break;
9371 case LDFF1SB_z_p_bz_d_64_unscaled:
9372 VIXL_UNIMPLEMENTED();
9373 break;
9374 case LDFF1SH_z_p_bz_d_64_unscaled:
9375 VIXL_UNIMPLEMENTED();
9376 break;
9377 case LDFF1SW_z_p_bz_d_64_unscaled:
9378 VIXL_UNIMPLEMENTED();
9379 break;
9380 case LDFF1W_z_p_bz_d_64_unscaled:
9381 VIXL_UNIMPLEMENTED();
9382 break;
9383 default:
9384 VIXL_UNIMPLEMENTED();
9385 break;
9386 }
9387}
9388
9389void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
9390 const Instruction* instr) {
9391 USE(instr);
9392 switch (instr->Mask(
9393 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9394 case LD1B_z_p_bz_d_x32_unscaled:
9395 VIXL_UNIMPLEMENTED();
9396 break;
9397 case LD1D_z_p_bz_d_x32_unscaled:
9398 VIXL_UNIMPLEMENTED();
9399 break;
9400 case LD1H_z_p_bz_d_x32_unscaled:
9401 VIXL_UNIMPLEMENTED();
9402 break;
9403 case LD1SB_z_p_bz_d_x32_unscaled:
9404 VIXL_UNIMPLEMENTED();
9405 break;
9406 case LD1SH_z_p_bz_d_x32_unscaled:
9407 VIXL_UNIMPLEMENTED();
9408 break;
9409 case LD1SW_z_p_bz_d_x32_unscaled:
9410 VIXL_UNIMPLEMENTED();
9411 break;
9412 case LD1W_z_p_bz_d_x32_unscaled:
9413 VIXL_UNIMPLEMENTED();
9414 break;
9415 case LDFF1B_z_p_bz_d_x32_unscaled:
9416 VIXL_UNIMPLEMENTED();
9417 break;
9418 case LDFF1D_z_p_bz_d_x32_unscaled:
9419 VIXL_UNIMPLEMENTED();
9420 break;
9421 case LDFF1H_z_p_bz_d_x32_unscaled:
9422 VIXL_UNIMPLEMENTED();
9423 break;
9424 case LDFF1SB_z_p_bz_d_x32_unscaled:
9425 VIXL_UNIMPLEMENTED();
9426 break;
9427 case LDFF1SH_z_p_bz_d_x32_unscaled:
9428 VIXL_UNIMPLEMENTED();
9429 break;
9430 case LDFF1SW_z_p_bz_d_x32_unscaled:
9431 VIXL_UNIMPLEMENTED();
9432 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009433 case LDFF1W_z_p_bz_d_x32_unscaled:
9434 VIXL_UNIMPLEMENTED();
9435 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009436 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009437 VIXL_UNIMPLEMENTED();
9438 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009439 }
9440}
9441
9442void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
9443 const Instruction* instr) {
9444 USE(instr);
9445 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
9446 case LD1B_z_p_ai_d:
9447 VIXL_UNIMPLEMENTED();
9448 break;
9449 case LD1D_z_p_ai_d:
9450 VIXL_UNIMPLEMENTED();
9451 break;
9452 case LD1H_z_p_ai_d:
9453 VIXL_UNIMPLEMENTED();
9454 break;
9455 case LD1SB_z_p_ai_d:
9456 VIXL_UNIMPLEMENTED();
9457 break;
9458 case LD1SH_z_p_ai_d:
9459 VIXL_UNIMPLEMENTED();
9460 break;
9461 case LD1SW_z_p_ai_d:
9462 VIXL_UNIMPLEMENTED();
9463 break;
9464 case LD1W_z_p_ai_d:
9465 VIXL_UNIMPLEMENTED();
9466 break;
9467 case LDFF1B_z_p_ai_d:
9468 VIXL_UNIMPLEMENTED();
9469 break;
9470 case LDFF1D_z_p_ai_d:
9471 VIXL_UNIMPLEMENTED();
9472 break;
9473 case LDFF1H_z_p_ai_d:
9474 VIXL_UNIMPLEMENTED();
9475 break;
9476 case LDFF1SB_z_p_ai_d:
9477 VIXL_UNIMPLEMENTED();
9478 break;
9479 case LDFF1SH_z_p_ai_d:
9480 VIXL_UNIMPLEMENTED();
9481 break;
9482 case LDFF1SW_z_p_ai_d:
9483 VIXL_UNIMPLEMENTED();
9484 break;
9485 case LDFF1W_z_p_ai_d:
9486 VIXL_UNIMPLEMENTED();
9487 break;
9488 default:
9489 VIXL_UNIMPLEMENTED();
9490 break;
9491 }
9492}
9493
9494void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
9495 const Instruction* instr) {
9496 USE(instr);
9497 switch (
9498 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009499 case PRFB_i_p_bz_d_64_scaled:
9500 VIXL_UNIMPLEMENTED();
9501 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009502 case PRFD_i_p_bz_d_64_scaled:
9503 VIXL_UNIMPLEMENTED();
9504 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009505 case PRFH_i_p_bz_d_64_scaled:
9506 VIXL_UNIMPLEMENTED();
9507 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009508 case PRFW_i_p_bz_d_64_scaled:
9509 VIXL_UNIMPLEMENTED();
9510 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009511 default:
9512 VIXL_UNIMPLEMENTED();
9513 break;
9514 }
9515}
9516
9517void Simulator::
9518 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
9519 const Instruction* instr) {
9520 USE(instr);
9521 switch (instr->Mask(
9522 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9523 case PRFB_i_p_bz_d_x32_scaled:
9524 VIXL_UNIMPLEMENTED();
9525 break;
9526 case PRFD_i_p_bz_d_x32_scaled:
9527 VIXL_UNIMPLEMENTED();
9528 break;
9529 case PRFH_i_p_bz_d_x32_scaled:
9530 VIXL_UNIMPLEMENTED();
9531 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009532 case PRFW_i_p_bz_d_x32_scaled:
9533 VIXL_UNIMPLEMENTED();
9534 break;
9535 default:
9536 VIXL_UNIMPLEMENTED();
9537 break;
9538 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009539}
9540
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009541void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
9542 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009543 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009544 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
9545 case PRFB_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009546 VIXL_UNIMPLEMENTED();
9547 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009548 case PRFD_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009549 VIXL_UNIMPLEMENTED();
9550 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009551 case PRFH_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009552 VIXL_UNIMPLEMENTED();
9553 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009554 case PRFW_i_p_ai_d:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009555 VIXL_UNIMPLEMENTED();
9556 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009557 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009558 VIXL_UNIMPLEMENTED();
9559 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009560 }
9561}
9562
9563void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
9564 const Instruction* instr) {
9565 USE(instr);
9566 switch (instr->Mask(SVEContiguousFirstFaultLoad_ScalarPlusScalarMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009567 case LDFF1B_z_p_br_u16:
9568 VIXL_UNIMPLEMENTED();
9569 break;
9570 case LDFF1B_z_p_br_u32:
9571 VIXL_UNIMPLEMENTED();
9572 break;
9573 case LDFF1B_z_p_br_u64:
9574 VIXL_UNIMPLEMENTED();
9575 break;
9576 case LDFF1B_z_p_br_u8:
9577 VIXL_UNIMPLEMENTED();
9578 break;
9579 case LDFF1D_z_p_br_u64:
9580 VIXL_UNIMPLEMENTED();
9581 break;
9582 case LDFF1H_z_p_br_u16:
9583 VIXL_UNIMPLEMENTED();
9584 break;
9585 case LDFF1H_z_p_br_u32:
9586 VIXL_UNIMPLEMENTED();
9587 break;
9588 case LDFF1H_z_p_br_u64:
9589 VIXL_UNIMPLEMENTED();
9590 break;
9591 case LDFF1SB_z_p_br_s16:
9592 VIXL_UNIMPLEMENTED();
9593 break;
9594 case LDFF1SB_z_p_br_s32:
9595 VIXL_UNIMPLEMENTED();
9596 break;
9597 case LDFF1SB_z_p_br_s64:
9598 VIXL_UNIMPLEMENTED();
9599 break;
9600 case LDFF1SH_z_p_br_s32:
9601 VIXL_UNIMPLEMENTED();
9602 break;
9603 case LDFF1SH_z_p_br_s64:
9604 VIXL_UNIMPLEMENTED();
9605 break;
9606 case LDFF1SW_z_p_br_s64:
9607 VIXL_UNIMPLEMENTED();
9608 break;
9609 case LDFF1W_z_p_br_u32:
9610 VIXL_UNIMPLEMENTED();
9611 break;
9612 case LDFF1W_z_p_br_u64:
9613 VIXL_UNIMPLEMENTED();
9614 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009615 default:
9616 VIXL_UNIMPLEMENTED();
9617 break;
9618 }
9619}
9620
9621void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
9622 const Instruction* instr) {
9623 USE(instr);
9624 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009625 case LDNF1B_z_p_bi_u16:
9626 VIXL_UNIMPLEMENTED();
9627 break;
9628 case LDNF1B_z_p_bi_u32:
9629 VIXL_UNIMPLEMENTED();
9630 break;
9631 case LDNF1B_z_p_bi_u64:
9632 VIXL_UNIMPLEMENTED();
9633 break;
9634 case LDNF1B_z_p_bi_u8:
9635 VIXL_UNIMPLEMENTED();
9636 break;
9637 case LDNF1D_z_p_bi_u64:
9638 VIXL_UNIMPLEMENTED();
9639 break;
9640 case LDNF1H_z_p_bi_u16:
9641 VIXL_UNIMPLEMENTED();
9642 break;
9643 case LDNF1H_z_p_bi_u32:
9644 VIXL_UNIMPLEMENTED();
9645 break;
9646 case LDNF1H_z_p_bi_u64:
9647 VIXL_UNIMPLEMENTED();
9648 break;
9649 case LDNF1SB_z_p_bi_s16:
9650 VIXL_UNIMPLEMENTED();
9651 break;
9652 case LDNF1SB_z_p_bi_s32:
9653 VIXL_UNIMPLEMENTED();
9654 break;
9655 case LDNF1SB_z_p_bi_s64:
9656 VIXL_UNIMPLEMENTED();
9657 break;
9658 case LDNF1SH_z_p_bi_s32:
9659 VIXL_UNIMPLEMENTED();
9660 break;
9661 case LDNF1SH_z_p_bi_s64:
9662 VIXL_UNIMPLEMENTED();
9663 break;
9664 case LDNF1SW_z_p_bi_s64:
9665 VIXL_UNIMPLEMENTED();
9666 break;
9667 case LDNF1W_z_p_bi_u32:
9668 VIXL_UNIMPLEMENTED();
9669 break;
9670 case LDNF1W_z_p_bi_u64:
9671 VIXL_UNIMPLEMENTED();
9672 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009673 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009674 VIXL_UNIMPLEMENTED();
9675 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009676 }
9677}
9678
9679void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
9680 const Instruction* instr) {
9681 USE(instr);
9682 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
9683 case LDNT1B_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009684 VIXL_UNIMPLEMENTED();
9685 break;
9686 case LDNT1D_z_p_bi_contiguous:
9687 VIXL_UNIMPLEMENTED();
9688 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009689 case LDNT1H_z_p_bi_contiguous:
9690 VIXL_UNIMPLEMENTED();
9691 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009692 case LDNT1W_z_p_bi_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009693 VIXL_UNIMPLEMENTED();
9694 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009695 default:
9696 VIXL_UNIMPLEMENTED();
9697 break;
9698 }
9699}
9700
9701void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
9702 const Instruction* instr) {
9703 USE(instr);
9704 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
9705 case LDNT1B_z_p_br_contiguous:
9706 VIXL_UNIMPLEMENTED();
9707 break;
9708 case LDNT1D_z_p_br_contiguous:
9709 VIXL_UNIMPLEMENTED();
9710 break;
9711 case LDNT1H_z_p_br_contiguous:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009712 VIXL_UNIMPLEMENTED();
9713 break;
9714 case LDNT1W_z_p_br_contiguous:
9715 VIXL_UNIMPLEMENTED();
9716 break;
9717 default:
9718 VIXL_UNIMPLEMENTED();
9719 break;
9720 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009721}
9722
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009723void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
9724 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009725 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009726 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
9727 case LD1RQB_z_p_bi_u8:
9728 VIXL_UNIMPLEMENTED();
9729 break;
9730 case LD1RQD_z_p_bi_u64:
9731 VIXL_UNIMPLEMENTED();
9732 break;
9733 case LD1RQH_z_p_bi_u16:
9734 VIXL_UNIMPLEMENTED();
9735 break;
9736 case LD1RQW_z_p_bi_u32:
9737 VIXL_UNIMPLEMENTED();
9738 break;
9739 default:
9740 VIXL_UNIMPLEMENTED();
9741 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009742 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +01009743}
9744
9745void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
9746 const Instruction* instr) {
9747 USE(instr);
9748 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
9749 case LD1RQB_z_p_br_contiguous:
9750 VIXL_UNIMPLEMENTED();
9751 break;
9752 case LD1RQD_z_p_br_contiguous:
9753 VIXL_UNIMPLEMENTED();
9754 break;
9755 case LD1RQH_z_p_br_contiguous:
9756 VIXL_UNIMPLEMENTED();
9757 break;
9758 case LD1RQW_z_p_br_contiguous:
9759 VIXL_UNIMPLEMENTED();
9760 break;
9761 default:
9762 VIXL_UNIMPLEMENTED();
9763 break;
9764 }
9765}
9766
9767void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
9768 const Instruction* instr) {
9769 USE(instr);
9770 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
9771 case LD2B_z_p_bi_contiguous:
9772 VIXL_UNIMPLEMENTED();
9773 break;
9774 case LD2D_z_p_bi_contiguous:
9775 VIXL_UNIMPLEMENTED();
9776 break;
9777 case LD2H_z_p_bi_contiguous:
9778 VIXL_UNIMPLEMENTED();
9779 break;
9780 case LD2W_z_p_bi_contiguous:
9781 VIXL_UNIMPLEMENTED();
9782 break;
9783 case LD3B_z_p_bi_contiguous:
9784 VIXL_UNIMPLEMENTED();
9785 break;
9786 case LD3D_z_p_bi_contiguous:
9787 VIXL_UNIMPLEMENTED();
9788 break;
9789 case LD3H_z_p_bi_contiguous:
9790 VIXL_UNIMPLEMENTED();
9791 break;
9792 case LD3W_z_p_bi_contiguous:
9793 VIXL_UNIMPLEMENTED();
9794 break;
9795 case LD4B_z_p_bi_contiguous:
9796 VIXL_UNIMPLEMENTED();
9797 break;
9798 case LD4D_z_p_bi_contiguous:
9799 VIXL_UNIMPLEMENTED();
9800 break;
9801 case LD4H_z_p_bi_contiguous:
9802 VIXL_UNIMPLEMENTED();
9803 break;
9804 case LD4W_z_p_bi_contiguous:
9805 VIXL_UNIMPLEMENTED();
9806 break;
9807 default:
9808 VIXL_UNIMPLEMENTED();
9809 break;
9810 }
9811}
9812
9813void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
9814 const Instruction* instr) {
9815 USE(instr);
9816 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
9817 case LD2B_z_p_br_contiguous:
9818 VIXL_UNIMPLEMENTED();
9819 break;
9820 case LD2D_z_p_br_contiguous:
9821 VIXL_UNIMPLEMENTED();
9822 break;
9823 case LD2H_z_p_br_contiguous:
9824 VIXL_UNIMPLEMENTED();
9825 break;
9826 case LD2W_z_p_br_contiguous:
9827 VIXL_UNIMPLEMENTED();
9828 break;
9829 case LD3B_z_p_br_contiguous:
9830 VIXL_UNIMPLEMENTED();
9831 break;
9832 case LD3D_z_p_br_contiguous:
9833 VIXL_UNIMPLEMENTED();
9834 break;
9835 case LD3H_z_p_br_contiguous:
9836 VIXL_UNIMPLEMENTED();
9837 break;
9838 case LD3W_z_p_br_contiguous:
9839 VIXL_UNIMPLEMENTED();
9840 break;
9841 case LD4B_z_p_br_contiguous:
9842 VIXL_UNIMPLEMENTED();
9843 break;
9844 case LD4D_z_p_br_contiguous:
9845 VIXL_UNIMPLEMENTED();
9846 break;
9847 case LD4H_z_p_br_contiguous:
9848 VIXL_UNIMPLEMENTED();
9849 break;
9850 case LD4W_z_p_br_contiguous:
9851 VIXL_UNIMPLEMENTED();
9852 break;
9853 default:
9854 VIXL_UNIMPLEMENTED();
9855 break;
9856 }
9857}
9858
9859void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
9860 const Instruction* instr) {
9861 USE(instr);
9862 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
9863 case ST1H_z_p_bz_s_x32_scaled:
9864 VIXL_UNIMPLEMENTED();
9865 break;
9866 case ST1W_z_p_bz_s_x32_scaled:
9867 VIXL_UNIMPLEMENTED();
9868 break;
9869 default:
9870 VIXL_UNIMPLEMENTED();
9871 break;
9872 }
9873}
9874
9875void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
9876 const Instruction* instr) {
9877 USE(instr);
9878 switch (
9879 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
9880 case ST1B_z_p_bz_s_x32_unscaled:
9881 VIXL_UNIMPLEMENTED();
9882 break;
9883 case ST1H_z_p_bz_s_x32_unscaled:
9884 VIXL_UNIMPLEMENTED();
9885 break;
9886 case ST1W_z_p_bz_s_x32_unscaled:
9887 VIXL_UNIMPLEMENTED();
9888 break;
9889 default:
9890 VIXL_UNIMPLEMENTED();
9891 break;
9892 }
9893}
9894
9895void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
9896 const Instruction* instr) {
9897 USE(instr);
9898 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
9899 case ST1B_z_p_ai_s:
9900 VIXL_UNIMPLEMENTED();
9901 break;
9902 case ST1H_z_p_ai_s:
9903 VIXL_UNIMPLEMENTED();
9904 break;
9905 case ST1W_z_p_ai_s:
9906 VIXL_UNIMPLEMENTED();
9907 break;
9908 default:
9909 VIXL_UNIMPLEMENTED();
9910 break;
9911 }
9912}
9913
9914void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
9915 const Instruction* instr) {
9916 USE(instr);
9917 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
9918 case ST1D_z_p_bz_d_64_scaled:
9919 VIXL_UNIMPLEMENTED();
9920 break;
9921 case ST1H_z_p_bz_d_64_scaled:
9922 VIXL_UNIMPLEMENTED();
9923 break;
9924 case ST1W_z_p_bz_d_64_scaled:
9925 VIXL_UNIMPLEMENTED();
9926 break;
9927 default:
9928 VIXL_UNIMPLEMENTED();
9929 break;
9930 }
9931}
9932
9933void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
9934 const Instruction* instr) {
9935 USE(instr);
9936 switch (
9937 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
9938 case ST1B_z_p_bz_d_64_unscaled:
9939 VIXL_UNIMPLEMENTED();
9940 break;
9941 case ST1D_z_p_bz_d_64_unscaled:
9942 VIXL_UNIMPLEMENTED();
9943 break;
9944 case ST1H_z_p_bz_d_64_unscaled:
9945 VIXL_UNIMPLEMENTED();
9946 break;
9947 case ST1W_z_p_bz_d_64_unscaled:
9948 VIXL_UNIMPLEMENTED();
9949 break;
9950 default:
9951 VIXL_UNIMPLEMENTED();
9952 break;
9953 }
9954}
9955
9956void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
9957 const Instruction* instr) {
9958 USE(instr);
9959 switch (instr->Mask(
9960 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9961 case ST1D_z_p_bz_d_x32_scaled:
9962 VIXL_UNIMPLEMENTED();
9963 break;
9964 case ST1H_z_p_bz_d_x32_scaled:
9965 VIXL_UNIMPLEMENTED();
9966 break;
9967 case ST1W_z_p_bz_d_x32_scaled:
9968 VIXL_UNIMPLEMENTED();
9969 break;
9970 default:
9971 VIXL_UNIMPLEMENTED();
9972 break;
9973 }
9974}
9975
9976void Simulator::
9977 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
9978 const Instruction* instr) {
9979 USE(instr);
9980 switch (instr->Mask(
9981 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9982 case ST1B_z_p_bz_d_x32_unscaled:
9983 VIXL_UNIMPLEMENTED();
9984 break;
9985 case ST1D_z_p_bz_d_x32_unscaled:
9986 VIXL_UNIMPLEMENTED();
9987 break;
9988 case ST1H_z_p_bz_d_x32_unscaled:
9989 VIXL_UNIMPLEMENTED();
9990 break;
9991 case ST1W_z_p_bz_d_x32_unscaled:
9992 VIXL_UNIMPLEMENTED();
9993 break;
9994 default:
9995 VIXL_UNIMPLEMENTED();
9996 break;
9997 }
9998}
9999
10000void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
10001 const Instruction* instr) {
10002 USE(instr);
10003 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
10004 case ST1B_z_p_ai_d:
10005 VIXL_UNIMPLEMENTED();
10006 break;
10007 case ST1D_z_p_ai_d:
10008 VIXL_UNIMPLEMENTED();
10009 break;
10010 case ST1H_z_p_ai_d:
10011 VIXL_UNIMPLEMENTED();
10012 break;
10013 case ST1W_z_p_ai_d:
10014 VIXL_UNIMPLEMENTED();
10015 break;
10016 default:
10017 VIXL_UNIMPLEMENTED();
10018 break;
10019 }
10020}
10021
10022void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
10023 const Instruction* instr) {
10024 USE(instr);
10025 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
10026 case STNT1B_z_p_bi_contiguous:
10027 VIXL_UNIMPLEMENTED();
10028 break;
10029 case STNT1D_z_p_bi_contiguous:
10030 VIXL_UNIMPLEMENTED();
10031 break;
10032 case STNT1H_z_p_bi_contiguous:
10033 VIXL_UNIMPLEMENTED();
10034 break;
10035 case STNT1W_z_p_bi_contiguous:
10036 VIXL_UNIMPLEMENTED();
10037 break;
10038 default:
10039 VIXL_UNIMPLEMENTED();
10040 break;
10041 }
10042}
10043
10044void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
10045 const Instruction* instr) {
10046 USE(instr);
10047 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
10048 case STNT1B_z_p_br_contiguous:
10049 VIXL_UNIMPLEMENTED();
10050 break;
10051 case STNT1D_z_p_br_contiguous:
10052 VIXL_UNIMPLEMENTED();
10053 break;
10054 case STNT1H_z_p_br_contiguous:
10055 VIXL_UNIMPLEMENTED();
10056 break;
10057 case STNT1W_z_p_br_contiguous:
10058 VIXL_UNIMPLEMENTED();
10059 break;
10060 default:
10061 VIXL_UNIMPLEMENTED();
10062 break;
10063 }
10064}
10065
10066void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
10067 const Instruction* instr) {
10068 USE(instr);
10069 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
10070 case ST1B_z_p_bi:
10071 case ST1D_z_p_bi:
10072 case ST1H_z_p_bi:
10073 case ST1W_z_p_bi: {
10074 int vl = GetVectorLengthInBytes();
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010075 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10076 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
10077 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10078 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10079 uint64_t offset =
10080 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010081 VectorFormat vform =
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010082 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010083 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010084 SVEStructuredStoreHelper(msize_in_bytes_log2,
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010085 vform,
10086 ReadPRegister(instr->GetPgLow8()),
10087 instr->GetRt(),
10088 1,
10089 addr);
10090 break;
10091 }
10092 default:
10093 VIXL_UNIMPLEMENTED();
10094 break;
10095 }
10096}
10097
10098void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
10099 const Instruction* instr) {
10100 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
10101 case ST1B_z_p_br:
10102 case ST1D_z_p_br:
10103 case ST1H_z_p_br:
10104 case ST1W_z_p_br: {
10105 uint64_t offset = ReadXRegister(instr->GetRm());
10106 offset <<= instr->ExtractBits(24, 23);
10107 VectorFormat vform =
10108 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
10109 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10110 SVEStructuredStoreHelper(instr->ExtractBits(24, 23),
10111 vform,
10112 ReadPRegister(instr->GetPgLow8()),
10113 instr->GetRt(),
10114 1,
10115 addr);
10116 break;
10117 }
10118 default:
10119 VIXL_UNIMPLEMENTED();
10120 break;
10121 }
10122}
10123
10124void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
10125 const Instruction* instr) {
10126 VectorFormat vform = instr->GetSVEVectorFormat();
10127 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10128 SimVRegister z_result;
10129
10130 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
10131 case CPY_z_p_v:
10132 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
10133 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
10134 break;
10135 default:
10136 VIXL_UNIMPLEMENTED();
10137 break;
10138 }
10139}
10140
10141void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
10142 const Instruction* instr) {
10143 USE(instr);
10144 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
10145 case ST2B_z_p_bi_contiguous:
10146 VIXL_UNIMPLEMENTED();
10147 break;
10148 case ST2D_z_p_bi_contiguous:
10149 VIXL_UNIMPLEMENTED();
10150 break;
10151 case ST2H_z_p_bi_contiguous:
10152 VIXL_UNIMPLEMENTED();
10153 break;
10154 case ST2W_z_p_bi_contiguous:
10155 VIXL_UNIMPLEMENTED();
10156 break;
10157 case ST3B_z_p_bi_contiguous:
10158 VIXL_UNIMPLEMENTED();
10159 break;
10160 case ST3D_z_p_bi_contiguous:
10161 VIXL_UNIMPLEMENTED();
10162 break;
10163 case ST3H_z_p_bi_contiguous:
10164 VIXL_UNIMPLEMENTED();
10165 break;
10166 case ST3W_z_p_bi_contiguous:
10167 VIXL_UNIMPLEMENTED();
10168 break;
10169 case ST4B_z_p_bi_contiguous:
10170 VIXL_UNIMPLEMENTED();
10171 break;
10172 case ST4D_z_p_bi_contiguous:
10173 VIXL_UNIMPLEMENTED();
10174 break;
10175 case ST4H_z_p_bi_contiguous:
10176 VIXL_UNIMPLEMENTED();
10177 break;
10178 case ST4W_z_p_bi_contiguous:
10179 VIXL_UNIMPLEMENTED();
10180 break;
10181 default:
10182 VIXL_UNIMPLEMENTED();
10183 break;
10184 }
10185}
10186
10187void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
10188 const Instruction* instr) {
10189 USE(instr);
10190 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
10191 case ST2B_z_p_br_contiguous:
10192 VIXL_UNIMPLEMENTED();
10193 break;
10194 case ST2D_z_p_br_contiguous:
10195 VIXL_UNIMPLEMENTED();
10196 break;
10197 case ST2H_z_p_br_contiguous:
10198 VIXL_UNIMPLEMENTED();
10199 break;
10200 case ST2W_z_p_br_contiguous:
10201 VIXL_UNIMPLEMENTED();
10202 break;
10203 case ST3B_z_p_br_contiguous:
10204 VIXL_UNIMPLEMENTED();
10205 break;
10206 case ST3D_z_p_br_contiguous:
10207 VIXL_UNIMPLEMENTED();
10208 break;
10209 case ST3H_z_p_br_contiguous:
10210 VIXL_UNIMPLEMENTED();
10211 break;
10212 case ST3W_z_p_br_contiguous:
10213 VIXL_UNIMPLEMENTED();
10214 break;
10215 case ST4B_z_p_br_contiguous:
10216 VIXL_UNIMPLEMENTED();
10217 break;
10218 case ST4D_z_p_br_contiguous:
10219 VIXL_UNIMPLEMENTED();
10220 break;
10221 case ST4H_z_p_br_contiguous:
10222 VIXL_UNIMPLEMENTED();
10223 break;
10224 case ST4W_z_p_br_contiguous:
10225 VIXL_UNIMPLEMENTED();
10226 break;
10227 default:
10228 VIXL_UNIMPLEMENTED();
10229 break;
10230 }
10231}
10232
10233void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
10234 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
10235 case STR_p_bi: {
10236 SimPRegister& pt = ReadPRegister(instr->GetPt());
10237 int pl = GetPredicateLengthInBytes();
10238 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10239 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10240 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
10241 for (int i = 0; i < pl; i++) {
10242 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
10243 }
10244 LogPWrite(address, instr->GetPt());
10245 break;
10246 }
10247 default:
10248 VIXL_UNIMPLEMENTED();
10249 break;
10250 }
10251}
10252
10253void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
10254 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
10255 case STR_z_bi: {
10256 SimVRegister& zt = ReadVRegister(instr->GetRt());
10257 int vl = GetVectorLengthInBytes();
10258 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10259 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10260 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
10261 for (int i = 0; i < vl; i++) {
10262 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
10263 }
10264 LogZWrite(address, instr->GetRt());
10265 break;
10266 }
10267 default:
10268 VIXL_UNIMPLEMENTED();
10269 break;
10270 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010271}
10272
10273void Simulator::VisitSVEMulIndex(const Instruction* instr) {
10274 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010275 switch (instr->Mask(SVEMulIndexMask)) {
10276 case SDOT_z_zzzi_d:
10277 VIXL_UNIMPLEMENTED();
10278 break;
10279 case SDOT_z_zzzi_s:
10280 VIXL_UNIMPLEMENTED();
10281 break;
10282 case UDOT_z_zzzi_d:
10283 VIXL_UNIMPLEMENTED();
10284 break;
10285 case UDOT_z_zzzi_s:
10286 VIXL_UNIMPLEMENTED();
10287 break;
10288 default:
10289 VIXL_UNIMPLEMENTED();
10290 break;
10291 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010292}
10293
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010294void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010295 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010296 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010297 case BRKAS_p_p_p_z:
10298 VIXL_UNIMPLEMENTED();
10299 break;
10300 case BRKA_p_p_p:
10301 VIXL_UNIMPLEMENTED();
10302 break;
10303 case BRKBS_p_p_p_z:
10304 VIXL_UNIMPLEMENTED();
10305 break;
10306 case BRKB_p_p_p:
10307 VIXL_UNIMPLEMENTED();
10308 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010309 default:
10310 VIXL_UNIMPLEMENTED();
10311 break;
10312 }
10313}
10314
10315void Simulator::VisitSVEPropagateBreakToNextPartition(
10316 const Instruction* instr) {
10317 USE(instr);
10318 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010319 case BRKNS_p_p_pp:
10320 VIXL_UNIMPLEMENTED();
10321 break;
10322 case BRKN_p_p_pp:
10323 VIXL_UNIMPLEMENTED();
10324 break;
10325 default:
10326 VIXL_UNIMPLEMENTED();
10327 break;
10328 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010329}
10330
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010331void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010332 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010333 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010334 case PUNPKHI_p_p:
10335 VIXL_UNIMPLEMENTED();
10336 break;
10337 case PUNPKLO_p_p:
10338 VIXL_UNIMPLEMENTED();
10339 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010340 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010341 VIXL_UNIMPLEMENTED();
10342 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010343 }
10344}
10345
10346void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
10347 USE(instr);
10348 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010349 case TRN1_p_pp:
10350 VIXL_UNIMPLEMENTED();
10351 break;
10352 case TRN2_p_pp:
10353 VIXL_UNIMPLEMENTED();
10354 break;
10355 case UZP1_p_pp:
10356 VIXL_UNIMPLEMENTED();
10357 break;
10358 case UZP2_p_pp:
10359 VIXL_UNIMPLEMENTED();
10360 break;
10361 case ZIP1_p_pp:
10362 VIXL_UNIMPLEMENTED();
10363 break;
10364 case ZIP2_p_pp:
10365 VIXL_UNIMPLEMENTED();
10366 break;
10367 default:
10368 VIXL_UNIMPLEMENTED();
10369 break;
10370 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010371}
10372
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010373void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
10374 USE(instr);
10375 switch (instr->Mask(SVEReversePredicateElementsMask)) {
10376 case REV_p_p:
10377 VIXL_UNIMPLEMENTED();
10378 break;
10379 default:
10380 VIXL_UNIMPLEMENTED();
10381 break;
10382 }
10383}
10384
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010385void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
10386 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010387 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
10388 case EXT_z_zi_des:
10389 VIXL_UNIMPLEMENTED();
10390 break;
10391 default:
10392 VIXL_UNIMPLEMENTED();
10393 break;
10394 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010395}
10396
10397void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
10398 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010399 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
10400 case TRN1_z_zz:
10401 VIXL_UNIMPLEMENTED();
10402 break;
10403 case TRN2_z_zz:
10404 VIXL_UNIMPLEMENTED();
10405 break;
10406 case UZP1_z_zz:
10407 VIXL_UNIMPLEMENTED();
10408 break;
10409 case UZP2_z_zz:
10410 VIXL_UNIMPLEMENTED();
10411 break;
10412 case ZIP1_z_zz:
10413 VIXL_UNIMPLEMENTED();
10414 break;
10415 case ZIP2_z_zz:
10416 VIXL_UNIMPLEMENTED();
10417 break;
10418 default:
10419 VIXL_UNIMPLEMENTED();
10420 break;
10421 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010422}
10423
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010424void Simulator::VisitSVEConditionallyBroadcastElementToVector(
10425 const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010426 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010427 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010428 case CLASTA_z_p_zz:
10429 VIXL_UNIMPLEMENTED();
10430 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010431 case CLASTB_z_p_zz:
10432 VIXL_UNIMPLEMENTED();
10433 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010434 default:
10435 VIXL_UNIMPLEMENTED();
10436 break;
10437 }
10438}
10439
10440void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
10441 const Instruction* instr) {
10442 USE(instr);
10443 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
10444 case CLASTA_v_p_z:
10445 VIXL_UNIMPLEMENTED();
10446 break;
10447 case CLASTB_v_p_z:
10448 VIXL_UNIMPLEMENTED();
10449 break;
10450 default:
10451 VIXL_UNIMPLEMENTED();
10452 break;
10453 }
10454}
10455
10456void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
10457 const Instruction* instr) {
10458 USE(instr);
10459 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
10460 case CLASTA_r_p_z:
10461 VIXL_UNIMPLEMENTED();
10462 break;
10463 case CLASTB_r_p_z:
10464 VIXL_UNIMPLEMENTED();
10465 break;
10466 default:
10467 VIXL_UNIMPLEMENTED();
10468 break;
10469 }
10470}
10471
10472void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
10473 const Instruction* instr) {
10474 USE(instr);
10475 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
10476 case LASTA_v_p_z:
10477 VIXL_UNIMPLEMENTED();
10478 break;
10479 case LASTB_v_p_z:
10480 VIXL_UNIMPLEMENTED();
10481 break;
10482 default:
10483 VIXL_UNIMPLEMENTED();
10484 break;
10485 }
10486}
10487
10488void Simulator::VisitSVEExtractElementToGeneralRegister(
10489 const Instruction* instr) {
10490 USE(instr);
10491 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
10492 case LASTA_r_p_z:
10493 VIXL_UNIMPLEMENTED();
10494 break;
10495 case LASTB_r_p_z:
10496 VIXL_UNIMPLEMENTED();
10497 break;
10498 default:
10499 VIXL_UNIMPLEMENTED();
10500 break;
10501 }
10502}
10503
10504void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
10505 USE(instr);
10506 switch (instr->Mask(SVECompressActiveElementsMask)) {
10507 case COMPACT_z_p_z:
10508 VIXL_UNIMPLEMENTED();
10509 break;
10510 default:
10511 VIXL_UNIMPLEMENTED();
10512 break;
10513 }
10514}
10515
10516void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
10517 const Instruction* instr) {
10518 VectorFormat vform = instr->GetSVEVectorFormat();
10519 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10520 SimVRegister z_result;
10521
10522 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010523 case CPY_z_p_r:
Jacob Bramley0093bb92019-10-04 15:54:10 +010010524 dup_immediate(vform,
10525 z_result,
10526 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10527 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010528 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010529 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010530 VIXL_UNIMPLEMENTED();
10531 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010532 }
10533}
10534
10535void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010536 VectorFormat vform = instr->GetSVEVectorFormat();
10537 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
10538 SimVRegister& zd = ReadVRegister(instr->GetRd());
10539
10540 SimVRegister result;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010541 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010542 case CPY_z_p_i: {
10543 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
10544 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
10545 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010546 break;
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010547 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010548 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010549 VIXL_UNIMPLEMENTED();
10550 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010551 }
Jacob Bramley0f62eab2019-10-23 17:07:47 +010010552
10553 if (instr->ExtractBit(14) != 0) {
10554 mov_merging(vform, zd, pg, result);
10555 } else {
10556 mov_zeroing(vform, zd, pg, result);
10557 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010558}
10559
10560void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
10561 USE(instr);
10562 switch (instr->Mask(SVEReverseWithinElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010563 case RBIT_z_p_z:
10564 VIXL_UNIMPLEMENTED();
10565 break;
10566 case REVB_z_z:
10567 VIXL_UNIMPLEMENTED();
10568 break;
10569 case REVH_z_z:
10570 VIXL_UNIMPLEMENTED();
10571 break;
10572 case REVW_z_z:
10573 VIXL_UNIMPLEMENTED();
10574 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010575 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010576 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010577 break;
10578 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010579}
10580
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010581void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010582 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010583 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
10584 case SPLICE_z_p_zz_des:
10585 VIXL_UNIMPLEMENTED();
10586 break;
10587 default:
10588 VIXL_UNIMPLEMENTED();
10589 break;
10590 }
10591}
TatWai Chong4f28df72019-08-14 17:50:30 -070010592
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010593void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
10594 SimVRegister& zd = ReadVRegister(instr->GetRd());
10595 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
10596 case DUP_z_r:
10597 dup_immediate(instr->GetSVEVectorFormat(),
10598 zd,
10599 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
10600 break;
10601 default:
10602 VIXL_UNIMPLEMENTED();
10603 break;
10604 }
10605}
10606
10607void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
10608 SimVRegister& zd = ReadVRegister(instr->GetRd());
10609 VectorFormat vform = instr->GetSVEVectorFormat();
10610 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
10611 case INSR_z_v:
10612 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
10613 break;
10614 default:
10615 VIXL_UNIMPLEMENTED();
10616 break;
10617 }
10618}
10619
10620void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
10621 SimVRegister& zd = ReadVRegister(instr->GetRd());
10622 VectorFormat vform = instr->GetSVEVectorFormat();
10623 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
10624 case INSR_z_r:
10625 insr(vform, zd, ReadXRegister(instr->GetRn()));
10626 break;
10627 default:
10628 VIXL_UNIMPLEMENTED();
10629 break;
10630 }
10631}
10632
10633void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
10634 SimVRegister& zd = ReadVRegister(instr->GetRd());
10635 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
TatWai Chong4f28df72019-08-14 17:50:30 -070010636 case DUP_z_zi: {
10637 std::pair<int, int> index_and_lane_size =
10638 instr->GetSVEPermuteIndexAndLaneSizeLog2();
10639 int index = index_and_lane_size.first;
10640 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
10641 VectorFormat vform =
10642 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
10643 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
10644 // Out of bounds, set the destination register to zero.
10645 dup_immediate(kFormatVnD, zd, 0);
10646 } else {
10647 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
10648 }
10649 return;
10650 }
TatWai Chong4f28df72019-08-14 17:50:30 -070010651 default:
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010652 VIXL_UNIMPLEMENTED();
TatWai Chong4f28df72019-08-14 17:50:30 -070010653 break;
10654 }
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010655}
TatWai Chong4f28df72019-08-14 17:50:30 -070010656
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010657void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
10658 SimVRegister& zd = ReadVRegister(instr->GetRd());
TatWai Chong4f28df72019-08-14 17:50:30 -070010659 VectorFormat vform = instr->GetSVEVectorFormat();
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010660 switch (instr->Mask(SVEReverseVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010661 case REV_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010662 rev(vform, zd, ReadVRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010663 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010664 default:
10665 VIXL_UNIMPLEMENTED();
10666 break;
10667 }
10668}
10669
10670void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
10671 SimVRegister& zd = ReadVRegister(instr->GetRd());
10672 VectorFormat vform = instr->GetSVEVectorFormat();
10673 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010674 case SUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010675 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010676 break;
10677 case SUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010678 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010679 break;
10680 case UUNPKHI_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010681 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010682 break;
10683 case UUNPKLO_z_z:
TatWai Chong4f28df72019-08-14 17:50:30 -070010684 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
10685 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010686 default:
10687 VIXL_UNIMPLEMENTED();
10688 break;
10689 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010690}
10691
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010692void Simulator::VisitSVETableLookup(const Instruction* instr) {
10693 SimVRegister& zd = ReadVRegister(instr->GetRd());
10694 switch (instr->Mask(SVETableLookupMask)) {
10695 case TBL_z_zz_1:
10696 Table(instr->GetSVEVectorFormat(),
10697 zd,
10698 ReadVRegister(instr->GetRn()),
10699 ReadVRegister(instr->GetRm()));
10700 return;
10701 default:
10702 break;
10703 }
10704}
10705
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010706void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
10707 USE(instr);
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010708
10709 VectorFormat vform = instr->GetSVEVectorFormat();
10710 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10711 SimPRegister& pn = ReadPRegister(instr->GetPn());
10712
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010713 switch (instr->Mask(SVEPredicateCountMask)) {
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010714 case CNTP_r_p_p: {
10715 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010716 break;
Jacob Bramleyd961a0c2019-07-17 10:53:45 +010010717 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010718 default:
10719 VIXL_UNIMPLEMENTED();
10720 break;
10721 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010722}
10723
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010724void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
10725 Instr op = instr->Mask(SVEPredicateLogicalMask);
TatWai Chongf4fa8222019-06-17 12:08:14 -070010726 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010727 case ANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010728 case AND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010729 case BICS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010730 case BIC_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010731 case EORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010732 case EOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010733 case NANDS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010734 case NAND_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010735 case NORS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010736 case NOR_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010737 case ORNS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010738 case ORN_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010739 case ORRS_p_p_pp_z:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010740 case ORR_p_p_pp_z:
TatWai Chongf4fa8222019-06-17 12:08:14 -070010741 case SEL_p_p_pp: {
10742 FlagsUpdate flags =
10743 instr->Mask(SVEPredicateLogicalSetFlagsBit) ? SetFlags : LeaveFlags;
10744 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
10745 ReadPRegister(instr->GetPd()),
10746 ReadPRegister(instr->ExtractBits(13, 10)),
10747 ReadPRegister(instr->GetPn()),
10748 ReadPRegister(instr->GetPm()),
10749 flags);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010750 break;
TatWai Chongf4fa8222019-06-17 12:08:14 -070010751 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010752 default:
10753 VIXL_UNIMPLEMENTED();
10754 break;
10755 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010756}
10757
Jacob Bramley0ce75842019-07-17 18:12:50 +010010758void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010759 USE(instr);
Jacob Bramley0ce75842019-07-17 18:12:50 +010010760 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
10761 LogicPRegister pdn = ReadPRegister(instr->GetPd());
10762 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010763 case PFIRST_p_p_p:
Jacob Bramley0ce75842019-07-17 18:12:50 +010010764 pfirst(pdn, pg, pdn);
10765 // TODO: Is this broken when pg == pdn?
10766 PredTest(kFormatVnB, pg, pdn);
10767 break;
10768 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010769 VIXL_UNIMPLEMENTED();
10770 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010771 }
10772}
10773
10774void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
10775 USE(instr);
10776 // This group only contains PTRUE{S}, and there are no unallocated encodings.
10777 VIXL_STATIC_ASSERT(
10778 SVEPredicateInitializeMask ==
10779 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
10780 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
10781 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
10782
10783 LogicPRegister pdn = ReadPRegister(instr->GetPd());
10784 VectorFormat vform = instr->GetSVEVectorFormat();
10785
10786 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
10787 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
10788}
10789
10790void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
10791 USE(instr);
10792 // This group only contains PNEXT, and there are no unallocated encodings.
10793 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
10794 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
10795
10796 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
10797 LogicPRegister pdn = ReadPRegister(instr->GetPd());
10798 VectorFormat vform = instr->GetSVEVectorFormat();
10799
10800 pnext(vform, pdn, pg, pdn);
10801 // TODO: Is this broken when pg == pdn?
10802 PredTest(vform, pg, pdn);
10803}
10804
10805void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
10806 const Instruction* instr) {
10807 USE(instr);
10808 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
10809 case RDFFR_p_p_f:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010810 case RDFFRS_p_p_f:
10811 VIXL_UNIMPLEMENTED();
10812 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010813 default:
10814 VIXL_UNIMPLEMENTED();
10815 break;
10816 }
10817}
10818
10819void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
10820 const Instruction* instr) {
10821 USE(instr);
10822 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010823 case RDFFR_p_f:
10824 VIXL_UNIMPLEMENTED();
10825 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010826 default:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010827 VIXL_UNIMPLEMENTED();
10828 break;
Jacob Bramley0ce75842019-07-17 18:12:50 +010010829 }
10830}
10831
10832void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
10833 USE(instr);
10834 switch (instr->Mask(SVEPredicateTestMask)) {
10835 case PTEST_p_p:
10836 PredTest(kFormatVnB,
10837 ReadPRegister(instr->ExtractBits(13, 10)),
10838 ReadPRegister(instr->GetPn()));
10839 break;
10840 default:
10841 VIXL_UNIMPLEMENTED();
10842 break;
10843 }
10844}
10845
10846void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
10847 USE(instr);
10848 switch (instr->Mask(SVEPredicateZeroMask)) {
10849 case PFALSE_p:
10850 pfalse(ReadPRegister(instr->GetPd()));
10851 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010852 default:
10853 VIXL_UNIMPLEMENTED();
10854 break;
10855 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010856}
10857
10858void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
10859 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010860 switch (instr->Mask(SVEPropagateBreakMask)) {
10861 case BRKPAS_p_p_pp:
10862 VIXL_UNIMPLEMENTED();
10863 break;
10864 case BRKPA_p_p_pp:
10865 VIXL_UNIMPLEMENTED();
10866 break;
10867 case BRKPBS_p_p_pp:
10868 VIXL_UNIMPLEMENTED();
10869 break;
10870 case BRKPB_p_p_pp:
10871 VIXL_UNIMPLEMENTED();
10872 break;
10873 default:
10874 VIXL_UNIMPLEMENTED();
10875 break;
10876 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010877}
10878
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010879void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
10880 uint64_t length = 0;
10881 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
10882 case ADDPL_r_ri:
10883 length = GetPredicateLengthInBytes();
10884 break;
10885 case ADDVL_r_ri:
10886 length = GetVectorLengthInBytes();
10887 break;
10888 default:
10889 VIXL_UNIMPLEMENTED();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010890 }
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010010891 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010892 WriteXRegister(instr->GetRd(),
10893 base + (length * instr->GetImmSVEVLScale()),
10894 LogRegWrites,
10895 Reg31IsStackPointer);
10896}
Jacob Bramley9e5da2a2019-08-06 18:52:07 +010010897
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010898void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
10899 int64_t scale = instr->GetImmSVEVLScale();
10900
10901 switch (instr->Mask(SVEStackFrameSizeMask)) {
10902 case RDVL_r_i:
10903 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
10904 break;
10905 default:
10906 VIXL_UNIMPLEMENTED();
10907 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010908}
10909
10910void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
10911 USE(instr);
TatWai Chong6205eb42019-09-24 10:07:20 +010010912
10913 // The only instruction in this group is `sel`, and there are no unused
10914 // encodings.
10915 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
10916
10917 VectorFormat vform = instr->GetSVEVectorFormat();
10918 SimVRegister& zd = ReadVRegister(instr->GetRd());
10919 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10920 SimVRegister& zn = ReadVRegister(instr->GetRn());
10921 SimVRegister& zm = ReadVRegister(instr->GetRm());
10922
10923 sel(vform, zd, pg, zn, zm);
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010924}
10925
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010926void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010927 USE(instr);
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010928 switch (instr->Mask(SVEFFRInitialiseMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010929 case SETFFR_f:
10930 VIXL_UNIMPLEMENTED();
10931 break;
Martyn Capewelld255bdb2019-08-13 16:27:30 +010010932 default:
10933 VIXL_UNIMPLEMENTED();
10934 break;
10935 }
10936}
10937
10938void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
10939 USE(instr);
10940 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +000010941 case WRFFR_f_p:
10942 VIXL_UNIMPLEMENTED();
10943 break;
10944 default:
10945 VIXL_UNIMPLEMENTED();
10946 break;
10947 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +000010948}
Alexandre Ramesd3832962016-07-04 15:03:43 +010010949
TatWai Chong6205eb42019-09-24 10:07:20 +010010950void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
10951 USE(instr);
10952 bool is_signed;
10953 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
10954 case LD1B_z_p_bi_u8:
10955 case LD1B_z_p_bi_u16:
10956 case LD1B_z_p_bi_u32:
10957 case LD1B_z_p_bi_u64:
10958 case LD1H_z_p_bi_u16:
10959 case LD1H_z_p_bi_u32:
10960 case LD1H_z_p_bi_u64:
10961 case LD1W_z_p_bi_u32:
10962 case LD1W_z_p_bi_u64:
10963 case LD1D_z_p_bi_u64:
10964 is_signed = false;
10965 break;
10966 case LD1SB_z_p_bi_s16:
10967 case LD1SB_z_p_bi_s32:
10968 case LD1SB_z_p_bi_s64:
10969 case LD1SH_z_p_bi_s32:
10970 case LD1SH_z_p_bi_s64:
10971 case LD1SW_z_p_bi_s64:
10972 is_signed = true;
10973 break;
10974 default:
10975 // This encoding group is complete, so no other values should be possible.
10976 VIXL_UNREACHABLE();
10977 is_signed = false;
10978 break;
10979 }
10980
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010981 int vl = GetVectorLengthInBytes();
TatWai Chong6205eb42019-09-24 10:07:20 +010010982 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
10983 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
Jacob Bramley6ebbba62019-10-09 15:02:10 +010010984 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10985 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10986 uint64_t offset =
10987 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010010988 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
TatWai Chong6205eb42019-09-24 10:07:20 +010010989 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10990 SVEStructuredLoadHelper(msize_in_bytes_log2,
10991 vform,
10992 ReadPRegister(instr->GetPgLow8()),
10993 instr->GetRt(),
10994 1,
10995 addr,
10996 is_signed);
10997}
10998
10999void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
11000 const Instruction* instr) {
11001 bool is_signed;
11002 USE(instr);
11003 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
11004 case LD1B_z_p_br_u8:
11005 case LD1B_z_p_br_u16:
11006 case LD1B_z_p_br_u32:
11007 case LD1B_z_p_br_u64:
11008 case LD1H_z_p_br_u16:
11009 case LD1H_z_p_br_u32:
11010 case LD1H_z_p_br_u64:
11011 case LD1W_z_p_br_u32:
11012 case LD1W_z_p_br_u64:
11013 case LD1D_z_p_br_u64:
11014 is_signed = false;
11015 break;
11016 case LD1SB_z_p_br_s16:
11017 case LD1SB_z_p_br_s32:
11018 case LD1SB_z_p_br_s64:
11019 case LD1SH_z_p_br_s32:
11020 case LD1SH_z_p_br_s64:
11021 case LD1SW_z_p_br_s64:
11022 is_signed = true;
11023 break;
11024 default:
11025 // This encoding group is complete, so no other values should be possible.
11026 VIXL_UNREACHABLE();
11027 is_signed = false;
11028 break;
11029 }
11030
11031 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11032 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11033 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11034 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11035 uint64_t offset = ReadXRegister(instr->GetRm());
11036 offset <<= msize_in_bytes_log2;
11037 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11038 SVEStructuredLoadHelper(msize_in_bytes_log2,
11039 vform,
11040 ReadPRegister(instr->GetPgLow8()),
11041 instr->GetRt(),
11042 1,
11043 addr,
11044 is_signed);
11045}
11046
Alexandre Ramesd3832962016-07-04 15:03:43 +010011047void Simulator::DoUnreachable(const Instruction* instr) {
11048 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11049 (instr->GetImmException() == kUnreachableOpcode));
11050
11051 fprintf(stream_,
11052 "Hit UNREACHABLE marker at pc=%p.\n",
11053 reinterpret_cast<const void*>(instr));
11054 abort();
11055}
11056
11057
11058void Simulator::DoTrace(const Instruction* instr) {
11059 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11060 (instr->GetImmException() == kTraceOpcode));
11061
11062 // Read the arguments encoded inline in the instruction stream.
11063 uint32_t parameters;
11064 uint32_t command;
11065
11066 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11067 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11068 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
11069
11070 switch (command) {
11071 case TRACE_ENABLE:
11072 SetTraceParameters(GetTraceParameters() | parameters);
11073 break;
11074 case TRACE_DISABLE:
11075 SetTraceParameters(GetTraceParameters() & ~parameters);
11076 break;
11077 default:
11078 VIXL_UNREACHABLE();
11079 }
11080
11081 WritePc(instr->GetInstructionAtOffset(kTraceLength));
11082}
11083
11084
11085void Simulator::DoLog(const Instruction* instr) {
11086 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11087 (instr->GetImmException() == kLogOpcode));
11088
11089 // Read the arguments encoded inline in the instruction stream.
11090 uint32_t parameters;
11091
11092 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11093 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
11094
11095 // We don't support a one-shot LOG_DISASM.
11096 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
11097 // Print the requested information.
11098 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
11099 if (parameters & LOG_REGS) PrintRegisters();
11100 if (parameters & LOG_VREGS) PrintVRegisters();
11101
11102 WritePc(instr->GetInstructionAtOffset(kLogLength));
11103}
11104
11105
11106void Simulator::DoPrintf(const Instruction* instr) {
11107 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11108 (instr->GetImmException() == kPrintfOpcode));
11109
11110 // Read the arguments encoded inline in the instruction stream.
11111 uint32_t arg_count;
11112 uint32_t arg_pattern_list;
11113 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11114 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
11115 memcpy(&arg_pattern_list,
11116 instr + kPrintfArgPatternListOffset,
11117 sizeof(arg_pattern_list));
11118
11119 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
11120 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
11121
11122 // We need to call the host printf function with a set of arguments defined by
11123 // arg_pattern_list. Because we don't know the types and sizes of the
11124 // arguments, this is very difficult to do in a robust and portable way. To
11125 // work around the problem, we pick apart the format string, and print one
11126 // format placeholder at a time.
11127
11128 // Allocate space for the format string. We take a copy, so we can modify it.
11129 // Leave enough space for one extra character per expected argument (plus the
11130 // '\0' termination).
11131 const char* format_base = ReadRegister<const char*>(0);
11132 VIXL_ASSERT(format_base != NULL);
11133 size_t length = strlen(format_base) + 1;
11134 char* const format = new char[length + arg_count];
11135
11136 // A list of chunks, each with exactly one format placeholder.
11137 const char* chunks[kPrintfMaxArgCount];
11138
11139 // Copy the format string and search for format placeholders.
11140 uint32_t placeholder_count = 0;
11141 char* format_scratch = format;
11142 for (size_t i = 0; i < length; i++) {
11143 if (format_base[i] != '%') {
11144 *format_scratch++ = format_base[i];
11145 } else {
11146 if (format_base[i + 1] == '%') {
11147 // Ignore explicit "%%" sequences.
11148 *format_scratch++ = format_base[i];
11149 i++;
11150 // Chunks after the first are passed as format strings to printf, so we
11151 // need to escape '%' characters in those chunks.
11152 if (placeholder_count > 0) *format_scratch++ = format_base[i];
11153 } else {
11154 VIXL_CHECK(placeholder_count < arg_count);
11155 // Insert '\0' before placeholders, and store their locations.
11156 *format_scratch++ = '\0';
11157 chunks[placeholder_count++] = format_scratch;
11158 *format_scratch++ = format_base[i];
11159 }
11160 }
11161 }
11162 VIXL_CHECK(placeholder_count == arg_count);
11163
11164 // Finally, call printf with each chunk, passing the appropriate register
11165 // argument. Normally, printf returns the number of bytes transmitted, so we
11166 // can emulate a single printf call by adding the result from each chunk. If
11167 // any call returns a negative (error) value, though, just return that value.
11168
11169 printf("%s", clr_printf);
11170
11171 // Because '\0' is inserted before each placeholder, the first string in
11172 // 'format' contains no format placeholders and should be printed literally.
11173 int result = printf("%s", format);
11174 int pcs_r = 1; // Start at x1. x0 holds the format string.
11175 int pcs_f = 0; // Start at d0.
11176 if (result >= 0) {
11177 for (uint32_t i = 0; i < placeholder_count; i++) {
11178 int part_result = -1;
11179
11180 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
11181 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
11182 switch (arg_pattern) {
11183 case kPrintfArgW:
11184 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
11185 break;
11186 case kPrintfArgX:
11187 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
11188 break;
11189 case kPrintfArgD:
11190 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
11191 break;
11192 default:
11193 VIXL_UNREACHABLE();
11194 }
11195
11196 if (part_result < 0) {
11197 // Handle error values.
11198 result = part_result;
11199 break;
11200 }
11201
11202 result += part_result;
11203 }
11204 }
11205
11206 printf("%s", clr_normal);
11207
11208 // Printf returns its result in x0 (just like the C library's printf).
11209 WriteXRegister(0, result);
11210
11211 // The printf parameters are inlined in the code, so skip them.
11212 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
11213
11214 // Set LR as if we'd just called a native printf function.
11215 WriteLr(ReadPc());
11216
11217 delete[] format;
11218}
11219
Alexandre Rames064e02d2016-07-12 11:53:13 +010011220
Alexandre Ramesca73ba02016-07-28 09:16:03 +010011221#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +010011222void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011223 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011224 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
11225 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011226 uintptr_t call_wrapper_address =
11227 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
11228 uintptr_t function_address =
11229 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -080011230 RuntimeCallType call_type = static_cast<RuntimeCallType>(
11231 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011232 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +010011233 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011234
11235 if (call_type == kCallRuntime) {
11236 WriteRegister(kLinkRegCode,
11237 instr->GetInstructionAtOffset(kRuntimeCallLength));
11238 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +010011239 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -080011240 // Read the return address from `lr` and write it into `pc`.
11241 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +010011242}
11243#else
11244void Simulator::DoRuntimeCall(const Instruction* instr) {
11245 USE(instr);
11246 VIXL_UNREACHABLE();
11247}
11248#endif
11249
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011250
11251void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
11252 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
11253
11254 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011255 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011256 std::numeric_limits<ElementType>::max());
11257
11258 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
11259
11260 size_t element_size = sizeof(ElementType);
11261 size_t offset = kConfigureCPUFeaturesListOffset;
11262
11263 // Read the kNone-terminated list of features.
11264 CPUFeatures parameters;
11265 while (true) {
11266 ElementType feature = Memory::Read<ElementType>(instr + offset);
11267 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +010011268 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010011269 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
11270 }
11271
11272 switch (instr->GetImmException()) {
11273 case kSetCPUFeaturesOpcode:
11274 SetCPUFeatures(parameters);
11275 break;
11276 case kEnableCPUFeaturesOpcode:
11277 GetCPUFeatures()->Combine(parameters);
11278 break;
11279 case kDisableCPUFeaturesOpcode:
11280 GetCPUFeatures()->Remove(parameters);
11281 break;
11282 default:
11283 VIXL_UNREACHABLE();
11284 break;
11285 }
11286
11287 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
11288}
11289
11290
11291void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
11292 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11293 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
11294 USE(instr);
11295
11296 saved_cpu_features_.push_back(*GetCPUFeatures());
11297}
11298
11299
11300void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
11301 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11302 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
11303 USE(instr);
11304
11305 SetCPUFeatures(saved_cpu_features_.back());
11306 saved_cpu_features_.pop_back();
11307}
11308
11309
Alexandre Ramesd3832962016-07-04 15:03:43 +010011310} // namespace aarch64
11311} // namespace vixl
11312
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010011313#endif // VIXL_INCLUDE_SIMULATOR_AARCH64