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