1 // 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
27 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
28
29 #include <errno.h>
30 #include <unistd.h>
31
32 #include <cmath>
33 #include <cstring>
34 #include <limits>
35
36 #include "simulator-aarch64.h"
37
38 namespace vixl {
39 namespace aarch64 {
40
41 using vixl::internal::SimFloat16;
42
43 const Instruction* Simulator::kEndOfSimAddress = NULL;
44
SetBits(int msb,int lsb,uint32_t bits)45 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
46 int width = msb - lsb + 1;
47 VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
48
49 bits <<= lsb;
50 uint32_t mask = ((1 << width) - 1) << lsb;
51 VIXL_ASSERT((mask & write_ignore_mask_) == 0);
52
53 value_ = (value_ & ~mask) | (bits & mask);
54 }
55
56
DefaultValueFor(SystemRegister id)57 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
58 switch (id) {
59 case NZCV:
60 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
61 case FPCR:
62 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
63 default:
64 VIXL_UNREACHABLE();
65 return SimSystemRegister();
66 }
67 }
68
69
Simulator(Decoder * decoder,FILE * stream,SimStack::Allocated stack)70 Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack)
71 : memory_(std::move(stack)),
72 movprfx_(NULL),
73 cpu_features_auditor_(decoder, CPUFeatures::All()) {
74 // Ensure that shift operations act as the simulator expects.
75 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
76 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
77
78 // Set up a placeholder pipe for CanReadMemory.
79 VIXL_CHECK(pipe(placeholder_pipe_fd_) == 0);
80
81 // Set up the decoder.
82 decoder_ = decoder;
83 decoder_->AppendVisitor(this);
84
85 stream_ = stream;
86
87 print_disasm_ = new PrintDisassembler(stream_);
88 // The Simulator and Disassembler share the same available list, held by the
89 // auditor. The Disassembler only annotates instructions with features that
90 // are _not_ available, so registering the auditor should have no effect
91 // unless the simulator is about to abort (due to missing features). In
92 // practice, this means that with trace enabled, the simulator will crash just
93 // after the disassembler prints the instruction, with the missing features
94 // enumerated.
95 print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
96
97 SetColouredTrace(false);
98 trace_parameters_ = LOG_NONE;
99
100 // We have to configure the SVE vector register length before calling
101 // ResetState().
102 SetVectorLengthInBits(kZRegMinSize);
103
104 ResetState();
105
106 // Print a warning about exclusive-access instructions, but only the first
107 // time they are encountered. This warning can be silenced using
108 // SilenceExclusiveAccessWarning().
109 print_exclusive_access_warning_ = true;
110
111 guard_pages_ = false;
112
113 // Initialize the common state of RNDR and RNDRRS.
114 uint16_t seed[3] = {11, 22, 33};
115 VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));
116 memcpy(rand_state_, seed, sizeof(rand_state_));
117
118 // Initialize all bits of pseudo predicate register to true.
119 LogicPRegister ones(pregister_all_true_);
120 ones.SetAllBits();
121 }
122
ResetSystemRegisters()123 void Simulator::ResetSystemRegisters() {
124 // Reset the system registers.
125 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
126 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
127 ResetFFR();
128 }
129
ResetRegisters()130 void Simulator::ResetRegisters() {
131 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
132 WriteXRegister(i, 0xbadbeef);
133 }
134 // Returning to address 0 exits the Simulator.
135 WriteLr(kEndOfSimAddress);
136 }
137
ResetVRegisters()138 void Simulator::ResetVRegisters() {
139 // Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
140 VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
141 int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
142 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
143 VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
144 vregisters_[i].NotifyAccessAsZ();
145 for (int lane = 0; lane < lane_count; lane++) {
146 // Encode the register number and (D-sized) lane into each NaN, to
147 // make them easier to trace.
148 uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
149 (0x0000000000000001 * lane);
150 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
151 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
152 vregisters_[i].Insert(lane, nan_bits);
153 }
154 }
155 }
156
ResetPRegisters()157 void Simulator::ResetPRegisters() {
158 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
159 int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
160 // Ensure the register configuration fits in this bit encoding.
161 VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
162 VIXL_ASSERT(lane_count <= UINT8_MAX);
163 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
164 VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
165 for (int lane = 0; lane < lane_count; lane++) {
166 // Encode the register number and (H-sized) lane into each lane slot.
167 uint16_t bits = (0x0100 * lane) | i;
168 pregisters_[i].Insert(lane, bits);
169 }
170 }
171 }
172
ResetFFR()173 void Simulator::ResetFFR() {
174 VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
175 int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
176 ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
177 }
178
ResetState()179 void Simulator::ResetState() {
180 ResetSystemRegisters();
181 ResetRegisters();
182 ResetVRegisters();
183 ResetPRegisters();
184
185 WriteSp(memory_.GetStack().GetBase());
186
187 pc_ = NULL;
188 pc_modified_ = false;
189
190 // BTI state.
191 btype_ = DefaultBType;
192 next_btype_ = DefaultBType;
193 }
194
SetVectorLengthInBits(unsigned vector_length)195 void Simulator::SetVectorLengthInBits(unsigned vector_length) {
196 VIXL_ASSERT((vector_length >= kZRegMinSize) &&
197 (vector_length <= kZRegMaxSize));
198 VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
199 vector_length_ = vector_length;
200
201 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
202 vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
203 }
204 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
205 pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
206 }
207
208 ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
209
210 ResetVRegisters();
211 ResetPRegisters();
212 ResetFFR();
213 }
214
~Simulator()215 Simulator::~Simulator() {
216 // The decoder may outlive the simulator.
217 decoder_->RemoveVisitor(print_disasm_);
218 delete print_disasm_;
219 close(placeholder_pipe_fd_[0]);
220 close(placeholder_pipe_fd_[1]);
221 }
222
223
Run()224 void Simulator::Run() {
225 // Flush any written registers before executing anything, so that
226 // manually-set registers are logged _before_ the first instruction.
227 LogAllWrittenRegisters();
228
229 while (pc_ != kEndOfSimAddress) {
230 ExecuteInstruction();
231 }
232 }
233
234
RunFrom(const Instruction * first)235 void Simulator::RunFrom(const Instruction* first) {
236 WritePc(first, NoBranchLog);
237 Run();
238 }
239
240
241 // clang-format off
242 const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
243 "x6", "x7", "x8", "x9", "x10", "x11",
244 "x12", "x13", "x14", "x15", "x16", "x17",
245 "x18", "x19", "x20", "x21", "x22", "x23",
246 "x24", "x25", "x26", "x27", "x28", "x29",
247 "lr", "xzr", "sp"};
248
249 const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
250 "w6", "w7", "w8", "w9", "w10", "w11",
251 "w12", "w13", "w14", "w15", "w16", "w17",
252 "w18", "w19", "w20", "w21", "w22", "w23",
253 "w24", "w25", "w26", "w27", "w28", "w29",
254 "w30", "wzr", "wsp"};
255
256 const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",
257 "b6", "b7", "b8", "b9", "b10", "b11",
258 "b12", "b13", "b14", "b15", "b16", "b17",
259 "b18", "b19", "b20", "b21", "b22", "b23",
260 "b24", "b25", "b26", "b27", "b28", "b29",
261 "b30", "b31"};
262
263 const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
264 "h6", "h7", "h8", "h9", "h10", "h11",
265 "h12", "h13", "h14", "h15", "h16", "h17",
266 "h18", "h19", "h20", "h21", "h22", "h23",
267 "h24", "h25", "h26", "h27", "h28", "h29",
268 "h30", "h31"};
269
270 const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
271 "s6", "s7", "s8", "s9", "s10", "s11",
272 "s12", "s13", "s14", "s15", "s16", "s17",
273 "s18", "s19", "s20", "s21", "s22", "s23",
274 "s24", "s25", "s26", "s27", "s28", "s29",
275 "s30", "s31"};
276
277 const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
278 "d6", "d7", "d8", "d9", "d10", "d11",
279 "d12", "d13", "d14", "d15", "d16", "d17",
280 "d18", "d19", "d20", "d21", "d22", "d23",
281 "d24", "d25", "d26", "d27", "d28", "d29",
282 "d30", "d31"};
283
284 const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
285 "v6", "v7", "v8", "v9", "v10", "v11",
286 "v12", "v13", "v14", "v15", "v16", "v17",
287 "v18", "v19", "v20", "v21", "v22", "v23",
288 "v24", "v25", "v26", "v27", "v28", "v29",
289 "v30", "v31"};
290
291 const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
292 "z6", "z7", "z8", "z9", "z10", "z11",
293 "z12", "z13", "z14", "z15", "z16", "z17",
294 "z18", "z19", "z20", "z21", "z22", "z23",
295 "z24", "z25", "z26", "z27", "z28", "z29",
296 "z30", "z31"};
297
298 const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
299 "p6", "p7", "p8", "p9", "p10", "p11",
300 "p12", "p13", "p14", "p15"};
301 // clang-format on
302
303
WRegNameForCode(unsigned code,Reg31Mode mode)304 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
305 // If the code represents the stack pointer, index the name after zr.
306 if ((code == kSPRegInternalCode) ||
307 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
308 code = kZeroRegCode + 1;
309 }
310 VIXL_ASSERT(code < ArrayLength(wreg_names));
311 return wreg_names[code];
312 }
313
314
XRegNameForCode(unsigned code,Reg31Mode mode)315 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
316 // If the code represents the stack pointer, index the name after zr.
317 if ((code == kSPRegInternalCode) ||
318 ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
319 code = kZeroRegCode + 1;
320 }
321 VIXL_ASSERT(code < ArrayLength(xreg_names));
322 return xreg_names[code];
323 }
324
325
BRegNameForCode(unsigned code)326 const char* Simulator::BRegNameForCode(unsigned code) {
327 VIXL_ASSERT(code < kNumberOfVRegisters);
328 return breg_names[code];
329 }
330
331
HRegNameForCode(unsigned code)332 const char* Simulator::HRegNameForCode(unsigned code) {
333 VIXL_ASSERT(code < kNumberOfVRegisters);
334 return hreg_names[code];
335 }
336
337
SRegNameForCode(unsigned code)338 const char* Simulator::SRegNameForCode(unsigned code) {
339 VIXL_ASSERT(code < kNumberOfVRegisters);
340 return sreg_names[code];
341 }
342
343
DRegNameForCode(unsigned code)344 const char* Simulator::DRegNameForCode(unsigned code) {
345 VIXL_ASSERT(code < kNumberOfVRegisters);
346 return dreg_names[code];
347 }
348
349
VRegNameForCode(unsigned code)350 const char* Simulator::VRegNameForCode(unsigned code) {
351 VIXL_ASSERT(code < kNumberOfVRegisters);
352 return vreg_names[code];
353 }
354
355
ZRegNameForCode(unsigned code)356 const char* Simulator::ZRegNameForCode(unsigned code) {
357 VIXL_ASSERT(code < kNumberOfZRegisters);
358 return zreg_names[code];
359 }
360
361
PRegNameForCode(unsigned code)362 const char* Simulator::PRegNameForCode(unsigned code) {
363 VIXL_ASSERT(code < kNumberOfPRegisters);
364 return preg_names[code];
365 }
366
ExpandToSimVRegister(const SimPRegister & pg)367 SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
368 SimVRegister ones, result;
369 dup_immediate(kFormatVnB, ones, 0xff);
370 mov_zeroing(kFormatVnB, result, pg, ones);
371 return result;
372 }
373
ExtractFromSimVRegister(VectorFormat vform,SimPRegister & pd,SimVRegister vreg)374 void Simulator::ExtractFromSimVRegister(VectorFormat vform,
375 SimPRegister& pd,
376 SimVRegister vreg) {
377 SimVRegister zero;
378 dup_immediate(kFormatVnB, zero, 0);
379 SVEIntCompareVectorsHelper(ne,
380 vform,
381 pd,
382 GetPTrue(),
383 vreg,
384 zero,
385 false,
386 LeaveFlags);
387 }
388
389 #define COLOUR(colour_code) "\033[0;" colour_code "m"
390 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
391 #define COLOUR_HIGHLIGHT "\033[43m"
392 #define NORMAL ""
393 #define GREY "30"
394 #define RED "31"
395 #define GREEN "32"
396 #define YELLOW "33"
397 #define BLUE "34"
398 #define MAGENTA "35"
399 #define CYAN "36"
400 #define WHITE "37"
SetColouredTrace(bool value)401 void Simulator::SetColouredTrace(bool value) {
402 coloured_trace_ = value;
403
404 clr_normal = value ? COLOUR(NORMAL) : "";
405 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
406 clr_flag_value = value ? COLOUR(NORMAL) : "";
407 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
408 clr_reg_value = value ? COLOUR(CYAN) : "";
409 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
410 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
411 clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
412 clr_preg_value = value ? COLOUR(GREEN) : "";
413 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
414 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
415 clr_warning_message = value ? COLOUR(YELLOW) : "";
416 clr_printf = value ? COLOUR(GREEN) : "";
417 clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
418
419 if (value) {
420 print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
421 print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
422 } else {
423 print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
424 print_disasm_->SetCPUFeaturesSuffix("");
425 }
426 }
427
428
SetTraceParameters(int parameters)429 void Simulator::SetTraceParameters(int parameters) {
430 bool disasm_before = trace_parameters_ & LOG_DISASM;
431 trace_parameters_ = parameters;
432 bool disasm_after = trace_parameters_ & LOG_DISASM;
433
434 if (disasm_before != disasm_after) {
435 if (disasm_after) {
436 decoder_->InsertVisitorBefore(print_disasm_, this);
437 } else {
438 decoder_->RemoveVisitor(print_disasm_);
439 }
440 }
441 }
442
443
444 // Helpers ---------------------------------------------------------------------
AddWithCarry(unsigned reg_size,bool set_flags,uint64_t left,uint64_t right,int carry_in)445 uint64_t Simulator::AddWithCarry(unsigned reg_size,
446 bool set_flags,
447 uint64_t left,
448 uint64_t right,
449 int carry_in) {
450 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
451 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
452
453 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
454 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
455 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
456
457 left &= reg_mask;
458 right &= reg_mask;
459 uint64_t result = (left + right + carry_in) & reg_mask;
460
461 if (set_flags) {
462 ReadNzcv().SetN(CalcNFlag(result, reg_size));
463 ReadNzcv().SetZ(CalcZFlag(result));
464
465 // Compute the C flag by comparing the result to the max unsigned integer.
466 uint64_t max_uint_2op = max_uint - carry_in;
467 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
468 ReadNzcv().SetC(C ? 1 : 0);
469
470 // Overflow iff the sign bit is the same for the two inputs and different
471 // for the result.
472 uint64_t left_sign = left & sign_mask;
473 uint64_t right_sign = right & sign_mask;
474 uint64_t result_sign = result & sign_mask;
475 bool V = (left_sign == right_sign) && (left_sign != result_sign);
476 ReadNzcv().SetV(V ? 1 : 0);
477
478 LogSystemRegister(NZCV);
479 }
480 return result;
481 }
482
483
ShiftOperand(unsigned reg_size,uint64_t uvalue,Shift shift_type,unsigned amount) const484 int64_t Simulator::ShiftOperand(unsigned reg_size,
485 uint64_t uvalue,
486 Shift shift_type,
487 unsigned amount) const {
488 VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
489 (reg_size == kSRegSize) || (reg_size == kDRegSize));
490 if (amount > 0) {
491 uint64_t mask = GetUintMask(reg_size);
492 bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
493 // The behavior is undefined in c++ if the shift amount greater than or
494 // equal to the register lane size. Work out the shifted result based on
495 // architectural behavior before performing the c++ type shfit operations.
496 switch (shift_type) {
497 case LSL:
498 if (amount >= reg_size) {
499 return UINT64_C(0);
500 }
501 uvalue <<= amount;
502 break;
503 case LSR:
504 if (amount >= reg_size) {
505 return UINT64_C(0);
506 }
507 uvalue >>= amount;
508 break;
509 case ASR:
510 if (amount >= reg_size) {
511 return is_negative ? ~UINT64_C(0) : UINT64_C(0);
512 }
513 uvalue >>= amount;
514 if (is_negative) {
515 // Simulate sign-extension to 64 bits.
516 uvalue |= ~UINT64_C(0) << (reg_size - amount);
517 }
518 break;
519 case ROR: {
520 uvalue = RotateRight(uvalue, amount, reg_size);
521 break;
522 }
523 default:
524 VIXL_UNIMPLEMENTED();
525 return 0;
526 }
527 uvalue &= mask;
528 }
529
530 int64_t result;
531 memcpy(&result, &uvalue, sizeof(result));
532 return result;
533 }
534
535
ExtendValue(unsigned reg_size,int64_t value,Extend extend_type,unsigned left_shift) const536 int64_t Simulator::ExtendValue(unsigned reg_size,
537 int64_t value,
538 Extend extend_type,
539 unsigned left_shift) const {
540 switch (extend_type) {
541 case UXTB:
542 value &= kByteMask;
543 break;
544 case UXTH:
545 value &= kHalfWordMask;
546 break;
547 case UXTW:
548 value &= kWordMask;
549 break;
550 case SXTB:
551 value &= kByteMask;
552 if ((value & 0x80) != 0) {
553 value |= ~UINT64_C(0) << 8;
554 }
555 break;
556 case SXTH:
557 value &= kHalfWordMask;
558 if ((value & 0x8000) != 0) {
559 value |= ~UINT64_C(0) << 16;
560 }
561 break;
562 case SXTW:
563 value &= kWordMask;
564 if ((value & 0x80000000) != 0) {
565 value |= ~UINT64_C(0) << 32;
566 }
567 break;
568 case UXTX:
569 case SXTX:
570 break;
571 default:
572 VIXL_UNREACHABLE();
573 }
574 return ShiftOperand(reg_size, value, LSL, left_shift);
575 }
576
577
FPCompare(double val0,double val1,FPTrapFlags trap)578 void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
579 AssertSupportedFPCR();
580
581 // TODO: This assumes that the C++ implementation handles comparisons in the
582 // way that we expect (as per AssertSupportedFPCR()).
583 bool process_exception = false;
584 if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
585 ReadNzcv().SetRawValue(FPUnorderedFlag);
586 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
587 (trap == EnableTrap)) {
588 process_exception = true;
589 }
590 } else if (val0 < val1) {
591 ReadNzcv().SetRawValue(FPLessThanFlag);
592 } else if (val0 > val1) {
593 ReadNzcv().SetRawValue(FPGreaterThanFlag);
594 } else if (val0 == val1) {
595 ReadNzcv().SetRawValue(FPEqualFlag);
596 } else {
597 VIXL_UNREACHABLE();
598 }
599 LogSystemRegister(NZCV);
600 if (process_exception) FPProcessException();
601 }
602
603
ComputeMemOperandAddress(const MemOperand & mem_op) const604 uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
605 VIXL_ASSERT(mem_op.IsValid());
606 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
607 if (mem_op.IsImmediateOffset()) {
608 return base + mem_op.GetOffset();
609 } else {
610 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
611 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
612 unsigned shift_amount = mem_op.GetShiftAmount();
613 if (mem_op.GetShift() != NO_SHIFT) {
614 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
615 }
616 if (mem_op.GetExtend() != NO_EXTEND) {
617 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
618 }
619 return static_cast<uint64_t>(base + offset);
620 }
621 }
622
623
GetPrintRegisterFormatForSize(unsigned reg_size,unsigned lane_size)624 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
625 unsigned reg_size, unsigned lane_size) {
626 VIXL_ASSERT(reg_size >= lane_size);
627
628 uint32_t format = 0;
629 if (reg_size != lane_size) {
630 switch (reg_size) {
631 default:
632 VIXL_UNREACHABLE();
633 break;
634 case kQRegSizeInBytes:
635 format = kPrintRegAsQVector;
636 break;
637 case kDRegSizeInBytes:
638 format = kPrintRegAsDVector;
639 break;
640 }
641 }
642
643 switch (lane_size) {
644 default:
645 VIXL_UNREACHABLE();
646 break;
647 case kQRegSizeInBytes:
648 format |= kPrintReg1Q;
649 break;
650 case kDRegSizeInBytes:
651 format |= kPrintReg1D;
652 break;
653 case kSRegSizeInBytes:
654 format |= kPrintReg1S;
655 break;
656 case kHRegSizeInBytes:
657 format |= kPrintReg1H;
658 break;
659 case kBRegSizeInBytes:
660 format |= kPrintReg1B;
661 break;
662 }
663 // These sizes would be duplicate case labels.
664 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
665 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
666 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
667 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
668
669 return static_cast<PrintRegisterFormat>(format);
670 }
671
672
GetPrintRegisterFormat(VectorFormat vform)673 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
674 VectorFormat vform) {
675 switch (vform) {
676 default:
677 VIXL_UNREACHABLE();
678 return kPrintReg16B;
679 case kFormat16B:
680 return kPrintReg16B;
681 case kFormat8B:
682 return kPrintReg8B;
683 case kFormat8H:
684 return kPrintReg8H;
685 case kFormat4H:
686 return kPrintReg4H;
687 case kFormat4S:
688 return kPrintReg4S;
689 case kFormat2S:
690 return kPrintReg2S;
691 case kFormat2D:
692 return kPrintReg2D;
693 case kFormat1D:
694 return kPrintReg1D;
695
696 case kFormatB:
697 return kPrintReg1B;
698 case kFormatH:
699 return kPrintReg1H;
700 case kFormatS:
701 return kPrintReg1S;
702 case kFormatD:
703 return kPrintReg1D;
704
705 case kFormatVnB:
706 return kPrintRegVnB;
707 case kFormatVnH:
708 return kPrintRegVnH;
709 case kFormatVnS:
710 return kPrintRegVnS;
711 case kFormatVnD:
712 return kPrintRegVnD;
713 }
714 }
715
716
GetPrintRegisterFormatFP(VectorFormat vform)717 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
718 VectorFormat vform) {
719 switch (vform) {
720 default:
721 VIXL_UNREACHABLE();
722 return kPrintReg16B;
723 case kFormat8H:
724 return kPrintReg8HFP;
725 case kFormat4H:
726 return kPrintReg4HFP;
727 case kFormat4S:
728 return kPrintReg4SFP;
729 case kFormat2S:
730 return kPrintReg2SFP;
731 case kFormat2D:
732 return kPrintReg2DFP;
733 case kFormat1D:
734 return kPrintReg1DFP;
735 case kFormatH:
736 return kPrintReg1HFP;
737 case kFormatS:
738 return kPrintReg1SFP;
739 case kFormatD:
740 return kPrintReg1DFP;
741 }
742 }
743
PrintRegisters()744 void Simulator::PrintRegisters() {
745 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
746 if (i == kSpRegCode) i = kSPRegInternalCode;
747 PrintRegister(i);
748 }
749 }
750
PrintVRegisters()751 void Simulator::PrintVRegisters() {
752 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
753 PrintVRegister(i);
754 }
755 }
756
PrintZRegisters()757 void Simulator::PrintZRegisters() {
758 for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
759 PrintZRegister(i);
760 }
761 }
762
PrintWrittenRegisters()763 void Simulator::PrintWrittenRegisters() {
764 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
765 if (registers_[i].WrittenSinceLastLog()) {
766 if (i == kSpRegCode) i = kSPRegInternalCode;
767 PrintRegister(i);
768 }
769 }
770 }
771
PrintWrittenVRegisters()772 void Simulator::PrintWrittenVRegisters() {
773 bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
774 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
775 if (vregisters_[i].WrittenSinceLastLog()) {
776 // Z registers are initialised in the constructor before the user can
777 // configure the CPU features, so we must also check for SVE here.
778 if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
779 PrintZRegister(i);
780 } else {
781 PrintVRegister(i);
782 }
783 }
784 }
785 }
786
PrintWrittenPRegisters()787 void Simulator::PrintWrittenPRegisters() {
788 // P registers are initialised in the constructor before the user can
789 // configure the CPU features, so we must check for SVE here.
790 if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
791 for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
792 if (pregisters_[i].WrittenSinceLastLog()) {
793 PrintPRegister(i);
794 }
795 }
796 if (ReadFFR().WrittenSinceLastLog()) PrintFFR();
797 }
798
PrintSystemRegisters()799 void Simulator::PrintSystemRegisters() {
800 PrintSystemRegister(NZCV);
801 PrintSystemRegister(FPCR);
802 }
803
PrintRegisterValue(const uint8_t * value,int value_size,PrintRegisterFormat format)804 void Simulator::PrintRegisterValue(const uint8_t* value,
805 int value_size,
806 PrintRegisterFormat format) {
807 int print_width = GetPrintRegSizeInBytes(format);
808 VIXL_ASSERT(print_width <= value_size);
809 for (int i = value_size - 1; i >= print_width; i--) {
810 // Pad with spaces so that values align vertically.
811 fprintf(stream_, " ");
812 // If we aren't explicitly printing a partial value, ensure that the
813 // unprinted bits are zero.
814 VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
815 }
816 fprintf(stream_, "0x");
817 for (int i = print_width - 1; i >= 0; i--) {
818 fprintf(stream_, "%02x", value[i]);
819 }
820 }
821
PrintRegisterValueFPAnnotations(const uint8_t * value,uint16_t lane_mask,PrintRegisterFormat format)822 void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
823 uint16_t lane_mask,
824 PrintRegisterFormat format) {
825 VIXL_ASSERT((format & kPrintRegAsFP) != 0);
826 int lane_size = GetPrintRegLaneSizeInBytes(format);
827 fprintf(stream_, " (");
828 bool last_inactive = false;
829 const char* sep = "";
830 for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
831 bool access = (lane_mask & (1 << (i * lane_size))) != 0;
832 if (access) {
833 // Read the lane as a double, so we can format all FP types in the same
834 // way. We squash NaNs, and a double can exactly represent any other value
835 // that the smaller types can represent, so this is lossless.
836 double element;
837 switch (lane_size) {
838 case kHRegSizeInBytes: {
839 Float16 element_fp16;
840 VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
841 memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
842 element = FPToDouble(element_fp16, kUseDefaultNaN);
843 break;
844 }
845 case kSRegSizeInBytes: {
846 float element_fp32;
847 memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
848 element = static_cast<double>(element_fp32);
849 break;
850 }
851 case kDRegSizeInBytes: {
852 memcpy(&element, &value[i * lane_size], sizeof(element));
853 break;
854 }
855 default:
856 VIXL_UNREACHABLE();
857 fprintf(stream_, "{UnknownFPValue}");
858 continue;
859 }
860 if (IsNaN(element)) {
861 // The fprintf behaviour for NaNs is implementation-defined. Always
862 // print "nan", so that traces are consistent.
863 fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
864 } else {
865 fprintf(stream_,
866 "%s%s%#.4g%s",
867 sep,
868 clr_vreg_value,
869 element,
870 clr_normal);
871 }
872 last_inactive = false;
873 } else if (!last_inactive) {
874 // Replace each contiguous sequence of inactive lanes with "...".
875 fprintf(stream_, "%s...", sep);
876 last_inactive = true;
877 }
878 }
879 fprintf(stream_, ")");
880 }
881
PrintRegister(int code,PrintRegisterFormat format,const char * suffix)882 void Simulator::PrintRegister(int code,
883 PrintRegisterFormat format,
884 const char* suffix) {
885 VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
886 (static_cast<unsigned>(code) == kSPRegInternalCode));
887 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
888 VIXL_ASSERT((format & kPrintRegAsFP) == 0);
889
890 SimRegister* reg;
891 SimRegister zero;
892 if (code == kZeroRegCode) {
893 reg = &zero;
894 } else {
895 // registers_[31] holds the SP.
896 VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
897 reg = ®isters_[code % kNumberOfRegisters];
898 }
899
900 // We trace register writes as whole register values, implying that any
901 // unprinted bits are all zero:
902 // "# x{code}: 0x{-----value----}"
903 // "# w{code}: 0x{-value}"
904 // Stores trace partial register values, implying nothing about the unprinted
905 // bits:
906 // "# x{code}<63:0>: 0x{-----value----}"
907 // "# x{code}<31:0>: 0x{-value}"
908 // "# x{code}<15:0>: 0x{--}"
909 // "# x{code}<7:0>: 0x{}"
910
911 bool is_partial = (format & kPrintRegPartial) != 0;
912 unsigned print_reg_size = GetPrintRegSizeInBits(format);
913 std::stringstream name;
914 if (is_partial) {
915 name << XRegNameForCode(code) << GetPartialRegSuffix(format);
916 } else {
917 // Notify the register that it has been logged, but only if we're printing
918 // all of it.
919 reg->NotifyRegisterLogged();
920 switch (print_reg_size) {
921 case kWRegSize:
922 name << WRegNameForCode(code);
923 break;
924 case kXRegSize:
925 name << XRegNameForCode(code);
926 break;
927 default:
928 VIXL_UNREACHABLE();
929 return;
930 }
931 }
932
933 fprintf(stream_,
934 "# %s%*s: %s",
935 clr_reg_name,
936 kPrintRegisterNameFieldWidth,
937 name.str().c_str(),
938 clr_reg_value);
939 PrintRegisterValue(*reg, format);
940 fprintf(stream_, "%s%s", clr_normal, suffix);
941 }
942
PrintVRegister(int code,PrintRegisterFormat format,const char * suffix)943 void Simulator::PrintVRegister(int code,
944 PrintRegisterFormat format,
945 const char* suffix) {
946 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
947 VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
948 ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
949 ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
950
951 // We trace register writes as whole register values, implying that any
952 // unprinted bits are all zero:
953 // "# v{code}: 0x{-------------value------------}"
954 // "# d{code}: 0x{-----value----}"
955 // "# s{code}: 0x{-value}"
956 // "# h{code}: 0x{--}"
957 // "# b{code}: 0x{}"
958 // Stores trace partial register values, implying nothing about the unprinted
959 // bits:
960 // "# v{code}<127:0>: 0x{-------------value------------}"
961 // "# v{code}<63:0>: 0x{-----value----}"
962 // "# v{code}<31:0>: 0x{-value}"
963 // "# v{code}<15:0>: 0x{--}"
964 // "# v{code}<7:0>: 0x{}"
965
966 bool is_partial = ((format & kPrintRegPartial) != 0);
967 std::stringstream name;
968 unsigned print_reg_size = GetPrintRegSizeInBits(format);
969 if (is_partial) {
970 name << VRegNameForCode(code) << GetPartialRegSuffix(format);
971 } else {
972 // Notify the register that it has been logged, but only if we're printing
973 // all of it.
974 vregisters_[code].NotifyRegisterLogged();
975 switch (print_reg_size) {
976 case kBRegSize:
977 name << BRegNameForCode(code);
978 break;
979 case kHRegSize:
980 name << HRegNameForCode(code);
981 break;
982 case kSRegSize:
983 name << SRegNameForCode(code);
984 break;
985 case kDRegSize:
986 name << DRegNameForCode(code);
987 break;
988 case kQRegSize:
989 name << VRegNameForCode(code);
990 break;
991 default:
992 VIXL_UNREACHABLE();
993 return;
994 }
995 }
996
997 fprintf(stream_,
998 "# %s%*s: %s",
999 clr_vreg_name,
1000 kPrintRegisterNameFieldWidth,
1001 name.str().c_str(),
1002 clr_vreg_value);
1003 PrintRegisterValue(vregisters_[code], format);
1004 fprintf(stream_, "%s", clr_normal);
1005 if ((format & kPrintRegAsFP) != 0) {
1006 PrintRegisterValueFPAnnotations(vregisters_[code], format);
1007 }
1008 fprintf(stream_, "%s", suffix);
1009 }
1010
PrintVRegistersForStructuredAccess(int rt_code,int reg_count,uint16_t focus_mask,PrintRegisterFormat format)1011 void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1012 int reg_count,
1013 uint16_t focus_mask,
1014 PrintRegisterFormat format) {
1015 bool print_fp = (format & kPrintRegAsFP) != 0;
1016 // Suppress FP formatting, so we can specify the lanes we're interested in.
1017 PrintRegisterFormat format_no_fp =
1018 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1019
1020 for (int r = 0; r < reg_count; r++) {
1021 int code = (rt_code + r) % kNumberOfVRegisters;
1022 PrintVRegister(code, format_no_fp, "");
1023 if (print_fp) {
1024 PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1025 }
1026 fprintf(stream_, "\n");
1027 }
1028 }
1029
PrintZRegistersForStructuredAccess(int rt_code,int q_index,int reg_count,uint16_t focus_mask,PrintRegisterFormat format)1030 void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1031 int q_index,
1032 int reg_count,
1033 uint16_t focus_mask,
1034 PrintRegisterFormat format) {
1035 bool print_fp = (format & kPrintRegAsFP) != 0;
1036 // Suppress FP formatting, so we can specify the lanes we're interested in.
1037 PrintRegisterFormat format_no_fp =
1038 static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1039
1040 PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
1041
1042 const unsigned size = kQRegSizeInBytes;
1043 unsigned byte_index = q_index * size;
1044 const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1045 VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
1046
1047 for (int r = 0; r < reg_count; r++) {
1048 int code = (rt_code + r) % kNumberOfZRegisters;
1049 PrintPartialZRegister(code, q_index, format_no_fp, "");
1050 if (print_fp) {
1051 PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
1052 }
1053 fprintf(stream_, "\n");
1054 }
1055 }
1056
PrintZRegister(int code,PrintRegisterFormat format)1057 void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1058 // We're going to print the register in parts, so force a partial format.
1059 format = GetPrintRegPartial(format);
1060 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1061 int vl = GetVectorLengthInBits();
1062 VIXL_ASSERT((vl % kQRegSize) == 0);
1063 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1064 PrintPartialZRegister(code, i, format);
1065 }
1066 vregisters_[code].NotifyRegisterLogged();
1067 }
1068
PrintPRegister(int code,PrintRegisterFormat format)1069 void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1070 // We're going to print the register in parts, so force a partial format.
1071 format = GetPrintRegPartial(format);
1072 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1073 int vl = GetVectorLengthInBits();
1074 VIXL_ASSERT((vl % kQRegSize) == 0);
1075 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1076 PrintPartialPRegister(code, i, format);
1077 }
1078 pregisters_[code].NotifyRegisterLogged();
1079 }
1080
PrintFFR(PrintRegisterFormat format)1081 void Simulator::PrintFFR(PrintRegisterFormat format) {
1082 // We're going to print the register in parts, so force a partial format.
1083 format = GetPrintRegPartial(format);
1084 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1085 int vl = GetVectorLengthInBits();
1086 VIXL_ASSERT((vl % kQRegSize) == 0);
1087 SimPRegister& ffr = ReadFFR();
1088 for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1089 PrintPartialPRegister("FFR", ffr, i, format);
1090 }
1091 ffr.NotifyRegisterLogged();
1092 }
1093
PrintPartialZRegister(int code,int q_index,PrintRegisterFormat format,const char * suffix)1094 void Simulator::PrintPartialZRegister(int code,
1095 int q_index,
1096 PrintRegisterFormat format,
1097 const char* suffix) {
1098 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1099 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1100 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1101 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1102
1103 // We _only_ trace partial Z register values in Q-sized chunks, because
1104 // they're often too large to reasonably fit on a single line. Each line
1105 // implies nothing about the unprinted bits.
1106 // "# z{code}<127:0>: 0x{-------------value------------}"
1107
1108 format = GetPrintRegAsQChunkOfSVE(format);
1109
1110 const unsigned size = kQRegSizeInBytes;
1111 unsigned byte_index = q_index * size;
1112 const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1113 VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1114
1115 int lsb = q_index * kQRegSize;
1116 int msb = lsb + kQRegSize - 1;
1117 std::stringstream name;
1118 name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
1119
1120 fprintf(stream_,
1121 "# %s%*s: %s",
1122 clr_vreg_name,
1123 kPrintRegisterNameFieldWidth,
1124 name.str().c_str(),
1125 clr_vreg_value);
1126 PrintRegisterValue(value, size, format);
1127 fprintf(stream_, "%s", clr_normal);
1128 if ((format & kPrintRegAsFP) != 0) {
1129 PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1130 }
1131 fprintf(stream_, "%s", suffix);
1132 }
1133
PrintPartialPRegister(const char * name,const SimPRegister & reg,int q_index,PrintRegisterFormat format,const char * suffix)1134 void Simulator::PrintPartialPRegister(const char* name,
1135 const SimPRegister& reg,
1136 int q_index,
1137 PrintRegisterFormat format,
1138 const char* suffix) {
1139 VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1140 VIXL_ASSERT((format & kPrintRegPartial) != 0);
1141 VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1142
1143 // We don't currently use the format for anything here.
1144 USE(format);
1145
1146 // We _only_ trace partial P register values, because they're often too large
1147 // to reasonably fit on a single line. Each line implies nothing about the
1148 // unprinted bits.
1149 //
1150 // We print values in binary, with spaces between each bit, in order for the
1151 // bits to align with the Z register bytes that they predicate.
1152 // "# {name}<15:0>: 0b{-------------value------------}"
1153
1154 int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1155 int lsb = q_index * print_size_in_bits;
1156 int msb = lsb + print_size_in_bits - 1;
1157 std::stringstream prefix;
1158 prefix << name << '<' << msb << ':' << lsb << '>';
1159
1160 fprintf(stream_,
1161 "# %s%*s: %s0b",
1162 clr_preg_name,
1163 kPrintRegisterNameFieldWidth,
1164 prefix.str().c_str(),
1165 clr_preg_value);
1166 for (int i = msb; i >= lsb; i--) {
1167 fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');
1168 }
1169 fprintf(stream_, "%s%s", clr_normal, suffix);
1170 }
1171
PrintPartialPRegister(int code,int q_index,PrintRegisterFormat format,const char * suffix)1172 void Simulator::PrintPartialPRegister(int code,
1173 int q_index,
1174 PrintRegisterFormat format,
1175 const char* suffix) {
1176 VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1177 PrintPartialPRegister(PRegNameForCode(code),
1178 pregisters_[code],
1179 q_index,
1180 format,
1181 suffix);
1182 }
1183
PrintSystemRegister(SystemRegister id)1184 void Simulator::PrintSystemRegister(SystemRegister id) {
1185 switch (id) {
1186 case NZCV:
1187 fprintf(stream_,
1188 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1189 clr_flag_name,
1190 clr_flag_value,
1191 ReadNzcv().GetN(),
1192 ReadNzcv().GetZ(),
1193 ReadNzcv().GetC(),
1194 ReadNzcv().GetV(),
1195 clr_normal);
1196 break;
1197 case FPCR: {
1198 static const char* rmode[] = {"0b00 (Round to Nearest)",
1199 "0b01 (Round towards Plus Infinity)",
1200 "0b10 (Round towards Minus Infinity)",
1201 "0b11 (Round towards Zero)"};
1202 VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
1203 fprintf(stream_,
1204 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1205 clr_flag_name,
1206 clr_flag_value,
1207 ReadFpcr().GetAHP(),
1208 ReadFpcr().GetDN(),
1209 ReadFpcr().GetFZ(),
1210 rmode[ReadFpcr().GetRMode()],
1211 clr_normal);
1212 break;
1213 }
1214 default:
1215 VIXL_UNREACHABLE();
1216 }
1217 }
1218
PrintPartialAccess(uint16_t access_mask,uint16_t future_access_mask,int struct_element_count,int lane_size_in_bytes,const char * op,uintptr_t address,int reg_size_in_bytes)1219 uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1220 uint16_t future_access_mask,
1221 int struct_element_count,
1222 int lane_size_in_bytes,
1223 const char* op,
1224 uintptr_t address,
1225 int reg_size_in_bytes) {
1226 // We want to assume that we'll access at least one lane.
1227 VIXL_ASSERT(access_mask != 0);
1228 VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1229 (reg_size_in_bytes == kQRegSizeInBytes));
1230 bool started_annotation = false;
1231 // Indent to match the register field, the fixed formatting, and the value
1232 // prefix ("0x"): "# {name}: 0x"
1233 fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1234 // First, annotate the lanes (byte by byte).
1235 for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1236 bool access = (access_mask & (1 << lane)) != 0;
1237 bool future = (future_access_mask & (1 << lane)) != 0;
1238 if (started_annotation) {
1239 // If we've started an annotation, draw a horizontal line in addition to
1240 // any other symbols.
1241 if (access) {
1242 fprintf(stream_, "─╨");
1243 } else if (future) {
1244 fprintf(stream_, "─║");
1245 } else {
1246 fprintf(stream_, "──");
1247 }
1248 } else {
1249 if (access) {
1250 started_annotation = true;
1251 fprintf(stream_, " ╙");
1252 } else if (future) {
1253 fprintf(stream_, " ║");
1254 } else {
1255 fprintf(stream_, " ");
1256 }
1257 }
1258 }
1259 VIXL_ASSERT(started_annotation);
1260 fprintf(stream_, "─ 0x");
1261 int lane_size_in_nibbles = lane_size_in_bytes * 2;
1262 // Print the most-significant struct element first.
1263 const char* sep = "";
1264 for (int i = struct_element_count - 1; i >= 0; i--) {
1265 int offset = lane_size_in_bytes * i;
1266 uint64_t nibble = MemReadUint(lane_size_in_bytes, address + offset);
1267 fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1268 sep = "'";
1269 }
1270 fprintf(stream_,
1271 " %s %s0x%016" PRIxPTR "%s\n",
1272 op,
1273 clr_memory_address,
1274 address,
1275 clr_normal);
1276 return future_access_mask & ~access_mask;
1277 }
1278
PrintAccess(int code,PrintRegisterFormat format,const char * op,uintptr_t address)1279 void Simulator::PrintAccess(int code,
1280 PrintRegisterFormat format,
1281 const char* op,
1282 uintptr_t address) {
1283 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1284 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1285 if ((format & kPrintRegPartial) == 0) {
1286 registers_[code].NotifyRegisterLogged();
1287 }
1288 // Scalar-format accesses use a simple format:
1289 // "# {reg}: 0x{value} -> {address}"
1290
1291 // Suppress the newline, so the access annotation goes on the same line.
1292 PrintRegister(code, format, "");
1293 fprintf(stream_,
1294 " %s %s0x%016" PRIxPTR "%s\n",
1295 op,
1296 clr_memory_address,
1297 address,
1298 clr_normal);
1299 }
1300
PrintVAccess(int code,PrintRegisterFormat format,const char * op,uintptr_t address)1301 void Simulator::PrintVAccess(int code,
1302 PrintRegisterFormat format,
1303 const char* op,
1304 uintptr_t address) {
1305 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1306
1307 // Scalar-format accesses use a simple format:
1308 // "# v{code}: 0x{value} -> {address}"
1309
1310 // Suppress the newline, so the access annotation goes on the same line.
1311 PrintVRegister(code, format, "");
1312 fprintf(stream_,
1313 " %s %s0x%016" PRIxPTR "%s\n",
1314 op,
1315 clr_memory_address,
1316 address,
1317 clr_normal);
1318 }
1319
PrintVStructAccess(int rt_code,int reg_count,PrintRegisterFormat format,const char * op,uintptr_t address)1320 void Simulator::PrintVStructAccess(int rt_code,
1321 int reg_count,
1322 PrintRegisterFormat format,
1323 const char* op,
1324 uintptr_t address) {
1325 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1326
1327 // For example:
1328 // "# v{code}: 0x{value}"
1329 // "# ...: 0x{value}"
1330 // "# ║ ╙─ {struct_value} -> {lowest_address}"
1331 // "# ╙───── {struct_value} -> {highest_address}"
1332
1333 uint16_t lane_mask = GetPrintRegLaneMask(format);
1334 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1335
1336 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1337 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1338 for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1339 uint16_t access_mask = 1 << i;
1340 VIXL_ASSERT((lane_mask & access_mask) != 0);
1341 lane_mask = PrintPartialAccess(access_mask,
1342 lane_mask,
1343 reg_count,
1344 lane_size_in_bytes,
1345 op,
1346 address + (i * reg_count));
1347 }
1348 }
1349
PrintVSingleStructAccess(int rt_code,int reg_count,int lane,PrintRegisterFormat format,const char * op,uintptr_t address)1350 void Simulator::PrintVSingleStructAccess(int rt_code,
1351 int reg_count,
1352 int lane,
1353 PrintRegisterFormat format,
1354 const char* op,
1355 uintptr_t address) {
1356 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1357
1358 // For example:
1359 // "# v{code}: 0x{value}"
1360 // "# ...: 0x{value}"
1361 // "# ╙───── {struct_value} -> {address}"
1362
1363 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1364 uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1365 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1366 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1367 }
1368
PrintVReplicatingStructAccess(int rt_code,int reg_count,PrintRegisterFormat format,const char * op,uintptr_t address)1369 void Simulator::PrintVReplicatingStructAccess(int rt_code,
1370 int reg_count,
1371 PrintRegisterFormat format,
1372 const char* op,
1373 uintptr_t address) {
1374 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1375
1376 // For example:
1377 // "# v{code}: 0x{value}"
1378 // "# ...: 0x{value}"
1379 // "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1380
1381 int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1382 uint16_t lane_mask = GetPrintRegLaneMask(format);
1383 PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1384 PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1385 }
1386
PrintZAccess(int rt_code,const char * op,uintptr_t address)1387 void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1388 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1389
1390 // Scalar-format accesses are split into separate chunks, each of which uses a
1391 // simple format:
1392 // "# z{code}<127:0>: 0x{value} -> {address}"
1393 // "# z{code}<255:128>: 0x{value} -> {address + 16}"
1394 // "# z{code}<383:256>: 0x{value} -> {address + 32}"
1395 // etc
1396
1397 int vl = GetVectorLengthInBits();
1398 VIXL_ASSERT((vl % kQRegSize) == 0);
1399 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1400 // Suppress the newline, so the access annotation goes on the same line.
1401 PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1402 fprintf(stream_,
1403 " %s %s0x%016" PRIxPTR "%s\n",
1404 op,
1405 clr_memory_address,
1406 address,
1407 clr_normal);
1408 address += kQRegSizeInBytes;
1409 }
1410 }
1411
PrintZStructAccess(int rt_code,int reg_count,const LogicPRegister & pg,PrintRegisterFormat format,int msize_in_bytes,const char * op,const LogicSVEAddressVector & addr)1412 void Simulator::PrintZStructAccess(int rt_code,
1413 int reg_count,
1414 const LogicPRegister& pg,
1415 PrintRegisterFormat format,
1416 int msize_in_bytes,
1417 const char* op,
1418 const LogicSVEAddressVector& addr) {
1419 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1420
1421 // For example:
1422 // "# z{code}<255:128>: 0x{value}"
1423 // "# ...<255:128>: 0x{value}"
1424 // "# ║ ╙─ {struct_value} -> {first_address}"
1425 // "# ╙───── {struct_value} -> {last_address}"
1426
1427 // We're going to print the register in parts, so force a partial format.
1428 bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1429 format = GetPrintRegPartial(format);
1430
1431 int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1432 int vl = GetVectorLengthInBits();
1433 VIXL_ASSERT((vl % kQRegSize) == 0);
1434 int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1435 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1436 uint16_t pred =
1437 pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1438 if ((pred == 0) && skip_inactive_chunks) continue;
1439
1440 PrintZRegistersForStructuredAccess(rt_code,
1441 q_index,
1442 reg_count,
1443 pred,
1444 format);
1445 if (pred == 0) {
1446 // This register chunk has no active lanes. The loop below would print
1447 // nothing, so leave a blank line to keep structures grouped together.
1448 fprintf(stream_, "#\n");
1449 continue;
1450 }
1451 for (int i = 0; i < lanes_per_q; i++) {
1452 uint16_t access = 1 << (i * esize_in_bytes);
1453 int lane = (q_index * lanes_per_q) + i;
1454 // Skip inactive lanes.
1455 if ((pred & access) == 0) continue;
1456 pred = PrintPartialAccess(access,
1457 pred,
1458 reg_count,
1459 msize_in_bytes,
1460 op,
1461 addr.GetStructAddress(lane));
1462 }
1463 }
1464
1465 // We print the whole register, even for stores.
1466 for (int i = 0; i < reg_count; i++) {
1467 vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1468 }
1469 }
1470
PrintPAccess(int code,const char * op,uintptr_t address)1471 void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1472 VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1473
1474 // Scalar-format accesses are split into separate chunks, each of which uses a
1475 // simple format:
1476 // "# p{code}<15:0>: 0b{value} -> {address}"
1477 // "# p{code}<31:16>: 0b{value} -> {address + 2}"
1478 // "# p{code}<47:32>: 0b{value} -> {address + 4}"
1479 // etc
1480
1481 int vl = GetVectorLengthInBits();
1482 VIXL_ASSERT((vl % kQRegSize) == 0);
1483 for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1484 // Suppress the newline, so the access annotation goes on the same line.
1485 PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1486 fprintf(stream_,
1487 " %s %s0x%016" PRIxPTR "%s\n",
1488 op,
1489 clr_memory_address,
1490 address,
1491 clr_normal);
1492 address += kQRegSizeInBytes;
1493 }
1494 }
1495
PrintRead(int rt_code,PrintRegisterFormat format,uintptr_t address)1496 void Simulator::PrintRead(int rt_code,
1497 PrintRegisterFormat format,
1498 uintptr_t address) {
1499 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1500 registers_[rt_code].NotifyRegisterLogged();
1501 PrintAccess(rt_code, format, "<-", address);
1502 }
1503
PrintExtendingRead(int rt_code,PrintRegisterFormat format,int access_size_in_bytes,uintptr_t address)1504 void Simulator::PrintExtendingRead(int rt_code,
1505 PrintRegisterFormat format,
1506 int access_size_in_bytes,
1507 uintptr_t address) {
1508 int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1509 if (access_size_in_bytes == reg_size_in_bytes) {
1510 // There is no extension here, so print a simple load.
1511 PrintRead(rt_code, format, address);
1512 return;
1513 }
1514 VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1515
1516 // For sign- and zero-extension, make it clear that the resulting register
1517 // value is different from what is loaded from memory.
1518 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1519 registers_[rt_code].NotifyRegisterLogged();
1520 PrintRegister(rt_code, format);
1521 PrintPartialAccess(1,
1522 0,
1523 1,
1524 access_size_in_bytes,
1525 "<-",
1526 address,
1527 kXRegSizeInBytes);
1528 }
1529
PrintVRead(int rt_code,PrintRegisterFormat format,uintptr_t address)1530 void Simulator::PrintVRead(int rt_code,
1531 PrintRegisterFormat format,
1532 uintptr_t address) {
1533 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1534 vregisters_[rt_code].NotifyRegisterLogged();
1535 PrintVAccess(rt_code, format, "<-", address);
1536 }
1537
PrintWrite(int rt_code,PrintRegisterFormat format,uintptr_t address)1538 void Simulator::PrintWrite(int rt_code,
1539 PrintRegisterFormat format,
1540 uintptr_t address) {
1541 // Because this trace doesn't represent a change to the source register's
1542 // value, only print the relevant part of the value.
1543 format = GetPrintRegPartial(format);
1544 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1545 registers_[rt_code].NotifyRegisterLogged();
1546 PrintAccess(rt_code, format, "->", address);
1547 }
1548
PrintVWrite(int rt_code,PrintRegisterFormat format,uintptr_t address)1549 void Simulator::PrintVWrite(int rt_code,
1550 PrintRegisterFormat format,
1551 uintptr_t address) {
1552 // Because this trace doesn't represent a change to the source register's
1553 // value, only print the relevant part of the value.
1554 format = GetPrintRegPartial(format);
1555 // It only makes sense to write scalar values here. Vectors are handled by
1556 // PrintVStructAccess.
1557 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1558 PrintVAccess(rt_code, format, "->", address);
1559 }
1560
PrintTakenBranch(const Instruction * target)1561 void Simulator::PrintTakenBranch(const Instruction* target) {
1562 fprintf(stream_,
1563 "# %sBranch%s to 0x%016" PRIx64 ".\n",
1564 clr_branch_marker,
1565 clr_normal,
1566 reinterpret_cast<uint64_t>(target));
1567 }
1568
1569 // Visitors---------------------------------------------------------------------
1570
1571
VisitReserved(const Instruction * instr)1572 void Simulator::VisitReserved(const Instruction* instr) {
1573 // UDF is the only instruction in this group, and the Decoder is precise here.
1574 VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
1575
1576 printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
1577 reinterpret_cast<const void*>(instr),
1578 instr->GetInstructionBits());
1579 VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
1580 }
1581
1582
VisitUnimplemented(const Instruction * instr)1583 void Simulator::VisitUnimplemented(const Instruction* instr) {
1584 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1585 reinterpret_cast<const void*>(instr),
1586 instr->GetInstructionBits());
1587 VIXL_UNIMPLEMENTED();
1588 }
1589
1590
VisitUnallocated(const Instruction * instr)1591 void Simulator::VisitUnallocated(const Instruction* instr) {
1592 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
1593 reinterpret_cast<const void*>(instr),
1594 instr->GetInstructionBits());
1595 VIXL_UNIMPLEMENTED();
1596 }
1597
1598
VisitPCRelAddressing(const Instruction * instr)1599 void Simulator::VisitPCRelAddressing(const Instruction* instr) {
1600 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
1601 (instr->Mask(PCRelAddressingMask) == ADRP));
1602
1603 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
1604 }
1605
1606
VisitUnconditionalBranch(const Instruction * instr)1607 void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
1608 switch (instr->Mask(UnconditionalBranchMask)) {
1609 case BL:
1610 WriteLr(instr->GetNextInstruction());
1611 VIXL_FALLTHROUGH();
1612 case B:
1613 WritePc(instr->GetImmPCOffsetTarget());
1614 break;
1615 default:
1616 VIXL_UNREACHABLE();
1617 }
1618 }
1619
1620
VisitConditionalBranch(const Instruction * instr)1621 void Simulator::VisitConditionalBranch(const Instruction* instr) {
1622 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
1623 if (ConditionPassed(instr->GetConditionBranch())) {
1624 WritePc(instr->GetImmPCOffsetTarget());
1625 }
1626 }
1627
GetBTypeFromInstruction(const Instruction * instr) const1628 BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
1629 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1630 case BLR:
1631 case BLRAA:
1632 case BLRAB:
1633 case BLRAAZ:
1634 case BLRABZ:
1635 return BranchAndLink;
1636 case BR:
1637 case BRAA:
1638 case BRAB:
1639 case BRAAZ:
1640 case BRABZ:
1641 if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
1642 !PcIsInGuardedPage()) {
1643 return BranchFromUnguardedOrToIP;
1644 }
1645 return BranchFromGuardedNotToIP;
1646 }
1647 return DefaultBType;
1648 }
1649
VisitUnconditionalBranchToRegister(const Instruction * instr)1650 void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
1651 bool authenticate = false;
1652 bool link = false;
1653 uint64_t addr = ReadXRegister(instr->GetRn());
1654 uint64_t context = 0;
1655
1656 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
1657 case BLR:
1658 link = true;
1659 VIXL_FALLTHROUGH();
1660 case BR:
1661 case RET:
1662 break;
1663
1664 case BLRAAZ:
1665 case BLRABZ:
1666 link = true;
1667 VIXL_FALLTHROUGH();
1668 case BRAAZ:
1669 case BRABZ:
1670 authenticate = true;
1671 break;
1672
1673 case BLRAA:
1674 case BLRAB:
1675 link = true;
1676 VIXL_FALLTHROUGH();
1677 case BRAA:
1678 case BRAB:
1679 authenticate = true;
1680 context = ReadXRegister(instr->GetRd());
1681 break;
1682
1683 case RETAA:
1684 case RETAB:
1685 authenticate = true;
1686 addr = ReadXRegister(kLinkRegCode);
1687 context = ReadXRegister(31, Reg31IsStackPointer);
1688 break;
1689 default:
1690 VIXL_UNREACHABLE();
1691 }
1692
1693 if (link) {
1694 WriteLr(instr->GetNextInstruction());
1695 }
1696
1697 if (authenticate) {
1698 PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
1699 addr = AuthPAC(addr, context, key, kInstructionPointer);
1700
1701 int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
1702 if (((addr >> error_lsb) & 0x3) != 0x0) {
1703 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
1704 }
1705 }
1706
1707 WritePc(Instruction::Cast(addr));
1708 WriteNextBType(GetBTypeFromInstruction(instr));
1709 }
1710
1711
VisitTestBranch(const Instruction * instr)1712 void Simulator::VisitTestBranch(const Instruction* instr) {
1713 unsigned bit_pos =
1714 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1715 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1716 bool take_branch = false;
1717 switch (instr->Mask(TestBranchMask)) {
1718 case TBZ:
1719 take_branch = bit_zero;
1720 break;
1721 case TBNZ:
1722 take_branch = !bit_zero;
1723 break;
1724 default:
1725 VIXL_UNIMPLEMENTED();
1726 }
1727 if (take_branch) {
1728 WritePc(instr->GetImmPCOffsetTarget());
1729 }
1730 }
1731
1732
VisitCompareBranch(const Instruction * instr)1733 void Simulator::VisitCompareBranch(const Instruction* instr) {
1734 unsigned rt = instr->GetRt();
1735 bool take_branch = false;
1736 switch (instr->Mask(CompareBranchMask)) {
1737 case CBZ_w:
1738 take_branch = (ReadWRegister(rt) == 0);
1739 break;
1740 case CBZ_x:
1741 take_branch = (ReadXRegister(rt) == 0);
1742 break;
1743 case CBNZ_w:
1744 take_branch = (ReadWRegister(rt) != 0);
1745 break;
1746 case CBNZ_x:
1747 take_branch = (ReadXRegister(rt) != 0);
1748 break;
1749 default:
1750 VIXL_UNIMPLEMENTED();
1751 }
1752 if (take_branch) {
1753 WritePc(instr->GetImmPCOffsetTarget());
1754 }
1755 }
1756
1757
AddSubHelper(const Instruction * instr,int64_t op2)1758 void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1759 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1760 bool set_flags = instr->GetFlagsUpdate();
1761 int64_t new_val = 0;
1762 Instr operation = instr->Mask(AddSubOpMask);
1763
1764 switch (operation) {
1765 case ADD:
1766 case ADDS: {
1767 new_val = AddWithCarry(reg_size,
1768 set_flags,
1769 ReadRegister(reg_size,
1770 instr->GetRn(),
1771 instr->GetRnMode()),
1772 op2);
1773 break;
1774 }
1775 case SUB:
1776 case SUBS: {
1777 new_val = AddWithCarry(reg_size,
1778 set_flags,
1779 ReadRegister(reg_size,
1780 instr->GetRn(),
1781 instr->GetRnMode()),
1782 ~op2,
1783 1);
1784 break;
1785 }
1786 default:
1787 VIXL_UNREACHABLE();
1788 }
1789
1790 WriteRegister(reg_size,
1791 instr->GetRd(),
1792 new_val,
1793 LogRegWrites,
1794 instr->GetRdMode());
1795 }
1796
1797
VisitAddSubShifted(const Instruction * instr)1798 void Simulator::VisitAddSubShifted(const Instruction* instr) {
1799 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1800 int64_t op2 = ShiftOperand(reg_size,
1801 ReadRegister(reg_size, instr->GetRm()),
1802 static_cast<Shift>(instr->GetShiftDP()),
1803 instr->GetImmDPShift());
1804 AddSubHelper(instr, op2);
1805 }
1806
1807
VisitAddSubImmediate(const Instruction * instr)1808 void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1809 int64_t op2 = instr->GetImmAddSub()
1810 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
1811 AddSubHelper(instr, op2);
1812 }
1813
1814
VisitAddSubExtended(const Instruction * instr)1815 void Simulator::VisitAddSubExtended(const Instruction* instr) {
1816 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1817 int64_t op2 = ExtendValue(reg_size,
1818 ReadRegister(reg_size, instr->GetRm()),
1819 static_cast<Extend>(instr->GetExtendMode()),
1820 instr->GetImmExtendShift());
1821 AddSubHelper(instr, op2);
1822 }
1823
1824
VisitAddSubWithCarry(const Instruction * instr)1825 void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1826 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1827 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1828 int64_t new_val;
1829
1830 if ((instr->Mask(AddSubOpMask) == SUB) ||
1831 (instr->Mask(AddSubOpMask) == SUBS)) {
1832 op2 = ~op2;
1833 }
1834
1835 new_val = AddWithCarry(reg_size,
1836 instr->GetFlagsUpdate(),
1837 ReadRegister(reg_size, instr->GetRn()),
1838 op2,
1839 ReadC());
1840
1841 WriteRegister(reg_size, instr->GetRd(), new_val);
1842 }
1843
1844
VisitRotateRightIntoFlags(const Instruction * instr)1845 void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
1846 switch (instr->Mask(RotateRightIntoFlagsMask)) {
1847 case RMIF: {
1848 uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
1849 unsigned shift = instr->GetImmRMIFRotation();
1850 unsigned mask = instr->GetNzcv();
1851 uint64_t rotated = RotateRight(value, shift, kXRegSize);
1852
1853 ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
1854 break;
1855 }
1856 }
1857 }
1858
1859
VisitEvaluateIntoFlags(const Instruction * instr)1860 void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
1861 uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
1862 unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
1863
1864 unsigned sign_bit = (value >> msb) & 1;
1865 unsigned overflow_bit = (value >> (msb + 1)) & 1;
1866 ReadNzcv().SetN(sign_bit);
1867 ReadNzcv().SetZ((value << (31 - msb)) == 0);
1868 ReadNzcv().SetV(sign_bit ^ overflow_bit);
1869 }
1870
1871
VisitLogicalShifted(const Instruction * instr)1872 void Simulator::VisitLogicalShifted(const Instruction* instr) {
1873 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1874 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1875 unsigned shift_amount = instr->GetImmDPShift();
1876 int64_t op2 = ShiftOperand(reg_size,
1877 ReadRegister(reg_size, instr->GetRm()),
1878 shift_type,
1879 shift_amount);
1880 if (instr->Mask(NOT) == NOT) {
1881 op2 = ~op2;
1882 }
1883 LogicalHelper(instr, op2);
1884 }
1885
1886
VisitLogicalImmediate(const Instruction * instr)1887 void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1888 if (instr->GetImmLogical() == 0) {
1889 VIXL_UNIMPLEMENTED();
1890 } else {
1891 LogicalHelper(instr, instr->GetImmLogical());
1892 }
1893 }
1894
1895
LogicalHelper(const Instruction * instr,int64_t op2)1896 void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1897 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1898 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1899 int64_t result = 0;
1900 bool update_flags = false;
1901
1902 // Switch on the logical operation, stripping out the NOT bit, as it has a
1903 // different meaning for logical immediate instructions.
1904 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1905 case ANDS:
1906 update_flags = true;
1907 VIXL_FALLTHROUGH();
1908 case AND:
1909 result = op1 & op2;
1910 break;
1911 case ORR:
1912 result = op1 | op2;
1913 break;
1914 case EOR:
1915 result = op1 ^ op2;
1916 break;
1917 default:
1918 VIXL_UNIMPLEMENTED();
1919 }
1920
1921 if (update_flags) {
1922 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1923 ReadNzcv().SetZ(CalcZFlag(result));
1924 ReadNzcv().SetC(0);
1925 ReadNzcv().SetV(0);
1926 LogSystemRegister(NZCV);
1927 }
1928
1929 WriteRegister(reg_size,
1930 instr->GetRd(),
1931 result,
1932 LogRegWrites,
1933 instr->GetRdMode());
1934 }
1935
1936
VisitConditionalCompareRegister(const Instruction * instr)1937 void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1938 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1939 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1940 }
1941
1942
VisitConditionalCompareImmediate(const Instruction * instr)1943 void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1944 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1945 }
1946
1947
ConditionalCompareHelper(const Instruction * instr,int64_t op2)1948 void Simulator::ConditionalCompareHelper(const Instruction* instr,
1949 int64_t op2) {
1950 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1951 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1952
1953 if (ConditionPassed(instr->GetCondition())) {
1954 // If the condition passes, set the status flags to the result of comparing
1955 // the operands.
1956 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1957 AddWithCarry(reg_size, true, op1, ~op2, 1);
1958 } else {
1959 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1960 AddWithCarry(reg_size, true, op1, op2, 0);
1961 }
1962 } else {
1963 // If the condition fails, set the status flags to the nzcv immediate.
1964 ReadNzcv().SetFlags(instr->GetNzcv());
1965 LogSystemRegister(NZCV);
1966 }
1967 }
1968
1969
VisitLoadStoreUnsignedOffset(const Instruction * instr)1970 void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1971 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1972 LoadStoreHelper(instr, offset, Offset);
1973 }
1974
1975
VisitLoadStoreUnscaledOffset(const Instruction * instr)1976 void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1977 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1978 }
1979
1980
VisitLoadStorePreIndex(const Instruction * instr)1981 void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1982 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1983 }
1984
1985
VisitLoadStorePostIndex(const Instruction * instr)1986 void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1987 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1988 }
1989
1990
1991 template <typename T1, typename T2>
LoadAcquireRCpcUnscaledOffsetHelper(const Instruction * instr)1992 void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
1993 unsigned rt = instr->GetRt();
1994 unsigned rn = instr->GetRn();
1995
1996 unsigned element_size = sizeof(T2);
1997 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1998 int offset = instr->GetImmLS();
1999 address += offset;
2000
2001 // Verify that the address is available to the host.
2002 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2003
2004 // Check the alignment of `address`.
2005 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2006 VIXL_ALIGNMENT_EXCEPTION();
2007 }
2008
2009 WriteRegister<T1>(rt, static_cast<T1>(MemRead<T2>(address)));
2010
2011 // Approximate load-acquire by issuing a full barrier after the load.
2012 __sync_synchronize();
2013
2014 LogRead(rt, GetPrintRegisterFormat(element_size), address);
2015 }
2016
2017
2018 template <typename T>
StoreReleaseUnscaledOffsetHelper(const Instruction * instr)2019 void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
2020 unsigned rt = instr->GetRt();
2021 unsigned rn = instr->GetRn();
2022
2023 unsigned element_size = sizeof(T);
2024 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2025 int offset = instr->GetImmLS();
2026 address += offset;
2027
2028 // Verify that the address is available to the host.
2029 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
2030
2031 // Check the alignment of `address`.
2032 if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
2033 VIXL_ALIGNMENT_EXCEPTION();
2034 }
2035
2036 // Approximate store-release by issuing a full barrier after the load.
2037 __sync_synchronize();
2038
2039 MemWrite<T>(address, ReadRegister<T>(rt));
2040
2041 LogWrite(rt, GetPrintRegisterFormat(element_size), address);
2042 }
2043
2044
VisitLoadStoreRCpcUnscaledOffset(const Instruction * instr)2045 void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
2046 switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
2047 case LDAPURB:
2048 LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
2049 break;
2050 case LDAPURH:
2051 LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
2052 break;
2053 case LDAPUR_w:
2054 LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
2055 break;
2056 case LDAPUR_x:
2057 LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
2058 break;
2059 case LDAPURSB_w:
2060 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
2061 break;
2062 case LDAPURSB_x:
2063 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
2064 break;
2065 case LDAPURSH_w:
2066 LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
2067 break;
2068 case LDAPURSH_x:
2069 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
2070 break;
2071 case LDAPURSW:
2072 LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
2073 break;
2074 case STLURB:
2075 StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
2076 break;
2077 case STLURH:
2078 StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
2079 break;
2080 case STLUR_w:
2081 StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
2082 break;
2083 case STLUR_x:
2084 StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
2085 break;
2086 }
2087 }
2088
2089
VisitLoadStorePAC(const Instruction * instr)2090 void Simulator::VisitLoadStorePAC(const Instruction* instr) {
2091 unsigned dst = instr->GetRt();
2092 unsigned addr_reg = instr->GetRn();
2093
2094 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
2095
2096 PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
2097 address = AuthPAC(address, 0, key, kDataPointer);
2098
2099 int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
2100 if (((address >> error_lsb) & 0x3) != 0x0) {
2101 VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
2102 }
2103
2104
2105 if ((addr_reg == 31) && ((address % 16) != 0)) {
2106 // When the base register is SP the stack pointer is required to be
2107 // quadword aligned prior to the address calculation and write-backs.
2108 // Misalignment will cause a stack alignment fault.
2109 VIXL_ALIGNMENT_EXCEPTION();
2110 }
2111
2112 int64_t offset = instr->GetImmLSPAC();
2113 address += offset;
2114
2115 if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
2116 // Pre-index mode.
2117 VIXL_ASSERT(offset != 0);
2118 WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
2119 }
2120
2121 uintptr_t addr_ptr = static_cast<uintptr_t>(address);
2122
2123 // Verify that the calculated address is available to the host.
2124 VIXL_ASSERT(address == addr_ptr);
2125
2126 WriteXRegister(dst, MemRead<uint64_t>(addr_ptr), NoRegLog);
2127 unsigned access_size = 1 << 3;
2128 LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
2129 }
2130
2131
VisitLoadStoreRegisterOffset(const Instruction * instr)2132 void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
2133 Extend ext = static_cast<Extend>(instr->GetExtendMode());
2134 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
2135 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
2136
2137 int64_t offset =
2138 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
2139 LoadStoreHelper(instr, offset, Offset);
2140 }
2141
2142
LoadStoreHelper(const Instruction * instr,int64_t offset,AddrMode addrmode)2143 void Simulator::LoadStoreHelper(const Instruction* instr,
2144 int64_t offset,
2145 AddrMode addrmode) {
2146 unsigned srcdst = instr->GetRt();
2147 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2148
2149 bool rt_is_vreg = false;
2150 int extend_to_size = 0;
2151 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
2152 switch (op) {
2153 case LDRB_w:
2154 WriteWRegister(srcdst, MemRead<uint8_t>(address), NoRegLog);
2155 extend_to_size = kWRegSizeInBytes;
2156 break;
2157 case LDRH_w:
2158 WriteWRegister(srcdst, MemRead<uint16_t>(address), NoRegLog);
2159 extend_to_size = kWRegSizeInBytes;
2160 break;
2161 case LDR_w:
2162 WriteWRegister(srcdst, MemRead<uint32_t>(address), NoRegLog);
2163 extend_to_size = kWRegSizeInBytes;
2164 break;
2165 case LDR_x:
2166 WriteXRegister(srcdst, MemRead<uint64_t>(address), NoRegLog);
2167 extend_to_size = kXRegSizeInBytes;
2168 break;
2169 case LDRSB_w:
2170 WriteWRegister(srcdst, MemRead<int8_t>(address), NoRegLog);
2171 extend_to_size = kWRegSizeInBytes;
2172 break;
2173 case LDRSH_w:
2174 WriteWRegister(srcdst, MemRead<int16_t>(address), NoRegLog);
2175 extend_to_size = kWRegSizeInBytes;
2176 break;
2177 case LDRSB_x:
2178 WriteXRegister(srcdst, MemRead<int8_t>(address), NoRegLog);
2179 extend_to_size = kXRegSizeInBytes;
2180 break;
2181 case LDRSH_x:
2182 WriteXRegister(srcdst, MemRead<int16_t>(address), NoRegLog);
2183 extend_to_size = kXRegSizeInBytes;
2184 break;
2185 case LDRSW_x:
2186 WriteXRegister(srcdst, MemRead<int32_t>(address), NoRegLog);
2187 extend_to_size = kXRegSizeInBytes;
2188 break;
2189 case LDR_b:
2190 WriteBRegister(srcdst, MemRead<uint8_t>(address), NoRegLog);
2191 rt_is_vreg = true;
2192 break;
2193 case LDR_h:
2194 WriteHRegister(srcdst, MemRead<uint16_t>(address), NoRegLog);
2195 rt_is_vreg = true;
2196 break;
2197 case LDR_s:
2198 WriteSRegister(srcdst, MemRead<float>(address), NoRegLog);
2199 rt_is_vreg = true;
2200 break;
2201 case LDR_d:
2202 WriteDRegister(srcdst, MemRead<double>(address), NoRegLog);
2203 rt_is_vreg = true;
2204 break;
2205 case LDR_q:
2206 WriteQRegister(srcdst, MemRead<qreg_t>(address), NoRegLog);
2207 rt_is_vreg = true;
2208 break;
2209
2210 case STRB_w:
2211 MemWrite<uint8_t>(address, ReadWRegister(srcdst));
2212 break;
2213 case STRH_w:
2214 MemWrite<uint16_t>(address, ReadWRegister(srcdst));
2215 break;
2216 case STR_w:
2217 MemWrite<uint32_t>(address, ReadWRegister(srcdst));
2218 break;
2219 case STR_x:
2220 MemWrite<uint64_t>(address, ReadXRegister(srcdst));
2221 break;
2222 case STR_b:
2223 MemWrite<uint8_t>(address, ReadBRegister(srcdst));
2224 rt_is_vreg = true;
2225 break;
2226 case STR_h:
2227 MemWrite<uint16_t>(address, ReadHRegisterBits(srcdst));
2228 rt_is_vreg = true;
2229 break;
2230 case STR_s:
2231 MemWrite<float>(address, ReadSRegister(srcdst));
2232 rt_is_vreg = true;
2233 break;
2234 case STR_d:
2235 MemWrite<double>(address, ReadDRegister(srcdst));
2236 rt_is_vreg = true;
2237 break;
2238 case STR_q:
2239 MemWrite<qreg_t>(address, ReadQRegister(srcdst));
2240 rt_is_vreg = true;
2241 break;
2242
2243 // Ignore prfm hint instructions.
2244 case PRFM:
2245 break;
2246
2247 default:
2248 VIXL_UNIMPLEMENTED();
2249 }
2250
2251 // Print a detailed trace (including the memory address).
2252 bool extend = (extend_to_size != 0);
2253 unsigned access_size = 1 << instr->GetSizeLS();
2254 unsigned result_size = extend ? extend_to_size : access_size;
2255 PrintRegisterFormat print_format =
2256 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2257 : GetPrintRegisterFormatForSize(result_size);
2258
2259 if (instr->IsLoad()) {
2260 if (rt_is_vreg) {
2261 LogVRead(srcdst, print_format, address);
2262 } else {
2263 LogExtendingRead(srcdst, print_format, access_size, address);
2264 }
2265 } else if (instr->IsStore()) {
2266 if (rt_is_vreg) {
2267 LogVWrite(srcdst, print_format, address);
2268 } else {
2269 LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
2270 }
2271 } else {
2272 VIXL_ASSERT(op == PRFM);
2273 }
2274
2275 local_monitor_.MaybeClear();
2276 }
2277
2278
VisitLoadStorePairOffset(const Instruction * instr)2279 void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
2280 LoadStorePairHelper(instr, Offset);
2281 }
2282
2283
VisitLoadStorePairPreIndex(const Instruction * instr)2284 void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
2285 LoadStorePairHelper(instr, PreIndex);
2286 }
2287
2288
VisitLoadStorePairPostIndex(const Instruction * instr)2289 void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
2290 LoadStorePairHelper(instr, PostIndex);
2291 }
2292
2293
VisitLoadStorePairNonTemporal(const Instruction * instr)2294 void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
2295 LoadStorePairHelper(instr, Offset);
2296 }
2297
2298
LoadStorePairHelper(const Instruction * instr,AddrMode addrmode)2299 void Simulator::LoadStorePairHelper(const Instruction* instr,
2300 AddrMode addrmode) {
2301 unsigned rt = instr->GetRt();
2302 unsigned rt2 = instr->GetRt2();
2303 int element_size = 1 << instr->GetSizeLSPair();
2304 int64_t offset = instr->GetImmLSPair() * element_size;
2305 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
2306 uintptr_t address2 = address + element_size;
2307
2308 LoadStorePairOp op =
2309 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
2310
2311 // 'rt' and 'rt2' can only be aliased for stores.
2312 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
2313
2314 bool rt_is_vreg = false;
2315 bool sign_extend = false;
2316 switch (op) {
2317 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
2318 // will print a more detailed log.
2319 case LDP_w: {
2320 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
2321 WriteWRegister(rt2, MemRead<uint32_t>(address2), NoRegLog);
2322 break;
2323 }
2324 case LDP_s: {
2325 WriteSRegister(rt, MemRead<float>(address), NoRegLog);
2326 WriteSRegister(rt2, MemRead<float>(address2), NoRegLog);
2327 rt_is_vreg = true;
2328 break;
2329 }
2330 case LDP_x: {
2331 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
2332 WriteXRegister(rt2, MemRead<uint64_t>(address2), NoRegLog);
2333 break;
2334 }
2335 case LDP_d: {
2336 WriteDRegister(rt, MemRead<double>(address), NoRegLog);
2337 WriteDRegister(rt2, MemRead<double>(address2), NoRegLog);
2338 rt_is_vreg = true;
2339 break;
2340 }
2341 case LDP_q: {
2342 WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog);
2343 WriteQRegister(rt2, MemRead<qreg_t>(address2), NoRegLog);
2344 rt_is_vreg = true;
2345 break;
2346 }
2347 case LDPSW_x: {
2348 WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog);
2349 WriteXRegister(rt2, MemRead<int32_t>(address2), NoRegLog);
2350 sign_extend = true;
2351 break;
2352 }
2353 case STP_w: {
2354 MemWrite<uint32_t>(address, ReadWRegister(rt));
2355 MemWrite<uint32_t>(address2, ReadWRegister(rt2));
2356 break;
2357 }
2358 case STP_s: {
2359 MemWrite<float>(address, ReadSRegister(rt));
2360 MemWrite<float>(address2, ReadSRegister(rt2));
2361 rt_is_vreg = true;
2362 break;
2363 }
2364 case STP_x: {
2365 MemWrite<uint64_t>(address, ReadXRegister(rt));
2366 MemWrite<uint64_t>(address2, ReadXRegister(rt2));
2367 break;
2368 }
2369 case STP_d: {
2370 MemWrite<double>(address, ReadDRegister(rt));
2371 MemWrite<double>(address2, ReadDRegister(rt2));
2372 rt_is_vreg = true;
2373 break;
2374 }
2375 case STP_q: {
2376 MemWrite<qreg_t>(address, ReadQRegister(rt));
2377 MemWrite<qreg_t>(address2, ReadQRegister(rt2));
2378 rt_is_vreg = true;
2379 break;
2380 }
2381 default:
2382 VIXL_UNREACHABLE();
2383 }
2384
2385 // Print a detailed trace (including the memory address).
2386 unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
2387 PrintRegisterFormat print_format =
2388 rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
2389 : GetPrintRegisterFormatForSize(result_size);
2390
2391 if (instr->IsLoad()) {
2392 if (rt_is_vreg) {
2393 LogVRead(rt, print_format, address);
2394 LogVRead(rt2, print_format, address2);
2395 } else if (sign_extend) {
2396 LogExtendingRead(rt, print_format, element_size, address);
2397 LogExtendingRead(rt2, print_format, element_size, address2);
2398 } else {
2399 LogRead(rt, print_format, address);
2400 LogRead(rt2, print_format, address2);
2401 }
2402 } else {
2403 if (rt_is_vreg) {
2404 LogVWrite(rt, print_format, address);
2405 LogVWrite(rt2, print_format, address2);
2406 } else {
2407 LogWrite(rt, print_format, address);
2408 LogWrite(rt2, print_format, address2);
2409 }
2410 }
2411
2412 local_monitor_.MaybeClear();
2413 }
2414
2415
2416 template <typename T>
CompareAndSwapHelper(const Instruction * instr)2417 void Simulator::CompareAndSwapHelper(const Instruction* instr) {
2418 unsigned rs = instr->GetRs();
2419 unsigned rt = instr->GetRt();
2420 unsigned rn = instr->GetRn();
2421
2422 unsigned element_size = sizeof(T);
2423 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2424
2425 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2426
2427 bool is_acquire = instr->ExtractBit(22) == 1;
2428 bool is_release = instr->ExtractBit(15) == 1;
2429
2430 T comparevalue = ReadRegister<T>(rs);
2431 T newvalue = ReadRegister<T>(rt);
2432
2433 // The architecture permits that the data read clears any exclusive monitors
2434 // associated with that location, even if the compare subsequently fails.
2435 local_monitor_.Clear();
2436
2437 T data = MemRead<T>(address);
2438 if (is_acquire) {
2439 // Approximate load-acquire by issuing a full barrier after the load.
2440 __sync_synchronize();
2441 }
2442
2443 if (data == comparevalue) {
2444 if (is_release) {
2445 // Approximate store-release by issuing a full barrier before the store.
2446 __sync_synchronize();
2447 }
2448 MemWrite<T>(address, newvalue);
2449 LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
2450 }
2451 WriteRegister<T>(rs, data, NoRegLog);
2452 LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
2453 }
2454
2455
2456 template <typename T>
CompareAndSwapPairHelper(const Instruction * instr)2457 void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
2458 VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
2459 unsigned rs = instr->GetRs();
2460 unsigned rt = instr->GetRt();
2461 unsigned rn = instr->GetRn();
2462
2463 VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
2464
2465 unsigned element_size = sizeof(T);
2466 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2467
2468 CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
2469
2470 uint64_t address2 = address + element_size;
2471
2472 bool is_acquire = instr->ExtractBit(22) == 1;
2473 bool is_release = instr->ExtractBit(15) == 1;
2474
2475 T comparevalue_high = ReadRegister<T>(rs + 1);
2476 T comparevalue_low = ReadRegister<T>(rs);
2477 T newvalue_high = ReadRegister<T>(rt + 1);
2478 T newvalue_low = ReadRegister<T>(rt);
2479
2480 // The architecture permits that the data read clears any exclusive monitors
2481 // associated with that location, even if the compare subsequently fails.
2482 local_monitor_.Clear();
2483
2484 T data_low = MemRead<T>(address);
2485 T data_high = MemRead<T>(address2);
2486
2487 if (is_acquire) {
2488 // Approximate load-acquire by issuing a full barrier after the load.
2489 __sync_synchronize();
2490 }
2491
2492 bool same =
2493 (data_high == comparevalue_high) && (data_low == comparevalue_low);
2494 if (same) {
2495 if (is_release) {
2496 // Approximate store-release by issuing a full barrier before the store.
2497 __sync_synchronize();
2498 }
2499
2500 MemWrite<T>(address, newvalue_low);
2501 MemWrite<T>(address2, newvalue_high);
2502 }
2503
2504 WriteRegister<T>(rs + 1, data_high, NoRegLog);
2505 WriteRegister<T>(rs, data_low, NoRegLog);
2506
2507 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2508 LogRead(rs, format, address);
2509 LogRead(rs + 1, format, address2);
2510
2511 if (same) {
2512 LogWrite(rt, format, address);
2513 LogWrite(rt + 1, format, address2);
2514 }
2515 }
2516
CanReadMemory(uintptr_t address,size_t size)2517 bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
2518 // To simulate fault-tolerant loads, we need to know what host addresses we
2519 // can access without generating a real fault. One way to do that is to
2520 // attempt to `write()` the memory to a placeholder pipe[1]. This is more
2521 // portable and less intrusive than using (global) signal handlers.
2522 //
2523 // [1]: https://stackoverflow.com/questions/7134590
2524
2525 size_t written = 0;
2526 bool can_read = true;
2527 // `write` will normally return after one invocation, but it is allowed to
2528 // handle only part of the operation, so wrap it in a loop.
2529 while (can_read && (written < size)) {
2530 ssize_t result = write(placeholder_pipe_fd_[1],
2531 reinterpret_cast<void*>(address + written),
2532 size - written);
2533 if (result > 0) {
2534 written += result;
2535 } else {
2536 switch (result) {
2537 case -EPERM:
2538 case -EFAULT:
2539 // The address range is not accessible.
2540 // `write` is supposed to return -EFAULT in this case, but in practice
2541 // it seems to return -EPERM, so we accept that too.
2542 can_read = false;
2543 break;
2544 case -EINTR:
2545 // The call was interrupted by a signal. Just try again.
2546 break;
2547 default:
2548 // Any other error is fatal.
2549 VIXL_ABORT();
2550 }
2551 }
2552 }
2553 // Drain the read side of the pipe. If we don't do this, we'll leak memory as
2554 // the placeholder data is buffered. As before, we expect to drain the whole
2555 // write in one invocation, but cannot guarantee that, so we wrap it in a
2556 // loop. This function is primarily intended to implement SVE fault-tolerant
2557 // loads, so the maximum Z register size is a good default buffer size.
2558 char buffer[kZRegMaxSizeInBytes];
2559 while (written > 0) {
2560 ssize_t result = read(placeholder_pipe_fd_[0],
2561 reinterpret_cast<void*>(buffer),
2562 sizeof(buffer));
2563 // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
2564 // we've read everything that was written, so treat 0 as an error.
2565 if (result > 0) {
2566 VIXL_ASSERT(static_cast<size_t>(result) <= written);
2567 written -= result;
2568 } else {
2569 // For -EINTR, just try again. We can't handle any other error.
2570 VIXL_CHECK(result == -EINTR);
2571 }
2572 }
2573
2574 return can_read;
2575 }
2576
PrintExclusiveAccessWarning()2577 void Simulator::PrintExclusiveAccessWarning() {
2578 if (print_exclusive_access_warning_) {
2579 fprintf(stderr,
2580 "%sWARNING:%s VIXL simulator support for "
2581 "load-/store-/clear-exclusive "
2582 "instructions is limited. Refer to the README for details.%s\n",
2583 clr_warning,
2584 clr_warning_message,
2585 clr_normal);
2586 print_exclusive_access_warning_ = false;
2587 }
2588 }
2589
VisitLoadStoreExclusive(const Instruction * instr)2590 void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
2591 LoadStoreExclusive op =
2592 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
2593
2594 switch (op) {
2595 case CAS_w:
2596 case CASA_w:
2597 case CASL_w:
2598 case CASAL_w:
2599 CompareAndSwapHelper<uint32_t>(instr);
2600 break;
2601 case CAS_x:
2602 case CASA_x:
2603 case CASL_x:
2604 case CASAL_x:
2605 CompareAndSwapHelper<uint64_t>(instr);
2606 break;
2607 case CASB:
2608 case CASAB:
2609 case CASLB:
2610 case CASALB:
2611 CompareAndSwapHelper<uint8_t>(instr);
2612 break;
2613 case CASH:
2614 case CASAH:
2615 case CASLH:
2616 case CASALH:
2617 CompareAndSwapHelper<uint16_t>(instr);
2618 break;
2619 case CASP_w:
2620 case CASPA_w:
2621 case CASPL_w:
2622 case CASPAL_w:
2623 CompareAndSwapPairHelper<uint32_t>(instr);
2624 break;
2625 case CASP_x:
2626 case CASPA_x:
2627 case CASPL_x:
2628 case CASPAL_x:
2629 CompareAndSwapPairHelper<uint64_t>(instr);
2630 break;
2631 default:
2632 PrintExclusiveAccessWarning();
2633
2634 unsigned rs = instr->GetRs();
2635 unsigned rt = instr->GetRt();
2636 unsigned rt2 = instr->GetRt2();
2637 unsigned rn = instr->GetRn();
2638
2639 bool is_exclusive = !instr->GetLdStXNotExclusive();
2640 bool is_acquire_release =
2641 !is_exclusive || instr->GetLdStXAcquireRelease();
2642 bool is_load = instr->GetLdStXLoad();
2643 bool is_pair = instr->GetLdStXPair();
2644
2645 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
2646 unsigned access_size = is_pair ? element_size * 2 : element_size;
2647 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2648
2649 CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
2650
2651 if (is_load) {
2652 if (is_exclusive) {
2653 local_monitor_.MarkExclusive(address, access_size);
2654 } else {
2655 // Any non-exclusive load can clear the local monitor as a side
2656 // effect. We don't need to do this, but it is useful to stress the
2657 // simulated code.
2658 local_monitor_.Clear();
2659 }
2660
2661 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
2662 // We will print a more detailed log.
2663 unsigned reg_size = 0;
2664 switch (op) {
2665 case LDXRB_w:
2666 case LDAXRB_w:
2667 case LDARB_w:
2668 case LDLARB:
2669 WriteWRegister(rt, MemRead<uint8_t>(address), NoRegLog);
2670 reg_size = kWRegSizeInBytes;
2671 break;
2672 case LDXRH_w:
2673 case LDAXRH_w:
2674 case LDARH_w:
2675 case LDLARH:
2676 WriteWRegister(rt, MemRead<uint16_t>(address), NoRegLog);
2677 reg_size = kWRegSizeInBytes;
2678 break;
2679 case LDXR_w:
2680 case LDAXR_w:
2681 case LDAR_w:
2682 case LDLAR_w:
2683 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
2684 reg_size = kWRegSizeInBytes;
2685 break;
2686 case LDXR_x:
2687 case LDAXR_x:
2688 case LDAR_x:
2689 case LDLAR_x:
2690 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
2691 reg_size = kXRegSizeInBytes;
2692 break;
2693 case LDXP_w:
2694 case LDAXP_w:
2695 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
2696 WriteWRegister(rt2,
2697 MemRead<uint32_t>(address + element_size),
2698 NoRegLog);
2699 reg_size = kWRegSizeInBytes;
2700 break;
2701 case LDXP_x:
2702 case LDAXP_x:
2703 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
2704 WriteXRegister(rt2,
2705 MemRead<uint64_t>(address + element_size),
2706 NoRegLog);
2707 reg_size = kXRegSizeInBytes;
2708 break;
2709 default:
2710 VIXL_UNREACHABLE();
2711 }
2712
2713 if (is_acquire_release) {
2714 // Approximate load-acquire by issuing a full barrier after the load.
2715 __sync_synchronize();
2716 }
2717
2718 PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
2719 LogExtendingRead(rt, format, element_size, address);
2720 if (is_pair) {
2721 LogExtendingRead(rt2, format, element_size, address + element_size);
2722 }
2723 } else {
2724 if (is_acquire_release) {
2725 // Approximate store-release by issuing a full barrier before the
2726 // store.
2727 __sync_synchronize();
2728 }
2729
2730 bool do_store = true;
2731 if (is_exclusive) {
2732 do_store = local_monitor_.IsExclusive(address, access_size) &&
2733 global_monitor_.IsExclusive(address, access_size);
2734 WriteWRegister(rs, do_store ? 0 : 1);
2735
2736 // - All exclusive stores explicitly clear the local monitor.
2737 local_monitor_.Clear();
2738 } else {
2739 // - Any other store can clear the local monitor as a side effect.
2740 local_monitor_.MaybeClear();
2741 }
2742
2743 if (do_store) {
2744 switch (op) {
2745 case STXRB_w:
2746 case STLXRB_w:
2747 case STLRB_w:
2748 case STLLRB:
2749 MemWrite<uint8_t>(address, ReadWRegister(rt));
2750 break;
2751 case STXRH_w:
2752 case STLXRH_w:
2753 case STLRH_w:
2754 case STLLRH:
2755 MemWrite<uint16_t>(address, ReadWRegister(rt));
2756 break;
2757 case STXR_w:
2758 case STLXR_w:
2759 case STLR_w:
2760 case STLLR_w:
2761 MemWrite<uint32_t>(address, ReadWRegister(rt));
2762 break;
2763 case STXR_x:
2764 case STLXR_x:
2765 case STLR_x:
2766 case STLLR_x:
2767 MemWrite<uint64_t>(address, ReadXRegister(rt));
2768 break;
2769 case STXP_w:
2770 case STLXP_w:
2771 MemWrite<uint32_t>(address, ReadWRegister(rt));
2772 MemWrite<uint32_t>(address + element_size, ReadWRegister(rt2));
2773 break;
2774 case STXP_x:
2775 case STLXP_x:
2776 MemWrite<uint64_t>(address, ReadXRegister(rt));
2777 MemWrite<uint64_t>(address + element_size, ReadXRegister(rt2));
2778 break;
2779 default:
2780 VIXL_UNREACHABLE();
2781 }
2782
2783 PrintRegisterFormat format =
2784 GetPrintRegisterFormatForSize(element_size);
2785 LogWrite(rt, format, address);
2786 if (is_pair) {
2787 LogWrite(rt2, format, address + element_size);
2788 }
2789 }
2790 }
2791 }
2792 }
2793
2794 template <typename T>
AtomicMemorySimpleHelper(const Instruction * instr)2795 void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
2796 unsigned rs = instr->GetRs();
2797 unsigned rt = instr->GetRt();
2798 unsigned rn = instr->GetRn();
2799
2800 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2801 bool is_release = instr->ExtractBit(22) == 1;
2802
2803 unsigned element_size = sizeof(T);
2804 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2805
2806 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2807
2808 T value = ReadRegister<T>(rs);
2809
2810 T data = MemRead<T>(address);
2811
2812 if (is_acquire) {
2813 // Approximate load-acquire by issuing a full barrier after the load.
2814 __sync_synchronize();
2815 }
2816
2817 T result = 0;
2818 switch (instr->Mask(AtomicMemorySimpleOpMask)) {
2819 case LDADDOp:
2820 result = data + value;
2821 break;
2822 case LDCLROp:
2823 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2824 result = data & ~value;
2825 break;
2826 case LDEOROp:
2827 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2828 result = data ^ value;
2829 break;
2830 case LDSETOp:
2831 VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
2832 result = data | value;
2833 break;
2834
2835 // Signed/Unsigned difference is done via the templated type T.
2836 case LDSMAXOp:
2837 case LDUMAXOp:
2838 result = (data > value) ? data : value;
2839 break;
2840 case LDSMINOp:
2841 case LDUMINOp:
2842 result = (data > value) ? value : data;
2843 break;
2844 }
2845
2846 if (is_release) {
2847 // Approximate store-release by issuing a full barrier before the store.
2848 __sync_synchronize();
2849 }
2850
2851 MemWrite<T>(address, result);
2852 WriteRegister<T>(rt, data, NoRegLog);
2853
2854 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2855 LogRead(rt, format, address);
2856 LogWrite(rs, format, address);
2857 }
2858
2859 template <typename T>
AtomicMemorySwapHelper(const Instruction * instr)2860 void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
2861 unsigned rs = instr->GetRs();
2862 unsigned rt = instr->GetRt();
2863 unsigned rn = instr->GetRn();
2864
2865 bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
2866 bool is_release = instr->ExtractBit(22) == 1;
2867
2868 unsigned element_size = sizeof(T);
2869 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2870
2871 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2872
2873 T data = MemRead<T>(address);
2874 if (is_acquire) {
2875 // Approximate load-acquire by issuing a full barrier after the load.
2876 __sync_synchronize();
2877 }
2878
2879 if (is_release) {
2880 // Approximate store-release by issuing a full barrier before the store.
2881 __sync_synchronize();
2882 }
2883 MemWrite<T>(address, ReadRegister<T>(rs));
2884
2885 WriteRegister<T>(rt, data);
2886
2887 PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
2888 LogRead(rt, format, address);
2889 LogWrite(rs, format, address);
2890 }
2891
2892 template <typename T>
LoadAcquireRCpcHelper(const Instruction * instr)2893 void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
2894 unsigned rt = instr->GetRt();
2895 unsigned rn = instr->GetRn();
2896
2897 unsigned element_size = sizeof(T);
2898 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
2899
2900 CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
2901
2902 WriteRegister<T>(rt, MemRead<T>(address));
2903
2904 // Approximate load-acquire by issuing a full barrier after the load.
2905 __sync_synchronize();
2906
2907 LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
2908 }
2909
2910 #define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
2911 V(LDADD) \
2912 V(LDCLR) \
2913 V(LDEOR) \
2914 V(LDSET) \
2915 V(LDUMAX) \
2916 V(LDUMIN)
2917
2918 #define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
2919 V(LDSMAX) \
2920 V(LDSMIN)
2921
VisitAtomicMemory(const Instruction * instr)2922 void Simulator::VisitAtomicMemory(const Instruction* instr) {
2923 switch (instr->Mask(AtomicMemoryMask)) {
2924 // clang-format off
2925 #define SIM_FUNC_B(A) \
2926 case A##B: \
2927 case A##AB: \
2928 case A##LB: \
2929 case A##ALB:
2930 #define SIM_FUNC_H(A) \
2931 case A##H: \
2932 case A##AH: \
2933 case A##LH: \
2934 case A##ALH:
2935 #define SIM_FUNC_w(A) \
2936 case A##_w: \
2937 case A##A_w: \
2938 case A##L_w: \
2939 case A##AL_w:
2940 #define SIM_FUNC_x(A) \
2941 case A##_x: \
2942 case A##A_x: \
2943 case A##L_x: \
2944 case A##AL_x:
2945
2946 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
2947 AtomicMemorySimpleHelper<uint8_t>(instr);
2948 break;
2949 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
2950 AtomicMemorySimpleHelper<int8_t>(instr);
2951 break;
2952 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
2953 AtomicMemorySimpleHelper<uint16_t>(instr);
2954 break;
2955 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
2956 AtomicMemorySimpleHelper<int16_t>(instr);
2957 break;
2958 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
2959 AtomicMemorySimpleHelper<uint32_t>(instr);
2960 break;
2961 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
2962 AtomicMemorySimpleHelper<int32_t>(instr);
2963 break;
2964 ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
2965 AtomicMemorySimpleHelper<uint64_t>(instr);
2966 break;
2967 ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
2968 AtomicMemorySimpleHelper<int64_t>(instr);
2969 break;
2970 // clang-format on
2971
2972 case SWPB:
2973 case SWPAB:
2974 case SWPLB:
2975 case SWPALB:
2976 AtomicMemorySwapHelper<uint8_t>(instr);
2977 break;
2978 case SWPH:
2979 case SWPAH:
2980 case SWPLH:
2981 case SWPALH:
2982 AtomicMemorySwapHelper<uint16_t>(instr);
2983 break;
2984 case SWP_w:
2985 case SWPA_w:
2986 case SWPL_w:
2987 case SWPAL_w:
2988 AtomicMemorySwapHelper<uint32_t>(instr);
2989 break;
2990 case SWP_x:
2991 case SWPA_x:
2992 case SWPL_x:
2993 case SWPAL_x:
2994 AtomicMemorySwapHelper<uint64_t>(instr);
2995 break;
2996 case LDAPRB:
2997 LoadAcquireRCpcHelper<uint8_t>(instr);
2998 break;
2999 case LDAPRH:
3000 LoadAcquireRCpcHelper<uint16_t>(instr);
3001 break;
3002 case LDAPR_w:
3003 LoadAcquireRCpcHelper<uint32_t>(instr);
3004 break;
3005 case LDAPR_x:
3006 LoadAcquireRCpcHelper<uint64_t>(instr);
3007 break;
3008 }
3009 }
3010
3011
VisitLoadLiteral(const Instruction * instr)3012 void Simulator::VisitLoadLiteral(const Instruction* instr) {
3013 unsigned rt = instr->GetRt();
3014 uint64_t address = instr->GetLiteralAddress<uint64_t>();
3015
3016 // Verify that the calculated address is available to the host.
3017 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3018
3019 switch (instr->Mask(LoadLiteralMask)) {
3020 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
3021 // print a more detailed log.
3022 case LDR_w_lit:
3023 WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
3024 LogRead(rt, kPrintWReg, address);
3025 break;
3026 case LDR_x_lit:
3027 WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
3028 LogRead(rt, kPrintXReg, address);
3029 break;
3030 case LDR_s_lit:
3031 WriteSRegister(rt, MemRead<float>(address), NoRegLog);
3032 LogVRead(rt, kPrintSRegFP, address);
3033 break;
3034 case LDR_d_lit:
3035 WriteDRegister(rt, MemRead<double>(address), NoRegLog);
3036 LogVRead(rt, kPrintDRegFP, address);
3037 break;
3038 case LDR_q_lit:
3039 WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog);
3040 LogVRead(rt, kPrintReg1Q, address);
3041 break;
3042 case LDRSW_x_lit:
3043 WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog);
3044 LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
3045 break;
3046
3047 // Ignore prfm hint instructions.
3048 case PRFM_lit:
3049 break;
3050
3051 default:
3052 VIXL_UNREACHABLE();
3053 }
3054
3055 local_monitor_.MaybeClear();
3056 }
3057
3058
AddressModeHelper(unsigned addr_reg,int64_t offset,AddrMode addrmode)3059 uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
3060 int64_t offset,
3061 AddrMode addrmode) {
3062 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
3063
3064 if ((addr_reg == 31) && ((address % 16) != 0)) {
3065 // When the base register is SP the stack pointer is required to be
3066 // quadword aligned prior to the address calculation and write-backs.
3067 // Misalignment will cause a stack alignment fault.
3068 VIXL_ALIGNMENT_EXCEPTION();
3069 }
3070
3071 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
3072 VIXL_ASSERT(offset != 0);
3073 // Only preindex should log the register update here. For Postindex, the
3074 // update will be printed automatically by LogWrittenRegisters _after_ the
3075 // memory access itself is logged.
3076 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
3077 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
3078 }
3079
3080 if ((addrmode == Offset) || (addrmode == PreIndex)) {
3081 address += offset;
3082 }
3083
3084 // Verify that the calculated address is available to the host.
3085 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3086
3087 return static_cast<uintptr_t>(address);
3088 }
3089
3090
VisitMoveWideImmediate(const Instruction * instr)3091 void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
3092 MoveWideImmediateOp mov_op =
3093 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
3094 int64_t new_xn_val = 0;
3095
3096 bool is_64_bits = instr->GetSixtyFourBits() == 1;
3097 // Shift is limited for W operations.
3098 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
3099
3100 // Get the shifted immediate.
3101 int64_t shift = instr->GetShiftMoveWide() * 16;
3102 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
3103 << shift;
3104
3105 // Compute the new value.
3106 switch (mov_op) {
3107 case MOVN_w:
3108 case MOVN_x: {
3109 new_xn_val = ~shifted_imm16;
3110 if (!is_64_bits) new_xn_val &= kWRegMask;
3111 break;
3112 }
3113 case MOVK_w:
3114 case MOVK_x: {
3115 unsigned reg_code = instr->GetRd();
3116 int64_t prev_xn_val =
3117 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
3118 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
3119 break;
3120 }
3121 case MOVZ_w:
3122 case MOVZ_x: {
3123 new_xn_val = shifted_imm16;
3124 break;
3125 }
3126 default:
3127 VIXL_UNREACHABLE();
3128 }
3129
3130 // Update the destination register.
3131 WriteXRegister(instr->GetRd(), new_xn_val);
3132 }
3133
3134
VisitConditionalSelect(const Instruction * instr)3135 void Simulator::VisitConditionalSelect(const Instruction* instr) {
3136 uint64_t new_val = ReadXRegister(instr->GetRn());
3137
3138 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
3139 new_val = ReadXRegister(instr->GetRm());
3140 switch (instr->Mask(ConditionalSelectMask)) {
3141 case CSEL_w:
3142 case CSEL_x:
3143 break;
3144 case CSINC_w:
3145 case CSINC_x:
3146 new_val++;
3147 break;
3148 case CSINV_w:
3149 case CSINV_x:
3150 new_val = ~new_val;
3151 break;
3152 case CSNEG_w:
3153 case CSNEG_x:
3154 new_val = -new_val;
3155 break;
3156 default:
3157 VIXL_UNIMPLEMENTED();
3158 }
3159 }
3160 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3161 WriteRegister(reg_size, instr->GetRd(), new_val);
3162 }
3163
3164
3165 // clang-format off
3166 #define PAUTH_MODES(V) \
3167 V(IA, ReadXRegister(src), kPACKeyIA, kInstructionPointer) \
3168 V(IB, ReadXRegister(src), kPACKeyIB, kInstructionPointer) \
3169 V(IZA, 0x00000000, kPACKeyIA, kInstructionPointer) \
3170 V(IZB, 0x00000000, kPACKeyIB, kInstructionPointer) \
3171 V(DA, ReadXRegister(src), kPACKeyDA, kDataPointer) \
3172 V(DB, ReadXRegister(src), kPACKeyDB, kDataPointer) \
3173 V(DZA, 0x00000000, kPACKeyDA, kDataPointer) \
3174 V(DZB, 0x00000000, kPACKeyDB, kDataPointer)
3175 // clang-format on
3176
VisitDataProcessing1Source(const Instruction * instr)3177 void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
3178 unsigned dst = instr->GetRd();
3179 unsigned src = instr->GetRn();
3180
3181 switch (instr->Mask(DataProcessing1SourceMask)) {
3182 #define DEFINE_PAUTH_FUNCS(SUFFIX, MOD, KEY, D) \
3183 case PAC##SUFFIX: { \
3184 uint64_t ptr = ReadXRegister(dst); \
3185 WriteXRegister(dst, AddPAC(ptr, MOD, KEY, D)); \
3186 break; \
3187 } \
3188 case AUT##SUFFIX: { \
3189 uint64_t ptr = ReadXRegister(dst); \
3190 WriteXRegister(dst, AuthPAC(ptr, MOD, KEY, D)); \
3191 break; \
3192 }
3193
3194 PAUTH_MODES(DEFINE_PAUTH_FUNCS)
3195 #undef DEFINE_PAUTH_FUNCS
3196
3197 case XPACI:
3198 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
3199 break;
3200 case XPACD:
3201 WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
3202 break;
3203 case RBIT_w:
3204 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
3205 break;
3206 case RBIT_x:
3207 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
3208 break;
3209 case REV16_w:
3210 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
3211 break;
3212 case REV16_x:
3213 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
3214 break;
3215 case REV_w:
3216 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
3217 break;
3218 case REV32_x:
3219 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
3220 break;
3221 case REV_x:
3222 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
3223 break;
3224 case CLZ_w:
3225 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
3226 break;
3227 case CLZ_x:
3228 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
3229 break;
3230 case CLS_w:
3231 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
3232 break;
3233 case CLS_x:
3234 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
3235 break;
3236 default:
3237 VIXL_UNIMPLEMENTED();
3238 }
3239 }
3240
3241
Poly32Mod2(unsigned n,uint64_t data,uint32_t poly)3242 uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
3243 VIXL_ASSERT((n > 32) && (n <= 64));
3244 for (unsigned i = (n - 1); i >= 32; i--) {
3245 if (((data >> i) & 1) != 0) {
3246 uint64_t polysh32 = (uint64_t)poly << (i - 32);
3247 uint64_t mask = (UINT64_C(1) << i) - 1;
3248 data = ((data & mask) ^ polysh32);
3249 }
3250 }
3251 return data & 0xffffffff;
3252 }
3253
3254
3255 template <typename T>
Crc32Checksum(uint32_t acc,T val,uint32_t poly)3256 uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
3257 unsigned size = sizeof(val) * 8; // Number of bits in type T.
3258 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
3259 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
3260 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
3261 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
3262 }
3263
3264
Crc32Checksum(uint32_t acc,uint64_t val,uint32_t poly)3265 uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
3266 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
3267 // the CRC of each 32-bit word sequentially.
3268 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
3269 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
3270 }
3271
3272
VisitDataProcessing2Source(const Instruction * instr)3273 void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
3274 Shift shift_op = NO_SHIFT;
3275 int64_t result = 0;
3276 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3277
3278 switch (instr->Mask(DataProcessing2SourceMask)) {
3279 case SDIV_w: {
3280 int32_t rn = ReadWRegister(instr->GetRn());
3281 int32_t rm = ReadWRegister(instr->GetRm());
3282 if ((rn == kWMinInt) && (rm == -1)) {
3283 result = kWMinInt;
3284 } else if (rm == 0) {
3285 // Division by zero can be trapped, but not on A-class processors.
3286 result = 0;
3287 } else {
3288 result = rn / rm;
3289 }
3290 break;
3291 }
3292 case SDIV_x: {
3293 int64_t rn = ReadXRegister(instr->GetRn());
3294 int64_t rm = ReadXRegister(instr->GetRm());
3295 if ((rn == kXMinInt) && (rm == -1)) {
3296 result = kXMinInt;
3297 } else if (rm == 0) {
3298 // Division by zero can be trapped, but not on A-class processors.
3299 result = 0;
3300 } else {
3301 result = rn / rm;
3302 }
3303 break;
3304 }
3305 case UDIV_w: {
3306 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
3307 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
3308 if (rm == 0) {
3309 // Division by zero can be trapped, but not on A-class processors.
3310 result = 0;
3311 } else {
3312 result = rn / rm;
3313 }
3314 break;
3315 }
3316 case UDIV_x: {
3317 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3318 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
3319 if (rm == 0) {
3320 // Division by zero can be trapped, but not on A-class processors.
3321 result = 0;
3322 } else {
3323 result = rn / rm;
3324 }
3325 break;
3326 }
3327 case LSLV_w:
3328 case LSLV_x:
3329 shift_op = LSL;
3330 break;
3331 case LSRV_w:
3332 case LSRV_x:
3333 shift_op = LSR;
3334 break;
3335 case ASRV_w:
3336 case ASRV_x:
3337 shift_op = ASR;
3338 break;
3339 case RORV_w:
3340 case RORV_x:
3341 shift_op = ROR;
3342 break;
3343 case PACGA: {
3344 uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
3345 uint64_t src = static_cast<uint64_t>(
3346 ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
3347 uint64_t code = ComputePAC(dst, src, kPACKeyGA);
3348 result = code & 0xffffffff00000000;
3349 break;
3350 }
3351 case CRC32B: {
3352 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3353 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3354 result = Crc32Checksum(acc, val, CRC32_POLY);
3355 break;
3356 }
3357 case CRC32H: {
3358 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3359 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3360 result = Crc32Checksum(acc, val, CRC32_POLY);
3361 break;
3362 }
3363 case CRC32W: {
3364 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3365 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3366 result = Crc32Checksum(acc, val, CRC32_POLY);
3367 break;
3368 }
3369 case CRC32X: {
3370 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3371 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3372 result = Crc32Checksum(acc, val, CRC32_POLY);
3373 reg_size = kWRegSize;
3374 break;
3375 }
3376 case CRC32CB: {
3377 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3378 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
3379 result = Crc32Checksum(acc, val, CRC32C_POLY);
3380 break;
3381 }
3382 case CRC32CH: {
3383 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3384 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
3385 result = Crc32Checksum(acc, val, CRC32C_POLY);
3386 break;
3387 }
3388 case CRC32CW: {
3389 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3390 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
3391 result = Crc32Checksum(acc, val, CRC32C_POLY);
3392 break;
3393 }
3394 case CRC32CX: {
3395 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
3396 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
3397 result = Crc32Checksum(acc, val, CRC32C_POLY);
3398 reg_size = kWRegSize;
3399 break;
3400 }
3401 default:
3402 VIXL_UNIMPLEMENTED();
3403 }
3404
3405 if (shift_op != NO_SHIFT) {
3406 // Shift distance encoded in the least-significant five/six bits of the
3407 // register.
3408 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
3409 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
3410 result = ShiftOperand(reg_size,
3411 ReadRegister(reg_size, instr->GetRn()),
3412 shift_op,
3413 shift);
3414 }
3415 WriteRegister(reg_size, instr->GetRd(), result);
3416 }
3417
3418
VisitDataProcessing3Source(const Instruction * instr)3419 void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
3420 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3421
3422 uint64_t result = 0;
3423 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
3424 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
3425 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
3426 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
3427 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
3428 uint64_t rn_u64 = ReadXRegister(instr->GetRn());
3429 uint64_t rm_u64 = ReadXRegister(instr->GetRm());
3430 switch (instr->Mask(DataProcessing3SourceMask)) {
3431 case MADD_w:
3432 case MADD_x:
3433 result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
3434 break;
3435 case MSUB_w:
3436 case MSUB_x:
3437 result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
3438 break;
3439 case SMADDL_x:
3440 result = ReadXRegister(instr->GetRa()) +
3441 static_cast<uint64_t>(rn_s32 * rm_s32);
3442 break;
3443 case SMSUBL_x:
3444 result = ReadXRegister(instr->GetRa()) -
3445 static_cast<uint64_t>(rn_s32 * rm_s32);
3446 break;
3447 case UMADDL_x:
3448 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
3449 break;
3450 case UMSUBL_x:
3451 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
3452 break;
3453 case UMULH_x:
3454 result =
3455 internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
3456 ReadRegister<uint64_t>(instr->GetRm()));
3457 break;
3458 case SMULH_x:
3459 result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
3460 ReadXRegister(instr->GetRm()));
3461 break;
3462 default:
3463 VIXL_UNIMPLEMENTED();
3464 }
3465 WriteRegister(reg_size, instr->GetRd(), result);
3466 }
3467
3468
VisitBitfield(const Instruction * instr)3469 void Simulator::VisitBitfield(const Instruction* instr) {
3470 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3471 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
3472 int R = instr->GetImmR();
3473 int S = instr->GetImmS();
3474 int diff = S - R;
3475 uint64_t mask;
3476 if (diff >= 0) {
3477 mask = ~UINT64_C(0) >> (64 - (diff + 1));
3478 mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
3479 } else {
3480 mask = ~UINT64_C(0) >> (64 - (S + 1));
3481 mask = RotateRight(mask, R, reg_size);
3482 diff += reg_size;
3483 }
3484
3485 // inzero indicates if the extracted bitfield is inserted into the
3486 // destination register value or in zero.
3487 // If extend is true, extend the sign of the extracted bitfield.
3488 bool inzero = false;
3489 bool extend = false;
3490 switch (instr->Mask(BitfieldMask)) {
3491 case BFM_x:
3492 case BFM_w:
3493 break;
3494 case SBFM_x:
3495 case SBFM_w:
3496 inzero = true;
3497 extend = true;
3498 break;
3499 case UBFM_x:
3500 case UBFM_w:
3501 inzero = true;
3502 break;
3503 default:
3504 VIXL_UNIMPLEMENTED();
3505 }
3506
3507 uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
3508 uint64_t src = ReadRegister(reg_size, instr->GetRn());
3509 // Rotate source bitfield into place.
3510 uint64_t result = RotateRight(src, R, reg_size);
3511 // Determine the sign extension.
3512 uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
3513 uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
3514
3515 // Merge sign extension, dest/zero and bitfield.
3516 result = signbits | (result & mask) | (dst & ~mask);
3517
3518 WriteRegister(reg_size, instr->GetRd(), result);
3519 }
3520
3521
VisitExtract(const Instruction * instr)3522 void Simulator::VisitExtract(const Instruction* instr) {
3523 unsigned lsb = instr->GetImmS();
3524 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
3525 uint64_t low_res =
3526 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
3527 uint64_t high_res = (lsb == 0)
3528 ? 0
3529 : ReadRegister<uint64_t>(reg_size, instr->GetRn())
3530 << (reg_size - lsb);
3531 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
3532 }
3533
3534
VisitFPImmediate(const Instruction * instr)3535 void Simulator::VisitFPImmediate(const Instruction* instr) {
3536 AssertSupportedFPCR();
3537 unsigned dest = instr->GetRd();
3538 switch (instr->Mask(FPImmediateMask)) {
3539 case FMOV_h_imm:
3540 WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
3541 break;
3542 case FMOV_s_imm:
3543 WriteSRegister(dest, instr->GetImmFP32());
3544 break;
3545 case FMOV_d_imm:
3546 WriteDRegister(dest, instr->GetImmFP64());
3547 break;
3548 default:
3549 VIXL_UNREACHABLE();
3550 }
3551 }
3552
3553
VisitFPIntegerConvert(const Instruction * instr)3554 void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
3555 AssertSupportedFPCR();
3556
3557 unsigned dst = instr->GetRd();
3558 unsigned src = instr->GetRn();
3559
3560 FPRounding round = ReadRMode();
3561
3562 switch (instr->Mask(FPIntegerConvertMask)) {
3563 case FCVTAS_wh:
3564 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
3565 break;
3566 case FCVTAS_xh:
3567 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
3568 break;
3569 case FCVTAS_ws:
3570 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
3571 break;
3572 case FCVTAS_xs:
3573 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
3574 break;
3575 case FCVTAS_wd:
3576 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
3577 break;
3578 case FCVTAS_xd:
3579 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
3580 break;
3581 case FCVTAU_wh:
3582 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
3583 break;
3584 case FCVTAU_xh:
3585 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
3586 break;
3587 case FCVTAU_ws:
3588 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
3589 break;
3590 case FCVTAU_xs:
3591 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
3592 break;
3593 case FCVTAU_wd:
3594 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
3595 break;
3596 case FCVTAU_xd:
3597 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
3598 break;
3599 case FCVTMS_wh:
3600 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
3601 break;
3602 case FCVTMS_xh:
3603 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
3604 break;
3605 case FCVTMS_ws:
3606 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
3607 break;
3608 case FCVTMS_xs:
3609 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
3610 break;
3611 case FCVTMS_wd:
3612 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
3613 break;
3614 case FCVTMS_xd:
3615 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
3616 break;
3617 case FCVTMU_wh:
3618 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
3619 break;
3620 case FCVTMU_xh:
3621 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
3622 break;
3623 case FCVTMU_ws:
3624 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
3625 break;
3626 case FCVTMU_xs:
3627 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
3628 break;
3629 case FCVTMU_wd:
3630 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
3631 break;
3632 case FCVTMU_xd:
3633 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
3634 break;
3635 case FCVTPS_wh:
3636 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
3637 break;
3638 case FCVTPS_xh:
3639 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
3640 break;
3641 case FCVTPS_ws:
3642 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
3643 break;
3644 case FCVTPS_xs:
3645 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
3646 break;
3647 case FCVTPS_wd:
3648 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
3649 break;
3650 case FCVTPS_xd:
3651 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
3652 break;
3653 case FCVTPU_wh:
3654 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
3655 break;
3656 case FCVTPU_xh:
3657 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
3658 break;
3659 case FCVTPU_ws:
3660 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
3661 break;
3662 case FCVTPU_xs:
3663 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
3664 break;
3665 case FCVTPU_wd:
3666 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
3667 break;
3668 case FCVTPU_xd:
3669 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
3670 break;
3671 case FCVTNS_wh:
3672 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
3673 break;
3674 case FCVTNS_xh:
3675 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
3676 break;
3677 case FCVTNS_ws:
3678 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
3679 break;
3680 case FCVTNS_xs:
3681 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
3682 break;
3683 case FCVTNS_wd:
3684 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
3685 break;
3686 case FCVTNS_xd:
3687 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
3688 break;
3689 case FCVTNU_wh:
3690 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
3691 break;
3692 case FCVTNU_xh:
3693 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
3694 break;
3695 case FCVTNU_ws:
3696 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
3697 break;
3698 case FCVTNU_xs:
3699 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
3700 break;
3701 case FCVTNU_wd:
3702 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
3703 break;
3704 case FCVTNU_xd:
3705 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
3706 break;
3707 case FCVTZS_wh:
3708 WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
3709 break;
3710 case FCVTZS_xh:
3711 WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
3712 break;
3713 case FCVTZS_ws:
3714 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
3715 break;
3716 case FCVTZS_xs:
3717 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
3718 break;
3719 case FCVTZS_wd:
3720 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
3721 break;
3722 case FCVTZS_xd:
3723 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
3724 break;
3725 case FCVTZU_wh:
3726 WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
3727 break;
3728 case FCVTZU_xh:
3729 WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
3730 break;
3731 case FCVTZU_ws:
3732 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
3733 break;
3734 case FCVTZU_xs:
3735 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
3736 break;
3737 case FCVTZU_wd:
3738 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
3739 break;
3740 case FCVTZU_xd:
3741 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
3742 break;
3743 case FJCVTZS:
3744 WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
3745 break;
3746 case FMOV_hw:
3747 WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
3748 break;
3749 case FMOV_wh:
3750 WriteWRegister(dst, ReadHRegisterBits(src));
3751 break;
3752 case FMOV_xh:
3753 WriteXRegister(dst, ReadHRegisterBits(src));
3754 break;
3755 case FMOV_hx:
3756 WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
3757 break;
3758 case FMOV_ws:
3759 WriteWRegister(dst, ReadSRegisterBits(src));
3760 break;
3761 case FMOV_xd:
3762 WriteXRegister(dst, ReadDRegisterBits(src));
3763 break;
3764 case FMOV_sw:
3765 WriteSRegisterBits(dst, ReadWRegister(src));
3766 break;
3767 case FMOV_dx:
3768 WriteDRegisterBits(dst, ReadXRegister(src));
3769 break;
3770 case FMOV_d1_x:
3771 LogicVRegister(ReadVRegister(dst))
3772 .SetUint(kFormatD, 1, ReadXRegister(src));
3773 break;
3774 case FMOV_x_d1:
3775 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
3776 break;
3777
3778 // A 32-bit input can be handled in the same way as a 64-bit input, since
3779 // the sign- or zero-extension will not affect the conversion.
3780 case SCVTF_dx:
3781 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
3782 break;
3783 case SCVTF_dw:
3784 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
3785 break;
3786 case UCVTF_dx:
3787 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
3788 break;
3789 case UCVTF_dw: {
3790 WriteDRegister(dst,
3791 UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
3792 break;
3793 }
3794 case SCVTF_sx:
3795 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
3796 break;
3797 case SCVTF_sw:
3798 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
3799 break;
3800 case UCVTF_sx:
3801 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
3802 break;
3803 case UCVTF_sw: {
3804 WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
3805 break;
3806 }
3807 case SCVTF_hx:
3808 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
3809 break;
3810 case SCVTF_hw:
3811 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
3812 break;
3813 case UCVTF_hx:
3814 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
3815 break;
3816 case UCVTF_hw: {
3817 WriteHRegister(dst,
3818 UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
3819 break;
3820 }
3821
3822 default:
3823 VIXL_UNREACHABLE();
3824 }
3825 }
3826
3827
VisitFPFixedPointConvert(const Instruction * instr)3828 void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
3829 AssertSupportedFPCR();
3830
3831 unsigned dst = instr->GetRd();
3832 unsigned src = instr->GetRn();
3833 int fbits = 64 - instr->GetFPScale();
3834
3835 FPRounding round = ReadRMode();
3836
3837 switch (instr->Mask(FPFixedPointConvertMask)) {
3838 // A 32-bit input can be handled in the same way as a 64-bit input, since
3839 // the sign- or zero-extension will not affect the conversion.
3840 case SCVTF_dx_fixed:
3841 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
3842 break;
3843 case SCVTF_dw_fixed:
3844 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
3845 break;
3846 case UCVTF_dx_fixed:
3847 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
3848 break;
3849 case UCVTF_dw_fixed: {
3850 WriteDRegister(dst,
3851 UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
3852 break;
3853 }
3854 case SCVTF_sx_fixed:
3855 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
3856 break;
3857 case SCVTF_sw_fixed:
3858 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
3859 break;
3860 case UCVTF_sx_fixed:
3861 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
3862 break;
3863 case UCVTF_sw_fixed: {
3864 WriteSRegister(dst,
3865 UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
3866 break;
3867 }
3868 case SCVTF_hx_fixed:
3869 WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
3870 break;
3871 case SCVTF_hw_fixed:
3872 WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
3873 break;
3874 case UCVTF_hx_fixed:
3875 WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
3876 break;
3877 case UCVTF_hw_fixed: {
3878 WriteHRegister(dst,
3879 UFixedToFloat16(ReadRegister<uint32_t>(src),
3880 fbits,
3881 round));
3882 break;
3883 }
3884 case FCVTZS_xd_fixed:
3885 WriteXRegister(dst,
3886 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3887 FPZero));
3888 break;
3889 case FCVTZS_wd_fixed:
3890 WriteWRegister(dst,
3891 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3892 FPZero));
3893 break;
3894 case FCVTZU_xd_fixed:
3895 WriteXRegister(dst,
3896 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
3897 FPZero));
3898 break;
3899 case FCVTZU_wd_fixed:
3900 WriteWRegister(dst,
3901 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
3902 FPZero));
3903 break;
3904 case FCVTZS_xs_fixed:
3905 WriteXRegister(dst,
3906 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3907 FPZero));
3908 break;
3909 case FCVTZS_ws_fixed:
3910 WriteWRegister(dst,
3911 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3912 FPZero));
3913 break;
3914 case FCVTZU_xs_fixed:
3915 WriteXRegister(dst,
3916 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
3917 FPZero));
3918 break;
3919 case FCVTZU_ws_fixed:
3920 WriteWRegister(dst,
3921 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
3922 FPZero));
3923 break;
3924 case FCVTZS_xh_fixed: {
3925 double output =
3926 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3927 WriteXRegister(dst, FPToInt64(output, FPZero));
3928 break;
3929 }
3930 case FCVTZS_wh_fixed: {
3931 double output =
3932 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3933 WriteWRegister(dst, FPToInt32(output, FPZero));
3934 break;
3935 }
3936 case FCVTZU_xh_fixed: {
3937 double output =
3938 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3939 WriteXRegister(dst, FPToUInt64(output, FPZero));
3940 break;
3941 }
3942 case FCVTZU_wh_fixed: {
3943 double output =
3944 static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
3945 WriteWRegister(dst, FPToUInt32(output, FPZero));
3946 break;
3947 }
3948 default:
3949 VIXL_UNREACHABLE();
3950 }
3951 }
3952
3953
VisitFPCompare(const Instruction * instr)3954 void Simulator::VisitFPCompare(const Instruction* instr) {
3955 AssertSupportedFPCR();
3956
3957 FPTrapFlags trap = DisableTrap;
3958 switch (instr->Mask(FPCompareMask)) {
3959 case FCMPE_h:
3960 trap = EnableTrap;
3961 VIXL_FALLTHROUGH();
3962 case FCMP_h:
3963 FPCompare(ReadHRegister(instr->GetRn()),
3964 ReadHRegister(instr->GetRm()),
3965 trap);
3966 break;
3967 case FCMPE_s:
3968 trap = EnableTrap;
3969 VIXL_FALLTHROUGH();
3970 case FCMP_s:
3971 FPCompare(ReadSRegister(instr->GetRn()),
3972 ReadSRegister(instr->GetRm()),
3973 trap);
3974 break;
3975 case FCMPE_d:
3976 trap = EnableTrap;
3977 VIXL_FALLTHROUGH();
3978 case FCMP_d:
3979 FPCompare(ReadDRegister(instr->GetRn()),
3980 ReadDRegister(instr->GetRm()),
3981 trap);
3982 break;
3983 case FCMPE_h_zero:
3984 trap = EnableTrap;
3985 VIXL_FALLTHROUGH();
3986 case FCMP_h_zero:
3987 FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
3988 break;
3989 case FCMPE_s_zero:
3990 trap = EnableTrap;
3991 VIXL_FALLTHROUGH();
3992 case FCMP_s_zero:
3993 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
3994 break;
3995 case FCMPE_d_zero:
3996 trap = EnableTrap;
3997 VIXL_FALLTHROUGH();
3998 case FCMP_d_zero:
3999 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
4000 break;
4001 default:
4002 VIXL_UNIMPLEMENTED();
4003 }
4004 }
4005
4006
VisitFPConditionalCompare(const Instruction * instr)4007 void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
4008 AssertSupportedFPCR();
4009
4010 FPTrapFlags trap = DisableTrap;
4011 switch (instr->Mask(FPConditionalCompareMask)) {
4012 case FCCMPE_h:
4013 trap = EnableTrap;
4014 VIXL_FALLTHROUGH();
4015 case FCCMP_h:
4016 if (ConditionPassed(instr->GetCondition())) {
4017 FPCompare(ReadHRegister(instr->GetRn()),
4018 ReadHRegister(instr->GetRm()),
4019 trap);
4020 } else {
4021 ReadNzcv().SetFlags(instr->GetNzcv());
4022 LogSystemRegister(NZCV);
4023 }
4024 break;
4025 case FCCMPE_s:
4026 trap = EnableTrap;
4027 VIXL_FALLTHROUGH();
4028 case FCCMP_s:
4029 if (ConditionPassed(instr->GetCondition())) {
4030 FPCompare(ReadSRegister(instr->GetRn()),
4031 ReadSRegister(instr->GetRm()),
4032 trap);
4033 } else {
4034 ReadNzcv().SetFlags(instr->GetNzcv());
4035 LogSystemRegister(NZCV);
4036 }
4037 break;
4038 case FCCMPE_d:
4039 trap = EnableTrap;
4040 VIXL_FALLTHROUGH();
4041 case FCCMP_d:
4042 if (ConditionPassed(instr->GetCondition())) {
4043 FPCompare(ReadDRegister(instr->GetRn()),
4044 ReadDRegister(instr->GetRm()),
4045 trap);
4046 } else {
4047 ReadNzcv().SetFlags(instr->GetNzcv());
4048 LogSystemRegister(NZCV);
4049 }
4050 break;
4051 default:
4052 VIXL_UNIMPLEMENTED();
4053 }
4054 }
4055
4056
VisitFPConditionalSelect(const Instruction * instr)4057 void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
4058 AssertSupportedFPCR();
4059
4060 Instr selected;
4061 if (ConditionPassed(instr->GetCondition())) {
4062 selected = instr->GetRn();
4063 } else {
4064 selected = instr->GetRm();
4065 }
4066
4067 switch (instr->Mask(FPConditionalSelectMask)) {
4068 case FCSEL_h:
4069 WriteHRegister(instr->GetRd(), ReadHRegister(selected));
4070 break;
4071 case FCSEL_s:
4072 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
4073 break;
4074 case FCSEL_d:
4075 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
4076 break;
4077 default:
4078 VIXL_UNIMPLEMENTED();
4079 }
4080 }
4081
4082
VisitFPDataProcessing1Source(const Instruction * instr)4083 void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
4084 AssertSupportedFPCR();
4085
4086 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4087 VectorFormat vform;
4088 switch (instr->Mask(FPTypeMask)) {
4089 default:
4090 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4091 case FP64:
4092 vform = kFormatD;
4093 break;
4094 case FP32:
4095 vform = kFormatS;
4096 break;
4097 case FP16:
4098 vform = kFormatH;
4099 break;
4100 }
4101
4102 SimVRegister& rd = ReadVRegister(instr->GetRd());
4103 SimVRegister& rn = ReadVRegister(instr->GetRn());
4104 bool inexact_exception = false;
4105 FrintMode frint_mode = kFrintToInteger;
4106
4107 unsigned fd = instr->GetRd();
4108 unsigned fn = instr->GetRn();
4109
4110 switch (instr->Mask(FPDataProcessing1SourceMask)) {
4111 case FMOV_h:
4112 WriteHRegister(fd, ReadHRegister(fn));
4113 return;
4114 case FMOV_s:
4115 WriteSRegister(fd, ReadSRegister(fn));
4116 return;
4117 case FMOV_d:
4118 WriteDRegister(fd, ReadDRegister(fn));
4119 return;
4120 case FABS_h:
4121 case FABS_s:
4122 case FABS_d:
4123 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
4124 // Explicitly log the register update whilst we have type information.
4125 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4126 return;
4127 case FNEG_h:
4128 case FNEG_s:
4129 case FNEG_d:
4130 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
4131 // Explicitly log the register update whilst we have type information.
4132 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4133 return;
4134 case FCVT_ds:
4135 WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
4136 return;
4137 case FCVT_sd:
4138 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
4139 return;
4140 case FCVT_hs:
4141 WriteHRegister(fd,
4142 Float16ToRawbits(
4143 FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
4144 return;
4145 case FCVT_sh:
4146 WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
4147 return;
4148 case FCVT_dh:
4149 WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
4150 return;
4151 case FCVT_hd:
4152 WriteHRegister(fd,
4153 Float16ToRawbits(
4154 FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
4155 return;
4156 case FSQRT_h:
4157 case FSQRT_s:
4158 case FSQRT_d:
4159 fsqrt(vform, rd, rn);
4160 // Explicitly log the register update whilst we have type information.
4161 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4162 return;
4163 case FRINT32X_s:
4164 case FRINT32X_d:
4165 inexact_exception = true;
4166 frint_mode = kFrintToInt32;
4167 break; // Use FPCR rounding mode.
4168 case FRINT64X_s:
4169 case FRINT64X_d:
4170 inexact_exception = true;
4171 frint_mode = kFrintToInt64;
4172 break; // Use FPCR rounding mode.
4173 case FRINT32Z_s:
4174 case FRINT32Z_d:
4175 inexact_exception = true;
4176 frint_mode = kFrintToInt32;
4177 fpcr_rounding = FPZero;
4178 break;
4179 case FRINT64Z_s:
4180 case FRINT64Z_d:
4181 inexact_exception = true;
4182 frint_mode = kFrintToInt64;
4183 fpcr_rounding = FPZero;
4184 break;
4185 case FRINTI_h:
4186 case FRINTI_s:
4187 case FRINTI_d:
4188 break; // Use FPCR rounding mode.
4189 case FRINTX_h:
4190 case FRINTX_s:
4191 case FRINTX_d:
4192 inexact_exception = true;
4193 break;
4194 case FRINTA_h:
4195 case FRINTA_s:
4196 case FRINTA_d:
4197 fpcr_rounding = FPTieAway;
4198 break;
4199 case FRINTM_h:
4200 case FRINTM_s:
4201 case FRINTM_d:
4202 fpcr_rounding = FPNegativeInfinity;
4203 break;
4204 case FRINTN_h:
4205 case FRINTN_s:
4206 case FRINTN_d:
4207 fpcr_rounding = FPTieEven;
4208 break;
4209 case FRINTP_h:
4210 case FRINTP_s:
4211 case FRINTP_d:
4212 fpcr_rounding = FPPositiveInfinity;
4213 break;
4214 case FRINTZ_h:
4215 case FRINTZ_s:
4216 case FRINTZ_d:
4217 fpcr_rounding = FPZero;
4218 break;
4219 default:
4220 VIXL_UNIMPLEMENTED();
4221 }
4222
4223 // Only FRINT* instructions fall through the switch above.
4224 frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
4225 // Explicitly log the register update whilst we have type information.
4226 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
4227 }
4228
4229
VisitFPDataProcessing2Source(const Instruction * instr)4230 void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
4231 AssertSupportedFPCR();
4232
4233 VectorFormat vform;
4234 switch (instr->Mask(FPTypeMask)) {
4235 default:
4236 VIXL_UNREACHABLE_OR_FALLTHROUGH();
4237 case FP64:
4238 vform = kFormatD;
4239 break;
4240 case FP32:
4241 vform = kFormatS;
4242 break;
4243 case FP16:
4244 vform = kFormatH;
4245 break;
4246 }
4247 SimVRegister& rd = ReadVRegister(instr->GetRd());
4248 SimVRegister& rn = ReadVRegister(instr->GetRn());
4249 SimVRegister& rm = ReadVRegister(instr->GetRm());
4250
4251 switch (instr->Mask(FPDataProcessing2SourceMask)) {
4252 case FADD_h:
4253 case FADD_s:
4254 case FADD_d:
4255 fadd(vform, rd, rn, rm);
4256 break;
4257 case FSUB_h:
4258 case FSUB_s:
4259 case FSUB_d:
4260 fsub(vform, rd, rn, rm);
4261 break;
4262 case FMUL_h:
4263 case FMUL_s:
4264 case FMUL_d:
4265 fmul(vform, rd, rn, rm);
4266 break;
4267 case FNMUL_h:
4268 case FNMUL_s:
4269 case FNMUL_d:
4270 fnmul(vform, rd, rn, rm);
4271 break;
4272 case FDIV_h:
4273 case FDIV_s:
4274 case FDIV_d:
4275 fdiv(vform, rd, rn, rm);
4276 break;
4277 case FMAX_h:
4278 case FMAX_s:
4279 case FMAX_d:
4280 fmax(vform, rd, rn, rm);
4281 break;
4282 case FMIN_h:
4283 case FMIN_s:
4284 case FMIN_d:
4285 fmin(vform, rd, rn, rm);
4286 break;
4287 case FMAXNM_h:
4288 case FMAXNM_s:
4289 case FMAXNM_d:
4290 fmaxnm(vform, rd, rn, rm);
4291 break;
4292 case FMINNM_h:
4293 case FMINNM_s:
4294 case FMINNM_d:
4295 fminnm(vform, rd, rn, rm);
4296 break;
4297 default:
4298 VIXL_UNREACHABLE();
4299 }
4300 // Explicitly log the register update whilst we have type information.
4301 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
4302 }
4303
4304
VisitFPDataProcessing3Source(const Instruction * instr)4305 void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
4306 AssertSupportedFPCR();
4307
4308 unsigned fd = instr->GetRd();
4309 unsigned fn = instr->GetRn();
4310 unsigned fm = instr->GetRm();
4311 unsigned fa = instr->GetRa();
4312
4313 switch (instr->Mask(FPDataProcessing3SourceMask)) {
4314 // fd = fa +/- (fn * fm)
4315 case FMADD_h:
4316 WriteHRegister(fd,
4317 FPMulAdd(ReadHRegister(fa),
4318 ReadHRegister(fn),
4319 ReadHRegister(fm)));
4320 break;
4321 case FMSUB_h:
4322 WriteHRegister(fd,
4323 FPMulAdd(ReadHRegister(fa),
4324 -ReadHRegister(fn),
4325 ReadHRegister(fm)));
4326 break;
4327 case FMADD_s:
4328 WriteSRegister(fd,
4329 FPMulAdd(ReadSRegister(fa),
4330 ReadSRegister(fn),
4331 ReadSRegister(fm)));
4332 break;
4333 case FMSUB_s:
4334 WriteSRegister(fd,
4335 FPMulAdd(ReadSRegister(fa),
4336 -ReadSRegister(fn),
4337 ReadSRegister(fm)));
4338 break;
4339 case FMADD_d:
4340 WriteDRegister(fd,
4341 FPMulAdd(ReadDRegister(fa),
4342 ReadDRegister(fn),
4343 ReadDRegister(fm)));
4344 break;
4345 case FMSUB_d:
4346 WriteDRegister(fd,
4347 FPMulAdd(ReadDRegister(fa),
4348 -ReadDRegister(fn),
4349 ReadDRegister(fm)));
4350 break;
4351 // Negated variants of the above.
4352 case FNMADD_h:
4353 WriteHRegister(fd,
4354 FPMulAdd(-ReadHRegister(fa),
4355 -ReadHRegister(fn),
4356 ReadHRegister(fm)));
4357 break;
4358 case FNMSUB_h:
4359 WriteHRegister(fd,
4360 FPMulAdd(-ReadHRegister(fa),
4361 ReadHRegister(fn),
4362 ReadHRegister(fm)));
4363 break;
4364 case FNMADD_s:
4365 WriteSRegister(fd,
4366 FPMulAdd(-ReadSRegister(fa),
4367 -ReadSRegister(fn),
4368 ReadSRegister(fm)));
4369 break;
4370 case FNMSUB_s:
4371 WriteSRegister(fd,
4372 FPMulAdd(-ReadSRegister(fa),
4373 ReadSRegister(fn),
4374 ReadSRegister(fm)));
4375 break;
4376 case FNMADD_d:
4377 WriteDRegister(fd,
4378 FPMulAdd(-ReadDRegister(fa),
4379 -ReadDRegister(fn),
4380 ReadDRegister(fm)));
4381 break;
4382 case FNMSUB_d:
4383 WriteDRegister(fd,
4384 FPMulAdd(-ReadDRegister(fa),
4385 ReadDRegister(fn),
4386 ReadDRegister(fm)));
4387 break;
4388 default:
4389 VIXL_UNIMPLEMENTED();
4390 }
4391 }
4392
4393
FPProcessNaNs(const Instruction * instr)4394 bool Simulator::FPProcessNaNs(const Instruction* instr) {
4395 unsigned fd = instr->GetRd();
4396 unsigned fn = instr->GetRn();
4397 unsigned fm = instr->GetRm();
4398 bool done = false;
4399
4400 if (instr->Mask(FP64) == FP64) {
4401 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
4402 if (IsNaN(result)) {
4403 WriteDRegister(fd, result);
4404 done = true;
4405 }
4406 } else if (instr->Mask(FP32) == FP32) {
4407 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
4408 if (IsNaN(result)) {
4409 WriteSRegister(fd, result);
4410 done = true;
4411 }
4412 } else {
4413 VIXL_ASSERT(instr->Mask(FP16) == FP16);
4414 VIXL_UNIMPLEMENTED();
4415 }
4416
4417 return done;
4418 }
4419
4420
SysOp_W(int op,int64_t val)4421 void Simulator::SysOp_W(int op, int64_t val) {
4422 switch (op) {
4423 case IVAU:
4424 case CVAC:
4425 case CVAU:
4426 case CVAP:
4427 case CVADP:
4428 case CIVAC: {
4429 // Perform a placeholder memory access to ensure that we have read access
4430 // to the specified address.
4431 volatile uint8_t y = MemRead<uint8_t>(val);
4432 USE(y);
4433 // TODO: Implement "case ZVA:".
4434 break;
4435 }
4436 default:
4437 VIXL_UNIMPLEMENTED();
4438 }
4439 }
4440
4441
4442 // clang-format off
4443 #define PAUTH_SYSTEM_MODES(V) \
4444 V(A1716, 17, ReadXRegister(16), kPACKeyIA) \
4445 V(B1716, 17, ReadXRegister(16), kPACKeyIB) \
4446 V(AZ, 30, 0x00000000, kPACKeyIA) \
4447 V(BZ, 30, 0x00000000, kPACKeyIB) \
4448 V(ASP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
4449 V(BSP, 30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
4450 // clang-format on
4451
4452
VisitSystem(const Instruction * instr)4453 void Simulator::VisitSystem(const Instruction* instr) {
4454 // Some system instructions hijack their Op and Cp fields to represent a
4455 // range of immediates instead of indicating a different instruction. This
4456 // makes the decoding tricky.
4457 if (instr->GetInstructionBits() == XPACLRI) {
4458 WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
4459 } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
4460 switch (instr->Mask(SystemPStateMask)) {
4461 case CFINV:
4462 ReadNzcv().SetC(!ReadC());
4463 break;
4464 case AXFLAG:
4465 ReadNzcv().SetN(0);
4466 ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
4467 ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
4468 ReadNzcv().SetV(0);
4469 break;
4470 case XAFLAG: {
4471 // Can't set the flags in place due to the logical dependencies.
4472 uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
4473 uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
4474 uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
4475 uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
4476 ReadNzcv().SetN(n);
4477 ReadNzcv().SetZ(z);
4478 ReadNzcv().SetC(c);
4479 ReadNzcv().SetV(v);
4480 break;
4481 }
4482 }
4483 } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
4484 // Check BType allows PACI[AB]SP instructions.
4485 if (PcIsInGuardedPage()) {
4486 Instr i = instr->Mask(SystemPAuthMask);
4487 if ((i == PACIASP) || (i == PACIBSP)) {
4488 switch (ReadBType()) {
4489 case BranchFromGuardedNotToIP:
4490 // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
4491 // assume here to be zero. This allows execution of PACI[AB]SP when
4492 // BTYPE is BranchFromGuardedNotToIP (0b11).
4493 case DefaultBType:
4494 case BranchFromUnguardedOrToIP:
4495 case BranchAndLink:
4496 break;
4497 }
4498 }
4499 }
4500
4501 switch (instr->Mask(SystemPAuthMask)) {
4502 #define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \
4503 case PACI##SUFFIX: \
4504 WriteXRegister(DST, \
4505 AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
4506 break; \
4507 case AUTI##SUFFIX: \
4508 WriteXRegister(DST, \
4509 AuthPAC(ReadXRegister(DST), \
4510 MOD, \
4511 KEY, \
4512 kInstructionPointer)); \
4513 break;
4514
4515 PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
4516 #undef DEFINE_PAUTH_FUNCS
4517 }
4518 } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
4519 SystemExclusiveMonitorFixed) {
4520 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
4521 switch (instr->Mask(SystemExclusiveMonitorMask)) {
4522 case CLREX: {
4523 PrintExclusiveAccessWarning();
4524 ClearLocalMonitor();
4525 break;
4526 }
4527 }
4528 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
4529 switch (instr->Mask(SystemSysRegMask)) {
4530 case MRS: {
4531 switch (instr->GetImmSystemRegister()) {
4532 case NZCV:
4533 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
4534 break;
4535 case FPCR:
4536 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
4537 break;
4538 case RNDR:
4539 case RNDRRS: {
4540 uint64_t high = jrand48(rand_state_);
4541 uint64_t low = jrand48(rand_state_);
4542 uint64_t rand_num = (high << 32) | (low & 0xffffffff);
4543 WriteXRegister(instr->GetRt(), rand_num);
4544 // Simulate successful random number generation.
4545 // TODO: Return failure occasionally as a random number cannot be
4546 // returned in a period of time.
4547 ReadNzcv().SetRawValue(NoFlag);
4548 LogSystemRegister(NZCV);
4549 break;
4550 }
4551 default:
4552 VIXL_UNIMPLEMENTED();
4553 }
4554 break;
4555 }
4556 case MSR: {
4557 switch (instr->GetImmSystemRegister()) {
4558 case NZCV:
4559 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
4560 LogSystemRegister(NZCV);
4561 break;
4562 case FPCR:
4563 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
4564 LogSystemRegister(FPCR);
4565 break;
4566 default:
4567 VIXL_UNIMPLEMENTED();
4568 }
4569 break;
4570 }
4571 }
4572 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
4573 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
4574 switch (instr->GetImmHint()) {
4575 case NOP:
4576 case ESB:
4577 case CSDB:
4578 case BTI_jc:
4579 break;
4580 case BTI:
4581 if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
4582 VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
4583 }
4584 break;
4585 case BTI_c:
4586 if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
4587 VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
4588 }
4589 break;
4590 case BTI_j:
4591 if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
4592 VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
4593 }
4594 break;
4595 default:
4596 VIXL_UNIMPLEMENTED();
4597 }
4598 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
4599 __sync_synchronize();
4600 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
4601 switch (instr->Mask(SystemSysMask)) {
4602 case SYS:
4603 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
4604 break;
4605 default:
4606 VIXL_UNIMPLEMENTED();
4607 }
4608 } else {
4609 VIXL_UNIMPLEMENTED();
4610 }
4611 }
4612
4613
VisitException(const Instruction * instr)4614 void Simulator::VisitException(const Instruction* instr) {
4615 switch (instr->Mask(ExceptionMask)) {
4616 case HLT:
4617 switch (instr->GetImmException()) {
4618 case kUnreachableOpcode:
4619 DoUnreachable(instr);
4620 return;
4621 case kTraceOpcode:
4622 DoTrace(instr);
4623 return;
4624 case kLogOpcode:
4625 DoLog(instr);
4626 return;
4627 case kPrintfOpcode:
4628 DoPrintf(instr);
4629 return;
4630 case kRuntimeCallOpcode:
4631 DoRuntimeCall(instr);
4632 return;
4633 case kSetCPUFeaturesOpcode:
4634 case kEnableCPUFeaturesOpcode:
4635 case kDisableCPUFeaturesOpcode:
4636 DoConfigureCPUFeatures(instr);
4637 return;
4638 case kSaveCPUFeaturesOpcode:
4639 DoSaveCPUFeatures(instr);
4640 return;
4641 case kRestoreCPUFeaturesOpcode:
4642 DoRestoreCPUFeatures(instr);
4643 return;
4644 default:
4645 HostBreakpoint();
4646 return;
4647 }
4648 case BRK:
4649 HostBreakpoint();
4650 return;
4651 default:
4652 VIXL_UNIMPLEMENTED();
4653 }
4654 }
4655
4656
VisitCrypto2RegSHA(const Instruction * instr)4657 void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
4658 VisitUnimplemented(instr);
4659 }
4660
4661
VisitCrypto3RegSHA(const Instruction * instr)4662 void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
4663 VisitUnimplemented(instr);
4664 }
4665
4666
VisitCryptoAES(const Instruction * instr)4667 void Simulator::VisitCryptoAES(const Instruction* instr) {
4668 VisitUnimplemented(instr);
4669 }
4670
4671
VisitNEON2RegMisc(const Instruction * instr)4672 void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
4673 NEONFormatDecoder nfd(instr);
4674 VectorFormat vf = nfd.GetVectorFormat();
4675
4676 static const NEONFormatMap map_lp =
4677 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
4678 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
4679
4680 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
4681 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
4682
4683 static const NEONFormatMap map_fcvtn = {{22, 30},
4684 {NF_4H, NF_8H, NF_2S, NF_4S}};
4685 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
4686
4687 SimVRegister& rd = ReadVRegister(instr->GetRd());
4688 SimVRegister& rn = ReadVRegister(instr->GetRn());
4689
4690 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
4691 // These instructions all use a two bit size field, except NOT and RBIT,
4692 // which use the field to encode the operation.
4693 switch (instr->Mask(NEON2RegMiscMask)) {
4694 case NEON_REV64:
4695 rev64(vf, rd, rn);
4696 break;
4697 case NEON_REV32:
4698 rev32(vf, rd, rn);
4699 break;
4700 case NEON_REV16:
4701 rev16(vf, rd, rn);
4702 break;
4703 case NEON_SUQADD:
4704 suqadd(vf, rd, rn);
4705 break;
4706 case NEON_USQADD:
4707 usqadd(vf, rd, rn);
4708 break;
4709 case NEON_CLS:
4710 cls(vf, rd, rn);
4711 break;
4712 case NEON_CLZ:
4713 clz(vf, rd, rn);
4714 break;
4715 case NEON_CNT:
4716 cnt(vf, rd, rn);
4717 break;
4718 case NEON_SQABS:
4719 abs(vf, rd, rn).SignedSaturate(vf);
4720 break;
4721 case NEON_SQNEG:
4722 neg(vf, rd, rn).SignedSaturate(vf);
4723 break;
4724 case NEON_CMGT_zero:
4725 cmp(vf, rd, rn, 0, gt);
4726 break;
4727 case NEON_CMGE_zero:
4728 cmp(vf, rd, rn, 0, ge);
4729 break;
4730 case NEON_CMEQ_zero:
4731 cmp(vf, rd, rn, 0, eq);
4732 break;
4733 case NEON_CMLE_zero:
4734 cmp(vf, rd, rn, 0, le);
4735 break;
4736 case NEON_CMLT_zero:
4737 cmp(vf, rd, rn, 0, lt);
4738 break;
4739 case NEON_ABS:
4740 abs(vf, rd, rn);
4741 break;
4742 case NEON_NEG:
4743 neg(vf, rd, rn);
4744 break;
4745 case NEON_SADDLP:
4746 saddlp(vf_lp, rd, rn);
4747 break;
4748 case NEON_UADDLP:
4749 uaddlp(vf_lp, rd, rn);
4750 break;
4751 case NEON_SADALP:
4752 sadalp(vf_lp, rd, rn);
4753 break;
4754 case NEON_UADALP:
4755 uadalp(vf_lp, rd, rn);
4756 break;
4757 case NEON_RBIT_NOT:
4758 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
4759 switch (instr->GetFPType()) {
4760 case 0:
4761 not_(vf, rd, rn);
4762 break;
4763 case 1:
4764 rbit(vf, rd, rn);
4765 break;
4766 default:
4767 VIXL_UNIMPLEMENTED();
4768 }
4769 break;
4770 }
4771 } else {
4772 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
4773 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4774 bool inexact_exception = false;
4775 FrintMode frint_mode = kFrintToInteger;
4776
4777 // These instructions all use a one bit size field, except XTN, SQXTUN,
4778 // SHLL, SQXTN and UQXTN, which use a two bit size field.
4779 switch (instr->Mask(NEON2RegMiscFPMask)) {
4780 case NEON_FABS:
4781 fabs_(fpf, rd, rn);
4782 return;
4783 case NEON_FNEG:
4784 fneg(fpf, rd, rn);
4785 return;
4786 case NEON_FSQRT:
4787 fsqrt(fpf, rd, rn);
4788 return;
4789 case NEON_FCVTL:
4790 if (instr->Mask(NEON_Q)) {
4791 fcvtl2(vf_fcvtl, rd, rn);
4792 } else {
4793 fcvtl(vf_fcvtl, rd, rn);
4794 }
4795 return;
4796 case NEON_FCVTN:
4797 if (instr->Mask(NEON_Q)) {
4798 fcvtn2(vf_fcvtn, rd, rn);
4799 } else {
4800 fcvtn(vf_fcvtn, rd, rn);
4801 }
4802 return;
4803 case NEON_FCVTXN:
4804 if (instr->Mask(NEON_Q)) {
4805 fcvtxn2(vf_fcvtn, rd, rn);
4806 } else {
4807 fcvtxn(vf_fcvtn, rd, rn);
4808 }
4809 return;
4810
4811 // The following instructions break from the switch statement, rather
4812 // than return.
4813 case NEON_FRINT32X:
4814 inexact_exception = true;
4815 frint_mode = kFrintToInt32;
4816 break; // Use FPCR rounding mode.
4817 case NEON_FRINT32Z:
4818 inexact_exception = true;
4819 frint_mode = kFrintToInt32;
4820 fpcr_rounding = FPZero;
4821 break;
4822 case NEON_FRINT64X:
4823 inexact_exception = true;
4824 frint_mode = kFrintToInt64;
4825 break; // Use FPCR rounding mode.
4826 case NEON_FRINT64Z:
4827 inexact_exception = true;
4828 frint_mode = kFrintToInt64;
4829 fpcr_rounding = FPZero;
4830 break;
4831 case NEON_FRINTI:
4832 break; // Use FPCR rounding mode.
4833 case NEON_FRINTX:
4834 inexact_exception = true;
4835 break;
4836 case NEON_FRINTA:
4837 fpcr_rounding = FPTieAway;
4838 break;
4839 case NEON_FRINTM:
4840 fpcr_rounding = FPNegativeInfinity;
4841 break;
4842 case NEON_FRINTN:
4843 fpcr_rounding = FPTieEven;
4844 break;
4845 case NEON_FRINTP:
4846 fpcr_rounding = FPPositiveInfinity;
4847 break;
4848 case NEON_FRINTZ:
4849 fpcr_rounding = FPZero;
4850 break;
4851
4852 case NEON_FCVTNS:
4853 fcvts(fpf, rd, rn, FPTieEven);
4854 return;
4855 case NEON_FCVTNU:
4856 fcvtu(fpf, rd, rn, FPTieEven);
4857 return;
4858 case NEON_FCVTPS:
4859 fcvts(fpf, rd, rn, FPPositiveInfinity);
4860 return;
4861 case NEON_FCVTPU:
4862 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4863 return;
4864 case NEON_FCVTMS:
4865 fcvts(fpf, rd, rn, FPNegativeInfinity);
4866 return;
4867 case NEON_FCVTMU:
4868 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4869 return;
4870 case NEON_FCVTZS:
4871 fcvts(fpf, rd, rn, FPZero);
4872 return;
4873 case NEON_FCVTZU:
4874 fcvtu(fpf, rd, rn, FPZero);
4875 return;
4876 case NEON_FCVTAS:
4877 fcvts(fpf, rd, rn, FPTieAway);
4878 return;
4879 case NEON_FCVTAU:
4880 fcvtu(fpf, rd, rn, FPTieAway);
4881 return;
4882 case NEON_SCVTF:
4883 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4884 return;
4885 case NEON_UCVTF:
4886 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4887 return;
4888 case NEON_URSQRTE:
4889 ursqrte(fpf, rd, rn);
4890 return;
4891 case NEON_URECPE:
4892 urecpe(fpf, rd, rn);
4893 return;
4894 case NEON_FRSQRTE:
4895 frsqrte(fpf, rd, rn);
4896 return;
4897 case NEON_FRECPE:
4898 frecpe(fpf, rd, rn, fpcr_rounding);
4899 return;
4900 case NEON_FCMGT_zero:
4901 fcmp_zero(fpf, rd, rn, gt);
4902 return;
4903 case NEON_FCMGE_zero:
4904 fcmp_zero(fpf, rd, rn, ge);
4905 return;
4906 case NEON_FCMEQ_zero:
4907 fcmp_zero(fpf, rd, rn, eq);
4908 return;
4909 case NEON_FCMLE_zero:
4910 fcmp_zero(fpf, rd, rn, le);
4911 return;
4912 case NEON_FCMLT_zero:
4913 fcmp_zero(fpf, rd, rn, lt);
4914 return;
4915 default:
4916 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
4917 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
4918 switch (instr->Mask(NEON2RegMiscMask)) {
4919 case NEON_XTN:
4920 xtn(vf, rd, rn);
4921 return;
4922 case NEON_SQXTN:
4923 sqxtn(vf, rd, rn);
4924 return;
4925 case NEON_UQXTN:
4926 uqxtn(vf, rd, rn);
4927 return;
4928 case NEON_SQXTUN:
4929 sqxtun(vf, rd, rn);
4930 return;
4931 case NEON_SHLL:
4932 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4933 if (instr->Mask(NEON_Q)) {
4934 shll2(vf, rd, rn);
4935 } else {
4936 shll(vf, rd, rn);
4937 }
4938 return;
4939 default:
4940 VIXL_UNIMPLEMENTED();
4941 }
4942 } else {
4943 VIXL_UNIMPLEMENTED();
4944 }
4945 }
4946
4947 // Only FRINT* instructions fall through the switch above.
4948 frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
4949 }
4950 }
4951
4952
VisitNEON2RegMiscFP16(const Instruction * instr)4953 void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
4954 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
4955 NEONFormatDecoder nfd(instr);
4956 VectorFormat fpf = nfd.GetVectorFormat(&map_half);
4957
4958 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4959
4960 SimVRegister& rd = ReadVRegister(instr->GetRd());
4961 SimVRegister& rn = ReadVRegister(instr->GetRn());
4962
4963 switch (instr->Mask(NEON2RegMiscFP16Mask)) {
4964 case NEON_SCVTF_H:
4965 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4966 return;
4967 case NEON_UCVTF_H:
4968 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4969 return;
4970 case NEON_FCVTNS_H:
4971 fcvts(fpf, rd, rn, FPTieEven);
4972 return;
4973 case NEON_FCVTNU_H:
4974 fcvtu(fpf, rd, rn, FPTieEven);
4975 return;
4976 case NEON_FCVTPS_H:
4977 fcvts(fpf, rd, rn, FPPositiveInfinity);
4978 return;
4979 case NEON_FCVTPU_H:
4980 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4981 return;
4982 case NEON_FCVTMS_H:
4983 fcvts(fpf, rd, rn, FPNegativeInfinity);
4984 return;
4985 case NEON_FCVTMU_H:
4986 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4987 return;
4988 case NEON_FCVTZS_H:
4989 fcvts(fpf, rd, rn, FPZero);
4990 return;
4991 case NEON_FCVTZU_H:
4992 fcvtu(fpf, rd, rn, FPZero);
4993 return;
4994 case NEON_FCVTAS_H:
4995 fcvts(fpf, rd, rn, FPTieAway);
4996 return;
4997 case NEON_FCVTAU_H:
4998 fcvtu(fpf, rd, rn, FPTieAway);
4999 return;
5000 case NEON_FRINTI_H:
5001 frint(fpf, rd, rn, fpcr_rounding, false);
5002 return;
5003 case NEON_FRINTX_H:
5004 frint(fpf, rd, rn, fpcr_rounding, true);
5005 return;
5006 case NEON_FRINTA_H:
5007 frint(fpf, rd, rn, FPTieAway, false);
5008 return;
5009 case NEON_FRINTM_H:
5010 frint(fpf, rd, rn, FPNegativeInfinity, false);
5011 return;
5012 case NEON_FRINTN_H:
5013 frint(fpf, rd, rn, FPTieEven, false);
5014 return;
5015 case NEON_FRINTP_H:
5016 frint(fpf, rd, rn, FPPositiveInfinity, false);
5017 return;
5018 case NEON_FRINTZ_H:
5019 frint(fpf, rd, rn, FPZero, false);
5020 return;
5021 case NEON_FABS_H:
5022 fabs_(fpf, rd, rn);
5023 return;
5024 case NEON_FNEG_H:
5025 fneg(fpf, rd, rn);
5026 return;
5027 case NEON_FSQRT_H:
5028 fsqrt(fpf, rd, rn);
5029 return;
5030 case NEON_FRSQRTE_H:
5031 frsqrte(fpf, rd, rn);
5032 return;
5033 case NEON_FRECPE_H:
5034 frecpe(fpf, rd, rn, fpcr_rounding);
5035 return;
5036 case NEON_FCMGT_H_zero:
5037 fcmp_zero(fpf, rd, rn, gt);
5038 return;
5039 case NEON_FCMGE_H_zero:
5040 fcmp_zero(fpf, rd, rn, ge);
5041 return;
5042 case NEON_FCMEQ_H_zero:
5043 fcmp_zero(fpf, rd, rn, eq);
5044 return;
5045 case NEON_FCMLE_H_zero:
5046 fcmp_zero(fpf, rd, rn, le);
5047 return;
5048 case NEON_FCMLT_H_zero:
5049 fcmp_zero(fpf, rd, rn, lt);
5050 return;
5051 default:
5052 VIXL_UNIMPLEMENTED();
5053 return;
5054 }
5055 }
5056
5057
VisitNEON3Same(const Instruction * instr)5058 void Simulator::VisitNEON3Same(const Instruction* instr) {
5059 NEONFormatDecoder nfd(instr);
5060 SimVRegister& rd = ReadVRegister(instr->GetRd());
5061 SimVRegister& rn = ReadVRegister(instr->GetRn());
5062 SimVRegister& rm = ReadVRegister(instr->GetRm());
5063
5064 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
5065 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
5066 switch (instr->Mask(NEON3SameLogicalMask)) {
5067 case NEON_AND:
5068 and_(vf, rd, rn, rm);
5069 break;
5070 case NEON_ORR:
5071 orr(vf, rd, rn, rm);
5072 break;
5073 case NEON_ORN:
5074 orn(vf, rd, rn, rm);
5075 break;
5076 case NEON_EOR:
5077 eor(vf, rd, rn, rm);
5078 break;
5079 case NEON_BIC:
5080 bic(vf, rd, rn, rm);
5081 break;
5082 case NEON_BIF:
5083 bif(vf, rd, rn, rm);
5084 break;
5085 case NEON_BIT:
5086 bit(vf, rd, rn, rm);
5087 break;
5088 case NEON_BSL:
5089 bsl(vf, rd, rn, rm);
5090 break;
5091 default:
5092 VIXL_UNIMPLEMENTED();
5093 }
5094 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
5095 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5096 switch (instr->Mask(NEON3SameFPMask)) {
5097 case NEON_FADD:
5098 fadd(vf, rd, rn, rm);
5099 break;
5100 case NEON_FSUB:
5101 fsub(vf, rd, rn, rm);
5102 break;
5103 case NEON_FMUL:
5104 fmul(vf, rd, rn, rm);
5105 break;
5106 case NEON_FDIV:
5107 fdiv(vf, rd, rn, rm);
5108 break;
5109 case NEON_FMAX:
5110 fmax(vf, rd, rn, rm);
5111 break;
5112 case NEON_FMIN:
5113 fmin(vf, rd, rn, rm);
5114 break;
5115 case NEON_FMAXNM:
5116 fmaxnm(vf, rd, rn, rm);
5117 break;
5118 case NEON_FMINNM:
5119 fminnm(vf, rd, rn, rm);
5120 break;
5121 case NEON_FMLA:
5122 fmla(vf, rd, rd, rn, rm);
5123 break;
5124 case NEON_FMLS:
5125 fmls(vf, rd, rd, rn, rm);
5126 break;
5127 case NEON_FMULX:
5128 fmulx(vf, rd, rn, rm);
5129 break;
5130 case NEON_FACGE:
5131 fabscmp(vf, rd, rn, rm, ge);
5132 break;
5133 case NEON_FACGT:
5134 fabscmp(vf, rd, rn, rm, gt);
5135 break;
5136 case NEON_FCMEQ:
5137 fcmp(vf, rd, rn, rm, eq);
5138 break;
5139 case NEON_FCMGE:
5140 fcmp(vf, rd, rn, rm, ge);
5141 break;
5142 case NEON_FCMGT:
5143 fcmp(vf, rd, rn, rm, gt);
5144 break;
5145 case NEON_FRECPS:
5146 frecps(vf, rd, rn, rm);
5147 break;
5148 case NEON_FRSQRTS:
5149 frsqrts(vf, rd, rn, rm);
5150 break;
5151 case NEON_FABD:
5152 fabd(vf, rd, rn, rm);
5153 break;
5154 case NEON_FADDP:
5155 faddp(vf, rd, rn, rm);
5156 break;
5157 case NEON_FMAXP:
5158 fmaxp(vf, rd, rn, rm);
5159 break;
5160 case NEON_FMAXNMP:
5161 fmaxnmp(vf, rd, rn, rm);
5162 break;
5163 case NEON_FMINP:
5164 fminp(vf, rd, rn, rm);
5165 break;
5166 case NEON_FMINNMP:
5167 fminnmp(vf, rd, rn, rm);
5168 break;
5169 default:
5170 // FMLAL{2} and FMLSL{2} have special-case encodings.
5171 switch (instr->Mask(NEON3SameFHMMask)) {
5172 case NEON_FMLAL:
5173 fmlal(vf, rd, rn, rm);
5174 break;
5175 case NEON_FMLAL2:
5176 fmlal2(vf, rd, rn, rm);
5177 break;
5178 case NEON_FMLSL:
5179 fmlsl(vf, rd, rn, rm);
5180 break;
5181 case NEON_FMLSL2:
5182 fmlsl2(vf, rd, rn, rm);
5183 break;
5184 default:
5185 VIXL_UNIMPLEMENTED();
5186 }
5187 }
5188 } else {
5189 VectorFormat vf = nfd.GetVectorFormat();
5190 switch (instr->Mask(NEON3SameMask)) {
5191 case NEON_ADD:
5192 add(vf, rd, rn, rm);
5193 break;
5194 case NEON_ADDP:
5195 addp(vf, rd, rn, rm);
5196 break;
5197 case NEON_CMEQ:
5198 cmp(vf, rd, rn, rm, eq);
5199 break;
5200 case NEON_CMGE:
5201 cmp(vf, rd, rn, rm, ge);
5202 break;
5203 case NEON_CMGT:
5204 cmp(vf, rd, rn, rm, gt);
5205 break;
5206 case NEON_CMHI:
5207 cmp(vf, rd, rn, rm, hi);
5208 break;
5209 case NEON_CMHS:
5210 cmp(vf, rd, rn, rm, hs);
5211 break;
5212 case NEON_CMTST:
5213 cmptst(vf, rd, rn, rm);
5214 break;
5215 case NEON_MLS:
5216 mls(vf, rd, rd, rn, rm);
5217 break;
5218 case NEON_MLA:
5219 mla(vf, rd, rd, rn, rm);
5220 break;
5221 case NEON_MUL:
5222 mul(vf, rd, rn, rm);
5223 break;
5224 case NEON_PMUL:
5225 pmul(vf, rd, rn, rm);
5226 break;
5227 case NEON_SMAX:
5228 smax(vf, rd, rn, rm);
5229 break;
5230 case NEON_SMAXP:
5231 smaxp(vf, rd, rn, rm);
5232 break;
5233 case NEON_SMIN:
5234 smin(vf, rd, rn, rm);
5235 break;
5236 case NEON_SMINP:
5237 sminp(vf, rd, rn, rm);
5238 break;
5239 case NEON_SUB:
5240 sub(vf, rd, rn, rm);
5241 break;
5242 case NEON_UMAX:
5243 umax(vf, rd, rn, rm);
5244 break;
5245 case NEON_UMAXP:
5246 umaxp(vf, rd, rn, rm);
5247 break;
5248 case NEON_UMIN:
5249 umin(vf, rd, rn, rm);
5250 break;
5251 case NEON_UMINP:
5252 uminp(vf, rd, rn, rm);
5253 break;
5254 case NEON_SSHL:
5255 sshl(vf, rd, rn, rm);
5256 break;
5257 case NEON_USHL:
5258 ushl(vf, rd, rn, rm);
5259 break;
5260 case NEON_SABD:
5261 absdiff(vf, rd, rn, rm, true);
5262 break;
5263 case NEON_UABD:
5264 absdiff(vf, rd, rn, rm, false);
5265 break;
5266 case NEON_SABA:
5267 saba(vf, rd, rn, rm);
5268 break;
5269 case NEON_UABA:
5270 uaba(vf, rd, rn, rm);
5271 break;
5272 case NEON_UQADD:
5273 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5274 break;
5275 case NEON_SQADD:
5276 add(vf, rd, rn, rm).SignedSaturate(vf);
5277 break;
5278 case NEON_UQSUB:
5279 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5280 break;
5281 case NEON_SQSUB:
5282 sub(vf, rd, rn, rm).SignedSaturate(vf);
5283 break;
5284 case NEON_SQDMULH:
5285 sqdmulh(vf, rd, rn, rm);
5286 break;
5287 case NEON_SQRDMULH:
5288 sqrdmulh(vf, rd, rn, rm);
5289 break;
5290 case NEON_UQSHL:
5291 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5292 break;
5293 case NEON_SQSHL:
5294 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5295 break;
5296 case NEON_URSHL:
5297 ushl(vf, rd, rn, rm).Round(vf);
5298 break;
5299 case NEON_SRSHL:
5300 sshl(vf, rd, rn, rm).Round(vf);
5301 break;
5302 case NEON_UQRSHL:
5303 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5304 break;
5305 case NEON_SQRSHL:
5306 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5307 break;
5308 case NEON_UHADD:
5309 add(vf, rd, rn, rm).Uhalve(vf);
5310 break;
5311 case NEON_URHADD:
5312 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
5313 break;
5314 case NEON_SHADD:
5315 add(vf, rd, rn, rm).Halve(vf);
5316 break;
5317 case NEON_SRHADD:
5318 add(vf, rd, rn, rm).Halve(vf).Round(vf);
5319 break;
5320 case NEON_UHSUB:
5321 sub(vf, rd, rn, rm).Uhalve(vf);
5322 break;
5323 case NEON_SHSUB:
5324 sub(vf, rd, rn, rm).Halve(vf);
5325 break;
5326 default:
5327 VIXL_UNIMPLEMENTED();
5328 }
5329 }
5330 }
5331
5332
VisitNEON3SameFP16(const Instruction * instr)5333 void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
5334 NEONFormatDecoder nfd(instr);
5335 SimVRegister& rd = ReadVRegister(instr->GetRd());
5336 SimVRegister& rn = ReadVRegister(instr->GetRn());
5337 SimVRegister& rm = ReadVRegister(instr->GetRm());
5338
5339 VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
5340 switch (instr->Mask(NEON3SameFP16Mask)) {
5341 #define SIM_FUNC(A, B) \
5342 case NEON_##A##_H: \
5343 B(vf, rd, rn, rm); \
5344 break;
5345 SIM_FUNC(FMAXNM, fmaxnm);
5346 SIM_FUNC(FADD, fadd);
5347 SIM_FUNC(FMULX, fmulx);
5348 SIM_FUNC(FMAX, fmax);
5349 SIM_FUNC(FRECPS, frecps);
5350 SIM_FUNC(FMINNM, fminnm);
5351 SIM_FUNC(FSUB, fsub);
5352 SIM_FUNC(FMIN, fmin);
5353 SIM_FUNC(FRSQRTS, frsqrts);
5354 SIM_FUNC(FMAXNMP, fmaxnmp);
5355 SIM_FUNC(FADDP, faddp);
5356 SIM_FUNC(FMUL, fmul);
5357 SIM_FUNC(FMAXP, fmaxp);
5358 SIM_FUNC(FDIV, fdiv);
5359 SIM_FUNC(FMINNMP, fminnmp);
5360 SIM_FUNC(FABD, fabd);
5361 SIM_FUNC(FMINP, fminp);
5362 #undef SIM_FUNC
5363 case NEON_FMLA_H:
5364 fmla(vf, rd, rd, rn, rm);
5365 break;
5366 case NEON_FMLS_H:
5367 fmls(vf, rd, rd, rn, rm);
5368 break;
5369 case NEON_FCMEQ_H:
5370 fcmp(vf, rd, rn, rm, eq);
5371 break;
5372 case NEON_FCMGE_H:
5373 fcmp(vf, rd, rn, rm, ge);
5374 break;
5375 case NEON_FACGE_H:
5376 fabscmp(vf, rd, rn, rm, ge);
5377 break;
5378 case NEON_FCMGT_H:
5379 fcmp(vf, rd, rn, rm, gt);
5380 break;
5381 case NEON_FACGT_H:
5382 fabscmp(vf, rd, rn, rm, gt);
5383 break;
5384 default:
5385 VIXL_UNIMPLEMENTED();
5386 break;
5387 }
5388 }
5389
VisitNEON3SameExtra(const Instruction * instr)5390 void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
5391 NEONFormatDecoder nfd(instr);
5392 SimVRegister& rd = ReadVRegister(instr->GetRd());
5393 SimVRegister& rn = ReadVRegister(instr->GetRn());
5394 SimVRegister& rm = ReadVRegister(instr->GetRm());
5395 int rot = 0;
5396 VectorFormat vf = nfd.GetVectorFormat();
5397 if (instr->Mask(NEON3SameExtraFCMLAMask) == NEON_FCMLA) {
5398 rot = instr->GetImmRotFcmlaVec();
5399 fcmla(vf, rd, rn, rm, rd, rot);
5400 } else if (instr->Mask(NEON3SameExtraFCADDMask) == NEON_FCADD) {
5401 rot = instr->GetImmRotFcadd();
5402 fcadd(vf, rd, rn, rm, rot);
5403 } else {
5404 switch (instr->Mask(NEON3SameExtraMask)) {
5405 case NEON_SDOT:
5406 sdot(vf, rd, rn, rm);
5407 break;
5408 case NEON_SQRDMLAH:
5409 sqrdmlah(vf, rd, rn, rm);
5410 break;
5411 case NEON_UDOT:
5412 udot(vf, rd, rn, rm);
5413 break;
5414 case NEON_SQRDMLSH:
5415 sqrdmlsh(vf, rd, rn, rm);
5416 break;
5417 default:
5418 VIXL_UNIMPLEMENTED();
5419 break;
5420 }
5421 }
5422 }
5423
5424
VisitNEON3Different(const Instruction * instr)5425 void Simulator::VisitNEON3Different(const Instruction* instr) {
5426 NEONFormatDecoder nfd(instr);
5427 VectorFormat vf = nfd.GetVectorFormat();
5428 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5429
5430 SimVRegister& rd = ReadVRegister(instr->GetRd());
5431 SimVRegister& rn = ReadVRegister(instr->GetRn());
5432 SimVRegister& rm = ReadVRegister(instr->GetRm());
5433
5434 switch (instr->Mask(NEON3DifferentMask)) {
5435 case NEON_PMULL:
5436 pmull(vf_l, rd, rn, rm);
5437 break;
5438 case NEON_PMULL2:
5439 pmull2(vf_l, rd, rn, rm);
5440 break;
5441 case NEON_UADDL:
5442 uaddl(vf_l, rd, rn, rm);
5443 break;
5444 case NEON_UADDL2:
5445 uaddl2(vf_l, rd, rn, rm);
5446 break;
5447 case NEON_SADDL:
5448 saddl(vf_l, rd, rn, rm);
5449 break;
5450 case NEON_SADDL2:
5451 saddl2(vf_l, rd, rn, rm);
5452 break;
5453 case NEON_USUBL:
5454 usubl(vf_l, rd, rn, rm);
5455 break;
5456 case NEON_USUBL2:
5457 usubl2(vf_l, rd, rn, rm);
5458 break;
5459 case NEON_SSUBL:
5460 ssubl(vf_l, rd, rn, rm);
5461 break;
5462 case NEON_SSUBL2:
5463 ssubl2(vf_l, rd, rn, rm);
5464 break;
5465 case NEON_SABAL:
5466 sabal(vf_l, rd, rn, rm);
5467 break;
5468 case NEON_SABAL2:
5469 sabal2(vf_l, rd, rn, rm);
5470 break;
5471 case NEON_UABAL:
5472 uabal(vf_l, rd, rn, rm);
5473 break;
5474 case NEON_UABAL2:
5475 uabal2(vf_l, rd, rn, rm);
5476 break;
5477 case NEON_SABDL:
5478 sabdl(vf_l, rd, rn, rm);
5479 break;
5480 case NEON_SABDL2:
5481 sabdl2(vf_l, rd, rn, rm);
5482 break;
5483 case NEON_UABDL:
5484 uabdl(vf_l, rd, rn, rm);
5485 break;
5486 case NEON_UABDL2:
5487 uabdl2(vf_l, rd, rn, rm);
5488 break;
5489 case NEON_SMLAL:
5490 smlal(vf_l, rd, rn, rm);
5491 break;
5492 case NEON_SMLAL2:
5493 smlal2(vf_l, rd, rn, rm);
5494 break;
5495 case NEON_UMLAL:
5496 umlal(vf_l, rd, rn, rm);
5497 break;
5498 case NEON_UMLAL2:
5499 umlal2(vf_l, rd, rn, rm);
5500 break;
5501 case NEON_SMLSL:
5502 smlsl(vf_l, rd, rn, rm);
5503 break;
5504 case NEON_SMLSL2:
5505 smlsl2(vf_l, rd, rn, rm);
5506 break;
5507 case NEON_UMLSL:
5508 umlsl(vf_l, rd, rn, rm);
5509 break;
5510 case NEON_UMLSL2:
5511 umlsl2(vf_l, rd, rn, rm);
5512 break;
5513 case NEON_SMULL:
5514 smull(vf_l, rd, rn, rm);
5515 break;
5516 case NEON_SMULL2:
5517 smull2(vf_l, rd, rn, rm);
5518 break;
5519 case NEON_UMULL:
5520 umull(vf_l, rd, rn, rm);
5521 break;
5522 case NEON_UMULL2:
5523 umull2(vf_l, rd, rn, rm);
5524 break;
5525 case NEON_SQDMLAL:
5526 sqdmlal(vf_l, rd, rn, rm);
5527 break;
5528 case NEON_SQDMLAL2:
5529 sqdmlal2(vf_l, rd, rn, rm);
5530 break;
5531 case NEON_SQDMLSL:
5532 sqdmlsl(vf_l, rd, rn, rm);
5533 break;
5534 case NEON_SQDMLSL2:
5535 sqdmlsl2(vf_l, rd, rn, rm);
5536 break;
5537 case NEON_SQDMULL:
5538 sqdmull(vf_l, rd, rn, rm);
5539 break;
5540 case NEON_SQDMULL2:
5541 sqdmull2(vf_l, rd, rn, rm);
5542 break;
5543 case NEON_UADDW:
5544 uaddw(vf_l, rd, rn, rm);
5545 break;
5546 case NEON_UADDW2:
5547 uaddw2(vf_l, rd, rn, rm);
5548 break;
5549 case NEON_SADDW:
5550 saddw(vf_l, rd, rn, rm);
5551 break;
5552 case NEON_SADDW2:
5553 saddw2(vf_l, rd, rn, rm);
5554 break;
5555 case NEON_USUBW:
5556 usubw(vf_l, rd, rn, rm);
5557 break;
5558 case NEON_USUBW2:
5559 usubw2(vf_l, rd, rn, rm);
5560 break;
5561 case NEON_SSUBW:
5562 ssubw(vf_l, rd, rn, rm);
5563 break;
5564 case NEON_SSUBW2:
5565 ssubw2(vf_l, rd, rn, rm);
5566 break;
5567 case NEON_ADDHN:
5568 addhn(vf, rd, rn, rm);
5569 break;
5570 case NEON_ADDHN2:
5571 addhn2(vf, rd, rn, rm);
5572 break;
5573 case NEON_RADDHN:
5574 raddhn(vf, rd, rn, rm);
5575 break;
5576 case NEON_RADDHN2:
5577 raddhn2(vf, rd, rn, rm);
5578 break;
5579 case NEON_SUBHN:
5580 subhn(vf, rd, rn, rm);
5581 break;
5582 case NEON_SUBHN2:
5583 subhn2(vf, rd, rn, rm);
5584 break;
5585 case NEON_RSUBHN:
5586 rsubhn(vf, rd, rn, rm);
5587 break;
5588 case NEON_RSUBHN2:
5589 rsubhn2(vf, rd, rn, rm);
5590 break;
5591 default:
5592 VIXL_UNIMPLEMENTED();
5593 }
5594 }
5595
5596
VisitNEONAcrossLanes(const Instruction * instr)5597 void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
5598 NEONFormatDecoder nfd(instr);
5599
5600 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5601
5602 SimVRegister& rd = ReadVRegister(instr->GetRd());
5603 SimVRegister& rn = ReadVRegister(instr->GetRn());
5604
5605 if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
5606 VectorFormat vf = nfd.GetVectorFormat(&map_half);
5607 switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
5608 case NEON_FMAXV_H:
5609 fmaxv(vf, rd, rn);
5610 break;
5611 case NEON_FMINV_H:
5612 fminv(vf, rd, rn);
5613 break;
5614 case NEON_FMAXNMV_H:
5615 fmaxnmv(vf, rd, rn);
5616 break;
5617 case NEON_FMINNMV_H:
5618 fminnmv(vf, rd, rn);
5619 break;
5620 default:
5621 VIXL_UNIMPLEMENTED();
5622 }
5623 } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
5624 // The input operand's VectorFormat is passed for these instructions.
5625 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5626
5627 switch (instr->Mask(NEONAcrossLanesFPMask)) {
5628 case NEON_FMAXV:
5629 fmaxv(vf, rd, rn);
5630 break;
5631 case NEON_FMINV:
5632 fminv(vf, rd, rn);
5633 break;
5634 case NEON_FMAXNMV:
5635 fmaxnmv(vf, rd, rn);
5636 break;
5637 case NEON_FMINNMV:
5638 fminnmv(vf, rd, rn);
5639 break;
5640 default:
5641 VIXL_UNIMPLEMENTED();
5642 }
5643 } else {
5644 VectorFormat vf = nfd.GetVectorFormat();
5645
5646 switch (instr->Mask(NEONAcrossLanesMask)) {
5647 case NEON_ADDV:
5648 addv(vf, rd, rn);
5649 break;
5650 case NEON_SMAXV:
5651 smaxv(vf, rd, rn);
5652 break;
5653 case NEON_SMINV:
5654 sminv(vf, rd, rn);
5655 break;
5656 case NEON_UMAXV:
5657 umaxv(vf, rd, rn);
5658 break;
5659 case NEON_UMINV:
5660 uminv(vf, rd, rn);
5661 break;
5662 case NEON_SADDLV:
5663 saddlv(vf, rd, rn);
5664 break;
5665 case NEON_UADDLV:
5666 uaddlv(vf, rd, rn);
5667 break;
5668 default:
5669 VIXL_UNIMPLEMENTED();
5670 }
5671 }
5672 }
5673
5674
VisitNEONByIndexedElement(const Instruction * instr)5675 void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
5676 NEONFormatDecoder nfd(instr);
5677 static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
5678 VectorFormat vf_r = nfd.GetVectorFormat();
5679 VectorFormat vf_half = nfd.GetVectorFormat(&map_half);
5680 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
5681
5682 SimVRegister& rd = ReadVRegister(instr->GetRd());
5683 SimVRegister& rn = ReadVRegister(instr->GetRn());
5684
5685 ByElementOp Op = NULL;
5686
5687 int rm_reg = instr->GetRm();
5688 int rm_low_reg = instr->GetRmLow16();
5689 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
5690 int index_hlm = (index << 1) | instr->GetNEONM();
5691
5692 switch (instr->Mask(NEONByIndexedElementFPLongMask)) {
5693 // These are oddballs and are best handled as special cases.
5694 // - Rm is encoded with only 4 bits (and must be in the lower 16 registers).
5695 // - The index is always H:L:M.
5696 case NEON_FMLAL_H_byelement:
5697 fmlal(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5698 return;
5699 case NEON_FMLAL2_H_byelement:
5700 fmlal2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5701 return;
5702 case NEON_FMLSL_H_byelement:
5703 fmlsl(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5704 return;
5705 case NEON_FMLSL2_H_byelement:
5706 fmlsl2(vf_r, rd, rn, ReadVRegister(rm_low_reg), index_hlm);
5707 return;
5708 }
5709
5710 if (instr->GetNEONSize() == 1) {
5711 rm_reg = rm_low_reg;
5712 index = index_hlm;
5713 }
5714
5715 switch (instr->Mask(NEONByIndexedElementMask)) {
5716 case NEON_MUL_byelement:
5717 Op = &Simulator::mul;
5718 vf = vf_r;
5719 break;
5720 case NEON_MLA_byelement:
5721 Op = &Simulator::mla;
5722 vf = vf_r;
5723 break;
5724 case NEON_MLS_byelement:
5725 Op = &Simulator::mls;
5726 vf = vf_r;
5727 break;
5728 case NEON_SQDMULH_byelement:
5729 Op = &Simulator::sqdmulh;
5730 vf = vf_r;
5731 break;
5732 case NEON_SQRDMULH_byelement:
5733 Op = &Simulator::sqrdmulh;
5734 vf = vf_r;
5735 break;
5736 case NEON_SDOT_byelement:
5737 Op = &Simulator::sdot;
5738 vf = vf_r;
5739 break;
5740 case NEON_SQRDMLAH_byelement:
5741 Op = &Simulator::sqrdmlah;
5742 vf = vf_r;
5743 break;
5744 case NEON_UDOT_byelement:
5745 Op = &Simulator::udot;
5746 vf = vf_r;
5747 break;
5748 case NEON_SQRDMLSH_byelement:
5749 Op = &Simulator::sqrdmlsh;
5750 vf = vf_r;
5751 break;
5752 case NEON_SMULL_byelement:
5753 if (instr->Mask(NEON_Q)) {
5754 Op = &Simulator::smull2;
5755 } else {
5756 Op = &Simulator::smull;
5757 }
5758 break;
5759 case NEON_UMULL_byelement:
5760 if (instr->Mask(NEON_Q)) {
5761 Op = &Simulator::umull2;
5762 } else {
5763 Op = &Simulator::umull;
5764 }
5765 break;
5766 case NEON_SMLAL_byelement:
5767 if (instr->Mask(NEON_Q)) {
5768 Op = &Simulator::smlal2;
5769 } else {
5770 Op = &Simulator::smlal;
5771 }
5772 break;
5773 case NEON_UMLAL_byelement:
5774 if (instr->Mask(NEON_Q)) {
5775 Op = &Simulator::umlal2;
5776 } else {
5777 Op = &Simulator::umlal;
5778 }
5779 break;
5780 case NEON_SMLSL_byelement:
5781 if (instr->Mask(NEON_Q)) {
5782 Op = &Simulator::smlsl2;
5783 } else {
5784 Op = &Simulator::smlsl;
5785 }
5786 break;
5787 case NEON_UMLSL_byelement:
5788 if (instr->Mask(NEON_Q)) {
5789 Op = &Simulator::umlsl2;
5790 } else {
5791 Op = &Simulator::umlsl;
5792 }
5793 break;
5794 case NEON_SQDMULL_byelement:
5795 if (instr->Mask(NEON_Q)) {
5796 Op = &Simulator::sqdmull2;
5797 } else {
5798 Op = &Simulator::sqdmull;
5799 }
5800 break;
5801 case NEON_SQDMLAL_byelement:
5802 if (instr->Mask(NEON_Q)) {
5803 Op = &Simulator::sqdmlal2;
5804 } else {
5805 Op = &Simulator::sqdmlal;
5806 }
5807 break;
5808 case NEON_SQDMLSL_byelement:
5809 if (instr->Mask(NEON_Q)) {
5810 Op = &Simulator::sqdmlsl2;
5811 } else {
5812 Op = &Simulator::sqdmlsl;
5813 }
5814 break;
5815 default:
5816 index = instr->GetNEONH();
5817 if (instr->GetFPType() == 0) {
5818 rm_reg &= 0xf;
5819 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
5820 } else if ((instr->GetFPType() & 1) == 0) {
5821 index = (index << 1) | instr->GetNEONL();
5822 }
5823
5824 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
5825
5826 switch (instr->Mask(NEONByIndexedElementFPMask)) {
5827 case NEON_FMUL_H_byelement:
5828 vf = vf_half;
5829 VIXL_FALLTHROUGH();
5830 case NEON_FMUL_byelement:
5831 Op = &Simulator::fmul;
5832 break;
5833 case NEON_FMLA_H_byelement:
5834 vf = vf_half;
5835 VIXL_FALLTHROUGH();
5836 case NEON_FMLA_byelement:
5837 Op = &Simulator::fmla;
5838 break;
5839 case NEON_FMLS_H_byelement:
5840 vf = vf_half;
5841 VIXL_FALLTHROUGH();
5842 case NEON_FMLS_byelement:
5843 Op = &Simulator::fmls;
5844 break;
5845 case NEON_FMULX_H_byelement:
5846 vf = vf_half;
5847 VIXL_FALLTHROUGH();
5848 case NEON_FMULX_byelement:
5849 Op = &Simulator::fmulx;
5850 break;
5851 default:
5852 if (instr->GetNEONSize() == 2) {
5853 index = instr->GetNEONH();
5854 } else {
5855 index = (instr->GetNEONH() << 1) | instr->GetNEONL();
5856 }
5857 switch (instr->Mask(NEONByIndexedElementFPComplexMask)) {
5858 case NEON_FCMLA_byelement:
5859 vf = vf_r;
5860 fcmla(vf,
5861 rd,
5862 rn,
5863 ReadVRegister(instr->GetRm()),
5864 index,
5865 instr->GetImmRotFcmlaSca());
5866 return;
5867 default:
5868 VIXL_UNIMPLEMENTED();
5869 }
5870 }
5871 }
5872
5873 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
5874 }
5875
5876
VisitNEONCopy(const Instruction * instr)5877 void Simulator::VisitNEONCopy(const Instruction* instr) {
5878 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
5879 VectorFormat vf = nfd.GetVectorFormat();
5880
5881 SimVRegister& rd = ReadVRegister(instr->GetRd());
5882 SimVRegister& rn = ReadVRegister(instr->GetRn());
5883 int imm5 = instr->GetImmNEON5();
5884 int tz = CountTrailingZeros(imm5, 32);
5885 int reg_index = imm5 >> (tz + 1);
5886
5887 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
5888 int imm4 = instr->GetImmNEON4();
5889 int rn_index = imm4 >> tz;
5890 ins_element(vf, rd, reg_index, rn, rn_index);
5891 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
5892 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
5893 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
5894 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
5895 value &= MaxUintFromFormat(vf);
5896 WriteXRegister(instr->GetRd(), value);
5897 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
5898 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
5899 if (instr->GetNEONQ()) {
5900 WriteXRegister(instr->GetRd(), value);
5901 } else {
5902 WriteWRegister(instr->GetRd(), (int32_t)value);
5903 }
5904 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
5905 dup_element(vf, rd, rn, reg_index);
5906 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
5907 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
5908 } else {
5909 VIXL_UNIMPLEMENTED();
5910 }
5911 }
5912
5913
VisitNEONExtract(const Instruction * instr)5914 void Simulator::VisitNEONExtract(const Instruction* instr) {
5915 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5916 VectorFormat vf = nfd.GetVectorFormat();
5917 SimVRegister& rd = ReadVRegister(instr->GetRd());
5918 SimVRegister& rn = ReadVRegister(instr->GetRn());
5919 SimVRegister& rm = ReadVRegister(instr->GetRm());
5920 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
5921 int index = instr->GetImmNEONExt();
5922 ext(vf, rd, rn, rm, index);
5923 } else {
5924 VIXL_UNIMPLEMENTED();
5925 }
5926 }
5927
5928
NEONLoadStoreMultiStructHelper(const Instruction * instr,AddrMode addr_mode)5929 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
5930 AddrMode addr_mode) {
5931 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
5932 VectorFormat vf = nfd.GetVectorFormat();
5933
5934 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
5935 int reg_size = RegisterSizeInBytesFromFormat(vf);
5936
5937 int reg[4];
5938 uint64_t addr[4];
5939 for (int i = 0; i < 4; i++) {
5940 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
5941 addr[i] = addr_base + (i * reg_size);
5942 }
5943 int struct_parts = 1;
5944 int reg_count = 1;
5945 bool log_read = true;
5946
5947 // Bit 23 determines whether this is an offset or post-index addressing mode.
5948 // In offset mode, bits 20 to 16 should be zero; these bits encode the
5949 // register or immediate in post-index mode.
5950 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
5951 VIXL_UNREACHABLE();
5952 }
5953
5954 // We use the PostIndex mask here, as it works in this case for both Offset
5955 // and PostIndex addressing.
5956 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
5957 case NEON_LD1_4v:
5958 case NEON_LD1_4v_post:
5959 ld1(vf, ReadVRegister(reg[3]), addr[3]);
5960 reg_count++;
5961 VIXL_FALLTHROUGH();
5962 case NEON_LD1_3v:
5963 case NEON_LD1_3v_post:
5964 ld1(vf, ReadVRegister(reg[2]), addr[2]);
5965 reg_count++;
5966 VIXL_FALLTHROUGH();
5967 case NEON_LD1_2v:
5968 case NEON_LD1_2v_post:
5969 ld1(vf, ReadVRegister(reg[1]), addr[1]);
5970 reg_count++;
5971 VIXL_FALLTHROUGH();
5972 case NEON_LD1_1v:
5973 case NEON_LD1_1v_post:
5974 ld1(vf, ReadVRegister(reg[0]), addr[0]);
5975 break;
5976 case NEON_ST1_4v:
5977 case NEON_ST1_4v_post:
5978 st1(vf, ReadVRegister(reg[3]), addr[3]);
5979 reg_count++;
5980 VIXL_FALLTHROUGH();
5981 case NEON_ST1_3v:
5982 case NEON_ST1_3v_post:
5983 st1(vf, ReadVRegister(reg[2]), addr[2]);
5984 reg_count++;
5985 VIXL_FALLTHROUGH();
5986 case NEON_ST1_2v:
5987 case NEON_ST1_2v_post:
5988 st1(vf, ReadVRegister(reg[1]), addr[1]);
5989 reg_count++;
5990 VIXL_FALLTHROUGH();
5991 case NEON_ST1_1v:
5992 case NEON_ST1_1v_post:
5993 st1(vf, ReadVRegister(reg[0]), addr[0]);
5994 log_read = false;
5995 break;
5996 case NEON_LD2_post:
5997 case NEON_LD2:
5998 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
5999 struct_parts = 2;
6000 reg_count = 2;
6001 break;
6002 case NEON_ST2:
6003 case NEON_ST2_post:
6004 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
6005 struct_parts = 2;
6006 reg_count = 2;
6007 log_read = false;
6008 break;
6009 case NEON_LD3_post:
6010 case NEON_LD3:
6011 ld3(vf,
6012 ReadVRegister(reg[0]),
6013 ReadVRegister(reg[1]),
6014 ReadVRegister(reg[2]),
6015 addr[0]);
6016 struct_parts = 3;
6017 reg_count = 3;
6018 break;
6019 case NEON_ST3:
6020 case NEON_ST3_post:
6021 st3(vf,
6022 ReadVRegister(reg[0]),
6023 ReadVRegister(reg[1]),
6024 ReadVRegister(reg[2]),
6025 addr[0]);
6026 struct_parts = 3;
6027 reg_count = 3;
6028 log_read = false;
6029 break;
6030 case NEON_ST4:
6031 case NEON_ST4_post:
6032 st4(vf,
6033 ReadVRegister(reg[0]),
6034 ReadVRegister(reg[1]),
6035 ReadVRegister(reg[2]),
6036 ReadVRegister(reg[3]),
6037 addr[0]);
6038 struct_parts = 4;
6039 reg_count = 4;
6040 log_read = false;
6041 break;
6042 case NEON_LD4_post:
6043 case NEON_LD4:
6044 ld4(vf,
6045 ReadVRegister(reg[0]),
6046 ReadVRegister(reg[1]),
6047 ReadVRegister(reg[2]),
6048 ReadVRegister(reg[3]),
6049 addr[0]);
6050 struct_parts = 4;
6051 reg_count = 4;
6052 break;
6053 default:
6054 VIXL_UNIMPLEMENTED();
6055 }
6056
6057 bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
6058 if (do_trace) {
6059 PrintRegisterFormat print_format =
6060 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
6061 const char* op;
6062 if (log_read) {
6063 op = "<-";
6064 } else {
6065 op = "->";
6066 // Stores don't represent a change to the source register's value, so only
6067 // print the relevant part of the value.
6068 print_format = GetPrintRegPartial(print_format);
6069 }
6070
6071 VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
6072 for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
6073 uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
6074 PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
6075 }
6076 }
6077
6078 if (addr_mode == PostIndex) {
6079 int rm = instr->GetRm();
6080 // The immediate post index addressing mode is indicated by rm = 31.
6081 // The immediate is implied by the number of vector registers used.
6082 addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
6083 : ReadXRegister(rm);
6084 WriteXRegister(instr->GetRn(), addr_base);
6085 } else {
6086 VIXL_ASSERT(addr_mode == Offset);
6087 }
6088 }
6089
6090
VisitNEONLoadStoreMultiStruct(const Instruction * instr)6091 void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
6092 NEONLoadStoreMultiStructHelper(instr, Offset);
6093 }
6094
6095
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)6096 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
6097 const Instruction* instr) {
6098 NEONLoadStoreMultiStructHelper(instr, PostIndex);
6099 }
6100
6101
NEONLoadStoreSingleStructHelper(const Instruction * instr,AddrMode addr_mode)6102 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
6103 AddrMode addr_mode) {
6104 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
6105 int rt = instr->GetRt();
6106
6107 // Bit 23 determines whether this is an offset or post-index addressing mode.
6108 // In offset mode, bits 20 to 16 should be zero; these bits encode the
6109 // register or immediate in post-index mode.
6110 if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
6111 VIXL_UNREACHABLE();
6112 }
6113
6114 // We use the PostIndex mask here, as it works in this case for both Offset
6115 // and PostIndex addressing.
6116 bool do_load = false;
6117
6118 bool replicating = false;
6119
6120 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
6121 VectorFormat vf_t = nfd.GetVectorFormat();
6122
6123 VectorFormat vf = kFormat16B;
6124 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
6125 case NEON_LD1_b:
6126 case NEON_LD1_b_post:
6127 case NEON_LD2_b:
6128 case NEON_LD2_b_post:
6129 case NEON_LD3_b:
6130 case NEON_LD3_b_post:
6131 case NEON_LD4_b:
6132 case NEON_LD4_b_post:
6133 do_load = true;
6134 VIXL_FALLTHROUGH();
6135 case NEON_ST1_b:
6136 case NEON_ST1_b_post:
6137 case NEON_ST2_b:
6138 case NEON_ST2_b_post:
6139 case NEON_ST3_b:
6140 case NEON_ST3_b_post:
6141 case NEON_ST4_b:
6142 case NEON_ST4_b_post:
6143 break;
6144
6145 case NEON_LD1_h:
6146 case NEON_LD1_h_post:
6147 case NEON_LD2_h:
6148 case NEON_LD2_h_post:
6149 case NEON_LD3_h:
6150 case NEON_LD3_h_post:
6151 case NEON_LD4_h:
6152 case NEON_LD4_h_post:
6153 do_load = true;
6154 VIXL_FALLTHROUGH();
6155 case NEON_ST1_h:
6156 case NEON_ST1_h_post:
6157 case NEON_ST2_h:
6158 case NEON_ST2_h_post:
6159 case NEON_ST3_h:
6160 case NEON_ST3_h_post:
6161 case NEON_ST4_h:
6162 case NEON_ST4_h_post:
6163 vf = kFormat8H;
6164 break;
6165 case NEON_LD1_s:
6166 case NEON_LD1_s_post:
6167 case NEON_LD2_s:
6168 case NEON_LD2_s_post:
6169 case NEON_LD3_s:
6170 case NEON_LD3_s_post:
6171 case NEON_LD4_s:
6172 case NEON_LD4_s_post:
6173 do_load = true;
6174 VIXL_FALLTHROUGH();
6175 case NEON_ST1_s:
6176 case NEON_ST1_s_post:
6177 case NEON_ST2_s:
6178 case NEON_ST2_s_post:
6179 case NEON_ST3_s:
6180 case NEON_ST3_s_post:
6181 case NEON_ST4_s:
6182 case NEON_ST4_s_post: {
6183 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
6184 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
6185 NEON_LD1_d_post);
6186 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
6187 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
6188 NEON_ST1_d_post);
6189 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
6190 break;
6191 }
6192
6193 case NEON_LD1R:
6194 case NEON_LD1R_post:
6195 case NEON_LD2R:
6196 case NEON_LD2R_post:
6197 case NEON_LD3R:
6198 case NEON_LD3R_post:
6199 case NEON_LD4R:
6200 case NEON_LD4R_post:
6201 vf = vf_t;
6202 do_load = true;
6203 replicating = true;
6204 break;
6205
6206 default:
6207 VIXL_UNIMPLEMENTED();
6208 }
6209
6210 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
6211 int lane = instr->GetNEONLSIndex(index_shift);
6212 int reg_count = 0;
6213 int rt2 = (rt + 1) % kNumberOfVRegisters;
6214 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
6215 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
6216 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
6217 case NEONLoadStoreSingle1:
6218 reg_count = 1;
6219 if (replicating) {
6220 VIXL_ASSERT(do_load);
6221 ld1r(vf, ReadVRegister(rt), addr);
6222 } else if (do_load) {
6223 ld1(vf, ReadVRegister(rt), lane, addr);
6224 } else {
6225 st1(vf, ReadVRegister(rt), lane, addr);
6226 }
6227 break;
6228 case NEONLoadStoreSingle2:
6229 reg_count = 2;
6230 if (replicating) {
6231 VIXL_ASSERT(do_load);
6232 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
6233 } else if (do_load) {
6234 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
6235 } else {
6236 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
6237 }
6238 break;
6239 case NEONLoadStoreSingle3:
6240 reg_count = 3;
6241 if (replicating) {
6242 VIXL_ASSERT(do_load);
6243 ld3r(vf,
6244 ReadVRegister(rt),
6245 ReadVRegister(rt2),
6246 ReadVRegister(rt3),
6247 addr);
6248 } else if (do_load) {
6249 ld3(vf,
6250 ReadVRegister(rt),
6251 ReadVRegister(rt2),
6252 ReadVRegister(rt3),
6253 lane,
6254 addr);
6255 } else {
6256 st3(vf,
6257 ReadVRegister(rt),
6258 ReadVRegister(rt2),
6259 ReadVRegister(rt3),
6260 lane,
6261 addr);
6262 }
6263 break;
6264 case NEONLoadStoreSingle4:
6265 reg_count = 4;
6266 if (replicating) {
6267 VIXL_ASSERT(do_load);
6268 ld4r(vf,
6269 ReadVRegister(rt),
6270 ReadVRegister(rt2),
6271 ReadVRegister(rt3),
6272 ReadVRegister(rt4),
6273 addr);
6274 } else if (do_load) {
6275 ld4(vf,
6276 ReadVRegister(rt),
6277 ReadVRegister(rt2),
6278 ReadVRegister(rt3),
6279 ReadVRegister(rt4),
6280 lane,
6281 addr);
6282 } else {
6283 st4(vf,
6284 ReadVRegister(rt),
6285 ReadVRegister(rt2),
6286 ReadVRegister(rt3),
6287 ReadVRegister(rt4),
6288 lane,
6289 addr);
6290 }
6291 break;
6292 default:
6293 VIXL_UNIMPLEMENTED();
6294 }
6295
6296 // Trace registers and/or memory writes.
6297 PrintRegisterFormat print_format =
6298 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
6299 if (do_load) {
6300 if (ShouldTraceVRegs()) {
6301 if (replicating) {
6302 PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
6303 } else {
6304 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
6305 }
6306 }
6307 } else {
6308 if (ShouldTraceWrites()) {
6309 // Stores don't represent a change to the source register's value, so only
6310 // print the relevant part of the value.
6311 print_format = GetPrintRegPartial(print_format);
6312 PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
6313 }
6314 }
6315
6316 if (addr_mode == PostIndex) {
6317 int rm = instr->GetRm();
6318 int lane_size = LaneSizeInBytesFromFormat(vf);
6319 WriteXRegister(instr->GetRn(),
6320 addr + ((rm == 31) ? (reg_count * lane_size)
6321 : ReadXRegister(rm)));
6322 }
6323 }
6324
6325
VisitNEONLoadStoreSingleStruct(const Instruction * instr)6326 void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
6327 NEONLoadStoreSingleStructHelper(instr, Offset);
6328 }
6329
6330
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)6331 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
6332 const Instruction* instr) {
6333 NEONLoadStoreSingleStructHelper(instr, PostIndex);
6334 }
6335
6336
VisitNEONModifiedImmediate(const Instruction * instr)6337 void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
6338 SimVRegister& rd = ReadVRegister(instr->GetRd());
6339 int cmode = instr->GetNEONCmode();
6340 int cmode_3_1 = (cmode >> 1) & 7;
6341 int cmode_3 = (cmode >> 3) & 1;
6342 int cmode_2 = (cmode >> 2) & 1;
6343 int cmode_1 = (cmode >> 1) & 1;
6344 int cmode_0 = cmode & 1;
6345 int half_enc = instr->ExtractBit(11);
6346 int q = instr->GetNEONQ();
6347 int op_bit = instr->GetNEONModImmOp();
6348 uint64_t imm8 = instr->GetImmNEONabcdefgh();
6349 // Find the format and immediate value
6350 uint64_t imm = 0;
6351 VectorFormat vform = kFormatUndefined;
6352 switch (cmode_3_1) {
6353 case 0x0:
6354 case 0x1:
6355 case 0x2:
6356 case 0x3:
6357 vform = (q == 1) ? kFormat4S : kFormat2S;
6358 imm = imm8 << (8 * cmode_3_1);
6359 break;
6360 case 0x4:
6361 case 0x5:
6362 vform = (q == 1) ? kFormat8H : kFormat4H;
6363 imm = imm8 << (8 * cmode_1);
6364 break;
6365 case 0x6:
6366 vform = (q == 1) ? kFormat4S : kFormat2S;
6367 if (cmode_0 == 0) {
6368 imm = imm8 << 8 | 0x000000ff;
6369 } else {
6370 imm = imm8 << 16 | 0x0000ffff;
6371 }
6372 break;
6373 case 0x7:
6374 if (cmode_0 == 0 && op_bit == 0) {
6375 vform = q ? kFormat16B : kFormat8B;
6376 imm = imm8;
6377 } else if (cmode_0 == 0 && op_bit == 1) {
6378 vform = q ? kFormat2D : kFormat1D;
6379 imm = 0;
6380 for (int i = 0; i < 8; ++i) {
6381 if (imm8 & (1 << i)) {
6382 imm |= (UINT64_C(0xff) << (8 * i));
6383 }
6384 }
6385 } else { // cmode_0 == 1, cmode == 0xf.
6386 if (half_enc == 1) {
6387 vform = q ? kFormat8H : kFormat4H;
6388 imm = Float16ToRawbits(instr->GetImmNEONFP16());
6389 } else if (op_bit == 0) {
6390 vform = q ? kFormat4S : kFormat2S;
6391 imm = FloatToRawbits(instr->GetImmNEONFP32());
6392 } else if (q == 1) {
6393 vform = kFormat2D;
6394 imm = DoubleToRawbits(instr->GetImmNEONFP64());
6395 } else {
6396 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
6397 VisitUnallocated(instr);
6398 }
6399 }
6400 break;
6401 default:
6402 VIXL_UNREACHABLE();
6403 break;
6404 }
6405
6406 // Find the operation
6407 NEONModifiedImmediateOp op;
6408 if (cmode_3 == 0) {
6409 if (cmode_0 == 0) {
6410 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6411 } else { // cmode<0> == '1'
6412 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6413 }
6414 } else { // cmode<3> == '1'
6415 if (cmode_2 == 0) {
6416 if (cmode_0 == 0) {
6417 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6418 } else { // cmode<0> == '1'
6419 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
6420 }
6421 } else { // cmode<2> == '1'
6422 if (cmode_1 == 0) {
6423 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
6424 } else { // cmode<1> == '1'
6425 if (cmode_0 == 0) {
6426 op = NEONModifiedImmediate_MOVI;
6427 } else { // cmode<0> == '1'
6428 op = NEONModifiedImmediate_MOVI;
6429 }
6430 }
6431 }
6432 }
6433
6434 // Call the logic function
6435 if (op == NEONModifiedImmediate_ORR) {
6436 orr(vform, rd, rd, imm);
6437 } else if (op == NEONModifiedImmediate_BIC) {
6438 bic(vform, rd, rd, imm);
6439 } else if (op == NEONModifiedImmediate_MOVI) {
6440 movi(vform, rd, imm);
6441 } else if (op == NEONModifiedImmediate_MVNI) {
6442 mvni(vform, rd, imm);
6443 } else {
6444 VisitUnimplemented(instr);
6445 }
6446 }
6447
6448
VisitNEONScalar2RegMisc(const Instruction * instr)6449 void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
6450 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6451 VectorFormat vf = nfd.GetVectorFormat();
6452
6453 SimVRegister& rd = ReadVRegister(instr->GetRd());
6454 SimVRegister& rn = ReadVRegister(instr->GetRn());
6455
6456 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
6457 // These instructions all use a two bit size field, except NOT and RBIT,
6458 // which use the field to encode the operation.
6459 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6460 case NEON_CMEQ_zero_scalar:
6461 cmp(vf, rd, rn, 0, eq);
6462 break;
6463 case NEON_CMGE_zero_scalar:
6464 cmp(vf, rd, rn, 0, ge);
6465 break;
6466 case NEON_CMGT_zero_scalar:
6467 cmp(vf, rd, rn, 0, gt);
6468 break;
6469 case NEON_CMLT_zero_scalar:
6470 cmp(vf, rd, rn, 0, lt);
6471 break;
6472 case NEON_CMLE_zero_scalar:
6473 cmp(vf, rd, rn, 0, le);
6474 break;
6475 case NEON_ABS_scalar:
6476 abs(vf, rd, rn);
6477 break;
6478 case NEON_SQABS_scalar:
6479 abs(vf, rd, rn).SignedSaturate(vf);
6480 break;
6481 case NEON_NEG_scalar:
6482 neg(vf, rd, rn);
6483 break;
6484 case NEON_SQNEG_scalar:
6485 neg(vf, rd, rn).SignedSaturate(vf);
6486 break;
6487 case NEON_SUQADD_scalar:
6488 suqadd(vf, rd, rn);
6489 break;
6490 case NEON_USQADD_scalar:
6491 usqadd(vf, rd, rn);
6492 break;
6493 default:
6494 VIXL_UNIMPLEMENTED();
6495 break;
6496 }
6497 } else {
6498 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6499 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6500
6501 // These instructions all use a one bit size field, except SQXTUN, SQXTN
6502 // and UQXTN, which use a two bit size field.
6503 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
6504 case NEON_FRECPE_scalar:
6505 frecpe(fpf, rd, rn, fpcr_rounding);
6506 break;
6507 case NEON_FRECPX_scalar:
6508 frecpx(fpf, rd, rn);
6509 break;
6510 case NEON_FRSQRTE_scalar:
6511 frsqrte(fpf, rd, rn);
6512 break;
6513 case NEON_FCMGT_zero_scalar:
6514 fcmp_zero(fpf, rd, rn, gt);
6515 break;
6516 case NEON_FCMGE_zero_scalar:
6517 fcmp_zero(fpf, rd, rn, ge);
6518 break;
6519 case NEON_FCMEQ_zero_scalar:
6520 fcmp_zero(fpf, rd, rn, eq);
6521 break;
6522 case NEON_FCMLE_zero_scalar:
6523 fcmp_zero(fpf, rd, rn, le);
6524 break;
6525 case NEON_FCMLT_zero_scalar:
6526 fcmp_zero(fpf, rd, rn, lt);
6527 break;
6528 case NEON_SCVTF_scalar:
6529 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6530 break;
6531 case NEON_UCVTF_scalar:
6532 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6533 break;
6534 case NEON_FCVTNS_scalar:
6535 fcvts(fpf, rd, rn, FPTieEven);
6536 break;
6537 case NEON_FCVTNU_scalar:
6538 fcvtu(fpf, rd, rn, FPTieEven);
6539 break;
6540 case NEON_FCVTPS_scalar:
6541 fcvts(fpf, rd, rn, FPPositiveInfinity);
6542 break;
6543 case NEON_FCVTPU_scalar:
6544 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6545 break;
6546 case NEON_FCVTMS_scalar:
6547 fcvts(fpf, rd, rn, FPNegativeInfinity);
6548 break;
6549 case NEON_FCVTMU_scalar:
6550 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6551 break;
6552 case NEON_FCVTZS_scalar:
6553 fcvts(fpf, rd, rn, FPZero);
6554 break;
6555 case NEON_FCVTZU_scalar:
6556 fcvtu(fpf, rd, rn, FPZero);
6557 break;
6558 case NEON_FCVTAS_scalar:
6559 fcvts(fpf, rd, rn, FPTieAway);
6560 break;
6561 case NEON_FCVTAU_scalar:
6562 fcvtu(fpf, rd, rn, FPTieAway);
6563 break;
6564 case NEON_FCVTXN_scalar:
6565 // Unlike all of the other FP instructions above, fcvtxn encodes dest
6566 // size S as size<0>=1. There's only one case, so we ignore the form.
6567 VIXL_ASSERT(instr->ExtractBit(22) == 1);
6568 fcvtxn(kFormatS, rd, rn);
6569 break;
6570 default:
6571 switch (instr->Mask(NEONScalar2RegMiscMask)) {
6572 case NEON_SQXTN_scalar:
6573 sqxtn(vf, rd, rn);
6574 break;
6575 case NEON_UQXTN_scalar:
6576 uqxtn(vf, rd, rn);
6577 break;
6578 case NEON_SQXTUN_scalar:
6579 sqxtun(vf, rd, rn);
6580 break;
6581 default:
6582 VIXL_UNIMPLEMENTED();
6583 }
6584 }
6585 }
6586 }
6587
6588
VisitNEONScalar2RegMiscFP16(const Instruction * instr)6589 void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
6590 VectorFormat fpf = kFormatH;
6591 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6592
6593 SimVRegister& rd = ReadVRegister(instr->GetRd());
6594 SimVRegister& rn = ReadVRegister(instr->GetRn());
6595
6596 switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
6597 case NEON_FRECPE_H_scalar:
6598 frecpe(fpf, rd, rn, fpcr_rounding);
6599 break;
6600 case NEON_FRECPX_H_scalar:
6601 frecpx(fpf, rd, rn);
6602 break;
6603 case NEON_FRSQRTE_H_scalar:
6604 frsqrte(fpf, rd, rn);
6605 break;
6606 case NEON_FCMGT_H_zero_scalar:
6607 fcmp_zero(fpf, rd, rn, gt);
6608 break;
6609 case NEON_FCMGE_H_zero_scalar:
6610 fcmp_zero(fpf, rd, rn, ge);
6611 break;
6612 case NEON_FCMEQ_H_zero_scalar:
6613 fcmp_zero(fpf, rd, rn, eq);
6614 break;
6615 case NEON_FCMLE_H_zero_scalar:
6616 fcmp_zero(fpf, rd, rn, le);
6617 break;
6618 case NEON_FCMLT_H_zero_scalar:
6619 fcmp_zero(fpf, rd, rn, lt);
6620 break;
6621 case NEON_SCVTF_H_scalar:
6622 scvtf(fpf, rd, rn, 0, fpcr_rounding);
6623 break;
6624 case NEON_UCVTF_H_scalar:
6625 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6626 break;
6627 case NEON_FCVTNS_H_scalar:
6628 fcvts(fpf, rd, rn, FPTieEven);
6629 break;
6630 case NEON_FCVTNU_H_scalar:
6631 fcvtu(fpf, rd, rn, FPTieEven);
6632 break;
6633 case NEON_FCVTPS_H_scalar:
6634 fcvts(fpf, rd, rn, FPPositiveInfinity);
6635 break;
6636 case NEON_FCVTPU_H_scalar:
6637 fcvtu(fpf, rd, rn, FPPositiveInfinity);
6638 break;
6639 case NEON_FCVTMS_H_scalar:
6640 fcvts(fpf, rd, rn, FPNegativeInfinity);
6641 break;
6642 case NEON_FCVTMU_H_scalar:
6643 fcvtu(fpf, rd, rn, FPNegativeInfinity);
6644 break;
6645 case NEON_FCVTZS_H_scalar:
6646 fcvts(fpf, rd, rn, FPZero);
6647 break;
6648 case NEON_FCVTZU_H_scalar:
6649 fcvtu(fpf, rd, rn, FPZero);
6650 break;
6651 case NEON_FCVTAS_H_scalar:
6652 fcvts(fpf, rd, rn, FPTieAway);
6653 break;
6654 case NEON_FCVTAU_H_scalar:
6655 fcvtu(fpf, rd, rn, FPTieAway);
6656 break;
6657 }
6658 }
6659
6660
VisitNEONScalar3Diff(const Instruction * instr)6661 void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
6662 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6663 VectorFormat vf = nfd.GetVectorFormat();
6664
6665 SimVRegister& rd = ReadVRegister(instr->GetRd());
6666 SimVRegister& rn = ReadVRegister(instr->GetRn());
6667 SimVRegister& rm = ReadVRegister(instr->GetRm());
6668 switch (instr->Mask(NEONScalar3DiffMask)) {
6669 case NEON_SQDMLAL_scalar:
6670 sqdmlal(vf, rd, rn, rm);
6671 break;
6672 case NEON_SQDMLSL_scalar:
6673 sqdmlsl(vf, rd, rn, rm);
6674 break;
6675 case NEON_SQDMULL_scalar:
6676 sqdmull(vf, rd, rn, rm);
6677 break;
6678 default:
6679 VIXL_UNIMPLEMENTED();
6680 }
6681 }
6682
6683
VisitNEONScalar3Same(const Instruction * instr)6684 void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
6685 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6686 VectorFormat vf = nfd.GetVectorFormat();
6687
6688 SimVRegister& rd = ReadVRegister(instr->GetRd());
6689 SimVRegister& rn = ReadVRegister(instr->GetRn());
6690 SimVRegister& rm = ReadVRegister(instr->GetRm());
6691
6692 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
6693 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6694 switch (instr->Mask(NEONScalar3SameFPMask)) {
6695 case NEON_FMULX_scalar:
6696 fmulx(vf, rd, rn, rm);
6697 break;
6698 case NEON_FACGE_scalar:
6699 fabscmp(vf, rd, rn, rm, ge);
6700 break;
6701 case NEON_FACGT_scalar:
6702 fabscmp(vf, rd, rn, rm, gt);
6703 break;
6704 case NEON_FCMEQ_scalar:
6705 fcmp(vf, rd, rn, rm, eq);
6706 break;
6707 case NEON_FCMGE_scalar:
6708 fcmp(vf, rd, rn, rm, ge);
6709 break;
6710 case NEON_FCMGT_scalar:
6711 fcmp(vf, rd, rn, rm, gt);
6712 break;
6713 case NEON_FRECPS_scalar:
6714 frecps(vf, rd, rn, rm);
6715 break;
6716 case NEON_FRSQRTS_scalar:
6717 frsqrts(vf, rd, rn, rm);
6718 break;
6719 case NEON_FABD_scalar:
6720 fabd(vf, rd, rn, rm);
6721 break;
6722 default:
6723 VIXL_UNIMPLEMENTED();
6724 }
6725 } else {
6726 switch (instr->Mask(NEONScalar3SameMask)) {
6727 case NEON_ADD_scalar:
6728 add(vf, rd, rn, rm);
6729 break;
6730 case NEON_SUB_scalar:
6731 sub(vf, rd, rn, rm);
6732 break;
6733 case NEON_CMEQ_scalar:
6734 cmp(vf, rd, rn, rm, eq);
6735 break;
6736 case NEON_CMGE_scalar:
6737 cmp(vf, rd, rn, rm, ge);
6738 break;
6739 case NEON_CMGT_scalar:
6740 cmp(vf, rd, rn, rm, gt);
6741 break;
6742 case NEON_CMHI_scalar:
6743 cmp(vf, rd, rn, rm, hi);
6744 break;
6745 case NEON_CMHS_scalar:
6746 cmp(vf, rd, rn, rm, hs);
6747 break;
6748 case NEON_CMTST_scalar:
6749 cmptst(vf, rd, rn, rm);
6750 break;
6751 case NEON_USHL_scalar:
6752 ushl(vf, rd, rn, rm);
6753 break;
6754 case NEON_SSHL_scalar:
6755 sshl(vf, rd, rn, rm);
6756 break;
6757 case NEON_SQDMULH_scalar:
6758 sqdmulh(vf, rd, rn, rm);
6759 break;
6760 case NEON_SQRDMULH_scalar:
6761 sqrdmulh(vf, rd, rn, rm);
6762 break;
6763 case NEON_UQADD_scalar:
6764 add(vf, rd, rn, rm).UnsignedSaturate(vf);
6765 break;
6766 case NEON_SQADD_scalar:
6767 add(vf, rd, rn, rm).SignedSaturate(vf);
6768 break;
6769 case NEON_UQSUB_scalar:
6770 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
6771 break;
6772 case NEON_SQSUB_scalar:
6773 sub(vf, rd, rn, rm).SignedSaturate(vf);
6774 break;
6775 case NEON_UQSHL_scalar:
6776 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
6777 break;
6778 case NEON_SQSHL_scalar:
6779 sshl(vf, rd, rn, rm).SignedSaturate(vf);
6780 break;
6781 case NEON_URSHL_scalar:
6782 ushl(vf, rd, rn, rm).Round(vf);
6783 break;
6784 case NEON_SRSHL_scalar:
6785 sshl(vf, rd, rn, rm).Round(vf);
6786 break;
6787 case NEON_UQRSHL_scalar:
6788 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
6789 break;
6790 case NEON_SQRSHL_scalar:
6791 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
6792 break;
6793 default:
6794 VIXL_UNIMPLEMENTED();
6795 }
6796 }
6797 }
6798
VisitNEONScalar3SameFP16(const Instruction * instr)6799 void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
6800 SimVRegister& rd = ReadVRegister(instr->GetRd());
6801 SimVRegister& rn = ReadVRegister(instr->GetRn());
6802 SimVRegister& rm = ReadVRegister(instr->GetRm());
6803
6804 switch (instr->Mask(NEONScalar3SameFP16Mask)) {
6805 case NEON_FABD_H_scalar:
6806 fabd(kFormatH, rd, rn, rm);
6807 break;
6808 case NEON_FMULX_H_scalar:
6809 fmulx(kFormatH, rd, rn, rm);
6810 break;
6811 case NEON_FCMEQ_H_scalar:
6812 fcmp(kFormatH, rd, rn, rm, eq);
6813 break;
6814 case NEON_FCMGE_H_scalar:
6815 fcmp(kFormatH, rd, rn, rm, ge);
6816 break;
6817 case NEON_FCMGT_H_scalar:
6818 fcmp(kFormatH, rd, rn, rm, gt);
6819 break;
6820 case NEON_FACGE_H_scalar:
6821 fabscmp(kFormatH, rd, rn, rm, ge);
6822 break;
6823 case NEON_FACGT_H_scalar:
6824 fabscmp(kFormatH, rd, rn, rm, gt);
6825 break;
6826 case NEON_FRECPS_H_scalar:
6827 frecps(kFormatH, rd, rn, rm);
6828 break;
6829 case NEON_FRSQRTS_H_scalar:
6830 frsqrts(kFormatH, rd, rn, rm);
6831 break;
6832 default:
6833 VIXL_UNREACHABLE();
6834 }
6835 }
6836
6837
VisitNEONScalar3SameExtra(const Instruction * instr)6838 void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
6839 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
6840 VectorFormat vf = nfd.GetVectorFormat();
6841
6842 SimVRegister& rd = ReadVRegister(instr->GetRd());
6843 SimVRegister& rn = ReadVRegister(instr->GetRn());
6844 SimVRegister& rm = ReadVRegister(instr->GetRm());
6845
6846 switch (instr->Mask(NEONScalar3SameExtraMask)) {
6847 case NEON_SQRDMLAH_scalar:
6848 sqrdmlah(vf, rd, rn, rm);
6849 break;
6850 case NEON_SQRDMLSH_scalar:
6851 sqrdmlsh(vf, rd, rn, rm);
6852 break;
6853 default:
6854 VIXL_UNIMPLEMENTED();
6855 }
6856 }
6857
VisitNEONScalarByIndexedElement(const Instruction * instr)6858 void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
6859 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
6860 VectorFormat vf = nfd.GetVectorFormat();
6861 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
6862
6863 SimVRegister& rd = ReadVRegister(instr->GetRd());
6864 SimVRegister& rn = ReadVRegister(instr->GetRn());
6865 ByElementOp Op = NULL;
6866
6867 int rm_reg = instr->GetRm();
6868 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
6869 if (instr->GetNEONSize() == 1) {
6870 rm_reg &= 0xf;
6871 index = (index << 1) | instr->GetNEONM();
6872 }
6873
6874 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
6875 case NEON_SQDMULL_byelement_scalar:
6876 Op = &Simulator::sqdmull;
6877 break;
6878 case NEON_SQDMLAL_byelement_scalar:
6879 Op = &Simulator::sqdmlal;
6880 break;
6881 case NEON_SQDMLSL_byelement_scalar:
6882 Op = &Simulator::sqdmlsl;
6883 break;
6884 case NEON_SQDMULH_byelement_scalar:
6885 Op = &Simulator::sqdmulh;
6886 vf = vf_r;
6887 break;
6888 case NEON_SQRDMULH_byelement_scalar:
6889 Op = &Simulator::sqrdmulh;
6890 vf = vf_r;
6891 break;
6892 case NEON_SQRDMLAH_byelement_scalar:
6893 Op = &Simulator::sqrdmlah;
6894 vf = vf_r;
6895 break;
6896 case NEON_SQRDMLSH_byelement_scalar:
6897 Op = &Simulator::sqrdmlsh;
6898 vf = vf_r;
6899 break;
6900 default:
6901 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
6902 index = instr->GetNEONH();
6903 if (instr->GetFPType() == 0) {
6904 index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
6905 rm_reg &= 0xf;
6906 vf = kFormatH;
6907 } else if ((instr->GetFPType() & 1) == 0) {
6908 index = (index << 1) | instr->GetNEONL();
6909 }
6910 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
6911 case NEON_FMUL_H_byelement_scalar:
6912 case NEON_FMUL_byelement_scalar:
6913 Op = &Simulator::fmul;
6914 break;
6915 case NEON_FMLA_H_byelement_scalar:
6916 case NEON_FMLA_byelement_scalar:
6917 Op = &Simulator::fmla;
6918 break;
6919 case NEON_FMLS_H_byelement_scalar:
6920 case NEON_FMLS_byelement_scalar:
6921 Op = &Simulator::fmls;
6922 break;
6923 case NEON_FMULX_H_byelement_scalar:
6924 case NEON_FMULX_byelement_scalar:
6925 Op = &Simulator::fmulx;
6926 break;
6927 default:
6928 VIXL_UNIMPLEMENTED();
6929 }
6930 }
6931
6932 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
6933 }
6934
6935
VisitNEONScalarCopy(const Instruction * instr)6936 void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
6937 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
6938 VectorFormat vf = nfd.GetVectorFormat();
6939
6940 SimVRegister& rd = ReadVRegister(instr->GetRd());
6941 SimVRegister& rn = ReadVRegister(instr->GetRn());
6942
6943 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
6944 int imm5 = instr->GetImmNEON5();
6945 int tz = CountTrailingZeros(imm5, 32);
6946 int rn_index = imm5 >> (tz + 1);
6947 dup_element(vf, rd, rn, rn_index);
6948 } else {
6949 VIXL_UNIMPLEMENTED();
6950 }
6951 }
6952
6953
VisitNEONScalarPairwise(const Instruction * instr)6954 void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
6955 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
6956 VectorFormat vf = nfd.GetVectorFormat();
6957
6958 SimVRegister& rd = ReadVRegister(instr->GetRd());
6959 SimVRegister& rn = ReadVRegister(instr->GetRn());
6960 switch (instr->Mask(NEONScalarPairwiseMask)) {
6961 case NEON_ADDP_scalar: {
6962 // All pairwise operations except ADDP use bit U to differentiate FP16
6963 // from FP32/FP64 variations.
6964 NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
6965 addp(nfd_addp.GetVectorFormat(), rd, rn);
6966 break;
6967 }
6968 case NEON_FADDP_h_scalar:
6969 case NEON_FADDP_scalar:
6970 faddp(vf, rd, rn);
6971 break;
6972 case NEON_FMAXP_h_scalar:
6973 case NEON_FMAXP_scalar:
6974 fmaxp(vf, rd, rn);
6975 break;
6976 case NEON_FMAXNMP_h_scalar:
6977 case NEON_FMAXNMP_scalar:
6978 fmaxnmp(vf, rd, rn);
6979 break;
6980 case NEON_FMINP_h_scalar:
6981 case NEON_FMINP_scalar:
6982 fminp(vf, rd, rn);
6983 break;
6984 case NEON_FMINNMP_h_scalar:
6985 case NEON_FMINNMP_scalar:
6986 fminnmp(vf, rd, rn);
6987 break;
6988 default:
6989 VIXL_UNIMPLEMENTED();
6990 }
6991 }
6992
6993
VisitNEONScalarShiftImmediate(const Instruction * instr)6994 void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
6995 SimVRegister& rd = ReadVRegister(instr->GetRd());
6996 SimVRegister& rn = ReadVRegister(instr->GetRn());
6997 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6998
6999 static const NEONFormatMap map = {{22, 21, 20, 19},
7000 {NF_UNDEF,
7001 NF_B,
7002 NF_H,
7003 NF_H,
7004 NF_S,
7005 NF_S,
7006 NF_S,
7007 NF_S,
7008 NF_D,
7009 NF_D,
7010 NF_D,
7011 NF_D,
7012 NF_D,
7013 NF_D,
7014 NF_D,
7015 NF_D}};
7016 NEONFormatDecoder nfd(instr, &map);
7017 VectorFormat vf = nfd.GetVectorFormat();
7018
7019 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
7020 int immh_immb = instr->GetImmNEONImmhImmb();
7021 int right_shift = (16 << highest_set_bit) - immh_immb;
7022 int left_shift = immh_immb - (8 << highest_set_bit);
7023 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
7024 case NEON_SHL_scalar:
7025 shl(vf, rd, rn, left_shift);
7026 break;
7027 case NEON_SLI_scalar:
7028 sli(vf, rd, rn, left_shift);
7029 break;
7030 case NEON_SQSHL_imm_scalar:
7031 sqshl(vf, rd, rn, left_shift);
7032 break;
7033 case NEON_UQSHL_imm_scalar:
7034 uqshl(vf, rd, rn, left_shift);
7035 break;
7036 case NEON_SQSHLU_scalar:
7037 sqshlu(vf, rd, rn, left_shift);
7038 break;
7039 case NEON_SRI_scalar:
7040 sri(vf, rd, rn, right_shift);
7041 break;
7042 case NEON_SSHR_scalar:
7043 sshr(vf, rd, rn, right_shift);
7044 break;
7045 case NEON_USHR_scalar:
7046 ushr(vf, rd, rn, right_shift);
7047 break;
7048 case NEON_SRSHR_scalar:
7049 sshr(vf, rd, rn, right_shift).Round(vf);
7050 break;
7051 case NEON_URSHR_scalar:
7052 ushr(vf, rd, rn, right_shift).Round(vf);
7053 break;
7054 case NEON_SSRA_scalar:
7055 ssra(vf, rd, rn, right_shift);
7056 break;
7057 case NEON_USRA_scalar:
7058 usra(vf, rd, rn, right_shift);
7059 break;
7060 case NEON_SRSRA_scalar:
7061 srsra(vf, rd, rn, right_shift);
7062 break;
7063 case NEON_URSRA_scalar:
7064 ursra(vf, rd, rn, right_shift);
7065 break;
7066 case NEON_UQSHRN_scalar:
7067 uqshrn(vf, rd, rn, right_shift);
7068 break;
7069 case NEON_UQRSHRN_scalar:
7070 uqrshrn(vf, rd, rn, right_shift);
7071 break;
7072 case NEON_SQSHRN_scalar:
7073 sqshrn(vf, rd, rn, right_shift);
7074 break;
7075 case NEON_SQRSHRN_scalar:
7076 sqrshrn(vf, rd, rn, right_shift);
7077 break;
7078 case NEON_SQSHRUN_scalar:
7079 sqshrun(vf, rd, rn, right_shift);
7080 break;
7081 case NEON_SQRSHRUN_scalar:
7082 sqrshrun(vf, rd, rn, right_shift);
7083 break;
7084 case NEON_FCVTZS_imm_scalar:
7085 fcvts(vf, rd, rn, FPZero, right_shift);
7086 break;
7087 case NEON_FCVTZU_imm_scalar:
7088 fcvtu(vf, rd, rn, FPZero, right_shift);
7089 break;
7090 case NEON_SCVTF_imm_scalar:
7091 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7092 break;
7093 case NEON_UCVTF_imm_scalar:
7094 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7095 break;
7096 default:
7097 VIXL_UNIMPLEMENTED();
7098 }
7099 }
7100
7101
VisitNEONShiftImmediate(const Instruction * instr)7102 void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
7103 SimVRegister& rd = ReadVRegister(instr->GetRd());
7104 SimVRegister& rn = ReadVRegister(instr->GetRn());
7105 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
7106
7107 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
7108 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
7109 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
7110 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
7111 NF_4H, NF_8H, NF_4H, NF_8H,
7112 NF_2S, NF_4S, NF_2S, NF_4S,
7113 NF_2S, NF_4S, NF_2S, NF_4S,
7114 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7115 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7116 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
7117 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
7118 NEONFormatDecoder nfd(instr, &map);
7119 VectorFormat vf = nfd.GetVectorFormat();
7120
7121 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
7122 static const NEONFormatMap map_l =
7123 {{22, 21, 20, 19},
7124 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
7125 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
7126
7127 int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
7128 int immh_immb = instr->GetImmNEONImmhImmb();
7129 int right_shift = (16 << highest_set_bit) - immh_immb;
7130 int left_shift = immh_immb - (8 << highest_set_bit);
7131
7132 switch (instr->Mask(NEONShiftImmediateMask)) {
7133 case NEON_SHL:
7134 shl(vf, rd, rn, left_shift);
7135 break;
7136 case NEON_SLI:
7137 sli(vf, rd, rn, left_shift);
7138 break;
7139 case NEON_SQSHLU:
7140 sqshlu(vf, rd, rn, left_shift);
7141 break;
7142 case NEON_SRI:
7143 sri(vf, rd, rn, right_shift);
7144 break;
7145 case NEON_SSHR:
7146 sshr(vf, rd, rn, right_shift);
7147 break;
7148 case NEON_USHR:
7149 ushr(vf, rd, rn, right_shift);
7150 break;
7151 case NEON_SRSHR:
7152 sshr(vf, rd, rn, right_shift).Round(vf);
7153 break;
7154 case NEON_URSHR:
7155 ushr(vf, rd, rn, right_shift).Round(vf);
7156 break;
7157 case NEON_SSRA:
7158 ssra(vf, rd, rn, right_shift);
7159 break;
7160 case NEON_USRA:
7161 usra(vf, rd, rn, right_shift);
7162 break;
7163 case NEON_SRSRA:
7164 srsra(vf, rd, rn, right_shift);
7165 break;
7166 case NEON_URSRA:
7167 ursra(vf, rd, rn, right_shift);
7168 break;
7169 case NEON_SQSHL_imm:
7170 sqshl(vf, rd, rn, left_shift);
7171 break;
7172 case NEON_UQSHL_imm:
7173 uqshl(vf, rd, rn, left_shift);
7174 break;
7175 case NEON_SCVTF_imm:
7176 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
7177 break;
7178 case NEON_UCVTF_imm:
7179 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
7180 break;
7181 case NEON_FCVTZS_imm:
7182 fcvts(vf, rd, rn, FPZero, right_shift);
7183 break;
7184 case NEON_FCVTZU_imm:
7185 fcvtu(vf, rd, rn, FPZero, right_shift);
7186 break;
7187 case NEON_SSHLL:
7188 vf = vf_l;
7189 if (instr->Mask(NEON_Q)) {
7190 sshll2(vf, rd, rn, left_shift);
7191 } else {
7192 sshll(vf, rd, rn, left_shift);
7193 }
7194 break;
7195 case NEON_USHLL:
7196 vf = vf_l;
7197 if (instr->Mask(NEON_Q)) {
7198 ushll2(vf, rd, rn, left_shift);
7199 } else {
7200 ushll(vf, rd, rn, left_shift);
7201 }
7202 break;
7203 case NEON_SHRN:
7204 if (instr->Mask(NEON_Q)) {
7205 shrn2(vf, rd, rn, right_shift);
7206 } else {
7207 shrn(vf, rd, rn, right_shift);
7208 }
7209 break;
7210 case NEON_RSHRN:
7211 if (instr->Mask(NEON_Q)) {
7212 rshrn2(vf, rd, rn, right_shift);
7213 } else {
7214 rshrn(vf, rd, rn, right_shift);
7215 }
7216 break;
7217 case NEON_UQSHRN:
7218 if (instr->Mask(NEON_Q)) {
7219 uqshrn2(vf, rd, rn, right_shift);
7220 } else {
7221 uqshrn(vf, rd, rn, right_shift);
7222 }
7223 break;
7224 case NEON_UQRSHRN:
7225 if (instr->Mask(NEON_Q)) {
7226 uqrshrn2(vf, rd, rn, right_shift);
7227 } else {
7228 uqrshrn(vf, rd, rn, right_shift);
7229 }
7230 break;
7231 case NEON_SQSHRN:
7232 if (instr->Mask(NEON_Q)) {
7233 sqshrn2(vf, rd, rn, right_shift);
7234 } else {
7235 sqshrn(vf, rd, rn, right_shift);
7236 }
7237 break;
7238 case NEON_SQRSHRN:
7239 if (instr->Mask(NEON_Q)) {
7240 sqrshrn2(vf, rd, rn, right_shift);
7241 } else {
7242 sqrshrn(vf, rd, rn, right_shift);
7243 }
7244 break;
7245 case NEON_SQSHRUN:
7246 if (instr->Mask(NEON_Q)) {
7247 sqshrun2(vf, rd, rn, right_shift);
7248 } else {
7249 sqshrun(vf, rd, rn, right_shift);
7250 }
7251 break;
7252 case NEON_SQRSHRUN:
7253 if (instr->Mask(NEON_Q)) {
7254 sqrshrun2(vf, rd, rn, right_shift);
7255 } else {
7256 sqrshrun(vf, rd, rn, right_shift);
7257 }
7258 break;
7259 default:
7260 VIXL_UNIMPLEMENTED();
7261 }
7262 }
7263
7264
VisitNEONTable(const Instruction * instr)7265 void Simulator::VisitNEONTable(const Instruction* instr) {
7266 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7267 VectorFormat vf = nfd.GetVectorFormat();
7268
7269 SimVRegister& rd = ReadVRegister(instr->GetRd());
7270 SimVRegister& rn = ReadVRegister(instr->GetRn());
7271 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
7272 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
7273 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
7274 SimVRegister& rm = ReadVRegister(instr->GetRm());
7275
7276 switch (instr->Mask(NEONTableMask)) {
7277 case NEON_TBL_1v:
7278 tbl(vf, rd, rn, rm);
7279 break;
7280 case NEON_TBL_2v:
7281 tbl(vf, rd, rn, rn2, rm);
7282 break;
7283 case NEON_TBL_3v:
7284 tbl(vf, rd, rn, rn2, rn3, rm);
7285 break;
7286 case NEON_TBL_4v:
7287 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
7288 break;
7289 case NEON_TBX_1v:
7290 tbx(vf, rd, rn, rm);
7291 break;
7292 case NEON_TBX_2v:
7293 tbx(vf, rd, rn, rn2, rm);
7294 break;
7295 case NEON_TBX_3v:
7296 tbx(vf, rd, rn, rn2, rn3, rm);
7297 break;
7298 case NEON_TBX_4v:
7299 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
7300 break;
7301 default:
7302 VIXL_UNIMPLEMENTED();
7303 }
7304 }
7305
7306
VisitNEONPerm(const Instruction * instr)7307 void Simulator::VisitNEONPerm(const Instruction* instr) {
7308 NEONFormatDecoder nfd(instr);
7309 VectorFormat vf = nfd.GetVectorFormat();
7310
7311 SimVRegister& rd = ReadVRegister(instr->GetRd());
7312 SimVRegister& rn = ReadVRegister(instr->GetRn());
7313 SimVRegister& rm = ReadVRegister(instr->GetRm());
7314
7315 switch (instr->Mask(NEONPermMask)) {
7316 case NEON_TRN1:
7317 trn1(vf, rd, rn, rm);
7318 break;
7319 case NEON_TRN2:
7320 trn2(vf, rd, rn, rm);
7321 break;
7322 case NEON_UZP1:
7323 uzp1(vf, rd, rn, rm);
7324 break;
7325 case NEON_UZP2:
7326 uzp2(vf, rd, rn, rm);
7327 break;
7328 case NEON_ZIP1:
7329 zip1(vf, rd, rn, rm);
7330 break;
7331 case NEON_ZIP2:
7332 zip2(vf, rd, rn, rm);
7333 break;
7334 default:
7335 VIXL_UNIMPLEMENTED();
7336 }
7337 }
7338
VisitSVEAddressGeneration(const Instruction * instr)7339 void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
7340 SimVRegister& zd = ReadVRegister(instr->GetRd());
7341 SimVRegister& zn = ReadVRegister(instr->GetRn());
7342 SimVRegister& zm = ReadVRegister(instr->GetRm());
7343 SimVRegister temp;
7344
7345 VectorFormat vform = kFormatVnD;
7346 mov(vform, temp, zm);
7347
7348 switch (instr->Mask(SVEAddressGenerationMask)) {
7349 case ADR_z_az_d_s32_scaled:
7350 sxt(vform, temp, temp, kSRegSize);
7351 break;
7352 case ADR_z_az_d_u32_scaled:
7353 uxt(vform, temp, temp, kSRegSize);
7354 break;
7355 case ADR_z_az_s_same_scaled:
7356 vform = kFormatVnS;
7357 break;
7358 case ADR_z_az_d_same_scaled:
7359 // Nothing to do.
7360 break;
7361 default:
7362 VIXL_UNIMPLEMENTED();
7363 break;
7364 }
7365
7366 int shift_amount = instr->ExtractBits(11, 10);
7367 shl(vform, temp, temp, shift_amount);
7368 add(vform, zd, zn, temp);
7369 }
7370
VisitSVEBitwiseLogicalWithImm_Unpredicated(const Instruction * instr)7371 void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
7372 const Instruction* instr) {
7373 Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
7374 switch (op) {
7375 case AND_z_zi:
7376 case EOR_z_zi:
7377 case ORR_z_zi: {
7378 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7379 uint64_t imm = instr->GetSVEImmLogical();
7380 // Valid immediate is a non-zero bits
7381 VIXL_ASSERT(imm != 0);
7382 SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
7383 op),
7384 SVEFormatFromLaneSizeInBytesLog2(lane_size),
7385 ReadVRegister(instr->GetRd()),
7386 imm);
7387 break;
7388 }
7389 default:
7390 VIXL_UNIMPLEMENTED();
7391 break;
7392 }
7393 }
7394
VisitSVEBroadcastBitmaskImm(const Instruction * instr)7395 void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
7396 switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
7397 case DUPM_z_i: {
7398 /* DUPM uses the same lane size and immediate encoding as bitwise logical
7399 * immediate instructions. */
7400 int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
7401 uint64_t imm = instr->GetSVEImmLogical();
7402 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7403 dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
7404 break;
7405 }
7406 default:
7407 VIXL_UNIMPLEMENTED();
7408 break;
7409 }
7410 }
7411
VisitSVEBitwiseLogicalUnpredicated(const Instruction * instr)7412 void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
7413 SimVRegister& zd = ReadVRegister(instr->GetRd());
7414 SimVRegister& zn = ReadVRegister(instr->GetRn());
7415 SimVRegister& zm = ReadVRegister(instr->GetRm());
7416 Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
7417
7418 LogicalOp logical_op;
7419 switch (op) {
7420 case AND_z_zz:
7421 logical_op = AND;
7422 break;
7423 case BIC_z_zz:
7424 logical_op = BIC;
7425 break;
7426 case EOR_z_zz:
7427 logical_op = EOR;
7428 break;
7429 case ORR_z_zz:
7430 logical_op = ORR;
7431 break;
7432 default:
7433 logical_op = LogicalOpMask;
7434 VIXL_UNIMPLEMENTED();
7435 break;
7436 }
7437 // Lane size of registers is irrelevant to the bitwise operations, so perform
7438 // the operation on D-sized lanes.
7439 SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
7440 }
7441
VisitSVEBitwiseShiftByImm_Predicated(const Instruction * instr)7442 void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
7443 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7444 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7445
7446 SimVRegister scratch;
7447 SimVRegister result;
7448
7449 bool for_division = false;
7450 Shift shift_op = NO_SHIFT;
7451 switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
7452 case ASRD_z_p_zi:
7453 shift_op = ASR;
7454 for_division = true;
7455 break;
7456 case ASR_z_p_zi:
7457 shift_op = ASR;
7458 break;
7459 case LSL_z_p_zi:
7460 shift_op = LSL;
7461 break;
7462 case LSR_z_p_zi:
7463 shift_op = LSR;
7464 break;
7465 default:
7466 VIXL_UNIMPLEMENTED();
7467 break;
7468 }
7469
7470 std::pair<int, int> shift_and_lane_size =
7471 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
7472 unsigned lane_size = shift_and_lane_size.second;
7473 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7474 int shift_dist = shift_and_lane_size.first;
7475
7476 if ((shift_op == ASR) && for_division) {
7477 asrd(vform, result, zdn, shift_dist);
7478 } else {
7479 if (shift_op == LSL) {
7480 // Shift distance is computed differently for LSL. Convert the result.
7481 shift_dist = (8 << lane_size) - shift_dist;
7482 }
7483 dup_immediate(vform, scratch, shift_dist);
7484 SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
7485 }
7486 mov_merging(vform, zdn, pg, result);
7487 }
7488
VisitSVEBitwiseShiftByVector_Predicated(const Instruction * instr)7489 void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
7490 const Instruction* instr) {
7491 VectorFormat vform = instr->GetSVEVectorFormat();
7492 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7493 SimVRegister& zm = ReadVRegister(instr->GetRn());
7494 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7495
7496 SimVRegister result;
7497 SimVRegister shiftand; // Vector to be shifted.
7498 SimVRegister shiftor; // Vector shift amount.
7499
7500 Shift shift_op = ASR;
7501 mov(vform, shiftand, zdn);
7502 mov(vform, shiftor, zm);
7503
7504 switch (instr->Mask(SVEBitwiseShiftByVector_PredicatedMask)) {
7505 case ASRR_z_p_zz:
7506 mov(vform, shiftand, zm);
7507 mov(vform, shiftor, zdn);
7508 VIXL_FALLTHROUGH();
7509 case ASR_z_p_zz:
7510 break;
7511 case LSLR_z_p_zz:
7512 mov(vform, shiftand, zm);
7513 mov(vform, shiftor, zdn);
7514 VIXL_FALLTHROUGH();
7515 case LSL_z_p_zz:
7516 shift_op = LSL;
7517 break;
7518 case LSRR_z_p_zz:
7519 mov(vform, shiftand, zm);
7520 mov(vform, shiftor, zdn);
7521 VIXL_FALLTHROUGH();
7522 case LSR_z_p_zz:
7523 shift_op = LSR;
7524 break;
7525 default:
7526 VIXL_UNIMPLEMENTED();
7527 break;
7528 }
7529 SVEBitwiseShiftHelper(shift_op,
7530 vform,
7531 result,
7532 shiftand,
7533 shiftor,
7534 /* is_wide_elements = */ false);
7535 mov_merging(vform, zdn, pg, result);
7536 }
7537
VisitSVEBitwiseShiftByWideElements_Predicated(const Instruction * instr)7538 void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
7539 const Instruction* instr) {
7540 VectorFormat vform = instr->GetSVEVectorFormat();
7541 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7542 SimVRegister& zm = ReadVRegister(instr->GetRn());
7543 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7544
7545 SimVRegister result;
7546 Shift shift_op = ASR;
7547
7548 switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
7549 case ASR_z_p_zw:
7550 break;
7551 case LSL_z_p_zw:
7552 shift_op = LSL;
7553 break;
7554 case LSR_z_p_zw:
7555 shift_op = LSR;
7556 break;
7557 default:
7558 VIXL_UNIMPLEMENTED();
7559 break;
7560 }
7561 SVEBitwiseShiftHelper(shift_op,
7562 vform,
7563 result,
7564 zdn,
7565 zm,
7566 /* is_wide_elements = */ true);
7567 mov_merging(vform, zdn, pg, result);
7568 }
7569
VisitSVEBitwiseShiftUnpredicated(const Instruction * instr)7570 void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
7571 SimVRegister& zd = ReadVRegister(instr->GetRd());
7572 SimVRegister& zn = ReadVRegister(instr->GetRn());
7573
7574 Shift shift_op;
7575 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7576 case ASR_z_zi:
7577 case ASR_z_zw:
7578 shift_op = ASR;
7579 break;
7580 case LSL_z_zi:
7581 case LSL_z_zw:
7582 shift_op = LSL;
7583 break;
7584 case LSR_z_zi:
7585 case LSR_z_zw:
7586 shift_op = LSR;
7587 break;
7588 default:
7589 shift_op = NO_SHIFT;
7590 VIXL_UNIMPLEMENTED();
7591 break;
7592 }
7593
7594 switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
7595 case ASR_z_zi:
7596 case LSL_z_zi:
7597 case LSR_z_zi: {
7598 SimVRegister scratch;
7599 std::pair<int, int> shift_and_lane_size =
7600 instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
7601 unsigned lane_size = shift_and_lane_size.second;
7602 VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
7603 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
7604 int shift_dist = shift_and_lane_size.first;
7605 if (shift_op == LSL) {
7606 // Shift distance is computed differently for LSL. Convert the result.
7607 shift_dist = (8 << lane_size) - shift_dist;
7608 }
7609 dup_immediate(vform, scratch, shift_dist);
7610 SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
7611 break;
7612 }
7613 case ASR_z_zw:
7614 case LSL_z_zw:
7615 case LSR_z_zw:
7616 SVEBitwiseShiftHelper(shift_op,
7617 instr->GetSVEVectorFormat(),
7618 zd,
7619 zn,
7620 ReadVRegister(instr->GetRm()),
7621 true);
7622 break;
7623 default:
7624 VIXL_UNIMPLEMENTED();
7625 break;
7626 }
7627 }
7628
VisitSVEIncDecRegisterByElementCount(const Instruction * instr)7629 void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
7630 // Although the instructions have a separate encoding class, the lane size is
7631 // encoded in the same way as most other SVE instructions.
7632 VectorFormat vform = instr->GetSVEVectorFormat();
7633
7634 int pattern = instr->GetImmSVEPredicateConstraint();
7635 int count = GetPredicateConstraintLaneCount(vform, pattern);
7636 int multiplier = instr->ExtractBits(19, 16) + 1;
7637
7638 switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
7639 case DECB_r_rs:
7640 case DECD_r_rs:
7641 case DECH_r_rs:
7642 case DECW_r_rs:
7643 count = -count;
7644 break;
7645 case INCB_r_rs:
7646 case INCD_r_rs:
7647 case INCH_r_rs:
7648 case INCW_r_rs:
7649 // Nothing to do.
7650 break;
7651 default:
7652 VIXL_UNIMPLEMENTED();
7653 return;
7654 }
7655
7656 WriteXRegister(instr->GetRd(),
7657 IncDecN(ReadXRegister(instr->GetRd()),
7658 count * multiplier,
7659 kXRegSize));
7660 }
7661
VisitSVEIncDecVectorByElementCount(const Instruction * instr)7662 void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
7663 VectorFormat vform = instr->GetSVEVectorFormat();
7664 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7665 VIXL_UNIMPLEMENTED();
7666 }
7667
7668 int pattern = instr->GetImmSVEPredicateConstraint();
7669 int count = GetPredicateConstraintLaneCount(vform, pattern);
7670 int multiplier = instr->ExtractBits(19, 16) + 1;
7671
7672 switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
7673 case DECD_z_zs:
7674 case DECH_z_zs:
7675 case DECW_z_zs:
7676 count = -count;
7677 break;
7678 case INCD_z_zs:
7679 case INCH_z_zs:
7680 case INCW_z_zs:
7681 // Nothing to do.
7682 break;
7683 default:
7684 VIXL_UNIMPLEMENTED();
7685 break;
7686 }
7687
7688 SimVRegister& zd = ReadVRegister(instr->GetRd());
7689 SimVRegister scratch;
7690 dup_immediate(vform,
7691 scratch,
7692 IncDecN(0,
7693 count * multiplier,
7694 LaneSizeInBitsFromFormat(vform)));
7695 add(vform, zd, zd, scratch);
7696 }
7697
VisitSVESaturatingIncDecRegisterByElementCount(const Instruction * instr)7698 void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
7699 const Instruction* instr) {
7700 // Although the instructions have a separate encoding class, the lane size is
7701 // encoded in the same way as most other SVE instructions.
7702 VectorFormat vform = instr->GetSVEVectorFormat();
7703
7704 int pattern = instr->GetImmSVEPredicateConstraint();
7705 int count = GetPredicateConstraintLaneCount(vform, pattern);
7706 int multiplier = instr->ExtractBits(19, 16) + 1;
7707
7708 unsigned width = kXRegSize;
7709 bool is_signed = false;
7710
7711 switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
7712 case SQDECB_r_rs_sx:
7713 case SQDECD_r_rs_sx:
7714 case SQDECH_r_rs_sx:
7715 case SQDECW_r_rs_sx:
7716 width = kWRegSize;
7717 VIXL_FALLTHROUGH();
7718 case SQDECB_r_rs_x:
7719 case SQDECD_r_rs_x:
7720 case SQDECH_r_rs_x:
7721 case SQDECW_r_rs_x:
7722 is_signed = true;
7723 count = -count;
7724 break;
7725 case SQINCB_r_rs_sx:
7726 case SQINCD_r_rs_sx:
7727 case SQINCH_r_rs_sx:
7728 case SQINCW_r_rs_sx:
7729 width = kWRegSize;
7730 VIXL_FALLTHROUGH();
7731 case SQINCB_r_rs_x:
7732 case SQINCD_r_rs_x:
7733 case SQINCH_r_rs_x:
7734 case SQINCW_r_rs_x:
7735 is_signed = true;
7736 break;
7737 case UQDECB_r_rs_uw:
7738 case UQDECD_r_rs_uw:
7739 case UQDECH_r_rs_uw:
7740 case UQDECW_r_rs_uw:
7741 width = kWRegSize;
7742 VIXL_FALLTHROUGH();
7743 case UQDECB_r_rs_x:
7744 case UQDECD_r_rs_x:
7745 case UQDECH_r_rs_x:
7746 case UQDECW_r_rs_x:
7747 count = -count;
7748 break;
7749 case UQINCB_r_rs_uw:
7750 case UQINCD_r_rs_uw:
7751 case UQINCH_r_rs_uw:
7752 case UQINCW_r_rs_uw:
7753 width = kWRegSize;
7754 VIXL_FALLTHROUGH();
7755 case UQINCB_r_rs_x:
7756 case UQINCD_r_rs_x:
7757 case UQINCH_r_rs_x:
7758 case UQINCW_r_rs_x:
7759 // Nothing to do.
7760 break;
7761 default:
7762 VIXL_UNIMPLEMENTED();
7763 break;
7764 }
7765
7766 WriteXRegister(instr->GetRd(),
7767 IncDecN(ReadXRegister(instr->GetRd()),
7768 count * multiplier,
7769 width,
7770 true,
7771 is_signed));
7772 }
7773
VisitSVESaturatingIncDecVectorByElementCount(const Instruction * instr)7774 void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
7775 const Instruction* instr) {
7776 VectorFormat vform = instr->GetSVEVectorFormat();
7777 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7778 VIXL_UNIMPLEMENTED();
7779 }
7780
7781 int pattern = instr->GetImmSVEPredicateConstraint();
7782 int count = GetPredicateConstraintLaneCount(vform, pattern);
7783 int multiplier = instr->ExtractBits(19, 16) + 1;
7784
7785 SimVRegister& zd = ReadVRegister(instr->GetRd());
7786 SimVRegister scratch;
7787 dup_immediate(vform,
7788 scratch,
7789 IncDecN(0,
7790 count * multiplier,
7791 LaneSizeInBitsFromFormat(vform)));
7792
7793 switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
7794 case SQDECD_z_zs:
7795 case SQDECH_z_zs:
7796 case SQDECW_z_zs:
7797 sub(vform, zd, zd, scratch).SignedSaturate(vform);
7798 break;
7799 case SQINCD_z_zs:
7800 case SQINCH_z_zs:
7801 case SQINCW_z_zs:
7802 add(vform, zd, zd, scratch).SignedSaturate(vform);
7803 break;
7804 case UQDECD_z_zs:
7805 case UQDECH_z_zs:
7806 case UQDECW_z_zs:
7807 sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
7808 break;
7809 case UQINCD_z_zs:
7810 case UQINCH_z_zs:
7811 case UQINCW_z_zs:
7812 add(vform, zd, zd, scratch).UnsignedSaturate(vform);
7813 break;
7814 default:
7815 VIXL_UNIMPLEMENTED();
7816 break;
7817 }
7818 }
7819
VisitSVEElementCount(const Instruction * instr)7820 void Simulator::VisitSVEElementCount(const Instruction* instr) {
7821 switch (instr->Mask(SVEElementCountMask)) {
7822 case CNTB_r_s:
7823 case CNTD_r_s:
7824 case CNTH_r_s:
7825 case CNTW_r_s:
7826 // All handled below.
7827 break;
7828 default:
7829 VIXL_UNIMPLEMENTED();
7830 break;
7831 }
7832
7833 // Although the instructions are separated, the lane size is encoded in the
7834 // same way as most other SVE instructions.
7835 VectorFormat vform = instr->GetSVEVectorFormat();
7836
7837 int pattern = instr->GetImmSVEPredicateConstraint();
7838 int count = GetPredicateConstraintLaneCount(vform, pattern);
7839 int multiplier = instr->ExtractBits(19, 16) + 1;
7840 WriteXRegister(instr->GetRd(), count * multiplier);
7841 }
7842
VisitSVEFPAccumulatingReduction(const Instruction * instr)7843 void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
7844 VectorFormat vform = instr->GetSVEVectorFormat();
7845 SimVRegister& vdn = ReadVRegister(instr->GetRd());
7846 SimVRegister& zm = ReadVRegister(instr->GetRn());
7847 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7848
7849 switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
7850 case FADDA_v_p_z:
7851 fadda(vform, vdn, pg, zm);
7852 break;
7853 default:
7854 VIXL_UNIMPLEMENTED();
7855 break;
7856 }
7857 }
7858
VisitSVEFPArithmetic_Predicated(const Instruction * instr)7859 void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
7860 VectorFormat vform = instr->GetSVEVectorFormat();
7861 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7862 SimVRegister& zm = ReadVRegister(instr->GetRn());
7863 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7864
7865 SimVRegister result;
7866
7867 switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
7868 case FABD_z_p_zz:
7869 fabd(vform, result, zdn, zm);
7870 break;
7871 case FADD_z_p_zz:
7872 fadd(vform, result, zdn, zm);
7873 break;
7874 case FDIVR_z_p_zz:
7875 fdiv(vform, result, zm, zdn);
7876 break;
7877 case FDIV_z_p_zz:
7878 fdiv(vform, result, zdn, zm);
7879 break;
7880 case FMAXNM_z_p_zz:
7881 fmaxnm(vform, result, zdn, zm);
7882 break;
7883 case FMAX_z_p_zz:
7884 fmax(vform, result, zdn, zm);
7885 break;
7886 case FMINNM_z_p_zz:
7887 fminnm(vform, result, zdn, zm);
7888 break;
7889 case FMIN_z_p_zz:
7890 fmin(vform, result, zdn, zm);
7891 break;
7892 case FMULX_z_p_zz:
7893 fmulx(vform, result, zdn, zm);
7894 break;
7895 case FMUL_z_p_zz:
7896 fmul(vform, result, zdn, zm);
7897 break;
7898 case FSCALE_z_p_zz:
7899 fscale(vform, result, zdn, zm);
7900 break;
7901 case FSUBR_z_p_zz:
7902 fsub(vform, result, zm, zdn);
7903 break;
7904 case FSUB_z_p_zz:
7905 fsub(vform, result, zdn, zm);
7906 break;
7907 default:
7908 VIXL_UNIMPLEMENTED();
7909 break;
7910 }
7911 mov_merging(vform, zdn, pg, result);
7912 }
7913
VisitSVEFPArithmeticWithImm_Predicated(const Instruction * instr)7914 void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
7915 const Instruction* instr) {
7916 VectorFormat vform = instr->GetSVEVectorFormat();
7917 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
7918 VIXL_UNIMPLEMENTED();
7919 }
7920
7921 SimVRegister& zdn = ReadVRegister(instr->GetRd());
7922 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
7923 SimVRegister result;
7924
7925 int i1 = instr->ExtractBit(5);
7926 SimVRegister add_sub_imm, min_max_imm, mul_imm;
7927 uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
7928 uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
7929 uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
7930 dup_immediate(vform, add_sub_imm, i1 ? one : half);
7931 dup_immediate(vform, min_max_imm, i1 ? one : 0);
7932 dup_immediate(vform, mul_imm, i1 ? two : half);
7933
7934 switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
7935 case FADD_z_p_zs:
7936 fadd(vform, result, zdn, add_sub_imm);
7937 break;
7938 case FMAXNM_z_p_zs:
7939 fmaxnm(vform, result, zdn, min_max_imm);
7940 break;
7941 case FMAX_z_p_zs:
7942 fmax(vform, result, zdn, min_max_imm);
7943 break;
7944 case FMINNM_z_p_zs:
7945 fminnm(vform, result, zdn, min_max_imm);
7946 break;
7947 case FMIN_z_p_zs:
7948 fmin(vform, result, zdn, min_max_imm);
7949 break;
7950 case FMUL_z_p_zs:
7951 fmul(vform, result, zdn, mul_imm);
7952 break;
7953 case FSUBR_z_p_zs:
7954 fsub(vform, result, add_sub_imm, zdn);
7955 break;
7956 case FSUB_z_p_zs:
7957 fsub(vform, result, zdn, add_sub_imm);
7958 break;
7959 default:
7960 VIXL_UNIMPLEMENTED();
7961 break;
7962 }
7963 mov_merging(vform, zdn, pg, result);
7964 }
7965
VisitSVEFPTrigMulAddCoefficient(const Instruction * instr)7966 void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
7967 VectorFormat vform = instr->GetSVEVectorFormat();
7968 SimVRegister& zd = ReadVRegister(instr->GetRd());
7969 SimVRegister& zm = ReadVRegister(instr->GetRn());
7970
7971 switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
7972 case FTMAD_z_zzi:
7973 ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
7974 break;
7975 default:
7976 VIXL_UNIMPLEMENTED();
7977 break;
7978 }
7979 }
7980
VisitSVEFPArithmeticUnpredicated(const Instruction * instr)7981 void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
7982 VectorFormat vform = instr->GetSVEVectorFormat();
7983 SimVRegister& zd = ReadVRegister(instr->GetRd());
7984 SimVRegister& zn = ReadVRegister(instr->GetRn());
7985 SimVRegister& zm = ReadVRegister(instr->GetRm());
7986
7987 switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
7988 case FADD_z_zz:
7989 fadd(vform, zd, zn, zm);
7990 break;
7991 case FMUL_z_zz:
7992 fmul(vform, zd, zn, zm);
7993 break;
7994 case FRECPS_z_zz:
7995 frecps(vform, zd, zn, zm);
7996 break;
7997 case FRSQRTS_z_zz:
7998 frsqrts(vform, zd, zn, zm);
7999 break;
8000 case FSUB_z_zz:
8001 fsub(vform, zd, zn, zm);
8002 break;
8003 case FTSMUL_z_zz:
8004 ftsmul(vform, zd, zn, zm);
8005 break;
8006 default:
8007 VIXL_UNIMPLEMENTED();
8008 break;
8009 }
8010 }
8011
VisitSVEFPCompareVectors(const Instruction * instr)8012 void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
8013 SimPRegister& pd = ReadPRegister(instr->GetPd());
8014 SimVRegister& zn = ReadVRegister(instr->GetRn());
8015 SimVRegister& zm = ReadVRegister(instr->GetRm());
8016 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8017 VectorFormat vform = instr->GetSVEVectorFormat();
8018 SimVRegister result;
8019
8020 switch (instr->Mask(SVEFPCompareVectorsMask)) {
8021 case FACGE_p_p_zz:
8022 fabscmp(vform, result, zn, zm, ge);
8023 break;
8024 case FACGT_p_p_zz:
8025 fabscmp(vform, result, zn, zm, gt);
8026 break;
8027 case FCMEQ_p_p_zz:
8028 fcmp(vform, result, zn, zm, eq);
8029 break;
8030 case FCMGE_p_p_zz:
8031 fcmp(vform, result, zn, zm, ge);
8032 break;
8033 case FCMGT_p_p_zz:
8034 fcmp(vform, result, zn, zm, gt);
8035 break;
8036 case FCMNE_p_p_zz:
8037 fcmp(vform, result, zn, zm, ne);
8038 break;
8039 case FCMUO_p_p_zz:
8040 fcmp(vform, result, zn, zm, uo);
8041 break;
8042 default:
8043 VIXL_UNIMPLEMENTED();
8044 break;
8045 }
8046
8047 ExtractFromSimVRegister(vform, pd, result);
8048 mov_zeroing(pd, pg, pd);
8049 }
8050
VisitSVEFPCompareWithZero(const Instruction * instr)8051 void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
8052 SimPRegister& pd = ReadPRegister(instr->GetPd());
8053 SimVRegister& zn = ReadVRegister(instr->GetRn());
8054 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8055 VectorFormat vform = instr->GetSVEVectorFormat();
8056 SimVRegister result;
8057
8058 SimVRegister zeros;
8059 dup_immediate(kFormatVnD, zeros, 0);
8060
8061 switch (instr->Mask(SVEFPCompareWithZeroMask)) {
8062 case FCMEQ_p_p_z0:
8063 fcmp(vform, result, zn, zeros, eq);
8064 break;
8065 case FCMGE_p_p_z0:
8066 fcmp(vform, result, zn, zeros, ge);
8067 break;
8068 case FCMGT_p_p_z0:
8069 fcmp(vform, result, zn, zeros, gt);
8070 break;
8071 case FCMLE_p_p_z0:
8072 fcmp(vform, result, zn, zeros, le);
8073 break;
8074 case FCMLT_p_p_z0:
8075 fcmp(vform, result, zn, zeros, lt);
8076 break;
8077 case FCMNE_p_p_z0:
8078 fcmp(vform, result, zn, zeros, ne);
8079 break;
8080 default:
8081 VIXL_UNIMPLEMENTED();
8082 break;
8083 }
8084
8085 ExtractFromSimVRegister(vform, pd, result);
8086 mov_zeroing(pd, pg, pd);
8087 }
8088
VisitSVEFPComplexAddition(const Instruction * instr)8089 void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
8090 VectorFormat vform = instr->GetSVEVectorFormat();
8091
8092 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
8093 VIXL_UNIMPLEMENTED();
8094 }
8095
8096 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8097 SimVRegister& zm = ReadVRegister(instr->GetRn());
8098 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8099 int rot = instr->ExtractBit(16);
8100
8101 SimVRegister result;
8102
8103 switch (instr->Mask(SVEFPComplexAdditionMask)) {
8104 case FCADD_z_p_zz:
8105 fcadd(vform, result, zdn, zm, rot);
8106 break;
8107 default:
8108 VIXL_UNIMPLEMENTED();
8109 break;
8110 }
8111 mov_merging(vform, zdn, pg, result);
8112 }
8113
VisitSVEFPComplexMulAdd(const Instruction * instr)8114 void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
8115 VectorFormat vform = instr->GetSVEVectorFormat();
8116
8117 if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
8118 VIXL_UNIMPLEMENTED();
8119 }
8120
8121 SimVRegister& zda = ReadVRegister(instr->GetRd());
8122 SimVRegister& zn = ReadVRegister(instr->GetRn());
8123 SimVRegister& zm = ReadVRegister(instr->GetRm());
8124 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8125 int rot = instr->ExtractBits(14, 13);
8126
8127 SimVRegister result;
8128
8129 switch (instr->Mask(SVEFPComplexMulAddMask)) {
8130 case FCMLA_z_p_zzz:
8131 fcmla(vform, result, zn, zm, zda, rot);
8132 break;
8133 default:
8134 VIXL_UNIMPLEMENTED();
8135 break;
8136 }
8137 mov_merging(vform, zda, pg, result);
8138 }
8139
VisitSVEFPComplexMulAddIndex(const Instruction * instr)8140 void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
8141 SimVRegister& zda = ReadVRegister(instr->GetRd());
8142 SimVRegister& zn = ReadVRegister(instr->GetRn());
8143 int rot = instr->ExtractBits(11, 10);
8144 unsigned zm_code = instr->GetRm();
8145 int index = -1;
8146 VectorFormat vform, vform_dup;
8147
8148 switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
8149 case FCMLA_z_zzzi_h:
8150 vform = kFormatVnH;
8151 vform_dup = kFormatVnS;
8152 index = zm_code >> 3;
8153 zm_code &= 0x7;
8154 break;
8155 case FCMLA_z_zzzi_s:
8156 vform = kFormatVnS;
8157 vform_dup = kFormatVnD;
8158 index = zm_code >> 4;
8159 zm_code &= 0xf;
8160 break;
8161 default:
8162 VIXL_UNIMPLEMENTED();
8163 break;
8164 }
8165
8166 if (index >= 0) {
8167 SimVRegister temp;
8168 dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
8169 fcmla(vform, zda, zn, temp, zda, rot);
8170 }
8171 }
8172
8173 typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
8174 LogicVRegister dst,
8175 const LogicVRegister& src);
8176
VisitSVEFPFastReduction(const Instruction * instr)8177 void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
8178 VectorFormat vform = instr->GetSVEVectorFormat();
8179 SimVRegister& vd = ReadVRegister(instr->GetRd());
8180 SimVRegister& zn = ReadVRegister(instr->GetRn());
8181 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8182 int lane_size = LaneSizeInBitsFromFormat(vform);
8183
8184 uint64_t inactive_value = 0;
8185 FastReduceFn fn = nullptr;
8186
8187 switch (instr->Mask(SVEFPFastReductionMask)) {
8188 case FADDV_v_p_z:
8189 fn = &Simulator::faddv;
8190 break;
8191 case FMAXNMV_v_p_z:
8192 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
8193 fn = &Simulator::fmaxnmv;
8194 break;
8195 case FMAXV_v_p_z:
8196 inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
8197 fn = &Simulator::fmaxv;
8198 break;
8199 case FMINNMV_v_p_z:
8200 inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
8201 fn = &Simulator::fminnmv;
8202 break;
8203 case FMINV_v_p_z:
8204 inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
8205 fn = &Simulator::fminv;
8206 break;
8207 default:
8208 VIXL_UNIMPLEMENTED();
8209 break;
8210 }
8211
8212 SimVRegister scratch;
8213 dup_immediate(vform, scratch, inactive_value);
8214 mov_merging(vform, scratch, pg, zn);
8215 if (fn != nullptr) (this->*fn)(vform, vd, scratch);
8216 }
8217
VisitSVEFPMulIndex(const Instruction * instr)8218 void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
8219 VectorFormat vform = kFormatUndefined;
8220 unsigned zm_code = instr->GetRm() & 0xf;
8221 unsigned index = instr->ExtractBits(20, 19);
8222
8223 switch (instr->Mask(SVEFPMulIndexMask)) {
8224 case FMUL_z_zzi_d:
8225 vform = kFormatVnD;
8226 index >>= 1; // Only bit 20 is the index for D lanes.
8227 break;
8228 case FMUL_z_zzi_h_i3h:
8229 index += 4; // Bit 22 (i3h) is the top bit of index.
8230 VIXL_FALLTHROUGH();
8231 case FMUL_z_zzi_h:
8232 vform = kFormatVnH;
8233 zm_code &= 7; // Three bits used for zm.
8234 break;
8235 case FMUL_z_zzi_s:
8236 vform = kFormatVnS;
8237 zm_code &= 7; // Three bits used for zm.
8238 break;
8239 default:
8240 VIXL_UNIMPLEMENTED();
8241 break;
8242 }
8243
8244 SimVRegister& zd = ReadVRegister(instr->GetRd());
8245 SimVRegister& zn = ReadVRegister(instr->GetRn());
8246 SimVRegister temp;
8247
8248 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
8249 fmul(vform, zd, zn, temp);
8250 }
8251
VisitSVEFPMulAdd(const Instruction * instr)8252 void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
8253 VectorFormat vform = instr->GetSVEVectorFormat();
8254
8255 SimVRegister& zd = ReadVRegister(instr->GetRd());
8256 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8257 SimVRegister result;
8258
8259 if (instr->ExtractBit(15) == 0) {
8260 // Floating-point multiply-accumulate writing addend.
8261 SimVRegister& zm = ReadVRegister(instr->GetRm());
8262 SimVRegister& zn = ReadVRegister(instr->GetRn());
8263
8264 switch (instr->Mask(SVEFPMulAddMask)) {
8265 // zda = zda + zn * zm
8266 case FMLA_z_p_zzz:
8267 fmla(vform, result, zd, zn, zm);
8268 break;
8269 // zda = -zda + -zn * zm
8270 case FNMLA_z_p_zzz:
8271 fneg(vform, result, zd);
8272 fmls(vform, result, result, zn, zm);
8273 break;
8274 // zda = zda + -zn * zm
8275 case FMLS_z_p_zzz:
8276 fmls(vform, result, zd, zn, zm);
8277 break;
8278 // zda = -zda + zn * zm
8279 case FNMLS_z_p_zzz:
8280 fneg(vform, result, zd);
8281 fmla(vform, result, result, zn, zm);
8282 break;
8283 default:
8284 VIXL_UNIMPLEMENTED();
8285 break;
8286 }
8287 } else {
8288 // Floating-point multiply-accumulate writing multiplicand.
8289 SimVRegister& za = ReadVRegister(instr->GetRm());
8290 SimVRegister& zm = ReadVRegister(instr->GetRn());
8291
8292 switch (instr->Mask(SVEFPMulAddMask)) {
8293 // zdn = za + zdn * zm
8294 case FMAD_z_p_zzz:
8295 fmla(vform, result, za, zd, zm);
8296 break;
8297 // zdn = -za + -zdn * zm
8298 case FNMAD_z_p_zzz:
8299 fneg(vform, result, za);
8300 fmls(vform, result, result, zd, zm);
8301 break;
8302 // zdn = za + -zdn * zm
8303 case FMSB_z_p_zzz:
8304 fmls(vform, result, za, zd, zm);
8305 break;
8306 // zdn = -za + zdn * zm
8307 case FNMSB_z_p_zzz:
8308 fneg(vform, result, za);
8309 fmla(vform, result, result, zd, zm);
8310 break;
8311 default:
8312 VIXL_UNIMPLEMENTED();
8313 break;
8314 }
8315 }
8316
8317 mov_merging(vform, zd, pg, result);
8318 }
8319
VisitSVEFPMulAddIndex(const Instruction * instr)8320 void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
8321 VectorFormat vform = kFormatUndefined;
8322 unsigned zm_code = 0xffffffff;
8323 unsigned index = 0xffffffff;
8324
8325 switch (instr->Mask(SVEFPMulAddIndexMask)) {
8326 case FMLA_z_zzzi_d:
8327 case FMLS_z_zzzi_d:
8328 vform = kFormatVnD;
8329 zm_code = instr->GetRmLow16();
8330 // Only bit 20 is the index for D lanes.
8331 index = instr->ExtractBit(20);
8332 break;
8333 case FMLA_z_zzzi_s:
8334 case FMLS_z_zzzi_s:
8335 vform = kFormatVnS;
8336 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
8337 index = instr->ExtractBits(20, 19);
8338 break;
8339 case FMLA_z_zzzi_h:
8340 case FMLS_z_zzzi_h:
8341 case FMLA_z_zzzi_h_i3h:
8342 case FMLS_z_zzzi_h_i3h:
8343 vform = kFormatVnH;
8344 zm_code = instr->GetRm() & 0x7; // Three bits used for zm.
8345 index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19);
8346 break;
8347 default:
8348 VIXL_UNIMPLEMENTED();
8349 break;
8350 }
8351
8352 SimVRegister& zd = ReadVRegister(instr->GetRd());
8353 SimVRegister& zn = ReadVRegister(instr->GetRn());
8354 SimVRegister temp;
8355
8356 dup_elements_to_segments(vform, temp, ReadVRegister(zm_code), index);
8357 if (instr->ExtractBit(10) == 1) {
8358 fmls(vform, zd, zd, zn, temp);
8359 } else {
8360 fmla(vform, zd, zd, zn, temp);
8361 }
8362 }
8363
VisitSVEFPConvertToInt(const Instruction * instr)8364 void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
8365 SimVRegister& zd = ReadVRegister(instr->GetRd());
8366 SimVRegister& zn = ReadVRegister(instr->GetRn());
8367 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8368 int dst_data_size;
8369 int src_data_size;
8370
8371 switch (instr->Mask(SVEFPConvertToIntMask)) {
8372 case FCVTZS_z_p_z_d2w:
8373 case FCVTZU_z_p_z_d2w:
8374 dst_data_size = kSRegSize;
8375 src_data_size = kDRegSize;
8376 break;
8377 case FCVTZS_z_p_z_d2x:
8378 case FCVTZU_z_p_z_d2x:
8379 dst_data_size = kDRegSize;
8380 src_data_size = kDRegSize;
8381 break;
8382 case FCVTZS_z_p_z_fp162h:
8383 case FCVTZU_z_p_z_fp162h:
8384 dst_data_size = kHRegSize;
8385 src_data_size = kHRegSize;
8386 break;
8387 case FCVTZS_z_p_z_fp162w:
8388 case FCVTZU_z_p_z_fp162w:
8389 dst_data_size = kSRegSize;
8390 src_data_size = kHRegSize;
8391 break;
8392 case FCVTZS_z_p_z_fp162x:
8393 case FCVTZU_z_p_z_fp162x:
8394 dst_data_size = kDRegSize;
8395 src_data_size = kHRegSize;
8396 break;
8397 case FCVTZS_z_p_z_s2w:
8398 case FCVTZU_z_p_z_s2w:
8399 dst_data_size = kSRegSize;
8400 src_data_size = kSRegSize;
8401 break;
8402 case FCVTZS_z_p_z_s2x:
8403 case FCVTZU_z_p_z_s2x:
8404 dst_data_size = kDRegSize;
8405 src_data_size = kSRegSize;
8406 break;
8407 default:
8408 VIXL_UNIMPLEMENTED();
8409 dst_data_size = 0;
8410 src_data_size = 0;
8411 break;
8412 }
8413
8414 VectorFormat vform =
8415 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8416
8417 if (instr->ExtractBit(16) == 0) {
8418 fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8419 } else {
8420 fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
8421 }
8422 }
8423
VisitSVEFPConvertPrecision(const Instruction * instr)8424 void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
8425 SimVRegister& zd = ReadVRegister(instr->GetRd());
8426 SimVRegister& zn = ReadVRegister(instr->GetRn());
8427 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8428 int dst_data_size;
8429 int src_data_size;
8430
8431 switch (instr->Mask(SVEFPConvertPrecisionMask)) {
8432 case FCVT_z_p_z_d2h:
8433 dst_data_size = kHRegSize;
8434 src_data_size = kDRegSize;
8435 break;
8436 case FCVT_z_p_z_d2s:
8437 dst_data_size = kSRegSize;
8438 src_data_size = kDRegSize;
8439 break;
8440 case FCVT_z_p_z_h2d:
8441 dst_data_size = kDRegSize;
8442 src_data_size = kHRegSize;
8443 break;
8444 case FCVT_z_p_z_h2s:
8445 dst_data_size = kSRegSize;
8446 src_data_size = kHRegSize;
8447 break;
8448 case FCVT_z_p_z_s2d:
8449 dst_data_size = kDRegSize;
8450 src_data_size = kSRegSize;
8451 break;
8452 case FCVT_z_p_z_s2h:
8453 dst_data_size = kHRegSize;
8454 src_data_size = kSRegSize;
8455 break;
8456 default:
8457 VIXL_UNIMPLEMENTED();
8458 dst_data_size = 0;
8459 src_data_size = 0;
8460 break;
8461 }
8462 VectorFormat vform =
8463 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8464
8465 fcvt(vform, dst_data_size, src_data_size, zd, pg, zn);
8466 }
8467
VisitSVEFPUnaryOp(const Instruction * instr)8468 void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
8469 SimVRegister& zd = ReadVRegister(instr->GetRd());
8470 SimVRegister& zn = ReadVRegister(instr->GetRn());
8471 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8472 VectorFormat vform = instr->GetSVEVectorFormat();
8473 SimVRegister result;
8474
8475 switch (instr->Mask(SVEFPUnaryOpMask)) {
8476 case FRECPX_z_p_z:
8477 frecpx(vform, result, zn);
8478 break;
8479 case FSQRT_z_p_z:
8480 fsqrt(vform, result, zn);
8481 break;
8482 default:
8483 VIXL_UNIMPLEMENTED();
8484 break;
8485 }
8486 mov_merging(vform, zd, pg, result);
8487 }
8488
VisitSVEFPRoundToIntegralValue(const Instruction * instr)8489 void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
8490 SimVRegister& zd = ReadVRegister(instr->GetRd());
8491 SimVRegister& zn = ReadVRegister(instr->GetRn());
8492 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8493 VectorFormat vform = instr->GetSVEVectorFormat();
8494 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8495 bool exact_exception = false;
8496
8497 switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
8498 case FRINTA_z_p_z:
8499 fpcr_rounding = FPTieAway;
8500 break;
8501 case FRINTI_z_p_z:
8502 break; // Use FPCR rounding mode.
8503 case FRINTM_z_p_z:
8504 fpcr_rounding = FPNegativeInfinity;
8505 break;
8506 case FRINTN_z_p_z:
8507 fpcr_rounding = FPTieEven;
8508 break;
8509 case FRINTP_z_p_z:
8510 fpcr_rounding = FPPositiveInfinity;
8511 break;
8512 case FRINTX_z_p_z:
8513 exact_exception = true;
8514 break;
8515 case FRINTZ_z_p_z:
8516 fpcr_rounding = FPZero;
8517 break;
8518 default:
8519 VIXL_UNIMPLEMENTED();
8520 break;
8521 }
8522
8523 SimVRegister result;
8524 frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
8525 mov_merging(vform, zd, pg, result);
8526 }
8527
VisitSVEIntConvertToFP(const Instruction * instr)8528 void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
8529 SimVRegister& zd = ReadVRegister(instr->GetRd());
8530 SimVRegister& zn = ReadVRegister(instr->GetRn());
8531 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8532 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8533 int dst_data_size;
8534 int src_data_size;
8535
8536 switch (instr->Mask(SVEIntConvertToFPMask)) {
8537 case SCVTF_z_p_z_h2fp16:
8538 case UCVTF_z_p_z_h2fp16:
8539 dst_data_size = kHRegSize;
8540 src_data_size = kHRegSize;
8541 break;
8542 case SCVTF_z_p_z_w2d:
8543 case UCVTF_z_p_z_w2d:
8544 dst_data_size = kDRegSize;
8545 src_data_size = kSRegSize;
8546 break;
8547 case SCVTF_z_p_z_w2fp16:
8548 case UCVTF_z_p_z_w2fp16:
8549 dst_data_size = kHRegSize;
8550 src_data_size = kSRegSize;
8551 break;
8552 case SCVTF_z_p_z_w2s:
8553 case UCVTF_z_p_z_w2s:
8554 dst_data_size = kSRegSize;
8555 src_data_size = kSRegSize;
8556 break;
8557 case SCVTF_z_p_z_x2d:
8558 case UCVTF_z_p_z_x2d:
8559 dst_data_size = kDRegSize;
8560 src_data_size = kDRegSize;
8561 break;
8562 case SCVTF_z_p_z_x2fp16:
8563 case UCVTF_z_p_z_x2fp16:
8564 dst_data_size = kHRegSize;
8565 src_data_size = kDRegSize;
8566 break;
8567 case SCVTF_z_p_z_x2s:
8568 case UCVTF_z_p_z_x2s:
8569 dst_data_size = kSRegSize;
8570 src_data_size = kDRegSize;
8571 break;
8572 default:
8573 VIXL_UNIMPLEMENTED();
8574 dst_data_size = 0;
8575 src_data_size = 0;
8576 break;
8577 }
8578
8579 VectorFormat vform =
8580 SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
8581
8582 if (instr->ExtractBit(16) == 0) {
8583 scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
8584 } else {
8585 ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
8586 }
8587 }
8588
VisitSVEFPUnaryOpUnpredicated(const Instruction * instr)8589 void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
8590 VectorFormat vform = instr->GetSVEVectorFormat();
8591 SimVRegister& zd = ReadVRegister(instr->GetRd());
8592 SimVRegister& zn = ReadVRegister(instr->GetRn());
8593 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8594
8595 switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
8596 case FRECPE_z_z:
8597 frecpe(vform, zd, zn, fpcr_rounding);
8598 break;
8599 case FRSQRTE_z_z:
8600 frsqrte(vform, zd, zn);
8601 break;
8602 default:
8603 VIXL_UNIMPLEMENTED();
8604 break;
8605 }
8606 }
8607
VisitSVEIncDecByPredicateCount(const Instruction * instr)8608 void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
8609 VectorFormat vform = instr->GetSVEVectorFormat();
8610 SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
8611
8612 int count = CountActiveLanes(vform, pg);
8613
8614 if (instr->ExtractBit(11) == 0) {
8615 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8616 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8617 case DECP_z_p_z:
8618 sub_uint(vform, zdn, zdn, count);
8619 break;
8620 case INCP_z_p_z:
8621 add_uint(vform, zdn, zdn, count);
8622 break;
8623 case SQDECP_z_p_z:
8624 sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
8625 break;
8626 case SQINCP_z_p_z:
8627 add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
8628 break;
8629 case UQDECP_z_p_z:
8630 sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
8631 break;
8632 case UQINCP_z_p_z:
8633 add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
8634 break;
8635 default:
8636 VIXL_UNIMPLEMENTED();
8637 break;
8638 }
8639 } else {
8640 bool is_saturating = (instr->ExtractBit(18) == 0);
8641 bool decrement =
8642 is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
8643 bool is_signed = (instr->ExtractBit(16) == 0);
8644 bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
8645 unsigned width = sf ? kXRegSize : kWRegSize;
8646
8647 switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
8648 case DECP_r_p_r:
8649 case INCP_r_p_r:
8650 case SQDECP_r_p_r_sx:
8651 case SQDECP_r_p_r_x:
8652 case SQINCP_r_p_r_sx:
8653 case SQINCP_r_p_r_x:
8654 case UQDECP_r_p_r_uw:
8655 case UQDECP_r_p_r_x:
8656 case UQINCP_r_p_r_uw:
8657 case UQINCP_r_p_r_x:
8658 WriteXRegister(instr->GetRd(),
8659 IncDecN(ReadXRegister(instr->GetRd()),
8660 decrement ? -count : count,
8661 width,
8662 is_saturating,
8663 is_signed));
8664 break;
8665 default:
8666 VIXL_UNIMPLEMENTED();
8667 break;
8668 }
8669 }
8670 }
8671
IncDecN(uint64_t acc,int64_t delta,unsigned n,bool is_saturating,bool is_signed)8672 uint64_t Simulator::IncDecN(uint64_t acc,
8673 int64_t delta,
8674 unsigned n,
8675 bool is_saturating,
8676 bool is_signed) {
8677 VIXL_ASSERT(n <= 64);
8678 VIXL_ASSERT(IsIntN(n, delta));
8679
8680 uint64_t sign_mask = UINT64_C(1) << (n - 1);
8681 uint64_t mask = GetUintMask(n);
8682
8683 acc &= mask; // Ignore initial accumulator high bits.
8684 uint64_t result = (acc + delta) & mask;
8685
8686 bool result_negative = ((result & sign_mask) != 0);
8687
8688 if (is_saturating) {
8689 if (is_signed) {
8690 bool acc_negative = ((acc & sign_mask) != 0);
8691 bool delta_negative = delta < 0;
8692
8693 // If the signs of the operands are the same, but different from the
8694 // result, there was an overflow.
8695 if ((acc_negative == delta_negative) &&
8696 (acc_negative != result_negative)) {
8697 if (result_negative) {
8698 // Saturate to [..., INT<n>_MAX].
8699 result_negative = false;
8700 result = mask & ~sign_mask; // E.g. 0x000000007fffffff
8701 } else {
8702 // Saturate to [INT<n>_MIN, ...].
8703 result_negative = true;
8704 result = ~mask | sign_mask; // E.g. 0xffffffff80000000
8705 }
8706 }
8707 } else {
8708 if ((delta < 0) && (result > acc)) {
8709 // Saturate to [0, ...].
8710 result = 0;
8711 } else if ((delta > 0) && (result < acc)) {
8712 // Saturate to [..., UINT<n>_MAX].
8713 result = mask;
8714 }
8715 }
8716 }
8717
8718 // Sign-extend if necessary.
8719 if (result_negative && is_signed) result |= ~mask;
8720
8721 return result;
8722 }
8723
VisitSVEIndexGeneration(const Instruction * instr)8724 void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
8725 VectorFormat vform = instr->GetSVEVectorFormat();
8726 SimVRegister& zd = ReadVRegister(instr->GetRd());
8727 switch (instr->Mask(SVEIndexGenerationMask)) {
8728 case INDEX_z_ii:
8729 case INDEX_z_ir:
8730 case INDEX_z_ri:
8731 case INDEX_z_rr: {
8732 uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
8733 : instr->ExtractSignedBits(9, 5);
8734 uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
8735 : instr->ExtractSignedBits(20, 16);
8736 index(vform, zd, start, step);
8737 break;
8738 }
8739 default:
8740 VIXL_UNIMPLEMENTED();
8741 break;
8742 }
8743 }
8744
VisitSVEIntArithmeticUnpredicated(const Instruction * instr)8745 void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
8746 VectorFormat vform = instr->GetSVEVectorFormat();
8747 SimVRegister& zd = ReadVRegister(instr->GetRd());
8748 SimVRegister& zn = ReadVRegister(instr->GetRn());
8749 SimVRegister& zm = ReadVRegister(instr->GetRm());
8750 switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
8751 case ADD_z_zz:
8752 add(vform, zd, zn, zm);
8753 break;
8754 case SQADD_z_zz:
8755 add(vform, zd, zn, zm).SignedSaturate(vform);
8756 break;
8757 case SQSUB_z_zz:
8758 sub(vform, zd, zn, zm).SignedSaturate(vform);
8759 break;
8760 case SUB_z_zz:
8761 sub(vform, zd, zn, zm);
8762 break;
8763 case UQADD_z_zz:
8764 add(vform, zd, zn, zm).UnsignedSaturate(vform);
8765 break;
8766 case UQSUB_z_zz:
8767 sub(vform, zd, zn, zm).UnsignedSaturate(vform);
8768 break;
8769 default:
8770 VIXL_UNIMPLEMENTED();
8771 break;
8772 }
8773 }
8774
VisitSVEIntAddSubtractVectors_Predicated(const Instruction * instr)8775 void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
8776 const Instruction* instr) {
8777 VectorFormat vform = instr->GetSVEVectorFormat();
8778 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8779 SimVRegister& zm = ReadVRegister(instr->GetRn());
8780 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8781 SimVRegister result;
8782
8783 switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
8784 case ADD_z_p_zz:
8785 add(vform, result, zdn, zm);
8786 break;
8787 case SUBR_z_p_zz:
8788 sub(vform, result, zm, zdn);
8789 break;
8790 case SUB_z_p_zz:
8791 sub(vform, result, zdn, zm);
8792 break;
8793 default:
8794 VIXL_UNIMPLEMENTED();
8795 break;
8796 }
8797 mov_merging(vform, zdn, pg, result);
8798 }
8799
VisitSVEBitwiseLogical_Predicated(const Instruction * instr)8800 void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
8801 VectorFormat vform = instr->GetSVEVectorFormat();
8802 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8803 SimVRegister& zm = ReadVRegister(instr->GetRn());
8804 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8805 SimVRegister result;
8806
8807 switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
8808 case AND_z_p_zz:
8809 SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
8810 break;
8811 case BIC_z_p_zz:
8812 SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
8813 break;
8814 case EOR_z_p_zz:
8815 SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
8816 break;
8817 case ORR_z_p_zz:
8818 SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
8819 break;
8820 default:
8821 VIXL_UNIMPLEMENTED();
8822 break;
8823 }
8824 mov_merging(vform, zdn, pg, result);
8825 }
8826
VisitSVEIntMulVectors_Predicated(const Instruction * instr)8827 void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
8828 VectorFormat vform = instr->GetSVEVectorFormat();
8829 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8830 SimVRegister& zm = ReadVRegister(instr->GetRn());
8831 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8832 SimVRegister result;
8833
8834 switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
8835 case MUL_z_p_zz:
8836 mul(vform, result, zdn, zm);
8837 break;
8838 case SMULH_z_p_zz:
8839 smulh(vform, result, zdn, zm);
8840 break;
8841 case UMULH_z_p_zz:
8842 umulh(vform, result, zdn, zm);
8843 break;
8844 default:
8845 VIXL_UNIMPLEMENTED();
8846 break;
8847 }
8848 mov_merging(vform, zdn, pg, result);
8849 }
8850
VisitSVEIntMinMaxDifference_Predicated(const Instruction * instr)8851 void Simulator::VisitSVEIntMinMaxDifference_Predicated(
8852 const Instruction* instr) {
8853 VectorFormat vform = instr->GetSVEVectorFormat();
8854 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8855 SimVRegister& zm = ReadVRegister(instr->GetRn());
8856 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8857 SimVRegister result;
8858
8859 switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
8860 case SABD_z_p_zz:
8861 absdiff(vform, result, zdn, zm, true);
8862 break;
8863 case SMAX_z_p_zz:
8864 smax(vform, result, zdn, zm);
8865 break;
8866 case SMIN_z_p_zz:
8867 smin(vform, result, zdn, zm);
8868 break;
8869 case UABD_z_p_zz:
8870 absdiff(vform, result, zdn, zm, false);
8871 break;
8872 case UMAX_z_p_zz:
8873 umax(vform, result, zdn, zm);
8874 break;
8875 case UMIN_z_p_zz:
8876 umin(vform, result, zdn, zm);
8877 break;
8878 default:
8879 VIXL_UNIMPLEMENTED();
8880 break;
8881 }
8882 mov_merging(vform, zdn, pg, result);
8883 }
8884
VisitSVEIntMulImm_Unpredicated(const Instruction * instr)8885 void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
8886 VectorFormat vform = instr->GetSVEVectorFormat();
8887 SimVRegister& zd = ReadVRegister(instr->GetRd());
8888 SimVRegister scratch;
8889
8890 switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
8891 case MUL_z_zi:
8892 dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
8893 mul(vform, zd, zd, scratch);
8894 break;
8895 default:
8896 VIXL_UNIMPLEMENTED();
8897 break;
8898 }
8899 }
8900
VisitSVEIntDivideVectors_Predicated(const Instruction * instr)8901 void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
8902 VectorFormat vform = instr->GetSVEVectorFormat();
8903 SimVRegister& zdn = ReadVRegister(instr->GetRd());
8904 SimVRegister& zm = ReadVRegister(instr->GetRn());
8905 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
8906 SimVRegister result;
8907
8908 VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
8909
8910 switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
8911 case SDIVR_z_p_zz:
8912 sdiv(vform, result, zm, zdn);
8913 break;
8914 case SDIV_z_p_zz:
8915 sdiv(vform, result, zdn, zm);
8916 break;
8917 case UDIVR_z_p_zz:
8918 udiv(vform, result, zm, zdn);
8919 break;
8920 case UDIV_z_p_zz:
8921 udiv(vform, result, zdn, zm);
8922 break;
8923 default:
8924 VIXL_UNIMPLEMENTED();
8925 break;
8926 }
8927 mov_merging(vform, zdn, pg, result);
8928 }
8929
VisitSVEIntMinMaxImm_Unpredicated(const Instruction * instr)8930 void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
8931 VectorFormat vform = instr->GetSVEVectorFormat();
8932 SimVRegister& zd = ReadVRegister(instr->GetRd());
8933 SimVRegister scratch;
8934
8935 uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
8936 int64_t signed_imm = instr->GetImmSVEIntWideSigned();
8937
8938 switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
8939 case SMAX_z_zi:
8940 dup_immediate(vform, scratch, signed_imm);
8941 smax(vform, zd, zd, scratch);
8942 break;
8943 case SMIN_z_zi:
8944 dup_immediate(vform, scratch, signed_imm);
8945 smin(vform, zd, zd, scratch);
8946 break;
8947 case UMAX_z_zi:
8948 dup_immediate(vform, scratch, unsigned_imm);
8949 umax(vform, zd, zd, scratch);
8950 break;
8951 case UMIN_z_zi:
8952 dup_immediate(vform, scratch, unsigned_imm);
8953 umin(vform, zd, zd, scratch);
8954 break;
8955 default:
8956 VIXL_UNIMPLEMENTED();
8957 break;
8958 }
8959 }
8960
VisitSVEIntCompareScalarCountAndLimit(const Instruction * instr)8961 void Simulator::VisitSVEIntCompareScalarCountAndLimit(
8962 const Instruction* instr) {
8963 unsigned rn_code = instr->GetRn();
8964 unsigned rm_code = instr->GetRm();
8965 SimPRegister& pd = ReadPRegister(instr->GetPd());
8966 VectorFormat vform = instr->GetSVEVectorFormat();
8967
8968 bool is_64_bit = instr->ExtractBit(12) == 1;
8969 int rsize = is_64_bit ? kXRegSize : kWRegSize;
8970 uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
8971
8972 uint64_t usrc1 = ReadXRegister(rn_code);
8973 int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
8974 uint64_t usrc2 = ssrc2 & mask;
8975
8976 bool last = true;
8977 for (int lane = 0; lane < LaneCountFromFormat(vform); lane++) {
8978 usrc1 &= mask;
8979 int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
8980
8981 bool cond = false;
8982 switch (instr->Mask(SVEIntCompareScalarCountAndLimitMask)) {
8983 case WHILELE_p_p_rr:
8984 cond = ssrc1 <= ssrc2;
8985 break;
8986 case WHILELO_p_p_rr:
8987 cond = usrc1 < usrc2;
8988 break;
8989 case WHILELS_p_p_rr:
8990 cond = usrc1 <= usrc2;
8991 break;
8992 case WHILELT_p_p_rr:
8993 cond = ssrc1 < ssrc2;
8994 break;
8995 default:
8996 VIXL_UNIMPLEMENTED();
8997 break;
8998 }
8999 last = last && cond;
9000 LogicPRegister dst(pd);
9001 dst.SetActive(vform, lane, last);
9002 usrc1++;
9003 }
9004
9005 PredTest(vform, GetPTrue(), pd);
9006 LogSystemRegister(NZCV);
9007 }
9008
VisitSVEConditionallyTerminateScalars(const Instruction * instr)9009 void Simulator::VisitSVEConditionallyTerminateScalars(
9010 const Instruction* instr) {
9011 unsigned rn_code = instr->GetRn();
9012 unsigned rm_code = instr->GetRm();
9013 bool is_64_bit = instr->ExtractBit(22) == 1;
9014 uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
9015 uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
9016 bool term;
9017 switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
9018 case CTERMEQ_rr:
9019 term = src1 == src2;
9020 break;
9021 case CTERMNE_rr:
9022 term = src1 != src2;
9023 break;
9024 default:
9025 term = false;
9026 VIXL_UNIMPLEMENTED();
9027 break;
9028 }
9029 ReadNzcv().SetN(term ? 1 : 0);
9030 ReadNzcv().SetV(term ? 0 : !ReadC());
9031 LogSystemRegister(NZCV);
9032 }
9033
VisitSVEIntCompareSignedImm(const Instruction * instr)9034 void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
9035 bool commute_inputs = false;
9036 Condition cond;
9037 switch (instr->Mask(SVEIntCompareSignedImmMask)) {
9038 case CMPEQ_p_p_zi:
9039 cond = eq;
9040 break;
9041 case CMPGE_p_p_zi:
9042 cond = ge;
9043 break;
9044 case CMPGT_p_p_zi:
9045 cond = gt;
9046 break;
9047 case CMPLE_p_p_zi:
9048 cond = ge;
9049 commute_inputs = true;
9050 break;
9051 case CMPLT_p_p_zi:
9052 cond = gt;
9053 commute_inputs = true;
9054 break;
9055 case CMPNE_p_p_zi:
9056 cond = ne;
9057 break;
9058 default:
9059 cond = al;
9060 VIXL_UNIMPLEMENTED();
9061 break;
9062 }
9063
9064 VectorFormat vform = instr->GetSVEVectorFormat();
9065 SimVRegister src2;
9066 dup_immediate(vform,
9067 src2,
9068 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
9069 SVEIntCompareVectorsHelper(cond,
9070 vform,
9071 ReadPRegister(instr->GetPd()),
9072 ReadPRegister(instr->GetPgLow8()),
9073 commute_inputs ? src2
9074 : ReadVRegister(instr->GetRn()),
9075 commute_inputs ? ReadVRegister(instr->GetRn())
9076 : src2);
9077 }
9078
VisitSVEIntCompareUnsignedImm(const Instruction * instr)9079 void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
9080 bool commute_inputs = false;
9081 Condition cond;
9082 switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
9083 case CMPHI_p_p_zi:
9084 cond = hi;
9085 break;
9086 case CMPHS_p_p_zi:
9087 cond = hs;
9088 break;
9089 case CMPLO_p_p_zi:
9090 cond = hi;
9091 commute_inputs = true;
9092 break;
9093 case CMPLS_p_p_zi:
9094 cond = hs;
9095 commute_inputs = true;
9096 break;
9097 default:
9098 cond = al;
9099 VIXL_UNIMPLEMENTED();
9100 break;
9101 }
9102
9103 VectorFormat vform = instr->GetSVEVectorFormat();
9104 SimVRegister src2;
9105 dup_immediate(vform, src2, instr->ExtractBits(20, 14));
9106 SVEIntCompareVectorsHelper(cond,
9107 vform,
9108 ReadPRegister(instr->GetPd()),
9109 ReadPRegister(instr->GetPgLow8()),
9110 commute_inputs ? src2
9111 : ReadVRegister(instr->GetRn()),
9112 commute_inputs ? ReadVRegister(instr->GetRn())
9113 : src2);
9114 }
9115
VisitSVEIntCompareVectors(const Instruction * instr)9116 void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
9117 Instr op = instr->Mask(SVEIntCompareVectorsMask);
9118 bool is_wide_elements = false;
9119 switch (op) {
9120 case CMPEQ_p_p_zw:
9121 case CMPGE_p_p_zw:
9122 case CMPGT_p_p_zw:
9123 case CMPHI_p_p_zw:
9124 case CMPHS_p_p_zw:
9125 case CMPLE_p_p_zw:
9126 case CMPLO_p_p_zw:
9127 case CMPLS_p_p_zw:
9128 case CMPLT_p_p_zw:
9129 case CMPNE_p_p_zw:
9130 is_wide_elements = true;
9131 break;
9132 }
9133
9134 Condition cond;
9135 switch (op) {
9136 case CMPEQ_p_p_zw:
9137 case CMPEQ_p_p_zz:
9138 cond = eq;
9139 break;
9140 case CMPGE_p_p_zw:
9141 case CMPGE_p_p_zz:
9142 cond = ge;
9143 break;
9144 case CMPGT_p_p_zw:
9145 case CMPGT_p_p_zz:
9146 cond = gt;
9147 break;
9148 case CMPHI_p_p_zw:
9149 case CMPHI_p_p_zz:
9150 cond = hi;
9151 break;
9152 case CMPHS_p_p_zw:
9153 case CMPHS_p_p_zz:
9154 cond = hs;
9155 break;
9156 case CMPNE_p_p_zw:
9157 case CMPNE_p_p_zz:
9158 cond = ne;
9159 break;
9160 case CMPLE_p_p_zw:
9161 cond = le;
9162 break;
9163 case CMPLO_p_p_zw:
9164 cond = lo;
9165 break;
9166 case CMPLS_p_p_zw:
9167 cond = ls;
9168 break;
9169 case CMPLT_p_p_zw:
9170 cond = lt;
9171 break;
9172 default:
9173 VIXL_UNIMPLEMENTED();
9174 cond = al;
9175 break;
9176 }
9177
9178 SVEIntCompareVectorsHelper(cond,
9179 instr->GetSVEVectorFormat(),
9180 ReadPRegister(instr->GetPd()),
9181 ReadPRegister(instr->GetPgLow8()),
9182 ReadVRegister(instr->GetRn()),
9183 ReadVRegister(instr->GetRm()),
9184 is_wide_elements);
9185 }
9186
VisitSVEFPExponentialAccelerator(const Instruction * instr)9187 void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
9188 VectorFormat vform = instr->GetSVEVectorFormat();
9189 SimVRegister& zd = ReadVRegister(instr->GetRd());
9190 SimVRegister& zn = ReadVRegister(instr->GetRn());
9191
9192 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
9193 (vform == kFormatVnD));
9194
9195 switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
9196 case FEXPA_z_z:
9197 fexpa(vform, zd, zn);
9198 break;
9199 default:
9200 VIXL_UNIMPLEMENTED();
9201 break;
9202 }
9203 }
9204
VisitSVEFPTrigSelectCoefficient(const Instruction * instr)9205 void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
9206 VectorFormat vform = instr->GetSVEVectorFormat();
9207 SimVRegister& zd = ReadVRegister(instr->GetRd());
9208 SimVRegister& zn = ReadVRegister(instr->GetRn());
9209 SimVRegister& zm = ReadVRegister(instr->GetRm());
9210
9211 VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
9212 (vform == kFormatVnD));
9213
9214 switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
9215 case FTSSEL_z_zz:
9216 ftssel(vform, zd, zn, zm);
9217 break;
9218 default:
9219 VIXL_UNIMPLEMENTED();
9220 break;
9221 }
9222 }
9223
VisitSVEConstructivePrefix_Unpredicated(const Instruction * instr)9224 void Simulator::VisitSVEConstructivePrefix_Unpredicated(
9225 const Instruction* instr) {
9226 SimVRegister& zd = ReadVRegister(instr->GetRd());
9227 SimVRegister& zn = ReadVRegister(instr->GetRn());
9228
9229 switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
9230 case MOVPRFX_z_z:
9231 mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
9232 // Record the movprfx, so the next ExecuteInstruction() can check it.
9233 movprfx_ = instr;
9234 break;
9235 default:
9236 VIXL_UNIMPLEMENTED();
9237 break;
9238 }
9239 }
9240
VisitSVEIntMulAddPredicated(const Instruction * instr)9241 void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
9242 VectorFormat vform = instr->GetSVEVectorFormat();
9243
9244 SimVRegister& zd = ReadVRegister(instr->GetRd());
9245 SimVRegister& zm = ReadVRegister(instr->GetRm());
9246
9247 SimVRegister result;
9248 switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
9249 case MLA_z_p_zzz:
9250 mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
9251 break;
9252 case MLS_z_p_zzz:
9253 mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
9254 break;
9255 case MAD_z_p_zzz:
9256 // 'za' is encoded in 'Rn'.
9257 mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
9258 break;
9259 case MSB_z_p_zzz: {
9260 // 'za' is encoded in 'Rn'.
9261 mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
9262 break;
9263 }
9264 default:
9265 VIXL_UNIMPLEMENTED();
9266 break;
9267 }
9268 mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
9269 }
9270
VisitSVEIntMulAddUnpredicated(const Instruction * instr)9271 void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
9272 VectorFormat vform = instr->GetSVEVectorFormat();
9273 SimVRegister& zda = ReadVRegister(instr->GetRd());
9274 SimVRegister& zn = ReadVRegister(instr->GetRn());
9275 SimVRegister& zm = ReadVRegister(instr->GetRm());
9276
9277 switch (instr->Mask(SVEIntMulAddUnpredicatedMask)) {
9278 case SDOT_z_zzz:
9279 sdot(vform, zda, zn, zm);
9280 break;
9281 case UDOT_z_zzz:
9282 udot(vform, zda, zn, zm);
9283 break;
9284 default:
9285 VIXL_UNIMPLEMENTED();
9286 break;
9287 }
9288 }
9289
VisitSVEMovprfx(const Instruction * instr)9290 void Simulator::VisitSVEMovprfx(const Instruction* instr) {
9291 VectorFormat vform = instr->GetSVEVectorFormat();
9292 SimVRegister& zn = ReadVRegister(instr->GetRn());
9293 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9294 SimVRegister& zd = ReadVRegister(instr->GetRd());
9295
9296 switch (instr->Mask(SVEMovprfxMask)) {
9297 case MOVPRFX_z_p_z:
9298 if (instr->ExtractBit(16)) {
9299 mov_merging(vform, zd, pg, zn);
9300 } else {
9301 mov_zeroing(vform, zd, pg, zn);
9302 }
9303
9304 // Record the movprfx, so the next ExecuteInstruction() can check it.
9305 movprfx_ = instr;
9306 break;
9307 default:
9308 VIXL_UNIMPLEMENTED();
9309 break;
9310 }
9311 }
9312
VisitSVEIntReduction(const Instruction * instr)9313 void Simulator::VisitSVEIntReduction(const Instruction* instr) {
9314 VectorFormat vform = instr->GetSVEVectorFormat();
9315 SimVRegister& vd = ReadVRegister(instr->GetRd());
9316 SimVRegister& zn = ReadVRegister(instr->GetRn());
9317 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9318
9319 if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
9320 switch (instr->Mask(SVEIntReductionLogicalMask)) {
9321 case ANDV_r_p_z:
9322 andv(vform, vd, pg, zn);
9323 break;
9324 case EORV_r_p_z:
9325 eorv(vform, vd, pg, zn);
9326 break;
9327 case ORV_r_p_z:
9328 orv(vform, vd, pg, zn);
9329 break;
9330 default:
9331 VIXL_UNIMPLEMENTED();
9332 break;
9333 }
9334 } else {
9335 switch (instr->Mask(SVEIntReductionMask)) {
9336 case SADDV_r_p_z:
9337 saddv(vform, vd, pg, zn);
9338 break;
9339 case SMAXV_r_p_z:
9340 smaxv(vform, vd, pg, zn);
9341 break;
9342 case SMINV_r_p_z:
9343 sminv(vform, vd, pg, zn);
9344 break;
9345 case UADDV_r_p_z:
9346 uaddv(vform, vd, pg, zn);
9347 break;
9348 case UMAXV_r_p_z:
9349 umaxv(vform, vd, pg, zn);
9350 break;
9351 case UMINV_r_p_z:
9352 uminv(vform, vd, pg, zn);
9353 break;
9354 default:
9355 VIXL_UNIMPLEMENTED();
9356 break;
9357 }
9358 }
9359 }
9360
VisitSVEIntUnaryArithmeticPredicated(const Instruction * instr)9361 void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
9362 VectorFormat vform = instr->GetSVEVectorFormat();
9363 SimVRegister& zn = ReadVRegister(instr->GetRn());
9364
9365 SimVRegister result;
9366 switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
9367 case ABS_z_p_z:
9368 abs(vform, result, zn);
9369 break;
9370 case CLS_z_p_z:
9371 cls(vform, result, zn);
9372 break;
9373 case CLZ_z_p_z:
9374 clz(vform, result, zn);
9375 break;
9376 case CNOT_z_p_z:
9377 cnot(vform, result, zn);
9378 break;
9379 case CNT_z_p_z:
9380 cnt(vform, result, zn);
9381 break;
9382 case FABS_z_p_z:
9383 fabs_(vform, result, zn);
9384 break;
9385 case FNEG_z_p_z:
9386 fneg(vform, result, zn);
9387 break;
9388 case NEG_z_p_z:
9389 neg(vform, result, zn);
9390 break;
9391 case NOT_z_p_z:
9392 not_(vform, result, zn);
9393 break;
9394 case SXTB_z_p_z:
9395 case SXTH_z_p_z:
9396 case SXTW_z_p_z:
9397 sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
9398 break;
9399 case UXTB_z_p_z:
9400 case UXTH_z_p_z:
9401 case UXTW_z_p_z:
9402 uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
9403 break;
9404 default:
9405 VIXL_UNIMPLEMENTED();
9406 break;
9407 }
9408
9409 SimVRegister& zd = ReadVRegister(instr->GetRd());
9410 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9411 mov_merging(vform, zd, pg, result);
9412 }
9413
VisitSVECopyFPImm_Predicated(const Instruction * instr)9414 void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
9415 // There is only one instruction in this group.
9416 VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
9417
9418 VectorFormat vform = instr->GetSVEVectorFormat();
9419 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
9420 SimVRegister& zd = ReadVRegister(instr->GetRd());
9421
9422 SimVRegister result;
9423 switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
9424 case FCPY_z_p_i: {
9425 int imm8 = instr->ExtractBits(12, 5);
9426 uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
9427 Instruction::Imm8ToFP64(imm8));
9428 dup_immediate(vform, result, value);
9429 break;
9430 }
9431 default:
9432 VIXL_UNIMPLEMENTED();
9433 break;
9434 }
9435 mov_merging(vform, zd, pg, result);
9436 }
9437
VisitSVEIntAddSubtractImm_Unpredicated(const Instruction * instr)9438 void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
9439 const Instruction* instr) {
9440 VectorFormat vform = instr->GetSVEVectorFormat();
9441 SimVRegister& zd = ReadVRegister(instr->GetRd());
9442 SimVRegister scratch;
9443
9444 uint64_t imm = instr->GetImmSVEIntWideUnsigned();
9445 imm <<= instr->ExtractBit(13) * 8;
9446
9447 switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
9448 case ADD_z_zi:
9449 add_uint(vform, zd, zd, imm);
9450 break;
9451 case SQADD_z_zi:
9452 add_uint(vform, zd, zd, imm).SignedSaturate(vform);
9453 break;
9454 case SQSUB_z_zi:
9455 sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
9456 break;
9457 case SUBR_z_zi:
9458 dup_immediate(vform, scratch, imm);
9459 sub(vform, zd, scratch, zd);
9460 break;
9461 case SUB_z_zi:
9462 sub_uint(vform, zd, zd, imm);
9463 break;
9464 case UQADD_z_zi:
9465 add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9466 break;
9467 case UQSUB_z_zi:
9468 sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
9469 break;
9470 default:
9471 break;
9472 }
9473 }
9474
VisitSVEBroadcastIntImm_Unpredicated(const Instruction * instr)9475 void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
9476 SimVRegister& zd = ReadVRegister(instr->GetRd());
9477
9478 VectorFormat format = instr->GetSVEVectorFormat();
9479 int64_t imm = instr->GetImmSVEIntWideSigned();
9480 int shift = instr->ExtractBit(13) * 8;
9481 imm *= 1 << shift;
9482
9483 switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
9484 case DUP_z_i:
9485 // The encoding of byte-sized lanes with lsl #8 is undefined.
9486 if ((format == kFormatVnB) && (shift == 8)) {
9487 VIXL_UNIMPLEMENTED();
9488 } else {
9489 dup_immediate(format, zd, imm);
9490 }
9491 break;
9492 default:
9493 VIXL_UNIMPLEMENTED();
9494 break;
9495 }
9496 }
9497
VisitSVEBroadcastFPImm_Unpredicated(const Instruction * instr)9498 void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
9499 VectorFormat vform = instr->GetSVEVectorFormat();
9500 SimVRegister& zd = ReadVRegister(instr->GetRd());
9501
9502 switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
9503 case FDUP_z_i:
9504 switch (vform) {
9505 case kFormatVnH:
9506 dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
9507 break;
9508 case kFormatVnS:
9509 dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
9510 break;
9511 case kFormatVnD:
9512 dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
9513 break;
9514 default:
9515 VIXL_UNIMPLEMENTED();
9516 }
9517 break;
9518 default:
9519 VIXL_UNIMPLEMENTED();
9520 break;
9521 }
9522 }
9523
VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(const Instruction * instr)9524 void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
9525 const Instruction* instr) {
9526 switch (instr->Mask(
9527 SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
9528 case LD1H_z_p_bz_s_x32_scaled:
9529 case LD1SH_z_p_bz_s_x32_scaled:
9530 case LDFF1H_z_p_bz_s_x32_scaled:
9531 case LDFF1SH_z_p_bz_s_x32_scaled:
9532 break;
9533 default:
9534 VIXL_UNIMPLEMENTED();
9535 break;
9536 }
9537
9538 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9539 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
9540 }
9541
VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)9542 void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
9543 const Instruction* instr) {
9544 switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
9545 case LD1B_z_p_bz_s_x32_unscaled:
9546 case LD1H_z_p_bz_s_x32_unscaled:
9547 case LD1SB_z_p_bz_s_x32_unscaled:
9548 case LD1SH_z_p_bz_s_x32_unscaled:
9549 case LD1W_z_p_bz_s_x32_unscaled:
9550 case LDFF1B_z_p_bz_s_x32_unscaled:
9551 case LDFF1H_z_p_bz_s_x32_unscaled:
9552 case LDFF1SB_z_p_bz_s_x32_unscaled:
9553 case LDFF1SH_z_p_bz_s_x32_unscaled:
9554 case LDFF1W_z_p_bz_s_x32_unscaled:
9555 break;
9556 default:
9557 VIXL_UNIMPLEMENTED();
9558 break;
9559 }
9560
9561 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9562 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
9563 }
9564
VisitSVE32BitGatherLoad_VectorPlusImm(const Instruction * instr)9565 void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
9566 const Instruction* instr) {
9567 switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
9568 case LD1B_z_p_ai_s:
9569 VIXL_UNIMPLEMENTED();
9570 break;
9571 case LD1H_z_p_ai_s:
9572 VIXL_UNIMPLEMENTED();
9573 break;
9574 case LD1SB_z_p_ai_s:
9575 VIXL_UNIMPLEMENTED();
9576 break;
9577 case LD1SH_z_p_ai_s:
9578 VIXL_UNIMPLEMENTED();
9579 break;
9580 case LD1W_z_p_ai_s:
9581 VIXL_UNIMPLEMENTED();
9582 break;
9583 case LDFF1B_z_p_ai_s:
9584 VIXL_UNIMPLEMENTED();
9585 break;
9586 case LDFF1H_z_p_ai_s:
9587 VIXL_UNIMPLEMENTED();
9588 break;
9589 case LDFF1SB_z_p_ai_s:
9590 VIXL_UNIMPLEMENTED();
9591 break;
9592 case LDFF1SH_z_p_ai_s:
9593 VIXL_UNIMPLEMENTED();
9594 break;
9595 case LDFF1W_z_p_ai_s:
9596 VIXL_UNIMPLEMENTED();
9597 break;
9598 default:
9599 VIXL_UNIMPLEMENTED();
9600 break;
9601 }
9602 }
9603
VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(const Instruction * instr)9604 void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
9605 const Instruction* instr) {
9606 switch (
9607 instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
9608 case LD1W_z_p_bz_s_x32_scaled:
9609 case LDFF1W_z_p_bz_s_x32_scaled:
9610 break;
9611 default:
9612 VIXL_UNIMPLEMENTED();
9613 break;
9614 }
9615
9616 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9617 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
9618 }
9619
VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(const Instruction * instr)9620 void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
9621 const Instruction* instr) {
9622 switch (
9623 instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
9624 // Ignore prefetch hint instructions.
9625 case PRFB_i_p_bz_s_x32_scaled:
9626 case PRFD_i_p_bz_s_x32_scaled:
9627 case PRFH_i_p_bz_s_x32_scaled:
9628 case PRFW_i_p_bz_s_x32_scaled:
9629 break;
9630 default:
9631 VIXL_UNIMPLEMENTED();
9632 break;
9633 }
9634 }
9635
VisitSVE32BitGatherPrefetch_VectorPlusImm(const Instruction * instr)9636 void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
9637 const Instruction* instr) {
9638 switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
9639 // Ignore prefetch hint instructions.
9640 case PRFB_i_p_ai_s:
9641 case PRFD_i_p_ai_s:
9642 case PRFH_i_p_ai_s:
9643 case PRFW_i_p_ai_s:
9644 break;
9645 default:
9646 VIXL_UNIMPLEMENTED();
9647 break;
9648 }
9649 }
9650
VisitSVEContiguousPrefetch_ScalarPlusImm(const Instruction * instr)9651 void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
9652 const Instruction* instr) {
9653 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
9654 // Ignore prefetch hint instructions.
9655 case PRFB_i_p_bi_s:
9656 case PRFD_i_p_bi_s:
9657 case PRFH_i_p_bi_s:
9658 case PRFW_i_p_bi_s:
9659 break;
9660 default:
9661 VIXL_UNIMPLEMENTED();
9662 break;
9663 }
9664 }
9665
VisitSVEContiguousPrefetch_ScalarPlusScalar(const Instruction * instr)9666 void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
9667 const Instruction* instr) {
9668 switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
9669 // Ignore prefetch hint instructions.
9670 case PRFB_i_p_br_s:
9671 case PRFD_i_p_br_s:
9672 case PRFH_i_p_br_s:
9673 case PRFW_i_p_br_s:
9674 if (instr->GetRm() == kZeroRegCode) {
9675 VIXL_UNIMPLEMENTED();
9676 }
9677 break;
9678 default:
9679 VIXL_UNIMPLEMENTED();
9680 break;
9681 }
9682 }
9683
VisitSVELoadAndBroadcastElement(const Instruction * instr)9684 void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
9685 bool is_signed;
9686 switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
9687 case LD1RB_z_p_bi_u8:
9688 case LD1RB_z_p_bi_u16:
9689 case LD1RB_z_p_bi_u32:
9690 case LD1RB_z_p_bi_u64:
9691 case LD1RH_z_p_bi_u16:
9692 case LD1RH_z_p_bi_u32:
9693 case LD1RH_z_p_bi_u64:
9694 case LD1RW_z_p_bi_u32:
9695 case LD1RW_z_p_bi_u64:
9696 case LD1RD_z_p_bi_u64:
9697 is_signed = false;
9698 break;
9699 case LD1RSB_z_p_bi_s16:
9700 case LD1RSB_z_p_bi_s32:
9701 case LD1RSB_z_p_bi_s64:
9702 case LD1RSH_z_p_bi_s32:
9703 case LD1RSH_z_p_bi_s64:
9704 case LD1RSW_z_p_bi_s64:
9705 is_signed = true;
9706 break;
9707 default:
9708 // This encoding group is complete, so no other values should be possible.
9709 VIXL_UNREACHABLE();
9710 is_signed = false;
9711 break;
9712 }
9713
9714 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
9715 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
9716 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
9717 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
9718 uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
9719 uint64_t base = ReadXRegister(instr->GetRn()) + offset;
9720 VectorFormat unpack_vform =
9721 SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
9722 SimVRegister temp;
9723 ld1r(vform, unpack_vform, temp, base, is_signed);
9724 mov_zeroing(vform,
9725 ReadVRegister(instr->GetRt()),
9726 ReadPRegister(instr->GetPgLow8()),
9727 temp);
9728 }
9729
VisitSVELoadPredicateRegister(const Instruction * instr)9730 void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
9731 switch (instr->Mask(SVELoadPredicateRegisterMask)) {
9732 case LDR_p_bi: {
9733 SimPRegister& pt = ReadPRegister(instr->GetPt());
9734 int pl = GetPredicateLengthInBytes();
9735 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9736 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9737 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
9738 for (int i = 0; i < pl; i++) {
9739 pt.Insert(i, MemRead<uint8_t>(address + i));
9740 }
9741 LogPRead(instr->GetPt(), address);
9742 break;
9743 }
9744 default:
9745 VIXL_UNIMPLEMENTED();
9746 break;
9747 }
9748 }
9749
VisitSVELoadVectorRegister(const Instruction * instr)9750 void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
9751 switch (instr->Mask(SVELoadVectorRegisterMask)) {
9752 case LDR_z_bi: {
9753 SimVRegister& zt = ReadVRegister(instr->GetRt());
9754 int vl = GetVectorLengthInBytes();
9755 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
9756 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
9757 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
9758 for (int i = 0; i < vl; i++) {
9759 zt.Insert(i, MemRead<uint8_t>(address + i));
9760 }
9761 LogZRead(instr->GetRt(), address);
9762 break;
9763 }
9764 default:
9765 VIXL_UNIMPLEMENTED();
9766 break;
9767 }
9768 }
9769
VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(const Instruction * instr)9770 void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
9771 const Instruction* instr) {
9772 switch (instr->Mask(
9773 SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
9774 case LD1D_z_p_bz_d_x32_scaled:
9775 case LD1H_z_p_bz_d_x32_scaled:
9776 case LD1SH_z_p_bz_d_x32_scaled:
9777 case LD1SW_z_p_bz_d_x32_scaled:
9778 case LD1W_z_p_bz_d_x32_scaled:
9779 case LDFF1H_z_p_bz_d_x32_scaled:
9780 case LDFF1W_z_p_bz_d_x32_scaled:
9781 case LDFF1D_z_p_bz_d_x32_scaled:
9782 case LDFF1SH_z_p_bz_d_x32_scaled:
9783 case LDFF1SW_z_p_bz_d_x32_scaled:
9784 break;
9785 default:
9786 VIXL_UNIMPLEMENTED();
9787 break;
9788 }
9789
9790 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9791 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
9792 }
9793
VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(const Instruction * instr)9794 void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
9795 const Instruction* instr) {
9796 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
9797 case LD1D_z_p_bz_d_64_scaled:
9798 case LD1H_z_p_bz_d_64_scaled:
9799 case LD1SH_z_p_bz_d_64_scaled:
9800 case LD1SW_z_p_bz_d_64_scaled:
9801 case LD1W_z_p_bz_d_64_scaled:
9802 case LDFF1H_z_p_bz_d_64_scaled:
9803 case LDFF1W_z_p_bz_d_64_scaled:
9804 case LDFF1D_z_p_bz_d_64_scaled:
9805 case LDFF1SH_z_p_bz_d_64_scaled:
9806 case LDFF1SW_z_p_bz_d_64_scaled:
9807 break;
9808 default:
9809 VIXL_UNIMPLEMENTED();
9810 break;
9811 }
9812
9813 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
9814 }
9815
VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)9816 void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
9817 const Instruction* instr) {
9818 switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
9819 case LD1B_z_p_bz_d_64_unscaled:
9820 case LD1D_z_p_bz_d_64_unscaled:
9821 case LD1H_z_p_bz_d_64_unscaled:
9822 case LD1SB_z_p_bz_d_64_unscaled:
9823 case LD1SH_z_p_bz_d_64_unscaled:
9824 case LD1SW_z_p_bz_d_64_unscaled:
9825 case LD1W_z_p_bz_d_64_unscaled:
9826 case LDFF1B_z_p_bz_d_64_unscaled:
9827 case LDFF1D_z_p_bz_d_64_unscaled:
9828 case LDFF1H_z_p_bz_d_64_unscaled:
9829 case LDFF1SB_z_p_bz_d_64_unscaled:
9830 case LDFF1SH_z_p_bz_d_64_unscaled:
9831 case LDFF1SW_z_p_bz_d_64_unscaled:
9832 case LDFF1W_z_p_bz_d_64_unscaled:
9833 break;
9834 default:
9835 VIXL_UNIMPLEMENTED();
9836 break;
9837 }
9838
9839 SVEGatherLoadScalarPlusVectorHelper(instr,
9840 kFormatVnD,
9841 NO_SVE_OFFSET_MODIFIER);
9842 }
9843
VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)9844 void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
9845 const Instruction* instr) {
9846 switch (instr->Mask(
9847 SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
9848 case LD1B_z_p_bz_d_x32_unscaled:
9849 case LD1D_z_p_bz_d_x32_unscaled:
9850 case LD1H_z_p_bz_d_x32_unscaled:
9851 case LD1SB_z_p_bz_d_x32_unscaled:
9852 case LD1SH_z_p_bz_d_x32_unscaled:
9853 case LD1SW_z_p_bz_d_x32_unscaled:
9854 case LD1W_z_p_bz_d_x32_unscaled:
9855 case LDFF1B_z_p_bz_d_x32_unscaled:
9856 case LDFF1H_z_p_bz_d_x32_unscaled:
9857 case LDFF1W_z_p_bz_d_x32_unscaled:
9858 case LDFF1D_z_p_bz_d_x32_unscaled:
9859 case LDFF1SB_z_p_bz_d_x32_unscaled:
9860 case LDFF1SH_z_p_bz_d_x32_unscaled:
9861 case LDFF1SW_z_p_bz_d_x32_unscaled:
9862 break;
9863 default:
9864 VIXL_UNIMPLEMENTED();
9865 break;
9866 }
9867
9868 SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
9869 SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
9870 }
9871
VisitSVE64BitGatherLoad_VectorPlusImm(const Instruction * instr)9872 void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
9873 const Instruction* instr) {
9874 switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
9875 case LD1B_z_p_ai_d:
9876 case LD1D_z_p_ai_d:
9877 case LD1H_z_p_ai_d:
9878 case LD1SB_z_p_ai_d:
9879 case LD1SH_z_p_ai_d:
9880 case LD1SW_z_p_ai_d:
9881 case LD1W_z_p_ai_d:
9882 case LDFF1B_z_p_ai_d:
9883 case LDFF1D_z_p_ai_d:
9884 case LDFF1H_z_p_ai_d:
9885 case LDFF1SB_z_p_ai_d:
9886 case LDFF1SH_z_p_ai_d:
9887 case LDFF1SW_z_p_ai_d:
9888 case LDFF1W_z_p_ai_d:
9889 break;
9890 default:
9891 VIXL_UNIMPLEMENTED();
9892 break;
9893 }
9894 bool is_signed = instr->ExtractBit(14) == 0;
9895 bool is_ff = instr->ExtractBit(13) == 1;
9896 // Note that these instructions don't use the Dtype encoding.
9897 int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
9898 uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
9899 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
9900 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9901 if (is_ff) {
9902 VIXL_UNIMPLEMENTED();
9903 } else {
9904 SVEStructuredLoadHelper(kFormatVnD,
9905 ReadPRegister(instr->GetPgLow8()),
9906 instr->GetRt(),
9907 addr,
9908 is_signed);
9909 }
9910 }
9911
VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(const Instruction * instr)9912 void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
9913 const Instruction* instr) {
9914 switch (
9915 instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
9916 // Ignore prefetch hint instructions.
9917 case PRFB_i_p_bz_d_64_scaled:
9918 case PRFD_i_p_bz_d_64_scaled:
9919 case PRFH_i_p_bz_d_64_scaled:
9920 case PRFW_i_p_bz_d_64_scaled:
9921 break;
9922 default:
9923 VIXL_UNIMPLEMENTED();
9924 break;
9925 }
9926 }
9927
9928 void Simulator::
VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)9929 VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
9930 const Instruction* instr) {
9931 switch (instr->Mask(
9932 SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
9933 // Ignore prefetch hint instructions.
9934 case PRFB_i_p_bz_d_x32_scaled:
9935 case PRFD_i_p_bz_d_x32_scaled:
9936 case PRFH_i_p_bz_d_x32_scaled:
9937 case PRFW_i_p_bz_d_x32_scaled:
9938 break;
9939 default:
9940 VIXL_UNIMPLEMENTED();
9941 break;
9942 }
9943 }
9944
VisitSVE64BitGatherPrefetch_VectorPlusImm(const Instruction * instr)9945 void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
9946 const Instruction* instr) {
9947 switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
9948 // Ignore prefetch hint instructions.
9949 case PRFB_i_p_ai_d:
9950 case PRFD_i_p_ai_d:
9951 case PRFH_i_p_ai_d:
9952 case PRFW_i_p_ai_d:
9953 break;
9954 default:
9955 VIXL_UNIMPLEMENTED();
9956 break;
9957 }
9958 }
9959
VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(const Instruction * instr)9960 void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
9961 const Instruction* instr) {
9962 bool is_signed;
9963 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
9964 case LDFF1B_z_p_br_u8:
9965 case LDFF1B_z_p_br_u16:
9966 case LDFF1B_z_p_br_u32:
9967 case LDFF1B_z_p_br_u64:
9968 case LDFF1H_z_p_br_u16:
9969 case LDFF1H_z_p_br_u32:
9970 case LDFF1H_z_p_br_u64:
9971 case LDFF1W_z_p_br_u32:
9972 case LDFF1W_z_p_br_u64:
9973 case LDFF1D_z_p_br_u64:
9974 is_signed = false;
9975 break;
9976 case LDFF1SB_z_p_br_s16:
9977 case LDFF1SB_z_p_br_s32:
9978 case LDFF1SB_z_p_br_s64:
9979 case LDFF1SH_z_p_br_s32:
9980 case LDFF1SH_z_p_br_s64:
9981 case LDFF1SW_z_p_br_s64:
9982 is_signed = true;
9983 break;
9984 default:
9985 // This encoding group is complete, so no other values should be possible.
9986 VIXL_UNREACHABLE();
9987 is_signed = false;
9988 break;
9989 }
9990
9991 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
9992 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
9993 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
9994 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
9995 uint64_t offset = ReadXRegister(instr->GetRm());
9996 offset <<= msize_in_bytes_log2;
9997 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
9998 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
9999 SVEFaultTolerantLoadHelper(vform,
10000 ReadPRegister(instr->GetPgLow8()),
10001 instr->GetRt(),
10002 addr,
10003 kSVEFirstFaultLoad,
10004 is_signed);
10005 }
10006
VisitSVEContiguousNonFaultLoad_ScalarPlusImm(const Instruction * instr)10007 void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
10008 const Instruction* instr) {
10009 bool is_signed = false;
10010 switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
10011 case LDNF1B_z_p_bi_u16:
10012 case LDNF1B_z_p_bi_u32:
10013 case LDNF1B_z_p_bi_u64:
10014 case LDNF1B_z_p_bi_u8:
10015 case LDNF1D_z_p_bi_u64:
10016 case LDNF1H_z_p_bi_u16:
10017 case LDNF1H_z_p_bi_u32:
10018 case LDNF1H_z_p_bi_u64:
10019 case LDNF1W_z_p_bi_u32:
10020 case LDNF1W_z_p_bi_u64:
10021 break;
10022 case LDNF1SB_z_p_bi_s16:
10023 case LDNF1SB_z_p_bi_s32:
10024 case LDNF1SB_z_p_bi_s64:
10025 case LDNF1SH_z_p_bi_s32:
10026 case LDNF1SH_z_p_bi_s64:
10027 case LDNF1SW_z_p_bi_s64:
10028 is_signed = true;
10029 break;
10030 default:
10031 VIXL_UNIMPLEMENTED();
10032 break;
10033 }
10034 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
10035 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
10036 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
10037 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
10038 int vl = GetVectorLengthInBytes();
10039 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10040 uint64_t offset =
10041 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
10042 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10043 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10044 SVEFaultTolerantLoadHelper(vform,
10045 ReadPRegister(instr->GetPgLow8()),
10046 instr->GetRt(),
10047 addr,
10048 kSVENonFaultLoad,
10049 is_signed);
10050 }
10051
VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(const Instruction * instr)10052 void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
10053 const Instruction* instr) {
10054 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10055 VectorFormat vform = kFormatUndefined;
10056
10057 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
10058 case LDNT1B_z_p_bi_contiguous:
10059 vform = kFormatVnB;
10060 break;
10061 case LDNT1D_z_p_bi_contiguous:
10062 vform = kFormatVnD;
10063 break;
10064 case LDNT1H_z_p_bi_contiguous:
10065 vform = kFormatVnH;
10066 break;
10067 case LDNT1W_z_p_bi_contiguous:
10068 vform = kFormatVnS;
10069 break;
10070 default:
10071 VIXL_UNIMPLEMENTED();
10072 break;
10073 }
10074 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10075 int vl = GetVectorLengthInBytes();
10076 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
10077 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10078 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10079 SVEStructuredLoadHelper(vform,
10080 pg,
10081 instr->GetRt(),
10082 addr,
10083 /* is_signed = */ false);
10084 }
10085
VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(const Instruction * instr)10086 void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
10087 const Instruction* instr) {
10088 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10089 VectorFormat vform = kFormatUndefined;
10090
10091 switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
10092 case LDNT1B_z_p_br_contiguous:
10093 vform = kFormatVnB;
10094 break;
10095 case LDNT1D_z_p_br_contiguous:
10096 vform = kFormatVnD;
10097 break;
10098 case LDNT1H_z_p_br_contiguous:
10099 vform = kFormatVnH;
10100 break;
10101 case LDNT1W_z_p_br_contiguous:
10102 vform = kFormatVnS;
10103 break;
10104 default:
10105 VIXL_UNIMPLEMENTED();
10106 break;
10107 }
10108 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10109 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
10110 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10111 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10112 SVEStructuredLoadHelper(vform,
10113 pg,
10114 instr->GetRt(),
10115 addr,
10116 /* is_signed = */ false);
10117 }
10118
VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(const Instruction * instr)10119 void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusImm(
10120 const Instruction* instr) {
10121 SimVRegister& zt = ReadVRegister(instr->GetRt());
10122 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10123
10124 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
10125 uint64_t offset = instr->ExtractSignedBits(19, 16) * 16;
10126
10127 VectorFormat vform = kFormatUndefined;
10128 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusImmMask)) {
10129 case LD1RQB_z_p_bi_u8:
10130 vform = kFormatVnB;
10131 break;
10132 case LD1RQD_z_p_bi_u64:
10133 vform = kFormatVnD;
10134 break;
10135 case LD1RQH_z_p_bi_u16:
10136 vform = kFormatVnH;
10137 break;
10138 case LD1RQW_z_p_bi_u32:
10139 vform = kFormatVnS;
10140 break;
10141 default:
10142 addr = offset = 0;
10143 break;
10144 }
10145 ld1(kFormat16B, zt, addr + offset);
10146 mov_zeroing(vform, zt, pg, zt);
10147 dup_element(kFormatVnQ, zt, zt, 0);
10148 }
10149
VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(const Instruction * instr)10150 void Simulator::VisitSVELoadAndBroadcastQuadword_ScalarPlusScalar(
10151 const Instruction* instr) {
10152 SimVRegister& zt = ReadVRegister(instr->GetRt());
10153 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10154
10155 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
10156 uint64_t offset = ReadXRegister(instr->GetRm());
10157
10158 VectorFormat vform = kFormatUndefined;
10159 switch (instr->Mask(SVELoadAndBroadcastQuadword_ScalarPlusScalarMask)) {
10160 case LD1RQB_z_p_br_contiguous:
10161 vform = kFormatVnB;
10162 break;
10163 case LD1RQD_z_p_br_contiguous:
10164 vform = kFormatVnD;
10165 offset <<= 3;
10166 break;
10167 case LD1RQH_z_p_br_contiguous:
10168 vform = kFormatVnH;
10169 offset <<= 1;
10170 break;
10171 case LD1RQW_z_p_br_contiguous:
10172 vform = kFormatVnS;
10173 offset <<= 2;
10174 break;
10175 default:
10176 addr = offset = 0;
10177 break;
10178 }
10179 ld1(kFormat16B, zt, addr + offset);
10180 mov_zeroing(vform, zt, pg, zt);
10181 dup_element(kFormatVnQ, zt, zt, 0);
10182 }
10183
VisitSVELoadMultipleStructures_ScalarPlusImm(const Instruction * instr)10184 void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
10185 const Instruction* instr) {
10186 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
10187 case LD2B_z_p_bi_contiguous:
10188 case LD2D_z_p_bi_contiguous:
10189 case LD2H_z_p_bi_contiguous:
10190 case LD2W_z_p_bi_contiguous:
10191 case LD3B_z_p_bi_contiguous:
10192 case LD3D_z_p_bi_contiguous:
10193 case LD3H_z_p_bi_contiguous:
10194 case LD3W_z_p_bi_contiguous:
10195 case LD4B_z_p_bi_contiguous:
10196 case LD4D_z_p_bi_contiguous:
10197 case LD4H_z_p_bi_contiguous:
10198 case LD4W_z_p_bi_contiguous: {
10199 int vl = GetVectorLengthInBytes();
10200 int msz = instr->ExtractBits(24, 23);
10201 int reg_count = instr->ExtractBits(22, 21) + 1;
10202 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10203 LogicSVEAddressVector addr(
10204 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10205 addr.SetMsizeInBytesLog2(msz);
10206 addr.SetRegCount(reg_count);
10207 SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10208 ReadPRegister(instr->GetPgLow8()),
10209 instr->GetRt(),
10210 addr);
10211 break;
10212 }
10213 default:
10214 VIXL_UNIMPLEMENTED();
10215 break;
10216 }
10217 }
10218
VisitSVELoadMultipleStructures_ScalarPlusScalar(const Instruction * instr)10219 void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
10220 const Instruction* instr) {
10221 switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
10222 case LD2B_z_p_br_contiguous:
10223 case LD2D_z_p_br_contiguous:
10224 case LD2H_z_p_br_contiguous:
10225 case LD2W_z_p_br_contiguous:
10226 case LD3B_z_p_br_contiguous:
10227 case LD3D_z_p_br_contiguous:
10228 case LD3H_z_p_br_contiguous:
10229 case LD3W_z_p_br_contiguous:
10230 case LD4B_z_p_br_contiguous:
10231 case LD4D_z_p_br_contiguous:
10232 case LD4H_z_p_br_contiguous:
10233 case LD4W_z_p_br_contiguous: {
10234 int msz = instr->ExtractBits(24, 23);
10235 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10236 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10237 LogicSVEAddressVector addr(
10238 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10239 addr.SetMsizeInBytesLog2(msz);
10240 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10241 SVEStructuredLoadHelper(vform,
10242 ReadPRegister(instr->GetPgLow8()),
10243 instr->GetRt(),
10244 addr,
10245 false);
10246 break;
10247 }
10248 default:
10249 VIXL_UNIMPLEMENTED();
10250 break;
10251 }
10252 }
10253
VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(const Instruction * instr)10254 void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
10255 const Instruction* instr) {
10256 switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
10257 case ST1H_z_p_bz_s_x32_scaled:
10258 case ST1W_z_p_bz_s_x32_scaled: {
10259 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10260 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10261 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
10262 uint64_t base = ReadXRegister(instr->GetRn());
10263 SVEOffsetModifier mod =
10264 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10265 LogicSVEAddressVector addr(base,
10266 &ReadVRegister(instr->GetRm()),
10267 kFormatVnS,
10268 mod,
10269 scale);
10270 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10271 SVEStructuredStoreHelper(kFormatVnS,
10272 ReadPRegister(instr->GetPgLow8()),
10273 instr->GetRt(),
10274 addr);
10275 break;
10276 }
10277 default:
10278 VIXL_UNIMPLEMENTED();
10279 break;
10280 }
10281 }
10282
VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)10283 void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
10284 const Instruction* instr) {
10285 switch (
10286 instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
10287 case ST1B_z_p_bz_s_x32_unscaled:
10288 case ST1H_z_p_bz_s_x32_unscaled:
10289 case ST1W_z_p_bz_s_x32_unscaled: {
10290 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10291 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10292 uint64_t base = ReadXRegister(instr->GetRn());
10293 SVEOffsetModifier mod =
10294 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10295 LogicSVEAddressVector addr(base,
10296 &ReadVRegister(instr->GetRm()),
10297 kFormatVnS,
10298 mod);
10299 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10300 SVEStructuredStoreHelper(kFormatVnS,
10301 ReadPRegister(instr->GetPgLow8()),
10302 instr->GetRt(),
10303 addr);
10304 break;
10305 }
10306 default:
10307 VIXL_UNIMPLEMENTED();
10308 break;
10309 }
10310 }
10311
VisitSVE32BitScatterStore_VectorPlusImm(const Instruction * instr)10312 void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
10313 const Instruction* instr) {
10314 int msz = 0;
10315 switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
10316 case ST1B_z_p_ai_s:
10317 msz = 0;
10318 break;
10319 case ST1H_z_p_ai_s:
10320 msz = 1;
10321 break;
10322 case ST1W_z_p_ai_s:
10323 msz = 2;
10324 break;
10325 default:
10326 VIXL_UNIMPLEMENTED();
10327 break;
10328 }
10329 uint64_t imm = instr->ExtractBits(20, 16) << msz;
10330 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
10331 addr.SetMsizeInBytesLog2(msz);
10332 SVEStructuredStoreHelper(kFormatVnS,
10333 ReadPRegister(instr->GetPgLow8()),
10334 instr->GetRt(),
10335 addr);
10336 }
10337
VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(const Instruction * instr)10338 void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
10339 const Instruction* instr) {
10340 switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
10341 case ST1D_z_p_bz_d_64_scaled:
10342 case ST1H_z_p_bz_d_64_scaled:
10343 case ST1W_z_p_bz_d_64_scaled: {
10344 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10345 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10346 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
10347 uint64_t base = ReadXRegister(instr->GetRn());
10348 LogicSVEAddressVector addr(base,
10349 &ReadVRegister(instr->GetRm()),
10350 kFormatVnD,
10351 SVE_LSL,
10352 scale);
10353 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10354 SVEStructuredStoreHelper(kFormatVnD,
10355 ReadPRegister(instr->GetPgLow8()),
10356 instr->GetRt(),
10357 addr);
10358 break;
10359 }
10360 default:
10361 VIXL_UNIMPLEMENTED();
10362 break;
10363 }
10364 }
10365
VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)10366 void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
10367 const Instruction* instr) {
10368 switch (
10369 instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
10370 case ST1B_z_p_bz_d_64_unscaled:
10371 case ST1D_z_p_bz_d_64_unscaled:
10372 case ST1H_z_p_bz_d_64_unscaled:
10373 case ST1W_z_p_bz_d_64_unscaled: {
10374 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10375 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10376 uint64_t base = ReadXRegister(instr->GetRn());
10377 LogicSVEAddressVector addr(base,
10378 &ReadVRegister(instr->GetRm()),
10379 kFormatVnD,
10380 NO_SVE_OFFSET_MODIFIER);
10381 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10382 SVEStructuredStoreHelper(kFormatVnD,
10383 ReadPRegister(instr->GetPgLow8()),
10384 instr->GetRt(),
10385 addr);
10386 break;
10387 }
10388 default:
10389 VIXL_UNIMPLEMENTED();
10390 break;
10391 }
10392 }
10393
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)10394 void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
10395 const Instruction* instr) {
10396 switch (instr->Mask(
10397 SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
10398 case ST1D_z_p_bz_d_x32_scaled:
10399 case ST1H_z_p_bz_d_x32_scaled:
10400 case ST1W_z_p_bz_d_x32_scaled: {
10401 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10402 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10403 int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
10404 uint64_t base = ReadXRegister(instr->GetRn());
10405 SVEOffsetModifier mod =
10406 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10407 LogicSVEAddressVector addr(base,
10408 &ReadVRegister(instr->GetRm()),
10409 kFormatVnD,
10410 mod,
10411 scale);
10412 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10413 SVEStructuredStoreHelper(kFormatVnD,
10414 ReadPRegister(instr->GetPgLow8()),
10415 instr->GetRt(),
10416 addr);
10417 break;
10418 }
10419 default:
10420 VIXL_UNIMPLEMENTED();
10421 break;
10422 }
10423 }
10424
10425 void Simulator::
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)10426 VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
10427 const Instruction* instr) {
10428 switch (instr->Mask(
10429 SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
10430 case ST1B_z_p_bz_d_x32_unscaled:
10431 case ST1D_z_p_bz_d_x32_unscaled:
10432 case ST1H_z_p_bz_d_x32_unscaled:
10433 case ST1W_z_p_bz_d_x32_unscaled: {
10434 unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10435 VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
10436 uint64_t base = ReadXRegister(instr->GetRn());
10437 SVEOffsetModifier mod =
10438 (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
10439 LogicSVEAddressVector addr(base,
10440 &ReadVRegister(instr->GetRm()),
10441 kFormatVnD,
10442 mod);
10443 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10444 SVEStructuredStoreHelper(kFormatVnD,
10445 ReadPRegister(instr->GetPgLow8()),
10446 instr->GetRt(),
10447 addr);
10448 break;
10449 }
10450 default:
10451 VIXL_UNIMPLEMENTED();
10452 break;
10453 }
10454 }
10455
VisitSVE64BitScatterStore_VectorPlusImm(const Instruction * instr)10456 void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
10457 const Instruction* instr) {
10458 int msz = 0;
10459 switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
10460 case ST1B_z_p_ai_d:
10461 msz = 0;
10462 break;
10463 case ST1D_z_p_ai_d:
10464 msz = 3;
10465 break;
10466 case ST1H_z_p_ai_d:
10467 msz = 1;
10468 break;
10469 case ST1W_z_p_ai_d:
10470 msz = 2;
10471 break;
10472 default:
10473 VIXL_UNIMPLEMENTED();
10474 break;
10475 }
10476 uint64_t imm = instr->ExtractBits(20, 16) << msz;
10477 LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
10478 addr.SetMsizeInBytesLog2(msz);
10479 SVEStructuredStoreHelper(kFormatVnD,
10480 ReadPRegister(instr->GetPgLow8()),
10481 instr->GetRt(),
10482 addr);
10483 }
10484
VisitSVEContiguousNonTemporalStore_ScalarPlusImm(const Instruction * instr)10485 void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
10486 const Instruction* instr) {
10487 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10488 VectorFormat vform = kFormatUndefined;
10489
10490 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
10491 case STNT1B_z_p_bi_contiguous:
10492 vform = kFormatVnB;
10493 break;
10494 case STNT1D_z_p_bi_contiguous:
10495 vform = kFormatVnD;
10496 break;
10497 case STNT1H_z_p_bi_contiguous:
10498 vform = kFormatVnH;
10499 break;
10500 case STNT1W_z_p_bi_contiguous:
10501 vform = kFormatVnS;
10502 break;
10503 default:
10504 VIXL_UNIMPLEMENTED();
10505 break;
10506 }
10507 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10508 int vl = GetVectorLengthInBytes();
10509 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
10510 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10511 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10512 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
10513 }
10514
VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(const Instruction * instr)10515 void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
10516 const Instruction* instr) {
10517 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10518 VectorFormat vform = kFormatUndefined;
10519
10520 switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
10521 case STNT1B_z_p_br_contiguous:
10522 vform = kFormatVnB;
10523 break;
10524 case STNT1D_z_p_br_contiguous:
10525 vform = kFormatVnD;
10526 break;
10527 case STNT1H_z_p_br_contiguous:
10528 vform = kFormatVnH;
10529 break;
10530 case STNT1W_z_p_br_contiguous:
10531 vform = kFormatVnS;
10532 break;
10533 default:
10534 VIXL_UNIMPLEMENTED();
10535 break;
10536 }
10537 int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
10538 uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
10539 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10540 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10541 SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
10542 }
10543
VisitSVEContiguousStore_ScalarPlusImm(const Instruction * instr)10544 void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
10545 const Instruction* instr) {
10546 switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
10547 case ST1B_z_p_bi:
10548 case ST1D_z_p_bi:
10549 case ST1H_z_p_bi:
10550 case ST1W_z_p_bi: {
10551 int vl = GetVectorLengthInBytes();
10552 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
10553 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
10554 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
10555 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
10556 uint64_t offset =
10557 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
10558 VectorFormat vform =
10559 SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
10560 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10561 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
10562 SVEStructuredStoreHelper(vform,
10563 ReadPRegister(instr->GetPgLow8()),
10564 instr->GetRt(),
10565 addr);
10566 break;
10567 }
10568 default:
10569 VIXL_UNIMPLEMENTED();
10570 break;
10571 }
10572 }
10573
VisitSVEContiguousStore_ScalarPlusScalar(const Instruction * instr)10574 void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
10575 const Instruction* instr) {
10576 switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
10577 case ST1B_z_p_br:
10578 case ST1D_z_p_br:
10579 case ST1H_z_p_br:
10580 case ST1W_z_p_br: {
10581 uint64_t offset = ReadXRegister(instr->GetRm());
10582 offset <<= instr->ExtractBits(24, 23);
10583 VectorFormat vform =
10584 SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
10585 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
10586 addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
10587 SVEStructuredStoreHelper(vform,
10588 ReadPRegister(instr->GetPgLow8()),
10589 instr->GetRt(),
10590 addr);
10591 break;
10592 }
10593 default:
10594 VIXL_UNIMPLEMENTED();
10595 break;
10596 }
10597 }
10598
VisitSVECopySIMDFPScalarRegisterToVector_Predicated(const Instruction * instr)10599 void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
10600 const Instruction* instr) {
10601 VectorFormat vform = instr->GetSVEVectorFormat();
10602 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10603 SimVRegister z_result;
10604
10605 switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
10606 case CPY_z_p_v:
10607 dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
10608 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
10609 break;
10610 default:
10611 VIXL_UNIMPLEMENTED();
10612 break;
10613 }
10614 }
10615
VisitSVEStoreMultipleStructures_ScalarPlusImm(const Instruction * instr)10616 void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
10617 const Instruction* instr) {
10618 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
10619 case ST2B_z_p_bi_contiguous:
10620 case ST2D_z_p_bi_contiguous:
10621 case ST2H_z_p_bi_contiguous:
10622 case ST2W_z_p_bi_contiguous:
10623 case ST3B_z_p_bi_contiguous:
10624 case ST3D_z_p_bi_contiguous:
10625 case ST3H_z_p_bi_contiguous:
10626 case ST3W_z_p_bi_contiguous:
10627 case ST4B_z_p_bi_contiguous:
10628 case ST4D_z_p_bi_contiguous:
10629 case ST4H_z_p_bi_contiguous:
10630 case ST4W_z_p_bi_contiguous: {
10631 int vl = GetVectorLengthInBytes();
10632 int msz = instr->ExtractBits(24, 23);
10633 int reg_count = instr->ExtractBits(22, 21) + 1;
10634 uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
10635 LogicSVEAddressVector addr(
10636 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10637 addr.SetMsizeInBytesLog2(msz);
10638 addr.SetRegCount(reg_count);
10639 SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
10640 ReadPRegister(instr->GetPgLow8()),
10641 instr->GetRt(),
10642 addr);
10643 break;
10644 }
10645 default:
10646 VIXL_UNIMPLEMENTED();
10647 break;
10648 }
10649 }
10650
VisitSVEStoreMultipleStructures_ScalarPlusScalar(const Instruction * instr)10651 void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
10652 const Instruction* instr) {
10653 switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
10654 case ST2B_z_p_br_contiguous:
10655 case ST2D_z_p_br_contiguous:
10656 case ST2H_z_p_br_contiguous:
10657 case ST2W_z_p_br_contiguous:
10658 case ST3B_z_p_br_contiguous:
10659 case ST3D_z_p_br_contiguous:
10660 case ST3H_z_p_br_contiguous:
10661 case ST3W_z_p_br_contiguous:
10662 case ST4B_z_p_br_contiguous:
10663 case ST4D_z_p_br_contiguous:
10664 case ST4H_z_p_br_contiguous:
10665 case ST4W_z_p_br_contiguous: {
10666 int msz = instr->ExtractBits(24, 23);
10667 uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
10668 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
10669 LogicSVEAddressVector addr(
10670 ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
10671 addr.SetMsizeInBytesLog2(msz);
10672 addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
10673 SVEStructuredStoreHelper(vform,
10674 ReadPRegister(instr->GetPgLow8()),
10675 instr->GetRt(),
10676 addr);
10677 break;
10678 }
10679 default:
10680 VIXL_UNIMPLEMENTED();
10681 break;
10682 }
10683 }
10684
VisitSVEStorePredicateRegister(const Instruction * instr)10685 void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
10686 switch (instr->Mask(SVEStorePredicateRegisterMask)) {
10687 case STR_p_bi: {
10688 SimPRegister& pt = ReadPRegister(instr->GetPt());
10689 int pl = GetPredicateLengthInBytes();
10690 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10691 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10692 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
10693 for (int i = 0; i < pl; i++) {
10694 MemWrite(address + i, pt.GetLane<uint8_t>(i));
10695 }
10696 LogPWrite(instr->GetPt(), address);
10697 break;
10698 }
10699 default:
10700 VIXL_UNIMPLEMENTED();
10701 break;
10702 }
10703 }
10704
VisitSVEStoreVectorRegister(const Instruction * instr)10705 void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
10706 switch (instr->Mask(SVEStoreVectorRegisterMask)) {
10707 case STR_z_bi: {
10708 SimVRegister& zt = ReadVRegister(instr->GetRt());
10709 int vl = GetVectorLengthInBytes();
10710 int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
10711 uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
10712 uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
10713 for (int i = 0; i < vl; i++) {
10714 MemWrite(address + i, zt.GetLane<uint8_t>(i));
10715 }
10716 LogZWrite(instr->GetRt(), address);
10717 break;
10718 }
10719 default:
10720 VIXL_UNIMPLEMENTED();
10721 break;
10722 }
10723 }
10724
VisitSVEMulIndex(const Instruction * instr)10725 void Simulator::VisitSVEMulIndex(const Instruction* instr) {
10726 VectorFormat vform = instr->GetSVEVectorFormat();
10727 SimVRegister& zda = ReadVRegister(instr->GetRd());
10728 SimVRegister& zn = ReadVRegister(instr->GetRn());
10729
10730 switch (instr->Mask(SVEMulIndexMask)) {
10731 case SDOT_z_zzzi_d:
10732 sdot(vform,
10733 zda,
10734 zn,
10735 ReadVRegister(instr->ExtractBits(19, 16)),
10736 instr->ExtractBit(20));
10737 break;
10738 case SDOT_z_zzzi_s:
10739 sdot(vform,
10740 zda,
10741 zn,
10742 ReadVRegister(instr->ExtractBits(18, 16)),
10743 instr->ExtractBits(20, 19));
10744 break;
10745 case UDOT_z_zzzi_d:
10746 udot(vform,
10747 zda,
10748 zn,
10749 ReadVRegister(instr->ExtractBits(19, 16)),
10750 instr->ExtractBit(20));
10751 break;
10752 case UDOT_z_zzzi_s:
10753 udot(vform,
10754 zda,
10755 zn,
10756 ReadVRegister(instr->ExtractBits(18, 16)),
10757 instr->ExtractBits(20, 19));
10758 break;
10759 default:
10760 VIXL_UNIMPLEMENTED();
10761 break;
10762 }
10763 }
10764
VisitSVEPartitionBreakCondition(const Instruction * instr)10765 void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
10766 SimPRegister& pd = ReadPRegister(instr->GetPd());
10767 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10768 SimPRegister& pn = ReadPRegister(instr->GetPn());
10769 SimPRegister result;
10770
10771 switch (instr->Mask(SVEPartitionBreakConditionMask)) {
10772 case BRKAS_p_p_p_z:
10773 case BRKA_p_p_p:
10774 brka(result, pg, pn);
10775 break;
10776 case BRKBS_p_p_p_z:
10777 case BRKB_p_p_p:
10778 brkb(result, pg, pn);
10779 break;
10780 default:
10781 VIXL_UNIMPLEMENTED();
10782 break;
10783 }
10784
10785 if (instr->ExtractBit(4) == 1) {
10786 mov_merging(pd, pg, result);
10787 } else {
10788 mov_zeroing(pd, pg, result);
10789 }
10790
10791 // Set flag if needed.
10792 if (instr->ExtractBit(22) == 1) {
10793 PredTest(kFormatVnB, pg, pd);
10794 }
10795 }
10796
VisitSVEPropagateBreakToNextPartition(const Instruction * instr)10797 void Simulator::VisitSVEPropagateBreakToNextPartition(
10798 const Instruction* instr) {
10799 SimPRegister& pdm = ReadPRegister(instr->GetPd());
10800 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
10801 SimPRegister& pn = ReadPRegister(instr->GetPn());
10802
10803 switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
10804 case BRKNS_p_p_pp:
10805 case BRKN_p_p_pp:
10806 brkn(pdm, pg, pn);
10807 break;
10808 default:
10809 VIXL_UNIMPLEMENTED();
10810 break;
10811 }
10812
10813 // Set flag if needed.
10814 if (instr->ExtractBit(22) == 1) {
10815 // Note that this ignores `pg`.
10816 PredTest(kFormatVnB, GetPTrue(), pdm);
10817 }
10818 }
10819
VisitSVEUnpackPredicateElements(const Instruction * instr)10820 void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
10821 SimPRegister& pd = ReadPRegister(instr->GetPd());
10822 SimPRegister& pn = ReadPRegister(instr->GetPn());
10823
10824 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10825 SimVRegister zero;
10826 dup_immediate(kFormatVnB, zero, 0);
10827
10828 switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
10829 case PUNPKHI_p_p:
10830 zip2(kFormatVnB, temp, temp, zero);
10831 break;
10832 case PUNPKLO_p_p:
10833 zip1(kFormatVnB, temp, temp, zero);
10834 break;
10835 default:
10836 VIXL_UNIMPLEMENTED();
10837 break;
10838 }
10839 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
10840 }
10841
VisitSVEPermutePredicateElements(const Instruction * instr)10842 void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
10843 VectorFormat vform = instr->GetSVEVectorFormat();
10844 SimPRegister& pd = ReadPRegister(instr->GetPd());
10845 SimPRegister& pn = ReadPRegister(instr->GetPn());
10846 SimPRegister& pm = ReadPRegister(instr->GetPm());
10847
10848 SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
10849 SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
10850
10851 switch (instr->Mask(SVEPermutePredicateElementsMask)) {
10852 case TRN1_p_pp:
10853 trn1(vform, temp0, temp0, temp1);
10854 break;
10855 case TRN2_p_pp:
10856 trn2(vform, temp0, temp0, temp1);
10857 break;
10858 case UZP1_p_pp:
10859 uzp1(vform, temp0, temp0, temp1);
10860 break;
10861 case UZP2_p_pp:
10862 uzp2(vform, temp0, temp0, temp1);
10863 break;
10864 case ZIP1_p_pp:
10865 zip1(vform, temp0, temp0, temp1);
10866 break;
10867 case ZIP2_p_pp:
10868 zip2(vform, temp0, temp0, temp1);
10869 break;
10870 default:
10871 VIXL_UNIMPLEMENTED();
10872 break;
10873 }
10874 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
10875 }
10876
VisitSVEReversePredicateElements(const Instruction * instr)10877 void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
10878 switch (instr->Mask(SVEReversePredicateElementsMask)) {
10879 case REV_p_p: {
10880 VectorFormat vform = instr->GetSVEVectorFormat();
10881 SimPRegister& pn = ReadPRegister(instr->GetPn());
10882 SimPRegister& pd = ReadPRegister(instr->GetPd());
10883 SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
10884 rev(vform, temp, temp);
10885 Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
10886 break;
10887 }
10888 default:
10889 VIXL_UNIMPLEMENTED();
10890 break;
10891 }
10892 }
10893
VisitSVEPermuteVectorExtract(const Instruction * instr)10894 void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
10895 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10896 // Second source register "Zm" is encoded where "Zn" would usually be.
10897 SimVRegister& zm = ReadVRegister(instr->GetRn());
10898
10899 const int imm8h_mask = 0x001F0000;
10900 const int imm8l_mask = 0x00001C00;
10901 int index = instr->ExtractBits<imm8h_mask | imm8l_mask>();
10902 int vl = GetVectorLengthInBytes();
10903 index = (index >= vl) ? 0 : index;
10904
10905 switch (instr->Mask(SVEPermuteVectorExtractMask)) {
10906 case EXT_z_zi_des:
10907 ext(kFormatVnB, zdn, zdn, zm, index);
10908 break;
10909 default:
10910 VIXL_UNIMPLEMENTED();
10911 break;
10912 }
10913 }
10914
VisitSVEPermuteVectorInterleaving(const Instruction * instr)10915 void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
10916 VectorFormat vform = instr->GetSVEVectorFormat();
10917 SimVRegister& zd = ReadVRegister(instr->GetRd());
10918 SimVRegister& zn = ReadVRegister(instr->GetRn());
10919 SimVRegister& zm = ReadVRegister(instr->GetRm());
10920
10921 switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
10922 case TRN1_z_zz:
10923 trn1(vform, zd, zn, zm);
10924 break;
10925 case TRN2_z_zz:
10926 trn2(vform, zd, zn, zm);
10927 break;
10928 case UZP1_z_zz:
10929 uzp1(vform, zd, zn, zm);
10930 break;
10931 case UZP2_z_zz:
10932 uzp2(vform, zd, zn, zm);
10933 break;
10934 case ZIP1_z_zz:
10935 zip1(vform, zd, zn, zm);
10936 break;
10937 case ZIP2_z_zz:
10938 zip2(vform, zd, zn, zm);
10939 break;
10940 default:
10941 VIXL_UNIMPLEMENTED();
10942 break;
10943 }
10944 }
10945
VisitSVEConditionallyBroadcastElementToVector(const Instruction * instr)10946 void Simulator::VisitSVEConditionallyBroadcastElementToVector(
10947 const Instruction* instr) {
10948 VectorFormat vform = instr->GetSVEVectorFormat();
10949 SimVRegister& zdn = ReadVRegister(instr->GetRd());
10950 SimVRegister& zm = ReadVRegister(instr->GetRn());
10951 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10952
10953 int active_offset = -1;
10954 switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
10955 case CLASTA_z_p_zz:
10956 active_offset = 1;
10957 break;
10958 case CLASTB_z_p_zz:
10959 active_offset = 0;
10960 break;
10961 default:
10962 VIXL_UNIMPLEMENTED();
10963 break;
10964 }
10965
10966 if (active_offset >= 0) {
10967 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
10968 if (value.first) {
10969 dup_immediate(vform, zdn, value.second);
10970 } else {
10971 // Trigger a line of trace for the operation, even though it doesn't
10972 // change the register value.
10973 mov(vform, zdn, zdn);
10974 }
10975 }
10976 }
10977
VisitSVEConditionallyExtractElementToSIMDFPScalar(const Instruction * instr)10978 void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
10979 const Instruction* instr) {
10980 VectorFormat vform = instr->GetSVEVectorFormat();
10981 SimVRegister& vdn = ReadVRegister(instr->GetRd());
10982 SimVRegister& zm = ReadVRegister(instr->GetRn());
10983 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10984
10985 int active_offset = -1;
10986 switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
10987 case CLASTA_v_p_z:
10988 active_offset = 1;
10989 break;
10990 case CLASTB_v_p_z:
10991 active_offset = 0;
10992 break;
10993 default:
10994 VIXL_UNIMPLEMENTED();
10995 break;
10996 }
10997
10998 if (active_offset >= 0) {
10999 LogicVRegister dst(vdn);
11000 uint64_t src1_value = dst.Uint(vform, 0);
11001 std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
11002 dup_immediate(vform, vdn, 0);
11003 dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
11004 }
11005 }
11006
VisitSVEConditionallyExtractElementToGeneralRegister(const Instruction * instr)11007 void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
11008 const Instruction* instr) {
11009 VectorFormat vform = instr->GetSVEVectorFormat();
11010 SimVRegister& zm = ReadVRegister(instr->GetRn());
11011 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11012
11013 int active_offset = -1;
11014 switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
11015 case CLASTA_r_p_z:
11016 active_offset = 1;
11017 break;
11018 case CLASTB_r_p_z:
11019 active_offset = 0;
11020 break;
11021 default:
11022 VIXL_UNIMPLEMENTED();
11023 break;
11024 }
11025
11026 if (active_offset >= 0) {
11027 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
11028 uint64_t masked_src = ReadXRegister(instr->GetRd()) &
11029 GetUintMask(LaneSizeInBitsFromFormat(vform));
11030 WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
11031 }
11032 }
11033
VisitSVEExtractElementToSIMDFPScalarRegister(const Instruction * instr)11034 void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
11035 const Instruction* instr) {
11036 VectorFormat vform = instr->GetSVEVectorFormat();
11037 SimVRegister& vdn = ReadVRegister(instr->GetRd());
11038 SimVRegister& zm = ReadVRegister(instr->GetRn());
11039 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11040
11041 int active_offset = -1;
11042 switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
11043 case LASTA_v_p_z:
11044 active_offset = 1;
11045 break;
11046 case LASTB_v_p_z:
11047 active_offset = 0;
11048 break;
11049 default:
11050 VIXL_UNIMPLEMENTED();
11051 break;
11052 }
11053
11054 if (active_offset >= 0) {
11055 LogicVRegister dst(vdn);
11056 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
11057 dup_immediate(vform, vdn, 0);
11058 dst.SetUint(vform, 0, value.second);
11059 }
11060 }
11061
VisitSVEExtractElementToGeneralRegister(const Instruction * instr)11062 void Simulator::VisitSVEExtractElementToGeneralRegister(
11063 const Instruction* instr) {
11064 VectorFormat vform = instr->GetSVEVectorFormat();
11065 SimVRegister& zm = ReadVRegister(instr->GetRn());
11066 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11067
11068 int active_offset = -1;
11069 switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
11070 case LASTA_r_p_z:
11071 active_offset = 1;
11072 break;
11073 case LASTB_r_p_z:
11074 active_offset = 0;
11075 break;
11076 default:
11077 VIXL_UNIMPLEMENTED();
11078 break;
11079 }
11080
11081 if (active_offset >= 0) {
11082 std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
11083 WriteXRegister(instr->GetRd(), value.second);
11084 }
11085 }
11086
VisitSVECompressActiveElements(const Instruction * instr)11087 void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
11088 VectorFormat vform = instr->GetSVEVectorFormat();
11089 SimVRegister& zd = ReadVRegister(instr->GetRd());
11090 SimVRegister& zn = ReadVRegister(instr->GetRn());
11091 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11092
11093 switch (instr->Mask(SVECompressActiveElementsMask)) {
11094 case COMPACT_z_p_z:
11095 compact(vform, zd, pg, zn);
11096 break;
11097 default:
11098 VIXL_UNIMPLEMENTED();
11099 break;
11100 }
11101 }
11102
VisitSVECopyGeneralRegisterToVector_Predicated(const Instruction * instr)11103 void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
11104 const Instruction* instr) {
11105 VectorFormat vform = instr->GetSVEVectorFormat();
11106 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11107 SimVRegister z_result;
11108
11109 switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
11110 case CPY_z_p_r:
11111 dup_immediate(vform,
11112 z_result,
11113 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
11114 mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
11115 break;
11116 default:
11117 VIXL_UNIMPLEMENTED();
11118 break;
11119 }
11120 }
11121
VisitSVECopyIntImm_Predicated(const Instruction * instr)11122 void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
11123 VectorFormat vform = instr->GetSVEVectorFormat();
11124 SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11125 SimVRegister& zd = ReadVRegister(instr->GetRd());
11126
11127 SimVRegister result;
11128 switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
11129 case CPY_z_p_i: {
11130 // Use unsigned arithmetic to avoid undefined behaviour during the shift.
11131 uint64_t imm8 = instr->GetImmSVEIntWideSigned();
11132 dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
11133 break;
11134 }
11135 default:
11136 VIXL_UNIMPLEMENTED();
11137 break;
11138 }
11139
11140 if (instr->ExtractBit(14) != 0) {
11141 mov_merging(vform, zd, pg, result);
11142 } else {
11143 mov_zeroing(vform, zd, pg, result);
11144 }
11145 }
11146
VisitSVEReverseWithinElements(const Instruction * instr)11147 void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
11148 SimVRegister& zd = ReadVRegister(instr->GetRd());
11149 SimVRegister& zn = ReadVRegister(instr->GetRn());
11150 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11151 SimVRegister result;
11152
11153 // In NEON, the chunk size in which elements are REVersed is in the
11154 // instruction mnemonic, and the element size attached to the register.
11155 // SVE reverses the semantics; the mapping to logic functions below is to
11156 // account for this.
11157 VectorFormat chunk_form = instr->GetSVEVectorFormat();
11158 VectorFormat element_form = kFormatUndefined;
11159
11160 switch (instr->Mask(SVEReverseWithinElementsMask)) {
11161 case RBIT_z_p_z:
11162 rbit(chunk_form, result, zn);
11163 break;
11164 case REVB_z_z:
11165 VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
11166 (chunk_form == kFormatVnD));
11167 element_form = kFormatVnB;
11168 break;
11169 case REVH_z_z:
11170 VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
11171 element_form = kFormatVnH;
11172 break;
11173 case REVW_z_z:
11174 VIXL_ASSERT(chunk_form == kFormatVnD);
11175 element_form = kFormatVnS;
11176 break;
11177 default:
11178 VIXL_UNIMPLEMENTED();
11179 break;
11180 }
11181
11182 if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
11183 VIXL_ASSERT(element_form != kFormatUndefined);
11184 switch (chunk_form) {
11185 case kFormatVnH:
11186 rev16(element_form, result, zn);
11187 break;
11188 case kFormatVnS:
11189 rev32(element_form, result, zn);
11190 break;
11191 case kFormatVnD:
11192 rev64(element_form, result, zn);
11193 break;
11194 default:
11195 VIXL_UNIMPLEMENTED();
11196 }
11197 }
11198
11199 mov_merging(chunk_form, zd, pg, result);
11200 }
11201
VisitSVEVectorSplice_Destructive(const Instruction * instr)11202 void Simulator::VisitSVEVectorSplice_Destructive(const Instruction* instr) {
11203 VectorFormat vform = instr->GetSVEVectorFormat();
11204 SimVRegister& zdn = ReadVRegister(instr->GetRd());
11205 SimVRegister& zm = ReadVRegister(instr->GetRn());
11206 SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11207
11208 switch (instr->Mask(SVEVectorSplice_DestructiveMask)) {
11209 case SPLICE_z_p_zz_des:
11210 splice(vform, zdn, pg, zdn, zm);
11211 break;
11212 default:
11213 VIXL_UNIMPLEMENTED();
11214 break;
11215 }
11216 }
11217
VisitSVEBroadcastGeneralRegister(const Instruction * instr)11218 void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
11219 SimVRegister& zd = ReadVRegister(instr->GetRd());
11220 switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
11221 case DUP_z_r:
11222 dup_immediate(instr->GetSVEVectorFormat(),
11223 zd,
11224 ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
11225 break;
11226 default:
11227 VIXL_UNIMPLEMENTED();
11228 break;
11229 }
11230 }
11231
VisitSVEInsertSIMDFPScalarRegister(const Instruction * instr)11232 void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
11233 SimVRegister& zd = ReadVRegister(instr->GetRd());
11234 VectorFormat vform = instr->GetSVEVectorFormat();
11235 switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
11236 case INSR_z_v:
11237 insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
11238 break;
11239 default:
11240 VIXL_UNIMPLEMENTED();
11241 break;
11242 }
11243 }
11244
VisitSVEInsertGeneralRegister(const Instruction * instr)11245 void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
11246 SimVRegister& zd = ReadVRegister(instr->GetRd());
11247 VectorFormat vform = instr->GetSVEVectorFormat();
11248 switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
11249 case INSR_z_r:
11250 insr(vform, zd, ReadXRegister(instr->GetRn()));
11251 break;
11252 default:
11253 VIXL_UNIMPLEMENTED();
11254 break;
11255 }
11256 }
11257
VisitSVEBroadcastIndexElement(const Instruction * instr)11258 void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
11259 SimVRegister& zd = ReadVRegister(instr->GetRd());
11260 switch (instr->Mask(SVEBroadcastIndexElementMask)) {
11261 case DUP_z_zi: {
11262 std::pair<int, int> index_and_lane_size =
11263 instr->GetSVEPermuteIndexAndLaneSizeLog2();
11264 int index = index_and_lane_size.first;
11265 int lane_size_in_bytes_log_2 = index_and_lane_size.second;
11266 VectorFormat vform =
11267 SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
11268 if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
11269 // Out of bounds, set the destination register to zero.
11270 dup_immediate(kFormatVnD, zd, 0);
11271 } else {
11272 dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
11273 }
11274 return;
11275 }
11276 default:
11277 VIXL_UNIMPLEMENTED();
11278 break;
11279 }
11280 }
11281
VisitSVEReverseVectorElements(const Instruction * instr)11282 void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
11283 SimVRegister& zd = ReadVRegister(instr->GetRd());
11284 VectorFormat vform = instr->GetSVEVectorFormat();
11285 switch (instr->Mask(SVEReverseVectorElementsMask)) {
11286 case REV_z_z:
11287 rev(vform, zd, ReadVRegister(instr->GetRn()));
11288 break;
11289 default:
11290 VIXL_UNIMPLEMENTED();
11291 break;
11292 }
11293 }
11294
VisitSVEUnpackVectorElements(const Instruction * instr)11295 void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
11296 SimVRegister& zd = ReadVRegister(instr->GetRd());
11297 VectorFormat vform = instr->GetSVEVectorFormat();
11298 switch (instr->Mask(SVEUnpackVectorElementsMask)) {
11299 case SUNPKHI_z_z:
11300 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
11301 break;
11302 case SUNPKLO_z_z:
11303 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
11304 break;
11305 case UUNPKHI_z_z:
11306 unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
11307 break;
11308 case UUNPKLO_z_z:
11309 unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
11310 break;
11311 default:
11312 VIXL_UNIMPLEMENTED();
11313 break;
11314 }
11315 }
11316
VisitSVETableLookup(const Instruction * instr)11317 void Simulator::VisitSVETableLookup(const Instruction* instr) {
11318 SimVRegister& zd = ReadVRegister(instr->GetRd());
11319 switch (instr->Mask(SVETableLookupMask)) {
11320 case TBL_z_zz_1:
11321 Table(instr->GetSVEVectorFormat(),
11322 zd,
11323 ReadVRegister(instr->GetRn()),
11324 ReadVRegister(instr->GetRm()));
11325 return;
11326 default:
11327 break;
11328 }
11329 }
11330
VisitSVEPredicateCount(const Instruction * instr)11331 void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
11332 VectorFormat vform = instr->GetSVEVectorFormat();
11333 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11334 SimPRegister& pn = ReadPRegister(instr->GetPn());
11335
11336 switch (instr->Mask(SVEPredicateCountMask)) {
11337 case CNTP_r_p_p: {
11338 WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
11339 break;
11340 }
11341 default:
11342 VIXL_UNIMPLEMENTED();
11343 break;
11344 }
11345 }
11346
VisitSVEPredicateLogical(const Instruction * instr)11347 void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
11348 Instr op = instr->Mask(SVEPredicateLogicalMask);
11349 SimPRegister& pd = ReadPRegister(instr->GetPd());
11350 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11351 SimPRegister& pn = ReadPRegister(instr->GetPn());
11352 SimPRegister& pm = ReadPRegister(instr->GetPm());
11353 SimPRegister result;
11354 switch (op) {
11355 case ANDS_p_p_pp_z:
11356 case AND_p_p_pp_z:
11357 case BICS_p_p_pp_z:
11358 case BIC_p_p_pp_z:
11359 case EORS_p_p_pp_z:
11360 case EOR_p_p_pp_z:
11361 case NANDS_p_p_pp_z:
11362 case NAND_p_p_pp_z:
11363 case NORS_p_p_pp_z:
11364 case NOR_p_p_pp_z:
11365 case ORNS_p_p_pp_z:
11366 case ORN_p_p_pp_z:
11367 case ORRS_p_p_pp_z:
11368 case ORR_p_p_pp_z:
11369 SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
11370 result,
11371 pn,
11372 pm);
11373 break;
11374 case SEL_p_p_pp:
11375 sel(pd, pg, pn, pm);
11376 return;
11377 default:
11378 VIXL_UNIMPLEMENTED();
11379 break;
11380 }
11381
11382 mov_zeroing(pd, pg, result);
11383 if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
11384 PredTest(kFormatVnB, pg, pd);
11385 }
11386 }
11387
VisitSVEPredicateFirstActive(const Instruction * instr)11388 void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
11389 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11390 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11391 switch (instr->Mask(SVEPredicateFirstActiveMask)) {
11392 case PFIRST_p_p_p:
11393 pfirst(pdn, pg, pdn);
11394 // TODO: Is this broken when pg == pdn?
11395 PredTest(kFormatVnB, pg, pdn);
11396 break;
11397 default:
11398 VIXL_UNIMPLEMENTED();
11399 break;
11400 }
11401 }
11402
VisitSVEPredicateInitialize(const Instruction * instr)11403 void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
11404 // This group only contains PTRUE{S}, and there are no unallocated encodings.
11405 VIXL_STATIC_ASSERT(
11406 SVEPredicateInitializeMask ==
11407 (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
11408 VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
11409 (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
11410
11411 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11412 VectorFormat vform = instr->GetSVEVectorFormat();
11413
11414 ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
11415 if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
11416 }
11417
VisitSVEPredicateNextActive(const Instruction * instr)11418 void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
11419 // This group only contains PNEXT, and there are no unallocated encodings.
11420 VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
11421 VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
11422
11423 LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
11424 LogicPRegister pdn = ReadPRegister(instr->GetPd());
11425 VectorFormat vform = instr->GetSVEVectorFormat();
11426
11427 pnext(vform, pdn, pg, pdn);
11428 // TODO: Is this broken when pg == pdn?
11429 PredTest(vform, pg, pdn);
11430 }
11431
VisitSVEPredicateReadFromFFR_Predicated(const Instruction * instr)11432 void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
11433 const Instruction* instr) {
11434 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11435 LogicPRegister pg(ReadPRegister(instr->GetPn()));
11436 FlagsUpdate flags = LeaveFlags;
11437 switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
11438 case RDFFR_p_p_f:
11439 // Do nothing.
11440 break;
11441 case RDFFRS_p_p_f:
11442 flags = SetFlags;
11443 break;
11444 default:
11445 VIXL_UNIMPLEMENTED();
11446 break;
11447 }
11448
11449 LogicPRegister ffr(ReadFFR());
11450 mov_zeroing(pd, pg, ffr);
11451
11452 if (flags == SetFlags) {
11453 PredTest(kFormatVnB, pg, pd);
11454 }
11455 }
11456
VisitSVEPredicateReadFromFFR_Unpredicated(const Instruction * instr)11457 void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
11458 const Instruction* instr) {
11459 LogicPRegister pd(ReadPRegister(instr->GetPd()));
11460 LogicPRegister ffr(ReadFFR());
11461 switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
11462 case RDFFR_p_f:
11463 mov(pd, ffr);
11464 break;
11465 default:
11466 VIXL_UNIMPLEMENTED();
11467 break;
11468 }
11469 }
11470
VisitSVEPredicateTest(const Instruction * instr)11471 void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
11472 switch (instr->Mask(SVEPredicateTestMask)) {
11473 case PTEST_p_p:
11474 PredTest(kFormatVnB,
11475 ReadPRegister(instr->ExtractBits(13, 10)),
11476 ReadPRegister(instr->GetPn()));
11477 break;
11478 default:
11479 VIXL_UNIMPLEMENTED();
11480 break;
11481 }
11482 }
11483
VisitSVEPredicateZero(const Instruction * instr)11484 void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
11485 switch (instr->Mask(SVEPredicateZeroMask)) {
11486 case PFALSE_p:
11487 pfalse(ReadPRegister(instr->GetPd()));
11488 break;
11489 default:
11490 VIXL_UNIMPLEMENTED();
11491 break;
11492 }
11493 }
11494
VisitSVEPropagateBreak(const Instruction * instr)11495 void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
11496 SimPRegister& pd = ReadPRegister(instr->GetPd());
11497 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11498 SimPRegister& pn = ReadPRegister(instr->GetPn());
11499 SimPRegister& pm = ReadPRegister(instr->GetPm());
11500
11501 bool set_flags = false;
11502 switch (instr->Mask(SVEPropagateBreakMask)) {
11503 case BRKPAS_p_p_pp:
11504 set_flags = true;
11505 VIXL_FALLTHROUGH();
11506 case BRKPA_p_p_pp:
11507 brkpa(pd, pg, pn, pm);
11508 break;
11509 case BRKPBS_p_p_pp:
11510 set_flags = true;
11511 VIXL_FALLTHROUGH();
11512 case BRKPB_p_p_pp:
11513 brkpb(pd, pg, pn, pm);
11514 break;
11515 default:
11516 VIXL_UNIMPLEMENTED();
11517 break;
11518 }
11519
11520 if (set_flags) {
11521 PredTest(kFormatVnB, pg, pd);
11522 }
11523 }
11524
VisitSVEStackFrameAdjustment(const Instruction * instr)11525 void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
11526 uint64_t length = 0;
11527 switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
11528 case ADDPL_r_ri:
11529 length = GetPredicateLengthInBytes();
11530 break;
11531 case ADDVL_r_ri:
11532 length = GetVectorLengthInBytes();
11533 break;
11534 default:
11535 VIXL_UNIMPLEMENTED();
11536 }
11537 uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
11538 WriteXRegister(instr->GetRd(),
11539 base + (length * instr->GetImmSVEVLScale()),
11540 LogRegWrites,
11541 Reg31IsStackPointer);
11542 }
11543
VisitSVEStackFrameSize(const Instruction * instr)11544 void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
11545 int64_t scale = instr->GetImmSVEVLScale();
11546
11547 switch (instr->Mask(SVEStackFrameSizeMask)) {
11548 case RDVL_r_i:
11549 WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
11550 break;
11551 default:
11552 VIXL_UNIMPLEMENTED();
11553 }
11554 }
11555
VisitSVEVectorSelect(const Instruction * instr)11556 void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
11557 // The only instruction in this group is `sel`, and there are no unused
11558 // encodings.
11559 VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
11560
11561 VectorFormat vform = instr->GetSVEVectorFormat();
11562 SimVRegister& zd = ReadVRegister(instr->GetRd());
11563 SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
11564 SimVRegister& zn = ReadVRegister(instr->GetRn());
11565 SimVRegister& zm = ReadVRegister(instr->GetRm());
11566
11567 sel(vform, zd, pg, zn, zm);
11568 }
11569
VisitSVEFFRInitialise(const Instruction * instr)11570 void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
11571 switch (instr->Mask(SVEFFRInitialiseMask)) {
11572 case SETFFR_f: {
11573 LogicPRegister ffr(ReadFFR());
11574 ffr.SetAllBits();
11575 break;
11576 }
11577 default:
11578 VIXL_UNIMPLEMENTED();
11579 break;
11580 }
11581 }
11582
VisitSVEFFRWriteFromPredicate(const Instruction * instr)11583 void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
11584 switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
11585 case WRFFR_f_p: {
11586 SimPRegister pn(ReadPRegister(instr->GetPn()));
11587 bool last_active = true;
11588 for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
11589 bool active = pn.GetBit(i);
11590 if (active && !last_active) {
11591 // `pn` is non-monotonic. This is UNPREDICTABLE.
11592 VIXL_ABORT();
11593 }
11594 last_active = active;
11595 }
11596 mov(ReadFFR(), pn);
11597 break;
11598 }
11599 default:
11600 VIXL_UNIMPLEMENTED();
11601 break;
11602 }
11603 }
11604
VisitSVEContiguousLoad_ScalarPlusImm(const Instruction * instr)11605 void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
11606 bool is_signed;
11607 switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
11608 case LD1B_z_p_bi_u8:
11609 case LD1B_z_p_bi_u16:
11610 case LD1B_z_p_bi_u32:
11611 case LD1B_z_p_bi_u64:
11612 case LD1H_z_p_bi_u16:
11613 case LD1H_z_p_bi_u32:
11614 case LD1H_z_p_bi_u64:
11615 case LD1W_z_p_bi_u32:
11616 case LD1W_z_p_bi_u64:
11617 case LD1D_z_p_bi_u64:
11618 is_signed = false;
11619 break;
11620 case LD1SB_z_p_bi_s16:
11621 case LD1SB_z_p_bi_s32:
11622 case LD1SB_z_p_bi_s64:
11623 case LD1SH_z_p_bi_s32:
11624 case LD1SH_z_p_bi_s64:
11625 case LD1SW_z_p_bi_s64:
11626 is_signed = true;
11627 break;
11628 default:
11629 // This encoding group is complete, so no other values should be possible.
11630 VIXL_UNREACHABLE();
11631 is_signed = false;
11632 break;
11633 }
11634
11635 int vl = GetVectorLengthInBytes();
11636 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11637 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11638 VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
11639 int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
11640 uint64_t offset =
11641 (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
11642 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11643 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11644 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11645 SVEStructuredLoadHelper(vform,
11646 ReadPRegister(instr->GetPgLow8()),
11647 instr->GetRt(),
11648 addr,
11649 is_signed);
11650 }
11651
VisitSVEContiguousLoad_ScalarPlusScalar(const Instruction * instr)11652 void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
11653 const Instruction* instr) {
11654 bool is_signed;
11655 switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
11656 case LD1B_z_p_br_u8:
11657 case LD1B_z_p_br_u16:
11658 case LD1B_z_p_br_u32:
11659 case LD1B_z_p_br_u64:
11660 case LD1H_z_p_br_u16:
11661 case LD1H_z_p_br_u32:
11662 case LD1H_z_p_br_u64:
11663 case LD1W_z_p_br_u32:
11664 case LD1W_z_p_br_u64:
11665 case LD1D_z_p_br_u64:
11666 is_signed = false;
11667 break;
11668 case LD1SB_z_p_br_s16:
11669 case LD1SB_z_p_br_s32:
11670 case LD1SB_z_p_br_s64:
11671 case LD1SH_z_p_br_s32:
11672 case LD1SH_z_p_br_s64:
11673 case LD1SW_z_p_br_s64:
11674 is_signed = true;
11675 break;
11676 default:
11677 // This encoding group is complete, so no other values should be possible.
11678 VIXL_UNREACHABLE();
11679 is_signed = false;
11680 break;
11681 }
11682
11683 int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11684 int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
11685 VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11686 VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11687 uint64_t offset = ReadXRegister(instr->GetRm());
11688 offset <<= msize_in_bytes_log2;
11689 LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
11690 addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11691 SVEStructuredLoadHelper(vform,
11692 ReadPRegister(instr->GetPgLow8()),
11693 instr->GetRt(),
11694 addr,
11695 is_signed);
11696 }
11697
DoUnreachable(const Instruction * instr)11698 void Simulator::DoUnreachable(const Instruction* instr) {
11699 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11700 (instr->GetImmException() == kUnreachableOpcode));
11701
11702 fprintf(stream_,
11703 "Hit UNREACHABLE marker at pc=%p.\n",
11704 reinterpret_cast<const void*>(instr));
11705 abort();
11706 }
11707
11708
DoTrace(const Instruction * instr)11709 void Simulator::DoTrace(const Instruction* instr) {
11710 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11711 (instr->GetImmException() == kTraceOpcode));
11712
11713 // Read the arguments encoded inline in the instruction stream.
11714 uint32_t parameters;
11715 uint32_t command;
11716
11717 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11718 memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters));
11719 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
11720
11721 switch (command) {
11722 case TRACE_ENABLE:
11723 SetTraceParameters(GetTraceParameters() | parameters);
11724 break;
11725 case TRACE_DISABLE:
11726 SetTraceParameters(GetTraceParameters() & ~parameters);
11727 break;
11728 default:
11729 VIXL_UNREACHABLE();
11730 }
11731
11732 WritePc(instr->GetInstructionAtOffset(kTraceLength));
11733 }
11734
11735
DoLog(const Instruction * instr)11736 void Simulator::DoLog(const Instruction* instr) {
11737 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11738 (instr->GetImmException() == kLogOpcode));
11739
11740 // Read the arguments encoded inline in the instruction stream.
11741 uint32_t parameters;
11742
11743 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11744 memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters));
11745
11746 // We don't support a one-shot LOG_DISASM.
11747 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
11748 // Print the requested information.
11749 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
11750 if (parameters & LOG_REGS) PrintRegisters();
11751 if (parameters & LOG_VREGS) PrintVRegisters();
11752
11753 WritePc(instr->GetInstructionAtOffset(kLogLength));
11754 }
11755
11756
DoPrintf(const Instruction * instr)11757 void Simulator::DoPrintf(const Instruction* instr) {
11758 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11759 (instr->GetImmException() == kPrintfOpcode));
11760
11761 // Read the arguments encoded inline in the instruction stream.
11762 uint32_t arg_count;
11763 uint32_t arg_pattern_list;
11764 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
11765 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
11766 memcpy(&arg_pattern_list,
11767 instr + kPrintfArgPatternListOffset,
11768 sizeof(arg_pattern_list));
11769
11770 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
11771 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
11772
11773 // We need to call the host printf function with a set of arguments defined by
11774 // arg_pattern_list. Because we don't know the types and sizes of the
11775 // arguments, this is very difficult to do in a robust and portable way. To
11776 // work around the problem, we pick apart the format string, and print one
11777 // format placeholder at a time.
11778
11779 // Allocate space for the format string. We take a copy, so we can modify it.
11780 // Leave enough space for one extra character per expected argument (plus the
11781 // '\0' termination).
11782 const char* format_base = ReadRegister<const char*>(0);
11783 VIXL_ASSERT(format_base != NULL);
11784 size_t length = strlen(format_base) + 1;
11785 char* const format = new char[length + arg_count];
11786
11787 // A list of chunks, each with exactly one format placeholder.
11788 const char* chunks[kPrintfMaxArgCount];
11789
11790 // Copy the format string and search for format placeholders.
11791 uint32_t placeholder_count = 0;
11792 char* format_scratch = format;
11793 for (size_t i = 0; i < length; i++) {
11794 if (format_base[i] != '%') {
11795 *format_scratch++ = format_base[i];
11796 } else {
11797 if (format_base[i + 1] == '%') {
11798 // Ignore explicit "%%" sequences.
11799 *format_scratch++ = format_base[i];
11800 i++;
11801 // Chunks after the first are passed as format strings to printf, so we
11802 // need to escape '%' characters in those chunks.
11803 if (placeholder_count > 0) *format_scratch++ = format_base[i];
11804 } else {
11805 VIXL_CHECK(placeholder_count < arg_count);
11806 // Insert '\0' before placeholders, and store their locations.
11807 *format_scratch++ = '\0';
11808 chunks[placeholder_count++] = format_scratch;
11809 *format_scratch++ = format_base[i];
11810 }
11811 }
11812 }
11813 VIXL_CHECK(placeholder_count == arg_count);
11814
11815 // Finally, call printf with each chunk, passing the appropriate register
11816 // argument. Normally, printf returns the number of bytes transmitted, so we
11817 // can emulate a single printf call by adding the result from each chunk. If
11818 // any call returns a negative (error) value, though, just return that value.
11819
11820 printf("%s", clr_printf);
11821
11822 // Because '\0' is inserted before each placeholder, the first string in
11823 // 'format' contains no format placeholders and should be printed literally.
11824 int result = printf("%s", format);
11825 int pcs_r = 1; // Start at x1. x0 holds the format string.
11826 int pcs_f = 0; // Start at d0.
11827 if (result >= 0) {
11828 for (uint32_t i = 0; i < placeholder_count; i++) {
11829 int part_result = -1;
11830
11831 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
11832 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
11833 switch (arg_pattern) {
11834 case kPrintfArgW:
11835 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
11836 break;
11837 case kPrintfArgX:
11838 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
11839 break;
11840 case kPrintfArgD:
11841 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
11842 break;
11843 default:
11844 VIXL_UNREACHABLE();
11845 }
11846
11847 if (part_result < 0) {
11848 // Handle error values.
11849 result = part_result;
11850 break;
11851 }
11852
11853 result += part_result;
11854 }
11855 }
11856
11857 printf("%s", clr_normal);
11858
11859 // Printf returns its result in x0 (just like the C library's printf).
11860 WriteXRegister(0, result);
11861
11862 // The printf parameters are inlined in the code, so skip them.
11863 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
11864
11865 // Set LR as if we'd just called a native printf function.
11866 WriteLr(ReadPc());
11867
11868 delete[] format;
11869 }
11870
11871
11872 #ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
DoRuntimeCall(const Instruction * instr)11873 void Simulator::DoRuntimeCall(const Instruction* instr) {
11874 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
11875 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
11876 // to call are passed inlined in the assembly.
11877 uintptr_t call_wrapper_address =
11878 MemRead<uintptr_t>(instr + kRuntimeCallWrapperOffset);
11879 uintptr_t function_address =
11880 MemRead<uintptr_t>(instr + kRuntimeCallFunctionOffset);
11881 RuntimeCallType call_type = static_cast<RuntimeCallType>(
11882 MemRead<uint32_t>(instr + kRuntimeCallTypeOffset));
11883 auto runtime_call_wrapper =
11884 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
11885
11886 if (call_type == kCallRuntime) {
11887 WriteRegister(kLinkRegCode,
11888 instr->GetInstructionAtOffset(kRuntimeCallLength));
11889 }
11890 runtime_call_wrapper(this, function_address);
11891 // Read the return address from `lr` and write it into `pc`.
11892 WritePc(ReadRegister<Instruction*>(kLinkRegCode));
11893 }
11894 #else
DoRuntimeCall(const Instruction * instr)11895 void Simulator::DoRuntimeCall(const Instruction* instr) {
11896 USE(instr);
11897 VIXL_UNREACHABLE();
11898 }
11899 #endif
11900
11901
DoConfigureCPUFeatures(const Instruction * instr)11902 void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
11903 VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
11904
11905 typedef ConfigureCPUFeaturesElementType ElementType;
11906 VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
11907 std::numeric_limits<ElementType>::max());
11908
11909 // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
11910
11911 size_t element_size = sizeof(ElementType);
11912 size_t offset = kConfigureCPUFeaturesListOffset;
11913
11914 // Read the kNone-terminated list of features.
11915 CPUFeatures parameters;
11916 while (true) {
11917 ElementType feature = MemRead<ElementType>(instr + offset);
11918 offset += element_size;
11919 if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
11920 parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
11921 }
11922
11923 switch (instr->GetImmException()) {
11924 case kSetCPUFeaturesOpcode:
11925 SetCPUFeatures(parameters);
11926 break;
11927 case kEnableCPUFeaturesOpcode:
11928 GetCPUFeatures()->Combine(parameters);
11929 break;
11930 case kDisableCPUFeaturesOpcode:
11931 GetCPUFeatures()->Remove(parameters);
11932 break;
11933 default:
11934 VIXL_UNREACHABLE();
11935 break;
11936 }
11937
11938 WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
11939 }
11940
11941
DoSaveCPUFeatures(const Instruction * instr)11942 void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
11943 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11944 (instr->GetImmException() == kSaveCPUFeaturesOpcode));
11945 USE(instr);
11946
11947 saved_cpu_features_.push_back(*GetCPUFeatures());
11948 }
11949
11950
DoRestoreCPUFeatures(const Instruction * instr)11951 void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
11952 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
11953 (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
11954 USE(instr);
11955
11956 SetCPUFeatures(saved_cpu_features_.back());
11957 saved_cpu_features_.pop_back();
11958 }
11959
11960
11961 } // namespace aarch64
11962 } // namespace vixl
11963
11964 #endif // VIXL_INCLUDE_SIMULATOR_AARCH64
11965