blob: db42b34509833735243b5c24ae798e2f85df82fc [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_));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100125}
126
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100127void Simulator::ResetSystemRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100128 // Reset the system registers.
129 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
130 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100131}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100132
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100133void Simulator::ResetRegisters() {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100134 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
135 WriteXRegister(i, 0xbadbeef);
136 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100137 // Returning to address 0 exits the Simulator.
138 WriteLr(kEndOfSimAddress);
139}
Pierre Langlois23703a72016-08-15 17:23:39 +0100140
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100141void Simulator::ResetVRegisters() {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800142 // 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 +0100143 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
144 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
TatWai Chonge3d059b2019-02-27 15:04:51 -0800145 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100146 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
147 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge3d059b2019-02-27 15:04:51 -0800148 // Encode the register number and (D-sized) lane into each NaN, to
149 // make them easier to trace.
150 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
151 (0x0000000000000001 * lane);
152 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
153 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100154 vregisters_[i].Insert(lane, nan_bits);
TatWai Chonge3d059b2019-02-27 15:04:51 -0800155 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100156 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100157}
TatWai Chonge3d059b2019-02-27 15:04:51 -0800158
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100159void Simulator::ResetPRegisters() {
160 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
161 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
162 // Ensure the register configuration fits in this bit encoding.
163 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
164 VIXL_ASSERT(lane_count <= UINT8_MAX);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700165 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100166 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
167 for (int lane = 0; lane < lane_count; lane++) {
TatWai Chonge0590cc2019-03-18 16:23:59 -0700168 // Encode the register number and (H-sized) lane into each lane slot.
169 uint16_t bits = (0x0100 * lane) | i;
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100170 pregisters_[i].Insert(lane, bits);
TatWai Chonge0590cc2019-03-18 16:23:59 -0700171 }
172 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100173}
TatWai Chonge0590cc2019-03-18 16:23:59 -0700174
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100175void Simulator::ResetState() {
176 ResetSystemRegisters();
177 ResetRegisters();
178 ResetVRegisters();
179 ResetPRegisters();
Martyn Capewellcb963f72018-10-22 15:25:28 +0100180
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100181 pc_ = NULL;
182 pc_modified_ = false;
183
184 // BTI state.
Martyn Capewellcb963f72018-10-22 15:25:28 +0100185 btype_ = DefaultBType;
186 next_btype_ = DefaultBType;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100187}
188
Jacob Bramley9d06c4d2019-05-13 18:15:06 +0100189void Simulator::SetVectorLengthInBits(unsigned vector_length) {
190 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
191 (vector_length <= kZRegMaxSize));
192 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
193 vector_length_ = vector_length;
194
195 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
196 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
197 }
198 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
199 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
200 }
201
202 ResetVRegisters();
203 ResetPRegisters();
204}
Alexandre Ramesd3832962016-07-04 15:03:43 +0100205
206Simulator::~Simulator() {
207 delete[] stack_;
208 // The decoder may outlive the simulator.
209 decoder_->RemoveVisitor(print_disasm_);
210 delete print_disasm_;
211
212 decoder_->RemoveVisitor(instrumentation_);
213 delete instrumentation_;
214}
215
216
217void Simulator::Run() {
218 // Flush any written registers before executing anything, so that
219 // manually-set registers are logged _before_ the first instruction.
220 LogAllWrittenRegisters();
221
222 while (pc_ != kEndOfSimAddress) {
223 ExecuteInstruction();
224 }
225}
226
227
228void Simulator::RunFrom(const Instruction* first) {
Jacob Bramleye79723a2016-06-07 17:50:47 +0100229 WritePc(first, NoBranchLog);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100230 Run();
231}
232
233
234const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
235 "x6", "x7", "x8", "x9", "x10", "x11",
236 "x12", "x13", "x14", "x15", "x16", "x17",
237 "x18", "x19", "x20", "x21", "x22", "x23",
238 "x24", "x25", "x26", "x27", "x28", "x29",
239 "lr", "xzr", "sp"};
240
241const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
242 "w6", "w7", "w8", "w9", "w10", "w11",
243 "w12", "w13", "w14", "w15", "w16", "w17",
244 "w18", "w19", "w20", "w21", "w22", "w23",
245 "w24", "w25", "w26", "w27", "w28", "w29",
246 "w30", "wzr", "wsp"};
247
Carey Williamsd8bb3572018-04-10 11:58:07 +0100248const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
249 "h6", "h7", "h8", "h9", "h10", "h11",
250 "h12", "h13", "h14", "h15", "h16", "h17",
251 "h18", "h19", "h20", "h21", "h22", "h23",
252 "h24", "h25", "h26", "h27", "h28", "h29",
253 "h30", "h31"};
254
Alexandre Ramesd3832962016-07-04 15:03:43 +0100255const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
256 "s6", "s7", "s8", "s9", "s10", "s11",
257 "s12", "s13", "s14", "s15", "s16", "s17",
258 "s18", "s19", "s20", "s21", "s22", "s23",
259 "s24", "s25", "s26", "s27", "s28", "s29",
260 "s30", "s31"};
261
262const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
263 "d6", "d7", "d8", "d9", "d10", "d11",
264 "d12", "d13", "d14", "d15", "d16", "d17",
265 "d18", "d19", "d20", "d21", "d22", "d23",
266 "d24", "d25", "d26", "d27", "d28", "d29",
267 "d30", "d31"};
268
269const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
270 "v6", "v7", "v8", "v9", "v10", "v11",
271 "v12", "v13", "v14", "v15", "v16", "v17",
272 "v18", "v19", "v20", "v21", "v22", "v23",
273 "v24", "v25", "v26", "v27", "v28", "v29",
274 "v30", "v31"};
275
TatWai Chong72d2e562019-05-16 11:22:22 -0700276const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
277 "z6", "z7", "z8", "z9", "z10", "z11",
278 "z12", "z13", "z14", "z15", "z16", "z17",
279 "z18", "z19", "z20", "z21", "z22", "z23",
280 "z24", "z25", "z26", "z27", "z28", "z29",
281 "z30", "z31"};
282
Alexandre Ramesd3832962016-07-04 15:03:43 +0100283
284const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
285 VIXL_ASSERT(code < kNumberOfRegisters);
286 // If the code represents the stack pointer, index the name after zr.
287 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
288 code = kZeroRegCode + 1;
289 }
290 return wreg_names[code];
291}
292
293
294const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
295 VIXL_ASSERT(code < kNumberOfRegisters);
296 // If the code represents the stack pointer, index the name after zr.
297 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
298 code = kZeroRegCode + 1;
299 }
300 return xreg_names[code];
301}
302
303
Carey Williamsd8bb3572018-04-10 11:58:07 +0100304const char* Simulator::HRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100305 VIXL_ASSERT(code < kNumberOfVRegisters);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100306 return hreg_names[code];
307}
308
309
Alexandre Ramesd3832962016-07-04 15:03:43 +0100310const char* Simulator::SRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100311 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100312 return sreg_names[code];
313}
314
315
316const char* Simulator::DRegNameForCode(unsigned code) {
Jacob Bramleycf93ad52019-04-15 16:00:22 +0100317 VIXL_ASSERT(code < kNumberOfVRegisters);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100318 return dreg_names[code];
319}
320
321
322const char* Simulator::VRegNameForCode(unsigned code) {
323 VIXL_ASSERT(code < kNumberOfVRegisters);
324 return vreg_names[code];
325}
326
327
TatWai Chong72d2e562019-05-16 11:22:22 -0700328const char* Simulator::ZRegNameForCode(unsigned code) {
329 VIXL_ASSERT(code < kNumberOfZRegisters);
330 return zreg_names[code];
331}
332
333
Alexandre Ramesd3832962016-07-04 15:03:43 +0100334#define COLOUR(colour_code) "\033[0;" colour_code "m"
335#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
Jacob Bramleye79723a2016-06-07 17:50:47 +0100336#define COLOUR_HIGHLIGHT "\033[43m"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100337#define NORMAL ""
338#define GREY "30"
339#define RED "31"
340#define GREEN "32"
341#define YELLOW "33"
342#define BLUE "34"
343#define MAGENTA "35"
344#define CYAN "36"
345#define WHITE "37"
346void Simulator::SetColouredTrace(bool value) {
347 coloured_trace_ = value;
348
349 clr_normal = value ? COLOUR(NORMAL) : "";
350 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
351 clr_flag_value = value ? COLOUR(NORMAL) : "";
352 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
353 clr_reg_value = value ? COLOUR(CYAN) : "";
354 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
355 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
356 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
357 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
358 clr_warning_message = value ? COLOUR(YELLOW) : "";
359 clr_printf = value ? COLOUR(GREEN) : "";
Jacob Bramleye79723a2016-06-07 17:50:47 +0100360 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +0100361
362 if (value) {
363 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
364 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
365 } else {
366 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
367 print_disasm_->SetCPUFeaturesSuffix("");
368 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100369}
370
371
372void Simulator::SetTraceParameters(int parameters) {
373 bool disasm_before = trace_parameters_ & LOG_DISASM;
374 trace_parameters_ = parameters;
375 bool disasm_after = trace_parameters_ & LOG_DISASM;
376
377 if (disasm_before != disasm_after) {
378 if (disasm_after) {
379 decoder_->InsertVisitorBefore(print_disasm_, this);
380 } else {
381 decoder_->RemoveVisitor(print_disasm_);
382 }
383 }
384}
385
386
387void Simulator::SetInstructionStats(bool value) {
388 if (value != instruction_stats_) {
389 if (value) {
390 if (instrumentation_ == NULL) {
391 // Set the sample period to 10, as the VIXL examples and tests are
392 // short.
393 instrumentation_ = new Instrument("vixl_stats.csv", 10);
394 }
395 decoder_->AppendVisitor(instrumentation_);
396 } else if (instrumentation_ != NULL) {
397 decoder_->RemoveVisitor(instrumentation_);
398 }
399 instruction_stats_ = value;
400 }
401}
402
403// Helpers ---------------------------------------------------------------------
404uint64_t Simulator::AddWithCarry(unsigned reg_size,
405 bool set_flags,
406 uint64_t left,
407 uint64_t right,
408 int carry_in) {
409 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
410 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
411
412 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
413 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
414 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
415
416 left &= reg_mask;
417 right &= reg_mask;
418 uint64_t result = (left + right + carry_in) & reg_mask;
419
420 if (set_flags) {
421 ReadNzcv().SetN(CalcNFlag(result, reg_size));
422 ReadNzcv().SetZ(CalcZFlag(result));
423
424 // Compute the C flag by comparing the result to the max unsigned integer.
425 uint64_t max_uint_2op = max_uint - carry_in;
426 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
427 ReadNzcv().SetC(C ? 1 : 0);
428
429 // Overflow iff the sign bit is the same for the two inputs and different
430 // for the result.
431 uint64_t left_sign = left & sign_mask;
432 uint64_t right_sign = right & sign_mask;
433 uint64_t result_sign = result & sign_mask;
434 bool V = (left_sign == right_sign) && (left_sign != result_sign);
435 ReadNzcv().SetV(V ? 1 : 0);
436
437 LogSystemRegister(NZCV);
438 }
439 return result;
440}
441
442
443int64_t Simulator::ShiftOperand(unsigned reg_size,
444 int64_t value,
445 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100446 unsigned amount) const {
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000447 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
Alexandre Ramesd3832962016-07-04 15:03:43 +0100448 if (amount == 0) {
449 return value;
450 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000451 uint64_t uvalue = static_cast<uint64_t>(value);
452 uint64_t mask = kWRegMask;
453 bool is_negative = (uvalue & kWSignMask) != 0;
454 if (reg_size == kXRegSize) {
455 mask = kXRegMask;
456 is_negative = (uvalue & kXSignMask) != 0;
457 }
458
Alexandre Ramesd3832962016-07-04 15:03:43 +0100459 switch (shift_type) {
460 case LSL:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000461 uvalue <<= amount;
462 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100463 case LSR:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000464 uvalue >>= amount;
465 break;
466 case ASR:
467 uvalue >>= amount;
468 if (is_negative) {
469 // Simulate sign-extension to 64 bits.
470 uvalue |= ~UINT64_C(0) << (reg_size - amount);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100471 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000472 break;
473 case ROR: {
Martyn Capewellfb8e3df2016-11-03 15:50:19 +0000474 uvalue = RotateRight(uvalue, amount, reg_size);
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000475 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100476 }
477 default:
478 VIXL_UNIMPLEMENTED();
479 return 0;
480 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000481 uvalue &= mask;
482
483 int64_t result;
484 memcpy(&result, &uvalue, sizeof(result));
485 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100486}
487
488
489int64_t Simulator::ExtendValue(unsigned reg_size,
490 int64_t value,
491 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100492 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100493 switch (extend_type) {
494 case UXTB:
495 value &= kByteMask;
496 break;
497 case UXTH:
498 value &= kHalfWordMask;
499 break;
500 case UXTW:
501 value &= kWordMask;
502 break;
503 case SXTB:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000504 value &= kByteMask;
505 if ((value & 0x80) != 0) {
506 value |= ~UINT64_C(0) << 8;
507 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100508 break;
509 case SXTH:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000510 value &= kHalfWordMask;
511 if ((value & 0x8000) != 0) {
512 value |= ~UINT64_C(0) << 16;
513 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100514 break;
515 case SXTW:
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000516 value &= kWordMask;
517 if ((value & 0x80000000) != 0) {
518 value |= ~UINT64_C(0) << 32;
519 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100520 break;
521 case UXTX:
522 case SXTX:
523 break;
524 default:
525 VIXL_UNREACHABLE();
526 }
Martyn Capewell5b24fb32016-11-02 18:52:55 +0000527 return ShiftOperand(reg_size, value, LSL, left_shift);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100528}
529
530
531void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
532 AssertSupportedFPCR();
533
534 // TODO: This assumes that the C++ implementation handles comparisons in the
535 // way that we expect (as per AssertSupportedFPCR()).
536 bool process_exception = false;
Jacob Bramleyca789742018-09-13 14:25:46 +0100537 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100538 ReadNzcv().SetRawValue(FPUnorderedFlag);
539 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
540 (trap == EnableTrap)) {
541 process_exception = true;
542 }
543 } else if (val0 < val1) {
544 ReadNzcv().SetRawValue(FPLessThanFlag);
545 } else if (val0 > val1) {
546 ReadNzcv().SetRawValue(FPGreaterThanFlag);
547 } else if (val0 == val1) {
548 ReadNzcv().SetRawValue(FPEqualFlag);
549 } else {
550 VIXL_UNREACHABLE();
551 }
552 LogSystemRegister(NZCV);
553 if (process_exception) FPProcessException();
554}
555
556
Alexandre Rames868bfc42016-07-19 17:10:48 +0100557uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
558 VIXL_ASSERT(mem_op.IsValid());
559 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
560 if (mem_op.IsImmediateOffset()) {
561 return base + mem_op.GetOffset();
562 } else {
563 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
564 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
Pierre Langloisf5348ce2016-09-22 11:15:35 +0100565 unsigned shift_amount = mem_op.GetShiftAmount();
Alexandre Rames868bfc42016-07-19 17:10:48 +0100566 if (mem_op.GetShift() != NO_SHIFT) {
567 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
568 }
569 if (mem_op.GetExtend() != NO_EXTEND) {
570 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
571 }
572 return static_cast<uint64_t>(base + offset);
573 }
574}
575
576
Alexandre Ramesd3832962016-07-04 15:03:43 +0100577Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
578 unsigned reg_size, unsigned lane_size) {
579 VIXL_ASSERT(reg_size >= lane_size);
580
581 uint32_t format = 0;
582 if (reg_size != lane_size) {
583 switch (reg_size) {
584 default:
585 VIXL_UNREACHABLE();
586 break;
587 case kQRegSizeInBytes:
588 format = kPrintRegAsQVector;
589 break;
590 case kDRegSizeInBytes:
591 format = kPrintRegAsDVector;
592 break;
593 }
594 }
595
596 switch (lane_size) {
597 default:
598 VIXL_UNREACHABLE();
599 break;
600 case kQRegSizeInBytes:
601 format |= kPrintReg1Q;
602 break;
603 case kDRegSizeInBytes:
604 format |= kPrintReg1D;
605 break;
606 case kSRegSizeInBytes:
607 format |= kPrintReg1S;
608 break;
609 case kHRegSizeInBytes:
610 format |= kPrintReg1H;
611 break;
612 case kBRegSizeInBytes:
613 format |= kPrintReg1B;
614 break;
615 }
616 // These sizes would be duplicate case labels.
617 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
618 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
619 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
620 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
621
622 return static_cast<PrintRegisterFormat>(format);
623}
624
625
626Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
627 VectorFormat vform) {
628 switch (vform) {
629 default:
630 VIXL_UNREACHABLE();
631 return kPrintReg16B;
632 case kFormat16B:
633 return kPrintReg16B;
634 case kFormat8B:
635 return kPrintReg8B;
636 case kFormat8H:
637 return kPrintReg8H;
638 case kFormat4H:
639 return kPrintReg4H;
640 case kFormat4S:
641 return kPrintReg4S;
642 case kFormat2S:
643 return kPrintReg2S;
644 case kFormat2D:
645 return kPrintReg2D;
646 case kFormat1D:
647 return kPrintReg1D;
648
649 case kFormatB:
650 return kPrintReg1B;
651 case kFormatH:
652 return kPrintReg1H;
653 case kFormatS:
654 return kPrintReg1S;
655 case kFormatD:
656 return kPrintReg1D;
657 }
658}
659
660
661Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
662 VectorFormat vform) {
663 switch (vform) {
664 default:
665 VIXL_UNREACHABLE();
666 return kPrintReg16B;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100667 case kFormat8H:
668 return kPrintReg8HFP;
669 case kFormat4H:
670 return kPrintReg4HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100671 case kFormat4S:
672 return kPrintReg4SFP;
673 case kFormat2S:
674 return kPrintReg2SFP;
675 case kFormat2D:
676 return kPrintReg2DFP;
677 case kFormat1D:
678 return kPrintReg1DFP;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100679 case kFormatH:
680 return kPrintReg1HFP;
Alexandre Ramesd3832962016-07-04 15:03:43 +0100681 case kFormatS:
682 return kPrintReg1SFP;
683 case kFormatD:
684 return kPrintReg1DFP;
685 }
686}
687
688
689void Simulator::PrintWrittenRegisters() {
690 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
691 if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
692 }
693}
694
695
696void Simulator::PrintWrittenVRegisters() {
697 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
698 // At this point there is no type information, so print as a raw 1Q.
699 if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
700 }
701}
702
703
704void Simulator::PrintSystemRegisters() {
705 PrintSystemRegister(NZCV);
706 PrintSystemRegister(FPCR);
707}
708
709
710void Simulator::PrintRegisters() {
711 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
712 PrintRegister(i);
713 }
714}
715
716
717void Simulator::PrintVRegisters() {
718 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
719 // At this point there is no type information, so print as a raw 1Q.
720 PrintVRegister(i, kPrintReg1Q);
721 }
722}
723
724
TatWai Chong72d2e562019-05-16 11:22:22 -0700725void Simulator::PrintZRegisters() {
726 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
727 PrintZRegister(i);
728 }
729}
730
731
Alexandre Ramesd3832962016-07-04 15:03:43 +0100732// Print a register's name and raw value.
733//
734// Only the least-significant `size_in_bytes` bytes of the register are printed,
735// but the value is aligned as if the whole register had been printed.
736//
737// For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
738// -- the default -- so that the whole register is printed. Other values of
739// size_in_bytes are intended for use when the register hasn't actually been
740// updated (such as in PrintWrite).
741//
742// No newline is printed. This allows the caller to print more details (such as
743// a memory access annotation).
744void Simulator::PrintRegisterRawHelper(unsigned code,
745 Reg31Mode r31mode,
746 int size_in_bytes) {
747 // The template for all supported sizes.
748 // "# x{code}: 0xffeeddccbbaa9988"
749 // "# w{code}: 0xbbaa9988"
750 // "# w{code}<15:0>: 0x9988"
751 // "# w{code}<7:0>: 0x88"
752 unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
753
754 const char* name = "";
755 const char* suffix = "";
756 switch (size_in_bytes) {
757 case kXRegSizeInBytes:
758 name = XRegNameForCode(code, r31mode);
759 break;
760 case kWRegSizeInBytes:
761 name = WRegNameForCode(code, r31mode);
762 break;
763 case 2:
764 name = WRegNameForCode(code, r31mode);
765 suffix = "<15:0>";
766 padding_chars -= strlen(suffix);
767 break;
768 case 1:
769 name = WRegNameForCode(code, r31mode);
770 suffix = "<7:0>";
771 padding_chars -= strlen(suffix);
772 break;
773 default:
774 VIXL_UNREACHABLE();
775 }
776 fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
777
778 // Print leading padding spaces.
779 VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
780 for (unsigned i = 0; i < padding_chars; i++) {
781 putc(' ', stream_);
782 }
783
784 // Print the specified bits in hexadecimal format.
785 uint64_t bits = ReadRegister<uint64_t>(code, r31mode);
786 bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
787 VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
788
789 int chars = size_in_bytes * 2;
790 fprintf(stream_,
791 "%s0x%0*" PRIx64 "%s",
792 clr_reg_value,
793 chars,
794 bits,
795 clr_normal);
796}
797
798
799void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
800 registers_[code].NotifyRegisterLogged();
801
802 // Don't print writes into xzr.
803 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
804 return;
805 }
806
807 // The template for all x and w registers:
808 // "# x{code}: 0x{value}"
809 // "# w{code}: 0x{value}"
810
811 PrintRegisterRawHelper(code, r31mode);
812 fprintf(stream_, "\n");
813}
814
815
816// Print a register's name and raw value.
817//
818// The `bytes` and `lsb` arguments can be used to limit the bytes that are
819// printed. These arguments are intended for use in cases where register hasn't
820// actually been updated (such as in PrintVWrite).
821//
822// No newline is printed. This allows the caller to print more details (such as
823// a floating-point interpretation or a memory access annotation).
824void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
825 // The template for vector types:
826 // "# v{code}: 0xffeeddccbbaa99887766554433221100".
827 // An example with bytes=4 and lsb=8:
828 // "# v{code}: 0xbbaa9988 ".
829 fprintf(stream_,
TatWai Chong72d2e562019-05-16 11:22:22 -0700830 "# %s%13s: %s",
Alexandre Ramesd3832962016-07-04 15:03:43 +0100831 clr_vreg_name,
832 VRegNameForCode(code),
833 clr_vreg_value);
834
835 int msb = lsb + bytes - 1;
836 int byte = kQRegSizeInBytes - 1;
837
838 // Print leading padding spaces. (Two spaces per byte.)
839 while (byte > msb) {
840 fprintf(stream_, " ");
841 byte--;
842 }
843
844 // Print the specified part of the value, byte by byte.
845 qreg_t rawbits = ReadQRegister(code);
846 fprintf(stream_, "0x");
847 while (byte >= lsb) {
848 fprintf(stream_, "%02x", rawbits.val[byte]);
849 byte--;
850 }
851
852 // Print trailing padding spaces.
853 while (byte >= 0) {
854 fprintf(stream_, " ");
855 byte--;
856 }
857 fprintf(stream_, "%s", clr_normal);
858}
859
860
TatWai Chong72d2e562019-05-16 11:22:22 -0700861void Simulator::PrintZRegisterRawHelper(
862 unsigned code, int lane_size, int data_size, int bytes, int start_byte) {
863 VIXL_ASSERT(lane_size >= data_size);
864 // Currently only support printing of 128-bit length value and it must have
865 // 128-bit alignement.
866 VIXL_ASSERT((bytes % kQRegSizeInBytes) == 0);
867 VIXL_ASSERT((start_byte % kQRegSizeInBytes) == 0);
868
869 // The template for vector types:
870 // "# z{code}<m+127:m>: 0x33333333222222221111111100000000",
871 // where m is multiple of 128b.
872 // An example with bytes=16 starting from a bit 128:
873 // "# z{code}<255:128>: 0x77777777666666665555555544444444".
874 // A qlane from a bit zero with lane=4, data=2, and bytes=16:
875 // "# z{code}<127:0>: 0x 3333 2222 1111 0000".
876
877 std::stringstream prefix;
878 prefix << ZRegNameForCode(code) << "<"
879 << ((start_byte + bytes) * kBitsPerByte) - 1 << ":"
880 << (start_byte * kBitsPerByte) << ">";
881
882 fprintf(stream_,
883 "# %s%13s: %s0x",
884 clr_vreg_name,
885 prefix.str().c_str(),
886 clr_vreg_value);
887
888 // Print the 128-bit length of register, lane by lane.
889 for (int i = kQRegSizeInBytes / lane_size; i > 0; i--) {
890 VIXL_ASSERT((kQRegSizeInBytes % lane_size) == 0);
891 // Skip the irrelevant part of value from lane if any.
892 for (int skips = lane_size - data_size; skips > 0; skips--) {
893 fprintf(stream_, " ");
894 bytes--;
895 }
896
897 // [`first_byte`, `last_byte`] represent the interval of bytes that are
898 // printed in each lane.
899 int last_byte = start_byte + bytes - 1;
900 int first_byte = last_byte - data_size + 1;
901 // Print the specified part of the value, byte by byte.
902 int lane_idx = last_byte >> kQRegSizeInBytesLog2;
903 qreg_t rawbits = vregisters_[code].GetLane<qreg_t>(lane_idx);
904 for (int byte = last_byte; byte >= first_byte; --byte) {
905 fprintf(stream_, "%02x", rawbits.val[byte % kQRegSizeInBytes]);
906 bytes--;
907 }
908 }
909 fprintf(stream_, "%s", clr_normal);
910}
911
912
Alexandre Ramesd3832962016-07-04 15:03:43 +0100913// Print each of the specified lanes of a register as a float or double value.
914//
915// The `lane_count` and `lslane` arguments can be used to limit the lanes that
916// are printed. These arguments are intended for use in cases where register
917// hasn't actually been updated (such as in PrintVWrite).
918//
919// No newline is printed. This allows the caller to print more details (such as
920// a memory access annotation).
921void Simulator::PrintVRegisterFPHelper(unsigned code,
922 unsigned lane_size_in_bytes,
923 int lane_count,
924 int rightmost_lane) {
Carey Williamsd8bb3572018-04-10 11:58:07 +0100925 VIXL_ASSERT((lane_size_in_bytes == kHRegSizeInBytes) ||
926 (lane_size_in_bytes == kSRegSizeInBytes) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +0100927 (lane_size_in_bytes == kDRegSizeInBytes));
928
929 unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
930 VIXL_ASSERT(msb <= kQRegSizeInBytes);
931
932 // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
933 // name is used:
Carey Williamsd8bb3572018-04-10 11:58:07 +0100934 // " (h{code}: {value})"
Alexandre Ramesd3832962016-07-04 15:03:43 +0100935 // " (s{code}: {value})"
936 // " (d{code}: {value})"
937 // For vector types, "..." is used to represent one or more omitted lanes.
938 // " (..., {value}, {value}, ...)"
Carey Williamsd8bb3572018-04-10 11:58:07 +0100939 if (lane_size_in_bytes == kHRegSizeInBytes) {
940 // TODO: Trace tests will fail until we regenerate them.
941 return;
942 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100943 if ((lane_count == 1) && (rightmost_lane == 0)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +0100944 const char* name;
945 switch (lane_size_in_bytes) {
946 case kHRegSizeInBytes:
947 name = HRegNameForCode(code);
948 break;
949 case kSRegSizeInBytes:
950 name = SRegNameForCode(code);
951 break;
952 case kDRegSizeInBytes:
953 name = DRegNameForCode(code);
954 break;
955 default:
Pierre Langlois226fbe42018-05-14 11:29:08 +0100956 name = NULL;
Carey Williamsd8bb3572018-04-10 11:58:07 +0100957 VIXL_UNREACHABLE();
958 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100959 fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
960 } else {
961 if (msb < (kQRegSizeInBytes - 1)) {
962 fprintf(stream_, " (..., ");
963 } else {
964 fprintf(stream_, " (");
965 }
966 }
967
968 // Print the list of values.
969 const char* separator = "";
970 int leftmost_lane = rightmost_lane + lane_count - 1;
971 for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
Carey Williamsd8bb3572018-04-10 11:58:07 +0100972 double value;
973 switch (lane_size_in_bytes) {
974 case kHRegSizeInBytes:
Jacob Bramleyca789742018-09-13 14:25:46 +0100975 value = ReadVRegister(code).GetLane<uint16_t>(lane);
Carey Williamsd8bb3572018-04-10 11:58:07 +0100976 break;
977 case kSRegSizeInBytes:
978 value = ReadVRegister(code).GetLane<float>(lane);
979 break;
980 case kDRegSizeInBytes:
981 value = ReadVRegister(code).GetLane<double>(lane);
982 break;
983 default:
984 value = 0.0;
985 VIXL_UNREACHABLE();
986 }
Jacob Bramleyca789742018-09-13 14:25:46 +0100987 if (IsNaN(value)) {
Alexandre Rames6b5fe942016-07-22 17:17:23 +0100988 // The output for NaNs is implementation defined. Always print `nan`, so
989 // that traces are coherent across different implementations.
990 fprintf(stream_, "%s%snan%s", separator, clr_vreg_value, clr_normal);
991 } else {
992 fprintf(stream_,
993 "%s%s%#g%s",
994 separator,
995 clr_vreg_value,
996 value,
997 clr_normal);
998 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100999 separator = ", ";
1000 }
1001
1002 if (rightmost_lane > 0) {
1003 fprintf(stream_, ", ...");
1004 }
1005 fprintf(stream_, ")");
1006}
1007
1008
1009void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
1010 vregisters_[code].NotifyRegisterLogged();
1011
1012 int lane_size_log2 = format & kPrintRegLaneSizeMask;
1013
1014 int reg_size_log2;
1015 if (format & kPrintRegAsQVector) {
1016 reg_size_log2 = kQRegSizeInBytesLog2;
1017 } else if (format & kPrintRegAsDVector) {
1018 reg_size_log2 = kDRegSizeInBytesLog2;
1019 } else {
1020 // Scalar types.
1021 reg_size_log2 = lane_size_log2;
1022 }
1023
1024 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
1025 int lane_size = 1 << lane_size_log2;
1026
1027 // The template for vector types:
1028 // "# v{code}: 0x{rawbits} (..., {value}, ...)".
1029 // The template for scalar types:
1030 // "# v{code}: 0x{rawbits} ({reg}:{value})".
1031 // The values in parentheses after the bit representations are floating-point
1032 // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
1033
1034 PrintVRegisterRawHelper(code);
1035 if (format & kPrintRegAsFP) {
1036 PrintVRegisterFPHelper(code, lane_size, lane_count);
1037 }
1038
1039 fprintf(stream_, "\n");
1040}
1041
TatWai Chong72d2e562019-05-16 11:22:22 -07001042void Simulator::PrintZRegister(unsigned code,
1043 PrintRegisterFormat format,
1044 int bytes,
1045 int start_byte) {
1046 vregisters_[code].NotifyRegisterLogged();
1047 if (bytes == 0) {
1048 // If no byte size specified, print the whole length of register.
1049 bytes = GetVectorLengthInBytes();
1050 }
1051
1052 int lane_size;
1053 switch (format) {
1054 case kPrintRegLaneSizeUnknown:
1055 // If no lane size specified, set to 128-bit lane by default.
1056 lane_size = kQRegSizeInBytes;
1057 break;
1058 case kPrintRegLaneSizeB:
1059 case kPrintRegLaneSizeH:
1060 case kPrintRegLaneSizeS:
1061 case kPrintRegLaneSizeD:
1062 lane_size = GetPrintRegLaneSizeInBytes(format);
1063 break;
1064 default:
1065 lane_size = 0;
1066 VIXL_UNIMPLEMENTED();
1067 break;
1068 }
1069
1070 while (bytes > 0) {
1071 PrintZRegisterRawHelper(code,
1072 lane_size,
1073 lane_size,
1074 kQRegSizeInBytes,
1075 start_byte + bytes - kQRegSizeInBytes);
1076 bytes -= kQRegSizeInBytes;
1077 fprintf(stream_, "\n");
1078 }
1079}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001080
1081void Simulator::PrintSystemRegister(SystemRegister id) {
1082 switch (id) {
1083 case NZCV:
1084 fprintf(stream_,
1085 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1086 clr_flag_name,
1087 clr_flag_value,
1088 ReadNzcv().GetN(),
1089 ReadNzcv().GetZ(),
1090 ReadNzcv().GetC(),
1091 ReadNzcv().GetV(),
1092 clr_normal);
1093 break;
1094 case FPCR: {
1095 static const char* rmode[] = {"0b00 (Round to Nearest)",
1096 "0b01 (Round towards Plus Infinity)",
1097 "0b10 (Round towards Minus Infinity)",
1098 "0b11 (Round towards Zero)"};
Jacob Bramleyca789742018-09-13 14:25:46 +01001099 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001100 fprintf(stream_,
1101 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1102 clr_flag_name,
1103 clr_flag_value,
1104 ReadFpcr().GetAHP(),
1105 ReadFpcr().GetDN(),
1106 ReadFpcr().GetFZ(),
1107 rmode[ReadFpcr().GetRMode()],
1108 clr_normal);
1109 break;
1110 }
1111 default:
1112 VIXL_UNREACHABLE();
1113 }
1114}
1115
1116
1117void Simulator::PrintRead(uintptr_t address,
1118 unsigned reg_code,
1119 PrintRegisterFormat format) {
1120 registers_[reg_code].NotifyRegisterLogged();
1121
1122 USE(format);
1123
1124 // The template is "# {reg}: 0x{value} <- {address}".
1125 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
1126 fprintf(stream_,
1127 " <- %s0x%016" PRIxPTR "%s\n",
1128 clr_memory_address,
1129 address,
1130 clr_normal);
1131}
1132
1133
1134void Simulator::PrintVRead(uintptr_t address,
1135 unsigned reg_code,
1136 PrintRegisterFormat format,
1137 unsigned lane) {
1138 vregisters_[reg_code].NotifyRegisterLogged();
1139
1140 // The template is "# v{code}: 0x{rawbits} <- address".
1141 PrintVRegisterRawHelper(reg_code);
1142 if (format & kPrintRegAsFP) {
1143 PrintVRegisterFPHelper(reg_code,
1144 GetPrintRegLaneSizeInBytes(format),
1145 GetPrintRegLaneCount(format),
1146 lane);
1147 }
1148 fprintf(stream_,
1149 " <- %s0x%016" PRIxPTR "%s\n",
1150 clr_memory_address,
1151 address,
1152 clr_normal);
1153}
1154
TatWai Chong72d2e562019-05-16 11:22:22 -07001155void Simulator::PrintZRead(uintptr_t address,
1156 unsigned reg_code,
1157 PrintRegisterFormat format,
1158 unsigned data_size,
1159 int bytes,
1160 int start_byte) {
1161 vregisters_[reg_code].NotifyRegisterLogged();
1162
1163 // The templates:
1164 // "# v{code}<m:n>: 0x{rawbits} <- {address}"
1165 // An example that prints an unpredicated memory read from a particular memory
1166 // location to the specified portion of Z register.
1167 // 0x00007fff00000000: 0x11110000 0x33332222 0x55554444 0x77776666
1168 // 0x00007fff00000010: 0x99998888 0xbbbbaaaa 0xddddcccc 0xffffeeee
1169 // The corresponding output is:
1170 // Zt<255:128>: 0x77776666555544443333222211110000 <- 0x00007fff00000000
1171 // Zt<383:256>: 0xffffeeeeddddccccbbbbaaaa99998888 <- 0x00007fff00000010
1172
1173 int lane_size = GetPrintRegLaneSizeInBytes(format);
1174 if (data_size == 0) {
1175 // Let the full lane of value are relevent.
1176 data_size = lane_size;
1177 }
1178 if (bytes == 0) {
1179 // If no byte size specified, print the whole length of register.
1180 bytes = GetVectorLengthInBytes();
1181 }
1182
1183 const int last_byte = start_byte + bytes - 1;
1184 while (start_byte < last_byte) {
1185 PrintZRegisterRawHelper(reg_code,
1186 lane_size,
1187 data_size,
1188 kQRegSizeInBytes,
1189 start_byte);
1190 fprintf(stream_,
1191 " <- %s0x%016" PRIxPTR "%s\n",
1192 clr_memory_address,
1193 address,
1194 clr_normal);
1195 start_byte += kQRegSizeInBytes;
1196 address += kQRegSizeInBytes;
1197 }
1198}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001199
1200void Simulator::PrintWrite(uintptr_t address,
1201 unsigned reg_code,
1202 PrintRegisterFormat format) {
1203 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1204
1205 // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
1206 // and readable, the value is aligned with the values in the register trace.
1207 PrintRegisterRawHelper(reg_code,
1208 Reg31IsZeroRegister,
1209 GetPrintRegSizeInBytes(format));
1210 fprintf(stream_,
1211 " -> %s0x%016" PRIxPTR "%s\n",
1212 clr_memory_address,
1213 address,
1214 clr_normal);
1215}
1216
1217
1218void Simulator::PrintVWrite(uintptr_t address,
1219 unsigned reg_code,
1220 PrintRegisterFormat format,
1221 unsigned lane) {
1222 // The templates:
1223 // "# v{code}: 0x{rawbits} -> {address}"
1224 // "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
1225 // "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
1226 // Because this trace doesn't represent a change to the source register's
1227 // value, only the relevant part of the value is printed. To keep the trace
1228 // tidy and readable, the raw value is aligned with the other values in the
1229 // register trace.
1230 int lane_count = GetPrintRegLaneCount(format);
1231 int lane_size = GetPrintRegLaneSizeInBytes(format);
1232 int reg_size = GetPrintRegSizeInBytes(format);
1233 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1234 if (format & kPrintRegAsFP) {
1235 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1236 }
1237 fprintf(stream_,
1238 " -> %s0x%016" PRIxPTR "%s\n",
1239 clr_memory_address,
1240 address,
1241 clr_normal);
1242}
1243
TatWai Chong72d2e562019-05-16 11:22:22 -07001244void Simulator::PrintZWrite(uintptr_t address,
1245 unsigned reg_code,
1246 PrintRegisterFormat format,
1247 unsigned data_size,
1248 int bytes,
1249 int start_byte) {
1250 // The templates:
1251 // "# v{code}<m:n>: 0x{rawbits} -> {address}"
1252 // An example that prints an unpredicated memory write from the specified
1253 // portion of Z register to a particular memory location.
1254 // Zt<255:128>: 0x77776666555544443333222211110000 -> 0x00007fff00000000
1255 // Zt<383:256>: 0xffffeeeeddddccccbbbbaaaa99998888 -> 0x00007fff00000010
1256
1257 int lane_size = GetPrintRegLaneSizeInBytes(format);
1258 if (data_size == 0) {
1259 // If no data size was specified, print the whole of each lane.
1260 data_size = lane_size;
1261 }
1262 if (bytes == 0) {
1263 // If no byte size was specified, print the whole register.
1264 bytes = GetVectorLengthInBytes();
1265 }
1266
1267 const int last_byte = start_byte + bytes - 1;
1268 while (start_byte < last_byte) {
1269 PrintZRegisterRawHelper(reg_code,
1270 lane_size,
1271 data_size,
1272 kQRegSizeInBytes,
1273 start_byte);
1274 fprintf(stream_,
1275 " -> %s0x%016" PRIxPTR "%s\n",
1276 clr_memory_address,
1277 address,
1278 clr_normal);
1279 start_byte += kQRegSizeInBytes;
1280 address += kQRegSizeInBytes;
1281 }
1282}
1283
Alexandre Ramesd3832962016-07-04 15:03:43 +01001284
Jacob Bramleye79723a2016-06-07 17:50:47 +01001285void Simulator::PrintTakenBranch(const Instruction* target) {
1286 fprintf(stream_,
1287 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1288 clr_branch_marker,
1289 clr_normal,
1290 reinterpret_cast<uint64_t>(target));
1291}
1292
1293
Alexandre Ramesd3832962016-07-04 15:03:43 +01001294// Visitors---------------------------------------------------------------------
1295
Jacob Bramley18c97bd2019-01-18 16:01:08 +00001296
1297void Simulator::VisitReserved(const Instruction* instr) {
1298 // UDF is the only instruction in this group, and the Decoder is precise here.
1299 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1300
1301 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1302 reinterpret_cast<const void*>(instr),
1303 instr->GetInstructionBits());
1304 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1305}
1306
1307
Alexandre Ramesd3832962016-07-04 15:03:43 +01001308void Simulator::VisitUnimplemented(const Instruction* instr) {
1309 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1310 reinterpret_cast<const void*>(instr),
1311 instr->GetInstructionBits());
1312 VIXL_UNIMPLEMENTED();
1313}
1314
1315
1316void Simulator::VisitUnallocated(const Instruction* instr) {
1317 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1318 reinterpret_cast<const void*>(instr),
1319 instr->GetInstructionBits());
1320 VIXL_UNIMPLEMENTED();
1321}
1322
1323
1324void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1325 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1326 (instr->Mask(PCRelAddressingMask) == ADRP));
1327
1328 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1329}
1330
1331
1332void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1333 switch (instr->Mask(UnconditionalBranchMask)) {
1334 case BL:
1335 WriteLr(instr->GetNextInstruction());
1336 VIXL_FALLTHROUGH();
1337 case B:
1338 WritePc(instr->GetImmPCOffsetTarget());
1339 break;
1340 default:
1341 VIXL_UNREACHABLE();
1342 }
1343}
1344
1345
1346void Simulator::VisitConditionalBranch(const Instruction* instr) {
1347 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1348 if (ConditionPassed(instr->GetConditionBranch())) {
1349 WritePc(instr->GetImmPCOffsetTarget());
1350 }
1351}
1352
Martyn Capewellcb963f72018-10-22 15:25:28 +01001353BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1354 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1355 case BLR:
1356 case BLRAA:
1357 case BLRAB:
1358 case BLRAAZ:
1359 case BLRABZ:
1360 return BranchAndLink;
1361 case BR:
1362 case BRAA:
1363 case BRAB:
1364 case BRAAZ:
1365 case BRABZ:
1366 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1367 !PcIsInGuardedPage()) {
1368 return BranchFromUnguardedOrToIP;
1369 }
1370 return BranchFromGuardedNotToIP;
1371 }
1372 return DefaultBType;
1373}
Alexandre Ramesd3832962016-07-04 15:03:43 +01001374
1375void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01001376 bool authenticate = false;
1377 bool link = false;
Martyn Capewellcb963f72018-10-22 15:25:28 +01001378 uint64_t addr = ReadXRegister(instr->GetRn());
Jacob Bramleyca789742018-09-13 14:25:46 +01001379 uint64_t context = 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001380
1381 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1382 case BLR:
Jacob Bramleyca789742018-09-13 14:25:46 +01001383 link = true;
Alexandre Ramesd3832962016-07-04 15:03:43 +01001384 VIXL_FALLTHROUGH();
1385 case BR:
1386 case RET:
Jacob Bramleyca789742018-09-13 14:25:46 +01001387 break;
1388
1389 case BLRAAZ:
1390 case BLRABZ:
1391 link = true;
1392 VIXL_FALLTHROUGH();
1393 case BRAAZ:
1394 case BRABZ:
1395 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001396 break;
1397
1398 case BLRAA:
1399 case BLRAB:
1400 link = true;
1401 VIXL_FALLTHROUGH();
1402 case BRAA:
1403 case BRAB:
1404 authenticate = true;
Jacob Bramleyca789742018-09-13 14:25:46 +01001405 context = ReadXRegister(instr->GetRd());
1406 break;
1407
1408 case RETAA:
1409 case RETAB:
1410 authenticate = true;
1411 addr = ReadXRegister(kLinkRegCode);
1412 context = ReadXRegister(31, Reg31IsStackPointer);
Alexandre Ramesd3832962016-07-04 15:03:43 +01001413 break;
1414 default:
1415 VIXL_UNREACHABLE();
1416 }
Jacob Bramleyca789742018-09-13 14:25:46 +01001417
1418 if (link) {
1419 WriteLr(instr->GetNextInstruction());
1420 }
1421
1422 if (authenticate) {
1423 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1424 addr = AuthPAC(addr, context, key, kInstructionPointer);
1425
1426 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1427 if (((addr >> error_lsb) & 0x3) != 0x0) {
1428 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1429 }
1430 }
1431
Martyn Capewellcb963f72018-10-22 15:25:28 +01001432 WritePc(Instruction::Cast(addr));
1433 WriteNextBType(GetBTypeFromInstruction(instr));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001434}
1435
1436
1437void Simulator::VisitTestBranch(const Instruction* instr) {
1438 unsigned bit_pos =
1439 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1440 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1441 bool take_branch = false;
1442 switch (instr->Mask(TestBranchMask)) {
1443 case TBZ:
1444 take_branch = bit_zero;
1445 break;
1446 case TBNZ:
1447 take_branch = !bit_zero;
1448 break;
1449 default:
1450 VIXL_UNIMPLEMENTED();
1451 }
1452 if (take_branch) {
1453 WritePc(instr->GetImmPCOffsetTarget());
1454 }
1455}
1456
1457
1458void Simulator::VisitCompareBranch(const Instruction* instr) {
1459 unsigned rt = instr->GetRt();
1460 bool take_branch = false;
1461 switch (instr->Mask(CompareBranchMask)) {
1462 case CBZ_w:
1463 take_branch = (ReadWRegister(rt) == 0);
1464 break;
1465 case CBZ_x:
1466 take_branch = (ReadXRegister(rt) == 0);
1467 break;
1468 case CBNZ_w:
1469 take_branch = (ReadWRegister(rt) != 0);
1470 break;
1471 case CBNZ_x:
1472 take_branch = (ReadXRegister(rt) != 0);
1473 break;
1474 default:
1475 VIXL_UNIMPLEMENTED();
1476 }
1477 if (take_branch) {
1478 WritePc(instr->GetImmPCOffsetTarget());
1479 }
1480}
1481
1482
1483void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1484 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1485 bool set_flags = instr->GetFlagsUpdate();
1486 int64_t new_val = 0;
1487 Instr operation = instr->Mask(AddSubOpMask);
1488
1489 switch (operation) {
1490 case ADD:
1491 case ADDS: {
1492 new_val = AddWithCarry(reg_size,
1493 set_flags,
1494 ReadRegister(reg_size,
1495 instr->GetRn(),
1496 instr->GetRnMode()),
1497 op2);
1498 break;
1499 }
1500 case SUB:
1501 case SUBS: {
1502 new_val = AddWithCarry(reg_size,
1503 set_flags,
1504 ReadRegister(reg_size,
1505 instr->GetRn(),
1506 instr->GetRnMode()),
1507 ~op2,
1508 1);
1509 break;
1510 }
1511 default:
1512 VIXL_UNREACHABLE();
1513 }
1514
1515 WriteRegister(reg_size,
1516 instr->GetRd(),
1517 new_val,
1518 LogRegWrites,
1519 instr->GetRdMode());
1520}
1521
1522
1523void Simulator::VisitAddSubShifted(const Instruction* instr) {
1524 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1525 int64_t op2 = ShiftOperand(reg_size,
1526 ReadRegister(reg_size, instr->GetRm()),
1527 static_cast<Shift>(instr->GetShiftDP()),
1528 instr->GetImmDPShift());
1529 AddSubHelper(instr, op2);
1530}
1531
1532
1533void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1534 int64_t op2 = instr->GetImmAddSub()
1535 << ((instr->GetShiftAddSub() == 1) ? 12 : 0);
1536 AddSubHelper(instr, op2);
1537}
1538
1539
1540void Simulator::VisitAddSubExtended(const Instruction* instr) {
1541 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1542 int64_t op2 = ExtendValue(reg_size,
1543 ReadRegister(reg_size, instr->GetRm()),
1544 static_cast<Extend>(instr->GetExtendMode()),
1545 instr->GetImmExtendShift());
1546 AddSubHelper(instr, op2);
1547}
1548
1549
1550void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1551 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1552 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1553 int64_t new_val;
1554
1555 if ((instr->Mask(AddSubOpMask) == SUB) ||
1556 (instr->Mask(AddSubOpMask) == SUBS)) {
1557 op2 = ~op2;
1558 }
1559
1560 new_val = AddWithCarry(reg_size,
1561 instr->GetFlagsUpdate(),
1562 ReadRegister(reg_size, instr->GetRn()),
1563 op2,
1564 ReadC());
1565
1566 WriteRegister(reg_size, instr->GetRd(), new_val);
1567}
1568
1569
Alexander Gilday2487f142018-11-05 13:07:27 +00001570void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1571 switch (instr->Mask(RotateRightIntoFlagsMask)) {
1572 case RMIF: {
1573 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1574 unsigned shift = instr->GetImmRMIFRotation();
1575 unsigned mask = instr->GetNzcv();
1576 uint64_t rotated = RotateRight(value, shift, kXRegSize);
1577
1578 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1579 break;
1580 }
1581 }
1582}
1583
1584
1585void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1586 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1587 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1588
1589 unsigned sign_bit = (value >> msb) & 1;
1590 unsigned overflow_bit = (value >> (msb + 1)) & 1;
1591 ReadNzcv().SetN(sign_bit);
1592 ReadNzcv().SetZ((value << (31 - msb)) == 0);
1593 ReadNzcv().SetV(sign_bit ^ overflow_bit);
1594}
1595
1596
Alexandre Ramesd3832962016-07-04 15:03:43 +01001597void Simulator::VisitLogicalShifted(const Instruction* instr) {
1598 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1599 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1600 unsigned shift_amount = instr->GetImmDPShift();
1601 int64_t op2 = ShiftOperand(reg_size,
1602 ReadRegister(reg_size, instr->GetRm()),
1603 shift_type,
1604 shift_amount);
1605 if (instr->Mask(NOT) == NOT) {
1606 op2 = ~op2;
1607 }
1608 LogicalHelper(instr, op2);
1609}
1610
1611
1612void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1613 LogicalHelper(instr, instr->GetImmLogical());
1614}
1615
1616
1617void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1618 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1619 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1620 int64_t result = 0;
1621 bool update_flags = false;
1622
1623 // Switch on the logical operation, stripping out the NOT bit, as it has a
1624 // different meaning for logical immediate instructions.
1625 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1626 case ANDS:
1627 update_flags = true;
1628 VIXL_FALLTHROUGH();
1629 case AND:
1630 result = op1 & op2;
1631 break;
1632 case ORR:
1633 result = op1 | op2;
1634 break;
1635 case EOR:
1636 result = op1 ^ op2;
1637 break;
1638 default:
1639 VIXL_UNIMPLEMENTED();
1640 }
1641
1642 if (update_flags) {
1643 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1644 ReadNzcv().SetZ(CalcZFlag(result));
1645 ReadNzcv().SetC(0);
1646 ReadNzcv().SetV(0);
1647 LogSystemRegister(NZCV);
1648 }
1649
1650 WriteRegister(reg_size,
1651 instr->GetRd(),
1652 result,
1653 LogRegWrites,
1654 instr->GetRdMode());
1655}
1656
1657
1658void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1659 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1660 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1661}
1662
1663
1664void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1665 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1666}
1667
1668
1669void Simulator::ConditionalCompareHelper(const Instruction* instr,
1670 int64_t op2) {
1671 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1672 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1673
1674 if (ConditionPassed(instr->GetCondition())) {
1675 // If the condition passes, set the status flags to the result of comparing
1676 // the operands.
1677 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1678 AddWithCarry(reg_size, true, op1, ~op2, 1);
1679 } else {
1680 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1681 AddWithCarry(reg_size, true, op1, op2, 0);
1682 }
1683 } else {
1684 // If the condition fails, set the status flags to the nzcv immediate.
1685 ReadNzcv().SetFlags(instr->GetNzcv());
1686 LogSystemRegister(NZCV);
1687 }
1688}
1689
1690
1691void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1692 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1693 LoadStoreHelper(instr, offset, Offset);
1694}
1695
1696
1697void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1698 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1699}
1700
1701
1702void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1703 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1704}
1705
1706
1707void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1708 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1709}
1710
1711
Alexander Gilday311edf22018-10-29 13:41:41 +00001712template <typename T1, typename T2>
1713void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1714 unsigned rt = instr->GetRt();
1715 unsigned rn = instr->GetRn();
1716
1717 unsigned element_size = sizeof(T2);
1718 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1719 int offset = instr->GetImmLS();
1720 address += offset;
1721
1722 // Verify that the address is available to the host.
1723 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1724
1725 // Check the alignment of `address`.
1726 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1727 VIXL_ALIGNMENT_EXCEPTION();
1728 }
1729
1730 WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address)));
1731
1732 // Approximate load-acquire by issuing a full barrier after the load.
1733 __sync_synchronize();
1734
1735 LogRead(address, rt, GetPrintRegisterFormat(element_size));
1736}
1737
1738
1739template <typename T>
1740void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
1741 unsigned rt = instr->GetRt();
1742 unsigned rn = instr->GetRn();
1743
1744 unsigned element_size = sizeof(T);
1745 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1746 int offset = instr->GetImmLS();
1747 address += offset;
1748
1749 // Verify that the address is available to the host.
1750 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1751
1752 // Check the alignment of `address`.
1753 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
1754 VIXL_ALIGNMENT_EXCEPTION();
1755 }
1756
1757 // Approximate store-release by issuing a full barrier after the load.
1758 __sync_synchronize();
1759
1760 Memory::Write<T>(address, ReadRegister<T>(rt));
1761
1762 LogWrite(address, rt, GetPrintRegisterFormat(element_size));
1763}
1764
1765
1766void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
1767 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
1768 case LDAPURB:
1769 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
1770 break;
1771 case LDAPURH:
1772 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
1773 break;
1774 case LDAPUR_w:
1775 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
1776 break;
1777 case LDAPUR_x:
1778 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
1779 break;
1780 case LDAPURSB_w:
1781 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
1782 break;
1783 case LDAPURSB_x:
1784 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
1785 break;
1786 case LDAPURSH_w:
1787 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
1788 break;
1789 case LDAPURSH_x:
1790 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
1791 break;
1792 case LDAPURSW:
1793 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
1794 break;
1795 case STLURB:
1796 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
1797 break;
1798 case STLURH:
1799 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
1800 break;
1801 case STLUR_w:
1802 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
1803 break;
1804 case STLUR_x:
1805 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
1806 break;
1807 }
1808}
1809
1810
Alexander Gilday75605592018-11-01 09:30:29 +00001811void Simulator::VisitLoadStorePAC(const Instruction* instr) {
1812 unsigned dst = instr->GetRt();
1813 unsigned addr_reg = instr->GetRn();
1814
1815 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
1816
1817 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
1818 address = AuthPAC(address, 0, key, kDataPointer);
1819
1820 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
1821 if (((address >> error_lsb) & 0x3) != 0x0) {
1822 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1823 }
1824
1825
1826 if ((addr_reg == 31) && ((address % 16) != 0)) {
1827 // When the base register is SP the stack pointer is required to be
1828 // quadword aligned prior to the address calculation and write-backs.
1829 // Misalignment will cause a stack alignment fault.
1830 VIXL_ALIGNMENT_EXCEPTION();
1831 }
1832
1833 int64_t offset = instr->GetImmLSPAC();
1834 address += offset;
1835
1836 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
1837 // Pre-index mode.
1838 VIXL_ASSERT(offset != 0);
1839 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
1840 }
1841
1842 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
1843
1844 // Verify that the calculated address is available to the host.
1845 VIXL_ASSERT(address == addr_ptr);
1846
1847 WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog);
1848 unsigned access_size = 1 << 3;
1849 LogRead(addr_ptr, dst, GetPrintRegisterFormatForSize(access_size));
1850}
1851
1852
Alexandre Ramesd3832962016-07-04 15:03:43 +01001853void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
1854 Extend ext = static_cast<Extend>(instr->GetExtendMode());
1855 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1856 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
1857
1858 int64_t offset =
1859 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
1860 LoadStoreHelper(instr, offset, Offset);
1861}
1862
1863
1864void Simulator::LoadStoreHelper(const Instruction* instr,
1865 int64_t offset,
1866 AddrMode addrmode) {
1867 unsigned srcdst = instr->GetRt();
1868 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
1869
1870 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
1871 switch (op) {
1872 case LDRB_w:
1873 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
1874 break;
1875 case LDRH_w:
1876 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
1877 break;
1878 case LDR_w:
1879 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
1880 break;
1881 case LDR_x:
1882 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
1883 break;
1884 case LDRSB_w:
1885 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
1886 break;
1887 case LDRSH_w:
1888 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
1889 break;
1890 case LDRSB_x:
1891 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
1892 break;
1893 case LDRSH_x:
1894 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
1895 break;
1896 case LDRSW_x:
1897 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
1898 break;
1899 case LDR_b:
1900 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
1901 break;
1902 case LDR_h:
1903 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
1904 break;
1905 case LDR_s:
1906 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
1907 break;
1908 case LDR_d:
1909 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
1910 break;
1911 case LDR_q:
1912 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
1913 break;
1914
1915 case STRB_w:
1916 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
1917 break;
1918 case STRH_w:
1919 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
1920 break;
1921 case STR_w:
1922 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
1923 break;
1924 case STR_x:
1925 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
1926 break;
1927 case STR_b:
1928 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
1929 break;
1930 case STR_h:
Jacob Bramleyca789742018-09-13 14:25:46 +01001931 Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001932 break;
1933 case STR_s:
1934 Memory::Write<float>(address, ReadSRegister(srcdst));
1935 break;
1936 case STR_d:
1937 Memory::Write<double>(address, ReadDRegister(srcdst));
1938 break;
1939 case STR_q:
1940 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
1941 break;
1942
1943 // Ignore prfm hint instructions.
1944 case PRFM:
1945 break;
1946
1947 default:
1948 VIXL_UNIMPLEMENTED();
1949 }
1950
1951 unsigned access_size = 1 << instr->GetSizeLS();
1952 if (instr->IsLoad()) {
1953 if ((op == LDR_s) || (op == LDR_d)) {
1954 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1955 } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1956 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1957 } else {
1958 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1959 }
1960 } else if (instr->IsStore()) {
1961 if ((op == STR_s) || (op == STR_d)) {
1962 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1963 } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1964 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1965 } else {
1966 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1967 }
1968 } else {
1969 VIXL_ASSERT(op == PRFM);
1970 }
1971
1972 local_monitor_.MaybeClear();
1973}
1974
1975
1976void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
1977 LoadStorePairHelper(instr, Offset);
1978}
1979
1980
1981void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
1982 LoadStorePairHelper(instr, PreIndex);
1983}
1984
1985
1986void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
1987 LoadStorePairHelper(instr, PostIndex);
1988}
1989
1990
1991void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
1992 LoadStorePairHelper(instr, Offset);
1993}
1994
1995
1996void Simulator::LoadStorePairHelper(const Instruction* instr,
1997 AddrMode addrmode) {
1998 unsigned rt = instr->GetRt();
1999 unsigned rt2 = instr->GetRt2();
2000 int element_size = 1 << instr->GetSizeLSPair();
2001 int64_t offset = instr->GetImmLSPair() * element_size;
2002 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2003 uintptr_t address2 = address + element_size;
2004
2005 LoadStorePairOp op =
2006 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
2007
2008 // 'rt' and 'rt2' can only be aliased for stores.
2009 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2010
2011 switch (op) {
2012 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
2013 // will print a more detailed log.
2014 case LDP_w: {
2015 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2016 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
2017 break;
2018 }
2019 case LDP_s: {
2020 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2021 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
2022 break;
2023 }
2024 case LDP_x: {
2025 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2026 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
2027 break;
2028 }
2029 case LDP_d: {
2030 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2031 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
2032 break;
2033 }
2034 case LDP_q: {
2035 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2036 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
2037 break;
2038 }
2039 case LDPSW_x: {
2040 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2041 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
2042 break;
2043 }
2044 case STP_w: {
2045 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2046 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
2047 break;
2048 }
2049 case STP_s: {
2050 Memory::Write<float>(address, ReadSRegister(rt));
2051 Memory::Write<float>(address2, ReadSRegister(rt2));
2052 break;
2053 }
2054 case STP_x: {
2055 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2056 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
2057 break;
2058 }
2059 case STP_d: {
2060 Memory::Write<double>(address, ReadDRegister(rt));
2061 Memory::Write<double>(address2, ReadDRegister(rt2));
2062 break;
2063 }
2064 case STP_q: {
2065 Memory::Write<qreg_t>(address, ReadQRegister(rt));
2066 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
2067 break;
2068 }
2069 default:
2070 VIXL_UNREACHABLE();
2071 }
2072
2073 // Print a detailed trace (including the memory address) instead of the basic
2074 // register:value trace generated by set_*reg().
2075 if (instr->IsLoad()) {
2076 if ((op == LDP_s) || (op == LDP_d)) {
2077 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
2078 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
2079 } else if (op == LDP_q) {
2080 LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2081 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2082 } else {
2083 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2084 LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2085 }
2086 } else {
2087 if ((op == STP_s) || (op == STP_d)) {
2088 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
2089 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
2090 } else if (op == STP_q) {
2091 LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2092 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2093 } else {
2094 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2095 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
2096 }
2097 }
2098
2099 local_monitor_.MaybeClear();
2100}
2101
2102
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002103template <typename T>
2104void Simulator::CompareAndSwapHelper(const Instruction* instr) {
2105 unsigned rs = instr->GetRs();
2106 unsigned rt = instr->GetRt();
2107 unsigned rn = instr->GetRn();
2108
2109 unsigned element_size = sizeof(T);
2110 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2111
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002112 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2113
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002114 bool is_acquire = instr->ExtractBit(22) == 1;
2115 bool is_release = instr->ExtractBit(15) == 1;
2116
2117 T comparevalue = ReadRegister<T>(rs);
2118 T newvalue = ReadRegister<T>(rt);
2119
2120 // The architecture permits that the data read clears any exclusive monitors
2121 // associated with that location, even if the compare subsequently fails.
2122 local_monitor_.Clear();
2123
2124 T data = Memory::Read<T>(address);
2125 if (is_acquire) {
2126 // Approximate load-acquire by issuing a full barrier after the load.
2127 __sync_synchronize();
2128 }
2129
2130 if (data == comparevalue) {
2131 if (is_release) {
2132 // Approximate store-release by issuing a full barrier before the store.
2133 __sync_synchronize();
2134 }
2135 Memory::Write<T>(address, newvalue);
2136 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2137 }
2138 WriteRegister<T>(rs, data);
2139 LogRead(address, rs, GetPrintRegisterFormatForSize(element_size));
2140}
2141
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002142
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002143template <typename T>
2144void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
2145 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
2146 unsigned rs = instr->GetRs();
2147 unsigned rt = instr->GetRt();
2148 unsigned rn = instr->GetRn();
2149
2150 VIXL_ASSERT((rs % 2 == 0) && (rs % 2 == 0));
2151
2152 unsigned element_size = sizeof(T);
2153 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002154
2155 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
2156
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002157 uint64_t address2 = address + element_size;
2158
2159 bool is_acquire = instr->ExtractBit(22) == 1;
2160 bool is_release = instr->ExtractBit(15) == 1;
2161
2162 T comparevalue_high = ReadRegister<T>(rs + 1);
2163 T comparevalue_low = ReadRegister<T>(rs);
2164 T newvalue_high = ReadRegister<T>(rt + 1);
2165 T newvalue_low = ReadRegister<T>(rt);
2166
2167 // The architecture permits that the data read clears any exclusive monitors
2168 // associated with that location, even if the compare subsequently fails.
2169 local_monitor_.Clear();
2170
2171 T data_high = Memory::Read<T>(address);
2172 T data_low = Memory::Read<T>(address2);
2173
2174 if (is_acquire) {
2175 // Approximate load-acquire by issuing a full barrier after the load.
2176 __sync_synchronize();
2177 }
2178
2179 bool same =
2180 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2181 if (same) {
2182 if (is_release) {
2183 // Approximate store-release by issuing a full barrier before the store.
2184 __sync_synchronize();
2185 }
2186
2187 Memory::Write<T>(address, newvalue_high);
2188 Memory::Write<T>(address2, newvalue_low);
2189 }
2190
2191 WriteRegister<T>(rs + 1, data_high);
2192 WriteRegister<T>(rs, data_low);
2193
2194 LogRead(address, rs + 1, GetPrintRegisterFormatForSize(element_size));
2195 LogRead(address2, rs, GetPrintRegisterFormatForSize(element_size));
2196
2197 if (same) {
2198 LogWrite(address, rt + 1, GetPrintRegisterFormatForSize(element_size));
2199 LogWrite(address2, rt, GetPrintRegisterFormatForSize(element_size));
2200 }
2201}
2202
Alexandre Ramesd3832962016-07-04 15:03:43 +01002203
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002204void Simulator::PrintExclusiveAccessWarning() {
2205 if (print_exclusive_access_warning_) {
2206 fprintf(stderr,
2207 "%sWARNING:%s VIXL simulator support for "
2208 "load-/store-/clear-exclusive "
2209 "instructions is limited. Refer to the README for details.%s\n",
2210 clr_warning,
2211 clr_warning_message,
2212 clr_normal);
2213 print_exclusive_access_warning_ = false;
2214 }
2215}
2216
2217
Alexandre Ramesd3832962016-07-04 15:03:43 +01002218void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002219 LoadStoreExclusive op =
2220 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
2221
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002222 switch (op) {
2223 case CAS_w:
2224 case CASA_w:
2225 case CASL_w:
2226 case CASAL_w:
2227 CompareAndSwapHelper<uint32_t>(instr);
2228 break;
2229 case CAS_x:
2230 case CASA_x:
2231 case CASL_x:
2232 case CASAL_x:
2233 CompareAndSwapHelper<uint64_t>(instr);
2234 break;
2235 case CASB:
2236 case CASAB:
2237 case CASLB:
2238 case CASALB:
2239 CompareAndSwapHelper<uint8_t>(instr);
2240 break;
2241 case CASH:
2242 case CASAH:
2243 case CASLH:
2244 case CASALH:
2245 CompareAndSwapHelper<uint16_t>(instr);
2246 break;
2247 case CASP_w:
2248 case CASPA_w:
2249 case CASPL_w:
2250 case CASPAL_w:
2251 CompareAndSwapPairHelper<uint32_t>(instr);
2252 break;
2253 case CASP_x:
2254 case CASPA_x:
2255 case CASPL_x:
2256 case CASPAL_x:
2257 CompareAndSwapPairHelper<uint64_t>(instr);
2258 break;
2259 default:
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002260 PrintExclusiveAccessWarning();
2261
2262 unsigned rs = instr->GetRs();
2263 unsigned rt = instr->GetRt();
2264 unsigned rt2 = instr->GetRt2();
2265 unsigned rn = instr->GetRn();
2266
2267 bool is_exclusive = !instr->GetLdStXNotExclusive();
2268 bool is_acquire_release =
2269 !is_exclusive || instr->GetLdStXAcquireRelease();
2270 bool is_load = instr->GetLdStXLoad();
2271 bool is_pair = instr->GetLdStXPair();
2272
2273 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2274 unsigned access_size = is_pair ? element_size * 2 : element_size;
2275 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2276
2277 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2278
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002279 if (is_load) {
2280 if (is_exclusive) {
2281 local_monitor_.MarkExclusive(address, access_size);
2282 } else {
2283 // Any non-exclusive load can clear the local monitor as a side
2284 // effect. We don't need to do this, but it is useful to stress the
2285 // simulated code.
2286 local_monitor_.Clear();
2287 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002288
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002289 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2290 // We will print a more detailed log.
2291 switch (op) {
2292 case LDXRB_w:
2293 case LDAXRB_w:
2294 case LDARB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002295 case LDLARB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002296 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
2297 break;
2298 case LDXRH_w:
2299 case LDAXRH_w:
2300 case LDARH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002301 case LDLARH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002302 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
2303 break;
2304 case LDXR_w:
2305 case LDAXR_w:
2306 case LDAR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002307 case LDLAR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002308 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2309 break;
2310 case LDXR_x:
2311 case LDAXR_x:
2312 case LDAR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002313 case LDLAR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002314 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2315 break;
2316 case LDXP_w:
2317 case LDAXP_w:
2318 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2319 WriteWRegister(rt2,
2320 Memory::Read<uint32_t>(address + element_size),
2321 NoRegLog);
2322 break;
2323 case LDXP_x:
2324 case LDAXP_x:
2325 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2326 WriteXRegister(rt2,
2327 Memory::Read<uint64_t>(address + element_size),
2328 NoRegLog);
2329 break;
2330 default:
2331 VIXL_UNREACHABLE();
2332 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002333
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002334 if (is_acquire_release) {
2335 // Approximate load-acquire by issuing a full barrier after the load.
2336 __sync_synchronize();
2337 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002338
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002339 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2340 if (is_pair) {
2341 LogRead(address + element_size,
2342 rt2,
2343 GetPrintRegisterFormatForSize(element_size));
2344 }
2345 } else {
2346 if (is_acquire_release) {
2347 // Approximate store-release by issuing a full barrier before the
2348 // store.
2349 __sync_synchronize();
2350 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002351
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002352 bool do_store = true;
2353 if (is_exclusive) {
2354 do_store = local_monitor_.IsExclusive(address, access_size) &&
2355 global_monitor_.IsExclusive(address, access_size);
2356 WriteWRegister(rs, do_store ? 0 : 1);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002357
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002358 // - All exclusive stores explicitly clear the local monitor.
2359 local_monitor_.Clear();
2360 } else {
2361 // - Any other store can clear the local monitor as a side effect.
2362 local_monitor_.MaybeClear();
2363 }
2364
2365 if (do_store) {
2366 switch (op) {
2367 case STXRB_w:
2368 case STLXRB_w:
2369 case STLRB_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002370 case STLLRB:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002371 Memory::Write<uint8_t>(address, ReadWRegister(rt));
2372 break;
2373 case STXRH_w:
2374 case STLXRH_w:
2375 case STLRH_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002376 case STLLRH:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002377 Memory::Write<uint16_t>(address, ReadWRegister(rt));
2378 break;
2379 case STXR_w:
2380 case STLXR_w:
2381 case STLR_w:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002382 case STLLR_w:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002383 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2384 break;
2385 case STXR_x:
2386 case STLXR_x:
2387 case STLR_x:
Alexander Gilday2c3cebb2018-04-13 16:15:34 +01002388 case STLLR_x:
Alexander Gilday4e5bad92018-04-16 17:42:00 +01002389 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2390 break;
2391 case STXP_w:
2392 case STLXP_w:
2393 Memory::Write<uint32_t>(address, ReadWRegister(rt));
2394 Memory::Write<uint32_t>(address + element_size,
2395 ReadWRegister(rt2));
2396 break;
2397 case STXP_x:
2398 case STLXP_x:
2399 Memory::Write<uint64_t>(address, ReadXRegister(rt));
2400 Memory::Write<uint64_t>(address + element_size,
2401 ReadXRegister(rt2));
2402 break;
2403 default:
2404 VIXL_UNREACHABLE();
2405 }
2406
2407 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
2408 if (is_pair) {
2409 LogWrite(address + element_size,
2410 rt2,
2411 GetPrintRegisterFormatForSize(element_size));
2412 }
2413 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002414 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002415 }
2416}
2417
Jacob Bramleyca789742018-09-13 14:25:46 +01002418template <typename T>
2419void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2420 unsigned rs = instr->GetRs();
2421 unsigned rt = instr->GetRt();
2422 unsigned rn = instr->GetRn();
2423
2424 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2425 bool is_release = instr->ExtractBit(22) == 1;
2426
2427 unsigned element_size = sizeof(T);
2428 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2429
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002430 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002431
2432 T value = ReadRegister<T>(rs);
2433
2434 T data = Memory::Read<T>(address);
2435
2436 if (is_acquire) {
2437 // Approximate load-acquire by issuing a full barrier after the load.
2438 __sync_synchronize();
2439 }
2440
2441 T result = 0;
2442 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2443 case LDADDOp:
2444 result = data + value;
2445 break;
2446 case LDCLROp:
2447 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2448 result = data & ~value;
2449 break;
2450 case LDEOROp:
2451 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2452 result = data ^ value;
2453 break;
2454 case LDSETOp:
2455 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2456 result = data | value;
2457 break;
2458
2459 // Signed/Unsigned difference is done via the templated type T.
2460 case LDSMAXOp:
2461 case LDUMAXOp:
2462 result = (data > value) ? data : value;
2463 break;
2464 case LDSMINOp:
2465 case LDUMINOp:
2466 result = (data > value) ? value : data;
2467 break;
2468 }
2469
2470 if (is_release) {
2471 // Approximate store-release by issuing a full barrier before the store.
2472 __sync_synchronize();
2473 }
2474
2475 Memory::Write<T>(address, result);
2476 WriteRegister<T>(rt, data, NoRegLog);
2477
2478 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
2479 LogWrite(address, rs, GetPrintRegisterFormatForSize(element_size));
2480}
2481
2482template <typename T>
2483void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2484 unsigned rs = instr->GetRs();
2485 unsigned rt = instr->GetRt();
2486 unsigned rn = instr->GetRn();
2487
2488 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2489 bool is_release = instr->ExtractBit(22) == 1;
2490
2491 unsigned element_size = sizeof(T);
2492 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2493
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002494 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
Jacob Bramleyca789742018-09-13 14:25:46 +01002495
2496 T data = Memory::Read<T>(address);
2497 if (is_acquire) {
2498 // Approximate load-acquire by issuing a full barrier after the load.
2499 __sync_synchronize();
2500 }
2501
2502 if (is_release) {
2503 // Approximate store-release by issuing a full barrier before the store.
2504 __sync_synchronize();
2505 }
2506 Memory::Write<T>(address, ReadRegister<T>(rs));
2507
2508 WriteRegister<T>(rt, data);
2509
2510 LogRead(address, rt, GetPrintRegisterFormat(element_size));
2511 LogWrite(address, rs, GetPrintRegisterFormat(element_size));
2512}
2513
2514template <typename T>
2515void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2516 unsigned rt = instr->GetRt();
2517 unsigned rn = instr->GetRn();
2518
2519 unsigned element_size = sizeof(T);
2520 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2521
Alexander Gilday3f89bf12018-10-25 14:03:49 +01002522 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2523
Jacob Bramleyca789742018-09-13 14:25:46 +01002524 WriteRegister<T>(rt, Memory::Read<T>(address));
2525
2526 // Approximate load-acquire by issuing a full barrier after the load.
2527 __sync_synchronize();
2528
2529 LogRead(address, rt, GetPrintRegisterFormat(element_size));
2530}
2531
2532#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2533 V(LDADD) \
2534 V(LDCLR) \
2535 V(LDEOR) \
2536 V(LDSET) \
2537 V(LDUMAX) \
2538 V(LDUMIN)
2539
2540#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2541 V(LDSMAX) \
2542 V(LDSMIN)
2543
2544void Simulator::VisitAtomicMemory(const Instruction* instr) {
2545 switch (instr->Mask(AtomicMemoryMask)) {
2546// clang-format off
2547#define SIM_FUNC_B(A) \
2548 case A##B: \
2549 case A##AB: \
2550 case A##LB: \
2551 case A##ALB:
2552#define SIM_FUNC_H(A) \
2553 case A##H: \
2554 case A##AH: \
2555 case A##LH: \
2556 case A##ALH:
2557#define SIM_FUNC_w(A) \
2558 case A##_w: \
2559 case A##A_w: \
2560 case A##L_w: \
2561 case A##AL_w:
2562#define SIM_FUNC_x(A) \
2563 case A##_x: \
2564 case A##A_x: \
2565 case A##L_x: \
2566 case A##AL_x:
2567
2568 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2569 AtomicMemorySimpleHelper<uint8_t>(instr);
2570 break;
2571 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2572 AtomicMemorySimpleHelper<int8_t>(instr);
2573 break;
2574 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2575 AtomicMemorySimpleHelper<uint16_t>(instr);
2576 break;
2577 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2578 AtomicMemorySimpleHelper<int16_t>(instr);
2579 break;
2580 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2581 AtomicMemorySimpleHelper<uint32_t>(instr);
2582 break;
2583 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2584 AtomicMemorySimpleHelper<int32_t>(instr);
2585 break;
2586 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2587 AtomicMemorySimpleHelper<uint64_t>(instr);
2588 break;
2589 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2590 AtomicMemorySimpleHelper<int64_t>(instr);
2591 break;
2592 // clang-format on
2593
2594 case SWPB:
2595 case SWPAB:
2596 case SWPLB:
2597 case SWPALB:
2598 AtomicMemorySwapHelper<uint8_t>(instr);
2599 break;
2600 case SWPH:
2601 case SWPAH:
2602 case SWPLH:
2603 case SWPALH:
2604 AtomicMemorySwapHelper<uint16_t>(instr);
2605 break;
2606 case SWP_w:
2607 case SWPA_w:
2608 case SWPL_w:
2609 case SWPAL_w:
2610 AtomicMemorySwapHelper<uint32_t>(instr);
2611 break;
2612 case SWP_x:
2613 case SWPA_x:
2614 case SWPL_x:
2615 case SWPAL_x:
2616 AtomicMemorySwapHelper<uint64_t>(instr);
2617 break;
2618 case LDAPRB:
2619 LoadAcquireRCpcHelper<uint8_t>(instr);
2620 break;
2621 case LDAPRH:
2622 LoadAcquireRCpcHelper<uint16_t>(instr);
2623 break;
2624 case LDAPR_w:
2625 LoadAcquireRCpcHelper<uint32_t>(instr);
2626 break;
2627 case LDAPR_x:
2628 LoadAcquireRCpcHelper<uint64_t>(instr);
2629 break;
2630 }
2631}
2632
Alexandre Ramesd3832962016-07-04 15:03:43 +01002633
2634void Simulator::VisitLoadLiteral(const Instruction* instr) {
2635 unsigned rt = instr->GetRt();
2636 uint64_t address = instr->GetLiteralAddress<uint64_t>();
2637
2638 // Verify that the calculated address is available to the host.
2639 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2640
2641 switch (instr->Mask(LoadLiteralMask)) {
2642 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
2643 // print a more detailed log.
2644 case LDR_w_lit:
2645 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
2646 LogRead(address, rt, kPrintWReg);
2647 break;
2648 case LDR_x_lit:
2649 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
2650 LogRead(address, rt, kPrintXReg);
2651 break;
2652 case LDR_s_lit:
2653 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
2654 LogVRead(address, rt, kPrintSReg);
2655 break;
2656 case LDR_d_lit:
2657 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
2658 LogVRead(address, rt, kPrintDReg);
2659 break;
2660 case LDR_q_lit:
2661 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
2662 LogVRead(address, rt, kPrintReg1Q);
2663 break;
2664 case LDRSW_x_lit:
2665 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
2666 LogRead(address, rt, kPrintWReg);
2667 break;
2668
2669 // Ignore prfm hint instructions.
2670 case PRFM_lit:
2671 break;
2672
2673 default:
2674 VIXL_UNREACHABLE();
2675 }
2676
2677 local_monitor_.MaybeClear();
2678}
2679
2680
2681uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
2682 int64_t offset,
2683 AddrMode addrmode) {
2684 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2685
2686 if ((addr_reg == 31) && ((address % 16) != 0)) {
2687 // When the base register is SP the stack pointer is required to be
2688 // quadword aligned prior to the address calculation and write-backs.
2689 // Misalignment will cause a stack alignment fault.
2690 VIXL_ALIGNMENT_EXCEPTION();
2691 }
2692
2693 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
2694 VIXL_ASSERT(offset != 0);
2695 // Only preindex should log the register update here. For Postindex, the
2696 // update will be printed automatically by LogWrittenRegisters _after_ the
2697 // memory access itself is logged.
2698 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
2699 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
2700 }
2701
2702 if ((addrmode == Offset) || (addrmode == PreIndex)) {
2703 address += offset;
2704 }
2705
2706 // Verify that the calculated address is available to the host.
2707 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2708
2709 return static_cast<uintptr_t>(address);
2710}
2711
2712
2713void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
2714 MoveWideImmediateOp mov_op =
2715 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
2716 int64_t new_xn_val = 0;
2717
2718 bool is_64_bits = instr->GetSixtyFourBits() == 1;
2719 // Shift is limited for W operations.
2720 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
2721
2722 // Get the shifted immediate.
2723 int64_t shift = instr->GetShiftMoveWide() * 16;
2724 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
2725 << shift;
2726
2727 // Compute the new value.
2728 switch (mov_op) {
2729 case MOVN_w:
2730 case MOVN_x: {
2731 new_xn_val = ~shifted_imm16;
2732 if (!is_64_bits) new_xn_val &= kWRegMask;
2733 break;
2734 }
2735 case MOVK_w:
2736 case MOVK_x: {
2737 unsigned reg_code = instr->GetRd();
2738 int64_t prev_xn_val =
2739 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
2740 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
2741 break;
2742 }
2743 case MOVZ_w:
2744 case MOVZ_x: {
2745 new_xn_val = shifted_imm16;
2746 break;
2747 }
2748 default:
2749 VIXL_UNREACHABLE();
2750 }
2751
2752 // Update the destination register.
2753 WriteXRegister(instr->GetRd(), new_xn_val);
2754}
2755
2756
2757void Simulator::VisitConditionalSelect(const Instruction* instr) {
2758 uint64_t new_val = ReadXRegister(instr->GetRn());
2759
2760 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
2761 new_val = ReadXRegister(instr->GetRm());
2762 switch (instr->Mask(ConditionalSelectMask)) {
2763 case CSEL_w:
2764 case CSEL_x:
2765 break;
2766 case CSINC_w:
2767 case CSINC_x:
2768 new_val++;
2769 break;
2770 case CSINV_w:
2771 case CSINV_x:
2772 new_val = ~new_val;
2773 break;
2774 case CSNEG_w:
2775 case CSNEG_x:
2776 new_val = -new_val;
2777 break;
2778 default:
2779 VIXL_UNIMPLEMENTED();
2780 }
2781 }
2782 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2783 WriteRegister(reg_size, instr->GetRd(), new_val);
2784}
2785
2786
Jacob Bramleyca789742018-09-13 14:25:46 +01002787// clang-format off
2788#define PAUTH_MODES(V) \
2789 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
2790 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
2791 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
2792 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
2793 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
2794 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
2795 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
2796 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
2797// clang-format on
2798
Alexandre Ramesd3832962016-07-04 15:03:43 +01002799void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
2800 unsigned dst = instr->GetRd();
2801 unsigned src = instr->GetRn();
2802
2803 switch (instr->Mask(DataProcessing1SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01002804#define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
2805 case PAC##SUFFIX: { \
2806 uint64_t ptr = ReadXRegister(dst); \
2807 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
2808 break; \
2809 } \
2810 case AUT##SUFFIX: { \
2811 uint64_t ptr = ReadXRegister(dst); \
2812 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
2813 break; \
2814 }
2815
2816 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
2817#undef DEFINE_PAUTH_FUNCS
2818
2819 case XPACI:
2820 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
2821 break;
2822 case XPACD:
2823 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
2824 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002825 case RBIT_w:
2826 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
2827 break;
2828 case RBIT_x:
2829 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
2830 break;
2831 case REV16_w:
2832 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
2833 break;
2834 case REV16_x:
2835 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
2836 break;
2837 case REV_w:
2838 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
2839 break;
2840 case REV32_x:
2841 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
2842 break;
2843 case REV_x:
2844 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
2845 break;
2846 case CLZ_w:
2847 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
2848 break;
2849 case CLZ_x:
2850 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
2851 break;
2852 case CLS_w:
2853 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
2854 break;
2855 case CLS_x:
2856 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
2857 break;
2858 default:
2859 VIXL_UNIMPLEMENTED();
2860 }
2861}
2862
2863
2864uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
2865 VIXL_ASSERT((n > 32) && (n <= 64));
2866 for (unsigned i = (n - 1); i >= 32; i--) {
2867 if (((data >> i) & 1) != 0) {
2868 uint64_t polysh32 = (uint64_t)poly << (i - 32);
2869 uint64_t mask = (UINT64_C(1) << i) - 1;
2870 data = ((data & mask) ^ polysh32);
2871 }
2872 }
2873 return data & 0xffffffff;
2874}
2875
2876
2877template <typename T>
2878uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
2879 unsigned size = sizeof(val) * 8; // Number of bits in type T.
2880 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
2881 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
2882 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
2883 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
2884}
2885
2886
2887uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
2888 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
2889 // the CRC of each 32-bit word sequentially.
2890 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
2891 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
2892}
2893
2894
2895void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
2896 Shift shift_op = NO_SHIFT;
2897 int64_t result = 0;
2898 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2899
2900 switch (instr->Mask(DataProcessing2SourceMask)) {
2901 case SDIV_w: {
2902 int32_t rn = ReadWRegister(instr->GetRn());
2903 int32_t rm = ReadWRegister(instr->GetRm());
2904 if ((rn == kWMinInt) && (rm == -1)) {
2905 result = kWMinInt;
2906 } else if (rm == 0) {
2907 // Division by zero can be trapped, but not on A-class processors.
2908 result = 0;
2909 } else {
2910 result = rn / rm;
2911 }
2912 break;
2913 }
2914 case SDIV_x: {
2915 int64_t rn = ReadXRegister(instr->GetRn());
2916 int64_t rm = ReadXRegister(instr->GetRm());
2917 if ((rn == kXMinInt) && (rm == -1)) {
2918 result = kXMinInt;
2919 } else if (rm == 0) {
2920 // Division by zero can be trapped, but not on A-class processors.
2921 result = 0;
2922 } else {
2923 result = rn / rm;
2924 }
2925 break;
2926 }
2927 case UDIV_w: {
2928 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
2929 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
2930 if (rm == 0) {
2931 // Division by zero can be trapped, but not on A-class processors.
2932 result = 0;
2933 } else {
2934 result = rn / rm;
2935 }
2936 break;
2937 }
2938 case UDIV_x: {
2939 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
2940 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
2941 if (rm == 0) {
2942 // Division by zero can be trapped, but not on A-class processors.
2943 result = 0;
2944 } else {
2945 result = rn / rm;
2946 }
2947 break;
2948 }
2949 case LSLV_w:
2950 case LSLV_x:
2951 shift_op = LSL;
2952 break;
2953 case LSRV_w:
2954 case LSRV_x:
2955 shift_op = LSR;
2956 break;
2957 case ASRV_w:
2958 case ASRV_x:
2959 shift_op = ASR;
2960 break;
2961 case RORV_w:
2962 case RORV_x:
2963 shift_op = ROR;
2964 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01002965 case PACGA: {
2966 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
2967 uint64_t src = static_cast<uint64_t>(
2968 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
2969 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
2970 result = code & 0xffffffff00000000;
2971 break;
2972 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01002973 case CRC32B: {
2974 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2975 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
2976 result = Crc32Checksum(acc, val, CRC32_POLY);
2977 break;
2978 }
2979 case CRC32H: {
2980 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2981 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
2982 result = Crc32Checksum(acc, val, CRC32_POLY);
2983 break;
2984 }
2985 case CRC32W: {
2986 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2987 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
2988 result = Crc32Checksum(acc, val, CRC32_POLY);
2989 break;
2990 }
2991 case CRC32X: {
2992 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2993 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
2994 result = Crc32Checksum(acc, val, CRC32_POLY);
2995 reg_size = kWRegSize;
2996 break;
2997 }
2998 case CRC32CB: {
2999 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3000 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3001 result = Crc32Checksum(acc, val, CRC32C_POLY);
3002 break;
3003 }
3004 case CRC32CH: {
3005 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3006 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3007 result = Crc32Checksum(acc, val, CRC32C_POLY);
3008 break;
3009 }
3010 case CRC32CW: {
3011 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3012 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3013 result = Crc32Checksum(acc, val, CRC32C_POLY);
3014 break;
3015 }
3016 case CRC32CX: {
3017 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3018 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3019 result = Crc32Checksum(acc, val, CRC32C_POLY);
3020 reg_size = kWRegSize;
3021 break;
3022 }
3023 default:
3024 VIXL_UNIMPLEMENTED();
3025 }
3026
3027 if (shift_op != NO_SHIFT) {
3028 // Shift distance encoded in the least-significant five/six bits of the
3029 // register.
3030 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
3031 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
3032 result = ShiftOperand(reg_size,
3033 ReadRegister(reg_size, instr->GetRn()),
3034 shift_op,
3035 shift);
3036 }
3037 WriteRegister(reg_size, instr->GetRd(), result);
3038}
3039
3040
3041// The algorithm used is adapted from the one described in section 8.2 of
3042// Hacker's Delight, by Henry S. Warren, Jr.
Alexandre Ramesd3832962016-07-04 15:03:43 +01003043template <typename T>
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003044static int64_t MultiplyHigh(T u, T v) {
3045 uint64_t u0, v0, w0, u1, v1, w1, w2, t;
3046 uint64_t sign_mask = UINT64_C(0x8000000000000000);
3047 uint64_t sign_ext = 0;
3048 if (std::numeric_limits<T>::is_signed) {
3049 sign_ext = UINT64_C(0xffffffff00000000);
3050 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003051
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003052 VIXL_ASSERT(sizeof(u) == sizeof(uint64_t));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003053 VIXL_ASSERT(sizeof(u) == sizeof(u0));
3054
3055 u0 = u & 0xffffffff;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003056 u1 = u >> 32 | (((u & sign_mask) != 0) ? sign_ext : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003057 v0 = v & 0xffffffff;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003058 v1 = v >> 32 | (((v & sign_mask) != 0) ? sign_ext : 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003059
3060 w0 = u0 * v0;
3061 t = u1 * v0 + (w0 >> 32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003062
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003063 w1 = t & 0xffffffff;
3064 w2 = t >> 32 | (((t & sign_mask) != 0) ? sign_ext : 0);
3065 w1 = u0 * v1 + w1;
3066 w1 = w1 >> 32 | (((w1 & sign_mask) != 0) ? sign_ext : 0);
3067
3068 uint64_t value = u1 * v1 + w2 + w1;
3069 int64_t result;
3070 memcpy(&result, &value, sizeof(result));
3071 return result;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003072}
3073
3074
3075void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
3076 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3077
3078 uint64_t result = 0;
3079 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
3080 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
3081 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
3082 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
3083 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003084 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
3085 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003086 switch (instr->Mask(DataProcessing3SourceMask)) {
3087 case MADD_w:
3088 case MADD_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003089 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003090 break;
3091 case MSUB_w:
3092 case MSUB_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003093 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003094 break;
3095 case SMADDL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003096 result = ReadXRegister(instr->GetRa()) +
3097 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003098 break;
3099 case SMSUBL_x:
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003100 result = ReadXRegister(instr->GetRa()) -
3101 static_cast<uint64_t>(rn_s32 * rm_s32);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003102 break;
3103 case UMADDL_x:
3104 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
3105 break;
3106 case UMSUBL_x:
3107 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
3108 break;
3109 case UMULH_x:
3110 result = MultiplyHigh(ReadRegister<uint64_t>(instr->GetRn()),
3111 ReadRegister<uint64_t>(instr->GetRm()));
3112 break;
3113 case SMULH_x:
3114 result = MultiplyHigh(ReadXRegister(instr->GetRn()),
3115 ReadXRegister(instr->GetRm()));
3116 break;
3117 default:
3118 VIXL_UNIMPLEMENTED();
3119 }
3120 WriteRegister(reg_size, instr->GetRd(), result);
3121}
3122
3123
3124void Simulator::VisitBitfield(const Instruction* instr) {
3125 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3126 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003127 int R = instr->GetImmR();
3128 int S = instr->GetImmS();
3129 int diff = S - R;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003130 uint64_t mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003131 if (diff >= 0) {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003132 mask = ~UINT64_C(0) >> (64 - (diff + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003133 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003134 } else {
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003135 mask = ~UINT64_C(0) >> (64 - (S + 1));
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003136 mask = RotateRight(mask, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003137 diff += reg_size;
3138 }
3139
3140 // inzero indicates if the extracted bitfield is inserted into the
3141 // destination register value or in zero.
3142 // If extend is true, extend the sign of the extracted bitfield.
3143 bool inzero = false;
3144 bool extend = false;
3145 switch (instr->Mask(BitfieldMask)) {
3146 case BFM_x:
3147 case BFM_w:
3148 break;
3149 case SBFM_x:
3150 case SBFM_w:
3151 inzero = true;
3152 extend = true;
3153 break;
3154 case UBFM_x:
3155 case UBFM_w:
3156 inzero = true;
3157 break;
3158 default:
3159 VIXL_UNIMPLEMENTED();
3160 }
3161
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003162 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
3163 uint64_t src = ReadRegister(reg_size, instr->GetRn());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003164 // Rotate source bitfield into place.
Martyn Capewellfb8e3df2016-11-03 15:50:19 +00003165 uint64_t result = RotateRight(src, R, reg_size);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003166 // Determine the sign extension.
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003167 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
3168 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003169
3170 // Merge sign extension, dest/zero and bitfield.
3171 result = signbits | (result & mask) | (dst & ~mask);
3172
3173 WriteRegister(reg_size, instr->GetRd(), result);
3174}
3175
3176
3177void Simulator::VisitExtract(const Instruction* instr) {
3178 unsigned lsb = instr->GetImmS();
3179 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3180 uint64_t low_res =
3181 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
Martyn Capewell5b24fb32016-11-02 18:52:55 +00003182 uint64_t high_res =
3183 (lsb == 0) ? 0 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
3184 << (reg_size - lsb);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003185 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
3186}
3187
3188
3189void Simulator::VisitFPImmediate(const Instruction* instr) {
3190 AssertSupportedFPCR();
Alexandre Ramesd3832962016-07-04 15:03:43 +01003191 unsigned dest = instr->GetRd();
3192 switch (instr->Mask(FPImmediateMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003193 case FMOV_h_imm:
Jacob Bramleyca789742018-09-13 14:25:46 +01003194 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
Carey Williamsd8bb3572018-04-10 11:58:07 +01003195 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003196 case FMOV_s_imm:
3197 WriteSRegister(dest, instr->GetImmFP32());
3198 break;
3199 case FMOV_d_imm:
3200 WriteDRegister(dest, instr->GetImmFP64());
3201 break;
3202 default:
3203 VIXL_UNREACHABLE();
3204 }
3205}
3206
3207
3208void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
3209 AssertSupportedFPCR();
3210
3211 unsigned dst = instr->GetRd();
3212 unsigned src = instr->GetRn();
3213
3214 FPRounding round = ReadRMode();
3215
3216 switch (instr->Mask(FPIntegerConvertMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003217 case FCVTAS_wh:
3218 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
3219 break;
3220 case FCVTAS_xh:
3221 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
3222 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003223 case FCVTAS_ws:
3224 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
3225 break;
3226 case FCVTAS_xs:
3227 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
3228 break;
3229 case FCVTAS_wd:
3230 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
3231 break;
3232 case FCVTAS_xd:
3233 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
3234 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003235 case FCVTAU_wh:
3236 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
3237 break;
3238 case FCVTAU_xh:
3239 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
3240 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003241 case FCVTAU_ws:
3242 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3243 break;
3244 case FCVTAU_xs:
3245 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3246 break;
3247 case FCVTAU_wd:
3248 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3249 break;
3250 case FCVTAU_xd:
3251 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3252 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003253 case FCVTMS_wh:
3254 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3255 break;
3256 case FCVTMS_xh:
3257 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3258 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003259 case FCVTMS_ws:
3260 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3261 break;
3262 case FCVTMS_xs:
3263 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3264 break;
3265 case FCVTMS_wd:
3266 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3267 break;
3268 case FCVTMS_xd:
3269 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3270 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003271 case FCVTMU_wh:
3272 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3273 break;
3274 case FCVTMU_xh:
3275 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3276 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003277 case FCVTMU_ws:
3278 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3279 break;
3280 case FCVTMU_xs:
3281 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3282 break;
3283 case FCVTMU_wd:
3284 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3285 break;
3286 case FCVTMU_xd:
3287 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3288 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003289 case FCVTPS_wh:
3290 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3291 break;
3292 case FCVTPS_xh:
3293 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3294 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003295 case FCVTPS_ws:
3296 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3297 break;
3298 case FCVTPS_xs:
3299 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3300 break;
3301 case FCVTPS_wd:
3302 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3303 break;
3304 case FCVTPS_xd:
3305 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3306 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003307 case FCVTPU_wh:
3308 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3309 break;
3310 case FCVTPU_xh:
3311 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3312 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003313 case FCVTPU_ws:
3314 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3315 break;
3316 case FCVTPU_xs:
3317 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3318 break;
3319 case FCVTPU_wd:
3320 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3321 break;
3322 case FCVTPU_xd:
3323 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3324 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003325 case FCVTNS_wh:
3326 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3327 break;
3328 case FCVTNS_xh:
3329 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3330 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003331 case FCVTNS_ws:
3332 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3333 break;
3334 case FCVTNS_xs:
3335 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3336 break;
3337 case FCVTNS_wd:
3338 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3339 break;
3340 case FCVTNS_xd:
3341 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3342 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003343 case FCVTNU_wh:
3344 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3345 break;
3346 case FCVTNU_xh:
3347 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3348 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003349 case FCVTNU_ws:
3350 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3351 break;
3352 case FCVTNU_xs:
3353 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3354 break;
3355 case FCVTNU_wd:
3356 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3357 break;
3358 case FCVTNU_xd:
3359 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3360 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003361 case FCVTZS_wh:
3362 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3363 break;
3364 case FCVTZS_xh:
3365 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3366 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003367 case FCVTZS_ws:
3368 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3369 break;
3370 case FCVTZS_xs:
3371 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3372 break;
3373 case FCVTZS_wd:
3374 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3375 break;
3376 case FCVTZS_xd:
3377 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3378 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003379 case FCVTZU_wh:
3380 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3381 break;
3382 case FCVTZU_xh:
3383 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3384 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003385 case FCVTZU_ws:
3386 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3387 break;
3388 case FCVTZU_xs:
3389 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3390 break;
3391 case FCVTZU_wd:
3392 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3393 break;
3394 case FCVTZU_xd:
3395 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3396 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003397 case FJCVTZS:
3398 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3399 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003400 case FMOV_hw:
3401 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3402 break;
3403 case FMOV_wh:
3404 WriteWRegister(dst, ReadHRegisterBits(src));
3405 break;
3406 case FMOV_xh:
3407 WriteXRegister(dst, ReadHRegisterBits(src));
3408 break;
3409 case FMOV_hx:
3410 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3411 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003412 case FMOV_ws:
3413 WriteWRegister(dst, ReadSRegisterBits(src));
3414 break;
3415 case FMOV_xd:
3416 WriteXRegister(dst, ReadDRegisterBits(src));
3417 break;
3418 case FMOV_sw:
3419 WriteSRegisterBits(dst, ReadWRegister(src));
3420 break;
3421 case FMOV_dx:
3422 WriteDRegisterBits(dst, ReadXRegister(src));
3423 break;
3424 case FMOV_d1_x:
3425 LogicVRegister(ReadVRegister(dst))
3426 .SetUint(kFormatD, 1, ReadXRegister(src));
3427 break;
3428 case FMOV_x_d1:
3429 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3430 break;
3431
3432 // A 32-bit input can be handled in the same way as a 64-bit input, since
3433 // the sign- or zero-extension will not affect the conversion.
3434 case SCVTF_dx:
3435 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3436 break;
3437 case SCVTF_dw:
3438 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3439 break;
3440 case UCVTF_dx:
3441 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3442 break;
3443 case UCVTF_dw: {
3444 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003445 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003446 break;
3447 }
3448 case SCVTF_sx:
3449 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3450 break;
3451 case SCVTF_sw:
3452 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3453 break;
3454 case UCVTF_sx:
3455 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3456 break;
3457 case UCVTF_sw: {
Jacob Bramleyca789742018-09-13 14:25:46 +01003458 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3459 break;
3460 }
3461 case SCVTF_hx:
3462 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3463 break;
3464 case SCVTF_hw:
3465 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3466 break;
3467 case UCVTF_hx:
3468 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3469 break;
3470 case UCVTF_hw: {
3471 WriteHRegister(dst,
3472 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003473 break;
3474 }
3475
3476 default:
3477 VIXL_UNREACHABLE();
3478 }
3479}
3480
3481
3482void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3483 AssertSupportedFPCR();
3484
3485 unsigned dst = instr->GetRd();
3486 unsigned src = instr->GetRn();
3487 int fbits = 64 - instr->GetFPScale();
3488
3489 FPRounding round = ReadRMode();
3490
3491 switch (instr->Mask(FPFixedPointConvertMask)) {
3492 // A 32-bit input can be handled in the same way as a 64-bit input, since
3493 // the sign- or zero-extension will not affect the conversion.
3494 case SCVTF_dx_fixed:
3495 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3496 break;
3497 case SCVTF_dw_fixed:
3498 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3499 break;
3500 case UCVTF_dx_fixed:
3501 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3502 break;
3503 case UCVTF_dw_fixed: {
3504 WriteDRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003505 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003506 break;
3507 }
3508 case SCVTF_sx_fixed:
3509 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3510 break;
3511 case SCVTF_sw_fixed:
3512 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3513 break;
3514 case UCVTF_sx_fixed:
3515 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3516 break;
3517 case UCVTF_sw_fixed: {
3518 WriteSRegister(dst,
Jacob Bramleyca789742018-09-13 14:25:46 +01003519 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3520 break;
3521 }
3522 case SCVTF_hx_fixed:
3523 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3524 break;
3525 case SCVTF_hw_fixed:
3526 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3527 break;
3528 case UCVTF_hx_fixed:
3529 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3530 break;
3531 case UCVTF_hw_fixed: {
3532 WriteHRegister(dst,
3533 UFixedToFloat16(ReadRegister<uint32_t>(src),
3534 fbits,
3535 round));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003536 break;
3537 }
3538 case FCVTZS_xd_fixed:
3539 WriteXRegister(dst,
3540 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3541 FPZero));
3542 break;
3543 case FCVTZS_wd_fixed:
3544 WriteWRegister(dst,
3545 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3546 FPZero));
3547 break;
3548 case FCVTZU_xd_fixed:
3549 WriteXRegister(dst,
3550 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3551 FPZero));
3552 break;
3553 case FCVTZU_wd_fixed:
3554 WriteWRegister(dst,
3555 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3556 FPZero));
3557 break;
3558 case FCVTZS_xs_fixed:
3559 WriteXRegister(dst,
3560 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3561 FPZero));
3562 break;
3563 case FCVTZS_ws_fixed:
3564 WriteWRegister(dst,
3565 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3566 FPZero));
3567 break;
3568 case FCVTZU_xs_fixed:
3569 WriteXRegister(dst,
3570 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3571 FPZero));
3572 break;
3573 case FCVTZU_ws_fixed:
3574 WriteWRegister(dst,
3575 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3576 FPZero));
3577 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003578 case FCVTZS_xh_fixed: {
3579 double output =
3580 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3581 WriteXRegister(dst, FPToInt64(output, FPZero));
3582 break;
3583 }
3584 case FCVTZS_wh_fixed: {
3585 double output =
3586 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3587 WriteWRegister(dst, FPToInt32(output, FPZero));
3588 break;
3589 }
3590 case FCVTZU_xh_fixed: {
3591 double output =
3592 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3593 WriteXRegister(dst, FPToUInt64(output, FPZero));
3594 break;
3595 }
3596 case FCVTZU_wh_fixed: {
3597 double output =
3598 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3599 WriteWRegister(dst, FPToUInt32(output, FPZero));
3600 break;
3601 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003602 default:
3603 VIXL_UNREACHABLE();
3604 }
3605}
3606
3607
3608void Simulator::VisitFPCompare(const Instruction* instr) {
3609 AssertSupportedFPCR();
3610
3611 FPTrapFlags trap = DisableTrap;
3612 switch (instr->Mask(FPCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003613 case FCMPE_h:
3614 trap = EnableTrap;
3615 VIXL_FALLTHROUGH();
3616 case FCMP_h:
3617 FPCompare(ReadHRegister(instr->GetRn()),
3618 ReadHRegister(instr->GetRm()),
3619 trap);
3620 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003621 case FCMPE_s:
3622 trap = EnableTrap;
3623 VIXL_FALLTHROUGH();
3624 case FCMP_s:
3625 FPCompare(ReadSRegister(instr->GetRn()),
3626 ReadSRegister(instr->GetRm()),
3627 trap);
3628 break;
3629 case FCMPE_d:
3630 trap = EnableTrap;
3631 VIXL_FALLTHROUGH();
3632 case FCMP_d:
3633 FPCompare(ReadDRegister(instr->GetRn()),
3634 ReadDRegister(instr->GetRm()),
3635 trap);
3636 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003637 case FCMPE_h_zero:
3638 trap = EnableTrap;
3639 VIXL_FALLTHROUGH();
3640 case FCMP_h_zero:
3641 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3642 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003643 case FCMPE_s_zero:
3644 trap = EnableTrap;
3645 VIXL_FALLTHROUGH();
3646 case FCMP_s_zero:
3647 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3648 break;
3649 case FCMPE_d_zero:
3650 trap = EnableTrap;
3651 VIXL_FALLTHROUGH();
3652 case FCMP_d_zero:
3653 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
3654 break;
3655 default:
3656 VIXL_UNIMPLEMENTED();
3657 }
3658}
3659
3660
3661void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
3662 AssertSupportedFPCR();
3663
3664 FPTrapFlags trap = DisableTrap;
3665 switch (instr->Mask(FPConditionalCompareMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003666 case FCCMPE_h:
3667 trap = EnableTrap;
3668 VIXL_FALLTHROUGH();
3669 case FCCMP_h:
3670 if (ConditionPassed(instr->GetCondition())) {
3671 FPCompare(ReadHRegister(instr->GetRn()),
3672 ReadHRegister(instr->GetRm()),
3673 trap);
3674 } else {
3675 ReadNzcv().SetFlags(instr->GetNzcv());
3676 LogSystemRegister(NZCV);
3677 }
3678 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003679 case FCCMPE_s:
3680 trap = EnableTrap;
3681 VIXL_FALLTHROUGH();
3682 case FCCMP_s:
3683 if (ConditionPassed(instr->GetCondition())) {
3684 FPCompare(ReadSRegister(instr->GetRn()),
3685 ReadSRegister(instr->GetRm()),
3686 trap);
3687 } else {
3688 ReadNzcv().SetFlags(instr->GetNzcv());
3689 LogSystemRegister(NZCV);
3690 }
3691 break;
3692 case FCCMPE_d:
3693 trap = EnableTrap;
3694 VIXL_FALLTHROUGH();
3695 case FCCMP_d:
3696 if (ConditionPassed(instr->GetCondition())) {
3697 FPCompare(ReadDRegister(instr->GetRn()),
3698 ReadDRegister(instr->GetRm()),
3699 trap);
3700 } else {
3701 ReadNzcv().SetFlags(instr->GetNzcv());
3702 LogSystemRegister(NZCV);
3703 }
3704 break;
3705 default:
3706 VIXL_UNIMPLEMENTED();
3707 }
3708}
3709
3710
3711void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
3712 AssertSupportedFPCR();
3713
3714 Instr selected;
3715 if (ConditionPassed(instr->GetCondition())) {
3716 selected = instr->GetRn();
3717 } else {
3718 selected = instr->GetRm();
3719 }
3720
3721 switch (instr->Mask(FPConditionalSelectMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003722 case FCSEL_h:
3723 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
3724 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003725 case FCSEL_s:
3726 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
3727 break;
3728 case FCSEL_d:
3729 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
3730 break;
3731 default:
3732 VIXL_UNIMPLEMENTED();
3733 }
3734}
3735
3736
3737void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
3738 AssertSupportedFPCR();
3739
3740 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
Carey Williamsd8bb3572018-04-10 11:58:07 +01003741 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01003742 switch (instr->Mask(FPTypeMask)) {
3743 default:
3744 VIXL_UNREACHABLE_OR_FALLTHROUGH();
3745 case FP64:
3746 vform = kFormatD;
3747 break;
3748 case FP32:
3749 vform = kFormatS;
3750 break;
3751 case FP16:
3752 vform = kFormatH;
3753 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003754 }
Jacob Bramleyca789742018-09-13 14:25:46 +01003755
Alexandre Ramesd3832962016-07-04 15:03:43 +01003756 SimVRegister& rd = ReadVRegister(instr->GetRd());
3757 SimVRegister& rn = ReadVRegister(instr->GetRn());
3758 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07003759 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003760
3761 unsigned fd = instr->GetRd();
3762 unsigned fn = instr->GetRn();
3763
3764 switch (instr->Mask(FPDataProcessing1SourceMask)) {
Carey Williamsd8bb3572018-04-10 11:58:07 +01003765 case FMOV_h:
3766 WriteHRegister(fd, ReadHRegister(fn));
3767 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003768 case FMOV_s:
3769 WriteSRegister(fd, ReadSRegister(fn));
3770 return;
3771 case FMOV_d:
3772 WriteDRegister(fd, ReadDRegister(fn));
3773 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003774 case FABS_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003775 case FABS_s:
3776 case FABS_d:
3777 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
3778 // Explicitly log the register update whilst we have type information.
3779 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3780 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003781 case FNEG_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003782 case FNEG_s:
3783 case FNEG_d:
3784 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
3785 // Explicitly log the register update whilst we have type information.
3786 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3787 return;
3788 case FCVT_ds:
Carey Williamsb57e3622018-04-10 11:42:03 +01003789 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003790 return;
3791 case FCVT_sd:
Carey Williamsb57e3622018-04-10 11:42:03 +01003792 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003793 return;
3794 case FCVT_hs:
Jacob Bramleyca789742018-09-13 14:25:46 +01003795 WriteHRegister(fd,
3796 Float16ToRawbits(
3797 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003798 return;
3799 case FCVT_sh:
Carey Williamsb57e3622018-04-10 11:42:03 +01003800 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003801 return;
3802 case FCVT_dh:
Jacob Bramleyca789742018-09-13 14:25:46 +01003803 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003804 return;
3805 case FCVT_hd:
Jacob Bramleyca789742018-09-13 14:25:46 +01003806 WriteHRegister(fd,
3807 Float16ToRawbits(
3808 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003809 return;
Jacob Bramleyca789742018-09-13 14:25:46 +01003810 case FSQRT_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003811 case FSQRT_s:
3812 case FSQRT_d:
3813 fsqrt(vform, rd, rn);
3814 // Explicitly log the register update whilst we have type information.
3815 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3816 return;
TatWai Chong04471812019-03-19 14:29:00 -07003817 case FRINT32X_s:
3818 case FRINT32X_d:
3819 inexact_exception = true;
3820 frint_mode = kFrintToInt32;
3821 break; // Use FPCR rounding mode.
3822 case FRINT64X_s:
3823 case FRINT64X_d:
3824 inexact_exception = true;
3825 frint_mode = kFrintToInt64;
3826 break; // Use FPCR rounding mode.
3827 case FRINT32Z_s:
3828 case FRINT32Z_d:
3829 inexact_exception = true;
3830 frint_mode = kFrintToInt32;
3831 fpcr_rounding = FPZero;
3832 break;
3833 case FRINT64Z_s:
3834 case FRINT64Z_d:
3835 inexact_exception = true;
3836 frint_mode = kFrintToInt64;
3837 fpcr_rounding = FPZero;
3838 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003839 case FRINTI_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003840 case FRINTI_s:
3841 case FRINTI_d:
3842 break; // Use FPCR rounding mode.
Jacob Bramleyca789742018-09-13 14:25:46 +01003843 case FRINTX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003844 case FRINTX_s:
3845 case FRINTX_d:
3846 inexact_exception = true;
3847 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003848 case FRINTA_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003849 case FRINTA_s:
3850 case FRINTA_d:
3851 fpcr_rounding = FPTieAway;
3852 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003853 case FRINTM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003854 case FRINTM_s:
3855 case FRINTM_d:
3856 fpcr_rounding = FPNegativeInfinity;
3857 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003858 case FRINTN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003859 case FRINTN_s:
3860 case FRINTN_d:
3861 fpcr_rounding = FPTieEven;
3862 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003863 case FRINTP_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003864 case FRINTP_s:
3865 case FRINTP_d:
3866 fpcr_rounding = FPPositiveInfinity;
3867 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003868 case FRINTZ_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003869 case FRINTZ_s:
3870 case FRINTZ_d:
3871 fpcr_rounding = FPZero;
3872 break;
3873 default:
3874 VIXL_UNIMPLEMENTED();
3875 }
3876
3877 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07003878 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003879 // Explicitly log the register update whilst we have type information.
3880 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
3881}
3882
3883
3884void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
3885 AssertSupportedFPCR();
3886
Carey Williamsd8bb3572018-04-10 11:58:07 +01003887 VectorFormat vform;
Jacob Bramleyc41760b2018-06-08 17:14:58 +01003888 switch (instr->Mask(FPTypeMask)) {
3889 default:
3890 VIXL_UNREACHABLE_OR_FALLTHROUGH();
3891 case FP64:
3892 vform = kFormatD;
3893 break;
3894 case FP32:
3895 vform = kFormatS;
3896 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003897 case FP16:
3898 vform = kFormatH;
3899 break;
Carey Williamsd8bb3572018-04-10 11:58:07 +01003900 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003901 SimVRegister& rd = ReadVRegister(instr->GetRd());
3902 SimVRegister& rn = ReadVRegister(instr->GetRn());
3903 SimVRegister& rm = ReadVRegister(instr->GetRm());
3904
3905 switch (instr->Mask(FPDataProcessing2SourceMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01003906 case FADD_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003907 case FADD_s:
3908 case FADD_d:
3909 fadd(vform, rd, rn, rm);
3910 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003911 case FSUB_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003912 case FSUB_s:
3913 case FSUB_d:
3914 fsub(vform, rd, rn, rm);
3915 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003916 case FMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003917 case FMUL_s:
3918 case FMUL_d:
3919 fmul(vform, rd, rn, rm);
3920 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003921 case FNMUL_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003922 case FNMUL_s:
3923 case FNMUL_d:
3924 fnmul(vform, rd, rn, rm);
3925 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003926 case FDIV_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003927 case FDIV_s:
3928 case FDIV_d:
3929 fdiv(vform, rd, rn, rm);
3930 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003931 case FMAX_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003932 case FMAX_s:
3933 case FMAX_d:
3934 fmax(vform, rd, rn, rm);
3935 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003936 case FMIN_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003937 case FMIN_s:
3938 case FMIN_d:
3939 fmin(vform, rd, rn, rm);
3940 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003941 case FMAXNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003942 case FMAXNM_s:
3943 case FMAXNM_d:
3944 fmaxnm(vform, rd, rn, rm);
3945 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01003946 case FMINNM_h:
Alexandre Ramesd3832962016-07-04 15:03:43 +01003947 case FMINNM_s:
3948 case FMINNM_d:
3949 fminnm(vform, rd, rn, rm);
3950 break;
3951 default:
3952 VIXL_UNREACHABLE();
3953 }
3954 // Explicitly log the register update whilst we have type information.
3955 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
3956}
3957
3958
3959void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
3960 AssertSupportedFPCR();
3961
3962 unsigned fd = instr->GetRd();
3963 unsigned fn = instr->GetRn();
3964 unsigned fm = instr->GetRm();
3965 unsigned fa = instr->GetRa();
3966
3967 switch (instr->Mask(FPDataProcessing3SourceMask)) {
3968 // fd = fa +/- (fn * fm)
Jacob Bramleyca789742018-09-13 14:25:46 +01003969 case FMADD_h:
3970 WriteHRegister(fd,
3971 FPMulAdd(ReadHRegister(fa),
3972 ReadHRegister(fn),
3973 ReadHRegister(fm)));
3974 break;
3975 case FMSUB_h:
3976 WriteHRegister(fd,
3977 FPMulAdd(ReadHRegister(fa),
3978 -ReadHRegister(fn),
3979 ReadHRegister(fm)));
3980 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003981 case FMADD_s:
3982 WriteSRegister(fd,
3983 FPMulAdd(ReadSRegister(fa),
3984 ReadSRegister(fn),
3985 ReadSRegister(fm)));
3986 break;
3987 case FMSUB_s:
3988 WriteSRegister(fd,
3989 FPMulAdd(ReadSRegister(fa),
3990 -ReadSRegister(fn),
3991 ReadSRegister(fm)));
3992 break;
3993 case FMADD_d:
3994 WriteDRegister(fd,
3995 FPMulAdd(ReadDRegister(fa),
3996 ReadDRegister(fn),
3997 ReadDRegister(fm)));
3998 break;
3999 case FMSUB_d:
4000 WriteDRegister(fd,
4001 FPMulAdd(ReadDRegister(fa),
4002 -ReadDRegister(fn),
4003 ReadDRegister(fm)));
4004 break;
4005 // Negated variants of the above.
Jacob Bramleyca789742018-09-13 14:25:46 +01004006 case FNMADD_h:
4007 WriteHRegister(fd,
4008 FPMulAdd(-ReadHRegister(fa),
4009 -ReadHRegister(fn),
4010 ReadHRegister(fm)));
4011 break;
4012 case FNMSUB_h:
4013 WriteHRegister(fd,
4014 FPMulAdd(-ReadHRegister(fa),
4015 ReadHRegister(fn),
4016 ReadHRegister(fm)));
4017 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004018 case FNMADD_s:
4019 WriteSRegister(fd,
4020 FPMulAdd(-ReadSRegister(fa),
4021 -ReadSRegister(fn),
4022 ReadSRegister(fm)));
4023 break;
4024 case FNMSUB_s:
4025 WriteSRegister(fd,
4026 FPMulAdd(-ReadSRegister(fa),
4027 ReadSRegister(fn),
4028 ReadSRegister(fm)));
4029 break;
4030 case FNMADD_d:
4031 WriteDRegister(fd,
4032 FPMulAdd(-ReadDRegister(fa),
4033 -ReadDRegister(fn),
4034 ReadDRegister(fm)));
4035 break;
4036 case FNMSUB_d:
4037 WriteDRegister(fd,
4038 FPMulAdd(-ReadDRegister(fa),
4039 ReadDRegister(fn),
4040 ReadDRegister(fm)));
4041 break;
4042 default:
4043 VIXL_UNIMPLEMENTED();
4044 }
4045}
4046
4047
4048bool Simulator::FPProcessNaNs(const Instruction* instr) {
4049 unsigned fd = instr->GetRd();
4050 unsigned fn = instr->GetRn();
4051 unsigned fm = instr->GetRm();
4052 bool done = false;
4053
4054 if (instr->Mask(FP64) == FP64) {
4055 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004056 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004057 WriteDRegister(fd, result);
4058 done = true;
4059 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004060 } else if (instr->Mask(FP32) == FP32) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004061 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
Jacob Bramleyca789742018-09-13 14:25:46 +01004062 if (IsNaN(result)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004063 WriteSRegister(fd, result);
4064 done = true;
4065 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004066 } else {
4067 VIXL_ASSERT(instr->Mask(FP16) == FP16);
4068 VIXL_UNIMPLEMENTED();
Alexandre Ramesd3832962016-07-04 15:03:43 +01004069 }
4070
4071 return done;
4072}
4073
4074
4075void Simulator::SysOp_W(int op, int64_t val) {
4076 switch (op) {
4077 case IVAU:
4078 case CVAC:
4079 case CVAU:
Jacob Bramley385eb902018-09-26 14:43:29 +01004080 case CVAP:
TatWai Chong684f5f72018-12-25 17:49:56 -08004081 case CVADP:
Alexandre Ramesd3832962016-07-04 15:03:43 +01004082 case CIVAC: {
4083 // Perform a dummy memory access to ensure that we have read access
4084 // to the specified address.
4085 volatile uint8_t y = Memory::Read<uint8_t>(val);
4086 USE(y);
4087 // TODO: Implement "case ZVA:".
4088 break;
4089 }
4090 default:
4091 VIXL_UNIMPLEMENTED();
4092 }
4093}
4094
4095
Jacob Bramleyca789742018-09-13 14:25:46 +01004096// clang-format off
4097#define PAUTH_SYSTEM_MODES(V) \
4098 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
4099 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
4100 V(AZ, 30, 0x00000000, kPACKeyIA) \
4101 V(BZ, 30, 0x00000000, kPACKeyIB) \
4102 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
4103 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
4104// clang-format on
4105
4106
Alexandre Ramesd3832962016-07-04 15:03:43 +01004107void Simulator::VisitSystem(const Instruction* instr) {
4108 // Some system instructions hijack their Op and Cp fields to represent a
4109 // range of immediates instead of indicating a different instruction. This
4110 // makes the decoding tricky.
Jacob Bramleyca789742018-09-13 14:25:46 +01004111 if (instr->GetInstructionBits() == XPACLRI) {
4112 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
Alexander Gilday2487f142018-11-05 13:07:27 +00004113 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
4114 switch (instr->Mask(SystemPStateMask)) {
4115 case CFINV:
4116 ReadNzcv().SetC(!ReadC());
4117 break;
Alexander Gilday84ee1442018-11-06 15:28:07 +00004118 case AXFLAG:
4119 ReadNzcv().SetN(0);
4120 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
4121 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
4122 ReadNzcv().SetV(0);
4123 break;
4124 case XAFLAG: {
4125 // Can't set the flags in place due to the logical dependencies.
4126 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
4127 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
4128 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
4129 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
4130 ReadNzcv().SetN(n);
4131 ReadNzcv().SetZ(z);
4132 ReadNzcv().SetC(c);
4133 ReadNzcv().SetV(v);
4134 break;
4135 }
Alexander Gilday2487f142018-11-05 13:07:27 +00004136 }
Jacob Bramleyca789742018-09-13 14:25:46 +01004137 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004138 // Check BType allows PACI[AB]SP instructions.
4139 if (PcIsInGuardedPage()) {
4140 Instr i = instr->Mask(SystemPAuthMask);
4141 if ((i == PACIASP) || (i == PACIBSP)) {
4142 switch (ReadBType()) {
Martyn Capewellcb963f72018-10-22 15:25:28 +01004143 case BranchFromGuardedNotToIP:
4144 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
4145 // assume here to be zero. This allows execution of PACI[AB]SP when
4146 // BTYPE is BranchFromGuardedNotToIP (0b11).
Martyn Capewelldddf02d2019-02-12 10:41:17 +00004147 case DefaultBType:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004148 case BranchFromUnguardedOrToIP:
4149 case BranchAndLink:
4150 break;
4151 }
4152 }
4153 }
4154
Jacob Bramleyca789742018-09-13 14:25:46 +01004155 switch (instr->Mask(SystemPAuthMask)) {
4156#define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
4157 case PACI##SUFFIX: \
4158 WriteXRegister(DST, \
4159 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
4160 break; \
4161 case AUTI##SUFFIX: \
4162 WriteXRegister(DST, \
4163 AuthPAC(ReadXRegister(DST), \
4164 MOD, \
4165 KEY, \
4166 kInstructionPointer)); \
4167 break;
4168
4169 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
4170#undef DEFINE_PAUTH_FUNCS
4171 }
4172 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
4173 SystemExclusiveMonitorFixed) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004174 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
4175 switch (instr->Mask(SystemExclusiveMonitorMask)) {
4176 case CLREX: {
4177 PrintExclusiveAccessWarning();
4178 ClearLocalMonitor();
4179 break;
4180 }
4181 }
4182 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
4183 switch (instr->Mask(SystemSysRegMask)) {
4184 case MRS: {
4185 switch (instr->GetImmSystemRegister()) {
4186 case NZCV:
4187 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
4188 break;
4189 case FPCR:
4190 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
4191 break;
TatWai Chong04edf682018-12-27 16:01:02 -08004192 case RNDR:
4193 case RNDRRS: {
4194 uint64_t high = jrand48(rndr_state_);
4195 uint64_t low = jrand48(rndr_state_);
4196 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
4197 WriteXRegister(instr->GetRt(), rand_num);
4198 // Simulate successful random number generation.
4199 // TODO: Return failure occasionally as a random number cannot be
4200 // returned in a period of time.
4201 ReadNzcv().SetRawValue(NoFlag);
4202 LogSystemRegister(NZCV);
4203 break;
4204 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004205 default:
4206 VIXL_UNIMPLEMENTED();
4207 }
4208 break;
4209 }
4210 case MSR: {
4211 switch (instr->GetImmSystemRegister()) {
4212 case NZCV:
4213 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
4214 LogSystemRegister(NZCV);
4215 break;
4216 case FPCR:
4217 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
4218 LogSystemRegister(FPCR);
4219 break;
4220 default:
4221 VIXL_UNIMPLEMENTED();
4222 }
4223 break;
4224 }
4225 }
4226 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
4227 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
4228 switch (instr->GetImmHint()) {
4229 case NOP:
Jacob Bramleyca789742018-09-13 14:25:46 +01004230 case ESB:
Martyn Capewella41e4342018-02-15 11:31:30 +00004231 case CSDB:
Martyn Capewellcb963f72018-10-22 15:25:28 +01004232 case BTI_jc:
4233 break;
4234 case BTI:
4235 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
4236 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
4237 }
4238 break;
4239 case BTI_c:
4240 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
4241 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
4242 }
4243 break;
4244 case BTI_j:
4245 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4246 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4247 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004248 break;
4249 default:
4250 VIXL_UNIMPLEMENTED();
4251 }
4252 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4253 __sync_synchronize();
4254 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4255 switch (instr->Mask(SystemSysMask)) {
4256 case SYS:
4257 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4258 break;
4259 default:
4260 VIXL_UNIMPLEMENTED();
4261 }
4262 } else {
4263 VIXL_UNIMPLEMENTED();
4264 }
4265}
4266
4267
4268void Simulator::VisitException(const Instruction* instr) {
4269 switch (instr->Mask(ExceptionMask)) {
4270 case HLT:
4271 switch (instr->GetImmException()) {
4272 case kUnreachableOpcode:
4273 DoUnreachable(instr);
4274 return;
4275 case kTraceOpcode:
4276 DoTrace(instr);
4277 return;
4278 case kLogOpcode:
4279 DoLog(instr);
4280 return;
4281 case kPrintfOpcode:
4282 DoPrintf(instr);
4283 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01004284 case kRuntimeCallOpcode:
4285 DoRuntimeCall(instr);
4286 return;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01004287 case kSetCPUFeaturesOpcode:
4288 case kEnableCPUFeaturesOpcode:
4289 case kDisableCPUFeaturesOpcode:
4290 DoConfigureCPUFeatures(instr);
4291 return;
4292 case kSaveCPUFeaturesOpcode:
4293 DoSaveCPUFeatures(instr);
4294 return;
4295 case kRestoreCPUFeaturesOpcode:
4296 DoRestoreCPUFeatures(instr);
4297 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004298 default:
4299 HostBreakpoint();
4300 return;
4301 }
4302 case BRK:
4303 HostBreakpoint();
4304 return;
4305 default:
4306 VIXL_UNIMPLEMENTED();
4307 }
4308}
4309
4310
4311void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4312 VisitUnimplemented(instr);
4313}
4314
4315
4316void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4317 VisitUnimplemented(instr);
4318}
4319
4320
4321void Simulator::VisitCryptoAES(const Instruction* instr) {
4322 VisitUnimplemented(instr);
4323}
4324
4325
4326void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4327 NEONFormatDecoder nfd(instr);
4328 VectorFormat vf = nfd.GetVectorFormat();
4329
4330 static const NEONFormatMap map_lp =
4331 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4332 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4333
4334 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4335 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4336
4337 static const NEONFormatMap map_fcvtn = {{22, 30},
4338 {NF_4H, NF_8H, NF_2S, NF_4S}};
4339 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4340
4341 SimVRegister& rd = ReadVRegister(instr->GetRd());
4342 SimVRegister& rn = ReadVRegister(instr->GetRn());
4343
4344 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4345 // These instructions all use a two bit size field, except NOT and RBIT,
4346 // which use the field to encode the operation.
4347 switch (instr->Mask(NEON2RegMiscMask)) {
4348 case NEON_REV64:
4349 rev64(vf, rd, rn);
4350 break;
4351 case NEON_REV32:
4352 rev32(vf, rd, rn);
4353 break;
4354 case NEON_REV16:
4355 rev16(vf, rd, rn);
4356 break;
4357 case NEON_SUQADD:
4358 suqadd(vf, rd, rn);
4359 break;
4360 case NEON_USQADD:
4361 usqadd(vf, rd, rn);
4362 break;
4363 case NEON_CLS:
4364 cls(vf, rd, rn);
4365 break;
4366 case NEON_CLZ:
4367 clz(vf, rd, rn);
4368 break;
4369 case NEON_CNT:
4370 cnt(vf, rd, rn);
4371 break;
4372 case NEON_SQABS:
4373 abs(vf, rd, rn).SignedSaturate(vf);
4374 break;
4375 case NEON_SQNEG:
4376 neg(vf, rd, rn).SignedSaturate(vf);
4377 break;
4378 case NEON_CMGT_zero:
4379 cmp(vf, rd, rn, 0, gt);
4380 break;
4381 case NEON_CMGE_zero:
4382 cmp(vf, rd, rn, 0, ge);
4383 break;
4384 case NEON_CMEQ_zero:
4385 cmp(vf, rd, rn, 0, eq);
4386 break;
4387 case NEON_CMLE_zero:
4388 cmp(vf, rd, rn, 0, le);
4389 break;
4390 case NEON_CMLT_zero:
4391 cmp(vf, rd, rn, 0, lt);
4392 break;
4393 case NEON_ABS:
4394 abs(vf, rd, rn);
4395 break;
4396 case NEON_NEG:
4397 neg(vf, rd, rn);
4398 break;
4399 case NEON_SADDLP:
4400 saddlp(vf_lp, rd, rn);
4401 break;
4402 case NEON_UADDLP:
4403 uaddlp(vf_lp, rd, rn);
4404 break;
4405 case NEON_SADALP:
4406 sadalp(vf_lp, rd, rn);
4407 break;
4408 case NEON_UADALP:
4409 uadalp(vf_lp, rd, rn);
4410 break;
4411 case NEON_RBIT_NOT:
4412 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4413 switch (instr->GetFPType()) {
4414 case 0:
4415 not_(vf, rd, rn);
4416 break;
4417 case 1:
4418 rbit(vf, rd, rn);
4419 break;
4420 default:
4421 VIXL_UNIMPLEMENTED();
4422 }
4423 break;
4424 }
4425 } else {
4426 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4427 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4428 bool inexact_exception = false;
TatWai Chong04471812019-03-19 14:29:00 -07004429 FrintMode frint_mode = kFrintToInteger;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004430
4431 // These instructions all use a one bit size field, except XTN, SQXTUN,
4432 // SHLL, SQXTN and UQXTN, which use a two bit size field.
4433 switch (instr->Mask(NEON2RegMiscFPMask)) {
4434 case NEON_FABS:
4435 fabs_(fpf, rd, rn);
4436 return;
4437 case NEON_FNEG:
4438 fneg(fpf, rd, rn);
4439 return;
4440 case NEON_FSQRT:
4441 fsqrt(fpf, rd, rn);
4442 return;
4443 case NEON_FCVTL:
4444 if (instr->Mask(NEON_Q)) {
4445 fcvtl2(vf_fcvtl, rd, rn);
4446 } else {
4447 fcvtl(vf_fcvtl, rd, rn);
4448 }
4449 return;
4450 case NEON_FCVTN:
4451 if (instr->Mask(NEON_Q)) {
4452 fcvtn2(vf_fcvtn, rd, rn);
4453 } else {
4454 fcvtn(vf_fcvtn, rd, rn);
4455 }
4456 return;
4457 case NEON_FCVTXN:
4458 if (instr->Mask(NEON_Q)) {
4459 fcvtxn2(vf_fcvtn, rd, rn);
4460 } else {
4461 fcvtxn(vf_fcvtn, rd, rn);
4462 }
4463 return;
4464
4465 // The following instructions break from the switch statement, rather
4466 // than return.
TatWai Chong04471812019-03-19 14:29:00 -07004467 case NEON_FRINT32X:
4468 inexact_exception = true;
4469 frint_mode = kFrintToInt32;
4470 break; // Use FPCR rounding mode.
4471 case NEON_FRINT32Z:
4472 inexact_exception = true;
4473 frint_mode = kFrintToInt32;
4474 fpcr_rounding = FPZero;
4475 break;
4476 case NEON_FRINT64X:
4477 inexact_exception = true;
4478 frint_mode = kFrintToInt64;
4479 break; // Use FPCR rounding mode.
4480 case NEON_FRINT64Z:
4481 inexact_exception = true;
4482 frint_mode = kFrintToInt64;
4483 fpcr_rounding = FPZero;
4484 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01004485 case NEON_FRINTI:
4486 break; // Use FPCR rounding mode.
4487 case NEON_FRINTX:
4488 inexact_exception = true;
4489 break;
4490 case NEON_FRINTA:
4491 fpcr_rounding = FPTieAway;
4492 break;
4493 case NEON_FRINTM:
4494 fpcr_rounding = FPNegativeInfinity;
4495 break;
4496 case NEON_FRINTN:
4497 fpcr_rounding = FPTieEven;
4498 break;
4499 case NEON_FRINTP:
4500 fpcr_rounding = FPPositiveInfinity;
4501 break;
4502 case NEON_FRINTZ:
4503 fpcr_rounding = FPZero;
4504 break;
4505
4506 case NEON_FCVTNS:
4507 fcvts(fpf, rd, rn, FPTieEven);
4508 return;
4509 case NEON_FCVTNU:
4510 fcvtu(fpf, rd, rn, FPTieEven);
4511 return;
4512 case NEON_FCVTPS:
4513 fcvts(fpf, rd, rn, FPPositiveInfinity);
4514 return;
4515 case NEON_FCVTPU:
4516 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4517 return;
4518 case NEON_FCVTMS:
4519 fcvts(fpf, rd, rn, FPNegativeInfinity);
4520 return;
4521 case NEON_FCVTMU:
4522 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4523 return;
4524 case NEON_FCVTZS:
4525 fcvts(fpf, rd, rn, FPZero);
4526 return;
4527 case NEON_FCVTZU:
4528 fcvtu(fpf, rd, rn, FPZero);
4529 return;
4530 case NEON_FCVTAS:
4531 fcvts(fpf, rd, rn, FPTieAway);
4532 return;
4533 case NEON_FCVTAU:
4534 fcvtu(fpf, rd, rn, FPTieAway);
4535 return;
4536 case NEON_SCVTF:
4537 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4538 return;
4539 case NEON_UCVTF:
4540 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4541 return;
4542 case NEON_URSQRTE:
4543 ursqrte(fpf, rd, rn);
4544 return;
4545 case NEON_URECPE:
4546 urecpe(fpf, rd, rn);
4547 return;
4548 case NEON_FRSQRTE:
4549 frsqrte(fpf, rd, rn);
4550 return;
4551 case NEON_FRECPE:
4552 frecpe(fpf, rd, rn, fpcr_rounding);
4553 return;
4554 case NEON_FCMGT_zero:
4555 fcmp_zero(fpf, rd, rn, gt);
4556 return;
4557 case NEON_FCMGE_zero:
4558 fcmp_zero(fpf, rd, rn, ge);
4559 return;
4560 case NEON_FCMEQ_zero:
4561 fcmp_zero(fpf, rd, rn, eq);
4562 return;
4563 case NEON_FCMLE_zero:
4564 fcmp_zero(fpf, rd, rn, le);
4565 return;
4566 case NEON_FCMLT_zero:
4567 fcmp_zero(fpf, rd, rn, lt);
4568 return;
4569 default:
4570 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4571 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4572 switch (instr->Mask(NEON2RegMiscMask)) {
4573 case NEON_XTN:
4574 xtn(vf, rd, rn);
4575 return;
4576 case NEON_SQXTN:
4577 sqxtn(vf, rd, rn);
4578 return;
4579 case NEON_UQXTN:
4580 uqxtn(vf, rd, rn);
4581 return;
4582 case NEON_SQXTUN:
4583 sqxtun(vf, rd, rn);
4584 return;
4585 case NEON_SHLL:
4586 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4587 if (instr->Mask(NEON_Q)) {
4588 shll2(vf, rd, rn);
4589 } else {
4590 shll(vf, rd, rn);
4591 }
4592 return;
4593 default:
4594 VIXL_UNIMPLEMENTED();
4595 }
4596 } else {
4597 VIXL_UNIMPLEMENTED();
4598 }
4599 }
4600
4601 // Only FRINT* instructions fall through the switch above.
TatWai Chong04471812019-03-19 14:29:00 -07004602 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004603 }
4604}
4605
4606
Jacob Bramleyca789742018-09-13 14:25:46 +01004607void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4608 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4609 NEONFormatDecoder nfd(instr);
4610 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4611
4612 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4613
4614 SimVRegister& rd = ReadVRegister(instr->GetRd());
4615 SimVRegister& rn = ReadVRegister(instr->GetRn());
4616
4617 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4618 case NEON_SCVTF_H:
4619 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4620 return;
4621 case NEON_UCVTF_H:
4622 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4623 return;
4624 case NEON_FCVTNS_H:
4625 fcvts(fpf, rd, rn, FPTieEven);
4626 return;
4627 case NEON_FCVTNU_H:
4628 fcvtu(fpf, rd, rn, FPTieEven);
4629 return;
4630 case NEON_FCVTPS_H:
4631 fcvts(fpf, rd, rn, FPPositiveInfinity);
4632 return;
4633 case NEON_FCVTPU_H:
4634 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4635 return;
4636 case NEON_FCVTMS_H:
4637 fcvts(fpf, rd, rn, FPNegativeInfinity);
4638 return;
4639 case NEON_FCVTMU_H:
4640 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4641 return;
4642 case NEON_FCVTZS_H:
4643 fcvts(fpf, rd, rn, FPZero);
4644 return;
4645 case NEON_FCVTZU_H:
4646 fcvtu(fpf, rd, rn, FPZero);
4647 return;
4648 case NEON_FCVTAS_H:
4649 fcvts(fpf, rd, rn, FPTieAway);
4650 return;
4651 case NEON_FCVTAU_H:
4652 fcvtu(fpf, rd, rn, FPTieAway);
4653 return;
4654 case NEON_FRINTI_H:
4655 frint(fpf, rd, rn, fpcr_rounding, false);
4656 return;
4657 case NEON_FRINTX_H:
4658 frint(fpf, rd, rn, fpcr_rounding, true);
4659 return;
4660 case NEON_FRINTA_H:
4661 frint(fpf, rd, rn, FPTieAway, false);
4662 return;
4663 case NEON_FRINTM_H:
4664 frint(fpf, rd, rn, FPNegativeInfinity, false);
4665 return;
4666 case NEON_FRINTN_H:
4667 frint(fpf, rd, rn, FPTieEven, false);
4668 return;
4669 case NEON_FRINTP_H:
4670 frint(fpf, rd, rn, FPPositiveInfinity, false);
4671 return;
4672 case NEON_FRINTZ_H:
4673 frint(fpf, rd, rn, FPZero, false);
4674 return;
4675 case NEON_FABS_H:
4676 fabs_(fpf, rd, rn);
4677 return;
4678 case NEON_FNEG_H:
4679 fneg(fpf, rd, rn);
4680 return;
4681 case NEON_FSQRT_H:
4682 fsqrt(fpf, rd, rn);
4683 return;
4684 case NEON_FRSQRTE_H:
4685 frsqrte(fpf, rd, rn);
4686 return;
4687 case NEON_FRECPE_H:
4688 frecpe(fpf, rd, rn, fpcr_rounding);
4689 return;
4690 case NEON_FCMGT_H_zero:
4691 fcmp_zero(fpf, rd, rn, gt);
4692 return;
4693 case NEON_FCMGE_H_zero:
4694 fcmp_zero(fpf, rd, rn, ge);
4695 return;
4696 case NEON_FCMEQ_H_zero:
4697 fcmp_zero(fpf, rd, rn, eq);
4698 return;
4699 case NEON_FCMLE_H_zero:
4700 fcmp_zero(fpf, rd, rn, le);
4701 return;
4702 case NEON_FCMLT_H_zero:
4703 fcmp_zero(fpf, rd, rn, lt);
4704 return;
4705 default:
4706 VIXL_UNIMPLEMENTED();
4707 return;
4708 }
4709}
4710
4711
Alexandre Ramesd3832962016-07-04 15:03:43 +01004712void Simulator::VisitNEON3Same(const Instruction* instr) {
4713 NEONFormatDecoder nfd(instr);
4714 SimVRegister& rd = ReadVRegister(instr->GetRd());
4715 SimVRegister& rn = ReadVRegister(instr->GetRn());
4716 SimVRegister& rm = ReadVRegister(instr->GetRm());
4717
4718 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
4719 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4720 switch (instr->Mask(NEON3SameLogicalMask)) {
4721 case NEON_AND:
4722 and_(vf, rd, rn, rm);
4723 break;
4724 case NEON_ORR:
4725 orr(vf, rd, rn, rm);
4726 break;
4727 case NEON_ORN:
4728 orn(vf, rd, rn, rm);
4729 break;
4730 case NEON_EOR:
4731 eor(vf, rd, rn, rm);
4732 break;
4733 case NEON_BIC:
4734 bic(vf, rd, rn, rm);
4735 break;
4736 case NEON_BIF:
4737 bif(vf, rd, rn, rm);
4738 break;
4739 case NEON_BIT:
4740 bit(vf, rd, rn, rm);
4741 break;
4742 case NEON_BSL:
4743 bsl(vf, rd, rn, rm);
4744 break;
4745 default:
4746 VIXL_UNIMPLEMENTED();
4747 }
4748 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
4749 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4750 switch (instr->Mask(NEON3SameFPMask)) {
4751 case NEON_FADD:
4752 fadd(vf, rd, rn, rm);
4753 break;
4754 case NEON_FSUB:
4755 fsub(vf, rd, rn, rm);
4756 break;
4757 case NEON_FMUL:
4758 fmul(vf, rd, rn, rm);
4759 break;
4760 case NEON_FDIV:
4761 fdiv(vf, rd, rn, rm);
4762 break;
4763 case NEON_FMAX:
4764 fmax(vf, rd, rn, rm);
4765 break;
4766 case NEON_FMIN:
4767 fmin(vf, rd, rn, rm);
4768 break;
4769 case NEON_FMAXNM:
4770 fmaxnm(vf, rd, rn, rm);
4771 break;
4772 case NEON_FMINNM:
4773 fminnm(vf, rd, rn, rm);
4774 break;
4775 case NEON_FMLA:
4776 fmla(vf, rd, rn, rm);
4777 break;
4778 case NEON_FMLS:
4779 fmls(vf, rd, rn, rm);
4780 break;
4781 case NEON_FMULX:
4782 fmulx(vf, rd, rn, rm);
4783 break;
4784 case NEON_FACGE:
4785 fabscmp(vf, rd, rn, rm, ge);
4786 break;
4787 case NEON_FACGT:
4788 fabscmp(vf, rd, rn, rm, gt);
4789 break;
4790 case NEON_FCMEQ:
4791 fcmp(vf, rd, rn, rm, eq);
4792 break;
4793 case NEON_FCMGE:
4794 fcmp(vf, rd, rn, rm, ge);
4795 break;
4796 case NEON_FCMGT:
4797 fcmp(vf, rd, rn, rm, gt);
4798 break;
4799 case NEON_FRECPS:
4800 frecps(vf, rd, rn, rm);
4801 break;
4802 case NEON_FRSQRTS:
4803 frsqrts(vf, rd, rn, rm);
4804 break;
4805 case NEON_FABD:
4806 fabd(vf, rd, rn, rm);
4807 break;
4808 case NEON_FADDP:
4809 faddp(vf, rd, rn, rm);
4810 break;
4811 case NEON_FMAXP:
4812 fmaxp(vf, rd, rn, rm);
4813 break;
4814 case NEON_FMAXNMP:
4815 fmaxnmp(vf, rd, rn, rm);
4816 break;
4817 case NEON_FMINP:
4818 fminp(vf, rd, rn, rm);
4819 break;
4820 case NEON_FMINNMP:
4821 fminnmp(vf, rd, rn, rm);
4822 break;
4823 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01004824 // FMLAL{2} and FMLSL{2} have special-case encodings.
4825 switch (instr->Mask(NEON3SameFHMMask)) {
4826 case NEON_FMLAL:
4827 fmlal(vf, rd, rn, rm);
4828 break;
4829 case NEON_FMLAL2:
4830 fmlal2(vf, rd, rn, rm);
4831 break;
4832 case NEON_FMLSL:
4833 fmlsl(vf, rd, rn, rm);
4834 break;
4835 case NEON_FMLSL2:
4836 fmlsl2(vf, rd, rn, rm);
4837 break;
4838 default:
4839 VIXL_UNIMPLEMENTED();
4840 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004841 }
4842 } else {
4843 VectorFormat vf = nfd.GetVectorFormat();
4844 switch (instr->Mask(NEON3SameMask)) {
4845 case NEON_ADD:
4846 add(vf, rd, rn, rm);
4847 break;
4848 case NEON_ADDP:
4849 addp(vf, rd, rn, rm);
4850 break;
4851 case NEON_CMEQ:
4852 cmp(vf, rd, rn, rm, eq);
4853 break;
4854 case NEON_CMGE:
4855 cmp(vf, rd, rn, rm, ge);
4856 break;
4857 case NEON_CMGT:
4858 cmp(vf, rd, rn, rm, gt);
4859 break;
4860 case NEON_CMHI:
4861 cmp(vf, rd, rn, rm, hi);
4862 break;
4863 case NEON_CMHS:
4864 cmp(vf, rd, rn, rm, hs);
4865 break;
4866 case NEON_CMTST:
4867 cmptst(vf, rd, rn, rm);
4868 break;
4869 case NEON_MLS:
Jacob Bramley22023df2019-05-14 17:55:43 +01004870 mls(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004871 break;
4872 case NEON_MLA:
Jacob Bramley22023df2019-05-14 17:55:43 +01004873 mla(vf, rd, rd, rn, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004874 break;
4875 case NEON_MUL:
4876 mul(vf, rd, rn, rm);
4877 break;
4878 case NEON_PMUL:
4879 pmul(vf, rd, rn, rm);
4880 break;
4881 case NEON_SMAX:
4882 smax(vf, rd, rn, rm);
4883 break;
4884 case NEON_SMAXP:
4885 smaxp(vf, rd, rn, rm);
4886 break;
4887 case NEON_SMIN:
4888 smin(vf, rd, rn, rm);
4889 break;
4890 case NEON_SMINP:
4891 sminp(vf, rd, rn, rm);
4892 break;
4893 case NEON_SUB:
4894 sub(vf, rd, rn, rm);
4895 break;
4896 case NEON_UMAX:
4897 umax(vf, rd, rn, rm);
4898 break;
4899 case NEON_UMAXP:
4900 umaxp(vf, rd, rn, rm);
4901 break;
4902 case NEON_UMIN:
4903 umin(vf, rd, rn, rm);
4904 break;
4905 case NEON_UMINP:
4906 uminp(vf, rd, rn, rm);
4907 break;
4908 case NEON_SSHL:
4909 sshl(vf, rd, rn, rm);
4910 break;
4911 case NEON_USHL:
4912 ushl(vf, rd, rn, rm);
4913 break;
4914 case NEON_SABD:
4915 absdiff(vf, rd, rn, rm, true);
4916 break;
4917 case NEON_UABD:
4918 absdiff(vf, rd, rn, rm, false);
4919 break;
4920 case NEON_SABA:
4921 saba(vf, rd, rn, rm);
4922 break;
4923 case NEON_UABA:
4924 uaba(vf, rd, rn, rm);
4925 break;
4926 case NEON_UQADD:
4927 add(vf, rd, rn, rm).UnsignedSaturate(vf);
4928 break;
4929 case NEON_SQADD:
4930 add(vf, rd, rn, rm).SignedSaturate(vf);
4931 break;
4932 case NEON_UQSUB:
4933 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
4934 break;
4935 case NEON_SQSUB:
4936 sub(vf, rd, rn, rm).SignedSaturate(vf);
4937 break;
4938 case NEON_SQDMULH:
4939 sqdmulh(vf, rd, rn, rm);
4940 break;
4941 case NEON_SQRDMULH:
4942 sqrdmulh(vf, rd, rn, rm);
4943 break;
4944 case NEON_UQSHL:
4945 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
4946 break;
4947 case NEON_SQSHL:
4948 sshl(vf, rd, rn, rm).SignedSaturate(vf);
4949 break;
4950 case NEON_URSHL:
4951 ushl(vf, rd, rn, rm).Round(vf);
4952 break;
4953 case NEON_SRSHL:
4954 sshl(vf, rd, rn, rm).Round(vf);
4955 break;
4956 case NEON_UQRSHL:
4957 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
4958 break;
4959 case NEON_SQRSHL:
4960 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
4961 break;
4962 case NEON_UHADD:
4963 add(vf, rd, rn, rm).Uhalve(vf);
4964 break;
4965 case NEON_URHADD:
4966 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
4967 break;
4968 case NEON_SHADD:
4969 add(vf, rd, rn, rm).Halve(vf);
4970 break;
4971 case NEON_SRHADD:
4972 add(vf, rd, rn, rm).Halve(vf).Round(vf);
4973 break;
4974 case NEON_UHSUB:
4975 sub(vf, rd, rn, rm).Uhalve(vf);
4976 break;
4977 case NEON_SHSUB:
4978 sub(vf, rd, rn, rm).Halve(vf);
4979 break;
4980 default:
4981 VIXL_UNIMPLEMENTED();
4982 }
4983 }
4984}
4985
4986
Jacob Bramleyca789742018-09-13 14:25:46 +01004987void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
4988 NEONFormatDecoder nfd(instr);
4989 SimVRegister& rd = ReadVRegister(instr->GetRd());
4990 SimVRegister& rn = ReadVRegister(instr->GetRn());
4991 SimVRegister& rm = ReadVRegister(instr->GetRm());
4992
4993 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
4994 switch (instr->Mask(NEON3SameFP16Mask)) {
4995#define SIM_FUNC(A, B) \
4996 case NEON_##A##_H: \
4997 B(vf, rd, rn, rm); \
4998 break;
4999 SIM_FUNC(FMAXNM, fmaxnm);
5000 SIM_FUNC(FMLA, fmla);
5001 SIM_FUNC(FADD, fadd);
5002 SIM_FUNC(FMULX, fmulx);
5003 SIM_FUNC(FMAX, fmax);
5004 SIM_FUNC(FRECPS, frecps);
5005 SIM_FUNC(FMINNM, fminnm);
5006 SIM_FUNC(FMLS, fmls);
5007 SIM_FUNC(FSUB, fsub);
5008 SIM_FUNC(FMIN, fmin);
5009 SIM_FUNC(FRSQRTS, frsqrts);
5010 SIM_FUNC(FMAXNMP, fmaxnmp);
5011 SIM_FUNC(FADDP, faddp);
5012 SIM_FUNC(FMUL, fmul);
5013 SIM_FUNC(FMAXP, fmaxp);
5014 SIM_FUNC(FDIV, fdiv);
5015 SIM_FUNC(FMINNMP, fminnmp);
5016 SIM_FUNC(FABD, fabd);
5017 SIM_FUNC(FMINP, fminp);
5018#undef SIM_FUNC
5019 case NEON_FCMEQ_H:
5020 fcmp(vf, rd, rn, rm, eq);
5021 break;
5022 case NEON_FCMGE_H:
5023 fcmp(vf, rd, rn, rm, ge);
5024 break;
5025 case NEON_FACGE_H:
5026 fabscmp(vf, rd, rn, rm, ge);
5027 break;
5028 case NEON_FCMGT_H:
5029 fcmp(vf, rd, rn, rm, gt);
5030 break;
5031 case NEON_FACGT_H:
5032 fabscmp(vf, rd, rn, rm, gt);
5033 break;
5034 default:
5035 VIXL_UNIMPLEMENTED();
5036 break;
5037 }
5038}
5039
Carey Williams2809e6c2018-03-13 12:24:16 +00005040void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
5041 NEONFormatDecoder nfd(instr);
5042 SimVRegister& rd = ReadVRegister(instr->GetRd());
5043 SimVRegister& rn = ReadVRegister(instr->GetRn());
5044 SimVRegister& rm = ReadVRegister(instr->GetRm());
5045 int rot = 0;
5046 VectorFormat vf = nfd.GetVectorFormat();
Jacob Bramley364c82b2018-08-24 17:51:52 +01005047 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
5048 rot = instr->GetImmRotFcmlaVec();
5049 fcmla(vf, rd, rn, rm, rot);
5050 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
5051 rot = instr->GetImmRotFcadd();
5052 fcadd(vf, rd, rn, rm, rot);
Alexander Gilday43785642018-04-04 13:42:33 +01005053 } else {
5054 switch (instr->Mask(NEON3SameExtraMask)) {
Alexander Gilday560332d2018-04-05 13:25:17 +01005055 case NEON_SDOT:
5056 sdot(vf, rd, rn, rm);
5057 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005058 case NEON_SQRDMLAH:
5059 sqrdmlah(vf, rd, rn, rm);
5060 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005061 case NEON_UDOT:
5062 udot(vf, rd, rn, rm);
5063 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005064 case NEON_SQRDMLSH:
5065 sqrdmlsh(vf, rd, rn, rm);
5066 break;
5067 default:
5068 VIXL_UNIMPLEMENTED();
5069 break;
5070 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005071 }
5072}
5073
5074
Alexandre Ramesd3832962016-07-04 15:03:43 +01005075void Simulator::VisitNEON3Different(const Instruction* instr) {
5076 NEONFormatDecoder nfd(instr);
5077 VectorFormat vf = nfd.GetVectorFormat();
5078 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5079
5080 SimVRegister& rd = ReadVRegister(instr->GetRd());
5081 SimVRegister& rn = ReadVRegister(instr->GetRn());
5082 SimVRegister& rm = ReadVRegister(instr->GetRm());
5083
5084 switch (instr->Mask(NEON3DifferentMask)) {
5085 case NEON_PMULL:
5086 pmull(vf_l, rd, rn, rm);
5087 break;
5088 case NEON_PMULL2:
5089 pmull2(vf_l, rd, rn, rm);
5090 break;
5091 case NEON_UADDL:
5092 uaddl(vf_l, rd, rn, rm);
5093 break;
5094 case NEON_UADDL2:
5095 uaddl2(vf_l, rd, rn, rm);
5096 break;
5097 case NEON_SADDL:
5098 saddl(vf_l, rd, rn, rm);
5099 break;
5100 case NEON_SADDL2:
5101 saddl2(vf_l, rd, rn, rm);
5102 break;
5103 case NEON_USUBL:
5104 usubl(vf_l, rd, rn, rm);
5105 break;
5106 case NEON_USUBL2:
5107 usubl2(vf_l, rd, rn, rm);
5108 break;
5109 case NEON_SSUBL:
5110 ssubl(vf_l, rd, rn, rm);
5111 break;
5112 case NEON_SSUBL2:
5113 ssubl2(vf_l, rd, rn, rm);
5114 break;
5115 case NEON_SABAL:
5116 sabal(vf_l, rd, rn, rm);
5117 break;
5118 case NEON_SABAL2:
5119 sabal2(vf_l, rd, rn, rm);
5120 break;
5121 case NEON_UABAL:
5122 uabal(vf_l, rd, rn, rm);
5123 break;
5124 case NEON_UABAL2:
5125 uabal2(vf_l, rd, rn, rm);
5126 break;
5127 case NEON_SABDL:
5128 sabdl(vf_l, rd, rn, rm);
5129 break;
5130 case NEON_SABDL2:
5131 sabdl2(vf_l, rd, rn, rm);
5132 break;
5133 case NEON_UABDL:
5134 uabdl(vf_l, rd, rn, rm);
5135 break;
5136 case NEON_UABDL2:
5137 uabdl2(vf_l, rd, rn, rm);
5138 break;
5139 case NEON_SMLAL:
5140 smlal(vf_l, rd, rn, rm);
5141 break;
5142 case NEON_SMLAL2:
5143 smlal2(vf_l, rd, rn, rm);
5144 break;
5145 case NEON_UMLAL:
5146 umlal(vf_l, rd, rn, rm);
5147 break;
5148 case NEON_UMLAL2:
5149 umlal2(vf_l, rd, rn, rm);
5150 break;
5151 case NEON_SMLSL:
5152 smlsl(vf_l, rd, rn, rm);
5153 break;
5154 case NEON_SMLSL2:
5155 smlsl2(vf_l, rd, rn, rm);
5156 break;
5157 case NEON_UMLSL:
5158 umlsl(vf_l, rd, rn, rm);
5159 break;
5160 case NEON_UMLSL2:
5161 umlsl2(vf_l, rd, rn, rm);
5162 break;
5163 case NEON_SMULL:
5164 smull(vf_l, rd, rn, rm);
5165 break;
5166 case NEON_SMULL2:
5167 smull2(vf_l, rd, rn, rm);
5168 break;
5169 case NEON_UMULL:
5170 umull(vf_l, rd, rn, rm);
5171 break;
5172 case NEON_UMULL2:
5173 umull2(vf_l, rd, rn, rm);
5174 break;
5175 case NEON_SQDMLAL:
5176 sqdmlal(vf_l, rd, rn, rm);
5177 break;
5178 case NEON_SQDMLAL2:
5179 sqdmlal2(vf_l, rd, rn, rm);
5180 break;
5181 case NEON_SQDMLSL:
5182 sqdmlsl(vf_l, rd, rn, rm);
5183 break;
5184 case NEON_SQDMLSL2:
5185 sqdmlsl2(vf_l, rd, rn, rm);
5186 break;
5187 case NEON_SQDMULL:
5188 sqdmull(vf_l, rd, rn, rm);
5189 break;
5190 case NEON_SQDMULL2:
5191 sqdmull2(vf_l, rd, rn, rm);
5192 break;
5193 case NEON_UADDW:
5194 uaddw(vf_l, rd, rn, rm);
5195 break;
5196 case NEON_UADDW2:
5197 uaddw2(vf_l, rd, rn, rm);
5198 break;
5199 case NEON_SADDW:
5200 saddw(vf_l, rd, rn, rm);
5201 break;
5202 case NEON_SADDW2:
5203 saddw2(vf_l, rd, rn, rm);
5204 break;
5205 case NEON_USUBW:
5206 usubw(vf_l, rd, rn, rm);
5207 break;
5208 case NEON_USUBW2:
5209 usubw2(vf_l, rd, rn, rm);
5210 break;
5211 case NEON_SSUBW:
5212 ssubw(vf_l, rd, rn, rm);
5213 break;
5214 case NEON_SSUBW2:
5215 ssubw2(vf_l, rd, rn, rm);
5216 break;
5217 case NEON_ADDHN:
5218 addhn(vf, rd, rn, rm);
5219 break;
5220 case NEON_ADDHN2:
5221 addhn2(vf, rd, rn, rm);
5222 break;
5223 case NEON_RADDHN:
5224 raddhn(vf, rd, rn, rm);
5225 break;
5226 case NEON_RADDHN2:
5227 raddhn2(vf, rd, rn, rm);
5228 break;
5229 case NEON_SUBHN:
5230 subhn(vf, rd, rn, rm);
5231 break;
5232 case NEON_SUBHN2:
5233 subhn2(vf, rd, rn, rm);
5234 break;
5235 case NEON_RSUBHN:
5236 rsubhn(vf, rd, rn, rm);
5237 break;
5238 case NEON_RSUBHN2:
5239 rsubhn2(vf, rd, rn, rm);
5240 break;
5241 default:
5242 VIXL_UNIMPLEMENTED();
5243 }
5244}
5245
5246
5247void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5248 NEONFormatDecoder nfd(instr);
5249
Jacob Bramleyca789742018-09-13 14:25:46 +01005250 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5251
Alexandre Ramesd3832962016-07-04 15:03:43 +01005252 SimVRegister& rd = ReadVRegister(instr->GetRd());
5253 SimVRegister& rn = ReadVRegister(instr->GetRn());
5254
Jacob Bramleyca789742018-09-13 14:25:46 +01005255 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5256 VectorFormat vf = nfd.GetVectorFormat(&map_half);
5257 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5258 case NEON_FMAXV_H:
5259 fmaxv(vf, rd, rn);
5260 break;
5261 case NEON_FMINV_H:
5262 fminv(vf, rd, rn);
5263 break;
5264 case NEON_FMAXNMV_H:
5265 fmaxnmv(vf, rd, rn);
5266 break;
5267 case NEON_FMINNMV_H:
5268 fminnmv(vf, rd, rn);
5269 break;
5270 default:
5271 VIXL_UNIMPLEMENTED();
5272 }
5273 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5274 // The input operand's VectorFormat is passed for these instructions.
Alexandre Ramesd3832962016-07-04 15:03:43 +01005275 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5276
5277 switch (instr->Mask(NEONAcrossLanesFPMask)) {
5278 case NEON_FMAXV:
5279 fmaxv(vf, rd, rn);
5280 break;
5281 case NEON_FMINV:
5282 fminv(vf, rd, rn);
5283 break;
5284 case NEON_FMAXNMV:
5285 fmaxnmv(vf, rd, rn);
5286 break;
5287 case NEON_FMINNMV:
5288 fminnmv(vf, rd, rn);
5289 break;
5290 default:
5291 VIXL_UNIMPLEMENTED();
5292 }
5293 } else {
5294 VectorFormat vf = nfd.GetVectorFormat();
5295
5296 switch (instr->Mask(NEONAcrossLanesMask)) {
5297 case NEON_ADDV:
5298 addv(vf, rd, rn);
5299 break;
5300 case NEON_SMAXV:
5301 smaxv(vf, rd, rn);
5302 break;
5303 case NEON_SMINV:
5304 sminv(vf, rd, rn);
5305 break;
5306 case NEON_UMAXV:
5307 umaxv(vf, rd, rn);
5308 break;
5309 case NEON_UMINV:
5310 uminv(vf, rd, rn);
5311 break;
5312 case NEON_SADDLV:
5313 saddlv(vf, rd, rn);
5314 break;
5315 case NEON_UADDLV:
5316 uaddlv(vf, rd, rn);
5317 break;
5318 default:
5319 VIXL_UNIMPLEMENTED();
5320 }
5321 }
5322}
5323
5324
5325void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5326 NEONFormatDecoder nfd(instr);
Jacob Bramleyca789742018-09-13 14:25:46 +01005327 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01005328 VectorFormat vf_r = nfd.GetVectorFormat();
Jacob Bramleyca789742018-09-13 14:25:46 +01005329 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005330 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5331
5332 SimVRegister& rd = ReadVRegister(instr->GetRd());
5333 SimVRegister& rn = ReadVRegister(instr->GetRn());
5334
5335 ByElementOp Op = NULL;
5336
5337 int rm_reg = instr->GetRm();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005338 int rm_low_reg = instr->GetRmLow16();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005339 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005340 int index_hlm = (index << 1) | instr->GetNEONM();
5341
5342 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5343 // These are oddballs and are best handled as special cases.
5344 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5345 // - The index is always H:L:M.
5346 case NEON_FMLAL_H_byelement:
5347 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5348 return;
5349 case NEON_FMLAL2_H_byelement:
5350 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5351 return;
5352 case NEON_FMLSL_H_byelement:
5353 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5354 return;
5355 case NEON_FMLSL2_H_byelement:
5356 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5357 return;
5358 }
5359
Alexandre Ramesd3832962016-07-04 15:03:43 +01005360 if (instr->GetNEONSize() == 1) {
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005361 rm_reg = rm_low_reg;
5362 index = index_hlm;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005363 }
5364
5365 switch (instr->Mask(NEONByIndexedElementMask)) {
5366 case NEON_MUL_byelement:
5367 Op = &Simulator::mul;
5368 vf = vf_r;
5369 break;
5370 case NEON_MLA_byelement:
5371 Op = &Simulator::mla;
5372 vf = vf_r;
5373 break;
5374 case NEON_MLS_byelement:
5375 Op = &Simulator::mls;
5376 vf = vf_r;
5377 break;
5378 case NEON_SQDMULH_byelement:
5379 Op = &Simulator::sqdmulh;
5380 vf = vf_r;
5381 break;
5382 case NEON_SQRDMULH_byelement:
5383 Op = &Simulator::sqrdmulh;
5384 vf = vf_r;
5385 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005386 case NEON_SDOT_byelement:
5387 Op = &Simulator::sdot;
5388 vf = vf_r;
5389 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005390 case NEON_SQRDMLAH_byelement:
5391 Op = &Simulator::sqrdmlah;
5392 vf = vf_r;
5393 break;
Alexander Gilday560332d2018-04-05 13:25:17 +01005394 case NEON_UDOT_byelement:
5395 Op = &Simulator::udot;
5396 vf = vf_r;
5397 break;
Alexander Gilday43785642018-04-04 13:42:33 +01005398 case NEON_SQRDMLSH_byelement:
5399 Op = &Simulator::sqrdmlsh;
5400 vf = vf_r;
5401 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005402 case NEON_SMULL_byelement:
5403 if (instr->Mask(NEON_Q)) {
5404 Op = &Simulator::smull2;
5405 } else {
5406 Op = &Simulator::smull;
5407 }
5408 break;
5409 case NEON_UMULL_byelement:
5410 if (instr->Mask(NEON_Q)) {
5411 Op = &Simulator::umull2;
5412 } else {
5413 Op = &Simulator::umull;
5414 }
5415 break;
5416 case NEON_SMLAL_byelement:
5417 if (instr->Mask(NEON_Q)) {
5418 Op = &Simulator::smlal2;
5419 } else {
5420 Op = &Simulator::smlal;
5421 }
5422 break;
5423 case NEON_UMLAL_byelement:
5424 if (instr->Mask(NEON_Q)) {
5425 Op = &Simulator::umlal2;
5426 } else {
5427 Op = &Simulator::umlal;
5428 }
5429 break;
5430 case NEON_SMLSL_byelement:
5431 if (instr->Mask(NEON_Q)) {
5432 Op = &Simulator::smlsl2;
5433 } else {
5434 Op = &Simulator::smlsl;
5435 }
5436 break;
5437 case NEON_UMLSL_byelement:
5438 if (instr->Mask(NEON_Q)) {
5439 Op = &Simulator::umlsl2;
5440 } else {
5441 Op = &Simulator::umlsl;
5442 }
5443 break;
5444 case NEON_SQDMULL_byelement:
5445 if (instr->Mask(NEON_Q)) {
5446 Op = &Simulator::sqdmull2;
5447 } else {
5448 Op = &Simulator::sqdmull;
5449 }
5450 break;
5451 case NEON_SQDMLAL_byelement:
5452 if (instr->Mask(NEON_Q)) {
5453 Op = &Simulator::sqdmlal2;
5454 } else {
5455 Op = &Simulator::sqdmlal;
5456 }
5457 break;
5458 case NEON_SQDMLSL_byelement:
5459 if (instr->Mask(NEON_Q)) {
5460 Op = &Simulator::sqdmlsl2;
5461 } else {
5462 Op = &Simulator::sqdmlsl;
5463 }
5464 break;
5465 default:
5466 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01005467 if (instr->GetFPType() == 0) {
5468 rm_reg &= 0xf;
5469 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5470 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005471 index = (index << 1) | instr->GetNEONL();
5472 }
5473
5474 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5475
5476 switch (instr->Mask(NEONByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01005477 case NEON_FMUL_H_byelement:
5478 vf = vf_half;
5479 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005480 case NEON_FMUL_byelement:
5481 Op = &Simulator::fmul;
5482 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005483 case NEON_FMLA_H_byelement:
5484 vf = vf_half;
5485 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005486 case NEON_FMLA_byelement:
5487 Op = &Simulator::fmla;
5488 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005489 case NEON_FMLS_H_byelement:
5490 vf = vf_half;
5491 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005492 case NEON_FMLS_byelement:
5493 Op = &Simulator::fmls;
5494 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01005495 case NEON_FMULX_H_byelement:
5496 vf = vf_half;
5497 VIXL_FALLTHROUGH();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005498 case NEON_FMULX_byelement:
5499 Op = &Simulator::fmulx;
5500 break;
5501 default:
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005502 if (instr->GetNEONSize() == 2) {
Carey Williams2809e6c2018-03-13 12:24:16 +00005503 index = instr->GetNEONH();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005504 } else {
Carey Williams2809e6c2018-03-13 12:24:16 +00005505 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
Jacob Bramley8f36e7f2018-08-23 17:45:37 +01005506 }
Carey Williams2809e6c2018-03-13 12:24:16 +00005507 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5508 case NEON_FCMLA_byelement:
5509 vf = vf_r;
5510 fcmla(vf,
5511 rd,
5512 rn,
5513 ReadVRegister(instr->GetRm()),
5514 index,
5515 instr->GetImmRotFcmlaSca());
5516 return;
5517 default:
5518 VIXL_UNIMPLEMENTED();
5519 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01005520 }
5521 }
5522
5523 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5524}
5525
5526
5527void Simulator::VisitNEONCopy(const Instruction* instr) {
5528 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5529 VectorFormat vf = nfd.GetVectorFormat();
5530
5531 SimVRegister& rd = ReadVRegister(instr->GetRd());
5532 SimVRegister& rn = ReadVRegister(instr->GetRn());
5533 int imm5 = instr->GetImmNEON5();
5534 int tz = CountTrailingZeros(imm5, 32);
5535 int reg_index = imm5 >> (tz + 1);
5536
5537 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5538 int imm4 = instr->GetImmNEON4();
5539 int rn_index = imm4 >> tz;
5540 ins_element(vf, rd, reg_index, rn, rn_index);
5541 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5542 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5543 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5544 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5545 value &= MaxUintFromFormat(vf);
5546 WriteXRegister(instr->GetRd(), value);
5547 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5548 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5549 if (instr->GetNEONQ()) {
5550 WriteXRegister(instr->GetRd(), value);
5551 } else {
5552 WriteWRegister(instr->GetRd(), (int32_t)value);
5553 }
5554 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5555 dup_element(vf, rd, rn, reg_index);
5556 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5557 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5558 } else {
5559 VIXL_UNIMPLEMENTED();
5560 }
5561}
5562
5563
5564void Simulator::VisitNEONExtract(const Instruction* instr) {
5565 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5566 VectorFormat vf = nfd.GetVectorFormat();
5567 SimVRegister& rd = ReadVRegister(instr->GetRd());
5568 SimVRegister& rn = ReadVRegister(instr->GetRn());
5569 SimVRegister& rm = ReadVRegister(instr->GetRm());
5570 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5571 int index = instr->GetImmNEONExt();
5572 ext(vf, rd, rn, rm, index);
5573 } else {
5574 VIXL_UNIMPLEMENTED();
5575 }
5576}
5577
5578
5579void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5580 AddrMode addr_mode) {
5581 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5582 VectorFormat vf = nfd.GetVectorFormat();
5583
5584 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5585 int reg_size = RegisterSizeInBytesFromFormat(vf);
5586
5587 int reg[4];
5588 uint64_t addr[4];
5589 for (int i = 0; i < 4; i++) {
5590 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5591 addr[i] = addr_base + (i * reg_size);
5592 }
5593 int count = 1;
5594 bool log_read = true;
5595
Martyn Capewell32009e32016-10-27 11:00:37 +01005596 // Bit 23 determines whether this is an offset or post-index addressing mode.
5597 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5598 // register or immediate in post-index mode.
5599 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005600 VIXL_UNREACHABLE();
5601 }
5602
5603 // We use the PostIndex mask here, as it works in this case for both Offset
5604 // and PostIndex addressing.
5605 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5606 case NEON_LD1_4v:
5607 case NEON_LD1_4v_post:
5608 ld1(vf, ReadVRegister(reg[3]), addr[3]);
5609 count++;
5610 VIXL_FALLTHROUGH();
5611 case NEON_LD1_3v:
5612 case NEON_LD1_3v_post:
5613 ld1(vf, ReadVRegister(reg[2]), addr[2]);
5614 count++;
5615 VIXL_FALLTHROUGH();
5616 case NEON_LD1_2v:
5617 case NEON_LD1_2v_post:
5618 ld1(vf, ReadVRegister(reg[1]), addr[1]);
5619 count++;
5620 VIXL_FALLTHROUGH();
5621 case NEON_LD1_1v:
5622 case NEON_LD1_1v_post:
5623 ld1(vf, ReadVRegister(reg[0]), addr[0]);
5624 break;
5625 case NEON_ST1_4v:
5626 case NEON_ST1_4v_post:
5627 st1(vf, ReadVRegister(reg[3]), addr[3]);
5628 count++;
5629 VIXL_FALLTHROUGH();
5630 case NEON_ST1_3v:
5631 case NEON_ST1_3v_post:
5632 st1(vf, ReadVRegister(reg[2]), addr[2]);
5633 count++;
5634 VIXL_FALLTHROUGH();
5635 case NEON_ST1_2v:
5636 case NEON_ST1_2v_post:
5637 st1(vf, ReadVRegister(reg[1]), addr[1]);
5638 count++;
5639 VIXL_FALLTHROUGH();
5640 case NEON_ST1_1v:
5641 case NEON_ST1_1v_post:
5642 st1(vf, ReadVRegister(reg[0]), addr[0]);
5643 log_read = false;
5644 break;
5645 case NEON_LD2_post:
5646 case NEON_LD2:
5647 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5648 count = 2;
5649 break;
5650 case NEON_ST2:
5651 case NEON_ST2_post:
5652 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5653 count = 2;
Jacob Bramley3728a462016-10-26 16:04:44 +01005654 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005655 break;
5656 case NEON_LD3_post:
5657 case NEON_LD3:
5658 ld3(vf,
5659 ReadVRegister(reg[0]),
5660 ReadVRegister(reg[1]),
5661 ReadVRegister(reg[2]),
5662 addr[0]);
5663 count = 3;
5664 break;
5665 case NEON_ST3:
5666 case NEON_ST3_post:
5667 st3(vf,
5668 ReadVRegister(reg[0]),
5669 ReadVRegister(reg[1]),
5670 ReadVRegister(reg[2]),
5671 addr[0]);
5672 count = 3;
Jacob Bramley3728a462016-10-26 16:04:44 +01005673 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005674 break;
5675 case NEON_ST4:
5676 case NEON_ST4_post:
5677 st4(vf,
5678 ReadVRegister(reg[0]),
5679 ReadVRegister(reg[1]),
5680 ReadVRegister(reg[2]),
5681 ReadVRegister(reg[3]),
5682 addr[0]);
5683 count = 4;
Jacob Bramley3728a462016-10-26 16:04:44 +01005684 log_read = false;
Alexandre Ramesd3832962016-07-04 15:03:43 +01005685 break;
5686 case NEON_LD4_post:
5687 case NEON_LD4:
5688 ld4(vf,
5689 ReadVRegister(reg[0]),
5690 ReadVRegister(reg[1]),
5691 ReadVRegister(reg[2]),
5692 ReadVRegister(reg[3]),
5693 addr[0]);
5694 count = 4;
5695 break;
5696 default:
5697 VIXL_UNIMPLEMENTED();
5698 }
5699
5700 // Explicitly log the register update whilst we have type information.
5701 for (int i = 0; i < count; i++) {
5702 // For de-interleaving loads, only print the base address.
5703 int lane_size = LaneSizeInBytesFromFormat(vf);
5704 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
5705 GetPrintRegisterFormatForSize(reg_size, lane_size));
5706 if (log_read) {
5707 LogVRead(addr_base, reg[i], format);
5708 } else {
5709 LogVWrite(addr_base, reg[i], format);
5710 }
5711 }
5712
5713 if (addr_mode == PostIndex) {
5714 int rm = instr->GetRm();
5715 // The immediate post index addressing mode is indicated by rm = 31.
5716 // The immediate is implied by the number of vector registers used.
5717 addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
5718 : ReadXRegister(rm);
5719 WriteXRegister(instr->GetRn(), addr_base);
5720 } else {
5721 VIXL_ASSERT(addr_mode == Offset);
5722 }
5723}
5724
5725
5726void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
5727 NEONLoadStoreMultiStructHelper(instr, Offset);
5728}
5729
5730
5731void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
5732 const Instruction* instr) {
5733 NEONLoadStoreMultiStructHelper(instr, PostIndex);
5734}
5735
5736
5737void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
5738 AddrMode addr_mode) {
5739 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5740 int rt = instr->GetRt();
5741
Martyn Capewell32009e32016-10-27 11:00:37 +01005742 // Bit 23 determines whether this is an offset or post-index addressing mode.
5743 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5744 // register or immediate in post-index mode.
5745 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005746 VIXL_UNREACHABLE();
5747 }
5748
5749 // We use the PostIndex mask here, as it works in this case for both Offset
5750 // and PostIndex addressing.
5751 bool do_load = false;
5752
5753 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5754 VectorFormat vf_t = nfd.GetVectorFormat();
5755
5756 VectorFormat vf = kFormat16B;
5757 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
5758 case NEON_LD1_b:
5759 case NEON_LD1_b_post:
5760 case NEON_LD2_b:
5761 case NEON_LD2_b_post:
5762 case NEON_LD3_b:
5763 case NEON_LD3_b_post:
5764 case NEON_LD4_b:
5765 case NEON_LD4_b_post:
5766 do_load = true;
5767 VIXL_FALLTHROUGH();
5768 case NEON_ST1_b:
5769 case NEON_ST1_b_post:
5770 case NEON_ST2_b:
5771 case NEON_ST2_b_post:
5772 case NEON_ST3_b:
5773 case NEON_ST3_b_post:
5774 case NEON_ST4_b:
5775 case NEON_ST4_b_post:
5776 break;
5777
5778 case NEON_LD1_h:
5779 case NEON_LD1_h_post:
5780 case NEON_LD2_h:
5781 case NEON_LD2_h_post:
5782 case NEON_LD3_h:
5783 case NEON_LD3_h_post:
5784 case NEON_LD4_h:
5785 case NEON_LD4_h_post:
5786 do_load = true;
5787 VIXL_FALLTHROUGH();
5788 case NEON_ST1_h:
5789 case NEON_ST1_h_post:
5790 case NEON_ST2_h:
5791 case NEON_ST2_h_post:
5792 case NEON_ST3_h:
5793 case NEON_ST3_h_post:
5794 case NEON_ST4_h:
5795 case NEON_ST4_h_post:
5796 vf = kFormat8H;
5797 break;
5798 case NEON_LD1_s:
5799 case NEON_LD1_s_post:
5800 case NEON_LD2_s:
5801 case NEON_LD2_s_post:
5802 case NEON_LD3_s:
5803 case NEON_LD3_s_post:
5804 case NEON_LD4_s:
5805 case NEON_LD4_s_post:
5806 do_load = true;
5807 VIXL_FALLTHROUGH();
5808 case NEON_ST1_s:
5809 case NEON_ST1_s_post:
5810 case NEON_ST2_s:
5811 case NEON_ST2_s_post:
5812 case NEON_ST3_s:
5813 case NEON_ST3_s_post:
5814 case NEON_ST4_s:
5815 case NEON_ST4_s_post: {
5816 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
5817 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
5818 NEON_LD1_d_post);
5819 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
5820 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
5821 NEON_ST1_d_post);
5822 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
5823 break;
5824 }
5825
5826 case NEON_LD1R:
5827 case NEON_LD1R_post: {
5828 vf = vf_t;
5829 ld1r(vf, ReadVRegister(rt), addr);
5830 do_load = true;
5831 break;
5832 }
5833
5834 case NEON_LD2R:
5835 case NEON_LD2R_post: {
5836 vf = vf_t;
5837 int rt2 = (rt + 1) % kNumberOfVRegisters;
5838 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
5839 do_load = true;
5840 break;
5841 }
5842
5843 case NEON_LD3R:
5844 case NEON_LD3R_post: {
5845 vf = vf_t;
5846 int rt2 = (rt + 1) % kNumberOfVRegisters;
5847 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5848 ld3r(vf, ReadVRegister(rt), ReadVRegister(rt2), ReadVRegister(rt3), addr);
5849 do_load = true;
5850 break;
5851 }
5852
5853 case NEON_LD4R:
5854 case NEON_LD4R_post: {
5855 vf = vf_t;
5856 int rt2 = (rt + 1) % kNumberOfVRegisters;
5857 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5858 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5859 ld4r(vf,
5860 ReadVRegister(rt),
5861 ReadVRegister(rt2),
5862 ReadVRegister(rt3),
5863 ReadVRegister(rt4),
5864 addr);
5865 do_load = true;
5866 break;
5867 }
5868 default:
5869 VIXL_UNIMPLEMENTED();
5870 }
5871
5872 PrintRegisterFormat print_format =
5873 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
5874 // Make sure that the print_format only includes a single lane.
5875 print_format =
5876 static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
5877
5878 int esize = LaneSizeInBytesFromFormat(vf);
5879 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
5880 int lane = instr->GetNEONLSIndex(index_shift);
5881 int scale = 0;
5882 int rt2 = (rt + 1) % kNumberOfVRegisters;
5883 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
5884 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
5885 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
5886 case NEONLoadStoreSingle1:
5887 scale = 1;
5888 if (do_load) {
5889 ld1(vf, ReadVRegister(rt), lane, addr);
5890 LogVRead(addr, rt, print_format, lane);
5891 } else {
5892 st1(vf, ReadVRegister(rt), lane, addr);
5893 LogVWrite(addr, rt, print_format, lane);
5894 }
5895 break;
5896 case NEONLoadStoreSingle2:
5897 scale = 2;
5898 if (do_load) {
5899 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
5900 LogVRead(addr, rt, print_format, lane);
5901 LogVRead(addr + esize, rt2, print_format, lane);
5902 } else {
5903 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
5904 LogVWrite(addr, rt, print_format, lane);
5905 LogVWrite(addr + esize, rt2, print_format, lane);
5906 }
5907 break;
5908 case NEONLoadStoreSingle3:
5909 scale = 3;
5910 if (do_load) {
5911 ld3(vf,
5912 ReadVRegister(rt),
5913 ReadVRegister(rt2),
5914 ReadVRegister(rt3),
5915 lane,
5916 addr);
5917 LogVRead(addr, rt, print_format, lane);
5918 LogVRead(addr + esize, rt2, print_format, lane);
5919 LogVRead(addr + (2 * esize), rt3, print_format, lane);
5920 } else {
5921 st3(vf,
5922 ReadVRegister(rt),
5923 ReadVRegister(rt2),
5924 ReadVRegister(rt3),
5925 lane,
5926 addr);
5927 LogVWrite(addr, rt, print_format, lane);
5928 LogVWrite(addr + esize, rt2, print_format, lane);
5929 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
5930 }
5931 break;
5932 case NEONLoadStoreSingle4:
5933 scale = 4;
5934 if (do_load) {
5935 ld4(vf,
5936 ReadVRegister(rt),
5937 ReadVRegister(rt2),
5938 ReadVRegister(rt3),
5939 ReadVRegister(rt4),
5940 lane,
5941 addr);
5942 LogVRead(addr, rt, print_format, lane);
5943 LogVRead(addr + esize, rt2, print_format, lane);
5944 LogVRead(addr + (2 * esize), rt3, print_format, lane);
5945 LogVRead(addr + (3 * esize), rt4, print_format, lane);
5946 } else {
5947 st4(vf,
5948 ReadVRegister(rt),
5949 ReadVRegister(rt2),
5950 ReadVRegister(rt3),
5951 ReadVRegister(rt4),
5952 lane,
5953 addr);
5954 LogVWrite(addr, rt, print_format, lane);
5955 LogVWrite(addr + esize, rt2, print_format, lane);
5956 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
5957 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
5958 }
5959 break;
5960 default:
5961 VIXL_UNIMPLEMENTED();
5962 }
5963
5964 if (addr_mode == PostIndex) {
5965 int rm = instr->GetRm();
5966 int lane_size = LaneSizeInBytesFromFormat(vf);
5967 WriteXRegister(instr->GetRn(),
5968 addr +
5969 ((rm == 31) ? (scale * lane_size) : ReadXRegister(rm)));
5970 }
5971}
5972
5973
5974void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
5975 NEONLoadStoreSingleStructHelper(instr, Offset);
5976}
5977
5978
5979void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
5980 const Instruction* instr) {
5981 NEONLoadStoreSingleStructHelper(instr, PostIndex);
5982}
5983
5984
5985void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
5986 SimVRegister& rd = ReadVRegister(instr->GetRd());
5987 int cmode = instr->GetNEONCmode();
5988 int cmode_3_1 = (cmode >> 1) & 7;
5989 int cmode_3 = (cmode >> 3) & 1;
5990 int cmode_2 = (cmode >> 2) & 1;
5991 int cmode_1 = (cmode >> 1) & 1;
5992 int cmode_0 = cmode & 1;
Carey Williamsd8bb3572018-04-10 11:58:07 +01005993 int half_enc = instr->ExtractBit(11);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005994 int q = instr->GetNEONQ();
5995 int op_bit = instr->GetNEONModImmOp();
5996 uint64_t imm8 = instr->GetImmNEONabcdefgh();
Alexandre Ramesd3832962016-07-04 15:03:43 +01005997 // Find the format and immediate value
5998 uint64_t imm = 0;
5999 VectorFormat vform = kFormatUndefined;
6000 switch (cmode_3_1) {
6001 case 0x0:
6002 case 0x1:
6003 case 0x2:
6004 case 0x3:
6005 vform = (q == 1) ? kFormat4S : kFormat2S;
6006 imm = imm8 << (8 * cmode_3_1);
6007 break;
6008 case 0x4:
6009 case 0x5:
6010 vform = (q == 1) ? kFormat8H : kFormat4H;
6011 imm = imm8 << (8 * cmode_1);
6012 break;
6013 case 0x6:
6014 vform = (q == 1) ? kFormat4S : kFormat2S;
6015 if (cmode_0 == 0) {
6016 imm = imm8 << 8 | 0x000000ff;
6017 } else {
6018 imm = imm8 << 16 | 0x0000ffff;
6019 }
6020 break;
6021 case 0x7:
6022 if (cmode_0 == 0 && op_bit == 0) {
6023 vform = q ? kFormat16B : kFormat8B;
6024 imm = imm8;
6025 } else if (cmode_0 == 0 && op_bit == 1) {
6026 vform = q ? kFormat2D : kFormat1D;
6027 imm = 0;
6028 for (int i = 0; i < 8; ++i) {
6029 if (imm8 & (1 << i)) {
6030 imm |= (UINT64_C(0xff) << (8 * i));
6031 }
6032 }
6033 } else { // cmode_0 == 1, cmode == 0xf.
Carey Williamsd8bb3572018-04-10 11:58:07 +01006034 if (half_enc == 1) {
6035 vform = q ? kFormat8H : kFormat4H;
Jacob Bramleyca789742018-09-13 14:25:46 +01006036 imm = Float16ToRawbits(instr->GetImmNEONFP16());
Carey Williamsd8bb3572018-04-10 11:58:07 +01006037 } else if (op_bit == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006038 vform = q ? kFormat4S : kFormat2S;
6039 imm = FloatToRawbits(instr->GetImmNEONFP32());
6040 } else if (q == 1) {
6041 vform = kFormat2D;
6042 imm = DoubleToRawbits(instr->GetImmNEONFP64());
6043 } else {
6044 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
6045 VisitUnallocated(instr);
6046 }
6047 }
6048 break;
6049 default:
6050 VIXL_UNREACHABLE();
6051 break;
6052 }
6053
6054 // Find the operation
6055 NEONModifiedImmediateOp op;
6056 if (cmode_3 == 0) {
6057 if (cmode_0 == 0) {
6058 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6059 } else { // cmode<0> == '1'
6060 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6061 }
6062 } else { // cmode<3> == '1'
6063 if (cmode_2 == 0) {
6064 if (cmode_0 == 0) {
6065 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6066 } else { // cmode<0> == '1'
6067 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6068 }
6069 } else { // cmode<2> == '1'
6070 if (cmode_1 == 0) {
6071 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6072 } else { // cmode<1> == '1'
6073 if (cmode_0 == 0) {
6074 op = NEONModifiedImmediate_MOVI;
6075 } else { // cmode<0> == '1'
6076 op = NEONModifiedImmediate_MOVI;
6077 }
6078 }
6079 }
6080 }
6081
6082 // Call the logic function
6083 if (op == NEONModifiedImmediate_ORR) {
6084 orr(vform, rd, rd, imm);
6085 } else if (op == NEONModifiedImmediate_BIC) {
6086 bic(vform, rd, rd, imm);
6087 } else if (op == NEONModifiedImmediate_MOVI) {
6088 movi(vform, rd, imm);
6089 } else if (op == NEONModifiedImmediate_MVNI) {
6090 mvni(vform, rd, imm);
6091 } else {
6092 VisitUnimplemented(instr);
6093 }
6094}
6095
6096
6097void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
6098 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6099 VectorFormat vf = nfd.GetVectorFormat();
6100
6101 SimVRegister& rd = ReadVRegister(instr->GetRd());
6102 SimVRegister& rn = ReadVRegister(instr->GetRn());
6103
6104 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
6105 // These instructions all use a two bit size field, except NOT and RBIT,
6106 // which use the field to encode the operation.
6107 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6108 case NEON_CMEQ_zero_scalar:
6109 cmp(vf, rd, rn, 0, eq);
6110 break;
6111 case NEON_CMGE_zero_scalar:
6112 cmp(vf, rd, rn, 0, ge);
6113 break;
6114 case NEON_CMGT_zero_scalar:
6115 cmp(vf, rd, rn, 0, gt);
6116 break;
6117 case NEON_CMLT_zero_scalar:
6118 cmp(vf, rd, rn, 0, lt);
6119 break;
6120 case NEON_CMLE_zero_scalar:
6121 cmp(vf, rd, rn, 0, le);
6122 break;
6123 case NEON_ABS_scalar:
6124 abs(vf, rd, rn);
6125 break;
6126 case NEON_SQABS_scalar:
6127 abs(vf, rd, rn).SignedSaturate(vf);
6128 break;
6129 case NEON_NEG_scalar:
6130 neg(vf, rd, rn);
6131 break;
6132 case NEON_SQNEG_scalar:
6133 neg(vf, rd, rn).SignedSaturate(vf);
6134 break;
6135 case NEON_SUQADD_scalar:
6136 suqadd(vf, rd, rn);
6137 break;
6138 case NEON_USQADD_scalar:
6139 usqadd(vf, rd, rn);
6140 break;
6141 default:
6142 VIXL_UNIMPLEMENTED();
6143 break;
6144 }
6145 } else {
6146 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6147 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6148
6149 // These instructions all use a one bit size field, except SQXTUN, SQXTN
6150 // and UQXTN, which use a two bit size field.
6151 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
6152 case NEON_FRECPE_scalar:
6153 frecpe(fpf, rd, rn, fpcr_rounding);
6154 break;
6155 case NEON_FRECPX_scalar:
6156 frecpx(fpf, rd, rn);
6157 break;
6158 case NEON_FRSQRTE_scalar:
6159 frsqrte(fpf, rd, rn);
6160 break;
6161 case NEON_FCMGT_zero_scalar:
6162 fcmp_zero(fpf, rd, rn, gt);
6163 break;
6164 case NEON_FCMGE_zero_scalar:
6165 fcmp_zero(fpf, rd, rn, ge);
6166 break;
6167 case NEON_FCMEQ_zero_scalar:
6168 fcmp_zero(fpf, rd, rn, eq);
6169 break;
6170 case NEON_FCMLE_zero_scalar:
6171 fcmp_zero(fpf, rd, rn, le);
6172 break;
6173 case NEON_FCMLT_zero_scalar:
6174 fcmp_zero(fpf, rd, rn, lt);
6175 break;
6176 case NEON_SCVTF_scalar:
6177 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6178 break;
6179 case NEON_UCVTF_scalar:
6180 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6181 break;
6182 case NEON_FCVTNS_scalar:
6183 fcvts(fpf, rd, rn, FPTieEven);
6184 break;
6185 case NEON_FCVTNU_scalar:
6186 fcvtu(fpf, rd, rn, FPTieEven);
6187 break;
6188 case NEON_FCVTPS_scalar:
6189 fcvts(fpf, rd, rn, FPPositiveInfinity);
6190 break;
6191 case NEON_FCVTPU_scalar:
6192 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6193 break;
6194 case NEON_FCVTMS_scalar:
6195 fcvts(fpf, rd, rn, FPNegativeInfinity);
6196 break;
6197 case NEON_FCVTMU_scalar:
6198 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6199 break;
6200 case NEON_FCVTZS_scalar:
6201 fcvts(fpf, rd, rn, FPZero);
6202 break;
6203 case NEON_FCVTZU_scalar:
6204 fcvtu(fpf, rd, rn, FPZero);
6205 break;
6206 case NEON_FCVTAS_scalar:
6207 fcvts(fpf, rd, rn, FPTieAway);
6208 break;
6209 case NEON_FCVTAU_scalar:
6210 fcvtu(fpf, rd, rn, FPTieAway);
6211 break;
6212 case NEON_FCVTXN_scalar:
6213 // Unlike all of the other FP instructions above, fcvtxn encodes dest
6214 // size S as size<0>=1. There's only one case, so we ignore the form.
6215 VIXL_ASSERT(instr->ExtractBit(22) == 1);
6216 fcvtxn(kFormatS, rd, rn);
6217 break;
6218 default:
6219 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6220 case NEON_SQXTN_scalar:
6221 sqxtn(vf, rd, rn);
6222 break;
6223 case NEON_UQXTN_scalar:
6224 uqxtn(vf, rd, rn);
6225 break;
6226 case NEON_SQXTUN_scalar:
6227 sqxtun(vf, rd, rn);
6228 break;
6229 default:
6230 VIXL_UNIMPLEMENTED();
6231 }
6232 }
6233 }
6234}
6235
6236
Jacob Bramleyca789742018-09-13 14:25:46 +01006237void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
6238 VectorFormat fpf = kFormatH;
6239 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6240
6241 SimVRegister& rd = ReadVRegister(instr->GetRd());
6242 SimVRegister& rn = ReadVRegister(instr->GetRn());
6243
6244 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6245 case NEON_FRECPE_H_scalar:
6246 frecpe(fpf, rd, rn, fpcr_rounding);
6247 break;
6248 case NEON_FRECPX_H_scalar:
6249 frecpx(fpf, rd, rn);
6250 break;
6251 case NEON_FRSQRTE_H_scalar:
6252 frsqrte(fpf, rd, rn);
6253 break;
6254 case NEON_FCMGT_H_zero_scalar:
6255 fcmp_zero(fpf, rd, rn, gt);
6256 break;
6257 case NEON_FCMGE_H_zero_scalar:
6258 fcmp_zero(fpf, rd, rn, ge);
6259 break;
6260 case NEON_FCMEQ_H_zero_scalar:
6261 fcmp_zero(fpf, rd, rn, eq);
6262 break;
6263 case NEON_FCMLE_H_zero_scalar:
6264 fcmp_zero(fpf, rd, rn, le);
6265 break;
6266 case NEON_FCMLT_H_zero_scalar:
6267 fcmp_zero(fpf, rd, rn, lt);
6268 break;
6269 case NEON_SCVTF_H_scalar:
6270 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6271 break;
6272 case NEON_UCVTF_H_scalar:
6273 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6274 break;
6275 case NEON_FCVTNS_H_scalar:
6276 fcvts(fpf, rd, rn, FPTieEven);
6277 break;
6278 case NEON_FCVTNU_H_scalar:
6279 fcvtu(fpf, rd, rn, FPTieEven);
6280 break;
6281 case NEON_FCVTPS_H_scalar:
6282 fcvts(fpf, rd, rn, FPPositiveInfinity);
6283 break;
6284 case NEON_FCVTPU_H_scalar:
6285 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6286 break;
6287 case NEON_FCVTMS_H_scalar:
6288 fcvts(fpf, rd, rn, FPNegativeInfinity);
6289 break;
6290 case NEON_FCVTMU_H_scalar:
6291 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6292 break;
6293 case NEON_FCVTZS_H_scalar:
6294 fcvts(fpf, rd, rn, FPZero);
6295 break;
6296 case NEON_FCVTZU_H_scalar:
6297 fcvtu(fpf, rd, rn, FPZero);
6298 break;
6299 case NEON_FCVTAS_H_scalar:
6300 fcvts(fpf, rd, rn, FPTieAway);
6301 break;
6302 case NEON_FCVTAU_H_scalar:
6303 fcvtu(fpf, rd, rn, FPTieAway);
6304 break;
6305 }
6306}
6307
6308
Alexandre Ramesd3832962016-07-04 15:03:43 +01006309void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6310 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6311 VectorFormat vf = nfd.GetVectorFormat();
6312
6313 SimVRegister& rd = ReadVRegister(instr->GetRd());
6314 SimVRegister& rn = ReadVRegister(instr->GetRn());
6315 SimVRegister& rm = ReadVRegister(instr->GetRm());
6316 switch (instr->Mask(NEONScalar3DiffMask)) {
6317 case NEON_SQDMLAL_scalar:
6318 sqdmlal(vf, rd, rn, rm);
6319 break;
6320 case NEON_SQDMLSL_scalar:
6321 sqdmlsl(vf, rd, rn, rm);
6322 break;
6323 case NEON_SQDMULL_scalar:
6324 sqdmull(vf, rd, rn, rm);
6325 break;
6326 default:
6327 VIXL_UNIMPLEMENTED();
6328 }
6329}
6330
6331
6332void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6333 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6334 VectorFormat vf = nfd.GetVectorFormat();
6335
6336 SimVRegister& rd = ReadVRegister(instr->GetRd());
6337 SimVRegister& rn = ReadVRegister(instr->GetRn());
6338 SimVRegister& rm = ReadVRegister(instr->GetRm());
6339
6340 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6341 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6342 switch (instr->Mask(NEONScalar3SameFPMask)) {
6343 case NEON_FMULX_scalar:
6344 fmulx(vf, rd, rn, rm);
6345 break;
6346 case NEON_FACGE_scalar:
6347 fabscmp(vf, rd, rn, rm, ge);
6348 break;
6349 case NEON_FACGT_scalar:
6350 fabscmp(vf, rd, rn, rm, gt);
6351 break;
6352 case NEON_FCMEQ_scalar:
6353 fcmp(vf, rd, rn, rm, eq);
6354 break;
6355 case NEON_FCMGE_scalar:
6356 fcmp(vf, rd, rn, rm, ge);
6357 break;
6358 case NEON_FCMGT_scalar:
6359 fcmp(vf, rd, rn, rm, gt);
6360 break;
6361 case NEON_FRECPS_scalar:
6362 frecps(vf, rd, rn, rm);
6363 break;
6364 case NEON_FRSQRTS_scalar:
6365 frsqrts(vf, rd, rn, rm);
6366 break;
6367 case NEON_FABD_scalar:
6368 fabd(vf, rd, rn, rm);
6369 break;
6370 default:
6371 VIXL_UNIMPLEMENTED();
6372 }
6373 } else {
6374 switch (instr->Mask(NEONScalar3SameMask)) {
6375 case NEON_ADD_scalar:
6376 add(vf, rd, rn, rm);
6377 break;
6378 case NEON_SUB_scalar:
6379 sub(vf, rd, rn, rm);
6380 break;
6381 case NEON_CMEQ_scalar:
6382 cmp(vf, rd, rn, rm, eq);
6383 break;
6384 case NEON_CMGE_scalar:
6385 cmp(vf, rd, rn, rm, ge);
6386 break;
6387 case NEON_CMGT_scalar:
6388 cmp(vf, rd, rn, rm, gt);
6389 break;
6390 case NEON_CMHI_scalar:
6391 cmp(vf, rd, rn, rm, hi);
6392 break;
6393 case NEON_CMHS_scalar:
6394 cmp(vf, rd, rn, rm, hs);
6395 break;
6396 case NEON_CMTST_scalar:
6397 cmptst(vf, rd, rn, rm);
6398 break;
6399 case NEON_USHL_scalar:
6400 ushl(vf, rd, rn, rm);
6401 break;
6402 case NEON_SSHL_scalar:
6403 sshl(vf, rd, rn, rm);
6404 break;
6405 case NEON_SQDMULH_scalar:
6406 sqdmulh(vf, rd, rn, rm);
6407 break;
6408 case NEON_SQRDMULH_scalar:
6409 sqrdmulh(vf, rd, rn, rm);
6410 break;
6411 case NEON_UQADD_scalar:
6412 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6413 break;
6414 case NEON_SQADD_scalar:
6415 add(vf, rd, rn, rm).SignedSaturate(vf);
6416 break;
6417 case NEON_UQSUB_scalar:
6418 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6419 break;
6420 case NEON_SQSUB_scalar:
6421 sub(vf, rd, rn, rm).SignedSaturate(vf);
6422 break;
6423 case NEON_UQSHL_scalar:
6424 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6425 break;
6426 case NEON_SQSHL_scalar:
6427 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6428 break;
6429 case NEON_URSHL_scalar:
6430 ushl(vf, rd, rn, rm).Round(vf);
6431 break;
6432 case NEON_SRSHL_scalar:
6433 sshl(vf, rd, rn, rm).Round(vf);
6434 break;
6435 case NEON_UQRSHL_scalar:
6436 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6437 break;
6438 case NEON_SQRSHL_scalar:
6439 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6440 break;
6441 default:
6442 VIXL_UNIMPLEMENTED();
6443 }
6444 }
6445}
6446
Jacob Bramleyca789742018-09-13 14:25:46 +01006447void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6448 SimVRegister& rd = ReadVRegister(instr->GetRd());
6449 SimVRegister& rn = ReadVRegister(instr->GetRn());
6450 SimVRegister& rm = ReadVRegister(instr->GetRm());
6451
6452 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6453 case NEON_FABD_H_scalar:
6454 fabd(kFormatH, rd, rn, rm);
6455 break;
6456 case NEON_FMULX_H_scalar:
6457 fmulx(kFormatH, rd, rn, rm);
6458 break;
6459 case NEON_FCMEQ_H_scalar:
6460 fcmp(kFormatH, rd, rn, rm, eq);
6461 break;
6462 case NEON_FCMGE_H_scalar:
6463 fcmp(kFormatH, rd, rn, rm, ge);
6464 break;
6465 case NEON_FCMGT_H_scalar:
6466 fcmp(kFormatH, rd, rn, rm, gt);
6467 break;
6468 case NEON_FACGE_H_scalar:
6469 fabscmp(kFormatH, rd, rn, rm, ge);
6470 break;
6471 case NEON_FACGT_H_scalar:
6472 fabscmp(kFormatH, rd, rn, rm, gt);
6473 break;
6474 case NEON_FRECPS_H_scalar:
6475 frecps(kFormatH, rd, rn, rm);
6476 break;
6477 case NEON_FRSQRTS_H_scalar:
6478 frsqrts(kFormatH, rd, rn, rm);
6479 break;
6480 default:
6481 VIXL_UNREACHABLE();
6482 }
6483}
6484
Alexandre Ramesd3832962016-07-04 15:03:43 +01006485
Alexander Gilday43785642018-04-04 13:42:33 +01006486void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6487 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6488 VectorFormat vf = nfd.GetVectorFormat();
6489
6490 SimVRegister& rd = ReadVRegister(instr->GetRd());
6491 SimVRegister& rn = ReadVRegister(instr->GetRn());
6492 SimVRegister& rm = ReadVRegister(instr->GetRm());
6493
6494 switch (instr->Mask(NEONScalar3SameExtraMask)) {
6495 case NEON_SQRDMLAH_scalar:
6496 sqrdmlah(vf, rd, rn, rm);
6497 break;
6498 case NEON_SQRDMLSH_scalar:
6499 sqrdmlsh(vf, rd, rn, rm);
6500 break;
6501 default:
6502 VIXL_UNIMPLEMENTED();
6503 }
6504}
6505
Alexandre Ramesd3832962016-07-04 15:03:43 +01006506void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6507 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6508 VectorFormat vf = nfd.GetVectorFormat();
6509 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6510
6511 SimVRegister& rd = ReadVRegister(instr->GetRd());
6512 SimVRegister& rn = ReadVRegister(instr->GetRn());
6513 ByElementOp Op = NULL;
6514
6515 int rm_reg = instr->GetRm();
6516 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6517 if (instr->GetNEONSize() == 1) {
6518 rm_reg &= 0xf;
6519 index = (index << 1) | instr->GetNEONM();
6520 }
6521
6522 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6523 case NEON_SQDMULL_byelement_scalar:
6524 Op = &Simulator::sqdmull;
6525 break;
6526 case NEON_SQDMLAL_byelement_scalar:
6527 Op = &Simulator::sqdmlal;
6528 break;
6529 case NEON_SQDMLSL_byelement_scalar:
6530 Op = &Simulator::sqdmlsl;
6531 break;
6532 case NEON_SQDMULH_byelement_scalar:
6533 Op = &Simulator::sqdmulh;
6534 vf = vf_r;
6535 break;
6536 case NEON_SQRDMULH_byelement_scalar:
6537 Op = &Simulator::sqrdmulh;
6538 vf = vf_r;
6539 break;
Alexander Gilday43785642018-04-04 13:42:33 +01006540 case NEON_SQRDMLAH_byelement_scalar:
6541 Op = &Simulator::sqrdmlah;
6542 vf = vf_r;
6543 break;
6544 case NEON_SQRDMLSH_byelement_scalar:
6545 Op = &Simulator::sqrdmlsh;
6546 vf = vf_r;
6547 break;
Alexandre Ramesd3832962016-07-04 15:03:43 +01006548 default:
6549 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6550 index = instr->GetNEONH();
Jacob Bramleyca789742018-09-13 14:25:46 +01006551 if (instr->GetFPType() == 0) {
6552 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6553 rm_reg &= 0xf;
6554 vf = kFormatH;
6555 } else if ((instr->GetFPType() & 1) == 0) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006556 index = (index << 1) | instr->GetNEONL();
6557 }
6558 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006559 case NEON_FMUL_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006560 case NEON_FMUL_byelement_scalar:
6561 Op = &Simulator::fmul;
6562 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006563 case NEON_FMLA_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006564 case NEON_FMLA_byelement_scalar:
6565 Op = &Simulator::fmla;
6566 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006567 case NEON_FMLS_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006568 case NEON_FMLS_byelement_scalar:
6569 Op = &Simulator::fmls;
6570 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006571 case NEON_FMULX_H_byelement_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006572 case NEON_FMULX_byelement_scalar:
6573 Op = &Simulator::fmulx;
6574 break;
6575 default:
6576 VIXL_UNIMPLEMENTED();
6577 }
6578 }
6579
6580 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6581}
6582
6583
6584void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6585 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6586 VectorFormat vf = nfd.GetVectorFormat();
6587
6588 SimVRegister& rd = ReadVRegister(instr->GetRd());
6589 SimVRegister& rn = ReadVRegister(instr->GetRn());
6590
6591 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6592 int imm5 = instr->GetImmNEON5();
6593 int tz = CountTrailingZeros(imm5, 32);
6594 int rn_index = imm5 >> (tz + 1);
6595 dup_element(vf, rd, rn, rn_index);
6596 } else {
6597 VIXL_UNIMPLEMENTED();
6598 }
6599}
6600
6601
6602void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006603 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006604 VectorFormat vf = nfd.GetVectorFormat();
6605
6606 SimVRegister& rd = ReadVRegister(instr->GetRd());
6607 SimVRegister& rn = ReadVRegister(instr->GetRn());
6608 switch (instr->Mask(NEONScalarPairwiseMask)) {
Jacob Bramleyca789742018-09-13 14:25:46 +01006609 case NEON_ADDP_scalar: {
6610 // All pairwise operations except ADDP use bit U to differentiate FP16
6611 // from FP32/FP64 variations.
6612 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6613 addp(nfd_addp.GetVectorFormat(), rd, rn);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006614 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006615 }
6616 case NEON_FADDP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006617 case NEON_FADDP_scalar:
6618 faddp(vf, rd, rn);
6619 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006620 case NEON_FMAXP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006621 case NEON_FMAXP_scalar:
6622 fmaxp(vf, rd, rn);
6623 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006624 case NEON_FMAXNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006625 case NEON_FMAXNMP_scalar:
6626 fmaxnmp(vf, rd, rn);
6627 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006628 case NEON_FMINP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006629 case NEON_FMINP_scalar:
6630 fminp(vf, rd, rn);
6631 break;
Jacob Bramleyca789742018-09-13 14:25:46 +01006632 case NEON_FMINNMP_h_scalar:
Alexandre Ramesd3832962016-07-04 15:03:43 +01006633 case NEON_FMINNMP_scalar:
6634 fminnmp(vf, rd, rn);
6635 break;
6636 default:
6637 VIXL_UNIMPLEMENTED();
6638 }
6639}
6640
6641
6642void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6643 SimVRegister& rd = ReadVRegister(instr->GetRd());
6644 SimVRegister& rn = ReadVRegister(instr->GetRn());
6645 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6646
6647 static const NEONFormatMap map = {{22, 21, 20, 19},
6648 {NF_UNDEF,
6649 NF_B,
6650 NF_H,
6651 NF_H,
6652 NF_S,
6653 NF_S,
6654 NF_S,
6655 NF_S,
6656 NF_D,
6657 NF_D,
6658 NF_D,
6659 NF_D,
6660 NF_D,
6661 NF_D,
6662 NF_D,
6663 NF_D}};
6664 NEONFormatDecoder nfd(instr, &map);
6665 VectorFormat vf = nfd.GetVectorFormat();
6666
6667 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
6668 int immhimmb = instr->GetImmNEONImmhImmb();
6669 int right_shift = (16 << highestSetBit) - immhimmb;
6670 int left_shift = immhimmb - (8 << highestSetBit);
6671 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
6672 case NEON_SHL_scalar:
6673 shl(vf, rd, rn, left_shift);
6674 break;
6675 case NEON_SLI_scalar:
6676 sli(vf, rd, rn, left_shift);
6677 break;
6678 case NEON_SQSHL_imm_scalar:
6679 sqshl(vf, rd, rn, left_shift);
6680 break;
6681 case NEON_UQSHL_imm_scalar:
6682 uqshl(vf, rd, rn, left_shift);
6683 break;
6684 case NEON_SQSHLU_scalar:
6685 sqshlu(vf, rd, rn, left_shift);
6686 break;
6687 case NEON_SRI_scalar:
6688 sri(vf, rd, rn, right_shift);
6689 break;
6690 case NEON_SSHR_scalar:
6691 sshr(vf, rd, rn, right_shift);
6692 break;
6693 case NEON_USHR_scalar:
6694 ushr(vf, rd, rn, right_shift);
6695 break;
6696 case NEON_SRSHR_scalar:
6697 sshr(vf, rd, rn, right_shift).Round(vf);
6698 break;
6699 case NEON_URSHR_scalar:
6700 ushr(vf, rd, rn, right_shift).Round(vf);
6701 break;
6702 case NEON_SSRA_scalar:
6703 ssra(vf, rd, rn, right_shift);
6704 break;
6705 case NEON_USRA_scalar:
6706 usra(vf, rd, rn, right_shift);
6707 break;
6708 case NEON_SRSRA_scalar:
6709 srsra(vf, rd, rn, right_shift);
6710 break;
6711 case NEON_URSRA_scalar:
6712 ursra(vf, rd, rn, right_shift);
6713 break;
6714 case NEON_UQSHRN_scalar:
6715 uqshrn(vf, rd, rn, right_shift);
6716 break;
6717 case NEON_UQRSHRN_scalar:
6718 uqrshrn(vf, rd, rn, right_shift);
6719 break;
6720 case NEON_SQSHRN_scalar:
6721 sqshrn(vf, rd, rn, right_shift);
6722 break;
6723 case NEON_SQRSHRN_scalar:
6724 sqrshrn(vf, rd, rn, right_shift);
6725 break;
6726 case NEON_SQSHRUN_scalar:
6727 sqshrun(vf, rd, rn, right_shift);
6728 break;
6729 case NEON_SQRSHRUN_scalar:
6730 sqrshrun(vf, rd, rn, right_shift);
6731 break;
6732 case NEON_FCVTZS_imm_scalar:
6733 fcvts(vf, rd, rn, FPZero, right_shift);
6734 break;
6735 case NEON_FCVTZU_imm_scalar:
6736 fcvtu(vf, rd, rn, FPZero, right_shift);
6737 break;
6738 case NEON_SCVTF_imm_scalar:
6739 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6740 break;
6741 case NEON_UCVTF_imm_scalar:
6742 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6743 break;
6744 default:
6745 VIXL_UNIMPLEMENTED();
6746 }
6747}
6748
6749
6750void Simulator::VisitNEONShiftImmediate(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 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
6756 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
6757 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
Pierre Langlois1bce0072017-06-06 17:58:58 +01006758 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
6759 NF_4H, NF_8H, NF_4H, NF_8H,
6760 NF_2S, NF_4S, NF_2S, NF_4S,
6761 NF_2S, NF_4S, NF_2S, NF_4S,
6762 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6763 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6764 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
6765 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
Alexandre Ramesd3832962016-07-04 15:03:43 +01006766 NEONFormatDecoder nfd(instr, &map);
6767 VectorFormat vf = nfd.GetVectorFormat();
6768
6769 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
6770 static const NEONFormatMap map_l =
6771 {{22, 21, 20, 19},
6772 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
6773 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
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
6780 switch (instr->Mask(NEONShiftImmediateMask)) {
6781 case NEON_SHL:
6782 shl(vf, rd, rn, left_shift);
6783 break;
6784 case NEON_SLI:
6785 sli(vf, rd, rn, left_shift);
6786 break;
6787 case NEON_SQSHLU:
6788 sqshlu(vf, rd, rn, left_shift);
6789 break;
6790 case NEON_SRI:
6791 sri(vf, rd, rn, right_shift);
6792 break;
6793 case NEON_SSHR:
6794 sshr(vf, rd, rn, right_shift);
6795 break;
6796 case NEON_USHR:
6797 ushr(vf, rd, rn, right_shift);
6798 break;
6799 case NEON_SRSHR:
6800 sshr(vf, rd, rn, right_shift).Round(vf);
6801 break;
6802 case NEON_URSHR:
6803 ushr(vf, rd, rn, right_shift).Round(vf);
6804 break;
6805 case NEON_SSRA:
6806 ssra(vf, rd, rn, right_shift);
6807 break;
6808 case NEON_USRA:
6809 usra(vf, rd, rn, right_shift);
6810 break;
6811 case NEON_SRSRA:
6812 srsra(vf, rd, rn, right_shift);
6813 break;
6814 case NEON_URSRA:
6815 ursra(vf, rd, rn, right_shift);
6816 break;
6817 case NEON_SQSHL_imm:
6818 sqshl(vf, rd, rn, left_shift);
6819 break;
6820 case NEON_UQSHL_imm:
6821 uqshl(vf, rd, rn, left_shift);
6822 break;
6823 case NEON_SCVTF_imm:
6824 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
6825 break;
6826 case NEON_UCVTF_imm:
6827 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
6828 break;
6829 case NEON_FCVTZS_imm:
6830 fcvts(vf, rd, rn, FPZero, right_shift);
6831 break;
6832 case NEON_FCVTZU_imm:
6833 fcvtu(vf, rd, rn, FPZero, right_shift);
6834 break;
6835 case NEON_SSHLL:
6836 vf = vf_l;
6837 if (instr->Mask(NEON_Q)) {
6838 sshll2(vf, rd, rn, left_shift);
6839 } else {
6840 sshll(vf, rd, rn, left_shift);
6841 }
6842 break;
6843 case NEON_USHLL:
6844 vf = vf_l;
6845 if (instr->Mask(NEON_Q)) {
6846 ushll2(vf, rd, rn, left_shift);
6847 } else {
6848 ushll(vf, rd, rn, left_shift);
6849 }
6850 break;
6851 case NEON_SHRN:
6852 if (instr->Mask(NEON_Q)) {
6853 shrn2(vf, rd, rn, right_shift);
6854 } else {
6855 shrn(vf, rd, rn, right_shift);
6856 }
6857 break;
6858 case NEON_RSHRN:
6859 if (instr->Mask(NEON_Q)) {
6860 rshrn2(vf, rd, rn, right_shift);
6861 } else {
6862 rshrn(vf, rd, rn, right_shift);
6863 }
6864 break;
6865 case NEON_UQSHRN:
6866 if (instr->Mask(NEON_Q)) {
6867 uqshrn2(vf, rd, rn, right_shift);
6868 } else {
6869 uqshrn(vf, rd, rn, right_shift);
6870 }
6871 break;
6872 case NEON_UQRSHRN:
6873 if (instr->Mask(NEON_Q)) {
6874 uqrshrn2(vf, rd, rn, right_shift);
6875 } else {
6876 uqrshrn(vf, rd, rn, right_shift);
6877 }
6878 break;
6879 case NEON_SQSHRN:
6880 if (instr->Mask(NEON_Q)) {
6881 sqshrn2(vf, rd, rn, right_shift);
6882 } else {
6883 sqshrn(vf, rd, rn, right_shift);
6884 }
6885 break;
6886 case NEON_SQRSHRN:
6887 if (instr->Mask(NEON_Q)) {
6888 sqrshrn2(vf, rd, rn, right_shift);
6889 } else {
6890 sqrshrn(vf, rd, rn, right_shift);
6891 }
6892 break;
6893 case NEON_SQSHRUN:
6894 if (instr->Mask(NEON_Q)) {
6895 sqshrun2(vf, rd, rn, right_shift);
6896 } else {
6897 sqshrun(vf, rd, rn, right_shift);
6898 }
6899 break;
6900 case NEON_SQRSHRUN:
6901 if (instr->Mask(NEON_Q)) {
6902 sqrshrun2(vf, rd, rn, right_shift);
6903 } else {
6904 sqrshrun(vf, rd, rn, right_shift);
6905 }
6906 break;
6907 default:
6908 VIXL_UNIMPLEMENTED();
6909 }
6910}
6911
6912
6913void Simulator::VisitNEONTable(const Instruction* instr) {
6914 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
6915 VectorFormat vf = nfd.GetVectorFormat();
6916
6917 SimVRegister& rd = ReadVRegister(instr->GetRd());
6918 SimVRegister& rn = ReadVRegister(instr->GetRn());
6919 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
6920 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
6921 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
6922 SimVRegister& rm = ReadVRegister(instr->GetRm());
6923
6924 switch (instr->Mask(NEONTableMask)) {
6925 case NEON_TBL_1v:
6926 tbl(vf, rd, rn, rm);
6927 break;
6928 case NEON_TBL_2v:
6929 tbl(vf, rd, rn, rn2, rm);
6930 break;
6931 case NEON_TBL_3v:
6932 tbl(vf, rd, rn, rn2, rn3, rm);
6933 break;
6934 case NEON_TBL_4v:
6935 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
6936 break;
6937 case NEON_TBX_1v:
6938 tbx(vf, rd, rn, rm);
6939 break;
6940 case NEON_TBX_2v:
6941 tbx(vf, rd, rn, rn2, rm);
6942 break;
6943 case NEON_TBX_3v:
6944 tbx(vf, rd, rn, rn2, rn3, rm);
6945 break;
6946 case NEON_TBX_4v:
6947 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
6948 break;
6949 default:
6950 VIXL_UNIMPLEMENTED();
6951 }
6952}
6953
6954
6955void Simulator::VisitNEONPerm(const Instruction* instr) {
6956 NEONFormatDecoder nfd(instr);
6957 VectorFormat vf = nfd.GetVectorFormat();
6958
6959 SimVRegister& rd = ReadVRegister(instr->GetRd());
6960 SimVRegister& rn = ReadVRegister(instr->GetRn());
6961 SimVRegister& rm = ReadVRegister(instr->GetRm());
6962
6963 switch (instr->Mask(NEONPermMask)) {
6964 case NEON_TRN1:
6965 trn1(vf, rd, rn, rm);
6966 break;
6967 case NEON_TRN2:
6968 trn2(vf, rd, rn, rm);
6969 break;
6970 case NEON_UZP1:
6971 uzp1(vf, rd, rn, rm);
6972 break;
6973 case NEON_UZP2:
6974 uzp2(vf, rd, rn, rm);
6975 break;
6976 case NEON_ZIP1:
6977 zip1(vf, rd, rn, rm);
6978 break;
6979 case NEON_ZIP2:
6980 zip2(vf, rd, rn, rm);
6981 break;
6982 default:
6983 VIXL_UNIMPLEMENTED();
6984 }
6985}
6986
Martyn Capewellb545d6c2018-11-08 18:14:23 +00006987void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
6988 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00006989 switch (instr->Mask(SVEAddressGenerationMask)) {
6990 case ADR_z_az_d_s32_scaled:
6991 VIXL_UNIMPLEMENTED();
6992 break;
6993 case ADR_z_az_d_u32_scaled:
6994 VIXL_UNIMPLEMENTED();
6995 break;
6996 case ADR_z_az_sd_same_scaled:
6997 VIXL_UNIMPLEMENTED();
6998 break;
6999 default:
7000 VIXL_UNIMPLEMENTED();
7001 break;
7002 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007003}
7004
7005void Simulator::VisitSVEBitwiseImm(const Instruction* instr) {
7006 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007007 switch (instr->Mask(SVEBitwiseImmMask)) {
7008 case AND_z_zi:
7009 VIXL_UNIMPLEMENTED();
7010 break;
7011 case DUPM_z_i:
7012 VIXL_UNIMPLEMENTED();
7013 break;
7014 case EOR_z_zi:
7015 VIXL_UNIMPLEMENTED();
7016 break;
7017 case ORR_z_zi:
7018 VIXL_UNIMPLEMENTED();
7019 break;
7020 default:
7021 VIXL_UNIMPLEMENTED();
7022 break;
7023 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007024}
7025
7026void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
7027 USE(instr);
TatWai Chongcfb94212019-05-16 13:30:09 -07007028 SimVRegister& zd = ReadVRegister(instr->GetRd());
7029 SimVRegister& zn = ReadVRegister(instr->GetRn());
7030 SimVRegister& zm = ReadVRegister(instr->GetRm());
7031 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
7032
7033 switch (op) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007034 case AND_z_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007035 case BIC_z_zz:
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007036 case EOR_z_zz:
TatWai Chongcfb94212019-05-16 13:30:09 -07007037 case ORR_z_zz:
7038 SVEBitwiseLogicalUnpredicatedHelper(
7039 static_cast<SVEBitwiseLogicalUnpredicatedOp>(op), zd, zn, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007040 break;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007041 default:
7042 VIXL_UNIMPLEMENTED();
7043 break;
7044 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007045}
7046
7047void Simulator::VisitSVEBitwiseShiftPredicated(const Instruction* instr) {
7048 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007049 switch (instr->Mask(SVEBitwiseShiftPredicatedMask)) {
7050 case ASRD_z_p_zi:
7051 VIXL_UNIMPLEMENTED();
7052 break;
7053 case ASRR_z_p_zz:
7054 VIXL_UNIMPLEMENTED();
7055 break;
7056 case ASR_z_p_zi:
7057 VIXL_UNIMPLEMENTED();
7058 break;
7059 case ASR_z_p_zw:
7060 VIXL_UNIMPLEMENTED();
7061 break;
7062 case ASR_z_p_zz:
7063 VIXL_UNIMPLEMENTED();
7064 break;
7065 case LSLR_z_p_zz:
7066 VIXL_UNIMPLEMENTED();
7067 break;
7068 case LSL_z_p_zi:
7069 VIXL_UNIMPLEMENTED();
7070 break;
7071 case LSL_z_p_zw:
7072 VIXL_UNIMPLEMENTED();
7073 break;
7074 case LSL_z_p_zz:
7075 VIXL_UNIMPLEMENTED();
7076 break;
7077 case LSRR_z_p_zz:
7078 VIXL_UNIMPLEMENTED();
7079 break;
7080 case LSR_z_p_zi:
7081 VIXL_UNIMPLEMENTED();
7082 break;
7083 case LSR_z_p_zw:
7084 VIXL_UNIMPLEMENTED();
7085 break;
7086 case LSR_z_p_zz:
7087 VIXL_UNIMPLEMENTED();
7088 break;
7089 default:
7090 VIXL_UNIMPLEMENTED();
7091 break;
7092 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007093}
7094
7095void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
7096 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007097 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7098 case ASR_z_zi:
7099 VIXL_UNIMPLEMENTED();
7100 break;
7101 case ASR_z_zw:
7102 VIXL_UNIMPLEMENTED();
7103 break;
7104 case LSL_z_zi:
7105 VIXL_UNIMPLEMENTED();
7106 break;
7107 case LSL_z_zw:
7108 VIXL_UNIMPLEMENTED();
7109 break;
7110 case LSR_z_zi:
7111 VIXL_UNIMPLEMENTED();
7112 break;
7113 case LSR_z_zw:
7114 VIXL_UNIMPLEMENTED();
7115 break;
7116 default:
7117 VIXL_UNIMPLEMENTED();
7118 break;
7119 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007120}
7121
7122void Simulator::VisitSVEElementCount(const Instruction* instr) {
7123 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007124 switch (instr->Mask(SVEElementCountMask)) {
7125 case CNTB_r_s:
7126 VIXL_UNIMPLEMENTED();
7127 break;
7128 case CNTD_r_s:
7129 VIXL_UNIMPLEMENTED();
7130 break;
7131 case CNTH_r_s:
7132 VIXL_UNIMPLEMENTED();
7133 break;
7134 case CNTW_r_s:
7135 VIXL_UNIMPLEMENTED();
7136 break;
7137 case DECB_r_rs:
7138 VIXL_UNIMPLEMENTED();
7139 break;
7140 case DECD_r_rs:
7141 VIXL_UNIMPLEMENTED();
7142 break;
7143 case DECD_z_zs:
7144 VIXL_UNIMPLEMENTED();
7145 break;
7146 case DECH_r_rs:
7147 VIXL_UNIMPLEMENTED();
7148 break;
7149 case DECH_z_zs:
7150 VIXL_UNIMPLEMENTED();
7151 break;
7152 case DECW_r_rs:
7153 VIXL_UNIMPLEMENTED();
7154 break;
7155 case DECW_z_zs:
7156 VIXL_UNIMPLEMENTED();
7157 break;
7158 case INCB_r_rs:
7159 VIXL_UNIMPLEMENTED();
7160 break;
7161 case INCD_r_rs:
7162 VIXL_UNIMPLEMENTED();
7163 break;
7164 case INCD_z_zs:
7165 VIXL_UNIMPLEMENTED();
7166 break;
7167 case INCH_r_rs:
7168 VIXL_UNIMPLEMENTED();
7169 break;
7170 case INCH_z_zs:
7171 VIXL_UNIMPLEMENTED();
7172 break;
7173 case INCW_r_rs:
7174 VIXL_UNIMPLEMENTED();
7175 break;
7176 case INCW_z_zs:
7177 VIXL_UNIMPLEMENTED();
7178 break;
7179 case SQDECB_r_rs_sx:
7180 VIXL_UNIMPLEMENTED();
7181 break;
7182 case SQDECB_r_rs_x:
7183 VIXL_UNIMPLEMENTED();
7184 break;
7185 case SQDECD_r_rs_sx:
7186 VIXL_UNIMPLEMENTED();
7187 break;
7188 case SQDECD_r_rs_x:
7189 VIXL_UNIMPLEMENTED();
7190 break;
7191 case SQDECD_z_zs:
7192 VIXL_UNIMPLEMENTED();
7193 break;
7194 case SQDECH_r_rs_sx:
7195 VIXL_UNIMPLEMENTED();
7196 break;
7197 case SQDECH_r_rs_x:
7198 VIXL_UNIMPLEMENTED();
7199 break;
7200 case SQDECH_z_zs:
7201 VIXL_UNIMPLEMENTED();
7202 break;
7203 case SQDECW_r_rs_sx:
7204 VIXL_UNIMPLEMENTED();
7205 break;
7206 case SQDECW_r_rs_x:
7207 VIXL_UNIMPLEMENTED();
7208 break;
7209 case SQDECW_z_zs:
7210 VIXL_UNIMPLEMENTED();
7211 break;
7212 case SQINCB_r_rs_sx:
7213 VIXL_UNIMPLEMENTED();
7214 break;
7215 case SQINCB_r_rs_x:
7216 VIXL_UNIMPLEMENTED();
7217 break;
7218 case SQINCD_r_rs_sx:
7219 VIXL_UNIMPLEMENTED();
7220 break;
7221 case SQINCD_r_rs_x:
7222 VIXL_UNIMPLEMENTED();
7223 break;
7224 case SQINCD_z_zs:
7225 VIXL_UNIMPLEMENTED();
7226 break;
7227 case SQINCH_r_rs_sx:
7228 VIXL_UNIMPLEMENTED();
7229 break;
7230 case SQINCH_r_rs_x:
7231 VIXL_UNIMPLEMENTED();
7232 break;
7233 case SQINCH_z_zs:
7234 VIXL_UNIMPLEMENTED();
7235 break;
7236 case SQINCW_r_rs_sx:
7237 VIXL_UNIMPLEMENTED();
7238 break;
7239 case SQINCW_r_rs_x:
7240 VIXL_UNIMPLEMENTED();
7241 break;
7242 case SQINCW_z_zs:
7243 VIXL_UNIMPLEMENTED();
7244 break;
7245 case UQDECB_r_rs_uw:
7246 VIXL_UNIMPLEMENTED();
7247 break;
7248 case UQDECB_r_rs_x:
7249 VIXL_UNIMPLEMENTED();
7250 break;
7251 case UQDECD_r_rs_uw:
7252 VIXL_UNIMPLEMENTED();
7253 break;
7254 case UQDECD_r_rs_x:
7255 VIXL_UNIMPLEMENTED();
7256 break;
7257 case UQDECD_z_zs:
7258 VIXL_UNIMPLEMENTED();
7259 break;
7260 case UQDECH_r_rs_uw:
7261 VIXL_UNIMPLEMENTED();
7262 break;
7263 case UQDECH_r_rs_x:
7264 VIXL_UNIMPLEMENTED();
7265 break;
7266 case UQDECH_z_zs:
7267 VIXL_UNIMPLEMENTED();
7268 break;
7269 case UQDECW_r_rs_uw:
7270 VIXL_UNIMPLEMENTED();
7271 break;
7272 case UQDECW_r_rs_x:
7273 VIXL_UNIMPLEMENTED();
7274 break;
7275 case UQDECW_z_zs:
7276 VIXL_UNIMPLEMENTED();
7277 break;
7278 case UQINCB_r_rs_uw:
7279 VIXL_UNIMPLEMENTED();
7280 break;
7281 case UQINCB_r_rs_x:
7282 VIXL_UNIMPLEMENTED();
7283 break;
7284 case UQINCD_r_rs_uw:
7285 VIXL_UNIMPLEMENTED();
7286 break;
7287 case UQINCD_r_rs_x:
7288 VIXL_UNIMPLEMENTED();
7289 break;
7290 case UQINCD_z_zs:
7291 VIXL_UNIMPLEMENTED();
7292 break;
7293 case UQINCH_r_rs_uw:
7294 VIXL_UNIMPLEMENTED();
7295 break;
7296 case UQINCH_r_rs_x:
7297 VIXL_UNIMPLEMENTED();
7298 break;
7299 case UQINCH_z_zs:
7300 VIXL_UNIMPLEMENTED();
7301 break;
7302 case UQINCW_r_rs_uw:
7303 VIXL_UNIMPLEMENTED();
7304 break;
7305 case UQINCW_r_rs_x:
7306 VIXL_UNIMPLEMENTED();
7307 break;
7308 case UQINCW_z_zs:
7309 VIXL_UNIMPLEMENTED();
7310 break;
7311 default:
7312 VIXL_UNIMPLEMENTED();
7313 break;
7314 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007315}
7316
7317void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
7318 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007319 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7320 case FADDA_v_p_z:
7321 VIXL_UNIMPLEMENTED();
7322 break;
7323 default:
7324 VIXL_UNIMPLEMENTED();
7325 break;
7326 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007327}
7328
7329void Simulator::VisitSVEFPArithmeticPredicated(const Instruction* instr) {
7330 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007331 switch (instr->Mask(SVEFPArithmeticPredicatedMask)) {
7332 case FABD_z_p_zz:
7333 VIXL_UNIMPLEMENTED();
7334 break;
7335 case FADD_z_p_zs:
7336 VIXL_UNIMPLEMENTED();
7337 break;
7338 case FADD_z_p_zz:
7339 VIXL_UNIMPLEMENTED();
7340 break;
7341 case FDIVR_z_p_zz:
7342 VIXL_UNIMPLEMENTED();
7343 break;
7344 case FDIV_z_p_zz:
7345 VIXL_UNIMPLEMENTED();
7346 break;
7347 case FMAXNM_z_p_zs:
7348 VIXL_UNIMPLEMENTED();
7349 break;
7350 case FMAXNM_z_p_zz:
7351 VIXL_UNIMPLEMENTED();
7352 break;
7353 case FMAX_z_p_zs:
7354 VIXL_UNIMPLEMENTED();
7355 break;
7356 case FMAX_z_p_zz:
7357 VIXL_UNIMPLEMENTED();
7358 break;
7359 case FMINNM_z_p_zs:
7360 VIXL_UNIMPLEMENTED();
7361 break;
7362 case FMINNM_z_p_zz:
7363 VIXL_UNIMPLEMENTED();
7364 break;
7365 case FMIN_z_p_zs:
7366 VIXL_UNIMPLEMENTED();
7367 break;
7368 case FMIN_z_p_zz:
7369 VIXL_UNIMPLEMENTED();
7370 break;
7371 case FMULX_z_p_zz:
7372 VIXL_UNIMPLEMENTED();
7373 break;
7374 case FMUL_z_p_zs:
7375 VIXL_UNIMPLEMENTED();
7376 break;
7377 case FMUL_z_p_zz:
7378 VIXL_UNIMPLEMENTED();
7379 break;
7380 case FSCALE_z_p_zz:
7381 VIXL_UNIMPLEMENTED();
7382 break;
7383 case FSUBR_z_p_zs:
7384 VIXL_UNIMPLEMENTED();
7385 break;
7386 case FSUBR_z_p_zz:
7387 VIXL_UNIMPLEMENTED();
7388 break;
7389 case FSUB_z_p_zs:
7390 VIXL_UNIMPLEMENTED();
7391 break;
7392 case FSUB_z_p_zz:
7393 VIXL_UNIMPLEMENTED();
7394 break;
7395 case FTMAD_z_zzi:
7396 VIXL_UNIMPLEMENTED();
7397 break;
7398 default:
7399 VIXL_UNIMPLEMENTED();
7400 break;
7401 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007402}
7403
7404void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
7405 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007406 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7407 case FADD_z_zz:
7408 VIXL_UNIMPLEMENTED();
7409 break;
7410 case FMUL_z_zz:
7411 VIXL_UNIMPLEMENTED();
7412 break;
7413 case FRECPS_z_zz:
7414 VIXL_UNIMPLEMENTED();
7415 break;
7416 case FRSQRTS_z_zz:
7417 VIXL_UNIMPLEMENTED();
7418 break;
7419 case FSUB_z_zz:
7420 VIXL_UNIMPLEMENTED();
7421 break;
7422 case FTSMUL_z_zz:
7423 VIXL_UNIMPLEMENTED();
7424 break;
7425 default:
7426 VIXL_UNIMPLEMENTED();
7427 break;
7428 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007429}
7430
7431void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
7432 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007433 switch (instr->Mask(SVEFPCompareVectorsMask)) {
7434 case FACGE_p_p_zz:
7435 VIXL_UNIMPLEMENTED();
7436 break;
7437 case FACGT_p_p_zz:
7438 VIXL_UNIMPLEMENTED();
7439 break;
7440 case FCMEQ_p_p_zz:
7441 VIXL_UNIMPLEMENTED();
7442 break;
7443 case FCMGE_p_p_zz:
7444 VIXL_UNIMPLEMENTED();
7445 break;
7446 case FCMGT_p_p_zz:
7447 VIXL_UNIMPLEMENTED();
7448 break;
7449 case FCMNE_p_p_zz:
7450 VIXL_UNIMPLEMENTED();
7451 break;
7452 case FCMUO_p_p_zz:
7453 VIXL_UNIMPLEMENTED();
7454 break;
7455 default:
7456 VIXL_UNIMPLEMENTED();
7457 break;
7458 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007459}
7460
7461void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
7462 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007463 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
7464 case FCMEQ_p_p_z0:
7465 VIXL_UNIMPLEMENTED();
7466 break;
7467 case FCMGE_p_p_z0:
7468 VIXL_UNIMPLEMENTED();
7469 break;
7470 case FCMGT_p_p_z0:
7471 VIXL_UNIMPLEMENTED();
7472 break;
7473 case FCMLE_p_p_z0:
7474 VIXL_UNIMPLEMENTED();
7475 break;
7476 case FCMLT_p_p_z0:
7477 VIXL_UNIMPLEMENTED();
7478 break;
7479 case FCMNE_p_p_z0:
7480 VIXL_UNIMPLEMENTED();
7481 break;
7482 default:
7483 VIXL_UNIMPLEMENTED();
7484 break;
7485 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007486}
7487
7488void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
7489 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007490 switch (instr->Mask(SVEFPComplexAdditionMask)) {
7491 case FCADD_z_p_zz:
7492 VIXL_UNIMPLEMENTED();
7493 break;
7494 default:
7495 VIXL_UNIMPLEMENTED();
7496 break;
7497 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007498}
7499
7500void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
7501 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007502 switch (instr->Mask(SVEFPComplexMulAddMask)) {
7503 case FCMLA_z_p_zzz:
7504 VIXL_UNIMPLEMENTED();
7505 break;
7506 default:
7507 VIXL_UNIMPLEMENTED();
7508 break;
7509 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007510}
7511
7512void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
7513 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007514 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
7515 case FCMLA_z_zzzi_h:
7516 VIXL_UNIMPLEMENTED();
7517 break;
7518 case FCMLA_z_zzzi_s:
7519 VIXL_UNIMPLEMENTED();
7520 break;
7521 default:
7522 VIXL_UNIMPLEMENTED();
7523 break;
7524 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007525}
7526
7527void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
7528 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007529 switch (instr->Mask(SVEFPFastReductionMask)) {
7530 case FADDV_v_p_z:
7531 VIXL_UNIMPLEMENTED();
7532 break;
7533 case FMAXNMV_v_p_z:
7534 VIXL_UNIMPLEMENTED();
7535 break;
7536 case FMAXV_v_p_z:
7537 VIXL_UNIMPLEMENTED();
7538 break;
7539 case FMINNMV_v_p_z:
7540 VIXL_UNIMPLEMENTED();
7541 break;
7542 case FMINV_v_p_z:
7543 VIXL_UNIMPLEMENTED();
7544 break;
7545 default:
7546 VIXL_UNIMPLEMENTED();
7547 break;
7548 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007549}
7550
7551void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
7552 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007553 switch (instr->Mask(SVEFPMulIndexMask)) {
7554 case FMUL_z_zzi_d:
7555 VIXL_UNIMPLEMENTED();
7556 break;
7557 case FMUL_z_zzi_h:
7558 VIXL_UNIMPLEMENTED();
7559 break;
7560 case FMUL_z_zzi_s:
7561 VIXL_UNIMPLEMENTED();
7562 break;
7563 default:
7564 VIXL_UNIMPLEMENTED();
7565 break;
7566 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007567}
7568
7569void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
7570 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007571 switch (instr->Mask(SVEFPMulAddMask)) {
7572 case FMAD_z_p_zzz:
7573 VIXL_UNIMPLEMENTED();
7574 break;
7575 case FMLA_z_p_zzz:
7576 VIXL_UNIMPLEMENTED();
7577 break;
7578 case FMLS_z_p_zzz:
7579 VIXL_UNIMPLEMENTED();
7580 break;
7581 case FMSB_z_p_zzz:
7582 VIXL_UNIMPLEMENTED();
7583 break;
7584 case FNMAD_z_p_zzz:
7585 VIXL_UNIMPLEMENTED();
7586 break;
7587 case FNMLA_z_p_zzz:
7588 VIXL_UNIMPLEMENTED();
7589 break;
7590 case FNMLS_z_p_zzz:
7591 VIXL_UNIMPLEMENTED();
7592 break;
7593 case FNMSB_z_p_zzz:
7594 VIXL_UNIMPLEMENTED();
7595 break;
7596 default:
7597 VIXL_UNIMPLEMENTED();
7598 break;
7599 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007600}
7601
7602void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
7603 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007604 switch (instr->Mask(SVEFPMulAddIndexMask)) {
7605 case FMLA_z_zzzi_d:
7606 VIXL_UNIMPLEMENTED();
7607 break;
7608 case FMLA_z_zzzi_h:
7609 VIXL_UNIMPLEMENTED();
7610 break;
7611 case FMLA_z_zzzi_s:
7612 VIXL_UNIMPLEMENTED();
7613 break;
7614 case FMLS_z_zzzi_d:
7615 VIXL_UNIMPLEMENTED();
7616 break;
7617 case FMLS_z_zzzi_h:
7618 VIXL_UNIMPLEMENTED();
7619 break;
7620 case FMLS_z_zzzi_s:
7621 VIXL_UNIMPLEMENTED();
7622 break;
7623 default:
7624 VIXL_UNIMPLEMENTED();
7625 break;
7626 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007627}
7628
7629void Simulator::VisitSVEFPUnaryOpPredicated(const Instruction* instr) {
7630 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007631 switch (instr->Mask(SVEFPUnaryOpPredicatedMask)) {
7632 case FCVTZS_z_p_z_d2w:
7633 VIXL_UNIMPLEMENTED();
7634 break;
7635 case FCVTZS_z_p_z_d2x:
7636 VIXL_UNIMPLEMENTED();
7637 break;
7638 case FCVTZS_z_p_z_fp162h:
7639 VIXL_UNIMPLEMENTED();
7640 break;
7641 case FCVTZS_z_p_z_fp162w:
7642 VIXL_UNIMPLEMENTED();
7643 break;
7644 case FCVTZS_z_p_z_fp162x:
7645 VIXL_UNIMPLEMENTED();
7646 break;
7647 case FCVTZS_z_p_z_s2w:
7648 VIXL_UNIMPLEMENTED();
7649 break;
7650 case FCVTZS_z_p_z_s2x:
7651 VIXL_UNIMPLEMENTED();
7652 break;
7653 case FCVTZU_z_p_z_d2w:
7654 VIXL_UNIMPLEMENTED();
7655 break;
7656 case FCVTZU_z_p_z_d2x:
7657 VIXL_UNIMPLEMENTED();
7658 break;
7659 case FCVTZU_z_p_z_fp162h:
7660 VIXL_UNIMPLEMENTED();
7661 break;
7662 case FCVTZU_z_p_z_fp162w:
7663 VIXL_UNIMPLEMENTED();
7664 break;
7665 case FCVTZU_z_p_z_fp162x:
7666 VIXL_UNIMPLEMENTED();
7667 break;
7668 case FCVTZU_z_p_z_s2w:
7669 VIXL_UNIMPLEMENTED();
7670 break;
7671 case FCVTZU_z_p_z_s2x:
7672 VIXL_UNIMPLEMENTED();
7673 break;
7674 case FCVT_z_p_z_d2h:
7675 VIXL_UNIMPLEMENTED();
7676 break;
7677 case FCVT_z_p_z_d2s:
7678 VIXL_UNIMPLEMENTED();
7679 break;
7680 case FCVT_z_p_z_h2d:
7681 VIXL_UNIMPLEMENTED();
7682 break;
7683 case FCVT_z_p_z_h2s:
7684 VIXL_UNIMPLEMENTED();
7685 break;
7686 case FCVT_z_p_z_s2d:
7687 VIXL_UNIMPLEMENTED();
7688 break;
7689 case FCVT_z_p_z_s2h:
7690 VIXL_UNIMPLEMENTED();
7691 break;
7692 case FRECPX_z_p_z:
7693 VIXL_UNIMPLEMENTED();
7694 break;
7695 case FRINTA_z_p_z:
7696 VIXL_UNIMPLEMENTED();
7697 break;
7698 case FRINTI_z_p_z:
7699 VIXL_UNIMPLEMENTED();
7700 break;
7701 case FRINTM_z_p_z:
7702 VIXL_UNIMPLEMENTED();
7703 break;
7704 case FRINTN_z_p_z:
7705 VIXL_UNIMPLEMENTED();
7706 break;
7707 case FRINTP_z_p_z:
7708 VIXL_UNIMPLEMENTED();
7709 break;
7710 case FRINTX_z_p_z:
7711 VIXL_UNIMPLEMENTED();
7712 break;
7713 case FRINTZ_z_p_z:
7714 VIXL_UNIMPLEMENTED();
7715 break;
7716 case FSQRT_z_p_z:
7717 VIXL_UNIMPLEMENTED();
7718 break;
7719 case SCVTF_z_p_z_h2fp16:
7720 VIXL_UNIMPLEMENTED();
7721 break;
7722 case SCVTF_z_p_z_w2d:
7723 VIXL_UNIMPLEMENTED();
7724 break;
7725 case SCVTF_z_p_z_w2fp16:
7726 VIXL_UNIMPLEMENTED();
7727 break;
7728 case SCVTF_z_p_z_w2s:
7729 VIXL_UNIMPLEMENTED();
7730 break;
7731 case SCVTF_z_p_z_x2d:
7732 VIXL_UNIMPLEMENTED();
7733 break;
7734 case SCVTF_z_p_z_x2fp16:
7735 VIXL_UNIMPLEMENTED();
7736 break;
7737 case SCVTF_z_p_z_x2s:
7738 VIXL_UNIMPLEMENTED();
7739 break;
7740 case UCVTF_z_p_z_h2fp16:
7741 VIXL_UNIMPLEMENTED();
7742 break;
7743 case UCVTF_z_p_z_w2d:
7744 VIXL_UNIMPLEMENTED();
7745 break;
7746 case UCVTF_z_p_z_w2fp16:
7747 VIXL_UNIMPLEMENTED();
7748 break;
7749 case UCVTF_z_p_z_w2s:
7750 VIXL_UNIMPLEMENTED();
7751 break;
7752 case UCVTF_z_p_z_x2d:
7753 VIXL_UNIMPLEMENTED();
7754 break;
7755 case UCVTF_z_p_z_x2fp16:
7756 VIXL_UNIMPLEMENTED();
7757 break;
7758 case UCVTF_z_p_z_x2s:
7759 VIXL_UNIMPLEMENTED();
7760 break;
7761 default:
7762 VIXL_UNIMPLEMENTED();
7763 break;
7764 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007765}
7766
7767void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
7768 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007769 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
7770 case FRECPE_z_z:
7771 VIXL_UNIMPLEMENTED();
7772 break;
7773 case FRSQRTE_z_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::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
7783 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007784 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
7785 case DECP_r_p_r:
7786 VIXL_UNIMPLEMENTED();
7787 break;
7788 case DECP_z_p_z:
7789 VIXL_UNIMPLEMENTED();
7790 break;
7791 case INCP_r_p_r:
7792 VIXL_UNIMPLEMENTED();
7793 break;
7794 case INCP_z_p_z:
7795 VIXL_UNIMPLEMENTED();
7796 break;
7797 case SQDECP_r_p_r_sx:
7798 VIXL_UNIMPLEMENTED();
7799 break;
7800 case SQDECP_r_p_r_x:
7801 VIXL_UNIMPLEMENTED();
7802 break;
7803 case SQDECP_z_p_z:
7804 VIXL_UNIMPLEMENTED();
7805 break;
7806 case SQINCP_r_p_r_sx:
7807 VIXL_UNIMPLEMENTED();
7808 break;
7809 case SQINCP_r_p_r_x:
7810 VIXL_UNIMPLEMENTED();
7811 break;
7812 case SQINCP_z_p_z:
7813 VIXL_UNIMPLEMENTED();
7814 break;
7815 case UQDECP_r_p_r_uw:
7816 VIXL_UNIMPLEMENTED();
7817 break;
7818 case UQDECP_r_p_r_x:
7819 VIXL_UNIMPLEMENTED();
7820 break;
7821 case UQDECP_z_p_z:
7822 VIXL_UNIMPLEMENTED();
7823 break;
7824 case UQINCP_r_p_r_uw:
7825 VIXL_UNIMPLEMENTED();
7826 break;
7827 case UQINCP_r_p_r_x:
7828 VIXL_UNIMPLEMENTED();
7829 break;
7830 case UQINCP_z_p_z:
7831 VIXL_UNIMPLEMENTED();
7832 break;
7833 default:
7834 VIXL_UNIMPLEMENTED();
7835 break;
7836 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007837}
7838
7839void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
7840 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007841 switch (instr->Mask(SVEIndexGenerationMask)) {
7842 case INDEX_z_ii:
7843 VIXL_UNIMPLEMENTED();
7844 break;
7845 case INDEX_z_ir:
7846 VIXL_UNIMPLEMENTED();
7847 break;
7848 case INDEX_z_ri:
7849 VIXL_UNIMPLEMENTED();
7850 break;
7851 case INDEX_z_rr:
7852 VIXL_UNIMPLEMENTED();
7853 break;
7854 default:
7855 VIXL_UNIMPLEMENTED();
7856 break;
7857 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007858}
7859
7860void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
7861 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007862 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
7863 case ADD_z_zz:
7864 VIXL_UNIMPLEMENTED();
7865 break;
7866 case SQADD_z_zz:
7867 VIXL_UNIMPLEMENTED();
7868 break;
7869 case SQSUB_z_zz:
7870 VIXL_UNIMPLEMENTED();
7871 break;
7872 case SUB_z_zz:
7873 VIXL_UNIMPLEMENTED();
7874 break;
7875 case UQADD_z_zz:
7876 VIXL_UNIMPLEMENTED();
7877 break;
7878 case UQSUB_z_zz:
7879 VIXL_UNIMPLEMENTED();
7880 break;
7881 default:
7882 VIXL_UNIMPLEMENTED();
7883 break;
7884 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007885}
7886
7887void Simulator::VisitSVEIntBinaryArithmeticPredicated(
7888 const Instruction* instr) {
7889 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007890 switch (instr->Mask(SVEIntBinaryArithmeticPredicatedMask)) {
7891 case ADD_z_p_zz:
7892 VIXL_UNIMPLEMENTED();
7893 break;
7894 case AND_z_p_zz:
7895 VIXL_UNIMPLEMENTED();
7896 break;
7897 case BIC_z_p_zz:
7898 VIXL_UNIMPLEMENTED();
7899 break;
7900 case EOR_z_p_zz:
7901 VIXL_UNIMPLEMENTED();
7902 break;
7903 case MUL_z_p_zz:
7904 VIXL_UNIMPLEMENTED();
7905 break;
7906 case ORR_z_p_zz:
7907 VIXL_UNIMPLEMENTED();
7908 break;
7909 case SABD_z_p_zz:
7910 VIXL_UNIMPLEMENTED();
7911 break;
7912 case SDIVR_z_p_zz:
7913 VIXL_UNIMPLEMENTED();
7914 break;
7915 case SDIV_z_p_zz:
7916 VIXL_UNIMPLEMENTED();
7917 break;
7918 case SMAX_z_p_zz:
7919 VIXL_UNIMPLEMENTED();
7920 break;
7921 case SMIN_z_p_zz:
7922 VIXL_UNIMPLEMENTED();
7923 break;
7924 case SMULH_z_p_zz:
7925 VIXL_UNIMPLEMENTED();
7926 break;
7927 case SUBR_z_p_zz:
7928 VIXL_UNIMPLEMENTED();
7929 break;
7930 case SUB_z_p_zz:
7931 VIXL_UNIMPLEMENTED();
7932 break;
7933 case UABD_z_p_zz:
7934 VIXL_UNIMPLEMENTED();
7935 break;
7936 case UDIVR_z_p_zz:
7937 VIXL_UNIMPLEMENTED();
7938 break;
7939 case UDIV_z_p_zz:
7940 VIXL_UNIMPLEMENTED();
7941 break;
7942 case UMAX_z_p_zz:
7943 VIXL_UNIMPLEMENTED();
7944 break;
7945 case UMIN_z_p_zz:
7946 VIXL_UNIMPLEMENTED();
7947 break;
7948 case UMULH_z_p_zz:
7949 VIXL_UNIMPLEMENTED();
7950 break;
7951 default:
7952 VIXL_UNIMPLEMENTED();
7953 break;
7954 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007955}
7956
7957void Simulator::VisitSVEIntCompareScalars(const Instruction* instr) {
7958 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007959 switch (instr->Mask(SVEIntCompareScalarsMask)) {
7960 case CTERMEQ_rr:
7961 VIXL_UNIMPLEMENTED();
7962 break;
7963 case CTERMNE_rr:
7964 VIXL_UNIMPLEMENTED();
7965 break;
7966 case WHILELE_p_p_rr:
7967 VIXL_UNIMPLEMENTED();
7968 break;
7969 case WHILELO_p_p_rr:
7970 VIXL_UNIMPLEMENTED();
7971 break;
7972 case WHILELS_p_p_rr:
7973 VIXL_UNIMPLEMENTED();
7974 break;
7975 case WHILELT_p_p_rr:
7976 VIXL_UNIMPLEMENTED();
7977 break;
7978 default:
7979 VIXL_UNIMPLEMENTED();
7980 break;
7981 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00007982}
7983
7984void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
7985 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00007986 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
7987 case CMPEQ_p_p_zi:
7988 VIXL_UNIMPLEMENTED();
7989 break;
7990 case CMPGE_p_p_zi:
7991 VIXL_UNIMPLEMENTED();
7992 break;
7993 case CMPGT_p_p_zi:
7994 VIXL_UNIMPLEMENTED();
7995 break;
7996 case CMPLE_p_p_zi:
7997 VIXL_UNIMPLEMENTED();
7998 break;
7999 case CMPLT_p_p_zi:
8000 VIXL_UNIMPLEMENTED();
8001 break;
8002 case CMPNE_p_p_zi:
8003 VIXL_UNIMPLEMENTED();
8004 break;
8005 default:
8006 VIXL_UNIMPLEMENTED();
8007 break;
8008 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008009}
8010
8011void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
8012 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008013 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
8014 case CMPHI_p_p_zi:
8015 VIXL_UNIMPLEMENTED();
8016 break;
8017 case CMPHS_p_p_zi:
8018 VIXL_UNIMPLEMENTED();
8019 break;
8020 case CMPLO_p_p_zi:
8021 VIXL_UNIMPLEMENTED();
8022 break;
8023 case CMPLS_p_p_zi:
8024 VIXL_UNIMPLEMENTED();
8025 break;
8026 default:
8027 VIXL_UNIMPLEMENTED();
8028 break;
8029 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008030}
8031
8032void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
8033 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008034 switch (instr->Mask(SVEIntCompareVectorsMask)) {
8035 case CMPEQ_p_p_zw:
8036 VIXL_UNIMPLEMENTED();
8037 break;
8038 case CMPEQ_p_p_zz:
8039 VIXL_UNIMPLEMENTED();
8040 break;
8041 case CMPGE_p_p_zw:
8042 VIXL_UNIMPLEMENTED();
8043 break;
8044 case CMPGE_p_p_zz:
8045 VIXL_UNIMPLEMENTED();
8046 break;
8047 case CMPGT_p_p_zw:
8048 VIXL_UNIMPLEMENTED();
8049 break;
8050 case CMPGT_p_p_zz:
8051 VIXL_UNIMPLEMENTED();
8052 break;
8053 case CMPHI_p_p_zw:
8054 VIXL_UNIMPLEMENTED();
8055 break;
8056 case CMPHI_p_p_zz:
8057 VIXL_UNIMPLEMENTED();
8058 break;
8059 case CMPHS_p_p_zw:
8060 VIXL_UNIMPLEMENTED();
8061 break;
8062 case CMPHS_p_p_zz:
8063 VIXL_UNIMPLEMENTED();
8064 break;
8065 case CMPLE_p_p_zw:
8066 VIXL_UNIMPLEMENTED();
8067 break;
8068 case CMPLO_p_p_zw:
8069 VIXL_UNIMPLEMENTED();
8070 break;
8071 case CMPLS_p_p_zw:
8072 VIXL_UNIMPLEMENTED();
8073 break;
8074 case CMPLT_p_p_zw:
8075 VIXL_UNIMPLEMENTED();
8076 break;
8077 case CMPNE_p_p_zw:
8078 VIXL_UNIMPLEMENTED();
8079 break;
8080 case CMPNE_p_p_zz:
8081 VIXL_UNIMPLEMENTED();
8082 break;
8083 default:
8084 VIXL_UNIMPLEMENTED();
8085 break;
8086 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008087}
8088
8089void Simulator::VisitSVEIntMiscUnpredicated(const Instruction* instr) {
8090 USE(instr);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008091
8092 SimVRegister& zd = ReadVRegister(instr->GetRd());
8093 SimVRegister& zn = ReadVRegister(instr->GetRn());
8094
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008095 switch (instr->Mask(SVEIntMiscUnpredicatedMask)) {
8096 case FEXPA_z_z:
8097 VIXL_UNIMPLEMENTED();
8098 break;
8099 case FTSSEL_z_zz:
8100 VIXL_UNIMPLEMENTED();
8101 break;
8102 case MOVPRFX_z_z:
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008103 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
8104 // Record the movprfx, so the next ExecuteInstruction() can check it.
8105 movprfx_ = instr;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008106 break;
8107 default:
8108 VIXL_UNIMPLEMENTED();
8109 break;
8110 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008111}
8112
8113void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
8114 USE(instr);
Jacob Bramley22023df2019-05-14 17:55:43 +01008115 VectorFormat vform = instr->GetSVEVectorFormat();
8116
8117 SimVRegister& zd = ReadVRegister(instr->GetRd());
8118 SimVRegister& zm = ReadVRegister(instr->GetRm());
8119
8120 SimVRegister result;
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008121 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008122 case MLA_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008123 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008124 break;
8125 case MLS_z_p_zzz:
Jacob Bramley22023df2019-05-14 17:55:43 +01008126 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008127 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008128 case MAD_z_p_zzz:
8129 // 'za' is encoded in 'Rn'.
8130 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008131 break;
Jacob Bramley22023df2019-05-14 17:55:43 +01008132 case MSB_z_p_zzz: {
8133 // 'za' is encoded in 'Rn'.
8134 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
8135 break;
8136 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008137 default:
8138 VIXL_UNIMPLEMENTED();
8139 break;
8140 }
Jacob Bramley22023df2019-05-14 17:55:43 +01008141 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008142}
8143
8144void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
8145 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008146 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
8147 case SDOT_z_zzz:
8148 VIXL_UNIMPLEMENTED();
8149 break;
8150 case UDOT_z_zzz:
8151 VIXL_UNIMPLEMENTED();
8152 break;
8153 default:
8154 VIXL_UNIMPLEMENTED();
8155 break;
8156 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008157}
8158
8159void Simulator::VisitSVEIntReduction(const Instruction* instr) {
8160 USE(instr);
Jacob Bramleyae2fc3b2019-05-21 19:24:36 +01008161
8162 VectorFormat vform = instr->GetSVEVectorFormat();
8163 SimVRegister& zn = ReadVRegister(instr->GetRn());
8164 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8165
8166 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
8167 switch (instr->Mask(SVEIntReductionLogicalMask)) {
8168 case ANDV_r_p_z:
8169 VIXL_UNIMPLEMENTED();
8170 break;
8171 case EORV_r_p_z:
8172 VIXL_UNIMPLEMENTED();
8173 break;
8174 case ORV_r_p_z:
8175 VIXL_UNIMPLEMENTED();
8176 break;
8177 default:
8178 VIXL_UNIMPLEMENTED();
8179 break;
8180 }
8181 } else {
8182 switch (instr->Mask(SVEIntReductionMask)) {
8183 case MOVPRFX_z_p_z: {
8184 SimVRegister& zd = ReadVRegister(instr->GetRd());
8185 if (instr->ExtractBit(16)) {
8186 mov_merging(vform, zd, pg, zn);
8187 } else {
8188 mov_zeroing(vform, zd, pg, zn);
8189 }
8190 // Record the movprfx, so the next ExecuteInstruction() can check it.
8191 movprfx_ = instr;
8192 break;
8193 }
8194 case SADDV_r_p_z:
8195 VIXL_UNIMPLEMENTED();
8196 break;
8197 case SMAXV_r_p_z:
8198 VIXL_UNIMPLEMENTED();
8199 break;
8200 case SMINV_r_p_z:
8201 VIXL_UNIMPLEMENTED();
8202 break;
8203 case UADDV_r_p_z:
8204 VIXL_UNIMPLEMENTED();
8205 break;
8206 case UMAXV_r_p_z:
8207 VIXL_UNIMPLEMENTED();
8208 break;
8209 case UMINV_r_p_z:
8210 VIXL_UNIMPLEMENTED();
8211 break;
8212 default:
8213 VIXL_UNIMPLEMENTED();
8214 break;
8215 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008216 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008217}
8218
8219void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
8220 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008221 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
8222 case ABS_z_p_z:
8223 VIXL_UNIMPLEMENTED();
8224 break;
8225 case CLS_z_p_z:
8226 VIXL_UNIMPLEMENTED();
8227 break;
8228 case CLZ_z_p_z:
8229 VIXL_UNIMPLEMENTED();
8230 break;
8231 case CNOT_z_p_z:
8232 VIXL_UNIMPLEMENTED();
8233 break;
8234 case CNT_z_p_z:
8235 VIXL_UNIMPLEMENTED();
8236 break;
8237 case FABS_z_p_z:
8238 VIXL_UNIMPLEMENTED();
8239 break;
8240 case FNEG_z_p_z:
8241 VIXL_UNIMPLEMENTED();
8242 break;
8243 case NEG_z_p_z:
8244 VIXL_UNIMPLEMENTED();
8245 break;
8246 case NOT_z_p_z:
8247 VIXL_UNIMPLEMENTED();
8248 break;
8249 case SXTB_z_p_z:
8250 VIXL_UNIMPLEMENTED();
8251 break;
8252 case SXTH_z_p_z:
8253 VIXL_UNIMPLEMENTED();
8254 break;
8255 case SXTW_z_p_z:
8256 VIXL_UNIMPLEMENTED();
8257 break;
8258 case UXTB_z_p_z:
8259 VIXL_UNIMPLEMENTED();
8260 break;
8261 case UXTH_z_p_z:
8262 VIXL_UNIMPLEMENTED();
8263 break;
8264 case UXTW_z_p_z:
8265 VIXL_UNIMPLEMENTED();
8266 break;
8267 default:
8268 VIXL_UNIMPLEMENTED();
8269 break;
8270 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008271}
8272
8273void Simulator::VisitSVEIntWideImmPredicated(const Instruction* instr) {
8274 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008275 switch (instr->Mask(SVEIntWideImmPredicatedMask)) {
8276 case CPY_z_p_i:
8277 VIXL_UNIMPLEMENTED();
8278 break;
8279 case FCPY_z_p_i:
8280 VIXL_UNIMPLEMENTED();
8281 break;
8282 default:
8283 VIXL_UNIMPLEMENTED();
8284 break;
8285 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008286}
8287
8288void Simulator::VisitSVEIntWideImmUnpredicated(const Instruction* instr) {
8289 USE(instr);
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01008290 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008291 switch (instr->Mask(SVEIntWideImmUnpredicatedMask)) {
8292 case ADD_z_zi:
8293 VIXL_UNIMPLEMENTED();
8294 break;
8295 case DUP_z_i:
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01008296 dup_immediate(instr->GetSVEVectorFormat(),
8297 zd,
8298 instr->GetImmSVEIntWideSigned());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008299 break;
8300 case FDUP_z_i:
8301 VIXL_UNIMPLEMENTED();
8302 break;
8303 case MUL_z_zi:
8304 VIXL_UNIMPLEMENTED();
8305 break;
8306 case SMAX_z_zi:
8307 VIXL_UNIMPLEMENTED();
8308 break;
8309 case SMIN_z_zi:
8310 VIXL_UNIMPLEMENTED();
8311 break;
8312 case SQADD_z_zi:
8313 VIXL_UNIMPLEMENTED();
8314 break;
8315 case SQSUB_z_zi:
8316 VIXL_UNIMPLEMENTED();
8317 break;
8318 case SUBR_z_zi:
8319 VIXL_UNIMPLEMENTED();
8320 break;
8321 case SUB_z_zi:
8322 VIXL_UNIMPLEMENTED();
8323 break;
8324 case UMAX_z_zi:
8325 VIXL_UNIMPLEMENTED();
8326 break;
8327 case UMIN_z_zi:
8328 VIXL_UNIMPLEMENTED();
8329 break;
8330 case UQADD_z_zi:
8331 VIXL_UNIMPLEMENTED();
8332 break;
8333 case UQSUB_z_zi:
8334 VIXL_UNIMPLEMENTED();
8335 break;
8336 default:
8337 VIXL_UNIMPLEMENTED();
8338 break;
8339 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008340}
8341
8342void Simulator::VisitSVEMem32BitGatherAndUnsizedContiguous(
8343 const Instruction* instr) {
8344 USE(instr);
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01008345 if (instr->Mask(SVEMemUnsizedContiguousLoadPMask) == LDR_p_bi) {
8346 SimPRegister& pt = ReadPRegister(instr->GetPt());
8347 uint64_t address = ReadXRegister(instr->GetRn());
8348 if (instr->Mask(0x003f1c00)) {
8349 // TODO: Support the VL multiplier.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008350 VIXL_UNIMPLEMENTED();
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01008351 }
8352 for (unsigned i = 0; i < GetPredicateLengthInBytes(); i++) {
8353 pt.Insert(i, Memory::Read<uint8_t>(address + i));
8354 }
8355 } else {
8356 // TODO: This switch doesn't work because the mask needs to vary on a finer
8357 // granularity. Early implementations have already been pulled out, but we
8358 // need to re-organise the instruction groups.
8359 switch (instr->Mask(SVEMem32BitGatherAndUnsizedContiguousMask)) {
8360 case LD1B_z_p_ai_s:
8361 case LD1B_z_p_bz_s_x32_unscaled:
8362 case LD1H_z_p_ai_s:
8363 case LD1H_z_p_bz_s_x32_scaled:
8364 case LD1H_z_p_bz_s_x32_unscaled:
8365 case LD1RB_z_p_bi_u16:
8366 case LD1RB_z_p_bi_u32:
8367 case LD1RB_z_p_bi_u64:
8368 case LD1RB_z_p_bi_u8:
8369 case LD1RD_z_p_bi_u64:
8370 case LD1RH_z_p_bi_u16:
8371 case LD1RH_z_p_bi_u32:
8372 case LD1RH_z_p_bi_u64:
8373 case LD1RSB_z_p_bi_s16:
8374 case LD1RSB_z_p_bi_s32:
8375 case LD1RSB_z_p_bi_s64:
8376 case LD1RSH_z_p_bi_s32:
8377 case LD1RSH_z_p_bi_s64:
8378 case LD1RSW_z_p_bi_s64:
8379 case LD1RW_z_p_bi_u32:
8380 case LD1RW_z_p_bi_u64:
8381 case LD1SB_z_p_ai_s:
8382 case LD1SB_z_p_bz_s_x32_unscaled:
8383 case LD1SH_z_p_ai_s:
8384 case LD1SH_z_p_bz_s_x32_scaled:
8385 case LD1SH_z_p_bz_s_x32_unscaled:
8386 case LD1W_z_p_ai_s:
8387 case LD1W_z_p_bz_s_x32_scaled:
8388 case LD1W_z_p_bz_s_x32_unscaled:
8389 case LDFF1B_z_p_ai_s:
8390 case LDFF1B_z_p_bz_s_x32_unscaled:
8391 case LDFF1H_z_p_ai_s:
8392 case LDFF1H_z_p_bz_s_x32_scaled:
8393 case LDFF1H_z_p_bz_s_x32_unscaled:
8394 case LDFF1SB_z_p_ai_s:
8395 case LDFF1SB_z_p_bz_s_x32_unscaled:
8396 case LDFF1SH_z_p_ai_s:
8397 case LDFF1SH_z_p_bz_s_x32_scaled:
8398 case LDFF1SH_z_p_bz_s_x32_unscaled:
8399 case LDFF1W_z_p_ai_s:
8400 case LDFF1W_z_p_bz_s_x32_scaled:
8401 case LDFF1W_z_p_bz_s_x32_unscaled:
8402 case LDR_z_bi:
8403 case PRFB_i_p_ai_s:
8404 case PRFB_i_p_bi_s:
8405 case PRFB_i_p_br_s:
8406 case PRFB_i_p_bz_s_x32_scaled:
8407 case PRFD_i_p_ai_s:
8408 case PRFD_i_p_bi_s:
8409 case PRFD_i_p_br_s:
8410 case PRFD_i_p_bz_s_x32_scaled:
8411 case PRFH_i_p_ai_s:
8412 case PRFH_i_p_bi_s:
8413 case PRFH_i_p_br_s:
8414 case PRFH_i_p_bz_s_x32_scaled:
8415 case PRFW_i_p_ai_s:
8416 case PRFW_i_p_bi_s:
8417 case PRFW_i_p_br_s:
8418 case PRFW_i_p_bz_s_x32_scaled:
8419 default:
8420 VIXL_UNIMPLEMENTED();
8421 break;
8422 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008423 }
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01008424 // TODO: LogRead
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008425}
8426
8427void Simulator::VisitSVEMem64BitGather(const Instruction* instr) {
8428 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008429 switch (instr->Mask(SVEMem64BitGatherMask)) {
8430 case LD1B_z_p_ai_d:
8431 VIXL_UNIMPLEMENTED();
8432 break;
8433 case LD1B_z_p_bz_d_64_unscaled:
8434 VIXL_UNIMPLEMENTED();
8435 break;
8436 case LD1B_z_p_bz_d_x32_unscaled:
8437 VIXL_UNIMPLEMENTED();
8438 break;
8439 case LD1D_z_p_ai_d:
8440 VIXL_UNIMPLEMENTED();
8441 break;
8442 case LD1D_z_p_bz_d_64_scaled:
8443 VIXL_UNIMPLEMENTED();
8444 break;
8445 case LD1D_z_p_bz_d_64_unscaled:
8446 VIXL_UNIMPLEMENTED();
8447 break;
8448 case LD1D_z_p_bz_d_x32_scaled:
8449 VIXL_UNIMPLEMENTED();
8450 break;
8451 case LD1D_z_p_bz_d_x32_unscaled:
8452 VIXL_UNIMPLEMENTED();
8453 break;
8454 case LD1H_z_p_ai_d:
8455 VIXL_UNIMPLEMENTED();
8456 break;
8457 case LD1H_z_p_bz_d_64_scaled:
8458 VIXL_UNIMPLEMENTED();
8459 break;
8460 case LD1H_z_p_bz_d_64_unscaled:
8461 VIXL_UNIMPLEMENTED();
8462 break;
8463 case LD1H_z_p_bz_d_x32_scaled:
8464 VIXL_UNIMPLEMENTED();
8465 break;
8466 case LD1H_z_p_bz_d_x32_unscaled:
8467 VIXL_UNIMPLEMENTED();
8468 break;
8469 case LD1SB_z_p_ai_d:
8470 VIXL_UNIMPLEMENTED();
8471 break;
8472 case LD1SB_z_p_bz_d_64_unscaled:
8473 VIXL_UNIMPLEMENTED();
8474 break;
8475 case LD1SB_z_p_bz_d_x32_unscaled:
8476 VIXL_UNIMPLEMENTED();
8477 break;
8478 case LD1SH_z_p_ai_d:
8479 VIXL_UNIMPLEMENTED();
8480 break;
8481 case LD1SH_z_p_bz_d_64_scaled:
8482 VIXL_UNIMPLEMENTED();
8483 break;
8484 case LD1SH_z_p_bz_d_64_unscaled:
8485 VIXL_UNIMPLEMENTED();
8486 break;
8487 case LD1SH_z_p_bz_d_x32_scaled:
8488 VIXL_UNIMPLEMENTED();
8489 break;
8490 case LD1SH_z_p_bz_d_x32_unscaled:
8491 VIXL_UNIMPLEMENTED();
8492 break;
8493 case LD1SW_z_p_ai_d:
8494 VIXL_UNIMPLEMENTED();
8495 break;
8496 case LD1SW_z_p_bz_d_64_scaled:
8497 VIXL_UNIMPLEMENTED();
8498 break;
8499 case LD1SW_z_p_bz_d_64_unscaled:
8500 VIXL_UNIMPLEMENTED();
8501 break;
8502 case LD1SW_z_p_bz_d_x32_scaled:
8503 VIXL_UNIMPLEMENTED();
8504 break;
8505 case LD1SW_z_p_bz_d_x32_unscaled:
8506 VIXL_UNIMPLEMENTED();
8507 break;
8508 case LD1W_z_p_ai_d:
8509 VIXL_UNIMPLEMENTED();
8510 break;
8511 case LD1W_z_p_bz_d_64_scaled:
8512 VIXL_UNIMPLEMENTED();
8513 break;
8514 case LD1W_z_p_bz_d_64_unscaled:
8515 VIXL_UNIMPLEMENTED();
8516 break;
8517 case LD1W_z_p_bz_d_x32_scaled:
8518 VIXL_UNIMPLEMENTED();
8519 break;
8520 case LD1W_z_p_bz_d_x32_unscaled:
8521 VIXL_UNIMPLEMENTED();
8522 break;
8523 case LDFF1B_z_p_ai_d:
8524 VIXL_UNIMPLEMENTED();
8525 break;
8526 case LDFF1B_z_p_bz_d_64_unscaled:
8527 VIXL_UNIMPLEMENTED();
8528 break;
8529 case LDFF1B_z_p_bz_d_x32_unscaled:
8530 VIXL_UNIMPLEMENTED();
8531 break;
8532 case LDFF1D_z_p_ai_d:
8533 VIXL_UNIMPLEMENTED();
8534 break;
8535 case LDFF1D_z_p_bz_d_64_scaled:
8536 VIXL_UNIMPLEMENTED();
8537 break;
8538 case LDFF1D_z_p_bz_d_64_unscaled:
8539 VIXL_UNIMPLEMENTED();
8540 break;
8541 case LDFF1D_z_p_bz_d_x32_scaled:
8542 VIXL_UNIMPLEMENTED();
8543 break;
8544 case LDFF1D_z_p_bz_d_x32_unscaled:
8545 VIXL_UNIMPLEMENTED();
8546 break;
8547 case LDFF1H_z_p_ai_d:
8548 VIXL_UNIMPLEMENTED();
8549 break;
8550 case LDFF1H_z_p_bz_d_64_scaled:
8551 VIXL_UNIMPLEMENTED();
8552 break;
8553 case LDFF1H_z_p_bz_d_64_unscaled:
8554 VIXL_UNIMPLEMENTED();
8555 break;
8556 case LDFF1H_z_p_bz_d_x32_scaled:
8557 VIXL_UNIMPLEMENTED();
8558 break;
8559 case LDFF1H_z_p_bz_d_x32_unscaled:
8560 VIXL_UNIMPLEMENTED();
8561 break;
8562 case LDFF1SB_z_p_ai_d:
8563 VIXL_UNIMPLEMENTED();
8564 break;
8565 case LDFF1SB_z_p_bz_d_64_unscaled:
8566 VIXL_UNIMPLEMENTED();
8567 break;
8568 case LDFF1SB_z_p_bz_d_x32_unscaled:
8569 VIXL_UNIMPLEMENTED();
8570 break;
8571 case LDFF1SH_z_p_ai_d:
8572 VIXL_UNIMPLEMENTED();
8573 break;
8574 case LDFF1SH_z_p_bz_d_64_scaled:
8575 VIXL_UNIMPLEMENTED();
8576 break;
8577 case LDFF1SH_z_p_bz_d_64_unscaled:
8578 VIXL_UNIMPLEMENTED();
8579 break;
8580 case LDFF1SH_z_p_bz_d_x32_scaled:
8581 VIXL_UNIMPLEMENTED();
8582 break;
8583 case LDFF1SH_z_p_bz_d_x32_unscaled:
8584 VIXL_UNIMPLEMENTED();
8585 break;
8586 case LDFF1SW_z_p_ai_d:
8587 VIXL_UNIMPLEMENTED();
8588 break;
8589 case LDFF1SW_z_p_bz_d_64_scaled:
8590 VIXL_UNIMPLEMENTED();
8591 break;
8592 case LDFF1SW_z_p_bz_d_64_unscaled:
8593 VIXL_UNIMPLEMENTED();
8594 break;
8595 case LDFF1SW_z_p_bz_d_x32_scaled:
8596 VIXL_UNIMPLEMENTED();
8597 break;
8598 case LDFF1SW_z_p_bz_d_x32_unscaled:
8599 VIXL_UNIMPLEMENTED();
8600 break;
8601 case LDFF1W_z_p_ai_d:
8602 VIXL_UNIMPLEMENTED();
8603 break;
8604 case LDFF1W_z_p_bz_d_64_scaled:
8605 VIXL_UNIMPLEMENTED();
8606 break;
8607 case LDFF1W_z_p_bz_d_64_unscaled:
8608 VIXL_UNIMPLEMENTED();
8609 break;
8610 case LDFF1W_z_p_bz_d_x32_scaled:
8611 VIXL_UNIMPLEMENTED();
8612 break;
8613 case LDFF1W_z_p_bz_d_x32_unscaled:
8614 VIXL_UNIMPLEMENTED();
8615 break;
8616 case PRFB_i_p_ai_d:
8617 VIXL_UNIMPLEMENTED();
8618 break;
8619 case PRFB_i_p_bz_d_64_scaled:
8620 VIXL_UNIMPLEMENTED();
8621 break;
8622 case PRFB_i_p_bz_d_x32_scaled:
8623 VIXL_UNIMPLEMENTED();
8624 break;
8625 case PRFD_i_p_ai_d:
8626 VIXL_UNIMPLEMENTED();
8627 break;
8628 case PRFD_i_p_bz_d_64_scaled:
8629 VIXL_UNIMPLEMENTED();
8630 break;
8631 case PRFD_i_p_bz_d_x32_scaled:
8632 VIXL_UNIMPLEMENTED();
8633 break;
8634 case PRFH_i_p_ai_d:
8635 VIXL_UNIMPLEMENTED();
8636 break;
8637 case PRFH_i_p_bz_d_64_scaled:
8638 VIXL_UNIMPLEMENTED();
8639 break;
8640 case PRFH_i_p_bz_d_x32_scaled:
8641 VIXL_UNIMPLEMENTED();
8642 break;
8643 case PRFW_i_p_ai_d:
8644 VIXL_UNIMPLEMENTED();
8645 break;
8646 case PRFW_i_p_bz_d_64_scaled:
8647 VIXL_UNIMPLEMENTED();
8648 break;
8649 case PRFW_i_p_bz_d_x32_scaled:
8650 VIXL_UNIMPLEMENTED();
8651 break;
8652 default:
8653 VIXL_UNIMPLEMENTED();
8654 break;
8655 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008656}
8657
8658void Simulator::VisitSVEMemContiguousLoad(const Instruction* instr) {
8659 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008660 switch (instr->Mask(SVEMemContiguousLoadMask)) {
8661 case LD1B_z_p_bi_u16:
8662 VIXL_UNIMPLEMENTED();
8663 break;
8664 case LD1B_z_p_bi_u32:
8665 VIXL_UNIMPLEMENTED();
8666 break;
8667 case LD1B_z_p_bi_u64:
8668 VIXL_UNIMPLEMENTED();
8669 break;
8670 case LD1B_z_p_bi_u8:
8671 VIXL_UNIMPLEMENTED();
8672 break;
8673 case LD1B_z_p_br_u16:
8674 VIXL_UNIMPLEMENTED();
8675 break;
8676 case LD1B_z_p_br_u32:
8677 VIXL_UNIMPLEMENTED();
8678 break;
8679 case LD1B_z_p_br_u64:
8680 VIXL_UNIMPLEMENTED();
8681 break;
8682 case LD1B_z_p_br_u8:
8683 VIXL_UNIMPLEMENTED();
8684 break;
8685 case LD1D_z_p_bi_u64:
8686 VIXL_UNIMPLEMENTED();
8687 break;
8688 case LD1D_z_p_br_u64:
8689 VIXL_UNIMPLEMENTED();
8690 break;
8691 case LD1H_z_p_bi_u16:
8692 VIXL_UNIMPLEMENTED();
8693 break;
8694 case LD1H_z_p_bi_u32:
8695 VIXL_UNIMPLEMENTED();
8696 break;
8697 case LD1H_z_p_bi_u64:
8698 VIXL_UNIMPLEMENTED();
8699 break;
8700 case LD1H_z_p_br_u16:
8701 VIXL_UNIMPLEMENTED();
8702 break;
8703 case LD1H_z_p_br_u32:
8704 VIXL_UNIMPLEMENTED();
8705 break;
8706 case LD1H_z_p_br_u64:
8707 VIXL_UNIMPLEMENTED();
8708 break;
8709 case LD1RQB_z_p_bi_u8:
8710 VIXL_UNIMPLEMENTED();
8711 break;
8712 case LD1RQB_z_p_br_contiguous:
8713 VIXL_UNIMPLEMENTED();
8714 break;
8715 case LD1RQD_z_p_bi_u64:
8716 VIXL_UNIMPLEMENTED();
8717 break;
8718 case LD1RQD_z_p_br_contiguous:
8719 VIXL_UNIMPLEMENTED();
8720 break;
8721 case LD1RQH_z_p_bi_u16:
8722 VIXL_UNIMPLEMENTED();
8723 break;
8724 case LD1RQH_z_p_br_contiguous:
8725 VIXL_UNIMPLEMENTED();
8726 break;
8727 case LD1RQW_z_p_bi_u32:
8728 VIXL_UNIMPLEMENTED();
8729 break;
8730 case LD1RQW_z_p_br_contiguous:
8731 VIXL_UNIMPLEMENTED();
8732 break;
8733 case LD1SB_z_p_bi_s16:
8734 VIXL_UNIMPLEMENTED();
8735 break;
8736 case LD1SB_z_p_bi_s32:
8737 VIXL_UNIMPLEMENTED();
8738 break;
8739 case LD1SB_z_p_bi_s64:
8740 VIXL_UNIMPLEMENTED();
8741 break;
8742 case LD1SB_z_p_br_s16:
8743 VIXL_UNIMPLEMENTED();
8744 break;
8745 case LD1SB_z_p_br_s32:
8746 VIXL_UNIMPLEMENTED();
8747 break;
8748 case LD1SB_z_p_br_s64:
8749 VIXL_UNIMPLEMENTED();
8750 break;
8751 case LD1SH_z_p_bi_s32:
8752 VIXL_UNIMPLEMENTED();
8753 break;
8754 case LD1SH_z_p_bi_s64:
8755 VIXL_UNIMPLEMENTED();
8756 break;
8757 case LD1SH_z_p_br_s32:
8758 VIXL_UNIMPLEMENTED();
8759 break;
8760 case LD1SH_z_p_br_s64:
8761 VIXL_UNIMPLEMENTED();
8762 break;
8763 case LD1SW_z_p_bi_s64:
8764 VIXL_UNIMPLEMENTED();
8765 break;
8766 case LD1SW_z_p_br_s64:
8767 VIXL_UNIMPLEMENTED();
8768 break;
8769 case LD1W_z_p_bi_u32:
8770 VIXL_UNIMPLEMENTED();
8771 break;
8772 case LD1W_z_p_bi_u64:
8773 VIXL_UNIMPLEMENTED();
8774 break;
8775 case LD1W_z_p_br_u32:
8776 VIXL_UNIMPLEMENTED();
8777 break;
8778 case LD1W_z_p_br_u64:
8779 VIXL_UNIMPLEMENTED();
8780 break;
8781 case LD2B_z_p_bi_contiguous:
8782 VIXL_UNIMPLEMENTED();
8783 break;
8784 case LD2B_z_p_br_contiguous:
8785 VIXL_UNIMPLEMENTED();
8786 break;
8787 case LD2D_z_p_bi_contiguous:
8788 VIXL_UNIMPLEMENTED();
8789 break;
8790 case LD2D_z_p_br_contiguous:
8791 VIXL_UNIMPLEMENTED();
8792 break;
8793 case LD2H_z_p_bi_contiguous:
8794 VIXL_UNIMPLEMENTED();
8795 break;
8796 case LD2H_z_p_br_contiguous:
8797 VIXL_UNIMPLEMENTED();
8798 break;
8799 case LD2W_z_p_bi_contiguous:
8800 VIXL_UNIMPLEMENTED();
8801 break;
8802 case LD2W_z_p_br_contiguous:
8803 VIXL_UNIMPLEMENTED();
8804 break;
8805 case LD3B_z_p_bi_contiguous:
8806 VIXL_UNIMPLEMENTED();
8807 break;
8808 case LD3B_z_p_br_contiguous:
8809 VIXL_UNIMPLEMENTED();
8810 break;
8811 case LD3D_z_p_bi_contiguous:
8812 VIXL_UNIMPLEMENTED();
8813 break;
8814 case LD3D_z_p_br_contiguous:
8815 VIXL_UNIMPLEMENTED();
8816 break;
8817 case LD3H_z_p_bi_contiguous:
8818 VIXL_UNIMPLEMENTED();
8819 break;
8820 case LD3H_z_p_br_contiguous:
8821 VIXL_UNIMPLEMENTED();
8822 break;
8823 case LD3W_z_p_bi_contiguous:
8824 VIXL_UNIMPLEMENTED();
8825 break;
8826 case LD3W_z_p_br_contiguous:
8827 VIXL_UNIMPLEMENTED();
8828 break;
8829 case LD4B_z_p_bi_contiguous:
8830 VIXL_UNIMPLEMENTED();
8831 break;
8832 case LD4B_z_p_br_contiguous:
8833 VIXL_UNIMPLEMENTED();
8834 break;
8835 case LD4D_z_p_bi_contiguous:
8836 VIXL_UNIMPLEMENTED();
8837 break;
8838 case LD4D_z_p_br_contiguous:
8839 VIXL_UNIMPLEMENTED();
8840 break;
8841 case LD4H_z_p_bi_contiguous:
8842 VIXL_UNIMPLEMENTED();
8843 break;
8844 case LD4H_z_p_br_contiguous:
8845 VIXL_UNIMPLEMENTED();
8846 break;
8847 case LD4W_z_p_bi_contiguous:
8848 VIXL_UNIMPLEMENTED();
8849 break;
8850 case LD4W_z_p_br_contiguous:
8851 VIXL_UNIMPLEMENTED();
8852 break;
8853 case LDFF1B_z_p_br_u16:
8854 VIXL_UNIMPLEMENTED();
8855 break;
8856 case LDFF1B_z_p_br_u32:
8857 VIXL_UNIMPLEMENTED();
8858 break;
8859 case LDFF1B_z_p_br_u64:
8860 VIXL_UNIMPLEMENTED();
8861 break;
8862 case LDFF1B_z_p_br_u8:
8863 VIXL_UNIMPLEMENTED();
8864 break;
8865 case LDFF1D_z_p_br_u64:
8866 VIXL_UNIMPLEMENTED();
8867 break;
8868 case LDFF1H_z_p_br_u16:
8869 VIXL_UNIMPLEMENTED();
8870 break;
8871 case LDFF1H_z_p_br_u32:
8872 VIXL_UNIMPLEMENTED();
8873 break;
8874 case LDFF1H_z_p_br_u64:
8875 VIXL_UNIMPLEMENTED();
8876 break;
8877 case LDFF1SB_z_p_br_s16:
8878 VIXL_UNIMPLEMENTED();
8879 break;
8880 case LDFF1SB_z_p_br_s32:
8881 VIXL_UNIMPLEMENTED();
8882 break;
8883 case LDFF1SB_z_p_br_s64:
8884 VIXL_UNIMPLEMENTED();
8885 break;
8886 case LDFF1SH_z_p_br_s32:
8887 VIXL_UNIMPLEMENTED();
8888 break;
8889 case LDFF1SH_z_p_br_s64:
8890 VIXL_UNIMPLEMENTED();
8891 break;
8892 case LDFF1SW_z_p_br_s64:
8893 VIXL_UNIMPLEMENTED();
8894 break;
8895 case LDFF1W_z_p_br_u32:
8896 VIXL_UNIMPLEMENTED();
8897 break;
8898 case LDFF1W_z_p_br_u64:
8899 VIXL_UNIMPLEMENTED();
8900 break;
8901 case LDNF1B_z_p_bi_u16:
8902 VIXL_UNIMPLEMENTED();
8903 break;
8904 case LDNF1B_z_p_bi_u32:
8905 VIXL_UNIMPLEMENTED();
8906 break;
8907 case LDNF1B_z_p_bi_u64:
8908 VIXL_UNIMPLEMENTED();
8909 break;
8910 case LDNF1B_z_p_bi_u8:
8911 VIXL_UNIMPLEMENTED();
8912 break;
8913 case LDNF1D_z_p_bi_u64:
8914 VIXL_UNIMPLEMENTED();
8915 break;
8916 case LDNF1H_z_p_bi_u16:
8917 VIXL_UNIMPLEMENTED();
8918 break;
8919 case LDNF1H_z_p_bi_u32:
8920 VIXL_UNIMPLEMENTED();
8921 break;
8922 case LDNF1H_z_p_bi_u64:
8923 VIXL_UNIMPLEMENTED();
8924 break;
8925 case LDNF1SB_z_p_bi_s16:
8926 VIXL_UNIMPLEMENTED();
8927 break;
8928 case LDNF1SB_z_p_bi_s32:
8929 VIXL_UNIMPLEMENTED();
8930 break;
8931 case LDNF1SB_z_p_bi_s64:
8932 VIXL_UNIMPLEMENTED();
8933 break;
8934 case LDNF1SH_z_p_bi_s32:
8935 VIXL_UNIMPLEMENTED();
8936 break;
8937 case LDNF1SH_z_p_bi_s64:
8938 VIXL_UNIMPLEMENTED();
8939 break;
8940 case LDNF1SW_z_p_bi_s64:
8941 VIXL_UNIMPLEMENTED();
8942 break;
8943 case LDNF1W_z_p_bi_u32:
8944 VIXL_UNIMPLEMENTED();
8945 break;
8946 case LDNF1W_z_p_bi_u64:
8947 VIXL_UNIMPLEMENTED();
8948 break;
8949 case LDNT1B_z_p_bi_contiguous:
8950 VIXL_UNIMPLEMENTED();
8951 break;
8952 case LDNT1B_z_p_br_contiguous:
8953 VIXL_UNIMPLEMENTED();
8954 break;
8955 case LDNT1D_z_p_bi_contiguous:
8956 VIXL_UNIMPLEMENTED();
8957 break;
8958 case LDNT1D_z_p_br_contiguous:
8959 VIXL_UNIMPLEMENTED();
8960 break;
8961 case LDNT1H_z_p_bi_contiguous:
8962 VIXL_UNIMPLEMENTED();
8963 break;
8964 case LDNT1H_z_p_br_contiguous:
8965 VIXL_UNIMPLEMENTED();
8966 break;
8967 case LDNT1W_z_p_bi_contiguous:
8968 VIXL_UNIMPLEMENTED();
8969 break;
8970 case LDNT1W_z_p_br_contiguous:
8971 VIXL_UNIMPLEMENTED();
8972 break;
8973 default:
8974 VIXL_UNIMPLEMENTED();
8975 break;
8976 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00008977}
8978
8979void Simulator::VisitSVEMemStore(const Instruction* instr) {
8980 USE(instr);
Jacob Bramleye546c4a2019-05-10 13:37:57 +01008981 if (instr->Mask(SVEMemStorePMask) == STR_p_bi) {
8982 SimPRegister& pt = ReadPRegister(instr->GetPt());
8983 uint64_t address = ReadXRegister(instr->GetRn());
8984 if (instr->Mask(0x003f1c00)) {
8985 // TODO: Support the VL multiplier.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008986 VIXL_UNIMPLEMENTED();
Jacob Bramleye546c4a2019-05-10 13:37:57 +01008987 }
8988 for (unsigned i = 0; i < GetPredicateLengthInBytes(); i++) {
8989 Memory::Write(address + i, pt.GetLane<uint8_t>(i));
8990 }
8991 } else if (instr->Mask(SVEMemStoreZMask) == STR_z_bi) {
8992 SimVRegister& zt = ReadVRegister(instr->GetRt());
8993 uint64_t address = ReadXRegister(instr->GetRn());
8994 if (instr->Mask(0x003f1c00)) {
8995 // TODO: Support the VL multiplier.
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00008996 VIXL_UNIMPLEMENTED();
Jacob Bramleye546c4a2019-05-10 13:37:57 +01008997 }
8998 for (unsigned i = 0; i < GetVectorLengthInBytes(); i++) {
8999 Memory::Write(address + i, zt.GetLane<uint8_t>(i));
9000 }
9001 } else {
9002 // TODO: This switch doesn't work because the mask needs to vary on a finer
9003 // granularity. Early implementations have already been pulled out, but we
9004 // need to re-organise the instruction groups.
9005 switch (instr->Mask(SVEMemStoreMask)) {
9006 case ST1B_z_p_ai_d:
9007 case ST1B_z_p_ai_s:
9008 case ST1B_z_p_bi:
9009 case ST1B_z_p_br:
9010 case ST1B_z_p_bz_d_64_unscaled:
9011 case ST1B_z_p_bz_d_x32_unscaled:
9012 case ST1B_z_p_bz_s_x32_unscaled:
9013 case ST1D_z_p_ai_d:
9014 case ST1D_z_p_bi:
9015 // TODO: fix encoding alias issue with enum above.
9016 // case ST1D_z_p_br:
9017 case ST1D_z_p_bz_d_64_scaled:
9018 case ST1D_z_p_bz_d_64_unscaled:
9019 case ST1D_z_p_bz_d_x32_scaled:
9020 case ST1D_z_p_bz_d_x32_unscaled:
9021 case ST1H_z_p_ai_d:
9022 case ST1H_z_p_ai_s:
9023 case ST1H_z_p_bi:
9024 case ST1H_z_p_br:
9025 case ST1H_z_p_bz_d_64_scaled:
9026 case ST1H_z_p_bz_d_64_unscaled:
9027 case ST1H_z_p_bz_d_x32_scaled:
9028 case ST1H_z_p_bz_d_x32_unscaled:
9029 case ST1H_z_p_bz_s_x32_scaled:
9030 case ST1H_z_p_bz_s_x32_unscaled:
9031 case ST1W_z_p_ai_d:
9032 case ST1W_z_p_ai_s:
9033 case ST1W_z_p_bi:
9034 case ST1W_z_p_br:
9035 case ST1W_z_p_bz_d_64_scaled:
9036 case ST1W_z_p_bz_d_64_unscaled:
9037 case ST1W_z_p_bz_d_x32_scaled:
9038 case ST1W_z_p_bz_d_x32_unscaled:
9039 case ST1W_z_p_bz_s_x32_scaled:
9040 case ST1W_z_p_bz_s_x32_unscaled:
9041 case ST2B_z_p_bi_contiguous:
9042 case ST2B_z_p_br_contiguous:
9043 case ST2D_z_p_bi_contiguous:
9044 case ST2D_z_p_br_contiguous:
9045 case ST2H_z_p_bi_contiguous:
9046 case ST2H_z_p_br_contiguous:
9047 case ST2W_z_p_bi_contiguous:
9048 case ST2W_z_p_br_contiguous:
9049 case ST3B_z_p_bi_contiguous:
9050 case ST3B_z_p_br_contiguous:
9051 case ST3D_z_p_bi_contiguous:
9052 case ST3D_z_p_br_contiguous:
9053 case ST3H_z_p_bi_contiguous:
9054 case ST3H_z_p_br_contiguous:
9055 case ST3W_z_p_bi_contiguous:
9056 case ST3W_z_p_br_contiguous:
9057 case ST4B_z_p_bi_contiguous:
9058 case ST4B_z_p_br_contiguous:
9059 case ST4D_z_p_bi_contiguous:
9060 case ST4D_z_p_br_contiguous:
9061 case ST4H_z_p_bi_contiguous:
9062 case ST4H_z_p_br_contiguous:
9063 case ST4W_z_p_bi_contiguous:
9064 case ST4W_z_p_br_contiguous:
9065 case STNT1B_z_p_bi_contiguous:
9066 case STNT1B_z_p_br_contiguous:
9067 case STNT1D_z_p_bi_contiguous:
9068 case STNT1D_z_p_br_contiguous:
9069 case STNT1H_z_p_bi_contiguous:
9070 case STNT1H_z_p_br_contiguous:
9071 case STNT1W_z_p_bi_contiguous:
9072 case STNT1W_z_p_br_contiguous:
9073 default:
9074 VIXL_UNIMPLEMENTED();
9075 break;
9076 }
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009077 }
Jacob Bramleye546c4a2019-05-10 13:37:57 +01009078 // TODO: LogWrite
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009079}
9080
9081void Simulator::VisitSVEMulIndex(const Instruction* instr) {
9082 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009083 switch (instr->Mask(SVEMulIndexMask)) {
9084 case SDOT_z_zzzi_d:
9085 VIXL_UNIMPLEMENTED();
9086 break;
9087 case SDOT_z_zzzi_s:
9088 VIXL_UNIMPLEMENTED();
9089 break;
9090 case UDOT_z_zzzi_d:
9091 VIXL_UNIMPLEMENTED();
9092 break;
9093 case UDOT_z_zzzi_s:
9094 VIXL_UNIMPLEMENTED();
9095 break;
9096 default:
9097 VIXL_UNIMPLEMENTED();
9098 break;
9099 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009100}
9101
9102void Simulator::VisitSVEPartitionBreak(const Instruction* instr) {
9103 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009104 switch (instr->Mask(SVEPartitionBreakMask)) {
9105 case BRKAS_p_p_p_z:
9106 VIXL_UNIMPLEMENTED();
9107 break;
9108 case BRKA_p_p_p:
9109 VIXL_UNIMPLEMENTED();
9110 break;
9111 case BRKBS_p_p_p_z:
9112 VIXL_UNIMPLEMENTED();
9113 break;
9114 case BRKB_p_p_p:
9115 VIXL_UNIMPLEMENTED();
9116 break;
9117 case BRKNS_p_p_pp:
9118 VIXL_UNIMPLEMENTED();
9119 break;
9120 case BRKN_p_p_pp:
9121 VIXL_UNIMPLEMENTED();
9122 break;
9123 default:
9124 VIXL_UNIMPLEMENTED();
9125 break;
9126 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009127}
9128
9129void Simulator::VisitSVEPermutePredicate(const Instruction* instr) {
9130 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009131 switch (instr->Mask(SVEPermutePredicateMask)) {
9132 case PUNPKHI_p_p:
9133 VIXL_UNIMPLEMENTED();
9134 break;
9135 case PUNPKLO_p_p:
9136 VIXL_UNIMPLEMENTED();
9137 break;
9138 case REV_p_p:
9139 VIXL_UNIMPLEMENTED();
9140 break;
9141 case TRN1_p_pp:
9142 VIXL_UNIMPLEMENTED();
9143 break;
9144 case TRN2_p_pp:
9145 VIXL_UNIMPLEMENTED();
9146 break;
9147 case UZP1_p_pp:
9148 VIXL_UNIMPLEMENTED();
9149 break;
9150 case UZP2_p_pp:
9151 VIXL_UNIMPLEMENTED();
9152 break;
9153 case ZIP1_p_pp:
9154 VIXL_UNIMPLEMENTED();
9155 break;
9156 case ZIP2_p_pp:
9157 VIXL_UNIMPLEMENTED();
9158 break;
9159 default:
9160 VIXL_UNIMPLEMENTED();
9161 break;
9162 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009163}
9164
9165void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
9166 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009167 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
9168 case EXT_z_zi_des:
9169 VIXL_UNIMPLEMENTED();
9170 break;
9171 default:
9172 VIXL_UNIMPLEMENTED();
9173 break;
9174 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009175}
9176
9177void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
9178 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009179 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
9180 case TRN1_z_zz:
9181 VIXL_UNIMPLEMENTED();
9182 break;
9183 case TRN2_z_zz:
9184 VIXL_UNIMPLEMENTED();
9185 break;
9186 case UZP1_z_zz:
9187 VIXL_UNIMPLEMENTED();
9188 break;
9189 case UZP2_z_zz:
9190 VIXL_UNIMPLEMENTED();
9191 break;
9192 case ZIP1_z_zz:
9193 VIXL_UNIMPLEMENTED();
9194 break;
9195 case ZIP2_z_zz:
9196 VIXL_UNIMPLEMENTED();
9197 break;
9198 default:
9199 VIXL_UNIMPLEMENTED();
9200 break;
9201 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009202}
9203
9204void Simulator::VisitSVEPermuteVectorPredicated(const Instruction* instr) {
9205 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009206 switch (instr->Mask(SVEPermuteVectorPredicatedMask)) {
9207 case CLASTA_r_p_z:
9208 VIXL_UNIMPLEMENTED();
9209 break;
9210 case CLASTA_v_p_z:
9211 VIXL_UNIMPLEMENTED();
9212 break;
9213 case CLASTA_z_p_zz:
9214 VIXL_UNIMPLEMENTED();
9215 break;
9216 case CLASTB_r_p_z:
9217 VIXL_UNIMPLEMENTED();
9218 break;
9219 case CLASTB_v_p_z:
9220 VIXL_UNIMPLEMENTED();
9221 break;
9222 case CLASTB_z_p_zz:
9223 VIXL_UNIMPLEMENTED();
9224 break;
9225 case COMPACT_z_p_z:
9226 VIXL_UNIMPLEMENTED();
9227 break;
9228 case CPY_z_p_r:
9229 VIXL_UNIMPLEMENTED();
9230 break;
9231 case CPY_z_p_v:
9232 VIXL_UNIMPLEMENTED();
9233 break;
9234 case LASTA_r_p_z:
9235 VIXL_UNIMPLEMENTED();
9236 break;
9237 case LASTA_v_p_z:
9238 VIXL_UNIMPLEMENTED();
9239 break;
9240 case LASTB_r_p_z:
9241 VIXL_UNIMPLEMENTED();
9242 break;
9243 case LASTB_v_p_z:
9244 VIXL_UNIMPLEMENTED();
9245 break;
9246 case RBIT_z_p_z:
9247 VIXL_UNIMPLEMENTED();
9248 break;
9249 case REVB_z_z:
9250 VIXL_UNIMPLEMENTED();
9251 break;
9252 case REVH_z_z:
9253 VIXL_UNIMPLEMENTED();
9254 break;
9255 case REVW_z_z:
9256 VIXL_UNIMPLEMENTED();
9257 break;
9258 case SPLICE_z_p_zz_des:
9259 VIXL_UNIMPLEMENTED();
9260 break;
9261 default:
9262 VIXL_UNIMPLEMENTED();
9263 break;
9264 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009265}
9266
9267void Simulator::VisitSVEPermuteVectorUnpredicated(const Instruction* instr) {
9268 USE(instr);
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01009269 SimVRegister& zd = ReadVRegister(instr->GetRd());
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009270 switch (instr->Mask(SVEPermuteVectorUnpredicatedMask)) {
9271 case DUP_z_r:
Jacob Bramley22023df2019-05-14 17:55:43 +01009272 dup_immediate(instr->GetSVEVectorFormat(),
9273 zd,
9274 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009275 break;
9276 case DUP_z_zi:
9277 VIXL_UNIMPLEMENTED();
9278 break;
9279 case INSR_z_r:
Jacob Bramley9d06c4d2019-05-13 18:15:06 +01009280 insr(instr->GetSVEVectorFormat(), zd, ReadXRegister(instr->GetRn()));
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009281 break;
9282 case INSR_z_v:
9283 VIXL_UNIMPLEMENTED();
9284 break;
9285 case REV_z_z:
9286 VIXL_UNIMPLEMENTED();
9287 break;
9288 case SUNPKHI_z_z:
9289 VIXL_UNIMPLEMENTED();
9290 break;
9291 case SUNPKLO_z_z:
9292 VIXL_UNIMPLEMENTED();
9293 break;
9294 case TBL_z_zz_1:
9295 VIXL_UNIMPLEMENTED();
9296 break;
9297 case UUNPKHI_z_z:
9298 VIXL_UNIMPLEMENTED();
9299 break;
9300 case UUNPKLO_z_z:
9301 VIXL_UNIMPLEMENTED();
9302 break;
9303 default:
9304 VIXL_UNIMPLEMENTED();
9305 break;
9306 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009307}
9308
9309void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
9310 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009311 switch (instr->Mask(SVEPredicateCountMask)) {
9312 case CNTP_r_p_p:
9313 VIXL_UNIMPLEMENTED();
9314 break;
9315 default:
9316 VIXL_UNIMPLEMENTED();
9317 break;
9318 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009319}
9320
9321void Simulator::VisitSVEPredicateLogicalOp(const Instruction* instr) {
9322 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009323 switch (instr->Mask(SVEPredicateLogicalOpMask)) {
9324 case ANDS_p_p_pp_z:
9325 VIXL_UNIMPLEMENTED();
9326 break;
9327 case AND_p_p_pp_z:
9328 VIXL_UNIMPLEMENTED();
9329 break;
9330 case BICS_p_p_pp_z:
9331 VIXL_UNIMPLEMENTED();
9332 break;
9333 case BIC_p_p_pp_z:
9334 VIXL_UNIMPLEMENTED();
9335 break;
9336 case EORS_p_p_pp_z:
9337 VIXL_UNIMPLEMENTED();
9338 break;
9339 case EOR_p_p_pp_z:
9340 VIXL_UNIMPLEMENTED();
9341 break;
9342 case NANDS_p_p_pp_z:
9343 VIXL_UNIMPLEMENTED();
9344 break;
9345 case NAND_p_p_pp_z:
9346 VIXL_UNIMPLEMENTED();
9347 break;
9348 case NORS_p_p_pp_z:
9349 VIXL_UNIMPLEMENTED();
9350 break;
9351 case NOR_p_p_pp_z:
9352 VIXL_UNIMPLEMENTED();
9353 break;
9354 case ORNS_p_p_pp_z:
9355 VIXL_UNIMPLEMENTED();
9356 break;
9357 case ORN_p_p_pp_z:
9358 VIXL_UNIMPLEMENTED();
9359 break;
9360 case ORRS_p_p_pp_z:
9361 VIXL_UNIMPLEMENTED();
9362 break;
9363 case ORR_p_p_pp_z:
9364 VIXL_UNIMPLEMENTED();
9365 break;
9366 case SEL_p_p_pp:
9367 VIXL_UNIMPLEMENTED();
9368 break;
9369 default:
9370 VIXL_UNIMPLEMENTED();
9371 break;
9372 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009373}
9374
9375void Simulator::VisitSVEPredicateMisc(const Instruction* instr) {
9376 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009377 switch (instr->Mask(SVEPredicateMiscMask)) {
9378 case PFALSE_p:
9379 VIXL_UNIMPLEMENTED();
9380 break;
9381 case PFIRST_p_p_p:
9382 VIXL_UNIMPLEMENTED();
9383 break;
9384 case PNEXT_p_p_p:
9385 VIXL_UNIMPLEMENTED();
9386 break;
9387 case PTEST_p_p:
9388 VIXL_UNIMPLEMENTED();
9389 break;
9390 case PTRUES_p_s:
9391 VIXL_UNIMPLEMENTED();
9392 break;
9393 case PTRUE_p_s:
9394 VIXL_UNIMPLEMENTED();
9395 break;
9396 case RDFFRS_p_p_f:
9397 VIXL_UNIMPLEMENTED();
9398 break;
9399 case RDFFR_p_f:
9400 VIXL_UNIMPLEMENTED();
9401 break;
9402 case RDFFR_p_p_f:
9403 VIXL_UNIMPLEMENTED();
9404 break;
9405 default:
9406 VIXL_UNIMPLEMENTED();
9407 break;
9408 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009409}
9410
9411void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
9412 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009413 switch (instr->Mask(SVEPropagateBreakMask)) {
9414 case BRKPAS_p_p_pp:
9415 VIXL_UNIMPLEMENTED();
9416 break;
9417 case BRKPA_p_p_pp:
9418 VIXL_UNIMPLEMENTED();
9419 break;
9420 case BRKPBS_p_p_pp:
9421 VIXL_UNIMPLEMENTED();
9422 break;
9423 case BRKPB_p_p_pp:
9424 VIXL_UNIMPLEMENTED();
9425 break;
9426 default:
9427 VIXL_UNIMPLEMENTED();
9428 break;
9429 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009430}
9431
9432void Simulator::VisitSVEStackAllocation(const Instruction* instr) {
9433 USE(instr);
Jacob Bramleye546c4a2019-05-10 13:37:57 +01009434 int64_t scale = instr->GetImmSVEVLScale();
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009435 switch (instr->Mask(SVEStackAllocationMask)) {
Jacob Bramleye546c4a2019-05-10 13:37:57 +01009436 case ADDPL_r_ri: { // Rd = Rn + (PL * scale)
9437 VIXL_UNIMPLEMENTED(); // Untested.
9438 uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
9439 WriteXRegister(instr->GetRd(),
9440 base + GetPredicateLengthInBytes() * scale,
9441 LogRegWrites,
9442 Reg31IsStackPointer);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009443 break;
Jacob Bramleye546c4a2019-05-10 13:37:57 +01009444 }
9445 case ADDVL_r_ri: { // Rd = Rn + (VL * scale)
9446 VIXL_UNIMPLEMENTED(); // Untested.
9447 uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
9448 WriteXRegister(instr->GetRd(),
9449 base + GetVectorLengthInBytes() * scale,
9450 LogRegWrites,
9451 Reg31IsStackPointer);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009452 break;
Jacob Bramleye546c4a2019-05-10 13:37:57 +01009453 }
9454 case RDVL_r_i: // Rd = VL * scale
9455 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009456 break;
9457 default:
9458 VIXL_UNIMPLEMENTED();
9459 break;
9460 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009461}
9462
9463void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
9464 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009465 switch (instr->Mask(SVEVectorSelectMask)) {
9466 case SEL_z_p_zz:
9467 VIXL_UNIMPLEMENTED();
9468 break;
9469 default:
9470 VIXL_UNIMPLEMENTED();
9471 break;
9472 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009473}
9474
9475void Simulator::VisitSVEWriteFFR(const Instruction* instr) {
9476 USE(instr);
Martyn Capewelle91d1ec2019-01-31 14:33:35 +00009477 switch (instr->Mask(SVEWriteFFRMask)) {
9478 case SETFFR_f:
9479 VIXL_UNIMPLEMENTED();
9480 break;
9481 case WRFFR_f_p:
9482 VIXL_UNIMPLEMENTED();
9483 break;
9484 default:
9485 VIXL_UNIMPLEMENTED();
9486 break;
9487 }
Martyn Capewellb545d6c2018-11-08 18:14:23 +00009488}
Alexandre Ramesd3832962016-07-04 15:03:43 +01009489
9490void Simulator::DoUnreachable(const Instruction* instr) {
9491 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
9492 (instr->GetImmException() == kUnreachableOpcode));
9493
9494 fprintf(stream_,
9495 "Hit UNREACHABLE marker at pc=%p.\n",
9496 reinterpret_cast<const void*>(instr));
9497 abort();
9498}
9499
9500
9501void Simulator::DoTrace(const Instruction* instr) {
9502 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
9503 (instr->GetImmException() == kTraceOpcode));
9504
9505 // Read the arguments encoded inline in the instruction stream.
9506 uint32_t parameters;
9507 uint32_t command;
9508
9509 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
9510 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
9511 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
9512
9513 switch (command) {
9514 case TRACE_ENABLE:
9515 SetTraceParameters(GetTraceParameters() | parameters);
9516 break;
9517 case TRACE_DISABLE:
9518 SetTraceParameters(GetTraceParameters() & ~parameters);
9519 break;
9520 default:
9521 VIXL_UNREACHABLE();
9522 }
9523
9524 WritePc(instr->GetInstructionAtOffset(kTraceLength));
9525}
9526
9527
9528void Simulator::DoLog(const Instruction* instr) {
9529 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
9530 (instr->GetImmException() == kLogOpcode));
9531
9532 // Read the arguments encoded inline in the instruction stream.
9533 uint32_t parameters;
9534
9535 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
9536 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
9537
9538 // We don't support a one-shot LOG_DISASM.
9539 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
9540 // Print the requested information.
9541 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
9542 if (parameters & LOG_REGS) PrintRegisters();
9543 if (parameters & LOG_VREGS) PrintVRegisters();
9544
9545 WritePc(instr->GetInstructionAtOffset(kLogLength));
9546}
9547
9548
9549void Simulator::DoPrintf(const Instruction* instr) {
9550 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
9551 (instr->GetImmException() == kPrintfOpcode));
9552
9553 // Read the arguments encoded inline in the instruction stream.
9554 uint32_t arg_count;
9555 uint32_t arg_pattern_list;
9556 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
9557 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
9558 memcpy(&arg_pattern_list,
9559 instr + kPrintfArgPatternListOffset,
9560 sizeof(arg_pattern_list));
9561
9562 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
9563 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
9564
9565 // We need to call the host printf function with a set of arguments defined by
9566 // arg_pattern_list. Because we don't know the types and sizes of the
9567 // arguments, this is very difficult to do in a robust and portable way. To
9568 // work around the problem, we pick apart the format string, and print one
9569 // format placeholder at a time.
9570
9571 // Allocate space for the format string. We take a copy, so we can modify it.
9572 // Leave enough space for one extra character per expected argument (plus the
9573 // '\0' termination).
9574 const char* format_base = ReadRegister<const char*>(0);
9575 VIXL_ASSERT(format_base != NULL);
9576 size_t length = strlen(format_base) + 1;
9577 char* const format = new char[length + arg_count];
9578
9579 // A list of chunks, each with exactly one format placeholder.
9580 const char* chunks[kPrintfMaxArgCount];
9581
9582 // Copy the format string and search for format placeholders.
9583 uint32_t placeholder_count = 0;
9584 char* format_scratch = format;
9585 for (size_t i = 0; i < length; i++) {
9586 if (format_base[i] != '%') {
9587 *format_scratch++ = format_base[i];
9588 } else {
9589 if (format_base[i + 1] == '%') {
9590 // Ignore explicit "%%" sequences.
9591 *format_scratch++ = format_base[i];
9592 i++;
9593 // Chunks after the first are passed as format strings to printf, so we
9594 // need to escape '%' characters in those chunks.
9595 if (placeholder_count > 0) *format_scratch++ = format_base[i];
9596 } else {
9597 VIXL_CHECK(placeholder_count < arg_count);
9598 // Insert '\0' before placeholders, and store their locations.
9599 *format_scratch++ = '\0';
9600 chunks[placeholder_count++] = format_scratch;
9601 *format_scratch++ = format_base[i];
9602 }
9603 }
9604 }
9605 VIXL_CHECK(placeholder_count == arg_count);
9606
9607 // Finally, call printf with each chunk, passing the appropriate register
9608 // argument. Normally, printf returns the number of bytes transmitted, so we
9609 // can emulate a single printf call by adding the result from each chunk. If
9610 // any call returns a negative (error) value, though, just return that value.
9611
9612 printf("%s", clr_printf);
9613
9614 // Because '\0' is inserted before each placeholder, the first string in
9615 // 'format' contains no format placeholders and should be printed literally.
9616 int result = printf("%s", format);
9617 int pcs_r = 1; // Start at x1. x0 holds the format string.
9618 int pcs_f = 0; // Start at d0.
9619 if (result >= 0) {
9620 for (uint32_t i = 0; i < placeholder_count; i++) {
9621 int part_result = -1;
9622
9623 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
9624 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
9625 switch (arg_pattern) {
9626 case kPrintfArgW:
9627 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
9628 break;
9629 case kPrintfArgX:
9630 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
9631 break;
9632 case kPrintfArgD:
9633 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
9634 break;
9635 default:
9636 VIXL_UNREACHABLE();
9637 }
9638
9639 if (part_result < 0) {
9640 // Handle error values.
9641 result = part_result;
9642 break;
9643 }
9644
9645 result += part_result;
9646 }
9647 }
9648
9649 printf("%s", clr_normal);
9650
9651 // Printf returns its result in x0 (just like the C library's printf).
9652 WriteXRegister(0, result);
9653
9654 // The printf parameters are inlined in the code, so skip them.
9655 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
9656
9657 // Set LR as if we'd just called a native printf function.
9658 WriteLr(ReadPc());
9659
9660 delete[] format;
9661}
9662
Alexandre Rames064e02d2016-07-12 11:53:13 +01009663
Alexandre Ramesca73ba02016-07-28 09:16:03 +01009664#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +01009665void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +01009666 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +01009667 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
9668 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +01009669 uintptr_t call_wrapper_address =
9670 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
9671 uintptr_t function_address =
9672 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames62799612017-02-05 20:22:52 -08009673 RuntimeCallType call_type = static_cast<RuntimeCallType>(
9674 Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset));
Alexandre Rames064e02d2016-07-12 11:53:13 +01009675 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +01009676 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames62799612017-02-05 20:22:52 -08009677
9678 if (call_type == kCallRuntime) {
9679 WriteRegister(kLinkRegCode,
9680 instr->GetInstructionAtOffset(kRuntimeCallLength));
9681 }
Alexandre Rames0d2a3d52016-08-15 14:24:44 +01009682 runtime_call_wrapper(this, function_address);
Alexandre Rames62799612017-02-05 20:22:52 -08009683 // Read the return address from `lr` and write it into `pc`.
9684 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
Alexandre Rames064e02d2016-07-12 11:53:13 +01009685}
9686#else
9687void Simulator::DoRuntimeCall(const Instruction* instr) {
9688 USE(instr);
9689 VIXL_UNREACHABLE();
9690}
9691#endif
9692
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01009693
9694void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
9695 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
9696
9697 typedef ConfigureCPUFeaturesElementType ElementType;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +01009698 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01009699 std::numeric_limits<ElementType>::max());
9700
9701 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
9702
9703 size_t element_size = sizeof(ElementType);
9704 size_t offset = kConfigureCPUFeaturesListOffset;
9705
9706 // Read the kNone-terminated list of features.
9707 CPUFeatures parameters;
9708 while (true) {
9709 ElementType feature = Memory::Read<ElementType>(instr + offset);
9710 offset += element_size;
Jacob Bramleyfdf332a2018-09-17 11:17:54 +01009711 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +01009712 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
9713 }
9714
9715 switch (instr->GetImmException()) {
9716 case kSetCPUFeaturesOpcode:
9717 SetCPUFeatures(parameters);
9718 break;
9719 case kEnableCPUFeaturesOpcode:
9720 GetCPUFeatures()->Combine(parameters);
9721 break;
9722 case kDisableCPUFeaturesOpcode:
9723 GetCPUFeatures()->Remove(parameters);
9724 break;
9725 default:
9726 VIXL_UNREACHABLE();
9727 break;
9728 }
9729
9730 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
9731}
9732
9733
9734void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
9735 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
9736 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
9737 USE(instr);
9738
9739 saved_cpu_features_.push_back(*GetCPUFeatures());
9740}
9741
9742
9743void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
9744 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
9745 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
9746 USE(instr);
9747
9748 SetCPUFeatures(saved_cpu_features_.back());
9749 saved_cpu_features_.pop_back();
9750}
9751
9752
Alexandre Ramesd3832962016-07-04 15:03:43 +01009753} // namespace aarch64
9754} // namespace vixl
9755
Pierre Langlois1e85b7f2016-08-05 14:20:36 +01009756#endif // VIXL_INCLUDE_SIMULATOR_AARCH64