1 // Copyright 2015, ARM Limited
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
28
29 #include <string.h>
30 #include <cmath>
31 #include "vixl/a64/simulator-a64.h"
32
33 namespace vixl {
34
35 const Instruction* Simulator::kEndOfSimAddress = NULL;
36
SetBits(int msb,int lsb,uint32_t bits)37 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
38 int width = msb - lsb + 1;
39 VIXL_ASSERT(is_uintn(width, bits) || is_intn(width, bits));
40
41 bits <<= lsb;
42 uint32_t mask = ((1 << width) - 1) << lsb;
43 VIXL_ASSERT((mask & write_ignore_mask_) == 0);
44
45 value_ = (value_ & ~mask) | (bits & mask);
46 }
47
48
DefaultValueFor(SystemRegister id)49 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
50 switch (id) {
51 case NZCV:
52 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
53 case FPCR:
54 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
55 default:
56 VIXL_UNREACHABLE();
57 return SimSystemRegister();
58 }
59 }
60
61
Simulator(Decoder * decoder,FILE * stream)62 Simulator::Simulator(Decoder* decoder, FILE* stream) {
63 // Ensure that shift operations act as the simulator expects.
64 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
65 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
66
67 instruction_stats_ = false;
68
69 // Set up the decoder.
70 decoder_ = decoder;
71 decoder_->AppendVisitor(this);
72
73 stream_ = stream;
74 print_disasm_ = new PrintDisassembler(stream_);
75 set_coloured_trace(false);
76 trace_parameters_ = LOG_NONE;
77
78 ResetState();
79
80 // Allocate and set up the simulator stack.
81 stack_ = new byte[stack_size_];
82 stack_limit_ = stack_ + stack_protection_size_;
83 // Configure the starting stack pointer.
84 // - Find the top of the stack.
85 byte * tos = stack_ + stack_size_;
86 // - There's a protection region at both ends of the stack.
87 tos -= stack_protection_size_;
88 // - The stack pointer must be 16-byte aligned.
89 tos = AlignDown(tos, 16);
90 set_sp(tos);
91
92 // Set the sample period to 10, as the VIXL examples and tests are short.
93 instrumentation_ = new Instrument("vixl_stats.csv", 10);
94
95 // Print a warning about exclusive-access instructions, but only the first
96 // time they are encountered. This warning can be silenced using
97 // SilenceExclusiveAccessWarning().
98 print_exclusive_access_warning_ = true;
99 }
100
101
ResetState()102 void Simulator::ResetState() {
103 // Reset the system registers.
104 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
105 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
106
107 // Reset registers to 0.
108 pc_ = NULL;
109 pc_modified_ = false;
110 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
111 set_xreg(i, 0xbadbeef);
112 }
113 // Set FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
114 uint64_t nan_bits = UINT64_C(0x7ff0dead7f8beef1);
115 VIXL_ASSERT(IsSignallingNaN(rawbits_to_double(nan_bits & kDRegMask)));
116 VIXL_ASSERT(IsSignallingNaN(rawbits_to_float(nan_bits & kSRegMask)));
117 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) {
118 set_dreg_bits(i, nan_bits);
119 }
120 // Returning to address 0 exits the Simulator.
121 set_lr(kEndOfSimAddress);
122 }
123
124
~Simulator()125 Simulator::~Simulator() {
126 delete[] stack_;
127 // The decoder may outlive the simulator.
128 decoder_->RemoveVisitor(print_disasm_);
129 delete print_disasm_;
130
131 decoder_->RemoveVisitor(instrumentation_);
132 delete instrumentation_;
133 }
134
135
Run()136 void Simulator::Run() {
137 pc_modified_ = false;
138 while (pc_ != kEndOfSimAddress) {
139 ExecuteInstruction();
140 LogAllWrittenRegisters();
141 }
142 }
143
144
RunFrom(const Instruction * first)145 void Simulator::RunFrom(const Instruction* first) {
146 set_pc(first);
147 Run();
148 }
149
150
151 const char* Simulator::xreg_names[] = {
152 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
153 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
154 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
155 "x24", "x25", "x26", "x27", "x28", "x29", "lr", "xzr", "sp"};
156
157 const char* Simulator::wreg_names[] = {
158 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
159 "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
160 "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
161 "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wzr", "wsp"};
162
163 const char* Simulator::sreg_names[] = {
164 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
165 "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
166 "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
167 "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};
168
169 const char* Simulator::dreg_names[] = {
170 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
171 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
172 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
173 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
174
175 const char* Simulator::vreg_names[] = {
176 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
177 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
178 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
179 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
180
181
182
WRegNameForCode(unsigned code,Reg31Mode mode)183 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
184 VIXL_ASSERT(code < kNumberOfRegisters);
185 // If the code represents the stack pointer, index the name after zr.
186 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
187 code = kZeroRegCode + 1;
188 }
189 return wreg_names[code];
190 }
191
192
XRegNameForCode(unsigned code,Reg31Mode mode)193 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
194 VIXL_ASSERT(code < kNumberOfRegisters);
195 // If the code represents the stack pointer, index the name after zr.
196 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
197 code = kZeroRegCode + 1;
198 }
199 return xreg_names[code];
200 }
201
202
SRegNameForCode(unsigned code)203 const char* Simulator::SRegNameForCode(unsigned code) {
204 VIXL_ASSERT(code < kNumberOfFPRegisters);
205 return sreg_names[code];
206 }
207
208
DRegNameForCode(unsigned code)209 const char* Simulator::DRegNameForCode(unsigned code) {
210 VIXL_ASSERT(code < kNumberOfFPRegisters);
211 return dreg_names[code];
212 }
213
214
VRegNameForCode(unsigned code)215 const char* Simulator::VRegNameForCode(unsigned code) {
216 VIXL_ASSERT(code < kNumberOfVRegisters);
217 return vreg_names[code];
218 }
219
220
221 #define COLOUR(colour_code) "\033[0;" colour_code "m"
222 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
223 #define NORMAL ""
224 #define GREY "30"
225 #define RED "31"
226 #define GREEN "32"
227 #define YELLOW "33"
228 #define BLUE "34"
229 #define MAGENTA "35"
230 #define CYAN "36"
231 #define WHITE "37"
set_coloured_trace(bool value)232 void Simulator::set_coloured_trace(bool value) {
233 coloured_trace_ = value;
234
235 clr_normal = value ? COLOUR(NORMAL) : "";
236 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
237 clr_flag_value = value ? COLOUR(NORMAL) : "";
238 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
239 clr_reg_value = value ? COLOUR(CYAN) : "";
240 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
241 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
242 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
243 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
244 clr_warning_message = value ? COLOUR(YELLOW) : "";
245 clr_printf = value ? COLOUR(GREEN) : "";
246 }
247
248
set_trace_parameters(int parameters)249 void Simulator::set_trace_parameters(int parameters) {
250 bool disasm_before = trace_parameters_ & LOG_DISASM;
251 trace_parameters_ = parameters;
252 bool disasm_after = trace_parameters_ & LOG_DISASM;
253
254 if (disasm_before != disasm_after) {
255 if (disasm_after) {
256 decoder_->InsertVisitorBefore(print_disasm_, this);
257 } else {
258 decoder_->RemoveVisitor(print_disasm_);
259 }
260 }
261 }
262
263
set_instruction_stats(bool value)264 void Simulator::set_instruction_stats(bool value) {
265 if (value != instruction_stats_) {
266 if (value) {
267 decoder_->AppendVisitor(instrumentation_);
268 } else {
269 decoder_->RemoveVisitor(instrumentation_);
270 }
271 instruction_stats_ = value;
272 }
273 }
274
275 // Helpers ---------------------------------------------------------------------
AddWithCarry(unsigned reg_size,bool set_flags,uint64_t left,uint64_t right,int carry_in)276 uint64_t Simulator::AddWithCarry(unsigned reg_size,
277 bool set_flags,
278 uint64_t left,
279 uint64_t right,
280 int carry_in) {
281 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
282 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
283
284 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
285 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
286 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
287
288 left &= reg_mask;
289 right &= reg_mask;
290 uint64_t result = (left + right + carry_in) & reg_mask;
291
292 if (set_flags) {
293 nzcv().SetN(CalcNFlag(result, reg_size));
294 nzcv().SetZ(CalcZFlag(result));
295
296 // Compute the C flag by comparing the result to the max unsigned integer.
297 uint64_t max_uint_2op = max_uint - carry_in;
298 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
299 nzcv().SetC(C ? 1 : 0);
300
301 // Overflow iff the sign bit is the same for the two inputs and different
302 // for the result.
303 uint64_t left_sign = left & sign_mask;
304 uint64_t right_sign = right & sign_mask;
305 uint64_t result_sign = result & sign_mask;
306 bool V = (left_sign == right_sign) && (left_sign != result_sign);
307 nzcv().SetV(V ? 1 : 0);
308
309 LogSystemRegister(NZCV);
310 }
311 return result;
312 }
313
314
ShiftOperand(unsigned reg_size,int64_t value,Shift shift_type,unsigned amount)315 int64_t Simulator::ShiftOperand(unsigned reg_size,
316 int64_t value,
317 Shift shift_type,
318 unsigned amount) {
319 if (amount == 0) {
320 return value;
321 }
322 int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
323 switch (shift_type) {
324 case LSL:
325 return (value << amount) & mask;
326 case LSR:
327 return static_cast<uint64_t>(value) >> amount;
328 case ASR: {
329 // Shift used to restore the sign.
330 unsigned s_shift = kXRegSize - reg_size;
331 // Value with its sign restored.
332 int64_t s_value = (value << s_shift) >> s_shift;
333 return (s_value >> amount) & mask;
334 }
335 case ROR: {
336 if (reg_size == kWRegSize) {
337 value &= kWRegMask;
338 }
339 return (static_cast<uint64_t>(value) >> amount) |
340 ((value & ((INT64_C(1) << amount) - 1)) <<
341 (reg_size - amount));
342 }
343 default:
344 VIXL_UNIMPLEMENTED();
345 return 0;
346 }
347 }
348
349
ExtendValue(unsigned reg_size,int64_t value,Extend extend_type,unsigned left_shift)350 int64_t Simulator::ExtendValue(unsigned reg_size,
351 int64_t value,
352 Extend extend_type,
353 unsigned left_shift) {
354 switch (extend_type) {
355 case UXTB:
356 value &= kByteMask;
357 break;
358 case UXTH:
359 value &= kHalfWordMask;
360 break;
361 case UXTW:
362 value &= kWordMask;
363 break;
364 case SXTB:
365 value = (value << 56) >> 56;
366 break;
367 case SXTH:
368 value = (value << 48) >> 48;
369 break;
370 case SXTW:
371 value = (value << 32) >> 32;
372 break;
373 case UXTX:
374 case SXTX:
375 break;
376 default:
377 VIXL_UNREACHABLE();
378 }
379 int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
380 return (value << left_shift) & mask;
381 }
382
383
FPCompare(double val0,double val1,FPTrapFlags trap)384 void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
385 AssertSupportedFPCR();
386
387 // TODO: This assumes that the C++ implementation handles comparisons in the
388 // way that we expect (as per AssertSupportedFPCR()).
389 bool process_exception = false;
390 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
391 nzcv().SetRawValue(FPUnorderedFlag);
392 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
393 (trap == EnableTrap)) {
394 process_exception = true;
395 }
396 } else if (val0 < val1) {
397 nzcv().SetRawValue(FPLessThanFlag);
398 } else if (val0 > val1) {
399 nzcv().SetRawValue(FPGreaterThanFlag);
400 } else if (val0 == val1) {
401 nzcv().SetRawValue(FPEqualFlag);
402 } else {
403 VIXL_UNREACHABLE();
404 }
405 LogSystemRegister(NZCV);
406 if (process_exception) FPProcessException();
407 }
408
409
GetPrintRegisterFormatForSize(unsigned reg_size,unsigned lane_size)410 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
411 unsigned reg_size, unsigned lane_size) {
412 VIXL_ASSERT(reg_size >= lane_size);
413
414 uint32_t format = 0;
415 if (reg_size != lane_size) {
416 switch (reg_size) {
417 default: VIXL_UNREACHABLE(); break;
418 case kQRegSizeInBytes: format = kPrintRegAsQVector; break;
419 case kDRegSizeInBytes: format = kPrintRegAsDVector; break;
420 }
421 }
422
423 switch (lane_size) {
424 default: VIXL_UNREACHABLE(); break;
425 case kQRegSizeInBytes: format |= kPrintReg1Q; break;
426 case kDRegSizeInBytes: format |= kPrintReg1D; break;
427 case kSRegSizeInBytes: format |= kPrintReg1S; break;
428 case kHRegSizeInBytes: format |= kPrintReg1H; break;
429 case kBRegSizeInBytes: format |= kPrintReg1B; break;
430 }
431 // These sizes would be duplicate case labels.
432 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
433 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
434 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
435 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
436
437 return static_cast<PrintRegisterFormat>(format);
438 }
439
440
GetPrintRegisterFormat(VectorFormat vform)441 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
442 VectorFormat vform) {
443 switch (vform) {
444 default: VIXL_UNREACHABLE(); return kPrintReg16B;
445 case kFormat16B: return kPrintReg16B;
446 case kFormat8B: return kPrintReg8B;
447 case kFormat8H: return kPrintReg8H;
448 case kFormat4H: return kPrintReg4H;
449 case kFormat4S: return kPrintReg4S;
450 case kFormat2S: return kPrintReg2S;
451 case kFormat2D: return kPrintReg2D;
452 case kFormat1D: return kPrintReg1D;
453 }
454 }
455
456
PrintWrittenRegisters()457 void Simulator::PrintWrittenRegisters() {
458 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
459 if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
460 }
461 }
462
463
PrintWrittenVRegisters()464 void Simulator::PrintWrittenVRegisters() {
465 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
466 // At this point there is no type information, so print as a raw 1Q.
467 if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
468 }
469 }
470
471
PrintSystemRegisters()472 void Simulator::PrintSystemRegisters() {
473 PrintSystemRegister(NZCV);
474 PrintSystemRegister(FPCR);
475 }
476
477
PrintRegisters()478 void Simulator::PrintRegisters() {
479 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
480 PrintRegister(i);
481 }
482 }
483
484
PrintVRegisters()485 void Simulator::PrintVRegisters() {
486 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
487 // At this point there is no type information, so print as a raw 1Q.
488 PrintVRegister(i, kPrintReg1Q);
489 }
490 }
491
492
493 // Print a register's name and raw value.
494 //
495 // Only the least-significant `size_in_bytes` bytes of the register are printed,
496 // but the value is aligned as if the whole register had been printed.
497 //
498 // For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
499 // -- the default -- so that the whole register is printed. Other values of
500 // size_in_bytes are intended for use when the register hasn't actually been
501 // updated (such as in PrintWrite).
502 //
503 // No newline is printed. This allows the caller to print more details (such as
504 // a memory access annotation).
PrintRegisterRawHelper(unsigned code,Reg31Mode r31mode,int size_in_bytes)505 void Simulator::PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
506 int size_in_bytes) {
507 // The template for all supported sizes.
508 // "# x{code}: 0xffeeddccbbaa9988"
509 // "# w{code}: 0xbbaa9988"
510 // "# w{code}<15:0>: 0x9988"
511 // "# w{code}<7:0>: 0x88"
512 unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
513
514 const char * name = "";
515 const char * suffix = "";
516 switch (size_in_bytes) {
517 case kXRegSizeInBytes: name = XRegNameForCode(code, r31mode); break;
518 case kWRegSizeInBytes: name = WRegNameForCode(code, r31mode); break;
519 case 2:
520 name = WRegNameForCode(code, r31mode);
521 suffix = "<15:0>";
522 padding_chars -= strlen(suffix);
523 break;
524 case 1:
525 name = WRegNameForCode(code, r31mode);
526 suffix = "<7:0>";
527 padding_chars -= strlen(suffix);
528 break;
529 default:
530 VIXL_UNREACHABLE();
531 }
532 fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
533
534 // Print leading padding spaces.
535 VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
536 for (unsigned i = 0; i < padding_chars; i++) {
537 putc(' ', stream_);
538 }
539
540 // Print the specified bits in hexadecimal format.
541 uint64_t bits = reg<uint64_t>(code, r31mode);
542 bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
543 VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
544
545 int chars = size_in_bytes * 2;
546 fprintf(stream_, "%s0x%0*" PRIx64 "%s",
547 clr_reg_value, chars, bits, clr_normal);
548 }
549
550
PrintRegister(unsigned code,Reg31Mode r31mode)551 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
552 registers_[code].NotifyRegisterLogged();
553
554 // Don't print writes into xzr.
555 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
556 return;
557 }
558
559 // The template for all x and w registers:
560 // "# x{code}: 0x{value}"
561 // "# w{code}: 0x{value}"
562
563 PrintRegisterRawHelper(code, r31mode);
564 fprintf(stream_, "\n");
565 }
566
567
568 // Print a register's name and raw value.
569 //
570 // The `bytes` and `lsb` arguments can be used to limit the bytes that are
571 // printed. These arguments are intended for use in cases where register hasn't
572 // actually been updated (such as in PrintVWrite).
573 //
574 // No newline is printed. This allows the caller to print more details (such as
575 // a floating-point interpretation or a memory access annotation).
PrintVRegisterRawHelper(unsigned code,int bytes,int lsb)576 void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
577 // The template for vector types:
578 // "# v{code}: 0xffeeddccbbaa99887766554433221100".
579 // An example with bytes=4 and lsb=8:
580 // "# v{code}: 0xbbaa9988 ".
581 fprintf(stream_, "# %s%5s: %s",
582 clr_vreg_name, VRegNameForCode(code), clr_vreg_value);
583
584 int msb = lsb + bytes - 1;
585 int byte = kQRegSizeInBytes - 1;
586
587 // Print leading padding spaces. (Two spaces per byte.)
588 while (byte > msb) {
589 fprintf(stream_, " ");
590 byte--;
591 }
592
593 // Print the specified part of the value, byte by byte.
594 qreg_t rawbits = qreg(code);
595 fprintf(stream_, "0x");
596 while (byte >= lsb) {
597 fprintf(stream_, "%02x", rawbits.val[byte]);
598 byte--;
599 }
600
601 // Print trailing padding spaces.
602 while (byte >= 0) {
603 fprintf(stream_, " ");
604 byte--;
605 }
606 fprintf(stream_, "%s", clr_normal);
607 }
608
609
610 // Print each of the specified lanes of a register as a float or double value.
611 //
612 // The `lane_count` and `lslane` arguments can be used to limit the lanes that
613 // are printed. These arguments are intended for use in cases where register
614 // hasn't actually been updated (such as in PrintVWrite).
615 //
616 // No newline is printed. This allows the caller to print more details (such as
617 // a memory access annotation).
PrintVRegisterFPHelper(unsigned code,unsigned lane_size_in_bytes,int lane_count,int rightmost_lane)618 void Simulator::PrintVRegisterFPHelper(unsigned code,
619 unsigned lane_size_in_bytes,
620 int lane_count,
621 int rightmost_lane) {
622 VIXL_ASSERT((lane_size_in_bytes == kSRegSizeInBytes) ||
623 (lane_size_in_bytes == kDRegSizeInBytes));
624
625 unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
626 VIXL_ASSERT(msb <= kQRegSizeInBytes);
627
628 // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
629 // name is used:
630 // " (s{code}: {value})"
631 // " (d{code}: {value})"
632 // For vector types, "..." is used to represent one or more omitted lanes.
633 // " (..., {value}, {value}, ...)"
634 if ((lane_count == 1) && (rightmost_lane == 0)) {
635 const char * name =
636 (lane_size_in_bytes == kSRegSizeInBytes) ? SRegNameForCode(code)
637 : DRegNameForCode(code);
638 fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
639 } else {
640 if (msb < (kQRegSizeInBytes - 1)) {
641 fprintf(stream_, " (..., ");
642 } else {
643 fprintf(stream_, " (");
644 }
645 }
646
647 // Print the list of values.
648 const char * separator = "";
649 int leftmost_lane = rightmost_lane + lane_count - 1;
650 for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
651 double value =
652 (lane_size_in_bytes == kSRegSizeInBytes) ? vreg(code).Get<float>(lane)
653 : vreg(code).Get<double>(lane);
654 fprintf(stream_, "%s%s%#g%s", separator, clr_vreg_value, value, clr_normal);
655 separator = ", ";
656 }
657
658 if (rightmost_lane > 0) {
659 fprintf(stream_, ", ...");
660 }
661 fprintf(stream_, ")");
662 }
663
664
PrintVRegister(unsigned code,PrintRegisterFormat format)665 void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
666 vregisters_[code].NotifyRegisterLogged();
667
668 int lane_size_log2 = format & kPrintRegLaneSizeMask;
669
670 int reg_size_log2;
671 if (format & kPrintRegAsQVector) {
672 reg_size_log2 = kQRegSizeInBytesLog2;
673 } else if (format & kPrintRegAsDVector) {
674 reg_size_log2 = kDRegSizeInBytesLog2;
675 } else {
676 // Scalar types.
677 reg_size_log2 = lane_size_log2;
678 }
679
680 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
681 int lane_size = 1 << lane_size_log2;
682
683 // The template for vector types:
684 // "# v{code}: 0x{rawbits} (..., {value}, ...)".
685 // The template for scalar types:
686 // "# v{code}: 0x{rawbits} ({reg}:{value})".
687 // The values in parentheses after the bit representations are floating-point
688 // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
689
690 PrintVRegisterRawHelper(code);
691 if (format & kPrintRegAsFP) {
692 PrintVRegisterFPHelper(code, lane_size, lane_count);
693 }
694
695 fprintf(stream_, "\n");
696 }
697
698
PrintSystemRegister(SystemRegister id)699 void Simulator::PrintSystemRegister(SystemRegister id) {
700 switch (id) {
701 case NZCV:
702 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
703 clr_flag_name, clr_flag_value,
704 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
705 clr_normal);
706 break;
707 case FPCR: {
708 static const char * rmode[] = {
709 "0b00 (Round to Nearest)",
710 "0b01 (Round towards Plus Infinity)",
711 "0b10 (Round towards Minus Infinity)",
712 "0b11 (Round towards Zero)"
713 };
714 VIXL_ASSERT(fpcr().RMode() < (sizeof(rmode) / sizeof(rmode[0])));
715 fprintf(stream_,
716 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
717 clr_flag_name, clr_flag_value,
718 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
719 clr_normal);
720 break;
721 }
722 default:
723 VIXL_UNREACHABLE();
724 }
725 }
726
727
PrintRead(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)728 void Simulator::PrintRead(uintptr_t address,
729 unsigned reg_code,
730 PrintRegisterFormat format) {
731 registers_[reg_code].NotifyRegisterLogged();
732
733 USE(format);
734
735 // The template is "# {reg}: 0x{value} <- {address}".
736 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
737 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
738 clr_memory_address, address, clr_normal);
739 }
740
741
PrintVRead(uintptr_t address,unsigned reg_code,PrintRegisterFormat format,unsigned lane)742 void Simulator::PrintVRead(uintptr_t address,
743 unsigned reg_code,
744 PrintRegisterFormat format,
745 unsigned lane) {
746 vregisters_[reg_code].NotifyRegisterLogged();
747
748 // The template is "# v{code}: 0x{rawbits} <- address".
749 PrintVRegisterRawHelper(reg_code);
750 if (format & kPrintRegAsFP) {
751 PrintVRegisterFPHelper(reg_code, GetPrintRegLaneSizeInBytes(format),
752 GetPrintRegLaneCount(format), lane);
753 }
754 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
755 clr_memory_address, address, clr_normal);
756 }
757
758
PrintWrite(uintptr_t address,unsigned reg_code,PrintRegisterFormat format)759 void Simulator::PrintWrite(uintptr_t address,
760 unsigned reg_code,
761 PrintRegisterFormat format) {
762 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
763
764 // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
765 // and readable, the value is aligned with the values in the register trace.
766 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister,
767 GetPrintRegSizeInBytes(format));
768 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
769 clr_memory_address, address, clr_normal);
770 }
771
772
PrintVWrite(uintptr_t address,unsigned reg_code,PrintRegisterFormat format,unsigned lane)773 void Simulator::PrintVWrite(uintptr_t address,
774 unsigned reg_code,
775 PrintRegisterFormat format,
776 unsigned lane) {
777 // The templates:
778 // "# v{code}: 0x{rawbits} -> {address}"
779 // "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
780 // "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
781 // Because this trace doesn't represent a change to the source register's
782 // value, only the relevant part of the value is printed. To keep the trace
783 // tidy and readable, the raw value is aligned with the other values in the
784 // register trace.
785 int lane_count = GetPrintRegLaneCount(format);
786 int lane_size = GetPrintRegLaneSizeInBytes(format);
787 int reg_size = GetPrintRegSizeInBytes(format);
788 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
789 if (format & kPrintRegAsFP) {
790 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
791 }
792 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
793 clr_memory_address, address, clr_normal);
794 }
795
796
797 // Visitors---------------------------------------------------------------------
798
VisitUnimplemented(const Instruction * instr)799 void Simulator::VisitUnimplemented(const Instruction* instr) {
800 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
801 reinterpret_cast<const void*>(instr), instr->InstructionBits());
802 VIXL_UNIMPLEMENTED();
803 }
804
805
VisitUnallocated(const Instruction * instr)806 void Simulator::VisitUnallocated(const Instruction* instr) {
807 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
808 reinterpret_cast<const void*>(instr), instr->InstructionBits());
809 VIXL_UNIMPLEMENTED();
810 }
811
812
VisitPCRelAddressing(const Instruction * instr)813 void Simulator::VisitPCRelAddressing(const Instruction* instr) {
814 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
815 (instr->Mask(PCRelAddressingMask) == ADRP));
816
817 set_reg(instr->Rd(), instr->ImmPCOffsetTarget());
818 }
819
820
VisitUnconditionalBranch(const Instruction * instr)821 void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
822 switch (instr->Mask(UnconditionalBranchMask)) {
823 case BL:
824 set_lr(instr->NextInstruction());
825 VIXL_FALLTHROUGH();
826 case B:
827 set_pc(instr->ImmPCOffsetTarget());
828 break;
829 default: VIXL_UNREACHABLE();
830 }
831 }
832
833
VisitConditionalBranch(const Instruction * instr)834 void Simulator::VisitConditionalBranch(const Instruction* instr) {
835 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
836 if (ConditionPassed(instr->ConditionBranch())) {
837 set_pc(instr->ImmPCOffsetTarget());
838 }
839 }
840
841
VisitUnconditionalBranchToRegister(const Instruction * instr)842 void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
843 const Instruction* target = Instruction::Cast(xreg(instr->Rn()));
844
845 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
846 case BLR:
847 set_lr(instr->NextInstruction());
848 VIXL_FALLTHROUGH();
849 case BR:
850 case RET: set_pc(target); break;
851 default: VIXL_UNREACHABLE();
852 }
853 }
854
855
VisitTestBranch(const Instruction * instr)856 void Simulator::VisitTestBranch(const Instruction* instr) {
857 unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
858 instr->ImmTestBranchBit40();
859 bool bit_zero = ((xreg(instr->Rt()) >> bit_pos) & 1) == 0;
860 bool take_branch = false;
861 switch (instr->Mask(TestBranchMask)) {
862 case TBZ: take_branch = bit_zero; break;
863 case TBNZ: take_branch = !bit_zero; break;
864 default: VIXL_UNIMPLEMENTED();
865 }
866 if (take_branch) {
867 set_pc(instr->ImmPCOffsetTarget());
868 }
869 }
870
871
VisitCompareBranch(const Instruction * instr)872 void Simulator::VisitCompareBranch(const Instruction* instr) {
873 unsigned rt = instr->Rt();
874 bool take_branch = false;
875 switch (instr->Mask(CompareBranchMask)) {
876 case CBZ_w: take_branch = (wreg(rt) == 0); break;
877 case CBZ_x: take_branch = (xreg(rt) == 0); break;
878 case CBNZ_w: take_branch = (wreg(rt) != 0); break;
879 case CBNZ_x: take_branch = (xreg(rt) != 0); break;
880 default: VIXL_UNIMPLEMENTED();
881 }
882 if (take_branch) {
883 set_pc(instr->ImmPCOffsetTarget());
884 }
885 }
886
887
AddSubHelper(const Instruction * instr,int64_t op2)888 void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
889 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
890 bool set_flags = instr->FlagsUpdate();
891 int64_t new_val = 0;
892 Instr operation = instr->Mask(AddSubOpMask);
893
894 switch (operation) {
895 case ADD:
896 case ADDS: {
897 new_val = AddWithCarry(reg_size,
898 set_flags,
899 reg(reg_size, instr->Rn(), instr->RnMode()),
900 op2);
901 break;
902 }
903 case SUB:
904 case SUBS: {
905 new_val = AddWithCarry(reg_size,
906 set_flags,
907 reg(reg_size, instr->Rn(), instr->RnMode()),
908 ~op2,
909 1);
910 break;
911 }
912 default: VIXL_UNREACHABLE();
913 }
914
915 set_reg(reg_size, instr->Rd(), new_val, LogRegWrites, instr->RdMode());
916 }
917
918
VisitAddSubShifted(const Instruction * instr)919 void Simulator::VisitAddSubShifted(const Instruction* instr) {
920 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
921 int64_t op2 = ShiftOperand(reg_size,
922 reg(reg_size, instr->Rm()),
923 static_cast<Shift>(instr->ShiftDP()),
924 instr->ImmDPShift());
925 AddSubHelper(instr, op2);
926 }
927
928
VisitAddSubImmediate(const Instruction * instr)929 void Simulator::VisitAddSubImmediate(const Instruction* instr) {
930 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
931 AddSubHelper(instr, op2);
932 }
933
934
VisitAddSubExtended(const Instruction * instr)935 void Simulator::VisitAddSubExtended(const Instruction* instr) {
936 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
937 int64_t op2 = ExtendValue(reg_size,
938 reg(reg_size, instr->Rm()),
939 static_cast<Extend>(instr->ExtendMode()),
940 instr->ImmExtendShift());
941 AddSubHelper(instr, op2);
942 }
943
944
VisitAddSubWithCarry(const Instruction * instr)945 void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
946 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
947 int64_t op2 = reg(reg_size, instr->Rm());
948 int64_t new_val;
949
950 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
951 op2 = ~op2;
952 }
953
954 new_val = AddWithCarry(reg_size,
955 instr->FlagsUpdate(),
956 reg(reg_size, instr->Rn()),
957 op2,
958 C());
959
960 set_reg(reg_size, instr->Rd(), new_val);
961 }
962
963
VisitLogicalShifted(const Instruction * instr)964 void Simulator::VisitLogicalShifted(const Instruction* instr) {
965 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
966 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
967 unsigned shift_amount = instr->ImmDPShift();
968 int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type,
969 shift_amount);
970 if (instr->Mask(NOT) == NOT) {
971 op2 = ~op2;
972 }
973 LogicalHelper(instr, op2);
974 }
975
976
VisitLogicalImmediate(const Instruction * instr)977 void Simulator::VisitLogicalImmediate(const Instruction* instr) {
978 LogicalHelper(instr, instr->ImmLogical());
979 }
980
981
LogicalHelper(const Instruction * instr,int64_t op2)982 void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
983 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
984 int64_t op1 = reg(reg_size, instr->Rn());
985 int64_t result = 0;
986 bool update_flags = false;
987
988 // Switch on the logical operation, stripping out the NOT bit, as it has a
989 // different meaning for logical immediate instructions.
990 switch (instr->Mask(LogicalOpMask & ~NOT)) {
991 case ANDS: update_flags = true; VIXL_FALLTHROUGH();
992 case AND: result = op1 & op2; break;
993 case ORR: result = op1 | op2; break;
994 case EOR: result = op1 ^ op2; break;
995 default:
996 VIXL_UNIMPLEMENTED();
997 }
998
999 if (update_flags) {
1000 nzcv().SetN(CalcNFlag(result, reg_size));
1001 nzcv().SetZ(CalcZFlag(result));
1002 nzcv().SetC(0);
1003 nzcv().SetV(0);
1004 LogSystemRegister(NZCV);
1005 }
1006
1007 set_reg(reg_size, instr->Rd(), result, LogRegWrites, instr->RdMode());
1008 }
1009
1010
VisitConditionalCompareRegister(const Instruction * instr)1011 void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1012 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1013 ConditionalCompareHelper(instr, reg(reg_size, instr->Rm()));
1014 }
1015
1016
VisitConditionalCompareImmediate(const Instruction * instr)1017 void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1018 ConditionalCompareHelper(instr, instr->ImmCondCmp());
1019 }
1020
1021
ConditionalCompareHelper(const Instruction * instr,int64_t op2)1022 void Simulator::ConditionalCompareHelper(const Instruction* instr,
1023 int64_t op2) {
1024 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1025 int64_t op1 = reg(reg_size, instr->Rn());
1026
1027 if (ConditionPassed(instr->Condition())) {
1028 // If the condition passes, set the status flags to the result of comparing
1029 // the operands.
1030 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1031 AddWithCarry(reg_size, true, op1, ~op2, 1);
1032 } else {
1033 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1034 AddWithCarry(reg_size, true, op1, op2, 0);
1035 }
1036 } else {
1037 // If the condition fails, set the status flags to the nzcv immediate.
1038 nzcv().SetFlags(instr->Nzcv());
1039 LogSystemRegister(NZCV);
1040 }
1041 }
1042
1043
VisitLoadStoreUnsignedOffset(const Instruction * instr)1044 void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1045 int offset = instr->ImmLSUnsigned() << instr->SizeLS();
1046 LoadStoreHelper(instr, offset, Offset);
1047 }
1048
1049
VisitLoadStoreUnscaledOffset(const Instruction * instr)1050 void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1051 LoadStoreHelper(instr, instr->ImmLS(), Offset);
1052 }
1053
1054
VisitLoadStorePreIndex(const Instruction * instr)1055 void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1056 LoadStoreHelper(instr, instr->ImmLS(), PreIndex);
1057 }
1058
1059
VisitLoadStorePostIndex(const Instruction * instr)1060 void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1061 LoadStoreHelper(instr, instr->ImmLS(), PostIndex);
1062 }
1063
1064
VisitLoadStoreRegisterOffset(const Instruction * instr)1065 void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
1066 Extend ext = static_cast<Extend>(instr->ExtendMode());
1067 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1068 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS();
1069
1070 int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
1071 shift_amount);
1072 LoadStoreHelper(instr, offset, Offset);
1073 }
1074
1075
1076
LoadStoreHelper(const Instruction * instr,int64_t offset,AddrMode addrmode)1077 void Simulator::LoadStoreHelper(const Instruction* instr,
1078 int64_t offset,
1079 AddrMode addrmode) {
1080 unsigned srcdst = instr->Rt();
1081 uintptr_t address = AddressModeHelper(instr->Rn(), offset, addrmode);
1082
1083 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
1084 switch (op) {
1085 case LDRB_w:
1086 set_wreg(srcdst, Memory::Read<uint8_t>(address), NoRegLog); break;
1087 case LDRH_w:
1088 set_wreg(srcdst, Memory::Read<uint16_t>(address), NoRegLog); break;
1089 case LDR_w:
1090 set_wreg(srcdst, Memory::Read<uint32_t>(address), NoRegLog); break;
1091 case LDR_x:
1092 set_xreg(srcdst, Memory::Read<uint64_t>(address), NoRegLog); break;
1093 case LDRSB_w:
1094 set_wreg(srcdst, Memory::Read<int8_t>(address), NoRegLog); break;
1095 case LDRSH_w:
1096 set_wreg(srcdst, Memory::Read<int16_t>(address), NoRegLog); break;
1097 case LDRSB_x:
1098 set_xreg(srcdst, Memory::Read<int8_t>(address), NoRegLog); break;
1099 case LDRSH_x:
1100 set_xreg(srcdst, Memory::Read<int16_t>(address), NoRegLog); break;
1101 case LDRSW_x:
1102 set_xreg(srcdst, Memory::Read<int32_t>(address), NoRegLog); break;
1103 case LDR_b:
1104 set_breg(srcdst, Memory::Read<uint8_t>(address), NoRegLog); break;
1105 case LDR_h:
1106 set_hreg(srcdst, Memory::Read<uint16_t>(address), NoRegLog); break;
1107 case LDR_s:
1108 set_sreg(srcdst, Memory::Read<float>(address), NoRegLog); break;
1109 case LDR_d:
1110 set_dreg(srcdst, Memory::Read<double>(address), NoRegLog); break;
1111 case LDR_q:
1112 set_qreg(srcdst, Memory::Read<qreg_t>(address), NoRegLog); break;
1113
1114 case STRB_w: Memory::Write<uint8_t>(address, wreg(srcdst)); break;
1115 case STRH_w: Memory::Write<uint16_t>(address, wreg(srcdst)); break;
1116 case STR_w: Memory::Write<uint32_t>(address, wreg(srcdst)); break;
1117 case STR_x: Memory::Write<uint64_t>(address, xreg(srcdst)); break;
1118 case STR_b: Memory::Write<uint8_t>(address, breg(srcdst)); break;
1119 case STR_h: Memory::Write<uint16_t>(address, hreg(srcdst)); break;
1120 case STR_s: Memory::Write<float>(address, sreg(srcdst)); break;
1121 case STR_d: Memory::Write<double>(address, dreg(srcdst)); break;
1122 case STR_q: Memory::Write<qreg_t>(address, qreg(srcdst)); break;
1123
1124 // Ignore prfm hint instructions.
1125 case PRFM: break;
1126
1127 default: VIXL_UNIMPLEMENTED();
1128 }
1129
1130 unsigned access_size = 1 << instr->SizeLS();
1131 if (instr->IsLoad()) {
1132 if ((op == LDR_s) || (op == LDR_d)) {
1133 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1134 } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1135 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1136 } else {
1137 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1138 }
1139 } else {
1140 if ((op == STR_s) || (op == STR_d)) {
1141 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1142 } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1143 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1144 } else {
1145 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1146 }
1147 }
1148
1149 local_monitor_.MaybeClear();
1150 }
1151
1152
VisitLoadStorePairOffset(const Instruction * instr)1153 void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
1154 LoadStorePairHelper(instr, Offset);
1155 }
1156
1157
VisitLoadStorePairPreIndex(const Instruction * instr)1158 void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
1159 LoadStorePairHelper(instr, PreIndex);
1160 }
1161
1162
VisitLoadStorePairPostIndex(const Instruction * instr)1163 void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
1164 LoadStorePairHelper(instr, PostIndex);
1165 }
1166
1167
VisitLoadStorePairNonTemporal(const Instruction * instr)1168 void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
1169 LoadStorePairHelper(instr, Offset);
1170 }
1171
1172
LoadStorePairHelper(const Instruction * instr,AddrMode addrmode)1173 void Simulator::LoadStorePairHelper(const Instruction* instr,
1174 AddrMode addrmode) {
1175 unsigned rt = instr->Rt();
1176 unsigned rt2 = instr->Rt2();
1177 int element_size = 1 << instr->SizeLSPair();
1178 int64_t offset = instr->ImmLSPair() * element_size;
1179 uintptr_t address = AddressModeHelper(instr->Rn(), offset, addrmode);
1180 uintptr_t address2 = address + element_size;
1181
1182 LoadStorePairOp op =
1183 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1184
1185 // 'rt' and 'rt2' can only be aliased for stores.
1186 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1187
1188 switch (op) {
1189 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
1190 // will print a more detailed log.
1191 case LDP_w: {
1192 set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
1193 set_wreg(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
1194 break;
1195 }
1196 case LDP_s: {
1197 set_sreg(rt, Memory::Read<float>(address), NoRegLog);
1198 set_sreg(rt2, Memory::Read<float>(address2), NoRegLog);
1199 break;
1200 }
1201 case LDP_x: {
1202 set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
1203 set_xreg(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
1204 break;
1205 }
1206 case LDP_d: {
1207 set_dreg(rt, Memory::Read<double>(address), NoRegLog);
1208 set_dreg(rt2, Memory::Read<double>(address2), NoRegLog);
1209 break;
1210 }
1211 case LDP_q: {
1212 set_qreg(rt, Memory::Read<qreg_t>(address), NoRegLog);
1213 set_qreg(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
1214 break;
1215 }
1216 case LDPSW_x: {
1217 set_xreg(rt, Memory::Read<int32_t>(address), NoRegLog);
1218 set_xreg(rt2, Memory::Read<int32_t>(address2), NoRegLog);
1219 break;
1220 }
1221 case STP_w: {
1222 Memory::Write<uint32_t>(address, wreg(rt));
1223 Memory::Write<uint32_t>(address2, wreg(rt2));
1224 break;
1225 }
1226 case STP_s: {
1227 Memory::Write<float>(address, sreg(rt));
1228 Memory::Write<float>(address2, sreg(rt2));
1229 break;
1230 }
1231 case STP_x: {
1232 Memory::Write<uint64_t>(address, xreg(rt));
1233 Memory::Write<uint64_t>(address2, xreg(rt2));
1234 break;
1235 }
1236 case STP_d: {
1237 Memory::Write<double>(address, dreg(rt));
1238 Memory::Write<double>(address2, dreg(rt2));
1239 break;
1240 }
1241 case STP_q: {
1242 Memory::Write<qreg_t>(address, qreg(rt));
1243 Memory::Write<qreg_t>(address2, qreg(rt2));
1244 break;
1245 }
1246 default: VIXL_UNREACHABLE();
1247 }
1248
1249 // Print a detailed trace (including the memory address) instead of the basic
1250 // register:value trace generated by set_*reg().
1251 if (instr->IsLoad()) {
1252 if ((op == LDP_s) || (op == LDP_d)) {
1253 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1254 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1255 } else if (op == LDP_q) {
1256 LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1257 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1258 } else {
1259 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1260 LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1261 }
1262 } else {
1263 if ((op == STP_s) || (op == STP_d)) {
1264 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1265 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1266 } else if (op == STP_q) {
1267 LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1268 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1269 } else {
1270 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1271 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1272 }
1273 }
1274
1275 local_monitor_.MaybeClear();
1276 }
1277
1278
PrintExclusiveAccessWarning()1279 void Simulator::PrintExclusiveAccessWarning() {
1280 if (print_exclusive_access_warning_) {
1281 fprintf(
1282 stderr,
1283 "%sWARNING:%s VIXL simulator support for load-/store-/clear-exclusive "
1284 "instructions is limited. Refer to the README for details.%s\n",
1285 clr_warning, clr_warning_message, clr_normal);
1286 print_exclusive_access_warning_ = false;
1287 }
1288 }
1289
1290
VisitLoadStoreExclusive(const Instruction * instr)1291 void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
1292 PrintExclusiveAccessWarning();
1293
1294 unsigned rs = instr->Rs();
1295 unsigned rt = instr->Rt();
1296 unsigned rt2 = instr->Rt2();
1297 unsigned rn = instr->Rn();
1298
1299 LoadStoreExclusive op =
1300 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
1301
1302 bool is_acquire_release = instr->LdStXAcquireRelease();
1303 bool is_exclusive = !instr->LdStXNotExclusive();
1304 bool is_load = instr->LdStXLoad();
1305 bool is_pair = instr->LdStXPair();
1306
1307 unsigned element_size = 1 << instr->LdStXSizeLog2();
1308 unsigned access_size = is_pair ? element_size * 2 : element_size;
1309 uint64_t address = reg<uint64_t>(rn, Reg31IsStackPointer);
1310
1311 // Verify that the address is available to the host.
1312 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1313
1314 // Check the alignment of `address`.
1315 if (AlignDown(address, access_size) != address) {
1316 VIXL_ALIGNMENT_EXCEPTION();
1317 }
1318
1319 // The sp must be aligned to 16 bytes when it is accessed.
1320 if ((rn == 31) && (AlignDown(address, 16) != address)) {
1321 VIXL_ALIGNMENT_EXCEPTION();
1322 }
1323
1324 if (is_load) {
1325 if (is_exclusive) {
1326 local_monitor_.MarkExclusive(address, access_size);
1327 } else {
1328 // Any non-exclusive load can clear the local monitor as a side effect. We
1329 // don't need to do this, but it is useful to stress the simulated code.
1330 local_monitor_.Clear();
1331 }
1332
1333 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
1334 // will print a more detailed log.
1335 switch (op) {
1336 case LDXRB_w:
1337 case LDAXRB_w:
1338 case LDARB_w:
1339 set_wreg(rt, Memory::Read<uint8_t>(address), NoRegLog);
1340 break;
1341 case LDXRH_w:
1342 case LDAXRH_w:
1343 case LDARH_w:
1344 set_wreg(rt, Memory::Read<uint16_t>(address), NoRegLog);
1345 break;
1346 case LDXR_w:
1347 case LDAXR_w:
1348 case LDAR_w:
1349 set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
1350 break;
1351 case LDXR_x:
1352 case LDAXR_x:
1353 case LDAR_x:
1354 set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
1355 break;
1356 case LDXP_w:
1357 case LDAXP_w:
1358 set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
1359 set_wreg(rt2, Memory::Read<uint32_t>(address + element_size), NoRegLog);
1360 break;
1361 case LDXP_x:
1362 case LDAXP_x:
1363 set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
1364 set_xreg(rt2, Memory::Read<uint64_t>(address + element_size), NoRegLog);
1365 break;
1366 default:
1367 VIXL_UNREACHABLE();
1368 }
1369
1370 if (is_acquire_release) {
1371 // Approximate load-acquire by issuing a full barrier after the load.
1372 __sync_synchronize();
1373 }
1374
1375 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1376 if (is_pair) {
1377 LogRead(address + element_size, rt2,
1378 GetPrintRegisterFormatForSize(element_size));
1379 }
1380 } else {
1381 if (is_acquire_release) {
1382 // Approximate store-release by issuing a full barrier before the store.
1383 __sync_synchronize();
1384 }
1385
1386 bool do_store = true;
1387 if (is_exclusive) {
1388 do_store = local_monitor_.IsExclusive(address, access_size) &&
1389 global_monitor_.IsExclusive(address, access_size);
1390 set_wreg(rs, do_store ? 0 : 1);
1391
1392 // - All exclusive stores explicitly clear the local monitor.
1393 local_monitor_.Clear();
1394 } else {
1395 // - Any other store can clear the local monitor as a side effect.
1396 local_monitor_.MaybeClear();
1397 }
1398
1399 if (do_store) {
1400 switch (op) {
1401 case STXRB_w:
1402 case STLXRB_w:
1403 case STLRB_w:
1404 Memory::Write<uint8_t>(address, wreg(rt));
1405 break;
1406 case STXRH_w:
1407 case STLXRH_w:
1408 case STLRH_w:
1409 Memory::Write<uint16_t>(address, wreg(rt));
1410 break;
1411 case STXR_w:
1412 case STLXR_w:
1413 case STLR_w:
1414 Memory::Write<uint32_t>(address, wreg(rt));
1415 break;
1416 case STXR_x:
1417 case STLXR_x:
1418 case STLR_x:
1419 Memory::Write<uint64_t>(address, xreg(rt));
1420 break;
1421 case STXP_w:
1422 case STLXP_w:
1423 Memory::Write<uint32_t>(address, wreg(rt));
1424 Memory::Write<uint32_t>(address + element_size, wreg(rt2));
1425 break;
1426 case STXP_x:
1427 case STLXP_x:
1428 Memory::Write<uint64_t>(address, xreg(rt));
1429 Memory::Write<uint64_t>(address + element_size, xreg(rt2));
1430 break;
1431 default:
1432 VIXL_UNREACHABLE();
1433 }
1434
1435 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1436 if (is_pair) {
1437 LogWrite(address + element_size, rt2,
1438 GetPrintRegisterFormatForSize(element_size));
1439 }
1440 }
1441 }
1442 }
1443
1444
VisitLoadLiteral(const Instruction * instr)1445 void Simulator::VisitLoadLiteral(const Instruction* instr) {
1446 unsigned rt = instr->Rt();
1447 uint64_t address = instr->LiteralAddress<uint64_t>();
1448
1449 // Verify that the calculated address is available to the host.
1450 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1451
1452 switch (instr->Mask(LoadLiteralMask)) {
1453 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
1454 // print a more detailed log.
1455 case LDR_w_lit:
1456 set_wreg(rt, Memory::Read<uint32_t>(address), NoRegLog);
1457 LogRead(address, rt, kPrintWReg);
1458 break;
1459 case LDR_x_lit:
1460 set_xreg(rt, Memory::Read<uint64_t>(address), NoRegLog);
1461 LogRead(address, rt, kPrintXReg);
1462 break;
1463 case LDR_s_lit:
1464 set_sreg(rt, Memory::Read<float>(address), NoRegLog);
1465 LogVRead(address, rt, kPrintSReg);
1466 break;
1467 case LDR_d_lit:
1468 set_dreg(rt, Memory::Read<double>(address), NoRegLog);
1469 LogVRead(address, rt, kPrintDReg);
1470 break;
1471 case LDR_q_lit:
1472 set_qreg(rt, Memory::Read<qreg_t>(address), NoRegLog);
1473 LogVRead(address, rt, kPrintReg1Q);
1474 break;
1475 case LDRSW_x_lit:
1476 set_xreg(rt, Memory::Read<int32_t>(address), NoRegLog);
1477 LogRead(address, rt, kPrintWReg);
1478 break;
1479
1480 // Ignore prfm hint instructions.
1481 case PRFM_lit: break;
1482
1483 default: VIXL_UNREACHABLE();
1484 }
1485
1486 local_monitor_.MaybeClear();
1487 }
1488
1489
AddressModeHelper(unsigned addr_reg,int64_t offset,AddrMode addrmode)1490 uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
1491 int64_t offset,
1492 AddrMode addrmode) {
1493 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1494
1495 if ((addr_reg == 31) && ((address % 16) != 0)) {
1496 // When the base register is SP the stack pointer is required to be
1497 // quadword aligned prior to the address calculation and write-backs.
1498 // Misalignment will cause a stack alignment fault.
1499 VIXL_ALIGNMENT_EXCEPTION();
1500 }
1501
1502 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1503 VIXL_ASSERT(offset != 0);
1504 // Only preindex should log the register update here. For Postindex, the
1505 // update will be printed automatically by LogWrittenRegisters _after_ the
1506 // memory access itself is logged.
1507 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
1508 set_xreg(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
1509 }
1510
1511 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1512 address += offset;
1513 }
1514
1515 // Verify that the calculated address is available to the host.
1516 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1517
1518 return static_cast<uintptr_t>(address);
1519 }
1520
1521
VisitMoveWideImmediate(const Instruction * instr)1522 void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
1523 MoveWideImmediateOp mov_op =
1524 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1525 int64_t new_xn_val = 0;
1526
1527 bool is_64_bits = instr->SixtyFourBits() == 1;
1528 // Shift is limited for W operations.
1529 VIXL_ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2));
1530
1531 // Get the shifted immediate.
1532 int64_t shift = instr->ShiftMoveWide() * 16;
1533 int64_t shifted_imm16 = static_cast<int64_t>(instr->ImmMoveWide()) << shift;
1534
1535 // Compute the new value.
1536 switch (mov_op) {
1537 case MOVN_w:
1538 case MOVN_x: {
1539 new_xn_val = ~shifted_imm16;
1540 if (!is_64_bits) new_xn_val &= kWRegMask;
1541 break;
1542 }
1543 case MOVK_w:
1544 case MOVK_x: {
1545 unsigned reg_code = instr->Rd();
1546 int64_t prev_xn_val = is_64_bits ? xreg(reg_code)
1547 : wreg(reg_code);
1548 new_xn_val =
1549 (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
1550 break;
1551 }
1552 case MOVZ_w:
1553 case MOVZ_x: {
1554 new_xn_val = shifted_imm16;
1555 break;
1556 }
1557 default:
1558 VIXL_UNREACHABLE();
1559 }
1560
1561 // Update the destination register.
1562 set_xreg(instr->Rd(), new_xn_val);
1563 }
1564
1565
VisitConditionalSelect(const Instruction * instr)1566 void Simulator::VisitConditionalSelect(const Instruction* instr) {
1567 uint64_t new_val = xreg(instr->Rn());
1568
1569 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) {
1570 new_val = xreg(instr->Rm());
1571 switch (instr->Mask(ConditionalSelectMask)) {
1572 case CSEL_w:
1573 case CSEL_x: break;
1574 case CSINC_w:
1575 case CSINC_x: new_val++; break;
1576 case CSINV_w:
1577 case CSINV_x: new_val = ~new_val; break;
1578 case CSNEG_w:
1579 case CSNEG_x: new_val = -new_val; break;
1580 default: VIXL_UNIMPLEMENTED();
1581 }
1582 }
1583 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1584 set_reg(reg_size, instr->Rd(), new_val);
1585 }
1586
1587
VisitDataProcessing1Source(const Instruction * instr)1588 void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
1589 unsigned dst = instr->Rd();
1590 unsigned src = instr->Rn();
1591
1592 switch (instr->Mask(DataProcessing1SourceMask)) {
1593 case RBIT_w: set_wreg(dst, ReverseBits(wreg(src))); break;
1594 case RBIT_x: set_xreg(dst, ReverseBits(xreg(src))); break;
1595 case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), 1)); break;
1596 case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), 1)); break;
1597 case REV_w: set_wreg(dst, ReverseBytes(wreg(src), 2)); break;
1598 case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), 2)); break;
1599 case REV_x: set_xreg(dst, ReverseBytes(xreg(src), 3)); break;
1600 case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src))); break;
1601 case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src))); break;
1602 case CLS_w: {
1603 set_wreg(dst, CountLeadingSignBits(wreg(src)));
1604 break;
1605 }
1606 case CLS_x: {
1607 set_xreg(dst, CountLeadingSignBits(xreg(src)));
1608 break;
1609 }
1610 default: VIXL_UNIMPLEMENTED();
1611 }
1612 }
1613
1614
Poly32Mod2(unsigned n,uint64_t data,uint32_t poly)1615 uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
1616 VIXL_ASSERT((n > 32) && (n <= 64));
1617 for (unsigned i = (n - 1); i >= 32; i--) {
1618 if (((data >> i) & 1) != 0) {
1619 uint64_t polysh32 = (uint64_t)poly << (i - 32);
1620 uint64_t mask = (UINT64_C(1) << i) - 1;
1621 data = ((data & mask) ^ polysh32);
1622 }
1623 }
1624 return data & 0xffffffff;
1625 }
1626
1627
1628 template <typename T>
Crc32Checksum(uint32_t acc,T val,uint32_t poly)1629 uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
1630 unsigned size = sizeof(val) * 8; // Number of bits in type T.
1631 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
1632 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
1633 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
1634 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
1635 }
1636
1637
Crc32Checksum(uint32_t acc,uint64_t val,uint32_t poly)1638 uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
1639 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
1640 // the CRC of each 32-bit word sequentially.
1641 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
1642 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
1643 }
1644
1645
VisitDataProcessing2Source(const Instruction * instr)1646 void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
1647 Shift shift_op = NO_SHIFT;
1648 int64_t result = 0;
1649 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1650
1651 switch (instr->Mask(DataProcessing2SourceMask)) {
1652 case SDIV_w: {
1653 int32_t rn = wreg(instr->Rn());
1654 int32_t rm = wreg(instr->Rm());
1655 if ((rn == kWMinInt) && (rm == -1)) {
1656 result = kWMinInt;
1657 } else if (rm == 0) {
1658 // Division by zero can be trapped, but not on A-class processors.
1659 result = 0;
1660 } else {
1661 result = rn / rm;
1662 }
1663 break;
1664 }
1665 case SDIV_x: {
1666 int64_t rn = xreg(instr->Rn());
1667 int64_t rm = xreg(instr->Rm());
1668 if ((rn == kXMinInt) && (rm == -1)) {
1669 result = kXMinInt;
1670 } else if (rm == 0) {
1671 // Division by zero can be trapped, but not on A-class processors.
1672 result = 0;
1673 } else {
1674 result = rn / rm;
1675 }
1676 break;
1677 }
1678 case UDIV_w: {
1679 uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn()));
1680 uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm()));
1681 if (rm == 0) {
1682 // Division by zero can be trapped, but not on A-class processors.
1683 result = 0;
1684 } else {
1685 result = rn / rm;
1686 }
1687 break;
1688 }
1689 case UDIV_x: {
1690 uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn()));
1691 uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm()));
1692 if (rm == 0) {
1693 // Division by zero can be trapped, but not on A-class processors.
1694 result = 0;
1695 } else {
1696 result = rn / rm;
1697 }
1698 break;
1699 }
1700 case LSLV_w:
1701 case LSLV_x: shift_op = LSL; break;
1702 case LSRV_w:
1703 case LSRV_x: shift_op = LSR; break;
1704 case ASRV_w:
1705 case ASRV_x: shift_op = ASR; break;
1706 case RORV_w:
1707 case RORV_x: shift_op = ROR; break;
1708 case CRC32B: {
1709 uint32_t acc = reg<uint32_t>(instr->Rn());
1710 uint8_t val = reg<uint8_t>(instr->Rm());
1711 result = Crc32Checksum(acc, val, CRC32_POLY);
1712 break;
1713 }
1714 case CRC32H: {
1715 uint32_t acc = reg<uint32_t>(instr->Rn());
1716 uint16_t val = reg<uint16_t>(instr->Rm());
1717 result = Crc32Checksum(acc, val, CRC32_POLY);
1718 break;
1719 }
1720 case CRC32W: {
1721 uint32_t acc = reg<uint32_t>(instr->Rn());
1722 uint32_t val = reg<uint32_t>(instr->Rm());
1723 result = Crc32Checksum(acc, val, CRC32_POLY);
1724 break;
1725 }
1726 case CRC32X: {
1727 uint32_t acc = reg<uint32_t>(instr->Rn());
1728 uint64_t val = reg<uint64_t>(instr->Rm());
1729 result = Crc32Checksum(acc, val, CRC32_POLY);
1730 reg_size = kWRegSize;
1731 break;
1732 }
1733 case CRC32CB: {
1734 uint32_t acc = reg<uint32_t>(instr->Rn());
1735 uint8_t val = reg<uint8_t>(instr->Rm());
1736 result = Crc32Checksum(acc, val, CRC32C_POLY);
1737 break;
1738 }
1739 case CRC32CH: {
1740 uint32_t acc = reg<uint32_t>(instr->Rn());
1741 uint16_t val = reg<uint16_t>(instr->Rm());
1742 result = Crc32Checksum(acc, val, CRC32C_POLY);
1743 break;
1744 }
1745 case CRC32CW: {
1746 uint32_t acc = reg<uint32_t>(instr->Rn());
1747 uint32_t val = reg<uint32_t>(instr->Rm());
1748 result = Crc32Checksum(acc, val, CRC32C_POLY);
1749 break;
1750 }
1751 case CRC32CX: {
1752 uint32_t acc = reg<uint32_t>(instr->Rn());
1753 uint64_t val = reg<uint64_t>(instr->Rm());
1754 result = Crc32Checksum(acc, val, CRC32C_POLY);
1755 reg_size = kWRegSize;
1756 break;
1757 }
1758 default: VIXL_UNIMPLEMENTED();
1759 }
1760
1761 if (shift_op != NO_SHIFT) {
1762 // Shift distance encoded in the least-significant five/six bits of the
1763 // register.
1764 int mask = (instr->SixtyFourBits() == 1) ? 0x3f : 0x1f;
1765 unsigned shift = wreg(instr->Rm()) & mask;
1766 result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op,
1767 shift);
1768 }
1769 set_reg(reg_size, instr->Rd(), result);
1770 }
1771
1772
1773 // The algorithm used is adapted from the one described in section 8.2 of
1774 // Hacker's Delight, by Henry S. Warren, Jr.
1775 // It assumes that a right shift on a signed integer is an arithmetic shift.
1776 // Type T must be either uint64_t or int64_t.
1777 template <typename T>
MultiplyHigh(T u,T v)1778 static T MultiplyHigh(T u, T v) {
1779 uint64_t u0, v0, w0;
1780 T u1, v1, w1, w2, t;
1781
1782 VIXL_ASSERT(sizeof(u) == sizeof(u0));
1783
1784 u0 = u & 0xffffffff;
1785 u1 = u >> 32;
1786 v0 = v & 0xffffffff;
1787 v1 = v >> 32;
1788
1789 w0 = u0 * v0;
1790 t = u1 * v0 + (w0 >> 32);
1791 w1 = t & 0xffffffff;
1792 w2 = t >> 32;
1793 w1 = u0 * v1 + w1;
1794
1795 return u1 * v1 + w2 + (w1 >> 32);
1796 }
1797
1798
VisitDataProcessing3Source(const Instruction * instr)1799 void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
1800 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1801
1802 int64_t result = 0;
1803 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
1804 uint64_t rn_u32 = reg<uint32_t>(instr->Rn());
1805 uint64_t rm_u32 = reg<uint32_t>(instr->Rm());
1806 int64_t rn_s32 = reg<int32_t>(instr->Rn());
1807 int64_t rm_s32 = reg<int32_t>(instr->Rm());
1808 switch (instr->Mask(DataProcessing3SourceMask)) {
1809 case MADD_w:
1810 case MADD_x:
1811 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm()));
1812 break;
1813 case MSUB_w:
1814 case MSUB_x:
1815 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm()));
1816 break;
1817 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break;
1818 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break;
1819 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break;
1820 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break;
1821 case UMULH_x:
1822 result = MultiplyHigh(reg<uint64_t>(instr->Rn()),
1823 reg<uint64_t>(instr->Rm()));
1824 break;
1825 case SMULH_x:
1826 result = MultiplyHigh(xreg(instr->Rn()), xreg(instr->Rm()));
1827 break;
1828 default: VIXL_UNIMPLEMENTED();
1829 }
1830 set_reg(reg_size, instr->Rd(), result);
1831 }
1832
1833
VisitBitfield(const Instruction * instr)1834 void Simulator::VisitBitfield(const Instruction* instr) {
1835 unsigned reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
1836 int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask;
1837 int64_t R = instr->ImmR();
1838 int64_t S = instr->ImmS();
1839 int64_t diff = S - R;
1840 int64_t mask;
1841 if (diff >= 0) {
1842 mask = (diff < (reg_size - 1)) ? (INT64_C(1) << (diff + 1)) - 1
1843 : reg_mask;
1844 } else {
1845 mask = (INT64_C(1) << (S + 1)) - 1;
1846 mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
1847 diff += reg_size;
1848 }
1849
1850 // inzero indicates if the extracted bitfield is inserted into the
1851 // destination register value or in zero.
1852 // If extend is true, extend the sign of the extracted bitfield.
1853 bool inzero = false;
1854 bool extend = false;
1855 switch (instr->Mask(BitfieldMask)) {
1856 case BFM_x:
1857 case BFM_w:
1858 break;
1859 case SBFM_x:
1860 case SBFM_w:
1861 inzero = true;
1862 extend = true;
1863 break;
1864 case UBFM_x:
1865 case UBFM_w:
1866 inzero = true;
1867 break;
1868 default:
1869 VIXL_UNIMPLEMENTED();
1870 }
1871
1872 int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd());
1873 int64_t src = reg(reg_size, instr->Rn());
1874 // Rotate source bitfield into place.
1875 int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
1876 // Determine the sign extension.
1877 int64_t topbits = ((INT64_C(1) << (reg_size - diff - 1)) - 1) << (diff + 1);
1878 int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
1879
1880 // Merge sign extension, dest/zero and bitfield.
1881 result = signbits | (result & mask) | (dst & ~mask);
1882
1883 set_reg(reg_size, instr->Rd(), result);
1884 }
1885
1886
VisitExtract(const Instruction * instr)1887 void Simulator::VisitExtract(const Instruction* instr) {
1888 unsigned lsb = instr->ImmS();
1889 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize
1890 : kWRegSize;
1891 uint64_t low_res = static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb;
1892 uint64_t high_res =
1893 (lsb == 0) ? 0 : reg(reg_size, instr->Rn()) << (reg_size - lsb);
1894 set_reg(reg_size, instr->Rd(), low_res | high_res);
1895 }
1896
1897
VisitFPImmediate(const Instruction * instr)1898 void Simulator::VisitFPImmediate(const Instruction* instr) {
1899 AssertSupportedFPCR();
1900
1901 unsigned dest = instr->Rd();
1902 switch (instr->Mask(FPImmediateMask)) {
1903 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break;
1904 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break;
1905 default: VIXL_UNREACHABLE();
1906 }
1907 }
1908
1909
VisitFPIntegerConvert(const Instruction * instr)1910 void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
1911 AssertSupportedFPCR();
1912
1913 unsigned dst = instr->Rd();
1914 unsigned src = instr->Rn();
1915
1916 FPRounding round = RMode();
1917
1918 switch (instr->Mask(FPIntegerConvertMask)) {
1919 case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
1920 case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break;
1921 case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break;
1922 case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break;
1923 case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break;
1924 case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break;
1925 case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break;
1926 case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break;
1927 case FCVTMS_ws:
1928 set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity));
1929 break;
1930 case FCVTMS_xs:
1931 set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity));
1932 break;
1933 case FCVTMS_wd:
1934 set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity));
1935 break;
1936 case FCVTMS_xd:
1937 set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity));
1938 break;
1939 case FCVTMU_ws:
1940 set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity));
1941 break;
1942 case FCVTMU_xs:
1943 set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity));
1944 break;
1945 case FCVTMU_wd:
1946 set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity));
1947 break;
1948 case FCVTMU_xd:
1949 set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity));
1950 break;
1951 case FCVTPS_ws:
1952 set_wreg(dst, FPToInt32(sreg(src), FPPositiveInfinity));
1953 break;
1954 case FCVTPS_xs:
1955 set_xreg(dst, FPToInt64(sreg(src), FPPositiveInfinity));
1956 break;
1957 case FCVTPS_wd:
1958 set_wreg(dst, FPToInt32(dreg(src), FPPositiveInfinity));
1959 break;
1960 case FCVTPS_xd:
1961 set_xreg(dst, FPToInt64(dreg(src), FPPositiveInfinity));
1962 break;
1963 case FCVTPU_ws:
1964 set_wreg(dst, FPToUInt32(sreg(src), FPPositiveInfinity));
1965 break;
1966 case FCVTPU_xs:
1967 set_xreg(dst, FPToUInt64(sreg(src), FPPositiveInfinity));
1968 break;
1969 case FCVTPU_wd:
1970 set_wreg(dst, FPToUInt32(dreg(src), FPPositiveInfinity));
1971 break;
1972 case FCVTPU_xd:
1973 set_xreg(dst, FPToUInt64(dreg(src), FPPositiveInfinity));
1974 break;
1975 case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break;
1976 case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break;
1977 case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break;
1978 case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break;
1979 case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break;
1980 case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break;
1981 case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break;
1982 case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break;
1983 case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break;
1984 case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break;
1985 case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break;
1986 case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break;
1987 case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break;
1988 case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break;
1989 case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break;
1990 case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break;
1991 case FMOV_ws: set_wreg(dst, sreg_bits(src)); break;
1992 case FMOV_xd: set_xreg(dst, dreg_bits(src)); break;
1993 case FMOV_sw: set_sreg_bits(dst, wreg(src)); break;
1994 case FMOV_dx: set_dreg_bits(dst, xreg(src)); break;
1995 case FMOV_d1_x:
1996 LogicVRegister(vreg(dst)).SetUint(kFormatD, 1, xreg(src));
1997 break;
1998 case FMOV_x_d1:
1999 set_xreg(dst, LogicVRegister(vreg(src)).Uint(kFormatD, 1));
2000 break;
2001
2002 // A 32-bit input can be handled in the same way as a 64-bit input, since
2003 // the sign- or zero-extension will not affect the conversion.
2004 case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break;
2005 case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break;
2006 case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break;
2007 case UCVTF_dw: {
2008 set_dreg(dst, UFixedToDouble(static_cast<uint32_t>(wreg(src)), 0, round));
2009 break;
2010 }
2011 case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break;
2012 case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break;
2013 case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break;
2014 case UCVTF_sw: {
2015 set_sreg(dst, UFixedToFloat(static_cast<uint32_t>(wreg(src)), 0, round));
2016 break;
2017 }
2018
2019 default: VIXL_UNREACHABLE();
2020 }
2021 }
2022
2023
VisitFPFixedPointConvert(const Instruction * instr)2024 void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
2025 AssertSupportedFPCR();
2026
2027 unsigned dst = instr->Rd();
2028 unsigned src = instr->Rn();
2029 int fbits = 64 - instr->FPScale();
2030
2031 FPRounding round = RMode();
2032
2033 switch (instr->Mask(FPFixedPointConvertMask)) {
2034 // A 32-bit input can be handled in the same way as a 64-bit input, since
2035 // the sign- or zero-extension will not affect the conversion.
2036 case SCVTF_dx_fixed:
2037 set_dreg(dst, FixedToDouble(xreg(src), fbits, round));
2038 break;
2039 case SCVTF_dw_fixed:
2040 set_dreg(dst, FixedToDouble(wreg(src), fbits, round));
2041 break;
2042 case UCVTF_dx_fixed:
2043 set_dreg(dst, UFixedToDouble(xreg(src), fbits, round));
2044 break;
2045 case UCVTF_dw_fixed: {
2046 set_dreg(dst,
2047 UFixedToDouble(static_cast<uint32_t>(wreg(src)), fbits, round));
2048 break;
2049 }
2050 case SCVTF_sx_fixed:
2051 set_sreg(dst, FixedToFloat(xreg(src), fbits, round));
2052 break;
2053 case SCVTF_sw_fixed:
2054 set_sreg(dst, FixedToFloat(wreg(src), fbits, round));
2055 break;
2056 case UCVTF_sx_fixed:
2057 set_sreg(dst, UFixedToFloat(xreg(src), fbits, round));
2058 break;
2059 case UCVTF_sw_fixed: {
2060 set_sreg(dst,
2061 UFixedToFloat(static_cast<uint32_t>(wreg(src)), fbits, round));
2062 break;
2063 }
2064 case FCVTZS_xd_fixed:
2065 set_xreg(dst, FPToInt64(dreg(src) * std::pow(2.0, fbits), FPZero));
2066 break;
2067 case FCVTZS_wd_fixed:
2068 set_wreg(dst, FPToInt32(dreg(src) * std::pow(2.0, fbits), FPZero));
2069 break;
2070 case FCVTZU_xd_fixed:
2071 set_xreg(dst, FPToUInt64(dreg(src) * std::pow(2.0, fbits), FPZero));
2072 break;
2073 case FCVTZU_wd_fixed:
2074 set_wreg(dst, FPToUInt32(dreg(src) * std::pow(2.0, fbits), FPZero));
2075 break;
2076 case FCVTZS_xs_fixed:
2077 set_xreg(dst, FPToInt64(sreg(src) * std::pow(2.0f, fbits), FPZero));
2078 break;
2079 case FCVTZS_ws_fixed:
2080 set_wreg(dst, FPToInt32(sreg(src) * std::pow(2.0f, fbits), FPZero));
2081 break;
2082 case FCVTZU_xs_fixed:
2083 set_xreg(dst, FPToUInt64(sreg(src) * std::pow(2.0f, fbits), FPZero));
2084 break;
2085 case FCVTZU_ws_fixed:
2086 set_wreg(dst, FPToUInt32(sreg(src) * std::pow(2.0f, fbits), FPZero));
2087 break;
2088 default: VIXL_UNREACHABLE();
2089 }
2090 }
2091
2092
VisitFPCompare(const Instruction * instr)2093 void Simulator::VisitFPCompare(const Instruction* instr) {
2094 AssertSupportedFPCR();
2095
2096 FPTrapFlags trap = DisableTrap;
2097 switch (instr->Mask(FPCompareMask)) {
2098 case FCMPE_s: trap = EnableTrap; VIXL_FALLTHROUGH();
2099 case FCMP_s: FPCompare(sreg(instr->Rn()), sreg(instr->Rm()), trap); break;
2100 case FCMPE_d: trap = EnableTrap; VIXL_FALLTHROUGH();
2101 case FCMP_d: FPCompare(dreg(instr->Rn()), dreg(instr->Rm()), trap); break;
2102 case FCMPE_s_zero: trap = EnableTrap; VIXL_FALLTHROUGH();
2103 case FCMP_s_zero: FPCompare(sreg(instr->Rn()), 0.0f, trap); break;
2104 case FCMPE_d_zero: trap = EnableTrap; VIXL_FALLTHROUGH();
2105 case FCMP_d_zero: FPCompare(dreg(instr->Rn()), 0.0, trap); break;
2106 default: VIXL_UNIMPLEMENTED();
2107 }
2108 }
2109
2110
VisitFPConditionalCompare(const Instruction * instr)2111 void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
2112 AssertSupportedFPCR();
2113
2114 FPTrapFlags trap = DisableTrap;
2115 switch (instr->Mask(FPConditionalCompareMask)) {
2116 case FCCMPE_s: trap = EnableTrap;
2117 VIXL_FALLTHROUGH();
2118 case FCCMP_s:
2119 if (ConditionPassed(instr->Condition())) {
2120 FPCompare(sreg(instr->Rn()), sreg(instr->Rm()), trap);
2121 } else {
2122 nzcv().SetFlags(instr->Nzcv());
2123 LogSystemRegister(NZCV);
2124 }
2125 break;
2126 case FCCMPE_d: trap = EnableTrap;
2127 VIXL_FALLTHROUGH();
2128 case FCCMP_d:
2129 if (ConditionPassed(instr->Condition())) {
2130 FPCompare(dreg(instr->Rn()), dreg(instr->Rm()), trap);
2131 } else {
2132 nzcv().SetFlags(instr->Nzcv());
2133 LogSystemRegister(NZCV);
2134 }
2135 break;
2136 default: VIXL_UNIMPLEMENTED();
2137 }
2138 }
2139
2140
VisitFPConditionalSelect(const Instruction * instr)2141 void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
2142 AssertSupportedFPCR();
2143
2144 Instr selected;
2145 if (ConditionPassed(instr->Condition())) {
2146 selected = instr->Rn();
2147 } else {
2148 selected = instr->Rm();
2149 }
2150
2151 switch (instr->Mask(FPConditionalSelectMask)) {
2152 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2153 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2154 default: VIXL_UNIMPLEMENTED();
2155 }
2156 }
2157
2158
VisitFPDataProcessing1Source(const Instruction * instr)2159 void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
2160 AssertSupportedFPCR();
2161
2162 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
2163 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2164 SimVRegister& rd = vreg(instr->Rd());
2165 SimVRegister& rn = vreg(instr->Rn());
2166 bool inexact_exception = false;
2167
2168 unsigned fd = instr->Rd();
2169 unsigned fn = instr->Rn();
2170
2171 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2172 case FMOV_s: set_sreg(fd, sreg(fn)); return;
2173 case FMOV_d: set_dreg(fd, dreg(fn)); return;
2174 case FABS_s: fabs_(kFormatS, vreg(fd), vreg(fn)); return;
2175 case FABS_d: fabs_(kFormatD, vreg(fd), vreg(fn)); return;
2176 case FNEG_s: fneg(kFormatS, vreg(fd), vreg(fn)); return;
2177 case FNEG_d: fneg(kFormatD, vreg(fd), vreg(fn)); return;
2178 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); return;
2179 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); return;
2180 case FCVT_hs: set_hreg(fd, FPToFloat16(sreg(fn), FPTieEven)); return;
2181 case FCVT_sh: set_sreg(fd, FPToFloat(hreg(fn))); return;
2182 case FCVT_dh: set_dreg(fd, FPToDouble(FPToFloat(hreg(fn)))); return;
2183 case FCVT_hd: set_hreg(fd, FPToFloat16(dreg(fn), FPTieEven)); return;
2184 case FSQRT_s:
2185 case FSQRT_d: fsqrt(vform, rd, rn); return;
2186 case FRINTI_s:
2187 case FRINTI_d: break; // Use FPCR rounding mode.
2188 case FRINTX_s:
2189 case FRINTX_d: inexact_exception = true; break;
2190 case FRINTA_s:
2191 case FRINTA_d: fpcr_rounding = FPTieAway; break;
2192 case FRINTM_s:
2193 case FRINTM_d: fpcr_rounding = FPNegativeInfinity; break;
2194 case FRINTN_s:
2195 case FRINTN_d: fpcr_rounding = FPTieEven; break;
2196 case FRINTP_s:
2197 case FRINTP_d: fpcr_rounding = FPPositiveInfinity; break;
2198 case FRINTZ_s:
2199 case FRINTZ_d: fpcr_rounding = FPZero; break;
2200 default: VIXL_UNIMPLEMENTED();
2201 }
2202
2203 // Only FRINT* instructions fall through the switch above.
2204 frint(vform, rd, rn, fpcr_rounding, inexact_exception);
2205 }
2206
2207
VisitFPDataProcessing2Source(const Instruction * instr)2208 void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
2209 AssertSupportedFPCR();
2210
2211 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2212 SimVRegister& rd = vreg(instr->Rd());
2213 SimVRegister& rn = vreg(instr->Rn());
2214 SimVRegister& rm = vreg(instr->Rm());
2215
2216 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2217 case FADD_s:
2218 case FADD_d: fadd(vform, rd, rn, rm); break;
2219 case FSUB_s:
2220 case FSUB_d: fsub(vform, rd, rn, rm); break;
2221 case FMUL_s:
2222 case FMUL_d: fmul(vform, rd, rn, rm); break;
2223 case FNMUL_s:
2224 case FNMUL_d: fnmul(vform, rd, rn, rm); break;
2225 case FDIV_s:
2226 case FDIV_d: fdiv(vform, rd, rn, rm); break;
2227 case FMAX_s:
2228 case FMAX_d: fmax(vform, rd, rn, rm); break;
2229 case FMIN_s:
2230 case FMIN_d: fmin(vform, rd, rn, rm); break;
2231 case FMAXNM_s:
2232 case FMAXNM_d: fmaxnm(vform, rd, rn, rm); break;
2233 case FMINNM_s:
2234 case FMINNM_d: fminnm(vform, rd, rn, rm); break;
2235 default:
2236 VIXL_UNREACHABLE();
2237 }
2238 }
2239
2240
VisitFPDataProcessing3Source(const Instruction * instr)2241 void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
2242 AssertSupportedFPCR();
2243
2244 unsigned fd = instr->Rd();
2245 unsigned fn = instr->Rn();
2246 unsigned fm = instr->Rm();
2247 unsigned fa = instr->Ra();
2248
2249 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2250 // fd = fa +/- (fn * fm)
2251 case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break;
2252 case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break;
2253 case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break;
2254 case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break;
2255 // Negated variants of the above.
2256 case FNMADD_s:
2257 set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm)));
2258 break;
2259 case FNMSUB_s:
2260 set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm)));
2261 break;
2262 case FNMADD_d:
2263 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2264 break;
2265 case FNMSUB_d:
2266 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2267 break;
2268 default: VIXL_UNIMPLEMENTED();
2269 }
2270 }
2271
2272
FPProcessNaNs(const Instruction * instr)2273 bool Simulator::FPProcessNaNs(const Instruction* instr) {
2274 unsigned fd = instr->Rd();
2275 unsigned fn = instr->Rn();
2276 unsigned fm = instr->Rm();
2277 bool done = false;
2278
2279 if (instr->Mask(FP64) == FP64) {
2280 double result = FPProcessNaNs(dreg(fn), dreg(fm));
2281 if (std::isnan(result)) {
2282 set_dreg(fd, result);
2283 done = true;
2284 }
2285 } else {
2286 float result = FPProcessNaNs(sreg(fn), sreg(fm));
2287 if (std::isnan(result)) {
2288 set_sreg(fd, result);
2289 done = true;
2290 }
2291 }
2292
2293 return done;
2294 }
2295
2296
SysOp_W(int op,int64_t val)2297 void Simulator::SysOp_W(int op, int64_t val) {
2298 switch (op) {
2299 case IVAU:
2300 case CVAC:
2301 case CVAU:
2302 case CIVAC: {
2303 // Perform a dummy memory access to ensure that we have read access
2304 // to the specified address.
2305 volatile uint8_t y = Memory::Read<uint8_t>(val);
2306 USE(y);
2307 // TODO: Implement "case ZVA:".
2308 break;
2309 }
2310 default:
2311 VIXL_UNIMPLEMENTED();
2312 }
2313 }
2314
2315
VisitSystem(const Instruction * instr)2316 void Simulator::VisitSystem(const Instruction* instr) {
2317 // Some system instructions hijack their Op and Cp fields to represent a
2318 // range of immediates instead of indicating a different instruction. This
2319 // makes the decoding tricky.
2320 if (instr->Mask(SystemExclusiveMonitorFMask) == SystemExclusiveMonitorFixed) {
2321 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
2322 switch (instr->Mask(SystemExclusiveMonitorMask)) {
2323 case CLREX: {
2324 PrintExclusiveAccessWarning();
2325 ClearLocalMonitor();
2326 break;
2327 }
2328 }
2329 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2330 switch (instr->Mask(SystemSysRegMask)) {
2331 case MRS: {
2332 switch (instr->ImmSystemRegister()) {
2333 case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break;
2334 case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break;
2335 default: VIXL_UNIMPLEMENTED();
2336 }
2337 break;
2338 }
2339 case MSR: {
2340 switch (instr->ImmSystemRegister()) {
2341 case NZCV:
2342 nzcv().SetRawValue(wreg(instr->Rt()));
2343 LogSystemRegister(NZCV);
2344 break;
2345 case FPCR:
2346 fpcr().SetRawValue(wreg(instr->Rt()));
2347 LogSystemRegister(FPCR);
2348 break;
2349 default: VIXL_UNIMPLEMENTED();
2350 }
2351 break;
2352 }
2353 }
2354 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
2355 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
2356 switch (instr->ImmHint()) {
2357 case NOP: break;
2358 default: VIXL_UNIMPLEMENTED();
2359 }
2360 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2361 __sync_synchronize();
2362 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
2363 switch (instr->Mask(SystemSysMask)) {
2364 case SYS: SysOp_W(instr->SysOp(), xreg(instr->Rt())); break;
2365 default: VIXL_UNIMPLEMENTED();
2366 }
2367 } else {
2368 VIXL_UNIMPLEMENTED();
2369 }
2370 }
2371
2372
VisitException(const Instruction * instr)2373 void Simulator::VisitException(const Instruction* instr) {
2374 switch (instr->Mask(ExceptionMask)) {
2375 case HLT:
2376 switch (instr->ImmException()) {
2377 case kUnreachableOpcode:
2378 DoUnreachable(instr);
2379 return;
2380 case kTraceOpcode:
2381 DoTrace(instr);
2382 return;
2383 case kLogOpcode:
2384 DoLog(instr);
2385 return;
2386 case kPrintfOpcode:
2387 DoPrintf(instr);
2388 return;
2389 default:
2390 HostBreakpoint();
2391 return;
2392 }
2393 case BRK:
2394 HostBreakpoint();
2395 return;
2396 default:
2397 VIXL_UNIMPLEMENTED();
2398 }
2399 }
2400
2401
VisitCrypto2RegSHA(const Instruction * instr)2402 void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
2403 VisitUnimplemented(instr);
2404 }
2405
2406
VisitCrypto3RegSHA(const Instruction * instr)2407 void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
2408 VisitUnimplemented(instr);
2409 }
2410
2411
VisitCryptoAES(const Instruction * instr)2412 void Simulator::VisitCryptoAES(const Instruction* instr) {
2413 VisitUnimplemented(instr);
2414 }
2415
2416
VisitNEON2RegMisc(const Instruction * instr)2417 void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
2418 NEONFormatDecoder nfd(instr);
2419 VectorFormat vf = nfd.GetVectorFormat();
2420
2421 static const NEONFormatMap map_lp = {
2422 {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}
2423 };
2424 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
2425
2426 static const NEONFormatMap map_fcvtl = {
2427 {22}, {NF_4S, NF_2D}
2428 };
2429 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
2430
2431 static const NEONFormatMap map_fcvtn = {
2432 {22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S}
2433 };
2434 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
2435
2436 SimVRegister& rd = vreg(instr->Rd());
2437 SimVRegister& rn = vreg(instr->Rn());
2438
2439 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
2440 // These instructions all use a two bit size field, except NOT and RBIT,
2441 // which use the field to encode the operation.
2442 switch (instr->Mask(NEON2RegMiscMask)) {
2443 case NEON_REV64: rev64(vf, rd, rn); break;
2444 case NEON_REV32: rev32(vf, rd, rn); break;
2445 case NEON_REV16: rev16(vf, rd, rn); break;
2446 case NEON_SUQADD: suqadd(vf, rd, rn); break;
2447 case NEON_USQADD: usqadd(vf, rd, rn); break;
2448 case NEON_CLS: cls(vf, rd, rn); break;
2449 case NEON_CLZ: clz(vf, rd, rn); break;
2450 case NEON_CNT: cnt(vf, rd, rn); break;
2451 case NEON_SQABS: abs(vf, rd, rn).SignedSaturate(vf); break;
2452 case NEON_SQNEG: neg(vf, rd, rn).SignedSaturate(vf); break;
2453 case NEON_CMGT_zero: cmp(vf, rd, rn, 0, gt); break;
2454 case NEON_CMGE_zero: cmp(vf, rd, rn, 0, ge); break;
2455 case NEON_CMEQ_zero: cmp(vf, rd, rn, 0, eq); break;
2456 case NEON_CMLE_zero: cmp(vf, rd, rn, 0, le); break;
2457 case NEON_CMLT_zero: cmp(vf, rd, rn, 0, lt); break;
2458 case NEON_ABS: abs(vf, rd, rn); break;
2459 case NEON_NEG: neg(vf, rd, rn); break;
2460 case NEON_SADDLP: saddlp(vf_lp, rd, rn); break;
2461 case NEON_UADDLP: uaddlp(vf_lp, rd, rn); break;
2462 case NEON_SADALP: sadalp(vf_lp, rd, rn); break;
2463 case NEON_UADALP: uadalp(vf_lp, rd, rn); break;
2464 case NEON_RBIT_NOT:
2465 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
2466 switch (instr->FPType()) {
2467 case 0: not_(vf, rd, rn); break;
2468 case 1: rbit(vf, rd, rn);; break;
2469 default:
2470 VIXL_UNIMPLEMENTED();
2471 }
2472 break;
2473 }
2474 } else {
2475 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
2476 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
2477 bool inexact_exception = false;
2478
2479 // These instructions all use a one bit size field, except XTN, SQXTUN,
2480 // SHLL, SQXTN and UQXTN, which use a two bit size field.
2481 switch (instr->Mask(NEON2RegMiscFPMask)) {
2482 case NEON_FABS: fabs_(fpf, rd, rn); return;
2483 case NEON_FNEG: fneg(fpf, rd, rn); return;
2484 case NEON_FSQRT: fsqrt(fpf, rd, rn); return;
2485 case NEON_FCVTL:
2486 if (instr->Mask(NEON_Q)) {
2487 fcvtl2(vf_fcvtl, rd, rn);
2488 } else {
2489 fcvtl(vf_fcvtl, rd, rn);
2490 }
2491 return;
2492 case NEON_FCVTN:
2493 if (instr->Mask(NEON_Q)) {
2494 fcvtn2(vf_fcvtn, rd, rn);
2495 } else {
2496 fcvtn(vf_fcvtn, rd, rn);
2497 }
2498 return;
2499 case NEON_FCVTXN:
2500 if (instr->Mask(NEON_Q)) {
2501 fcvtxn2(vf_fcvtn, rd, rn);
2502 } else {
2503 fcvtxn(vf_fcvtn, rd, rn);
2504 }
2505 return;
2506
2507 // The following instructions break from the switch statement, rather
2508 // than return.
2509 case NEON_FRINTI: break; // Use FPCR rounding mode.
2510 case NEON_FRINTX: inexact_exception = true; break;
2511 case NEON_FRINTA: fpcr_rounding = FPTieAway; break;
2512 case NEON_FRINTM: fpcr_rounding = FPNegativeInfinity; break;
2513 case NEON_FRINTN: fpcr_rounding = FPTieEven; break;
2514 case NEON_FRINTP: fpcr_rounding = FPPositiveInfinity; break;
2515 case NEON_FRINTZ: fpcr_rounding = FPZero; break;
2516
2517 case NEON_FCVTNS: fcvts(fpf, rd, rn, FPTieEven); return;
2518 case NEON_FCVTNU: fcvtu(fpf, rd, rn, FPTieEven); return;
2519 case NEON_FCVTPS: fcvts(fpf, rd, rn, FPPositiveInfinity); return;
2520 case NEON_FCVTPU: fcvtu(fpf, rd, rn, FPPositiveInfinity); return;
2521 case NEON_FCVTMS: fcvts(fpf, rd, rn, FPNegativeInfinity); return;
2522 case NEON_FCVTMU: fcvtu(fpf, rd, rn, FPNegativeInfinity); return;
2523 case NEON_FCVTZS: fcvts(fpf, rd, rn, FPZero); return;
2524 case NEON_FCVTZU: fcvtu(fpf, rd, rn, FPZero); return;
2525 case NEON_FCVTAS: fcvts(fpf, rd, rn, FPTieAway); return;
2526 case NEON_FCVTAU: fcvtu(fpf, rd, rn, FPTieAway); return;
2527 case NEON_SCVTF: scvtf(fpf, rd, rn, 0, fpcr_rounding); return;
2528 case NEON_UCVTF: ucvtf(fpf, rd, rn, 0, fpcr_rounding); return;
2529 case NEON_URSQRTE: ursqrte(fpf, rd, rn); return;
2530 case NEON_URECPE: urecpe(fpf, rd, rn); return;
2531 case NEON_FRSQRTE: frsqrte(fpf, rd, rn); return;
2532 case NEON_FRECPE: frecpe(fpf, rd, rn, fpcr_rounding); return;
2533 case NEON_FCMGT_zero: fcmp_zero(fpf, rd, rn, gt); return;
2534 case NEON_FCMGE_zero: fcmp_zero(fpf, rd, rn, ge); return;
2535 case NEON_FCMEQ_zero: fcmp_zero(fpf, rd, rn, eq); return;
2536 case NEON_FCMLE_zero: fcmp_zero(fpf, rd, rn, le); return;
2537 case NEON_FCMLT_zero: fcmp_zero(fpf, rd, rn, lt); return;
2538 default:
2539 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
2540 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
2541 switch (instr->Mask(NEON2RegMiscMask)) {
2542 case NEON_XTN: xtn(vf, rd, rn); return;
2543 case NEON_SQXTN: sqxtn(vf, rd, rn); return;
2544 case NEON_UQXTN: uqxtn(vf, rd, rn); return;
2545 case NEON_SQXTUN: sqxtun(vf, rd, rn); return;
2546 case NEON_SHLL:
2547 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
2548 if (instr->Mask(NEON_Q)) {
2549 shll2(vf, rd, rn);
2550 } else {
2551 shll(vf, rd, rn);
2552 }
2553 return;
2554 default:
2555 VIXL_UNIMPLEMENTED();
2556 }
2557 } else {
2558 VIXL_UNIMPLEMENTED();
2559 }
2560 }
2561
2562 // Only FRINT* instructions fall through the switch above.
2563 frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
2564 }
2565 }
2566
2567
VisitNEON3Same(const Instruction * instr)2568 void Simulator::VisitNEON3Same(const Instruction* instr) {
2569 NEONFormatDecoder nfd(instr);
2570 SimVRegister& rd = vreg(instr->Rd());
2571 SimVRegister& rn = vreg(instr->Rn());
2572 SimVRegister& rm = vreg(instr->Rm());
2573
2574 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
2575 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
2576 switch (instr->Mask(NEON3SameLogicalMask)) {
2577 case NEON_AND: and_(vf, rd, rn, rm); break;
2578 case NEON_ORR: orr(vf, rd, rn, rm); break;
2579 case NEON_ORN: orn(vf, rd, rn, rm); break;
2580 case NEON_EOR: eor(vf, rd, rn, rm); break;
2581 case NEON_BIC: bic(vf, rd, rn, rm); break;
2582 case NEON_BIF: bif(vf, rd, rn, rm); break;
2583 case NEON_BIT: bit(vf, rd, rn, rm); break;
2584 case NEON_BSL: bsl(vf, rd, rn, rm); break;
2585 default:
2586 VIXL_UNIMPLEMENTED();
2587 }
2588 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
2589 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
2590 switch (instr->Mask(NEON3SameFPMask)) {
2591 case NEON_FADD: fadd(vf, rd, rn, rm); break;
2592 case NEON_FSUB: fsub(vf, rd, rn, rm); break;
2593 case NEON_FMUL: fmul(vf, rd, rn, rm); break;
2594 case NEON_FDIV: fdiv(vf, rd, rn, rm); break;
2595 case NEON_FMAX: fmax(vf, rd, rn, rm); break;
2596 case NEON_FMIN: fmin(vf, rd, rn, rm); break;
2597 case NEON_FMAXNM: fmaxnm(vf, rd, rn, rm); break;
2598 case NEON_FMINNM: fminnm(vf, rd, rn, rm); break;
2599 case NEON_FMLA: fmla(vf, rd, rn, rm); break;
2600 case NEON_FMLS: fmls(vf, rd, rn, rm); break;
2601 case NEON_FMULX: fmulx(vf, rd, rn, rm); break;
2602 case NEON_FACGE: fabscmp(vf, rd, rn, rm, ge); break;
2603 case NEON_FACGT: fabscmp(vf, rd, rn, rm, gt); break;
2604 case NEON_FCMEQ: fcmp(vf, rd, rn, rm, eq); break;
2605 case NEON_FCMGE: fcmp(vf, rd, rn, rm, ge); break;
2606 case NEON_FCMGT: fcmp(vf, rd, rn, rm, gt); break;
2607 case NEON_FRECPS: frecps(vf, rd, rn, rm); break;
2608 case NEON_FRSQRTS: frsqrts(vf, rd, rn, rm); break;
2609 case NEON_FABD: fabd(vf, rd, rn, rm); break;
2610 case NEON_FADDP: faddp(vf, rd, rn, rm); break;
2611 case NEON_FMAXP: fmaxp(vf, rd, rn, rm); break;
2612 case NEON_FMAXNMP: fmaxnmp(vf, rd, rn, rm); break;
2613 case NEON_FMINP: fminp(vf, rd, rn, rm); break;
2614 case NEON_FMINNMP: fminnmp(vf, rd, rn, rm); break;
2615 default:
2616 VIXL_UNIMPLEMENTED();
2617 }
2618 } else {
2619 VectorFormat vf = nfd.GetVectorFormat();
2620 switch (instr->Mask(NEON3SameMask)) {
2621 case NEON_ADD: add(vf, rd, rn, rm); break;
2622 case NEON_ADDP: addp(vf, rd, rn, rm); break;
2623 case NEON_CMEQ: cmp(vf, rd, rn, rm, eq); break;
2624 case NEON_CMGE: cmp(vf, rd, rn, rm, ge); break;
2625 case NEON_CMGT: cmp(vf, rd, rn, rm, gt); break;
2626 case NEON_CMHI: cmp(vf, rd, rn, rm, hi); break;
2627 case NEON_CMHS: cmp(vf, rd, rn, rm, hs); break;
2628 case NEON_CMTST: cmptst(vf, rd, rn, rm); break;
2629 case NEON_MLS: mls(vf, rd, rn, rm); break;
2630 case NEON_MLA: mla(vf, rd, rn, rm); break;
2631 case NEON_MUL: mul(vf, rd, rn, rm); break;
2632 case NEON_PMUL: pmul(vf, rd, rn, rm); break;
2633 case NEON_SMAX: smax(vf, rd, rn, rm); break;
2634 case NEON_SMAXP: smaxp(vf, rd, rn, rm); break;
2635 case NEON_SMIN: smin(vf, rd, rn, rm); break;
2636 case NEON_SMINP: sminp(vf, rd, rn, rm); break;
2637 case NEON_SUB: sub(vf, rd, rn, rm); break;
2638 case NEON_UMAX: umax(vf, rd, rn, rm); break;
2639 case NEON_UMAXP: umaxp(vf, rd, rn, rm); break;
2640 case NEON_UMIN: umin(vf, rd, rn, rm); break;
2641 case NEON_UMINP: uminp(vf, rd, rn, rm); break;
2642 case NEON_SSHL: sshl(vf, rd, rn, rm); break;
2643 case NEON_USHL: ushl(vf, rd, rn, rm); break;
2644 case NEON_SABD: absdiff(vf, rd, rn, rm, true); break;
2645 case NEON_UABD: absdiff(vf, rd, rn, rm, false); break;
2646 case NEON_SABA: saba(vf, rd, rn, rm); break;
2647 case NEON_UABA: uaba(vf, rd, rn, rm); break;
2648 case NEON_UQADD: add(vf, rd, rn, rm).UnsignedSaturate(vf); break;
2649 case NEON_SQADD: add(vf, rd, rn, rm).SignedSaturate(vf); break;
2650 case NEON_UQSUB: sub(vf, rd, rn, rm).UnsignedSaturate(vf); break;
2651 case NEON_SQSUB: sub(vf, rd, rn, rm).SignedSaturate(vf); break;
2652 case NEON_SQDMULH: sqdmulh(vf, rd, rn, rm); break;
2653 case NEON_SQRDMULH: sqrdmulh(vf, rd, rn, rm); break;
2654 case NEON_UQSHL: ushl(vf, rd, rn, rm).UnsignedSaturate(vf); break;
2655 case NEON_SQSHL: sshl(vf, rd, rn, rm).SignedSaturate(vf); break;
2656 case NEON_URSHL: ushl(vf, rd, rn, rm).Round(vf); break;
2657 case NEON_SRSHL: sshl(vf, rd, rn, rm).Round(vf); break;
2658 case NEON_UQRSHL:
2659 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
2660 break;
2661 case NEON_SQRSHL:
2662 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
2663 break;
2664 case NEON_UHADD:
2665 add(vf, rd, rn, rm).Uhalve(vf);
2666 break;
2667 case NEON_URHADD:
2668 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
2669 break;
2670 case NEON_SHADD:
2671 add(vf, rd, rn, rm).Halve(vf);
2672 break;
2673 case NEON_SRHADD:
2674 add(vf, rd, rn, rm).Halve(vf).Round(vf);
2675 break;
2676 case NEON_UHSUB:
2677 sub(vf, rd, rn, rm).Uhalve(vf);
2678 break;
2679 case NEON_SHSUB:
2680 sub(vf, rd, rn, rm).Halve(vf);
2681 break;
2682 default:
2683 VIXL_UNIMPLEMENTED();
2684 }
2685 }
2686 }
2687
2688
VisitNEON3Different(const Instruction * instr)2689 void Simulator::VisitNEON3Different(const Instruction* instr) {
2690 NEONFormatDecoder nfd(instr);
2691 VectorFormat vf = nfd.GetVectorFormat();
2692 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
2693
2694 SimVRegister& rd = vreg(instr->Rd());
2695 SimVRegister& rn = vreg(instr->Rn());
2696 SimVRegister& rm = vreg(instr->Rm());
2697
2698 switch (instr->Mask(NEON3DifferentMask)) {
2699 case NEON_PMULL: pmull(vf_l, rd, rn, rm); break;
2700 case NEON_PMULL2: pmull2(vf_l, rd, rn, rm); break;
2701 case NEON_UADDL: uaddl(vf_l, rd, rn, rm); break;
2702 case NEON_UADDL2: uaddl2(vf_l, rd, rn, rm); break;
2703 case NEON_SADDL: saddl(vf_l, rd, rn, rm); break;
2704 case NEON_SADDL2: saddl2(vf_l, rd, rn, rm); break;
2705 case NEON_USUBL: usubl(vf_l, rd, rn, rm); break;
2706 case NEON_USUBL2: usubl2(vf_l, rd, rn, rm); break;
2707 case NEON_SSUBL: ssubl(vf_l, rd, rn, rm); break;
2708 case NEON_SSUBL2: ssubl2(vf_l, rd, rn, rm); break;
2709 case NEON_SABAL: sabal(vf_l, rd, rn, rm); break;
2710 case NEON_SABAL2: sabal2(vf_l, rd, rn, rm); break;
2711 case NEON_UABAL: uabal(vf_l, rd, rn, rm); break;
2712 case NEON_UABAL2: uabal2(vf_l, rd, rn, rm); break;
2713 case NEON_SABDL: sabdl(vf_l, rd, rn, rm); break;
2714 case NEON_SABDL2: sabdl2(vf_l, rd, rn, rm); break;
2715 case NEON_UABDL: uabdl(vf_l, rd, rn, rm); break;
2716 case NEON_UABDL2: uabdl2(vf_l, rd, rn, rm); break;
2717 case NEON_SMLAL: smlal(vf_l, rd, rn, rm); break;
2718 case NEON_SMLAL2: smlal2(vf_l, rd, rn, rm); break;
2719 case NEON_UMLAL: umlal(vf_l, rd, rn, rm); break;
2720 case NEON_UMLAL2: umlal2(vf_l, rd, rn, rm); break;
2721 case NEON_SMLSL: smlsl(vf_l, rd, rn, rm); break;
2722 case NEON_SMLSL2: smlsl2(vf_l, rd, rn, rm); break;
2723 case NEON_UMLSL: umlsl(vf_l, rd, rn, rm); break;
2724 case NEON_UMLSL2: umlsl2(vf_l, rd, rn, rm); break;
2725 case NEON_SMULL: smull(vf_l, rd, rn, rm); break;
2726 case NEON_SMULL2: smull2(vf_l, rd, rn, rm); break;
2727 case NEON_UMULL: umull(vf_l, rd, rn, rm); break;
2728 case NEON_UMULL2: umull2(vf_l, rd, rn, rm); break;
2729 case NEON_SQDMLAL: sqdmlal(vf_l, rd, rn, rm); break;
2730 case NEON_SQDMLAL2: sqdmlal2(vf_l, rd, rn, rm); break;
2731 case NEON_SQDMLSL: sqdmlsl(vf_l, rd, rn, rm); break;
2732 case NEON_SQDMLSL2: sqdmlsl2(vf_l, rd, rn, rm); break;
2733 case NEON_SQDMULL: sqdmull(vf_l, rd, rn, rm); break;
2734 case NEON_SQDMULL2: sqdmull2(vf_l, rd, rn, rm); break;
2735 case NEON_UADDW: uaddw(vf_l, rd, rn, rm); break;
2736 case NEON_UADDW2: uaddw2(vf_l, rd, rn, rm); break;
2737 case NEON_SADDW: saddw(vf_l, rd, rn, rm); break;
2738 case NEON_SADDW2: saddw2(vf_l, rd, rn, rm); break;
2739 case NEON_USUBW: usubw(vf_l, rd, rn, rm); break;
2740 case NEON_USUBW2: usubw2(vf_l, rd, rn, rm); break;
2741 case NEON_SSUBW: ssubw(vf_l, rd, rn, rm); break;
2742 case NEON_SSUBW2: ssubw2(vf_l, rd, rn, rm); break;
2743 case NEON_ADDHN: addhn(vf, rd, rn, rm); break;
2744 case NEON_ADDHN2: addhn2(vf, rd, rn, rm); break;
2745 case NEON_RADDHN: raddhn(vf, rd, rn, rm); break;
2746 case NEON_RADDHN2: raddhn2(vf, rd, rn, rm); break;
2747 case NEON_SUBHN: subhn(vf, rd, rn, rm); break;
2748 case NEON_SUBHN2: subhn2(vf, rd, rn, rm); break;
2749 case NEON_RSUBHN: rsubhn(vf, rd, rn, rm); break;
2750 case NEON_RSUBHN2: rsubhn2(vf, rd, rn, rm); break;
2751 default:
2752 VIXL_UNIMPLEMENTED();
2753 }
2754 }
2755
2756
VisitNEONAcrossLanes(const Instruction * instr)2757 void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
2758 NEONFormatDecoder nfd(instr);
2759
2760 SimVRegister& rd = vreg(instr->Rd());
2761 SimVRegister& rn = vreg(instr->Rn());
2762
2763 // The input operand's VectorFormat is passed for these instructions.
2764 if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
2765 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
2766
2767 switch (instr->Mask(NEONAcrossLanesFPMask)) {
2768 case NEON_FMAXV: fmaxv(vf, rd, rn); break;
2769 case NEON_FMINV: fminv(vf, rd, rn); break;
2770 case NEON_FMAXNMV: fmaxnmv(vf, rd, rn); break;
2771 case NEON_FMINNMV: fminnmv(vf, rd, rn); break;
2772 default:
2773 VIXL_UNIMPLEMENTED();
2774 }
2775 } else {
2776 VectorFormat vf = nfd.GetVectorFormat();
2777
2778 switch (instr->Mask(NEONAcrossLanesMask)) {
2779 case NEON_ADDV: addv(vf, rd, rn); break;
2780 case NEON_SMAXV: smaxv(vf, rd, rn); break;
2781 case NEON_SMINV: sminv(vf, rd, rn); break;
2782 case NEON_UMAXV: umaxv(vf, rd, rn); break;
2783 case NEON_UMINV: uminv(vf, rd, rn); break;
2784 case NEON_SADDLV: saddlv(vf, rd, rn); break;
2785 case NEON_UADDLV: uaddlv(vf, rd, rn); break;
2786 default:
2787 VIXL_UNIMPLEMENTED();
2788 }
2789 }
2790 }
2791
2792
VisitNEONByIndexedElement(const Instruction * instr)2793 void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
2794 NEONFormatDecoder nfd(instr);
2795 VectorFormat vf_r = nfd.GetVectorFormat();
2796 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
2797
2798 SimVRegister& rd = vreg(instr->Rd());
2799 SimVRegister& rn = vreg(instr->Rn());
2800
2801 ByElementOp Op = NULL;
2802
2803 int rm_reg = instr->Rm();
2804 int index = (instr->NEONH() << 1) | instr->NEONL();
2805 if (instr->NEONSize() == 1) {
2806 rm_reg &= 0xf;
2807 index = (index << 1) | instr->NEONM();
2808 }
2809
2810 switch (instr->Mask(NEONByIndexedElementMask)) {
2811 case NEON_MUL_byelement: Op = &Simulator::mul; vf = vf_r; break;
2812 case NEON_MLA_byelement: Op = &Simulator::mla; vf = vf_r; break;
2813 case NEON_MLS_byelement: Op = &Simulator::mls; vf = vf_r; break;
2814 case NEON_SQDMULH_byelement: Op = &Simulator::sqdmulh; vf = vf_r; break;
2815 case NEON_SQRDMULH_byelement: Op = &Simulator::sqrdmulh; vf = vf_r; break;
2816 case NEON_SMULL_byelement:
2817 if (instr->Mask(NEON_Q)) {
2818 Op = &Simulator::smull2;
2819 } else {
2820 Op = &Simulator::smull;
2821 }
2822 break;
2823 case NEON_UMULL_byelement:
2824 if (instr->Mask(NEON_Q)) {
2825 Op = &Simulator::umull2;
2826 } else {
2827 Op = &Simulator::umull;
2828 }
2829 break;
2830 case NEON_SMLAL_byelement:
2831 if (instr->Mask(NEON_Q)) {
2832 Op = &Simulator::smlal2;
2833 } else {
2834 Op = &Simulator::smlal;
2835 }
2836 break;
2837 case NEON_UMLAL_byelement:
2838 if (instr->Mask(NEON_Q)) {
2839 Op = &Simulator::umlal2;
2840 } else {
2841 Op = &Simulator::umlal;
2842 }
2843 break;
2844 case NEON_SMLSL_byelement:
2845 if (instr->Mask(NEON_Q)) {
2846 Op = &Simulator::smlsl2;
2847 } else {
2848 Op = &Simulator::smlsl;
2849 }
2850 break;
2851 case NEON_UMLSL_byelement:
2852 if (instr->Mask(NEON_Q)) {
2853 Op = &Simulator::umlsl2;
2854 } else {
2855 Op = &Simulator::umlsl;
2856 }
2857 break;
2858 case NEON_SQDMULL_byelement:
2859 if (instr->Mask(NEON_Q)) {
2860 Op = &Simulator::sqdmull2;
2861 } else {
2862 Op = &Simulator::sqdmull;
2863 }
2864 break;
2865 case NEON_SQDMLAL_byelement:
2866 if (instr->Mask(NEON_Q)) {
2867 Op = &Simulator::sqdmlal2;
2868 } else {
2869 Op = &Simulator::sqdmlal;
2870 }
2871 break;
2872 case NEON_SQDMLSL_byelement:
2873 if (instr->Mask(NEON_Q)) {
2874 Op = &Simulator::sqdmlsl2;
2875 } else {
2876 Op = &Simulator::sqdmlsl;
2877 }
2878 break;
2879 default:
2880 index = instr->NEONH();
2881 if ((instr->FPType() & 1) == 0) {
2882 index = (index << 1) | instr->NEONL();
2883 }
2884
2885 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
2886
2887 switch (instr->Mask(NEONByIndexedElementFPMask)) {
2888 case NEON_FMUL_byelement: Op = &Simulator::fmul; break;
2889 case NEON_FMLA_byelement: Op = &Simulator::fmla; break;
2890 case NEON_FMLS_byelement: Op = &Simulator::fmls; break;
2891 case NEON_FMULX_byelement: Op = &Simulator::fmulx; break;
2892 default: VIXL_UNIMPLEMENTED();
2893 }
2894 }
2895
2896 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
2897 }
2898
2899
VisitNEONCopy(const Instruction * instr)2900 void Simulator::VisitNEONCopy(const Instruction* instr) {
2901 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
2902 VectorFormat vf = nfd.GetVectorFormat();
2903
2904 SimVRegister& rd = vreg(instr->Rd());
2905 SimVRegister& rn = vreg(instr->Rn());
2906 int imm5 = instr->ImmNEON5();
2907 int tz = CountTrailingZeros(imm5, 32);
2908 int reg_index = imm5 >> (tz + 1);
2909
2910 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
2911 int imm4 = instr->ImmNEON4();
2912 int rn_index = imm4 >> tz;
2913 ins_element(vf, rd, reg_index, rn, rn_index);
2914 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
2915 ins_immediate(vf, rd, reg_index, xreg(instr->Rn()));
2916 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
2917 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
2918 value &= MaxUintFromFormat(vf);
2919 set_xreg(instr->Rd(), value);
2920 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
2921 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
2922 if (instr->NEONQ()) {
2923 set_xreg(instr->Rd(), value);
2924 } else {
2925 set_wreg(instr->Rd(), (int32_t)value);
2926 }
2927 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
2928 dup_element(vf, rd, rn, reg_index);
2929 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
2930 dup_immediate(vf, rd, xreg(instr->Rn()));
2931 } else {
2932 VIXL_UNIMPLEMENTED();
2933 }
2934 }
2935
2936
VisitNEONExtract(const Instruction * instr)2937 void Simulator::VisitNEONExtract(const Instruction* instr) {
2938 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
2939 VectorFormat vf = nfd.GetVectorFormat();
2940 SimVRegister& rd = vreg(instr->Rd());
2941 SimVRegister& rn = vreg(instr->Rn());
2942 SimVRegister& rm = vreg(instr->Rm());
2943 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
2944 int index = instr->ImmNEONExt();
2945 ext(vf, rd, rn, rm, index);
2946 } else {
2947 VIXL_UNIMPLEMENTED();
2948 }
2949 }
2950
2951
NEONLoadStoreMultiStructHelper(const Instruction * instr,AddrMode addr_mode)2952 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
2953 AddrMode addr_mode) {
2954 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
2955 VectorFormat vf = nfd.GetVectorFormat();
2956
2957 uint64_t addr_base = xreg(instr->Rn(), Reg31IsStackPointer);
2958 int reg_size = RegisterSizeInBytesFromFormat(vf);
2959
2960 int reg[4];
2961 uint64_t addr[4];
2962 for (int i = 0; i < 4; i++) {
2963 reg[i] = (instr->Rt() + i) % kNumberOfVRegisters;
2964 addr[i] = addr_base + (i * reg_size);
2965 }
2966 int count = 1;
2967 bool log_read = true;
2968
2969 Instr itype = instr->Mask(NEONLoadStoreMultiStructMask);
2970 if (((itype == NEON_LD1_1v) || (itype == NEON_LD1_2v) ||
2971 (itype == NEON_LD1_3v) || (itype == NEON_LD1_4v) ||
2972 (itype == NEON_ST1_1v) || (itype == NEON_ST1_2v) ||
2973 (itype == NEON_ST1_3v) || (itype == NEON_ST1_4v)) &&
2974 (instr->Bits(20, 16) != 0)) {
2975 VIXL_UNREACHABLE();
2976 }
2977
2978 // We use the PostIndex mask here, as it works in this case for both Offset
2979 // and PostIndex addressing.
2980 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
2981 case NEON_LD1_4v:
2982 case NEON_LD1_4v_post: ld1(vf, vreg(reg[3]), addr[3]); count++;
2983 VIXL_FALLTHROUGH();
2984 case NEON_LD1_3v:
2985 case NEON_LD1_3v_post: ld1(vf, vreg(reg[2]), addr[2]); count++;
2986 VIXL_FALLTHROUGH();
2987 case NEON_LD1_2v:
2988 case NEON_LD1_2v_post: ld1(vf, vreg(reg[1]), addr[1]); count++;
2989 VIXL_FALLTHROUGH();
2990 case NEON_LD1_1v:
2991 case NEON_LD1_1v_post:
2992 ld1(vf, vreg(reg[0]), addr[0]);
2993 log_read = true;
2994 break;
2995 case NEON_ST1_4v:
2996 case NEON_ST1_4v_post: st1(vf, vreg(reg[3]), addr[3]); count++;
2997 VIXL_FALLTHROUGH();
2998 case NEON_ST1_3v:
2999 case NEON_ST1_3v_post: st1(vf, vreg(reg[2]), addr[2]); count++;
3000 VIXL_FALLTHROUGH();
3001 case NEON_ST1_2v:
3002 case NEON_ST1_2v_post: st1(vf, vreg(reg[1]), addr[1]); count++;
3003 VIXL_FALLTHROUGH();
3004 case NEON_ST1_1v:
3005 case NEON_ST1_1v_post:
3006 st1(vf, vreg(reg[0]), addr[0]);
3007 log_read = false;
3008 break;
3009 case NEON_LD2_post:
3010 case NEON_LD2:
3011 ld2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
3012 count = 2;
3013 break;
3014 case NEON_ST2:
3015 case NEON_ST2_post:
3016 st2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
3017 count = 2;
3018 break;
3019 case NEON_LD3_post:
3020 case NEON_LD3:
3021 ld3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
3022 count = 3;
3023 break;
3024 case NEON_ST3:
3025 case NEON_ST3_post:
3026 st3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
3027 count = 3;
3028 break;
3029 case NEON_ST4:
3030 case NEON_ST4_post:
3031 st4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]),
3032 addr[0]);
3033 count = 4;
3034 break;
3035 case NEON_LD4_post:
3036 case NEON_LD4:
3037 ld4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]),
3038 addr[0]);
3039 count = 4;
3040 break;
3041 default: VIXL_UNIMPLEMENTED();
3042 }
3043
3044 // Explicitly log the register update whilst we have type information.
3045 for (int i = 0; i < count; i++) {
3046 // For de-interleaving loads, only print the base address.
3047 int lane_size = LaneSizeInBytesFromFormat(vf);
3048 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
3049 GetPrintRegisterFormatForSize(reg_size, lane_size));
3050 if (log_read) {
3051 LogVRead(addr_base, reg[i], format);
3052 } else {
3053 LogVWrite(addr_base, reg[i], format);
3054 }
3055 }
3056
3057 if (addr_mode == PostIndex) {
3058 int rm = instr->Rm();
3059 // The immediate post index addressing mode is indicated by rm = 31.
3060 // The immediate is implied by the number of vector registers used.
3061 addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
3062 : xreg(rm);
3063 set_xreg(instr->Rn(), addr_base);
3064 } else {
3065 VIXL_ASSERT(addr_mode == Offset);
3066 }
3067 }
3068
3069
VisitNEONLoadStoreMultiStruct(const Instruction * instr)3070 void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
3071 NEONLoadStoreMultiStructHelper(instr, Offset);
3072 }
3073
3074
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)3075 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
3076 const Instruction* instr) {
3077 NEONLoadStoreMultiStructHelper(instr, PostIndex);
3078 }
3079
3080
NEONLoadStoreSingleStructHelper(const Instruction * instr,AddrMode addr_mode)3081 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
3082 AddrMode addr_mode) {
3083 uint64_t addr = xreg(instr->Rn(), Reg31IsStackPointer);
3084 int rt = instr->Rt();
3085
3086 Instr itype = instr->Mask(NEONLoadStoreSingleStructMask);
3087 if (((itype == NEON_LD1_b) || (itype == NEON_LD1_h) ||
3088 (itype == NEON_LD1_s) || (itype == NEON_LD1_d)) &&
3089 (instr->Bits(20, 16) != 0)) {
3090 VIXL_UNREACHABLE();
3091 }
3092
3093 // We use the PostIndex mask here, as it works in this case for both Offset
3094 // and PostIndex addressing.
3095 bool do_load = false;
3096
3097 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3098 VectorFormat vf_t = nfd.GetVectorFormat();
3099
3100 VectorFormat vf = kFormat16B;
3101 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
3102 case NEON_LD1_b:
3103 case NEON_LD1_b_post:
3104 case NEON_LD2_b:
3105 case NEON_LD2_b_post:
3106 case NEON_LD3_b:
3107 case NEON_LD3_b_post:
3108 case NEON_LD4_b:
3109 case NEON_LD4_b_post: do_load = true;
3110 VIXL_FALLTHROUGH();
3111 case NEON_ST1_b:
3112 case NEON_ST1_b_post:
3113 case NEON_ST2_b:
3114 case NEON_ST2_b_post:
3115 case NEON_ST3_b:
3116 case NEON_ST3_b_post:
3117 case NEON_ST4_b:
3118 case NEON_ST4_b_post: break;
3119
3120 case NEON_LD1_h:
3121 case NEON_LD1_h_post:
3122 case NEON_LD2_h:
3123 case NEON_LD2_h_post:
3124 case NEON_LD3_h:
3125 case NEON_LD3_h_post:
3126 case NEON_LD4_h:
3127 case NEON_LD4_h_post: do_load = true;
3128 VIXL_FALLTHROUGH();
3129 case NEON_ST1_h:
3130 case NEON_ST1_h_post:
3131 case NEON_ST2_h:
3132 case NEON_ST2_h_post:
3133 case NEON_ST3_h:
3134 case NEON_ST3_h_post:
3135 case NEON_ST4_h:
3136 case NEON_ST4_h_post: vf = kFormat8H; break;
3137 case NEON_LD1_s:
3138 case NEON_LD1_s_post:
3139 case NEON_LD2_s:
3140 case NEON_LD2_s_post:
3141 case NEON_LD3_s:
3142 case NEON_LD3_s_post:
3143 case NEON_LD4_s:
3144 case NEON_LD4_s_post: do_load = true;
3145 VIXL_FALLTHROUGH();
3146 case NEON_ST1_s:
3147 case NEON_ST1_s_post:
3148 case NEON_ST2_s:
3149 case NEON_ST2_s_post:
3150 case NEON_ST3_s:
3151 case NEON_ST3_s_post:
3152 case NEON_ST4_s:
3153 case NEON_ST4_s_post: {
3154 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
3155 VIXL_STATIC_ASSERT(
3156 (NEON_LD1_s_post | (1 << NEONLSSize_offset)) == NEON_LD1_d_post);
3157 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
3158 VIXL_STATIC_ASSERT(
3159 (NEON_ST1_s_post | (1 << NEONLSSize_offset)) == NEON_ST1_d_post);
3160 vf = ((instr->NEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
3161 break;
3162 }
3163
3164 case NEON_LD1R:
3165 case NEON_LD1R_post: {
3166 vf = vf_t;
3167 ld1r(vf, vreg(rt), addr);
3168 do_load = true;
3169 break;
3170 }
3171
3172 case NEON_LD2R:
3173 case NEON_LD2R_post: {
3174 vf = vf_t;
3175 int rt2 = (rt + 1) % kNumberOfVRegisters;
3176 ld2r(vf, vreg(rt), vreg(rt2), addr);
3177 do_load = true;
3178 break;
3179 }
3180
3181 case NEON_LD3R:
3182 case NEON_LD3R_post: {
3183 vf = vf_t;
3184 int rt2 = (rt + 1) % kNumberOfVRegisters;
3185 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
3186 ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
3187 do_load = true;
3188 break;
3189 }
3190
3191 case NEON_LD4R:
3192 case NEON_LD4R_post: {
3193 vf = vf_t;
3194 int rt2 = (rt + 1) % kNumberOfVRegisters;
3195 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
3196 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
3197 ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
3198 do_load = true;
3199 break;
3200 }
3201 default: VIXL_UNIMPLEMENTED();
3202 }
3203
3204 PrintRegisterFormat print_format =
3205 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
3206 // Make sure that the print_format only includes a single lane.
3207 print_format =
3208 static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
3209
3210 int esize = LaneSizeInBytesFromFormat(vf);
3211 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
3212 int lane = instr->NEONLSIndex(index_shift);
3213 int scale = 0;
3214 int rt2 = (rt + 1) % kNumberOfVRegisters;
3215 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
3216 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
3217 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
3218 case NEONLoadStoreSingle1:
3219 scale = 1;
3220 if (do_load) {
3221 ld1(vf, vreg(rt), lane, addr);
3222 LogVRead(addr, rt, print_format, lane);
3223 } else {
3224 st1(vf, vreg(rt), lane, addr);
3225 LogVWrite(addr, rt, print_format, lane);
3226 }
3227 break;
3228 case NEONLoadStoreSingle2:
3229 scale = 2;
3230 if (do_load) {
3231 ld2(vf, vreg(rt), vreg(rt2), lane, addr);
3232 LogVRead(addr, rt, print_format, lane);
3233 LogVRead(addr + esize, rt2, print_format, lane);
3234 } else {
3235 st2(vf, vreg(rt), vreg(rt2), lane, addr);
3236 LogVWrite(addr, rt, print_format, lane);
3237 LogVWrite(addr + esize, rt2, print_format, lane);
3238 }
3239 break;
3240 case NEONLoadStoreSingle3:
3241 scale = 3;
3242 if (do_load) {
3243 ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
3244 LogVRead(addr, rt, print_format, lane);
3245 LogVRead(addr + esize, rt2, print_format, lane);
3246 LogVRead(addr + (2 * esize), rt3, print_format, lane);
3247 } else {
3248 st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
3249 LogVWrite(addr, rt, print_format, lane);
3250 LogVWrite(addr + esize, rt2, print_format, lane);
3251 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
3252 }
3253 break;
3254 case NEONLoadStoreSingle4:
3255 scale = 4;
3256 if (do_load) {
3257 ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
3258 LogVRead(addr, rt, print_format, lane);
3259 LogVRead(addr + esize, rt2, print_format, lane);
3260 LogVRead(addr + (2 * esize), rt3, print_format, lane);
3261 LogVRead(addr + (3 * esize), rt4, print_format, lane);
3262 } else {
3263 st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
3264 LogVWrite(addr, rt, print_format, lane);
3265 LogVWrite(addr + esize, rt2, print_format, lane);
3266 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
3267 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
3268 }
3269 break;
3270 default: VIXL_UNIMPLEMENTED();
3271 }
3272
3273 if (addr_mode == PostIndex) {
3274 int rm = instr->Rm();
3275 int lane_size = LaneSizeInBytesFromFormat(vf);
3276 set_xreg(instr->Rn(), addr + ((rm == 31) ? (scale * lane_size) : xreg(rm)));
3277 }
3278 }
3279
3280
VisitNEONLoadStoreSingleStruct(const Instruction * instr)3281 void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
3282 NEONLoadStoreSingleStructHelper(instr, Offset);
3283 }
3284
3285
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)3286 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
3287 const Instruction* instr) {
3288 NEONLoadStoreSingleStructHelper(instr, PostIndex);
3289 }
3290
3291
VisitNEONModifiedImmediate(const Instruction * instr)3292 void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
3293 SimVRegister& rd = vreg(instr->Rd());
3294 int cmode = instr->NEONCmode();
3295 int cmode_3_1 = (cmode >> 1) & 7;
3296 int cmode_3 = (cmode >> 3) & 1;
3297 int cmode_2 = (cmode >> 2) & 1;
3298 int cmode_1 = (cmode >> 1) & 1;
3299 int cmode_0 = cmode & 1;
3300 int q = instr->NEONQ();
3301 int op_bit = instr->NEONModImmOp();
3302 uint64_t imm8 = instr->ImmNEONabcdefgh();
3303
3304 // Find the format and immediate value
3305 uint64_t imm = 0;
3306 VectorFormat vform = kFormatUndefined;
3307 switch (cmode_3_1) {
3308 case 0x0:
3309 case 0x1:
3310 case 0x2:
3311 case 0x3:
3312 vform = (q == 1) ? kFormat4S : kFormat2S;
3313 imm = imm8 << (8 * cmode_3_1);
3314 break;
3315 case 0x4:
3316 case 0x5:
3317 vform = (q == 1) ? kFormat8H : kFormat4H;
3318 imm = imm8 << (8 * cmode_1);
3319 break;
3320 case 0x6:
3321 vform = (q == 1) ? kFormat4S : kFormat2S;
3322 if (cmode_0 == 0) {
3323 imm = imm8 << 8 | 0x000000ff;
3324 } else {
3325 imm = imm8 << 16 | 0x0000ffff;
3326 }
3327 break;
3328 case 0x7:
3329 if (cmode_0 == 0 && op_bit == 0) {
3330 vform = q ? kFormat16B : kFormat8B;
3331 imm = imm8;
3332 } else if (cmode_0 == 0 && op_bit == 1) {
3333 vform = q ? kFormat2D : kFormat1D;
3334 imm = 0;
3335 for (int i = 0; i < 8; ++i) {
3336 if (imm8 & (1 << i)) {
3337 imm |= (UINT64_C(0xff) << (8 * i));
3338 }
3339 }
3340 } else { // cmode_0 == 1, cmode == 0xf.
3341 if (op_bit == 0) {
3342 vform = q ? kFormat4S : kFormat2S;
3343 imm = float_to_rawbits(instr->ImmNEONFP32());
3344 } else if (q == 1) {
3345 vform = kFormat2D;
3346 imm = double_to_rawbits(instr->ImmNEONFP64());
3347 } else {
3348 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
3349 VisitUnallocated(instr);
3350 }
3351 }
3352 break;
3353 default: VIXL_UNREACHABLE(); break;
3354 }
3355
3356 // Find the operation
3357 NEONModifiedImmediateOp op;
3358 if (cmode_3 == 0) {
3359 if (cmode_0 == 0) {
3360 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
3361 } else { // cmode<0> == '1'
3362 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
3363 }
3364 } else { // cmode<3> == '1'
3365 if (cmode_2 == 0) {
3366 if (cmode_0 == 0) {
3367 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
3368 } else { // cmode<0> == '1'
3369 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
3370 }
3371 } else { // cmode<2> == '1'
3372 if (cmode_1 == 0) {
3373 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
3374 } else { // cmode<1> == '1'
3375 if (cmode_0 == 0) {
3376 op = NEONModifiedImmediate_MOVI;
3377 } else { // cmode<0> == '1'
3378 op = NEONModifiedImmediate_MOVI;
3379 }
3380 }
3381 }
3382 }
3383
3384 // Call the logic function
3385 if (op == NEONModifiedImmediate_ORR) {
3386 orr(vform, rd, rd, imm);
3387 } else if (op == NEONModifiedImmediate_BIC) {
3388 bic(vform, rd, rd, imm);
3389 } else if (op == NEONModifiedImmediate_MOVI) {
3390 movi(vform, rd, imm);
3391 } else if (op == NEONModifiedImmediate_MVNI) {
3392 mvni(vform, rd, imm);
3393 } else {
3394 VisitUnimplemented(instr);
3395 }
3396 }
3397
3398
VisitNEONScalar2RegMisc(const Instruction * instr)3399 void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
3400 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
3401 VectorFormat vf = nfd.GetVectorFormat();
3402
3403 SimVRegister& rd = vreg(instr->Rd());
3404 SimVRegister& rn = vreg(instr->Rn());
3405
3406 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
3407 // These instructions all use a two bit size field, except NOT and RBIT,
3408 // which use the field to encode the operation.
3409 switch (instr->Mask(NEONScalar2RegMiscMask)) {
3410 case NEON_CMEQ_zero_scalar: cmp(vf, rd, rn, 0, eq); break;
3411 case NEON_CMGE_zero_scalar: cmp(vf, rd, rn, 0, ge); break;
3412 case NEON_CMGT_zero_scalar: cmp(vf, rd, rn, 0, gt); break;
3413 case NEON_CMLT_zero_scalar: cmp(vf, rd, rn, 0, lt); break;
3414 case NEON_CMLE_zero_scalar: cmp(vf, rd, rn, 0, le); break;
3415 case NEON_ABS_scalar: abs(vf, rd, rn); break;
3416 case NEON_SQABS_scalar: abs(vf, rd, rn).SignedSaturate(vf); break;
3417 case NEON_NEG_scalar: neg(vf, rd, rn); break;
3418 case NEON_SQNEG_scalar: neg(vf, rd, rn).SignedSaturate(vf); break;
3419 case NEON_SUQADD_scalar: suqadd(vf, rd, rn); break;
3420 case NEON_USQADD_scalar: usqadd(vf, rd, rn); break;
3421 default: VIXL_UNIMPLEMENTED(); break;
3422 }
3423 } else {
3424 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
3425 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3426
3427 // These instructions all use a one bit size field, except SQXTUN, SQXTN
3428 // and UQXTN, which use a two bit size field.
3429 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
3430 case NEON_FRECPE_scalar: frecpe(fpf, rd, rn, fpcr_rounding); break;
3431 case NEON_FRECPX_scalar: frecpx(fpf, rd, rn); break;
3432 case NEON_FRSQRTE_scalar: frsqrte(fpf, rd, rn); break;
3433 case NEON_FCMGT_zero_scalar: fcmp_zero(fpf, rd, rn, gt); break;
3434 case NEON_FCMGE_zero_scalar: fcmp_zero(fpf, rd, rn, ge); break;
3435 case NEON_FCMEQ_zero_scalar: fcmp_zero(fpf, rd, rn, eq); break;
3436 case NEON_FCMLE_zero_scalar: fcmp_zero(fpf, rd, rn, le); break;
3437 case NEON_FCMLT_zero_scalar: fcmp_zero(fpf, rd, rn, lt); break;
3438 case NEON_SCVTF_scalar: scvtf(fpf, rd, rn, 0, fpcr_rounding); break;
3439 case NEON_UCVTF_scalar: ucvtf(fpf, rd, rn, 0, fpcr_rounding); break;
3440 case NEON_FCVTNS_scalar: fcvts(fpf, rd, rn, FPTieEven); break;
3441 case NEON_FCVTNU_scalar: fcvtu(fpf, rd, rn, FPTieEven); break;
3442 case NEON_FCVTPS_scalar: fcvts(fpf, rd, rn, FPPositiveInfinity); break;
3443 case NEON_FCVTPU_scalar: fcvtu(fpf, rd, rn, FPPositiveInfinity); break;
3444 case NEON_FCVTMS_scalar: fcvts(fpf, rd, rn, FPNegativeInfinity); break;
3445 case NEON_FCVTMU_scalar: fcvtu(fpf, rd, rn, FPNegativeInfinity); break;
3446 case NEON_FCVTZS_scalar: fcvts(fpf, rd, rn, FPZero); break;
3447 case NEON_FCVTZU_scalar: fcvtu(fpf, rd, rn, FPZero); break;
3448 case NEON_FCVTAS_scalar: fcvts(fpf, rd, rn, FPTieAway); break;
3449 case NEON_FCVTAU_scalar: fcvtu(fpf, rd, rn, FPTieAway); break;
3450 case NEON_FCVTXN_scalar:
3451 // Unlike all of the other FP instructions above, fcvtxn encodes dest
3452 // size S as size<0>=1. There's only one case, so we ignore the form.
3453 VIXL_ASSERT(instr->Bit(22) == 1);
3454 fcvtxn(kFormatS, rd, rn);
3455 break;
3456 default:
3457 switch (instr->Mask(NEONScalar2RegMiscMask)) {
3458 case NEON_SQXTN_scalar: sqxtn(vf, rd, rn); break;
3459 case NEON_UQXTN_scalar: uqxtn(vf, rd, rn); break;
3460 case NEON_SQXTUN_scalar: sqxtun(vf, rd, rn); break;
3461 default:
3462 VIXL_UNIMPLEMENTED();
3463 }
3464 }
3465 }
3466 }
3467
3468
VisitNEONScalar3Diff(const Instruction * instr)3469 void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
3470 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
3471 VectorFormat vf = nfd.GetVectorFormat();
3472
3473 SimVRegister& rd = vreg(instr->Rd());
3474 SimVRegister& rn = vreg(instr->Rn());
3475 SimVRegister& rm = vreg(instr->Rm());
3476 switch (instr->Mask(NEONScalar3DiffMask)) {
3477 case NEON_SQDMLAL_scalar: sqdmlal(vf, rd, rn, rm); break;
3478 case NEON_SQDMLSL_scalar: sqdmlsl(vf, rd, rn, rm); break;
3479 case NEON_SQDMULL_scalar: sqdmull(vf, rd, rn, rm); break;
3480 default:
3481 VIXL_UNIMPLEMENTED();
3482 }
3483 }
3484
3485
VisitNEONScalar3Same(const Instruction * instr)3486 void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
3487 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
3488 VectorFormat vf = nfd.GetVectorFormat();
3489
3490 SimVRegister& rd = vreg(instr->Rd());
3491 SimVRegister& rn = vreg(instr->Rn());
3492 SimVRegister& rm = vreg(instr->Rm());
3493
3494 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
3495 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
3496 switch (instr->Mask(NEONScalar3SameFPMask)) {
3497 case NEON_FMULX_scalar: fmulx(vf, rd, rn, rm); break;
3498 case NEON_FACGE_scalar: fabscmp(vf, rd, rn, rm, ge); break;
3499 case NEON_FACGT_scalar: fabscmp(vf, rd, rn, rm, gt); break;
3500 case NEON_FCMEQ_scalar: fcmp(vf, rd, rn, rm, eq); break;
3501 case NEON_FCMGE_scalar: fcmp(vf, rd, rn, rm, ge); break;
3502 case NEON_FCMGT_scalar: fcmp(vf, rd, rn, rm, gt); break;
3503 case NEON_FRECPS_scalar: frecps(vf, rd, rn, rm); break;
3504 case NEON_FRSQRTS_scalar: frsqrts(vf, rd, rn, rm); break;
3505 case NEON_FABD_scalar: fabd(vf, rd, rn, rm); break;
3506 default:
3507 VIXL_UNIMPLEMENTED();
3508 }
3509 } else {
3510 switch (instr->Mask(NEONScalar3SameMask)) {
3511 case NEON_ADD_scalar: add(vf, rd, rn, rm); break;
3512 case NEON_SUB_scalar: sub(vf, rd, rn, rm); break;
3513 case NEON_CMEQ_scalar: cmp(vf, rd, rn, rm, eq); break;
3514 case NEON_CMGE_scalar: cmp(vf, rd, rn, rm, ge); break;
3515 case NEON_CMGT_scalar: cmp(vf, rd, rn, rm, gt); break;
3516 case NEON_CMHI_scalar: cmp(vf, rd, rn, rm, hi); break;
3517 case NEON_CMHS_scalar: cmp(vf, rd, rn, rm, hs); break;
3518 case NEON_CMTST_scalar: cmptst(vf, rd, rn, rm); break;
3519 case NEON_USHL_scalar: ushl(vf, rd, rn, rm); break;
3520 case NEON_SSHL_scalar: sshl(vf, rd, rn, rm); break;
3521 case NEON_SQDMULH_scalar: sqdmulh(vf, rd, rn, rm); break;
3522 case NEON_SQRDMULH_scalar: sqrdmulh(vf, rd, rn, rm); break;
3523 case NEON_UQADD_scalar:
3524 add(vf, rd, rn, rm).UnsignedSaturate(vf);
3525 break;
3526 case NEON_SQADD_scalar:
3527 add(vf, rd, rn, rm).SignedSaturate(vf);
3528 break;
3529 case NEON_UQSUB_scalar:
3530 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
3531 break;
3532 case NEON_SQSUB_scalar:
3533 sub(vf, rd, rn, rm).SignedSaturate(vf);
3534 break;
3535 case NEON_UQSHL_scalar:
3536 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
3537 break;
3538 case NEON_SQSHL_scalar:
3539 sshl(vf, rd, rn, rm).SignedSaturate(vf);
3540 break;
3541 case NEON_URSHL_scalar:
3542 ushl(vf, rd, rn, rm).Round(vf);
3543 break;
3544 case NEON_SRSHL_scalar:
3545 sshl(vf, rd, rn, rm).Round(vf);
3546 break;
3547 case NEON_UQRSHL_scalar:
3548 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
3549 break;
3550 case NEON_SQRSHL_scalar:
3551 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
3552 break;
3553 default:
3554 VIXL_UNIMPLEMENTED();
3555 }
3556 }
3557 }
3558
3559
VisitNEONScalarByIndexedElement(const Instruction * instr)3560 void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
3561 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
3562 VectorFormat vf = nfd.GetVectorFormat();
3563 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
3564
3565 SimVRegister& rd = vreg(instr->Rd());
3566 SimVRegister& rn = vreg(instr->Rn());
3567 ByElementOp Op = NULL;
3568
3569 int rm_reg = instr->Rm();
3570 int index = (instr->NEONH() << 1) | instr->NEONL();
3571 if (instr->NEONSize() == 1) {
3572 rm_reg &= 0xf;
3573 index = (index << 1) | instr->NEONM();
3574 }
3575
3576 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
3577 case NEON_SQDMULL_byelement_scalar: Op = &Simulator::sqdmull; break;
3578 case NEON_SQDMLAL_byelement_scalar: Op = &Simulator::sqdmlal; break;
3579 case NEON_SQDMLSL_byelement_scalar: Op = &Simulator::sqdmlsl; break;
3580 case NEON_SQDMULH_byelement_scalar:
3581 Op = &Simulator::sqdmulh;
3582 vf = vf_r;
3583 break;
3584 case NEON_SQRDMULH_byelement_scalar:
3585 Op = &Simulator::sqrdmulh;
3586 vf = vf_r;
3587 break;
3588 default:
3589 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
3590 index = instr->NEONH();
3591 if ((instr->FPType() & 1) == 0) {
3592 index = (index << 1) | instr->NEONL();
3593 }
3594 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
3595 case NEON_FMUL_byelement_scalar: Op = &Simulator::fmul; break;
3596 case NEON_FMLA_byelement_scalar: Op = &Simulator::fmla; break;
3597 case NEON_FMLS_byelement_scalar: Op = &Simulator::fmls; break;
3598 case NEON_FMULX_byelement_scalar: Op = &Simulator::fmulx; break;
3599 default: VIXL_UNIMPLEMENTED();
3600 }
3601 }
3602
3603 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
3604 }
3605
3606
VisitNEONScalarCopy(const Instruction * instr)3607 void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
3608 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
3609 VectorFormat vf = nfd.GetVectorFormat();
3610
3611 SimVRegister& rd = vreg(instr->Rd());
3612 SimVRegister& rn = vreg(instr->Rn());
3613
3614 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
3615 int imm5 = instr->ImmNEON5();
3616 int tz = CountTrailingZeros(imm5, 32);
3617 int rn_index = imm5 >> (tz + 1);
3618 dup_element(vf, rd, rn, rn_index);
3619 } else {
3620 VIXL_UNIMPLEMENTED();
3621 }
3622 }
3623
3624
VisitNEONScalarPairwise(const Instruction * instr)3625 void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
3626 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
3627 VectorFormat vf = nfd.GetVectorFormat();
3628
3629 SimVRegister& rd = vreg(instr->Rd());
3630 SimVRegister& rn = vreg(instr->Rn());
3631 switch (instr->Mask(NEONScalarPairwiseMask)) {
3632 case NEON_ADDP_scalar: addp(vf, rd, rn); break;
3633 case NEON_FADDP_scalar: faddp(vf, rd, rn); break;
3634 case NEON_FMAXP_scalar: fmaxp(vf, rd, rn); break;
3635 case NEON_FMAXNMP_scalar: fmaxnmp(vf, rd, rn); break;
3636 case NEON_FMINP_scalar: fminp(vf, rd, rn); break;
3637 case NEON_FMINNMP_scalar: fminnmp(vf, rd, rn); break;
3638 default:
3639 VIXL_UNIMPLEMENTED();
3640 }
3641 }
3642
3643
VisitNEONScalarShiftImmediate(const Instruction * instr)3644 void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
3645 SimVRegister& rd = vreg(instr->Rd());
3646 SimVRegister& rn = vreg(instr->Rn());
3647 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3648
3649 static const NEONFormatMap map = {
3650 {22, 21, 20, 19},
3651 {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S,
3652 NF_D, NF_D, NF_D, NF_D, NF_D, NF_D, NF_D, NF_D}
3653 };
3654 NEONFormatDecoder nfd(instr, &map);
3655 VectorFormat vf = nfd.GetVectorFormat();
3656
3657 int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
3658 int immhimmb = instr->ImmNEONImmhImmb();
3659 int right_shift = (16 << highestSetBit) - immhimmb;
3660 int left_shift = immhimmb - (8 << highestSetBit);
3661 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
3662 case NEON_SHL_scalar: shl(vf, rd, rn, left_shift); break;
3663 case NEON_SLI_scalar: sli(vf, rd, rn, left_shift); break;
3664 case NEON_SQSHL_imm_scalar: sqshl(vf, rd, rn, left_shift); break;
3665 case NEON_UQSHL_imm_scalar: uqshl(vf, rd, rn, left_shift); break;
3666 case NEON_SQSHLU_scalar: sqshlu(vf, rd, rn, left_shift); break;
3667 case NEON_SRI_scalar: sri(vf, rd, rn, right_shift); break;
3668 case NEON_SSHR_scalar: sshr(vf, rd, rn, right_shift); break;
3669 case NEON_USHR_scalar: ushr(vf, rd, rn, right_shift); break;
3670 case NEON_SRSHR_scalar: sshr(vf, rd, rn, right_shift).Round(vf); break;
3671 case NEON_URSHR_scalar: ushr(vf, rd, rn, right_shift).Round(vf); break;
3672 case NEON_SSRA_scalar: ssra(vf, rd, rn, right_shift); break;
3673 case NEON_USRA_scalar: usra(vf, rd, rn, right_shift); break;
3674 case NEON_SRSRA_scalar: srsra(vf, rd, rn, right_shift); break;
3675 case NEON_URSRA_scalar: ursra(vf, rd, rn, right_shift); break;
3676 case NEON_UQSHRN_scalar: uqshrn(vf, rd, rn, right_shift); break;
3677 case NEON_UQRSHRN_scalar: uqrshrn(vf, rd, rn, right_shift); break;
3678 case NEON_SQSHRN_scalar: sqshrn(vf, rd, rn, right_shift); break;
3679 case NEON_SQRSHRN_scalar: sqrshrn(vf, rd, rn, right_shift); break;
3680 case NEON_SQSHRUN_scalar: sqshrun(vf, rd, rn, right_shift); break;
3681 case NEON_SQRSHRUN_scalar: sqrshrun(vf, rd, rn, right_shift); break;
3682 case NEON_FCVTZS_imm_scalar: fcvts(vf, rd, rn, FPZero, right_shift); break;
3683 case NEON_FCVTZU_imm_scalar: fcvtu(vf, rd, rn, FPZero, right_shift); break;
3684 case NEON_SCVTF_imm_scalar:
3685 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
3686 break;
3687 case NEON_UCVTF_imm_scalar:
3688 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
3689 break;
3690 default:
3691 VIXL_UNIMPLEMENTED();
3692 }
3693 }
3694
3695
VisitNEONShiftImmediate(const Instruction * instr)3696 void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
3697 SimVRegister& rd = vreg(instr->Rd());
3698 SimVRegister& rn = vreg(instr->Rn());
3699 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3700
3701 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
3702 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
3703 static const NEONFormatMap map = {
3704 {22, 21, 20, 19, 30},
3705 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H,
3706 NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
3707 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
3708 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}
3709 };
3710 NEONFormatDecoder nfd(instr, &map);
3711 VectorFormat vf = nfd.GetVectorFormat();
3712
3713 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
3714 static const NEONFormatMap map_l = {
3715 {22, 21, 20, 19},
3716 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}
3717 };
3718 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
3719
3720 int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
3721 int immhimmb = instr->ImmNEONImmhImmb();
3722 int right_shift = (16 << highestSetBit) - immhimmb;
3723 int left_shift = immhimmb - (8 << highestSetBit);
3724
3725 switch (instr->Mask(NEONShiftImmediateMask)) {
3726 case NEON_SHL: shl(vf, rd, rn, left_shift); break;
3727 case NEON_SLI: sli(vf, rd, rn, left_shift); break;
3728 case NEON_SQSHLU: sqshlu(vf, rd, rn, left_shift); break;
3729 case NEON_SRI: sri(vf, rd, rn, right_shift); break;
3730 case NEON_SSHR: sshr(vf, rd, rn, right_shift); break;
3731 case NEON_USHR: ushr(vf, rd, rn, right_shift); break;
3732 case NEON_SRSHR: sshr(vf, rd, rn, right_shift).Round(vf); break;
3733 case NEON_URSHR: ushr(vf, rd, rn, right_shift).Round(vf); break;
3734 case NEON_SSRA: ssra(vf, rd, rn, right_shift); break;
3735 case NEON_USRA: usra(vf, rd, rn, right_shift); break;
3736 case NEON_SRSRA: srsra(vf, rd, rn, right_shift); break;
3737 case NEON_URSRA: ursra(vf, rd, rn, right_shift); break;
3738 case NEON_SQSHL_imm: sqshl(vf, rd, rn, left_shift); break;
3739 case NEON_UQSHL_imm: uqshl(vf, rd, rn, left_shift); break;
3740 case NEON_SCVTF_imm: scvtf(vf, rd, rn, right_shift, fpcr_rounding); break;
3741 case NEON_UCVTF_imm: ucvtf(vf, rd, rn, right_shift, fpcr_rounding); break;
3742 case NEON_FCVTZS_imm: fcvts(vf, rd, rn, FPZero, right_shift); break;
3743 case NEON_FCVTZU_imm: fcvtu(vf, rd, rn, FPZero, right_shift); break;
3744 case NEON_SSHLL:
3745 vf = vf_l;
3746 if (instr->Mask(NEON_Q)) {
3747 sshll2(vf, rd, rn, left_shift);
3748 } else {
3749 sshll(vf, rd, rn, left_shift);
3750 }
3751 break;
3752 case NEON_USHLL:
3753 vf = vf_l;
3754 if (instr->Mask(NEON_Q)) {
3755 ushll2(vf, rd, rn, left_shift);
3756 } else {
3757 ushll(vf, rd, rn, left_shift);
3758 }
3759 break;
3760 case NEON_SHRN:
3761 if (instr->Mask(NEON_Q)) {
3762 shrn2(vf, rd, rn, right_shift);
3763 } else {
3764 shrn(vf, rd, rn, right_shift);
3765 }
3766 break;
3767 case NEON_RSHRN:
3768 if (instr->Mask(NEON_Q)) {
3769 rshrn2(vf, rd, rn, right_shift);
3770 } else {
3771 rshrn(vf, rd, rn, right_shift);
3772 }
3773 break;
3774 case NEON_UQSHRN:
3775 if (instr->Mask(NEON_Q)) {
3776 uqshrn2(vf, rd, rn, right_shift);
3777 } else {
3778 uqshrn(vf, rd, rn, right_shift);
3779 }
3780 break;
3781 case NEON_UQRSHRN:
3782 if (instr->Mask(NEON_Q)) {
3783 uqrshrn2(vf, rd, rn, right_shift);
3784 } else {
3785 uqrshrn(vf, rd, rn, right_shift);
3786 }
3787 break;
3788 case NEON_SQSHRN:
3789 if (instr->Mask(NEON_Q)) {
3790 sqshrn2(vf, rd, rn, right_shift);
3791 } else {
3792 sqshrn(vf, rd, rn, right_shift);
3793 }
3794 break;
3795 case NEON_SQRSHRN:
3796 if (instr->Mask(NEON_Q)) {
3797 sqrshrn2(vf, rd, rn, right_shift);
3798 } else {
3799 sqrshrn(vf, rd, rn, right_shift);
3800 }
3801 break;
3802 case NEON_SQSHRUN:
3803 if (instr->Mask(NEON_Q)) {
3804 sqshrun2(vf, rd, rn, right_shift);
3805 } else {
3806 sqshrun(vf, rd, rn, right_shift);
3807 }
3808 break;
3809 case NEON_SQRSHRUN:
3810 if (instr->Mask(NEON_Q)) {
3811 sqrshrun2(vf, rd, rn, right_shift);
3812 } else {
3813 sqrshrun(vf, rd, rn, right_shift);
3814 }
3815 break;
3816 default:
3817 VIXL_UNIMPLEMENTED();
3818 }
3819 }
3820
3821
VisitNEONTable(const Instruction * instr)3822 void Simulator::VisitNEONTable(const Instruction* instr) {
3823 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3824 VectorFormat vf = nfd.GetVectorFormat();
3825
3826 SimVRegister& rd = vreg(instr->Rd());
3827 SimVRegister& rn = vreg(instr->Rn());
3828 SimVRegister& rn2 = vreg((instr->Rn() + 1) % kNumberOfVRegisters);
3829 SimVRegister& rn3 = vreg((instr->Rn() + 2) % kNumberOfVRegisters);
3830 SimVRegister& rn4 = vreg((instr->Rn() + 3) % kNumberOfVRegisters);
3831 SimVRegister& rm = vreg(instr->Rm());
3832
3833 switch (instr->Mask(NEONTableMask)) {
3834 case NEON_TBL_1v: tbl(vf, rd, rn, rm); break;
3835 case NEON_TBL_2v: tbl(vf, rd, rn, rn2, rm); break;
3836 case NEON_TBL_3v: tbl(vf, rd, rn, rn2, rn3, rm); break;
3837 case NEON_TBL_4v: tbl(vf, rd, rn, rn2, rn3, rn4, rm); break;
3838 case NEON_TBX_1v: tbx(vf, rd, rn, rm); break;
3839 case NEON_TBX_2v: tbx(vf, rd, rn, rn2, rm); break;
3840 case NEON_TBX_3v: tbx(vf, rd, rn, rn2, rn3, rm); break;
3841 case NEON_TBX_4v: tbx(vf, rd, rn, rn2, rn3, rn4, rm); break;
3842 default:
3843 VIXL_UNIMPLEMENTED();
3844 }
3845 }
3846
3847
VisitNEONPerm(const Instruction * instr)3848 void Simulator::VisitNEONPerm(const Instruction* instr) {
3849 NEONFormatDecoder nfd(instr);
3850 VectorFormat vf = nfd.GetVectorFormat();
3851
3852 SimVRegister& rd = vreg(instr->Rd());
3853 SimVRegister& rn = vreg(instr->Rn());
3854 SimVRegister& rm = vreg(instr->Rm());
3855
3856 switch (instr->Mask(NEONPermMask)) {
3857 case NEON_TRN1: trn1(vf, rd, rn, rm); break;
3858 case NEON_TRN2: trn2(vf, rd, rn, rm); break;
3859 case NEON_UZP1: uzp1(vf, rd, rn, rm); break;
3860 case NEON_UZP2: uzp2(vf, rd, rn, rm); break;
3861 case NEON_ZIP1: zip1(vf, rd, rn, rm); break;
3862 case NEON_ZIP2: zip2(vf, rd, rn, rm); break;
3863 default:
3864 VIXL_UNIMPLEMENTED();
3865 }
3866 }
3867
3868
DoUnreachable(const Instruction * instr)3869 void Simulator::DoUnreachable(const Instruction* instr) {
3870 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3871 (instr->ImmException() == kUnreachableOpcode));
3872
3873 fprintf(stream_, "Hit UNREACHABLE marker at pc=%p.\n",
3874 reinterpret_cast<const void*>(instr));
3875 abort();
3876 }
3877
3878
DoTrace(const Instruction * instr)3879 void Simulator::DoTrace(const Instruction* instr) {
3880 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3881 (instr->ImmException() == kTraceOpcode));
3882
3883 // Read the arguments encoded inline in the instruction stream.
3884 uint32_t parameters;
3885 uint32_t command;
3886
3887 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
3888 memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters));
3889 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
3890
3891 switch (command) {
3892 case TRACE_ENABLE:
3893 set_trace_parameters(trace_parameters() | parameters);
3894 break;
3895 case TRACE_DISABLE:
3896 set_trace_parameters(trace_parameters() & ~parameters);
3897 break;
3898 default:
3899 VIXL_UNREACHABLE();
3900 }
3901
3902 set_pc(instr->InstructionAtOffset(kTraceLength));
3903 }
3904
3905
DoLog(const Instruction * instr)3906 void Simulator::DoLog(const Instruction* instr) {
3907 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3908 (instr->ImmException() == kLogOpcode));
3909
3910 // Read the arguments encoded inline in the instruction stream.
3911 uint32_t parameters;
3912
3913 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
3914 memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters));
3915
3916 // We don't support a one-shot LOG_DISASM.
3917 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
3918 // Print the requested information.
3919 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
3920 if (parameters & LOG_REGS) PrintRegisters();
3921 if (parameters & LOG_VREGS) PrintVRegisters();
3922
3923 set_pc(instr->InstructionAtOffset(kLogLength));
3924 }
3925
3926
DoPrintf(const Instruction * instr)3927 void Simulator::DoPrintf(const Instruction* instr) {
3928 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3929 (instr->ImmException() == kPrintfOpcode));
3930
3931 // Read the arguments encoded inline in the instruction stream.
3932 uint32_t arg_count;
3933 uint32_t arg_pattern_list;
3934 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
3935 memcpy(&arg_count,
3936 instr + kPrintfArgCountOffset,
3937 sizeof(arg_count));
3938 memcpy(&arg_pattern_list,
3939 instr + kPrintfArgPatternListOffset,
3940 sizeof(arg_pattern_list));
3941
3942 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
3943 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
3944
3945 // We need to call the host printf function with a set of arguments defined by
3946 // arg_pattern_list. Because we don't know the types and sizes of the
3947 // arguments, this is very difficult to do in a robust and portable way. To
3948 // work around the problem, we pick apart the format string, and print one
3949 // format placeholder at a time.
3950
3951 // Allocate space for the format string. We take a copy, so we can modify it.
3952 // Leave enough space for one extra character per expected argument (plus the
3953 // '\0' termination).
3954 const char * format_base = reg<const char *>(0);
3955 VIXL_ASSERT(format_base != NULL);
3956 size_t length = strlen(format_base) + 1;
3957 char * const format = new char[length + arg_count];
3958
3959 // A list of chunks, each with exactly one format placeholder.
3960 const char * chunks[kPrintfMaxArgCount];
3961
3962 // Copy the format string and search for format placeholders.
3963 uint32_t placeholder_count = 0;
3964 char * format_scratch = format;
3965 for (size_t i = 0; i < length; i++) {
3966 if (format_base[i] != '%') {
3967 *format_scratch++ = format_base[i];
3968 } else {
3969 if (format_base[i + 1] == '%') {
3970 // Ignore explicit "%%" sequences.
3971 *format_scratch++ = format_base[i];
3972 i++;
3973 // Chunks after the first are passed as format strings to printf, so we
3974 // need to escape '%' characters in those chunks.
3975 if (placeholder_count > 0) *format_scratch++ = format_base[i];
3976 } else {
3977 VIXL_CHECK(placeholder_count < arg_count);
3978 // Insert '\0' before placeholders, and store their locations.
3979 *format_scratch++ = '\0';
3980 chunks[placeholder_count++] = format_scratch;
3981 *format_scratch++ = format_base[i];
3982 }
3983 }
3984 }
3985 VIXL_CHECK(placeholder_count == arg_count);
3986
3987 // Finally, call printf with each chunk, passing the appropriate register
3988 // argument. Normally, printf returns the number of bytes transmitted, so we
3989 // can emulate a single printf call by adding the result from each chunk. If
3990 // any call returns a negative (error) value, though, just return that value.
3991
3992 printf("%s", clr_printf);
3993
3994 // Because '\0' is inserted before each placeholder, the first string in
3995 // 'format' contains no format placeholders and should be printed literally.
3996 int result = printf("%s", format);
3997 int pcs_r = 1; // Start at x1. x0 holds the format string.
3998 int pcs_f = 0; // Start at d0.
3999 if (result >= 0) {
4000 for (uint32_t i = 0; i < placeholder_count; i++) {
4001 int part_result = -1;
4002
4003 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
4004 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
4005 switch (arg_pattern) {
4006 case kPrintfArgW: part_result = printf(chunks[i], wreg(pcs_r++)); break;
4007 case kPrintfArgX: part_result = printf(chunks[i], xreg(pcs_r++)); break;
4008 case kPrintfArgD: part_result = printf(chunks[i], dreg(pcs_f++)); break;
4009 default: VIXL_UNREACHABLE();
4010 }
4011
4012 if (part_result < 0) {
4013 // Handle error values.
4014 result = part_result;
4015 break;
4016 }
4017
4018 result += part_result;
4019 }
4020 }
4021
4022 printf("%s", clr_normal);
4023
4024 // Printf returns its result in x0 (just like the C library's printf).
4025 set_xreg(0, result);
4026
4027 // The printf parameters are inlined in the code, so skip them.
4028 set_pc(instr->InstructionAtOffset(kPrintfLength));
4029
4030 // Set LR as if we'd just called a native printf function.
4031 set_lr(pc());
4032
4033 delete[] format;
4034 }
4035
4036 } // namespace vixl
4037
4038 #endif // VIXL_INCLUDE_SIMULATOR
4039