blob: 0fd780f2432d8bec6239d1d500f54f70d3594683 [file] [log] [blame]
Alexandre Ramesd3832962016-07-04 15:03:43 +01001// Copyright 2015, VIXL authors
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// * Neither the name of ARM Limited nor the names of its contributors may be
13// used to endorse or promote products derived from this software without
14// specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
Pierre Langlois1e85b7f2016-08-05 14:20:36 +010027#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
Alexandre Ramesd3832962016-07-04 15:03:43 +010028
Pierre Langlois78973f22016-08-10 14:35:56 +010029#include <cstring>
Alexandre Ramesd3832962016-07-04 15:03:43 +010030#include <cmath>
31
32#include "aarch64/simulator-aarch64.h"
33
34namespace vixl {
35namespace aarch64 {
36
37const Instruction* Simulator::kEndOfSimAddress = NULL;
38
39void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
40 int width = msb - lsb + 1;
41 VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
42
43 bits <<= lsb;
44 uint32_t mask = ((1 << width) - 1) << lsb;
45 VIXL_ASSERT((mask & write_ignore_mask_) == 0);
46
47 value_ = (value_ & ~mask) | (bits & mask);
48}
49
50
51SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
52 switch (id) {
53 case NZCV:
54 return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
55 case FPCR:
56 return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
57 default:
58 VIXL_UNREACHABLE();
59 return SimSystemRegister();
60 }
61}
62
63
64Simulator::Simulator(Decoder* decoder, FILE* stream) {
65 // Ensure that shift operations act as the simulator expects.
66 VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
67 VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
68
69 instruction_stats_ = false;
70
71 // Set up the decoder.
72 decoder_ = decoder;
73 decoder_->AppendVisitor(this);
74
75 stream_ = stream;
76 print_disasm_ = new PrintDisassembler(stream_);
77 SetColouredTrace(false);
78 trace_parameters_ = LOG_NONE;
79
80 ResetState();
81
82 // Allocate and set up the simulator stack.
83 stack_ = new byte[stack_size_];
84 stack_limit_ = stack_ + stack_protection_size_;
85 // Configure the starting stack pointer.
86 // - Find the top of the stack.
87 byte* tos = stack_ + stack_size_;
88 // - There's a protection region at both ends of the stack.
89 tos -= stack_protection_size_;
90 // - The stack pointer must be 16-byte aligned.
91 tos = AlignDown(tos, 16);
92 WriteSp(tos);
93
94 instrumentation_ = NULL;
95
96 // Print a warning about exclusive-access instructions, but only the first
97 // time they are encountered. This warning can be silenced using
98 // SilenceExclusiveAccessWarning().
99 print_exclusive_access_warning_ = true;
100}
101
102
103void Simulator::ResetState() {
104 // Reset the system registers.
105 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
106 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
107
108 // Reset registers to 0.
109 pc_ = NULL;
110 pc_modified_ = false;
111 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
112 WriteXRegister(i, 0xbadbeef);
113 }
114 // Set FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
Pierre Langlois23703a72016-08-15 17:23:39 +0100115 uint64_t nan_bits[] = {
116 UINT64_C(0x7ff00cab7f8ba9e1), UINT64_C(0x7ff0dead7f8beef1),
117 };
118 VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits[0] & kDRegMask)));
119 VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits[0] & kSRegMask)));
120
121 qreg_t q_bits;
122 VIXL_ASSERT(sizeof(q_bits) == sizeof(nan_bits));
123 memcpy(&q_bits, nan_bits, sizeof(nan_bits));
124
125 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
126 WriteQRegister(i, q_bits);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100127 }
128 // Returning to address 0 exits the Simulator.
129 WriteLr(kEndOfSimAddress);
130}
131
132
133Simulator::~Simulator() {
134 delete[] stack_;
135 // The decoder may outlive the simulator.
136 decoder_->RemoveVisitor(print_disasm_);
137 delete print_disasm_;
138
139 decoder_->RemoveVisitor(instrumentation_);
140 delete instrumentation_;
141}
142
143
144void Simulator::Run() {
145 // Flush any written registers before executing anything, so that
146 // manually-set registers are logged _before_ the first instruction.
147 LogAllWrittenRegisters();
148
149 while (pc_ != kEndOfSimAddress) {
150 ExecuteInstruction();
151 }
152}
153
154
155void Simulator::RunFrom(const Instruction* first) {
156 WritePc(first);
157 Run();
158}
159
160
161const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
162 "x6", "x7", "x8", "x9", "x10", "x11",
163 "x12", "x13", "x14", "x15", "x16", "x17",
164 "x18", "x19", "x20", "x21", "x22", "x23",
165 "x24", "x25", "x26", "x27", "x28", "x29",
166 "lr", "xzr", "sp"};
167
168const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
169 "w6", "w7", "w8", "w9", "w10", "w11",
170 "w12", "w13", "w14", "w15", "w16", "w17",
171 "w18", "w19", "w20", "w21", "w22", "w23",
172 "w24", "w25", "w26", "w27", "w28", "w29",
173 "w30", "wzr", "wsp"};
174
175const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
176 "s6", "s7", "s8", "s9", "s10", "s11",
177 "s12", "s13", "s14", "s15", "s16", "s17",
178 "s18", "s19", "s20", "s21", "s22", "s23",
179 "s24", "s25", "s26", "s27", "s28", "s29",
180 "s30", "s31"};
181
182const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
183 "d6", "d7", "d8", "d9", "d10", "d11",
184 "d12", "d13", "d14", "d15", "d16", "d17",
185 "d18", "d19", "d20", "d21", "d22", "d23",
186 "d24", "d25", "d26", "d27", "d28", "d29",
187 "d30", "d31"};
188
189const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
190 "v6", "v7", "v8", "v9", "v10", "v11",
191 "v12", "v13", "v14", "v15", "v16", "v17",
192 "v18", "v19", "v20", "v21", "v22", "v23",
193 "v24", "v25", "v26", "v27", "v28", "v29",
194 "v30", "v31"};
195
196
197const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
198 VIXL_ASSERT(code < kNumberOfRegisters);
199 // If the code represents the stack pointer, index the name after zr.
200 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
201 code = kZeroRegCode + 1;
202 }
203 return wreg_names[code];
204}
205
206
207const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
208 VIXL_ASSERT(code < kNumberOfRegisters);
209 // If the code represents the stack pointer, index the name after zr.
210 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
211 code = kZeroRegCode + 1;
212 }
213 return xreg_names[code];
214}
215
216
217const char* Simulator::SRegNameForCode(unsigned code) {
218 VIXL_ASSERT(code < kNumberOfFPRegisters);
219 return sreg_names[code];
220}
221
222
223const char* Simulator::DRegNameForCode(unsigned code) {
224 VIXL_ASSERT(code < kNumberOfFPRegisters);
225 return dreg_names[code];
226}
227
228
229const char* Simulator::VRegNameForCode(unsigned code) {
230 VIXL_ASSERT(code < kNumberOfVRegisters);
231 return vreg_names[code];
232}
233
234
235#define COLOUR(colour_code) "\033[0;" colour_code "m"
236#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
237#define NORMAL ""
238#define GREY "30"
239#define RED "31"
240#define GREEN "32"
241#define YELLOW "33"
242#define BLUE "34"
243#define MAGENTA "35"
244#define CYAN "36"
245#define WHITE "37"
246void Simulator::SetColouredTrace(bool value) {
247 coloured_trace_ = value;
248
249 clr_normal = value ? COLOUR(NORMAL) : "";
250 clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
251 clr_flag_value = value ? COLOUR(NORMAL) : "";
252 clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
253 clr_reg_value = value ? COLOUR(CYAN) : "";
254 clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
255 clr_vreg_value = value ? COLOUR(MAGENTA) : "";
256 clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
257 clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
258 clr_warning_message = value ? COLOUR(YELLOW) : "";
259 clr_printf = value ? COLOUR(GREEN) : "";
260}
261
262
263void Simulator::SetTraceParameters(int parameters) {
264 bool disasm_before = trace_parameters_ & LOG_DISASM;
265 trace_parameters_ = parameters;
266 bool disasm_after = trace_parameters_ & LOG_DISASM;
267
268 if (disasm_before != disasm_after) {
269 if (disasm_after) {
270 decoder_->InsertVisitorBefore(print_disasm_, this);
271 } else {
272 decoder_->RemoveVisitor(print_disasm_);
273 }
274 }
275}
276
277
278void Simulator::SetInstructionStats(bool value) {
279 if (value != instruction_stats_) {
280 if (value) {
281 if (instrumentation_ == NULL) {
282 // Set the sample period to 10, as the VIXL examples and tests are
283 // short.
284 instrumentation_ = new Instrument("vixl_stats.csv", 10);
285 }
286 decoder_->AppendVisitor(instrumentation_);
287 } else if (instrumentation_ != NULL) {
288 decoder_->RemoveVisitor(instrumentation_);
289 }
290 instruction_stats_ = value;
291 }
292}
293
294// Helpers ---------------------------------------------------------------------
295uint64_t Simulator::AddWithCarry(unsigned reg_size,
296 bool set_flags,
297 uint64_t left,
298 uint64_t right,
299 int carry_in) {
300 VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
301 VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
302
303 uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
304 uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
305 uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
306
307 left &= reg_mask;
308 right &= reg_mask;
309 uint64_t result = (left + right + carry_in) & reg_mask;
310
311 if (set_flags) {
312 ReadNzcv().SetN(CalcNFlag(result, reg_size));
313 ReadNzcv().SetZ(CalcZFlag(result));
314
315 // Compute the C flag by comparing the result to the max unsigned integer.
316 uint64_t max_uint_2op = max_uint - carry_in;
317 bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
318 ReadNzcv().SetC(C ? 1 : 0);
319
320 // Overflow iff the sign bit is the same for the two inputs and different
321 // for the result.
322 uint64_t left_sign = left & sign_mask;
323 uint64_t right_sign = right & sign_mask;
324 uint64_t result_sign = result & sign_mask;
325 bool V = (left_sign == right_sign) && (left_sign != result_sign);
326 ReadNzcv().SetV(V ? 1 : 0);
327
328 LogSystemRegister(NZCV);
329 }
330 return result;
331}
332
333
334int64_t Simulator::ShiftOperand(unsigned reg_size,
335 int64_t value,
336 Shift shift_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100337 unsigned amount) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100338 if (amount == 0) {
339 return value;
340 }
341 int64_t mask = reg_size == kXRegSize ? kXRegMask : kWRegMask;
342 switch (shift_type) {
343 case LSL:
344 return (value << amount) & mask;
345 case LSR:
346 return static_cast<uint64_t>(value) >> amount;
347 case ASR: {
348 // Shift used to restore the sign.
349 unsigned s_shift = kXRegSize - reg_size;
350 // Value with its sign restored.
351 int64_t s_value = (value << s_shift) >> s_shift;
352 return (s_value >> amount) & mask;
353 }
354 case ROR: {
355 if (reg_size == kWRegSize) {
356 value &= kWRegMask;
357 }
358 return (static_cast<uint64_t>(value) >> amount) |
359 ((value & ((INT64_C(1) << amount) - 1)) << (reg_size - amount));
360 }
361 default:
362 VIXL_UNIMPLEMENTED();
363 return 0;
364 }
365}
366
367
368int64_t Simulator::ExtendValue(unsigned reg_size,
369 int64_t value,
370 Extend extend_type,
Alexandre Rames868bfc42016-07-19 17:10:48 +0100371 unsigned left_shift) const {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100372 switch (extend_type) {
373 case UXTB:
374 value &= kByteMask;
375 break;
376 case UXTH:
377 value &= kHalfWordMask;
378 break;
379 case UXTW:
380 value &= kWordMask;
381 break;
382 case SXTB:
383 value = (value << 56) >> 56;
384 break;
385 case SXTH:
386 value = (value << 48) >> 48;
387 break;
388 case SXTW:
389 value = (value << 32) >> 32;
390 break;
391 case UXTX:
392 case SXTX:
393 break;
394 default:
395 VIXL_UNREACHABLE();
396 }
397 int64_t mask = (reg_size == kXRegSize) ? kXRegMask : kWRegMask;
398 return (value << left_shift) & mask;
399}
400
401
402void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
403 AssertSupportedFPCR();
404
405 // TODO: This assumes that the C++ implementation handles comparisons in the
406 // way that we expect (as per AssertSupportedFPCR()).
407 bool process_exception = false;
408 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
409 ReadNzcv().SetRawValue(FPUnorderedFlag);
410 if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
411 (trap == EnableTrap)) {
412 process_exception = true;
413 }
414 } else if (val0 < val1) {
415 ReadNzcv().SetRawValue(FPLessThanFlag);
416 } else if (val0 > val1) {
417 ReadNzcv().SetRawValue(FPGreaterThanFlag);
418 } else if (val0 == val1) {
419 ReadNzcv().SetRawValue(FPEqualFlag);
420 } else {
421 VIXL_UNREACHABLE();
422 }
423 LogSystemRegister(NZCV);
424 if (process_exception) FPProcessException();
425}
426
427
Alexandre Rames868bfc42016-07-19 17:10:48 +0100428uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
429 VIXL_ASSERT(mem_op.IsValid());
430 int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
431 if (mem_op.IsImmediateOffset()) {
432 return base + mem_op.GetOffset();
433 } else {
434 VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
435 int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
436 int64_t shift_amount = mem_op.GetShiftAmount();
437 if (mem_op.GetShift() != NO_SHIFT) {
438 offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
439 }
440 if (mem_op.GetExtend() != NO_EXTEND) {
441 offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
442 }
443 return static_cast<uint64_t>(base + offset);
444 }
445}
446
447
Alexandre Ramesd3832962016-07-04 15:03:43 +0100448Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
449 unsigned reg_size, unsigned lane_size) {
450 VIXL_ASSERT(reg_size >= lane_size);
451
452 uint32_t format = 0;
453 if (reg_size != lane_size) {
454 switch (reg_size) {
455 default:
456 VIXL_UNREACHABLE();
457 break;
458 case kQRegSizeInBytes:
459 format = kPrintRegAsQVector;
460 break;
461 case kDRegSizeInBytes:
462 format = kPrintRegAsDVector;
463 break;
464 }
465 }
466
467 switch (lane_size) {
468 default:
469 VIXL_UNREACHABLE();
470 break;
471 case kQRegSizeInBytes:
472 format |= kPrintReg1Q;
473 break;
474 case kDRegSizeInBytes:
475 format |= kPrintReg1D;
476 break;
477 case kSRegSizeInBytes:
478 format |= kPrintReg1S;
479 break;
480 case kHRegSizeInBytes:
481 format |= kPrintReg1H;
482 break;
483 case kBRegSizeInBytes:
484 format |= kPrintReg1B;
485 break;
486 }
487 // These sizes would be duplicate case labels.
488 VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
489 VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
490 VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
491 VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
492
493 return static_cast<PrintRegisterFormat>(format);
494}
495
496
497Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
498 VectorFormat vform) {
499 switch (vform) {
500 default:
501 VIXL_UNREACHABLE();
502 return kPrintReg16B;
503 case kFormat16B:
504 return kPrintReg16B;
505 case kFormat8B:
506 return kPrintReg8B;
507 case kFormat8H:
508 return kPrintReg8H;
509 case kFormat4H:
510 return kPrintReg4H;
511 case kFormat4S:
512 return kPrintReg4S;
513 case kFormat2S:
514 return kPrintReg2S;
515 case kFormat2D:
516 return kPrintReg2D;
517 case kFormat1D:
518 return kPrintReg1D;
519
520 case kFormatB:
521 return kPrintReg1B;
522 case kFormatH:
523 return kPrintReg1H;
524 case kFormatS:
525 return kPrintReg1S;
526 case kFormatD:
527 return kPrintReg1D;
528 }
529}
530
531
532Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
533 VectorFormat vform) {
534 switch (vform) {
535 default:
536 VIXL_UNREACHABLE();
537 return kPrintReg16B;
538 case kFormat4S:
539 return kPrintReg4SFP;
540 case kFormat2S:
541 return kPrintReg2SFP;
542 case kFormat2D:
543 return kPrintReg2DFP;
544 case kFormat1D:
545 return kPrintReg1DFP;
546
547 case kFormatS:
548 return kPrintReg1SFP;
549 case kFormatD:
550 return kPrintReg1DFP;
551 }
552}
553
554
555void Simulator::PrintWrittenRegisters() {
556 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
557 if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
558 }
559}
560
561
562void Simulator::PrintWrittenVRegisters() {
563 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
564 // At this point there is no type information, so print as a raw 1Q.
565 if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
566 }
567}
568
569
570void Simulator::PrintSystemRegisters() {
571 PrintSystemRegister(NZCV);
572 PrintSystemRegister(FPCR);
573}
574
575
576void Simulator::PrintRegisters() {
577 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
578 PrintRegister(i);
579 }
580}
581
582
583void Simulator::PrintVRegisters() {
584 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
585 // At this point there is no type information, so print as a raw 1Q.
586 PrintVRegister(i, kPrintReg1Q);
587 }
588}
589
590
591// Print a register's name and raw value.
592//
593// Only the least-significant `size_in_bytes` bytes of the register are printed,
594// but the value is aligned as if the whole register had been printed.
595//
596// For typical register updates, size_in_bytes should be set to kXRegSizeInBytes
597// -- the default -- so that the whole register is printed. Other values of
598// size_in_bytes are intended for use when the register hasn't actually been
599// updated (such as in PrintWrite).
600//
601// No newline is printed. This allows the caller to print more details (such as
602// a memory access annotation).
603void Simulator::PrintRegisterRawHelper(unsigned code,
604 Reg31Mode r31mode,
605 int size_in_bytes) {
606 // The template for all supported sizes.
607 // "# x{code}: 0xffeeddccbbaa9988"
608 // "# w{code}: 0xbbaa9988"
609 // "# w{code}<15:0>: 0x9988"
610 // "# w{code}<7:0>: 0x88"
611 unsigned padding_chars = (kXRegSizeInBytes - size_in_bytes) * 2;
612
613 const char* name = "";
614 const char* suffix = "";
615 switch (size_in_bytes) {
616 case kXRegSizeInBytes:
617 name = XRegNameForCode(code, r31mode);
618 break;
619 case kWRegSizeInBytes:
620 name = WRegNameForCode(code, r31mode);
621 break;
622 case 2:
623 name = WRegNameForCode(code, r31mode);
624 suffix = "<15:0>";
625 padding_chars -= strlen(suffix);
626 break;
627 case 1:
628 name = WRegNameForCode(code, r31mode);
629 suffix = "<7:0>";
630 padding_chars -= strlen(suffix);
631 break;
632 default:
633 VIXL_UNREACHABLE();
634 }
635 fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
636
637 // Print leading padding spaces.
638 VIXL_ASSERT(padding_chars < (kXRegSizeInBytes * 2));
639 for (unsigned i = 0; i < padding_chars; i++) {
640 putc(' ', stream_);
641 }
642
643 // Print the specified bits in hexadecimal format.
644 uint64_t bits = ReadRegister<uint64_t>(code, r31mode);
645 bits &= kXRegMask >> ((kXRegSizeInBytes - size_in_bytes) * 8);
646 VIXL_STATIC_ASSERT(sizeof(bits) == kXRegSizeInBytes);
647
648 int chars = size_in_bytes * 2;
649 fprintf(stream_,
650 "%s0x%0*" PRIx64 "%s",
651 clr_reg_value,
652 chars,
653 bits,
654 clr_normal);
655}
656
657
658void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
659 registers_[code].NotifyRegisterLogged();
660
661 // Don't print writes into xzr.
662 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
663 return;
664 }
665
666 // The template for all x and w registers:
667 // "# x{code}: 0x{value}"
668 // "# w{code}: 0x{value}"
669
670 PrintRegisterRawHelper(code, r31mode);
671 fprintf(stream_, "\n");
672}
673
674
675// Print a register's name and raw value.
676//
677// The `bytes` and `lsb` arguments can be used to limit the bytes that are
678// printed. These arguments are intended for use in cases where register hasn't
679// actually been updated (such as in PrintVWrite).
680//
681// No newline is printed. This allows the caller to print more details (such as
682// a floating-point interpretation or a memory access annotation).
683void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
684 // The template for vector types:
685 // "# v{code}: 0xffeeddccbbaa99887766554433221100".
686 // An example with bytes=4 and lsb=8:
687 // "# v{code}: 0xbbaa9988 ".
688 fprintf(stream_,
689 "# %s%5s: %s",
690 clr_vreg_name,
691 VRegNameForCode(code),
692 clr_vreg_value);
693
694 int msb = lsb + bytes - 1;
695 int byte = kQRegSizeInBytes - 1;
696
697 // Print leading padding spaces. (Two spaces per byte.)
698 while (byte > msb) {
699 fprintf(stream_, " ");
700 byte--;
701 }
702
703 // Print the specified part of the value, byte by byte.
704 qreg_t rawbits = ReadQRegister(code);
705 fprintf(stream_, "0x");
706 while (byte >= lsb) {
707 fprintf(stream_, "%02x", rawbits.val[byte]);
708 byte--;
709 }
710
711 // Print trailing padding spaces.
712 while (byte >= 0) {
713 fprintf(stream_, " ");
714 byte--;
715 }
716 fprintf(stream_, "%s", clr_normal);
717}
718
719
720// Print each of the specified lanes of a register as a float or double value.
721//
722// The `lane_count` and `lslane` arguments can be used to limit the lanes that
723// are printed. These arguments are intended for use in cases where register
724// hasn't actually been updated (such as in PrintVWrite).
725//
726// No newline is printed. This allows the caller to print more details (such as
727// a memory access annotation).
728void Simulator::PrintVRegisterFPHelper(unsigned code,
729 unsigned lane_size_in_bytes,
730 int lane_count,
731 int rightmost_lane) {
732 VIXL_ASSERT((lane_size_in_bytes == kSRegSizeInBytes) ||
733 (lane_size_in_bytes == kDRegSizeInBytes));
734
735 unsigned msb = ((lane_count + rightmost_lane) * lane_size_in_bytes);
736 VIXL_ASSERT(msb <= kQRegSizeInBytes);
737
738 // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
739 // name is used:
740 // " (s{code}: {value})"
741 // " (d{code}: {value})"
742 // For vector types, "..." is used to represent one or more omitted lanes.
743 // " (..., {value}, {value}, ...)"
744 if ((lane_count == 1) && (rightmost_lane == 0)) {
745 const char* name = (lane_size_in_bytes == kSRegSizeInBytes)
746 ? SRegNameForCode(code)
747 : DRegNameForCode(code);
748 fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
749 } else {
750 if (msb < (kQRegSizeInBytes - 1)) {
751 fprintf(stream_, " (..., ");
752 } else {
753 fprintf(stream_, " (");
754 }
755 }
756
757 // Print the list of values.
758 const char* separator = "";
759 int leftmost_lane = rightmost_lane + lane_count - 1;
760 for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
761 double value = (lane_size_in_bytes == kSRegSizeInBytes)
762 ? ReadVRegister(code).GetLane<float>(lane)
763 : ReadVRegister(code).GetLane<double>(lane);
Alexandre Rames6b5fe942016-07-22 17:17:23 +0100764 if (std::isnan(value)) {
765 // The output for NaNs is implementation defined. Always print `nan`, so
766 // that traces are coherent across different implementations.
767 fprintf(stream_, "%s%snan%s", separator, clr_vreg_value, clr_normal);
768 } else {
769 fprintf(stream_,
770 "%s%s%#g%s",
771 separator,
772 clr_vreg_value,
773 value,
774 clr_normal);
775 }
Alexandre Ramesd3832962016-07-04 15:03:43 +0100776 separator = ", ";
777 }
778
779 if (rightmost_lane > 0) {
780 fprintf(stream_, ", ...");
781 }
782 fprintf(stream_, ")");
783}
784
785
786void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
787 vregisters_[code].NotifyRegisterLogged();
788
789 int lane_size_log2 = format & kPrintRegLaneSizeMask;
790
791 int reg_size_log2;
792 if (format & kPrintRegAsQVector) {
793 reg_size_log2 = kQRegSizeInBytesLog2;
794 } else if (format & kPrintRegAsDVector) {
795 reg_size_log2 = kDRegSizeInBytesLog2;
796 } else {
797 // Scalar types.
798 reg_size_log2 = lane_size_log2;
799 }
800
801 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
802 int lane_size = 1 << lane_size_log2;
803
804 // The template for vector types:
805 // "# v{code}: 0x{rawbits} (..., {value}, ...)".
806 // The template for scalar types:
807 // "# v{code}: 0x{rawbits} ({reg}:{value})".
808 // The values in parentheses after the bit representations are floating-point
809 // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
810
811 PrintVRegisterRawHelper(code);
812 if (format & kPrintRegAsFP) {
813 PrintVRegisterFPHelper(code, lane_size, lane_count);
814 }
815
816 fprintf(stream_, "\n");
817}
818
819
820void Simulator::PrintSystemRegister(SystemRegister id) {
821 switch (id) {
822 case NZCV:
823 fprintf(stream_,
824 "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
825 clr_flag_name,
826 clr_flag_value,
827 ReadNzcv().GetN(),
828 ReadNzcv().GetZ(),
829 ReadNzcv().GetC(),
830 ReadNzcv().GetV(),
831 clr_normal);
832 break;
833 case FPCR: {
834 static const char* rmode[] = {"0b00 (Round to Nearest)",
835 "0b01 (Round towards Plus Infinity)",
836 "0b10 (Round towards Minus Infinity)",
837 "0b11 (Round towards Zero)"};
838 VIXL_ASSERT(ReadFpcr().GetRMode() < (sizeof(rmode) / sizeof(rmode[0])));
839 fprintf(stream_,
840 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
841 clr_flag_name,
842 clr_flag_value,
843 ReadFpcr().GetAHP(),
844 ReadFpcr().GetDN(),
845 ReadFpcr().GetFZ(),
846 rmode[ReadFpcr().GetRMode()],
847 clr_normal);
848 break;
849 }
850 default:
851 VIXL_UNREACHABLE();
852 }
853}
854
855
856void Simulator::PrintRead(uintptr_t address,
857 unsigned reg_code,
858 PrintRegisterFormat format) {
859 registers_[reg_code].NotifyRegisterLogged();
860
861 USE(format);
862
863 // The template is "# {reg}: 0x{value} <- {address}".
864 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
865 fprintf(stream_,
866 " <- %s0x%016" PRIxPTR "%s\n",
867 clr_memory_address,
868 address,
869 clr_normal);
870}
871
872
873void Simulator::PrintVRead(uintptr_t address,
874 unsigned reg_code,
875 PrintRegisterFormat format,
876 unsigned lane) {
877 vregisters_[reg_code].NotifyRegisterLogged();
878
879 // The template is "# v{code}: 0x{rawbits} <- address".
880 PrintVRegisterRawHelper(reg_code);
881 if (format & kPrintRegAsFP) {
882 PrintVRegisterFPHelper(reg_code,
883 GetPrintRegLaneSizeInBytes(format),
884 GetPrintRegLaneCount(format),
885 lane);
886 }
887 fprintf(stream_,
888 " <- %s0x%016" PRIxPTR "%s\n",
889 clr_memory_address,
890 address,
891 clr_normal);
892}
893
894
895void Simulator::PrintWrite(uintptr_t address,
896 unsigned reg_code,
897 PrintRegisterFormat format) {
898 VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
899
900 // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
901 // and readable, the value is aligned with the values in the register trace.
902 PrintRegisterRawHelper(reg_code,
903 Reg31IsZeroRegister,
904 GetPrintRegSizeInBytes(format));
905 fprintf(stream_,
906 " -> %s0x%016" PRIxPTR "%s\n",
907 clr_memory_address,
908 address,
909 clr_normal);
910}
911
912
913void Simulator::PrintVWrite(uintptr_t address,
914 unsigned reg_code,
915 PrintRegisterFormat format,
916 unsigned lane) {
917 // The templates:
918 // "# v{code}: 0x{rawbits} -> {address}"
919 // "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
920 // "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
921 // Because this trace doesn't represent a change to the source register's
922 // value, only the relevant part of the value is printed. To keep the trace
923 // tidy and readable, the raw value is aligned with the other values in the
924 // register trace.
925 int lane_count = GetPrintRegLaneCount(format);
926 int lane_size = GetPrintRegLaneSizeInBytes(format);
927 int reg_size = GetPrintRegSizeInBytes(format);
928 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
929 if (format & kPrintRegAsFP) {
930 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
931 }
932 fprintf(stream_,
933 " -> %s0x%016" PRIxPTR "%s\n",
934 clr_memory_address,
935 address,
936 clr_normal);
937}
938
939
940// Visitors---------------------------------------------------------------------
941
942void Simulator::VisitUnimplemented(const Instruction* instr) {
943 printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
944 reinterpret_cast<const void*>(instr),
945 instr->GetInstructionBits());
946 VIXL_UNIMPLEMENTED();
947}
948
949
950void Simulator::VisitUnallocated(const Instruction* instr) {
951 printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
952 reinterpret_cast<const void*>(instr),
953 instr->GetInstructionBits());
954 VIXL_UNIMPLEMENTED();
955}
956
957
958void Simulator::VisitPCRelAddressing(const Instruction* instr) {
959 VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
960 (instr->Mask(PCRelAddressingMask) == ADRP));
961
962 WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
963}
964
965
966void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
967 switch (instr->Mask(UnconditionalBranchMask)) {
968 case BL:
969 WriteLr(instr->GetNextInstruction());
970 VIXL_FALLTHROUGH();
971 case B:
972 WritePc(instr->GetImmPCOffsetTarget());
973 break;
974 default:
975 VIXL_UNREACHABLE();
976 }
977}
978
979
980void Simulator::VisitConditionalBranch(const Instruction* instr) {
981 VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
982 if (ConditionPassed(instr->GetConditionBranch())) {
983 WritePc(instr->GetImmPCOffsetTarget());
984 }
985}
986
987
988void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
989 const Instruction* target = Instruction::Cast(ReadXRegister(instr->GetRn()));
990
991 switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
992 case BLR:
993 WriteLr(instr->GetNextInstruction());
994 VIXL_FALLTHROUGH();
995 case BR:
996 case RET:
997 WritePc(target);
998 break;
999 default:
1000 VIXL_UNREACHABLE();
1001 }
1002}
1003
1004
1005void Simulator::VisitTestBranch(const Instruction* instr) {
1006 unsigned bit_pos =
1007 (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
1008 bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
1009 bool take_branch = false;
1010 switch (instr->Mask(TestBranchMask)) {
1011 case TBZ:
1012 take_branch = bit_zero;
1013 break;
1014 case TBNZ:
1015 take_branch = !bit_zero;
1016 break;
1017 default:
1018 VIXL_UNIMPLEMENTED();
1019 }
1020 if (take_branch) {
1021 WritePc(instr->GetImmPCOffsetTarget());
1022 }
1023}
1024
1025
1026void Simulator::VisitCompareBranch(const Instruction* instr) {
1027 unsigned rt = instr->GetRt();
1028 bool take_branch = false;
1029 switch (instr->Mask(CompareBranchMask)) {
1030 case CBZ_w:
1031 take_branch = (ReadWRegister(rt) == 0);
1032 break;
1033 case CBZ_x:
1034 take_branch = (ReadXRegister(rt) == 0);
1035 break;
1036 case CBNZ_w:
1037 take_branch = (ReadWRegister(rt) != 0);
1038 break;
1039 case CBNZ_x:
1040 take_branch = (ReadXRegister(rt) != 0);
1041 break;
1042 default:
1043 VIXL_UNIMPLEMENTED();
1044 }
1045 if (take_branch) {
1046 WritePc(instr->GetImmPCOffsetTarget());
1047 }
1048}
1049
1050
1051void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
1052 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1053 bool set_flags = instr->GetFlagsUpdate();
1054 int64_t new_val = 0;
1055 Instr operation = instr->Mask(AddSubOpMask);
1056
1057 switch (operation) {
1058 case ADD:
1059 case ADDS: {
1060 new_val = AddWithCarry(reg_size,
1061 set_flags,
1062 ReadRegister(reg_size,
1063 instr->GetRn(),
1064 instr->GetRnMode()),
1065 op2);
1066 break;
1067 }
1068 case SUB:
1069 case SUBS: {
1070 new_val = AddWithCarry(reg_size,
1071 set_flags,
1072 ReadRegister(reg_size,
1073 instr->GetRn(),
1074 instr->GetRnMode()),
1075 ~op2,
1076 1);
1077 break;
1078 }
1079 default:
1080 VIXL_UNREACHABLE();
1081 }
1082
1083 WriteRegister(reg_size,
1084 instr->GetRd(),
1085 new_val,
1086 LogRegWrites,
1087 instr->GetRdMode());
1088}
1089
1090
1091void Simulator::VisitAddSubShifted(const Instruction* instr) {
1092 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1093 int64_t op2 = ShiftOperand(reg_size,
1094 ReadRegister(reg_size, instr->GetRm()),
1095 static_cast<Shift>(instr->GetShiftDP()),
1096 instr->GetImmDPShift());
1097 AddSubHelper(instr, op2);
1098}
1099
1100
1101void Simulator::VisitAddSubImmediate(const Instruction* instr) {
1102 int64_t op2 = instr->GetImmAddSub()
1103 << ((instr->GetShiftAddSub() == 1) ? 12 : 0);
1104 AddSubHelper(instr, op2);
1105}
1106
1107
1108void Simulator::VisitAddSubExtended(const Instruction* instr) {
1109 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1110 int64_t op2 = ExtendValue(reg_size,
1111 ReadRegister(reg_size, instr->GetRm()),
1112 static_cast<Extend>(instr->GetExtendMode()),
1113 instr->GetImmExtendShift());
1114 AddSubHelper(instr, op2);
1115}
1116
1117
1118void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
1119 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1120 int64_t op2 = ReadRegister(reg_size, instr->GetRm());
1121 int64_t new_val;
1122
1123 if ((instr->Mask(AddSubOpMask) == SUB) ||
1124 (instr->Mask(AddSubOpMask) == SUBS)) {
1125 op2 = ~op2;
1126 }
1127
1128 new_val = AddWithCarry(reg_size,
1129 instr->GetFlagsUpdate(),
1130 ReadRegister(reg_size, instr->GetRn()),
1131 op2,
1132 ReadC());
1133
1134 WriteRegister(reg_size, instr->GetRd(), new_val);
1135}
1136
1137
1138void Simulator::VisitLogicalShifted(const Instruction* instr) {
1139 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1140 Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
1141 unsigned shift_amount = instr->GetImmDPShift();
1142 int64_t op2 = ShiftOperand(reg_size,
1143 ReadRegister(reg_size, instr->GetRm()),
1144 shift_type,
1145 shift_amount);
1146 if (instr->Mask(NOT) == NOT) {
1147 op2 = ~op2;
1148 }
1149 LogicalHelper(instr, op2);
1150}
1151
1152
1153void Simulator::VisitLogicalImmediate(const Instruction* instr) {
1154 LogicalHelper(instr, instr->GetImmLogical());
1155}
1156
1157
1158void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
1159 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1160 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1161 int64_t result = 0;
1162 bool update_flags = false;
1163
1164 // Switch on the logical operation, stripping out the NOT bit, as it has a
1165 // different meaning for logical immediate instructions.
1166 switch (instr->Mask(LogicalOpMask & ~NOT)) {
1167 case ANDS:
1168 update_flags = true;
1169 VIXL_FALLTHROUGH();
1170 case AND:
1171 result = op1 & op2;
1172 break;
1173 case ORR:
1174 result = op1 | op2;
1175 break;
1176 case EOR:
1177 result = op1 ^ op2;
1178 break;
1179 default:
1180 VIXL_UNIMPLEMENTED();
1181 }
1182
1183 if (update_flags) {
1184 ReadNzcv().SetN(CalcNFlag(result, reg_size));
1185 ReadNzcv().SetZ(CalcZFlag(result));
1186 ReadNzcv().SetC(0);
1187 ReadNzcv().SetV(0);
1188 LogSystemRegister(NZCV);
1189 }
1190
1191 WriteRegister(reg_size,
1192 instr->GetRd(),
1193 result,
1194 LogRegWrites,
1195 instr->GetRdMode());
1196}
1197
1198
1199void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
1200 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1201 ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
1202}
1203
1204
1205void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
1206 ConditionalCompareHelper(instr, instr->GetImmCondCmp());
1207}
1208
1209
1210void Simulator::ConditionalCompareHelper(const Instruction* instr,
1211 int64_t op2) {
1212 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1213 int64_t op1 = ReadRegister(reg_size, instr->GetRn());
1214
1215 if (ConditionPassed(instr->GetCondition())) {
1216 // If the condition passes, set the status flags to the result of comparing
1217 // the operands.
1218 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1219 AddWithCarry(reg_size, true, op1, ~op2, 1);
1220 } else {
1221 VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
1222 AddWithCarry(reg_size, true, op1, op2, 0);
1223 }
1224 } else {
1225 // If the condition fails, set the status flags to the nzcv immediate.
1226 ReadNzcv().SetFlags(instr->GetNzcv());
1227 LogSystemRegister(NZCV);
1228 }
1229}
1230
1231
1232void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
1233 int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
1234 LoadStoreHelper(instr, offset, Offset);
1235}
1236
1237
1238void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
1239 LoadStoreHelper(instr, instr->GetImmLS(), Offset);
1240}
1241
1242
1243void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
1244 LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
1245}
1246
1247
1248void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
1249 LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
1250}
1251
1252
1253void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
1254 Extend ext = static_cast<Extend>(instr->GetExtendMode());
1255 VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
1256 unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
1257
1258 int64_t offset =
1259 ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
1260 LoadStoreHelper(instr, offset, Offset);
1261}
1262
1263
1264void Simulator::LoadStoreHelper(const Instruction* instr,
1265 int64_t offset,
1266 AddrMode addrmode) {
1267 unsigned srcdst = instr->GetRt();
1268 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
1269
1270 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
1271 switch (op) {
1272 case LDRB_w:
1273 WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
1274 break;
1275 case LDRH_w:
1276 WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
1277 break;
1278 case LDR_w:
1279 WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog);
1280 break;
1281 case LDR_x:
1282 WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog);
1283 break;
1284 case LDRSB_w:
1285 WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
1286 break;
1287 case LDRSH_w:
1288 WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
1289 break;
1290 case LDRSB_x:
1291 WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog);
1292 break;
1293 case LDRSH_x:
1294 WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog);
1295 break;
1296 case LDRSW_x:
1297 WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog);
1298 break;
1299 case LDR_b:
1300 WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog);
1301 break;
1302 case LDR_h:
1303 WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog);
1304 break;
1305 case LDR_s:
1306 WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog);
1307 break;
1308 case LDR_d:
1309 WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog);
1310 break;
1311 case LDR_q:
1312 WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog);
1313 break;
1314
1315 case STRB_w:
1316 Memory::Write<uint8_t>(address, ReadWRegister(srcdst));
1317 break;
1318 case STRH_w:
1319 Memory::Write<uint16_t>(address, ReadWRegister(srcdst));
1320 break;
1321 case STR_w:
1322 Memory::Write<uint32_t>(address, ReadWRegister(srcdst));
1323 break;
1324 case STR_x:
1325 Memory::Write<uint64_t>(address, ReadXRegister(srcdst));
1326 break;
1327 case STR_b:
1328 Memory::Write<uint8_t>(address, ReadBRegister(srcdst));
1329 break;
1330 case STR_h:
1331 Memory::Write<uint16_t>(address, ReadHRegister(srcdst));
1332 break;
1333 case STR_s:
1334 Memory::Write<float>(address, ReadSRegister(srcdst));
1335 break;
1336 case STR_d:
1337 Memory::Write<double>(address, ReadDRegister(srcdst));
1338 break;
1339 case STR_q:
1340 Memory::Write<qreg_t>(address, ReadQRegister(srcdst));
1341 break;
1342
1343 // Ignore prfm hint instructions.
1344 case PRFM:
1345 break;
1346
1347 default:
1348 VIXL_UNIMPLEMENTED();
1349 }
1350
1351 unsigned access_size = 1 << instr->GetSizeLS();
1352 if (instr->IsLoad()) {
1353 if ((op == LDR_s) || (op == LDR_d)) {
1354 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1355 } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1356 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1357 } else {
1358 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1359 }
1360 } else if (instr->IsStore()) {
1361 if ((op == STR_s) || (op == STR_d)) {
1362 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1363 } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1364 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1365 } else {
1366 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1367 }
1368 } else {
1369 VIXL_ASSERT(op == PRFM);
1370 }
1371
1372 local_monitor_.MaybeClear();
1373}
1374
1375
1376void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
1377 LoadStorePairHelper(instr, Offset);
1378}
1379
1380
1381void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
1382 LoadStorePairHelper(instr, PreIndex);
1383}
1384
1385
1386void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
1387 LoadStorePairHelper(instr, PostIndex);
1388}
1389
1390
1391void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
1392 LoadStorePairHelper(instr, Offset);
1393}
1394
1395
1396void Simulator::LoadStorePairHelper(const Instruction* instr,
1397 AddrMode addrmode) {
1398 unsigned rt = instr->GetRt();
1399 unsigned rt2 = instr->GetRt2();
1400 int element_size = 1 << instr->GetSizeLSPair();
1401 int64_t offset = instr->GetImmLSPair() * element_size;
1402 uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
1403 uintptr_t address2 = address + element_size;
1404
1405 LoadStorePairOp op =
1406 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1407
1408 // 'rt' and 'rt2' can only be aliased for stores.
1409 VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1410
1411 switch (op) {
1412 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
1413 // will print a more detailed log.
1414 case LDP_w: {
1415 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
1416 WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog);
1417 break;
1418 }
1419 case LDP_s: {
1420 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
1421 WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog);
1422 break;
1423 }
1424 case LDP_x: {
1425 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
1426 WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog);
1427 break;
1428 }
1429 case LDP_d: {
1430 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
1431 WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog);
1432 break;
1433 }
1434 case LDP_q: {
1435 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
1436 WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog);
1437 break;
1438 }
1439 case LDPSW_x: {
1440 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
1441 WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog);
1442 break;
1443 }
1444 case STP_w: {
1445 Memory::Write<uint32_t>(address, ReadWRegister(rt));
1446 Memory::Write<uint32_t>(address2, ReadWRegister(rt2));
1447 break;
1448 }
1449 case STP_s: {
1450 Memory::Write<float>(address, ReadSRegister(rt));
1451 Memory::Write<float>(address2, ReadSRegister(rt2));
1452 break;
1453 }
1454 case STP_x: {
1455 Memory::Write<uint64_t>(address, ReadXRegister(rt));
1456 Memory::Write<uint64_t>(address2, ReadXRegister(rt2));
1457 break;
1458 }
1459 case STP_d: {
1460 Memory::Write<double>(address, ReadDRegister(rt));
1461 Memory::Write<double>(address2, ReadDRegister(rt2));
1462 break;
1463 }
1464 case STP_q: {
1465 Memory::Write<qreg_t>(address, ReadQRegister(rt));
1466 Memory::Write<qreg_t>(address2, ReadQRegister(rt2));
1467 break;
1468 }
1469 default:
1470 VIXL_UNREACHABLE();
1471 }
1472
1473 // Print a detailed trace (including the memory address) instead of the basic
1474 // register:value trace generated by set_*reg().
1475 if (instr->IsLoad()) {
1476 if ((op == LDP_s) || (op == LDP_d)) {
1477 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1478 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1479 } else if (op == LDP_q) {
1480 LogVRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1481 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1482 } else {
1483 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1484 LogRead(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1485 }
1486 } else {
1487 if ((op == STP_s) || (op == STP_d)) {
1488 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(element_size));
1489 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(element_size));
1490 } else if (op == STP_q) {
1491 LogVWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1492 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1493 } else {
1494 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1495 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(element_size));
1496 }
1497 }
1498
1499 local_monitor_.MaybeClear();
1500}
1501
1502
1503void Simulator::PrintExclusiveAccessWarning() {
1504 if (print_exclusive_access_warning_) {
1505 fprintf(stderr,
1506 "%sWARNING:%s VIXL simulator support for "
1507 "load-/store-/clear-exclusive "
1508 "instructions is limited. Refer to the README for details.%s\n",
1509 clr_warning,
1510 clr_warning_message,
1511 clr_normal);
1512 print_exclusive_access_warning_ = false;
1513 }
1514}
1515
1516
1517void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
1518 PrintExclusiveAccessWarning();
1519
1520 unsigned rs = instr->GetRs();
1521 unsigned rt = instr->GetRt();
1522 unsigned rt2 = instr->GetRt2();
1523 unsigned rn = instr->GetRn();
1524
1525 LoadStoreExclusive op =
1526 static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
1527
1528 bool is_acquire_release = instr->GetLdStXAcquireRelease();
1529 bool is_exclusive = !instr->GetLdStXNotExclusive();
1530 bool is_load = instr->GetLdStXLoad();
1531 bool is_pair = instr->GetLdStXPair();
1532
1533 unsigned element_size = 1 << instr->GetLdStXSizeLog2();
1534 unsigned access_size = is_pair ? element_size * 2 : element_size;
1535 uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
1536
1537 // Verify that the address is available to the host.
1538 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1539
1540 // Check the alignment of `address`.
1541 if (AlignDown(address, access_size) != address) {
1542 VIXL_ALIGNMENT_EXCEPTION();
1543 }
1544
1545 // The sp must be aligned to 16 bytes when it is accessed.
1546 if ((rn == 31) && (AlignDown(address, 16) != address)) {
1547 VIXL_ALIGNMENT_EXCEPTION();
1548 }
1549
1550 if (is_load) {
1551 if (is_exclusive) {
1552 local_monitor_.MarkExclusive(address, access_size);
1553 } else {
1554 // Any non-exclusive load can clear the local monitor as a side effect. We
1555 // don't need to do this, but it is useful to stress the simulated code.
1556 local_monitor_.Clear();
1557 }
1558
1559 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
1560 // will print a more detailed log.
1561 switch (op) {
1562 case LDXRB_w:
1563 case LDAXRB_w:
1564 case LDARB_w:
1565 WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog);
1566 break;
1567 case LDXRH_w:
1568 case LDAXRH_w:
1569 case LDARH_w:
1570 WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog);
1571 break;
1572 case LDXR_w:
1573 case LDAXR_w:
1574 case LDAR_w:
1575 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
1576 break;
1577 case LDXR_x:
1578 case LDAXR_x:
1579 case LDAR_x:
1580 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
1581 break;
1582 case LDXP_w:
1583 case LDAXP_w:
1584 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
1585 WriteWRegister(rt2,
1586 Memory::Read<uint32_t>(address + element_size),
1587 NoRegLog);
1588 break;
1589 case LDXP_x:
1590 case LDAXP_x:
1591 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
1592 WriteXRegister(rt2,
1593 Memory::Read<uint64_t>(address + element_size),
1594 NoRegLog);
1595 break;
1596 default:
1597 VIXL_UNREACHABLE();
1598 }
1599
1600 if (is_acquire_release) {
1601 // Approximate load-acquire by issuing a full barrier after the load.
1602 __sync_synchronize();
1603 }
1604
1605 LogRead(address, rt, GetPrintRegisterFormatForSize(element_size));
1606 if (is_pair) {
1607 LogRead(address + element_size,
1608 rt2,
1609 GetPrintRegisterFormatForSize(element_size));
1610 }
1611 } else {
1612 if (is_acquire_release) {
1613 // Approximate store-release by issuing a full barrier before the store.
1614 __sync_synchronize();
1615 }
1616
1617 bool do_store = true;
1618 if (is_exclusive) {
1619 do_store = local_monitor_.IsExclusive(address, access_size) &&
1620 global_monitor_.IsExclusive(address, access_size);
1621 WriteWRegister(rs, do_store ? 0 : 1);
1622
1623 // - All exclusive stores explicitly clear the local monitor.
1624 local_monitor_.Clear();
1625 } else {
1626 // - Any other store can clear the local monitor as a side effect.
1627 local_monitor_.MaybeClear();
1628 }
1629
1630 if (do_store) {
1631 switch (op) {
1632 case STXRB_w:
1633 case STLXRB_w:
1634 case STLRB_w:
1635 Memory::Write<uint8_t>(address, ReadWRegister(rt));
1636 break;
1637 case STXRH_w:
1638 case STLXRH_w:
1639 case STLRH_w:
1640 Memory::Write<uint16_t>(address, ReadWRegister(rt));
1641 break;
1642 case STXR_w:
1643 case STLXR_w:
1644 case STLR_w:
1645 Memory::Write<uint32_t>(address, ReadWRegister(rt));
1646 break;
1647 case STXR_x:
1648 case STLXR_x:
1649 case STLR_x:
1650 Memory::Write<uint64_t>(address, ReadXRegister(rt));
1651 break;
1652 case STXP_w:
1653 case STLXP_w:
1654 Memory::Write<uint32_t>(address, ReadWRegister(rt));
1655 Memory::Write<uint32_t>(address + element_size, ReadWRegister(rt2));
1656 break;
1657 case STXP_x:
1658 case STLXP_x:
1659 Memory::Write<uint64_t>(address, ReadXRegister(rt));
1660 Memory::Write<uint64_t>(address + element_size, ReadXRegister(rt2));
1661 break;
1662 default:
1663 VIXL_UNREACHABLE();
1664 }
1665
1666 LogWrite(address, rt, GetPrintRegisterFormatForSize(element_size));
1667 if (is_pair) {
1668 LogWrite(address + element_size,
1669 rt2,
1670 GetPrintRegisterFormatForSize(element_size));
1671 }
1672 }
1673 }
1674}
1675
1676
1677void Simulator::VisitLoadLiteral(const Instruction* instr) {
1678 unsigned rt = instr->GetRt();
1679 uint64_t address = instr->GetLiteralAddress<uint64_t>();
1680
1681 // Verify that the calculated address is available to the host.
1682 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1683
1684 switch (instr->Mask(LoadLiteralMask)) {
1685 // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
1686 // print a more detailed log.
1687 case LDR_w_lit:
1688 WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog);
1689 LogRead(address, rt, kPrintWReg);
1690 break;
1691 case LDR_x_lit:
1692 WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog);
1693 LogRead(address, rt, kPrintXReg);
1694 break;
1695 case LDR_s_lit:
1696 WriteSRegister(rt, Memory::Read<float>(address), NoRegLog);
1697 LogVRead(address, rt, kPrintSReg);
1698 break;
1699 case LDR_d_lit:
1700 WriteDRegister(rt, Memory::Read<double>(address), NoRegLog);
1701 LogVRead(address, rt, kPrintDReg);
1702 break;
1703 case LDR_q_lit:
1704 WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog);
1705 LogVRead(address, rt, kPrintReg1Q);
1706 break;
1707 case LDRSW_x_lit:
1708 WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog);
1709 LogRead(address, rt, kPrintWReg);
1710 break;
1711
1712 // Ignore prfm hint instructions.
1713 case PRFM_lit:
1714 break;
1715
1716 default:
1717 VIXL_UNREACHABLE();
1718 }
1719
1720 local_monitor_.MaybeClear();
1721}
1722
1723
1724uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
1725 int64_t offset,
1726 AddrMode addrmode) {
1727 uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
1728
1729 if ((addr_reg == 31) && ((address % 16) != 0)) {
1730 // When the base register is SP the stack pointer is required to be
1731 // quadword aligned prior to the address calculation and write-backs.
1732 // Misalignment will cause a stack alignment fault.
1733 VIXL_ALIGNMENT_EXCEPTION();
1734 }
1735
1736 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1737 VIXL_ASSERT(offset != 0);
1738 // Only preindex should log the register update here. For Postindex, the
1739 // update will be printed automatically by LogWrittenRegisters _after_ the
1740 // memory access itself is logged.
1741 RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
1742 WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
1743 }
1744
1745 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1746 address += offset;
1747 }
1748
1749 // Verify that the calculated address is available to the host.
1750 VIXL_ASSERT(address == static_cast<uintptr_t>(address));
1751
1752 return static_cast<uintptr_t>(address);
1753}
1754
1755
1756void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
1757 MoveWideImmediateOp mov_op =
1758 static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
1759 int64_t new_xn_val = 0;
1760
1761 bool is_64_bits = instr->GetSixtyFourBits() == 1;
1762 // Shift is limited for W operations.
1763 VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
1764
1765 // Get the shifted immediate.
1766 int64_t shift = instr->GetShiftMoveWide() * 16;
1767 int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
1768 << shift;
1769
1770 // Compute the new value.
1771 switch (mov_op) {
1772 case MOVN_w:
1773 case MOVN_x: {
1774 new_xn_val = ~shifted_imm16;
1775 if (!is_64_bits) new_xn_val &= kWRegMask;
1776 break;
1777 }
1778 case MOVK_w:
1779 case MOVK_x: {
1780 unsigned reg_code = instr->GetRd();
1781 int64_t prev_xn_val =
1782 is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
1783 new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
1784 break;
1785 }
1786 case MOVZ_w:
1787 case MOVZ_x: {
1788 new_xn_val = shifted_imm16;
1789 break;
1790 }
1791 default:
1792 VIXL_UNREACHABLE();
1793 }
1794
1795 // Update the destination register.
1796 WriteXRegister(instr->GetRd(), new_xn_val);
1797}
1798
1799
1800void Simulator::VisitConditionalSelect(const Instruction* instr) {
1801 uint64_t new_val = ReadXRegister(instr->GetRn());
1802
1803 if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
1804 new_val = ReadXRegister(instr->GetRm());
1805 switch (instr->Mask(ConditionalSelectMask)) {
1806 case CSEL_w:
1807 case CSEL_x:
1808 break;
1809 case CSINC_w:
1810 case CSINC_x:
1811 new_val++;
1812 break;
1813 case CSINV_w:
1814 case CSINV_x:
1815 new_val = ~new_val;
1816 break;
1817 case CSNEG_w:
1818 case CSNEG_x:
1819 new_val = -new_val;
1820 break;
1821 default:
1822 VIXL_UNIMPLEMENTED();
1823 }
1824 }
1825 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1826 WriteRegister(reg_size, instr->GetRd(), new_val);
1827}
1828
1829
1830void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
1831 unsigned dst = instr->GetRd();
1832 unsigned src = instr->GetRn();
1833
1834 switch (instr->Mask(DataProcessing1SourceMask)) {
1835 case RBIT_w:
1836 WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
1837 break;
1838 case RBIT_x:
1839 WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
1840 break;
1841 case REV16_w:
1842 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
1843 break;
1844 case REV16_x:
1845 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
1846 break;
1847 case REV_w:
1848 WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
1849 break;
1850 case REV32_x:
1851 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
1852 break;
1853 case REV_x:
1854 WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
1855 break;
1856 case CLZ_w:
1857 WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
1858 break;
1859 case CLZ_x:
1860 WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
1861 break;
1862 case CLS_w:
1863 WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
1864 break;
1865 case CLS_x:
1866 WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
1867 break;
1868 default:
1869 VIXL_UNIMPLEMENTED();
1870 }
1871}
1872
1873
1874uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
1875 VIXL_ASSERT((n > 32) && (n <= 64));
1876 for (unsigned i = (n - 1); i >= 32; i--) {
1877 if (((data >> i) & 1) != 0) {
1878 uint64_t polysh32 = (uint64_t)poly << (i - 32);
1879 uint64_t mask = (UINT64_C(1) << i) - 1;
1880 data = ((data & mask) ^ polysh32);
1881 }
1882 }
1883 return data & 0xffffffff;
1884}
1885
1886
1887template <typename T>
1888uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
1889 unsigned size = sizeof(val) * 8; // Number of bits in type T.
1890 VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
1891 uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
1892 uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
1893 return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
1894}
1895
1896
1897uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
1898 // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
1899 // the CRC of each 32-bit word sequentially.
1900 acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
1901 return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
1902}
1903
1904
1905void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
1906 Shift shift_op = NO_SHIFT;
1907 int64_t result = 0;
1908 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
1909
1910 switch (instr->Mask(DataProcessing2SourceMask)) {
1911 case SDIV_w: {
1912 int32_t rn = ReadWRegister(instr->GetRn());
1913 int32_t rm = ReadWRegister(instr->GetRm());
1914 if ((rn == kWMinInt) && (rm == -1)) {
1915 result = kWMinInt;
1916 } else if (rm == 0) {
1917 // Division by zero can be trapped, but not on A-class processors.
1918 result = 0;
1919 } else {
1920 result = rn / rm;
1921 }
1922 break;
1923 }
1924 case SDIV_x: {
1925 int64_t rn = ReadXRegister(instr->GetRn());
1926 int64_t rm = ReadXRegister(instr->GetRm());
1927 if ((rn == kXMinInt) && (rm == -1)) {
1928 result = kXMinInt;
1929 } else if (rm == 0) {
1930 // Division by zero can be trapped, but not on A-class processors.
1931 result = 0;
1932 } else {
1933 result = rn / rm;
1934 }
1935 break;
1936 }
1937 case UDIV_w: {
1938 uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
1939 uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
1940 if (rm == 0) {
1941 // Division by zero can be trapped, but not on A-class processors.
1942 result = 0;
1943 } else {
1944 result = rn / rm;
1945 }
1946 break;
1947 }
1948 case UDIV_x: {
1949 uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
1950 uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
1951 if (rm == 0) {
1952 // Division by zero can be trapped, but not on A-class processors.
1953 result = 0;
1954 } else {
1955 result = rn / rm;
1956 }
1957 break;
1958 }
1959 case LSLV_w:
1960 case LSLV_x:
1961 shift_op = LSL;
1962 break;
1963 case LSRV_w:
1964 case LSRV_x:
1965 shift_op = LSR;
1966 break;
1967 case ASRV_w:
1968 case ASRV_x:
1969 shift_op = ASR;
1970 break;
1971 case RORV_w:
1972 case RORV_x:
1973 shift_op = ROR;
1974 break;
1975 case CRC32B: {
1976 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
1977 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
1978 result = Crc32Checksum(acc, val, CRC32_POLY);
1979 break;
1980 }
1981 case CRC32H: {
1982 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
1983 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
1984 result = Crc32Checksum(acc, val, CRC32_POLY);
1985 break;
1986 }
1987 case CRC32W: {
1988 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
1989 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
1990 result = Crc32Checksum(acc, val, CRC32_POLY);
1991 break;
1992 }
1993 case CRC32X: {
1994 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
1995 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
1996 result = Crc32Checksum(acc, val, CRC32_POLY);
1997 reg_size = kWRegSize;
1998 break;
1999 }
2000 case CRC32CB: {
2001 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2002 uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
2003 result = Crc32Checksum(acc, val, CRC32C_POLY);
2004 break;
2005 }
2006 case CRC32CH: {
2007 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2008 uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
2009 result = Crc32Checksum(acc, val, CRC32C_POLY);
2010 break;
2011 }
2012 case CRC32CW: {
2013 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2014 uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
2015 result = Crc32Checksum(acc, val, CRC32C_POLY);
2016 break;
2017 }
2018 case CRC32CX: {
2019 uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
2020 uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
2021 result = Crc32Checksum(acc, val, CRC32C_POLY);
2022 reg_size = kWRegSize;
2023 break;
2024 }
2025 default:
2026 VIXL_UNIMPLEMENTED();
2027 }
2028
2029 if (shift_op != NO_SHIFT) {
2030 // Shift distance encoded in the least-significant five/six bits of the
2031 // register.
2032 int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
2033 unsigned shift = ReadWRegister(instr->GetRm()) & mask;
2034 result = ShiftOperand(reg_size,
2035 ReadRegister(reg_size, instr->GetRn()),
2036 shift_op,
2037 shift);
2038 }
2039 WriteRegister(reg_size, instr->GetRd(), result);
2040}
2041
2042
2043// The algorithm used is adapted from the one described in section 8.2 of
2044// Hacker's Delight, by Henry S. Warren, Jr.
2045// It assumes that a right shift on a signed integer is an arithmetic shift.
2046// Type T must be either uint64_t or int64_t.
2047template <typename T>
2048static T MultiplyHigh(T u, T v) {
2049 uint64_t u0, v0, w0;
2050 T u1, v1, w1, w2, t;
2051
2052 VIXL_ASSERT(sizeof(u) == sizeof(u0));
2053
2054 u0 = u & 0xffffffff;
2055 u1 = u >> 32;
2056 v0 = v & 0xffffffff;
2057 v1 = v >> 32;
2058
2059 w0 = u0 * v0;
2060 t = u1 * v0 + (w0 >> 32);
2061 w1 = t & 0xffffffff;
2062 w2 = t >> 32;
2063 w1 = u0 * v1 + w1;
2064
2065 return u1 * v1 + w2 + (w1 >> 32);
2066}
2067
2068
2069void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
2070 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2071
2072 uint64_t result = 0;
2073 // Extract and sign- or zero-extend 32-bit arguments for widening operations.
2074 uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
2075 uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
2076 int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
2077 int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
2078 switch (instr->Mask(DataProcessing3SourceMask)) {
2079 case MADD_w:
2080 case MADD_x:
2081 result = ReadXRegister(instr->GetRa()) +
2082 (ReadXRegister(instr->GetRn()) * ReadXRegister(instr->GetRm()));
2083 break;
2084 case MSUB_w:
2085 case MSUB_x:
2086 result = ReadXRegister(instr->GetRa()) -
2087 (ReadXRegister(instr->GetRn()) * ReadXRegister(instr->GetRm()));
2088 break;
2089 case SMADDL_x:
2090 result = ReadXRegister(instr->GetRa()) + (rn_s32 * rm_s32);
2091 break;
2092 case SMSUBL_x:
2093 result = ReadXRegister(instr->GetRa()) - (rn_s32 * rm_s32);
2094 break;
2095 case UMADDL_x:
2096 result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
2097 break;
2098 case UMSUBL_x:
2099 result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
2100 break;
2101 case UMULH_x:
2102 result = MultiplyHigh(ReadRegister<uint64_t>(instr->GetRn()),
2103 ReadRegister<uint64_t>(instr->GetRm()));
2104 break;
2105 case SMULH_x:
2106 result = MultiplyHigh(ReadXRegister(instr->GetRn()),
2107 ReadXRegister(instr->GetRm()));
2108 break;
2109 default:
2110 VIXL_UNIMPLEMENTED();
2111 }
2112 WriteRegister(reg_size, instr->GetRd(), result);
2113}
2114
2115
2116void Simulator::VisitBitfield(const Instruction* instr) {
2117 unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
2118 int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
2119 int64_t R = instr->GetImmR();
2120 int64_t S = instr->GetImmS();
2121 int64_t diff = S - R;
2122 int64_t mask;
2123 if (diff >= 0) {
2124 mask = (diff < (reg_size - 1)) ? (INT64_C(1) << (diff + 1)) - 1 : reg_mask;
2125 } else {
2126 mask = (INT64_C(1) << (S + 1)) - 1;
2127 mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R));
2128 diff += reg_size;
2129 }
2130
2131 // inzero indicates if the extracted bitfield is inserted into the
2132 // destination register value or in zero.
2133 // If extend is true, extend the sign of the extracted bitfield.
2134 bool inzero = false;
2135 bool extend = false;
2136 switch (instr->Mask(BitfieldMask)) {
2137 case BFM_x:
2138 case BFM_w:
2139 break;
2140 case SBFM_x:
2141 case SBFM_w:
2142 inzero = true;
2143 extend = true;
2144 break;
2145 case UBFM_x:
2146 case UBFM_w:
2147 inzero = true;
2148 break;
2149 default:
2150 VIXL_UNIMPLEMENTED();
2151 }
2152
2153 int64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
2154 int64_t src = ReadRegister(reg_size, instr->GetRn());
2155 // Rotate source bitfield into place.
2156 int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R));
2157 // Determine the sign extension.
2158 int64_t topbits = ((INT64_C(1) << (reg_size - diff - 1)) - 1) << (diff + 1);
2159 int64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
2160
2161 // Merge sign extension, dest/zero and bitfield.
2162 result = signbits | (result & mask) | (dst & ~mask);
2163
2164 WriteRegister(reg_size, instr->GetRd(), result);
2165}
2166
2167
2168void Simulator::VisitExtract(const Instruction* instr) {
2169 unsigned lsb = instr->GetImmS();
2170 unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
2171 uint64_t low_res =
2172 static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
2173 uint64_t high_res = (lsb == 0) ? 0 : ReadRegister(reg_size, instr->GetRn())
2174 << (reg_size - lsb);
2175 WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
2176}
2177
2178
2179void Simulator::VisitFPImmediate(const Instruction* instr) {
2180 AssertSupportedFPCR();
2181
2182 unsigned dest = instr->GetRd();
2183 switch (instr->Mask(FPImmediateMask)) {
2184 case FMOV_s_imm:
2185 WriteSRegister(dest, instr->GetImmFP32());
2186 break;
2187 case FMOV_d_imm:
2188 WriteDRegister(dest, instr->GetImmFP64());
2189 break;
2190 default:
2191 VIXL_UNREACHABLE();
2192 }
2193}
2194
2195
2196void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
2197 AssertSupportedFPCR();
2198
2199 unsigned dst = instr->GetRd();
2200 unsigned src = instr->GetRn();
2201
2202 FPRounding round = ReadRMode();
2203
2204 switch (instr->Mask(FPIntegerConvertMask)) {
2205 case FCVTAS_ws:
2206 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
2207 break;
2208 case FCVTAS_xs:
2209 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
2210 break;
2211 case FCVTAS_wd:
2212 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
2213 break;
2214 case FCVTAS_xd:
2215 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
2216 break;
2217 case FCVTAU_ws:
2218 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
2219 break;
2220 case FCVTAU_xs:
2221 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
2222 break;
2223 case FCVTAU_wd:
2224 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
2225 break;
2226 case FCVTAU_xd:
2227 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
2228 break;
2229 case FCVTMS_ws:
2230 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
2231 break;
2232 case FCVTMS_xs:
2233 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
2234 break;
2235 case FCVTMS_wd:
2236 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
2237 break;
2238 case FCVTMS_xd:
2239 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
2240 break;
2241 case FCVTMU_ws:
2242 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
2243 break;
2244 case FCVTMU_xs:
2245 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
2246 break;
2247 case FCVTMU_wd:
2248 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
2249 break;
2250 case FCVTMU_xd:
2251 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
2252 break;
2253 case FCVTPS_ws:
2254 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
2255 break;
2256 case FCVTPS_xs:
2257 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
2258 break;
2259 case FCVTPS_wd:
2260 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
2261 break;
2262 case FCVTPS_xd:
2263 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
2264 break;
2265 case FCVTPU_ws:
2266 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
2267 break;
2268 case FCVTPU_xs:
2269 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
2270 break;
2271 case FCVTPU_wd:
2272 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
2273 break;
2274 case FCVTPU_xd:
2275 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
2276 break;
2277 case FCVTNS_ws:
2278 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
2279 break;
2280 case FCVTNS_xs:
2281 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
2282 break;
2283 case FCVTNS_wd:
2284 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
2285 break;
2286 case FCVTNS_xd:
2287 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
2288 break;
2289 case FCVTNU_ws:
2290 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
2291 break;
2292 case FCVTNU_xs:
2293 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
2294 break;
2295 case FCVTNU_wd:
2296 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
2297 break;
2298 case FCVTNU_xd:
2299 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
2300 break;
2301 case FCVTZS_ws:
2302 WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
2303 break;
2304 case FCVTZS_xs:
2305 WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
2306 break;
2307 case FCVTZS_wd:
2308 WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
2309 break;
2310 case FCVTZS_xd:
2311 WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
2312 break;
2313 case FCVTZU_ws:
2314 WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
2315 break;
2316 case FCVTZU_xs:
2317 WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
2318 break;
2319 case FCVTZU_wd:
2320 WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
2321 break;
2322 case FCVTZU_xd:
2323 WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
2324 break;
2325 case FMOV_ws:
2326 WriteWRegister(dst, ReadSRegisterBits(src));
2327 break;
2328 case FMOV_xd:
2329 WriteXRegister(dst, ReadDRegisterBits(src));
2330 break;
2331 case FMOV_sw:
2332 WriteSRegisterBits(dst, ReadWRegister(src));
2333 break;
2334 case FMOV_dx:
2335 WriteDRegisterBits(dst, ReadXRegister(src));
2336 break;
2337 case FMOV_d1_x:
2338 LogicVRegister(ReadVRegister(dst))
2339 .SetUint(kFormatD, 1, ReadXRegister(src));
2340 break;
2341 case FMOV_x_d1:
2342 WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
2343 break;
2344
2345 // A 32-bit input can be handled in the same way as a 64-bit input, since
2346 // the sign- or zero-extension will not affect the conversion.
2347 case SCVTF_dx:
2348 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
2349 break;
2350 case SCVTF_dw:
2351 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
2352 break;
2353 case UCVTF_dx:
2354 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
2355 break;
2356 case UCVTF_dw: {
2357 WriteDRegister(dst,
2358 UFixedToDouble(static_cast<uint32_t>(ReadWRegister(src)),
2359 0,
2360 round));
2361 break;
2362 }
2363 case SCVTF_sx:
2364 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
2365 break;
2366 case SCVTF_sw:
2367 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
2368 break;
2369 case UCVTF_sx:
2370 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
2371 break;
2372 case UCVTF_sw: {
2373 WriteSRegister(dst,
2374 UFixedToFloat(static_cast<uint32_t>(ReadWRegister(src)),
2375 0,
2376 round));
2377 break;
2378 }
2379
2380 default:
2381 VIXL_UNREACHABLE();
2382 }
2383}
2384
2385
2386void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
2387 AssertSupportedFPCR();
2388
2389 unsigned dst = instr->GetRd();
2390 unsigned src = instr->GetRn();
2391 int fbits = 64 - instr->GetFPScale();
2392
2393 FPRounding round = ReadRMode();
2394
2395 switch (instr->Mask(FPFixedPointConvertMask)) {
2396 // A 32-bit input can be handled in the same way as a 64-bit input, since
2397 // the sign- or zero-extension will not affect the conversion.
2398 case SCVTF_dx_fixed:
2399 WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
2400 break;
2401 case SCVTF_dw_fixed:
2402 WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
2403 break;
2404 case UCVTF_dx_fixed:
2405 WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
2406 break;
2407 case UCVTF_dw_fixed: {
2408 WriteDRegister(dst,
2409 UFixedToDouble(static_cast<uint32_t>(ReadWRegister(src)),
2410 fbits,
2411 round));
2412 break;
2413 }
2414 case SCVTF_sx_fixed:
2415 WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
2416 break;
2417 case SCVTF_sw_fixed:
2418 WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
2419 break;
2420 case UCVTF_sx_fixed:
2421 WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
2422 break;
2423 case UCVTF_sw_fixed: {
2424 WriteSRegister(dst,
2425 UFixedToFloat(static_cast<uint32_t>(ReadWRegister(src)),
2426 fbits,
2427 round));
2428 break;
2429 }
2430 case FCVTZS_xd_fixed:
2431 WriteXRegister(dst,
2432 FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
2433 FPZero));
2434 break;
2435 case FCVTZS_wd_fixed:
2436 WriteWRegister(dst,
2437 FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
2438 FPZero));
2439 break;
2440 case FCVTZU_xd_fixed:
2441 WriteXRegister(dst,
2442 FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
2443 FPZero));
2444 break;
2445 case FCVTZU_wd_fixed:
2446 WriteWRegister(dst,
2447 FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
2448 FPZero));
2449 break;
2450 case FCVTZS_xs_fixed:
2451 WriteXRegister(dst,
2452 FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
2453 FPZero));
2454 break;
2455 case FCVTZS_ws_fixed:
2456 WriteWRegister(dst,
2457 FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
2458 FPZero));
2459 break;
2460 case FCVTZU_xs_fixed:
2461 WriteXRegister(dst,
2462 FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
2463 FPZero));
2464 break;
2465 case FCVTZU_ws_fixed:
2466 WriteWRegister(dst,
2467 FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
2468 FPZero));
2469 break;
2470 default:
2471 VIXL_UNREACHABLE();
2472 }
2473}
2474
2475
2476void Simulator::VisitFPCompare(const Instruction* instr) {
2477 AssertSupportedFPCR();
2478
2479 FPTrapFlags trap = DisableTrap;
2480 switch (instr->Mask(FPCompareMask)) {
2481 case FCMPE_s:
2482 trap = EnableTrap;
2483 VIXL_FALLTHROUGH();
2484 case FCMP_s:
2485 FPCompare(ReadSRegister(instr->GetRn()),
2486 ReadSRegister(instr->GetRm()),
2487 trap);
2488 break;
2489 case FCMPE_d:
2490 trap = EnableTrap;
2491 VIXL_FALLTHROUGH();
2492 case FCMP_d:
2493 FPCompare(ReadDRegister(instr->GetRn()),
2494 ReadDRegister(instr->GetRm()),
2495 trap);
2496 break;
2497 case FCMPE_s_zero:
2498 trap = EnableTrap;
2499 VIXL_FALLTHROUGH();
2500 case FCMP_s_zero:
2501 FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
2502 break;
2503 case FCMPE_d_zero:
2504 trap = EnableTrap;
2505 VIXL_FALLTHROUGH();
2506 case FCMP_d_zero:
2507 FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
2508 break;
2509 default:
2510 VIXL_UNIMPLEMENTED();
2511 }
2512}
2513
2514
2515void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
2516 AssertSupportedFPCR();
2517
2518 FPTrapFlags trap = DisableTrap;
2519 switch (instr->Mask(FPConditionalCompareMask)) {
2520 case FCCMPE_s:
2521 trap = EnableTrap;
2522 VIXL_FALLTHROUGH();
2523 case FCCMP_s:
2524 if (ConditionPassed(instr->GetCondition())) {
2525 FPCompare(ReadSRegister(instr->GetRn()),
2526 ReadSRegister(instr->GetRm()),
2527 trap);
2528 } else {
2529 ReadNzcv().SetFlags(instr->GetNzcv());
2530 LogSystemRegister(NZCV);
2531 }
2532 break;
2533 case FCCMPE_d:
2534 trap = EnableTrap;
2535 VIXL_FALLTHROUGH();
2536 case FCCMP_d:
2537 if (ConditionPassed(instr->GetCondition())) {
2538 FPCompare(ReadDRegister(instr->GetRn()),
2539 ReadDRegister(instr->GetRm()),
2540 trap);
2541 } else {
2542 ReadNzcv().SetFlags(instr->GetNzcv());
2543 LogSystemRegister(NZCV);
2544 }
2545 break;
2546 default:
2547 VIXL_UNIMPLEMENTED();
2548 }
2549}
2550
2551
2552void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
2553 AssertSupportedFPCR();
2554
2555 Instr selected;
2556 if (ConditionPassed(instr->GetCondition())) {
2557 selected = instr->GetRn();
2558 } else {
2559 selected = instr->GetRm();
2560 }
2561
2562 switch (instr->Mask(FPConditionalSelectMask)) {
2563 case FCSEL_s:
2564 WriteSRegister(instr->GetRd(), ReadSRegister(selected));
2565 break;
2566 case FCSEL_d:
2567 WriteDRegister(instr->GetRd(), ReadDRegister(selected));
2568 break;
2569 default:
2570 VIXL_UNIMPLEMENTED();
2571 }
2572}
2573
2574
2575void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
2576 AssertSupportedFPCR();
2577
2578 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
2579 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2580 SimVRegister& rd = ReadVRegister(instr->GetRd());
2581 SimVRegister& rn = ReadVRegister(instr->GetRn());
2582 bool inexact_exception = false;
2583
2584 unsigned fd = instr->GetRd();
2585 unsigned fn = instr->GetRn();
2586
2587 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2588 case FMOV_s:
2589 WriteSRegister(fd, ReadSRegister(fn));
2590 return;
2591 case FMOV_d:
2592 WriteDRegister(fd, ReadDRegister(fn));
2593 return;
2594 case FABS_s:
2595 case FABS_d:
2596 fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
2597 // Explicitly log the register update whilst we have type information.
2598 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2599 return;
2600 case FNEG_s:
2601 case FNEG_d:
2602 fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
2603 // Explicitly log the register update whilst we have type information.
2604 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2605 return;
2606 case FCVT_ds:
2607 WriteDRegister(fd, FPToDouble(ReadSRegister(fn)));
2608 return;
2609 case FCVT_sd:
2610 WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven));
2611 return;
2612 case FCVT_hs:
2613 WriteHRegister(fd, FPToFloat16(ReadSRegister(fn), FPTieEven));
2614 return;
2615 case FCVT_sh:
2616 WriteSRegister(fd, FPToFloat(ReadHRegister(fn)));
2617 return;
2618 case FCVT_dh:
2619 WriteDRegister(fd, FPToDouble(FPToFloat(ReadHRegister(fn))));
2620 return;
2621 case FCVT_hd:
2622 WriteHRegister(fd, FPToFloat16(ReadDRegister(fn), FPTieEven));
2623 return;
2624 case FSQRT_s:
2625 case FSQRT_d:
2626 fsqrt(vform, rd, rn);
2627 // Explicitly log the register update whilst we have type information.
2628 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2629 return;
2630 case FRINTI_s:
2631 case FRINTI_d:
2632 break; // Use FPCR rounding mode.
2633 case FRINTX_s:
2634 case FRINTX_d:
2635 inexact_exception = true;
2636 break;
2637 case FRINTA_s:
2638 case FRINTA_d:
2639 fpcr_rounding = FPTieAway;
2640 break;
2641 case FRINTM_s:
2642 case FRINTM_d:
2643 fpcr_rounding = FPNegativeInfinity;
2644 break;
2645 case FRINTN_s:
2646 case FRINTN_d:
2647 fpcr_rounding = FPTieEven;
2648 break;
2649 case FRINTP_s:
2650 case FRINTP_d:
2651 fpcr_rounding = FPPositiveInfinity;
2652 break;
2653 case FRINTZ_s:
2654 case FRINTZ_d:
2655 fpcr_rounding = FPZero;
2656 break;
2657 default:
2658 VIXL_UNIMPLEMENTED();
2659 }
2660
2661 // Only FRINT* instructions fall through the switch above.
2662 frint(vform, rd, rn, fpcr_rounding, inexact_exception);
2663 // Explicitly log the register update whilst we have type information.
2664 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2665}
2666
2667
2668void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
2669 AssertSupportedFPCR();
2670
2671 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2672 SimVRegister& rd = ReadVRegister(instr->GetRd());
2673 SimVRegister& rn = ReadVRegister(instr->GetRn());
2674 SimVRegister& rm = ReadVRegister(instr->GetRm());
2675
2676 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2677 case FADD_s:
2678 case FADD_d:
2679 fadd(vform, rd, rn, rm);
2680 break;
2681 case FSUB_s:
2682 case FSUB_d:
2683 fsub(vform, rd, rn, rm);
2684 break;
2685 case FMUL_s:
2686 case FMUL_d:
2687 fmul(vform, rd, rn, rm);
2688 break;
2689 case FNMUL_s:
2690 case FNMUL_d:
2691 fnmul(vform, rd, rn, rm);
2692 break;
2693 case FDIV_s:
2694 case FDIV_d:
2695 fdiv(vform, rd, rn, rm);
2696 break;
2697 case FMAX_s:
2698 case FMAX_d:
2699 fmax(vform, rd, rn, rm);
2700 break;
2701 case FMIN_s:
2702 case FMIN_d:
2703 fmin(vform, rd, rn, rm);
2704 break;
2705 case FMAXNM_s:
2706 case FMAXNM_d:
2707 fmaxnm(vform, rd, rn, rm);
2708 break;
2709 case FMINNM_s:
2710 case FMINNM_d:
2711 fminnm(vform, rd, rn, rm);
2712 break;
2713 default:
2714 VIXL_UNREACHABLE();
2715 }
2716 // Explicitly log the register update whilst we have type information.
2717 LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
2718}
2719
2720
2721void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
2722 AssertSupportedFPCR();
2723
2724 unsigned fd = instr->GetRd();
2725 unsigned fn = instr->GetRn();
2726 unsigned fm = instr->GetRm();
2727 unsigned fa = instr->GetRa();
2728
2729 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2730 // fd = fa +/- (fn * fm)
2731 case FMADD_s:
2732 WriteSRegister(fd,
2733 FPMulAdd(ReadSRegister(fa),
2734 ReadSRegister(fn),
2735 ReadSRegister(fm)));
2736 break;
2737 case FMSUB_s:
2738 WriteSRegister(fd,
2739 FPMulAdd(ReadSRegister(fa),
2740 -ReadSRegister(fn),
2741 ReadSRegister(fm)));
2742 break;
2743 case FMADD_d:
2744 WriteDRegister(fd,
2745 FPMulAdd(ReadDRegister(fa),
2746 ReadDRegister(fn),
2747 ReadDRegister(fm)));
2748 break;
2749 case FMSUB_d:
2750 WriteDRegister(fd,
2751 FPMulAdd(ReadDRegister(fa),
2752 -ReadDRegister(fn),
2753 ReadDRegister(fm)));
2754 break;
2755 // Negated variants of the above.
2756 case FNMADD_s:
2757 WriteSRegister(fd,
2758 FPMulAdd(-ReadSRegister(fa),
2759 -ReadSRegister(fn),
2760 ReadSRegister(fm)));
2761 break;
2762 case FNMSUB_s:
2763 WriteSRegister(fd,
2764 FPMulAdd(-ReadSRegister(fa),
2765 ReadSRegister(fn),
2766 ReadSRegister(fm)));
2767 break;
2768 case FNMADD_d:
2769 WriteDRegister(fd,
2770 FPMulAdd(-ReadDRegister(fa),
2771 -ReadDRegister(fn),
2772 ReadDRegister(fm)));
2773 break;
2774 case FNMSUB_d:
2775 WriteDRegister(fd,
2776 FPMulAdd(-ReadDRegister(fa),
2777 ReadDRegister(fn),
2778 ReadDRegister(fm)));
2779 break;
2780 default:
2781 VIXL_UNIMPLEMENTED();
2782 }
2783}
2784
2785
2786bool Simulator::FPProcessNaNs(const Instruction* instr) {
2787 unsigned fd = instr->GetRd();
2788 unsigned fn = instr->GetRn();
2789 unsigned fm = instr->GetRm();
2790 bool done = false;
2791
2792 if (instr->Mask(FP64) == FP64) {
2793 double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
2794 if (std::isnan(result)) {
2795 WriteDRegister(fd, result);
2796 done = true;
2797 }
2798 } else {
2799 float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
2800 if (std::isnan(result)) {
2801 WriteSRegister(fd, result);
2802 done = true;
2803 }
2804 }
2805
2806 return done;
2807}
2808
2809
2810void Simulator::SysOp_W(int op, int64_t val) {
2811 switch (op) {
2812 case IVAU:
2813 case CVAC:
2814 case CVAU:
2815 case CIVAC: {
2816 // Perform a dummy memory access to ensure that we have read access
2817 // to the specified address.
2818 volatile uint8_t y = Memory::Read<uint8_t>(val);
2819 USE(y);
2820 // TODO: Implement "case ZVA:".
2821 break;
2822 }
2823 default:
2824 VIXL_UNIMPLEMENTED();
2825 }
2826}
2827
2828
2829void Simulator::VisitSystem(const Instruction* instr) {
2830 // Some system instructions hijack their Op and Cp fields to represent a
2831 // range of immediates instead of indicating a different instruction. This
2832 // makes the decoding tricky.
2833 if (instr->Mask(SystemExclusiveMonitorFMask) == SystemExclusiveMonitorFixed) {
2834 VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
2835 switch (instr->Mask(SystemExclusiveMonitorMask)) {
2836 case CLREX: {
2837 PrintExclusiveAccessWarning();
2838 ClearLocalMonitor();
2839 break;
2840 }
2841 }
2842 } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
2843 switch (instr->Mask(SystemSysRegMask)) {
2844 case MRS: {
2845 switch (instr->GetImmSystemRegister()) {
2846 case NZCV:
2847 WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
2848 break;
2849 case FPCR:
2850 WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
2851 break;
2852 default:
2853 VIXL_UNIMPLEMENTED();
2854 }
2855 break;
2856 }
2857 case MSR: {
2858 switch (instr->GetImmSystemRegister()) {
2859 case NZCV:
2860 ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
2861 LogSystemRegister(NZCV);
2862 break;
2863 case FPCR:
2864 ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
2865 LogSystemRegister(FPCR);
2866 break;
2867 default:
2868 VIXL_UNIMPLEMENTED();
2869 }
2870 break;
2871 }
2872 }
2873 } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
2874 VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
2875 switch (instr->GetImmHint()) {
2876 case NOP:
2877 break;
2878 default:
2879 VIXL_UNIMPLEMENTED();
2880 }
2881 } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
2882 __sync_synchronize();
2883 } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
2884 switch (instr->Mask(SystemSysMask)) {
2885 case SYS:
2886 SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
2887 break;
2888 default:
2889 VIXL_UNIMPLEMENTED();
2890 }
2891 } else {
2892 VIXL_UNIMPLEMENTED();
2893 }
2894}
2895
2896
2897void Simulator::VisitException(const Instruction* instr) {
2898 switch (instr->Mask(ExceptionMask)) {
2899 case HLT:
2900 switch (instr->GetImmException()) {
2901 case kUnreachableOpcode:
2902 DoUnreachable(instr);
2903 return;
2904 case kTraceOpcode:
2905 DoTrace(instr);
2906 return;
2907 case kLogOpcode:
2908 DoLog(instr);
2909 return;
2910 case kPrintfOpcode:
2911 DoPrintf(instr);
2912 return;
Alexandre Rames064e02d2016-07-12 11:53:13 +01002913 case kRuntimeCallOpcode:
2914 DoRuntimeCall(instr);
2915 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01002916 default:
2917 HostBreakpoint();
2918 return;
2919 }
2920 case BRK:
2921 HostBreakpoint();
2922 return;
2923 default:
2924 VIXL_UNIMPLEMENTED();
2925 }
2926}
2927
2928
2929void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
2930 VisitUnimplemented(instr);
2931}
2932
2933
2934void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
2935 VisitUnimplemented(instr);
2936}
2937
2938
2939void Simulator::VisitCryptoAES(const Instruction* instr) {
2940 VisitUnimplemented(instr);
2941}
2942
2943
2944void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
2945 NEONFormatDecoder nfd(instr);
2946 VectorFormat vf = nfd.GetVectorFormat();
2947
2948 static const NEONFormatMap map_lp =
2949 {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
2950 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
2951
2952 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
2953 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
2954
2955 static const NEONFormatMap map_fcvtn = {{22, 30},
2956 {NF_4H, NF_8H, NF_2S, NF_4S}};
2957 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
2958
2959 SimVRegister& rd = ReadVRegister(instr->GetRd());
2960 SimVRegister& rn = ReadVRegister(instr->GetRn());
2961
2962 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
2963 // These instructions all use a two bit size field, except NOT and RBIT,
2964 // which use the field to encode the operation.
2965 switch (instr->Mask(NEON2RegMiscMask)) {
2966 case NEON_REV64:
2967 rev64(vf, rd, rn);
2968 break;
2969 case NEON_REV32:
2970 rev32(vf, rd, rn);
2971 break;
2972 case NEON_REV16:
2973 rev16(vf, rd, rn);
2974 break;
2975 case NEON_SUQADD:
2976 suqadd(vf, rd, rn);
2977 break;
2978 case NEON_USQADD:
2979 usqadd(vf, rd, rn);
2980 break;
2981 case NEON_CLS:
2982 cls(vf, rd, rn);
2983 break;
2984 case NEON_CLZ:
2985 clz(vf, rd, rn);
2986 break;
2987 case NEON_CNT:
2988 cnt(vf, rd, rn);
2989 break;
2990 case NEON_SQABS:
2991 abs(vf, rd, rn).SignedSaturate(vf);
2992 break;
2993 case NEON_SQNEG:
2994 neg(vf, rd, rn).SignedSaturate(vf);
2995 break;
2996 case NEON_CMGT_zero:
2997 cmp(vf, rd, rn, 0, gt);
2998 break;
2999 case NEON_CMGE_zero:
3000 cmp(vf, rd, rn, 0, ge);
3001 break;
3002 case NEON_CMEQ_zero:
3003 cmp(vf, rd, rn, 0, eq);
3004 break;
3005 case NEON_CMLE_zero:
3006 cmp(vf, rd, rn, 0, le);
3007 break;
3008 case NEON_CMLT_zero:
3009 cmp(vf, rd, rn, 0, lt);
3010 break;
3011 case NEON_ABS:
3012 abs(vf, rd, rn);
3013 break;
3014 case NEON_NEG:
3015 neg(vf, rd, rn);
3016 break;
3017 case NEON_SADDLP:
3018 saddlp(vf_lp, rd, rn);
3019 break;
3020 case NEON_UADDLP:
3021 uaddlp(vf_lp, rd, rn);
3022 break;
3023 case NEON_SADALP:
3024 sadalp(vf_lp, rd, rn);
3025 break;
3026 case NEON_UADALP:
3027 uadalp(vf_lp, rd, rn);
3028 break;
3029 case NEON_RBIT_NOT:
3030 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3031 switch (instr->GetFPType()) {
3032 case 0:
3033 not_(vf, rd, rn);
3034 break;
3035 case 1:
3036 rbit(vf, rd, rn);
3037 break;
3038 default:
3039 VIXL_UNIMPLEMENTED();
3040 }
3041 break;
3042 }
3043 } else {
3044 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
3045 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
3046 bool inexact_exception = false;
3047
3048 // These instructions all use a one bit size field, except XTN, SQXTUN,
3049 // SHLL, SQXTN and UQXTN, which use a two bit size field.
3050 switch (instr->Mask(NEON2RegMiscFPMask)) {
3051 case NEON_FABS:
3052 fabs_(fpf, rd, rn);
3053 return;
3054 case NEON_FNEG:
3055 fneg(fpf, rd, rn);
3056 return;
3057 case NEON_FSQRT:
3058 fsqrt(fpf, rd, rn);
3059 return;
3060 case NEON_FCVTL:
3061 if (instr->Mask(NEON_Q)) {
3062 fcvtl2(vf_fcvtl, rd, rn);
3063 } else {
3064 fcvtl(vf_fcvtl, rd, rn);
3065 }
3066 return;
3067 case NEON_FCVTN:
3068 if (instr->Mask(NEON_Q)) {
3069 fcvtn2(vf_fcvtn, rd, rn);
3070 } else {
3071 fcvtn(vf_fcvtn, rd, rn);
3072 }
3073 return;
3074 case NEON_FCVTXN:
3075 if (instr->Mask(NEON_Q)) {
3076 fcvtxn2(vf_fcvtn, rd, rn);
3077 } else {
3078 fcvtxn(vf_fcvtn, rd, rn);
3079 }
3080 return;
3081
3082 // The following instructions break from the switch statement, rather
3083 // than return.
3084 case NEON_FRINTI:
3085 break; // Use FPCR rounding mode.
3086 case NEON_FRINTX:
3087 inexact_exception = true;
3088 break;
3089 case NEON_FRINTA:
3090 fpcr_rounding = FPTieAway;
3091 break;
3092 case NEON_FRINTM:
3093 fpcr_rounding = FPNegativeInfinity;
3094 break;
3095 case NEON_FRINTN:
3096 fpcr_rounding = FPTieEven;
3097 break;
3098 case NEON_FRINTP:
3099 fpcr_rounding = FPPositiveInfinity;
3100 break;
3101 case NEON_FRINTZ:
3102 fpcr_rounding = FPZero;
3103 break;
3104
3105 case NEON_FCVTNS:
3106 fcvts(fpf, rd, rn, FPTieEven);
3107 return;
3108 case NEON_FCVTNU:
3109 fcvtu(fpf, rd, rn, FPTieEven);
3110 return;
3111 case NEON_FCVTPS:
3112 fcvts(fpf, rd, rn, FPPositiveInfinity);
3113 return;
3114 case NEON_FCVTPU:
3115 fcvtu(fpf, rd, rn, FPPositiveInfinity);
3116 return;
3117 case NEON_FCVTMS:
3118 fcvts(fpf, rd, rn, FPNegativeInfinity);
3119 return;
3120 case NEON_FCVTMU:
3121 fcvtu(fpf, rd, rn, FPNegativeInfinity);
3122 return;
3123 case NEON_FCVTZS:
3124 fcvts(fpf, rd, rn, FPZero);
3125 return;
3126 case NEON_FCVTZU:
3127 fcvtu(fpf, rd, rn, FPZero);
3128 return;
3129 case NEON_FCVTAS:
3130 fcvts(fpf, rd, rn, FPTieAway);
3131 return;
3132 case NEON_FCVTAU:
3133 fcvtu(fpf, rd, rn, FPTieAway);
3134 return;
3135 case NEON_SCVTF:
3136 scvtf(fpf, rd, rn, 0, fpcr_rounding);
3137 return;
3138 case NEON_UCVTF:
3139 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
3140 return;
3141 case NEON_URSQRTE:
3142 ursqrte(fpf, rd, rn);
3143 return;
3144 case NEON_URECPE:
3145 urecpe(fpf, rd, rn);
3146 return;
3147 case NEON_FRSQRTE:
3148 frsqrte(fpf, rd, rn);
3149 return;
3150 case NEON_FRECPE:
3151 frecpe(fpf, rd, rn, fpcr_rounding);
3152 return;
3153 case NEON_FCMGT_zero:
3154 fcmp_zero(fpf, rd, rn, gt);
3155 return;
3156 case NEON_FCMGE_zero:
3157 fcmp_zero(fpf, rd, rn, ge);
3158 return;
3159 case NEON_FCMEQ_zero:
3160 fcmp_zero(fpf, rd, rn, eq);
3161 return;
3162 case NEON_FCMLE_zero:
3163 fcmp_zero(fpf, rd, rn, le);
3164 return;
3165 case NEON_FCMLT_zero:
3166 fcmp_zero(fpf, rd, rn, lt);
3167 return;
3168 default:
3169 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
3170 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
3171 switch (instr->Mask(NEON2RegMiscMask)) {
3172 case NEON_XTN:
3173 xtn(vf, rd, rn);
3174 return;
3175 case NEON_SQXTN:
3176 sqxtn(vf, rd, rn);
3177 return;
3178 case NEON_UQXTN:
3179 uqxtn(vf, rd, rn);
3180 return;
3181 case NEON_SQXTUN:
3182 sqxtun(vf, rd, rn);
3183 return;
3184 case NEON_SHLL:
3185 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3186 if (instr->Mask(NEON_Q)) {
3187 shll2(vf, rd, rn);
3188 } else {
3189 shll(vf, rd, rn);
3190 }
3191 return;
3192 default:
3193 VIXL_UNIMPLEMENTED();
3194 }
3195 } else {
3196 VIXL_UNIMPLEMENTED();
3197 }
3198 }
3199
3200 // Only FRINT* instructions fall through the switch above.
3201 frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
3202 }
3203}
3204
3205
3206void Simulator::VisitNEON3Same(const Instruction* instr) {
3207 NEONFormatDecoder nfd(instr);
3208 SimVRegister& rd = ReadVRegister(instr->GetRd());
3209 SimVRegister& rn = ReadVRegister(instr->GetRn());
3210 SimVRegister& rm = ReadVRegister(instr->GetRm());
3211
3212 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
3213 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3214 switch (instr->Mask(NEON3SameLogicalMask)) {
3215 case NEON_AND:
3216 and_(vf, rd, rn, rm);
3217 break;
3218 case NEON_ORR:
3219 orr(vf, rd, rn, rm);
3220 break;
3221 case NEON_ORN:
3222 orn(vf, rd, rn, rm);
3223 break;
3224 case NEON_EOR:
3225 eor(vf, rd, rn, rm);
3226 break;
3227 case NEON_BIC:
3228 bic(vf, rd, rn, rm);
3229 break;
3230 case NEON_BIF:
3231 bif(vf, rd, rn, rm);
3232 break;
3233 case NEON_BIT:
3234 bit(vf, rd, rn, rm);
3235 break;
3236 case NEON_BSL:
3237 bsl(vf, rd, rn, rm);
3238 break;
3239 default:
3240 VIXL_UNIMPLEMENTED();
3241 }
3242 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
3243 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
3244 switch (instr->Mask(NEON3SameFPMask)) {
3245 case NEON_FADD:
3246 fadd(vf, rd, rn, rm);
3247 break;
3248 case NEON_FSUB:
3249 fsub(vf, rd, rn, rm);
3250 break;
3251 case NEON_FMUL:
3252 fmul(vf, rd, rn, rm);
3253 break;
3254 case NEON_FDIV:
3255 fdiv(vf, rd, rn, rm);
3256 break;
3257 case NEON_FMAX:
3258 fmax(vf, rd, rn, rm);
3259 break;
3260 case NEON_FMIN:
3261 fmin(vf, rd, rn, rm);
3262 break;
3263 case NEON_FMAXNM:
3264 fmaxnm(vf, rd, rn, rm);
3265 break;
3266 case NEON_FMINNM:
3267 fminnm(vf, rd, rn, rm);
3268 break;
3269 case NEON_FMLA:
3270 fmla(vf, rd, rn, rm);
3271 break;
3272 case NEON_FMLS:
3273 fmls(vf, rd, rn, rm);
3274 break;
3275 case NEON_FMULX:
3276 fmulx(vf, rd, rn, rm);
3277 break;
3278 case NEON_FACGE:
3279 fabscmp(vf, rd, rn, rm, ge);
3280 break;
3281 case NEON_FACGT:
3282 fabscmp(vf, rd, rn, rm, gt);
3283 break;
3284 case NEON_FCMEQ:
3285 fcmp(vf, rd, rn, rm, eq);
3286 break;
3287 case NEON_FCMGE:
3288 fcmp(vf, rd, rn, rm, ge);
3289 break;
3290 case NEON_FCMGT:
3291 fcmp(vf, rd, rn, rm, gt);
3292 break;
3293 case NEON_FRECPS:
3294 frecps(vf, rd, rn, rm);
3295 break;
3296 case NEON_FRSQRTS:
3297 frsqrts(vf, rd, rn, rm);
3298 break;
3299 case NEON_FABD:
3300 fabd(vf, rd, rn, rm);
3301 break;
3302 case NEON_FADDP:
3303 faddp(vf, rd, rn, rm);
3304 break;
3305 case NEON_FMAXP:
3306 fmaxp(vf, rd, rn, rm);
3307 break;
3308 case NEON_FMAXNMP:
3309 fmaxnmp(vf, rd, rn, rm);
3310 break;
3311 case NEON_FMINP:
3312 fminp(vf, rd, rn, rm);
3313 break;
3314 case NEON_FMINNMP:
3315 fminnmp(vf, rd, rn, rm);
3316 break;
3317 default:
3318 VIXL_UNIMPLEMENTED();
3319 }
3320 } else {
3321 VectorFormat vf = nfd.GetVectorFormat();
3322 switch (instr->Mask(NEON3SameMask)) {
3323 case NEON_ADD:
3324 add(vf, rd, rn, rm);
3325 break;
3326 case NEON_ADDP:
3327 addp(vf, rd, rn, rm);
3328 break;
3329 case NEON_CMEQ:
3330 cmp(vf, rd, rn, rm, eq);
3331 break;
3332 case NEON_CMGE:
3333 cmp(vf, rd, rn, rm, ge);
3334 break;
3335 case NEON_CMGT:
3336 cmp(vf, rd, rn, rm, gt);
3337 break;
3338 case NEON_CMHI:
3339 cmp(vf, rd, rn, rm, hi);
3340 break;
3341 case NEON_CMHS:
3342 cmp(vf, rd, rn, rm, hs);
3343 break;
3344 case NEON_CMTST:
3345 cmptst(vf, rd, rn, rm);
3346 break;
3347 case NEON_MLS:
3348 mls(vf, rd, rn, rm);
3349 break;
3350 case NEON_MLA:
3351 mla(vf, rd, rn, rm);
3352 break;
3353 case NEON_MUL:
3354 mul(vf, rd, rn, rm);
3355 break;
3356 case NEON_PMUL:
3357 pmul(vf, rd, rn, rm);
3358 break;
3359 case NEON_SMAX:
3360 smax(vf, rd, rn, rm);
3361 break;
3362 case NEON_SMAXP:
3363 smaxp(vf, rd, rn, rm);
3364 break;
3365 case NEON_SMIN:
3366 smin(vf, rd, rn, rm);
3367 break;
3368 case NEON_SMINP:
3369 sminp(vf, rd, rn, rm);
3370 break;
3371 case NEON_SUB:
3372 sub(vf, rd, rn, rm);
3373 break;
3374 case NEON_UMAX:
3375 umax(vf, rd, rn, rm);
3376 break;
3377 case NEON_UMAXP:
3378 umaxp(vf, rd, rn, rm);
3379 break;
3380 case NEON_UMIN:
3381 umin(vf, rd, rn, rm);
3382 break;
3383 case NEON_UMINP:
3384 uminp(vf, rd, rn, rm);
3385 break;
3386 case NEON_SSHL:
3387 sshl(vf, rd, rn, rm);
3388 break;
3389 case NEON_USHL:
3390 ushl(vf, rd, rn, rm);
3391 break;
3392 case NEON_SABD:
3393 absdiff(vf, rd, rn, rm, true);
3394 break;
3395 case NEON_UABD:
3396 absdiff(vf, rd, rn, rm, false);
3397 break;
3398 case NEON_SABA:
3399 saba(vf, rd, rn, rm);
3400 break;
3401 case NEON_UABA:
3402 uaba(vf, rd, rn, rm);
3403 break;
3404 case NEON_UQADD:
3405 add(vf, rd, rn, rm).UnsignedSaturate(vf);
3406 break;
3407 case NEON_SQADD:
3408 add(vf, rd, rn, rm).SignedSaturate(vf);
3409 break;
3410 case NEON_UQSUB:
3411 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
3412 break;
3413 case NEON_SQSUB:
3414 sub(vf, rd, rn, rm).SignedSaturate(vf);
3415 break;
3416 case NEON_SQDMULH:
3417 sqdmulh(vf, rd, rn, rm);
3418 break;
3419 case NEON_SQRDMULH:
3420 sqrdmulh(vf, rd, rn, rm);
3421 break;
3422 case NEON_UQSHL:
3423 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
3424 break;
3425 case NEON_SQSHL:
3426 sshl(vf, rd, rn, rm).SignedSaturate(vf);
3427 break;
3428 case NEON_URSHL:
3429 ushl(vf, rd, rn, rm).Round(vf);
3430 break;
3431 case NEON_SRSHL:
3432 sshl(vf, rd, rn, rm).Round(vf);
3433 break;
3434 case NEON_UQRSHL:
3435 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
3436 break;
3437 case NEON_SQRSHL:
3438 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
3439 break;
3440 case NEON_UHADD:
3441 add(vf, rd, rn, rm).Uhalve(vf);
3442 break;
3443 case NEON_URHADD:
3444 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
3445 break;
3446 case NEON_SHADD:
3447 add(vf, rd, rn, rm).Halve(vf);
3448 break;
3449 case NEON_SRHADD:
3450 add(vf, rd, rn, rm).Halve(vf).Round(vf);
3451 break;
3452 case NEON_UHSUB:
3453 sub(vf, rd, rn, rm).Uhalve(vf);
3454 break;
3455 case NEON_SHSUB:
3456 sub(vf, rd, rn, rm).Halve(vf);
3457 break;
3458 default:
3459 VIXL_UNIMPLEMENTED();
3460 }
3461 }
3462}
3463
3464
3465void Simulator::VisitNEON3Different(const Instruction* instr) {
3466 NEONFormatDecoder nfd(instr);
3467 VectorFormat vf = nfd.GetVectorFormat();
3468 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3469
3470 SimVRegister& rd = ReadVRegister(instr->GetRd());
3471 SimVRegister& rn = ReadVRegister(instr->GetRn());
3472 SimVRegister& rm = ReadVRegister(instr->GetRm());
3473
3474 switch (instr->Mask(NEON3DifferentMask)) {
3475 case NEON_PMULL:
3476 pmull(vf_l, rd, rn, rm);
3477 break;
3478 case NEON_PMULL2:
3479 pmull2(vf_l, rd, rn, rm);
3480 break;
3481 case NEON_UADDL:
3482 uaddl(vf_l, rd, rn, rm);
3483 break;
3484 case NEON_UADDL2:
3485 uaddl2(vf_l, rd, rn, rm);
3486 break;
3487 case NEON_SADDL:
3488 saddl(vf_l, rd, rn, rm);
3489 break;
3490 case NEON_SADDL2:
3491 saddl2(vf_l, rd, rn, rm);
3492 break;
3493 case NEON_USUBL:
3494 usubl(vf_l, rd, rn, rm);
3495 break;
3496 case NEON_USUBL2:
3497 usubl2(vf_l, rd, rn, rm);
3498 break;
3499 case NEON_SSUBL:
3500 ssubl(vf_l, rd, rn, rm);
3501 break;
3502 case NEON_SSUBL2:
3503 ssubl2(vf_l, rd, rn, rm);
3504 break;
3505 case NEON_SABAL:
3506 sabal(vf_l, rd, rn, rm);
3507 break;
3508 case NEON_SABAL2:
3509 sabal2(vf_l, rd, rn, rm);
3510 break;
3511 case NEON_UABAL:
3512 uabal(vf_l, rd, rn, rm);
3513 break;
3514 case NEON_UABAL2:
3515 uabal2(vf_l, rd, rn, rm);
3516 break;
3517 case NEON_SABDL:
3518 sabdl(vf_l, rd, rn, rm);
3519 break;
3520 case NEON_SABDL2:
3521 sabdl2(vf_l, rd, rn, rm);
3522 break;
3523 case NEON_UABDL:
3524 uabdl(vf_l, rd, rn, rm);
3525 break;
3526 case NEON_UABDL2:
3527 uabdl2(vf_l, rd, rn, rm);
3528 break;
3529 case NEON_SMLAL:
3530 smlal(vf_l, rd, rn, rm);
3531 break;
3532 case NEON_SMLAL2:
3533 smlal2(vf_l, rd, rn, rm);
3534 break;
3535 case NEON_UMLAL:
3536 umlal(vf_l, rd, rn, rm);
3537 break;
3538 case NEON_UMLAL2:
3539 umlal2(vf_l, rd, rn, rm);
3540 break;
3541 case NEON_SMLSL:
3542 smlsl(vf_l, rd, rn, rm);
3543 break;
3544 case NEON_SMLSL2:
3545 smlsl2(vf_l, rd, rn, rm);
3546 break;
3547 case NEON_UMLSL:
3548 umlsl(vf_l, rd, rn, rm);
3549 break;
3550 case NEON_UMLSL2:
3551 umlsl2(vf_l, rd, rn, rm);
3552 break;
3553 case NEON_SMULL:
3554 smull(vf_l, rd, rn, rm);
3555 break;
3556 case NEON_SMULL2:
3557 smull2(vf_l, rd, rn, rm);
3558 break;
3559 case NEON_UMULL:
3560 umull(vf_l, rd, rn, rm);
3561 break;
3562 case NEON_UMULL2:
3563 umull2(vf_l, rd, rn, rm);
3564 break;
3565 case NEON_SQDMLAL:
3566 sqdmlal(vf_l, rd, rn, rm);
3567 break;
3568 case NEON_SQDMLAL2:
3569 sqdmlal2(vf_l, rd, rn, rm);
3570 break;
3571 case NEON_SQDMLSL:
3572 sqdmlsl(vf_l, rd, rn, rm);
3573 break;
3574 case NEON_SQDMLSL2:
3575 sqdmlsl2(vf_l, rd, rn, rm);
3576 break;
3577 case NEON_SQDMULL:
3578 sqdmull(vf_l, rd, rn, rm);
3579 break;
3580 case NEON_SQDMULL2:
3581 sqdmull2(vf_l, rd, rn, rm);
3582 break;
3583 case NEON_UADDW:
3584 uaddw(vf_l, rd, rn, rm);
3585 break;
3586 case NEON_UADDW2:
3587 uaddw2(vf_l, rd, rn, rm);
3588 break;
3589 case NEON_SADDW:
3590 saddw(vf_l, rd, rn, rm);
3591 break;
3592 case NEON_SADDW2:
3593 saddw2(vf_l, rd, rn, rm);
3594 break;
3595 case NEON_USUBW:
3596 usubw(vf_l, rd, rn, rm);
3597 break;
3598 case NEON_USUBW2:
3599 usubw2(vf_l, rd, rn, rm);
3600 break;
3601 case NEON_SSUBW:
3602 ssubw(vf_l, rd, rn, rm);
3603 break;
3604 case NEON_SSUBW2:
3605 ssubw2(vf_l, rd, rn, rm);
3606 break;
3607 case NEON_ADDHN:
3608 addhn(vf, rd, rn, rm);
3609 break;
3610 case NEON_ADDHN2:
3611 addhn2(vf, rd, rn, rm);
3612 break;
3613 case NEON_RADDHN:
3614 raddhn(vf, rd, rn, rm);
3615 break;
3616 case NEON_RADDHN2:
3617 raddhn2(vf, rd, rn, rm);
3618 break;
3619 case NEON_SUBHN:
3620 subhn(vf, rd, rn, rm);
3621 break;
3622 case NEON_SUBHN2:
3623 subhn2(vf, rd, rn, rm);
3624 break;
3625 case NEON_RSUBHN:
3626 rsubhn(vf, rd, rn, rm);
3627 break;
3628 case NEON_RSUBHN2:
3629 rsubhn2(vf, rd, rn, rm);
3630 break;
3631 default:
3632 VIXL_UNIMPLEMENTED();
3633 }
3634}
3635
3636
3637void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
3638 NEONFormatDecoder nfd(instr);
3639
3640 SimVRegister& rd = ReadVRegister(instr->GetRd());
3641 SimVRegister& rn = ReadVRegister(instr->GetRn());
3642
3643 // The input operand's VectorFormat is passed for these instructions.
3644 if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
3645 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
3646
3647 switch (instr->Mask(NEONAcrossLanesFPMask)) {
3648 case NEON_FMAXV:
3649 fmaxv(vf, rd, rn);
3650 break;
3651 case NEON_FMINV:
3652 fminv(vf, rd, rn);
3653 break;
3654 case NEON_FMAXNMV:
3655 fmaxnmv(vf, rd, rn);
3656 break;
3657 case NEON_FMINNMV:
3658 fminnmv(vf, rd, rn);
3659 break;
3660 default:
3661 VIXL_UNIMPLEMENTED();
3662 }
3663 } else {
3664 VectorFormat vf = nfd.GetVectorFormat();
3665
3666 switch (instr->Mask(NEONAcrossLanesMask)) {
3667 case NEON_ADDV:
3668 addv(vf, rd, rn);
3669 break;
3670 case NEON_SMAXV:
3671 smaxv(vf, rd, rn);
3672 break;
3673 case NEON_SMINV:
3674 sminv(vf, rd, rn);
3675 break;
3676 case NEON_UMAXV:
3677 umaxv(vf, rd, rn);
3678 break;
3679 case NEON_UMINV:
3680 uminv(vf, rd, rn);
3681 break;
3682 case NEON_SADDLV:
3683 saddlv(vf, rd, rn);
3684 break;
3685 case NEON_UADDLV:
3686 uaddlv(vf, rd, rn);
3687 break;
3688 default:
3689 VIXL_UNIMPLEMENTED();
3690 }
3691 }
3692}
3693
3694
3695void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
3696 NEONFormatDecoder nfd(instr);
3697 VectorFormat vf_r = nfd.GetVectorFormat();
3698 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3699
3700 SimVRegister& rd = ReadVRegister(instr->GetRd());
3701 SimVRegister& rn = ReadVRegister(instr->GetRn());
3702
3703 ByElementOp Op = NULL;
3704
3705 int rm_reg = instr->GetRm();
3706 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
3707 if (instr->GetNEONSize() == 1) {
3708 rm_reg &= 0xf;
3709 index = (index << 1) | instr->GetNEONM();
3710 }
3711
3712 switch (instr->Mask(NEONByIndexedElementMask)) {
3713 case NEON_MUL_byelement:
3714 Op = &Simulator::mul;
3715 vf = vf_r;
3716 break;
3717 case NEON_MLA_byelement:
3718 Op = &Simulator::mla;
3719 vf = vf_r;
3720 break;
3721 case NEON_MLS_byelement:
3722 Op = &Simulator::mls;
3723 vf = vf_r;
3724 break;
3725 case NEON_SQDMULH_byelement:
3726 Op = &Simulator::sqdmulh;
3727 vf = vf_r;
3728 break;
3729 case NEON_SQRDMULH_byelement:
3730 Op = &Simulator::sqrdmulh;
3731 vf = vf_r;
3732 break;
3733 case NEON_SMULL_byelement:
3734 if (instr->Mask(NEON_Q)) {
3735 Op = &Simulator::smull2;
3736 } else {
3737 Op = &Simulator::smull;
3738 }
3739 break;
3740 case NEON_UMULL_byelement:
3741 if (instr->Mask(NEON_Q)) {
3742 Op = &Simulator::umull2;
3743 } else {
3744 Op = &Simulator::umull;
3745 }
3746 break;
3747 case NEON_SMLAL_byelement:
3748 if (instr->Mask(NEON_Q)) {
3749 Op = &Simulator::smlal2;
3750 } else {
3751 Op = &Simulator::smlal;
3752 }
3753 break;
3754 case NEON_UMLAL_byelement:
3755 if (instr->Mask(NEON_Q)) {
3756 Op = &Simulator::umlal2;
3757 } else {
3758 Op = &Simulator::umlal;
3759 }
3760 break;
3761 case NEON_SMLSL_byelement:
3762 if (instr->Mask(NEON_Q)) {
3763 Op = &Simulator::smlsl2;
3764 } else {
3765 Op = &Simulator::smlsl;
3766 }
3767 break;
3768 case NEON_UMLSL_byelement:
3769 if (instr->Mask(NEON_Q)) {
3770 Op = &Simulator::umlsl2;
3771 } else {
3772 Op = &Simulator::umlsl;
3773 }
3774 break;
3775 case NEON_SQDMULL_byelement:
3776 if (instr->Mask(NEON_Q)) {
3777 Op = &Simulator::sqdmull2;
3778 } else {
3779 Op = &Simulator::sqdmull;
3780 }
3781 break;
3782 case NEON_SQDMLAL_byelement:
3783 if (instr->Mask(NEON_Q)) {
3784 Op = &Simulator::sqdmlal2;
3785 } else {
3786 Op = &Simulator::sqdmlal;
3787 }
3788 break;
3789 case NEON_SQDMLSL_byelement:
3790 if (instr->Mask(NEON_Q)) {
3791 Op = &Simulator::sqdmlsl2;
3792 } else {
3793 Op = &Simulator::sqdmlsl;
3794 }
3795 break;
3796 default:
3797 index = instr->GetNEONH();
3798 if ((instr->GetFPType() & 1) == 0) {
3799 index = (index << 1) | instr->GetNEONL();
3800 }
3801
3802 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
3803
3804 switch (instr->Mask(NEONByIndexedElementFPMask)) {
3805 case NEON_FMUL_byelement:
3806 Op = &Simulator::fmul;
3807 break;
3808 case NEON_FMLA_byelement:
3809 Op = &Simulator::fmla;
3810 break;
3811 case NEON_FMLS_byelement:
3812 Op = &Simulator::fmls;
3813 break;
3814 case NEON_FMULX_byelement:
3815 Op = &Simulator::fmulx;
3816 break;
3817 default:
3818 VIXL_UNIMPLEMENTED();
3819 }
3820 }
3821
3822 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
3823}
3824
3825
3826void Simulator::VisitNEONCopy(const Instruction* instr) {
3827 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
3828 VectorFormat vf = nfd.GetVectorFormat();
3829
3830 SimVRegister& rd = ReadVRegister(instr->GetRd());
3831 SimVRegister& rn = ReadVRegister(instr->GetRn());
3832 int imm5 = instr->GetImmNEON5();
3833 int tz = CountTrailingZeros(imm5, 32);
3834 int reg_index = imm5 >> (tz + 1);
3835
3836 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
3837 int imm4 = instr->GetImmNEON4();
3838 int rn_index = imm4 >> tz;
3839 ins_element(vf, rd, reg_index, rn, rn_index);
3840 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
3841 ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
3842 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
3843 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
3844 value &= MaxUintFromFormat(vf);
3845 WriteXRegister(instr->GetRd(), value);
3846 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
3847 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
3848 if (instr->GetNEONQ()) {
3849 WriteXRegister(instr->GetRd(), value);
3850 } else {
3851 WriteWRegister(instr->GetRd(), (int32_t)value);
3852 }
3853 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
3854 dup_element(vf, rd, rn, reg_index);
3855 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
3856 dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
3857 } else {
3858 VIXL_UNIMPLEMENTED();
3859 }
3860}
3861
3862
3863void Simulator::VisitNEONExtract(const Instruction* instr) {
3864 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
3865 VectorFormat vf = nfd.GetVectorFormat();
3866 SimVRegister& rd = ReadVRegister(instr->GetRd());
3867 SimVRegister& rn = ReadVRegister(instr->GetRn());
3868 SimVRegister& rm = ReadVRegister(instr->GetRm());
3869 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
3870 int index = instr->GetImmNEONExt();
3871 ext(vf, rd, rn, rm, index);
3872 } else {
3873 VIXL_UNIMPLEMENTED();
3874 }
3875}
3876
3877
3878void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
3879 AddrMode addr_mode) {
3880 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
3881 VectorFormat vf = nfd.GetVectorFormat();
3882
3883 uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
3884 int reg_size = RegisterSizeInBytesFromFormat(vf);
3885
3886 int reg[4];
3887 uint64_t addr[4];
3888 for (int i = 0; i < 4; i++) {
3889 reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
3890 addr[i] = addr_base + (i * reg_size);
3891 }
3892 int count = 1;
3893 bool log_read = true;
3894
3895 Instr itype = instr->Mask(NEONLoadStoreMultiStructMask);
3896 if (((itype == NEON_LD1_1v) || (itype == NEON_LD1_2v) ||
3897 (itype == NEON_LD1_3v) || (itype == NEON_LD1_4v) ||
3898 (itype == NEON_ST1_1v) || (itype == NEON_ST1_2v) ||
3899 (itype == NEON_ST1_3v) || (itype == NEON_ST1_4v)) &&
3900 (instr->ExtractBits(20, 16) != 0)) {
3901 VIXL_UNREACHABLE();
3902 }
3903
3904 // We use the PostIndex mask here, as it works in this case for both Offset
3905 // and PostIndex addressing.
3906 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
3907 case NEON_LD1_4v:
3908 case NEON_LD1_4v_post:
3909 ld1(vf, ReadVRegister(reg[3]), addr[3]);
3910 count++;
3911 VIXL_FALLTHROUGH();
3912 case NEON_LD1_3v:
3913 case NEON_LD1_3v_post:
3914 ld1(vf, ReadVRegister(reg[2]), addr[2]);
3915 count++;
3916 VIXL_FALLTHROUGH();
3917 case NEON_LD1_2v:
3918 case NEON_LD1_2v_post:
3919 ld1(vf, ReadVRegister(reg[1]), addr[1]);
3920 count++;
3921 VIXL_FALLTHROUGH();
3922 case NEON_LD1_1v:
3923 case NEON_LD1_1v_post:
3924 ld1(vf, ReadVRegister(reg[0]), addr[0]);
3925 break;
3926 case NEON_ST1_4v:
3927 case NEON_ST1_4v_post:
3928 st1(vf, ReadVRegister(reg[3]), addr[3]);
3929 count++;
3930 VIXL_FALLTHROUGH();
3931 case NEON_ST1_3v:
3932 case NEON_ST1_3v_post:
3933 st1(vf, ReadVRegister(reg[2]), addr[2]);
3934 count++;
3935 VIXL_FALLTHROUGH();
3936 case NEON_ST1_2v:
3937 case NEON_ST1_2v_post:
3938 st1(vf, ReadVRegister(reg[1]), addr[1]);
3939 count++;
3940 VIXL_FALLTHROUGH();
3941 case NEON_ST1_1v:
3942 case NEON_ST1_1v_post:
3943 st1(vf, ReadVRegister(reg[0]), addr[0]);
3944 log_read = false;
3945 break;
3946 case NEON_LD2_post:
3947 case NEON_LD2:
3948 ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
3949 count = 2;
3950 break;
3951 case NEON_ST2:
3952 case NEON_ST2_post:
3953 st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
3954 count = 2;
3955 break;
3956 case NEON_LD3_post:
3957 case NEON_LD3:
3958 ld3(vf,
3959 ReadVRegister(reg[0]),
3960 ReadVRegister(reg[1]),
3961 ReadVRegister(reg[2]),
3962 addr[0]);
3963 count = 3;
3964 break;
3965 case NEON_ST3:
3966 case NEON_ST3_post:
3967 st3(vf,
3968 ReadVRegister(reg[0]),
3969 ReadVRegister(reg[1]),
3970 ReadVRegister(reg[2]),
3971 addr[0]);
3972 count = 3;
3973 break;
3974 case NEON_ST4:
3975 case NEON_ST4_post:
3976 st4(vf,
3977 ReadVRegister(reg[0]),
3978 ReadVRegister(reg[1]),
3979 ReadVRegister(reg[2]),
3980 ReadVRegister(reg[3]),
3981 addr[0]);
3982 count = 4;
3983 break;
3984 case NEON_LD4_post:
3985 case NEON_LD4:
3986 ld4(vf,
3987 ReadVRegister(reg[0]),
3988 ReadVRegister(reg[1]),
3989 ReadVRegister(reg[2]),
3990 ReadVRegister(reg[3]),
3991 addr[0]);
3992 count = 4;
3993 break;
3994 default:
3995 VIXL_UNIMPLEMENTED();
3996 }
3997
3998 // Explicitly log the register update whilst we have type information.
3999 for (int i = 0; i < count; i++) {
4000 // For de-interleaving loads, only print the base address.
4001 int lane_size = LaneSizeInBytesFromFormat(vf);
4002 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
4003 GetPrintRegisterFormatForSize(reg_size, lane_size));
4004 if (log_read) {
4005 LogVRead(addr_base, reg[i], format);
4006 } else {
4007 LogVWrite(addr_base, reg[i], format);
4008 }
4009 }
4010
4011 if (addr_mode == PostIndex) {
4012 int rm = instr->GetRm();
4013 // The immediate post index addressing mode is indicated by rm = 31.
4014 // The immediate is implied by the number of vector registers used.
4015 addr_base += (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count
4016 : ReadXRegister(rm);
4017 WriteXRegister(instr->GetRn(), addr_base);
4018 } else {
4019 VIXL_ASSERT(addr_mode == Offset);
4020 }
4021}
4022
4023
4024void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
4025 NEONLoadStoreMultiStructHelper(instr, Offset);
4026}
4027
4028
4029void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
4030 const Instruction* instr) {
4031 NEONLoadStoreMultiStructHelper(instr, PostIndex);
4032}
4033
4034
4035void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
4036 AddrMode addr_mode) {
4037 uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
4038 int rt = instr->GetRt();
4039
4040 Instr itype = instr->Mask(NEONLoadStoreSingleStructMask);
4041 if (((itype == NEON_LD1_b) || (itype == NEON_LD1_h) ||
4042 (itype == NEON_LD1_s) || (itype == NEON_LD1_d)) &&
4043 (instr->ExtractBits(20, 16) != 0)) {
4044 VIXL_UNREACHABLE();
4045 }
4046
4047 // We use the PostIndex mask here, as it works in this case for both Offset
4048 // and PostIndex addressing.
4049 bool do_load = false;
4050
4051 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4052 VectorFormat vf_t = nfd.GetVectorFormat();
4053
4054 VectorFormat vf = kFormat16B;
4055 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
4056 case NEON_LD1_b:
4057 case NEON_LD1_b_post:
4058 case NEON_LD2_b:
4059 case NEON_LD2_b_post:
4060 case NEON_LD3_b:
4061 case NEON_LD3_b_post:
4062 case NEON_LD4_b:
4063 case NEON_LD4_b_post:
4064 do_load = true;
4065 VIXL_FALLTHROUGH();
4066 case NEON_ST1_b:
4067 case NEON_ST1_b_post:
4068 case NEON_ST2_b:
4069 case NEON_ST2_b_post:
4070 case NEON_ST3_b:
4071 case NEON_ST3_b_post:
4072 case NEON_ST4_b:
4073 case NEON_ST4_b_post:
4074 break;
4075
4076 case NEON_LD1_h:
4077 case NEON_LD1_h_post:
4078 case NEON_LD2_h:
4079 case NEON_LD2_h_post:
4080 case NEON_LD3_h:
4081 case NEON_LD3_h_post:
4082 case NEON_LD4_h:
4083 case NEON_LD4_h_post:
4084 do_load = true;
4085 VIXL_FALLTHROUGH();
4086 case NEON_ST1_h:
4087 case NEON_ST1_h_post:
4088 case NEON_ST2_h:
4089 case NEON_ST2_h_post:
4090 case NEON_ST3_h:
4091 case NEON_ST3_h_post:
4092 case NEON_ST4_h:
4093 case NEON_ST4_h_post:
4094 vf = kFormat8H;
4095 break;
4096 case NEON_LD1_s:
4097 case NEON_LD1_s_post:
4098 case NEON_LD2_s:
4099 case NEON_LD2_s_post:
4100 case NEON_LD3_s:
4101 case NEON_LD3_s_post:
4102 case NEON_LD4_s:
4103 case NEON_LD4_s_post:
4104 do_load = true;
4105 VIXL_FALLTHROUGH();
4106 case NEON_ST1_s:
4107 case NEON_ST1_s_post:
4108 case NEON_ST2_s:
4109 case NEON_ST2_s_post:
4110 case NEON_ST3_s:
4111 case NEON_ST3_s_post:
4112 case NEON_ST4_s:
4113 case NEON_ST4_s_post: {
4114 VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
4115 VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
4116 NEON_LD1_d_post);
4117 VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
4118 VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
4119 NEON_ST1_d_post);
4120 vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
4121 break;
4122 }
4123
4124 case NEON_LD1R:
4125 case NEON_LD1R_post: {
4126 vf = vf_t;
4127 ld1r(vf, ReadVRegister(rt), addr);
4128 do_load = true;
4129 break;
4130 }
4131
4132 case NEON_LD2R:
4133 case NEON_LD2R_post: {
4134 vf = vf_t;
4135 int rt2 = (rt + 1) % kNumberOfVRegisters;
4136 ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
4137 do_load = true;
4138 break;
4139 }
4140
4141 case NEON_LD3R:
4142 case NEON_LD3R_post: {
4143 vf = vf_t;
4144 int rt2 = (rt + 1) % kNumberOfVRegisters;
4145 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4146 ld3r(vf, ReadVRegister(rt), ReadVRegister(rt2), ReadVRegister(rt3), addr);
4147 do_load = true;
4148 break;
4149 }
4150
4151 case NEON_LD4R:
4152 case NEON_LD4R_post: {
4153 vf = vf_t;
4154 int rt2 = (rt + 1) % kNumberOfVRegisters;
4155 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4156 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4157 ld4r(vf,
4158 ReadVRegister(rt),
4159 ReadVRegister(rt2),
4160 ReadVRegister(rt3),
4161 ReadVRegister(rt4),
4162 addr);
4163 do_load = true;
4164 break;
4165 }
4166 default:
4167 VIXL_UNIMPLEMENTED();
4168 }
4169
4170 PrintRegisterFormat print_format =
4171 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
4172 // Make sure that the print_format only includes a single lane.
4173 print_format =
4174 static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
4175
4176 int esize = LaneSizeInBytesFromFormat(vf);
4177 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
4178 int lane = instr->GetNEONLSIndex(index_shift);
4179 int scale = 0;
4180 int rt2 = (rt + 1) % kNumberOfVRegisters;
4181 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4182 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4183 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
4184 case NEONLoadStoreSingle1:
4185 scale = 1;
4186 if (do_load) {
4187 ld1(vf, ReadVRegister(rt), lane, addr);
4188 LogVRead(addr, rt, print_format, lane);
4189 } else {
4190 st1(vf, ReadVRegister(rt), lane, addr);
4191 LogVWrite(addr, rt, print_format, lane);
4192 }
4193 break;
4194 case NEONLoadStoreSingle2:
4195 scale = 2;
4196 if (do_load) {
4197 ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
4198 LogVRead(addr, rt, print_format, lane);
4199 LogVRead(addr + esize, rt2, print_format, lane);
4200 } else {
4201 st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
4202 LogVWrite(addr, rt, print_format, lane);
4203 LogVWrite(addr + esize, rt2, print_format, lane);
4204 }
4205 break;
4206 case NEONLoadStoreSingle3:
4207 scale = 3;
4208 if (do_load) {
4209 ld3(vf,
4210 ReadVRegister(rt),
4211 ReadVRegister(rt2),
4212 ReadVRegister(rt3),
4213 lane,
4214 addr);
4215 LogVRead(addr, rt, print_format, lane);
4216 LogVRead(addr + esize, rt2, print_format, lane);
4217 LogVRead(addr + (2 * esize), rt3, print_format, lane);
4218 } else {
4219 st3(vf,
4220 ReadVRegister(rt),
4221 ReadVRegister(rt2),
4222 ReadVRegister(rt3),
4223 lane,
4224 addr);
4225 LogVWrite(addr, rt, print_format, lane);
4226 LogVWrite(addr + esize, rt2, print_format, lane);
4227 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4228 }
4229 break;
4230 case NEONLoadStoreSingle4:
4231 scale = 4;
4232 if (do_load) {
4233 ld4(vf,
4234 ReadVRegister(rt),
4235 ReadVRegister(rt2),
4236 ReadVRegister(rt3),
4237 ReadVRegister(rt4),
4238 lane,
4239 addr);
4240 LogVRead(addr, rt, print_format, lane);
4241 LogVRead(addr + esize, rt2, print_format, lane);
4242 LogVRead(addr + (2 * esize), rt3, print_format, lane);
4243 LogVRead(addr + (3 * esize), rt4, print_format, lane);
4244 } else {
4245 st4(vf,
4246 ReadVRegister(rt),
4247 ReadVRegister(rt2),
4248 ReadVRegister(rt3),
4249 ReadVRegister(rt4),
4250 lane,
4251 addr);
4252 LogVWrite(addr, rt, print_format, lane);
4253 LogVWrite(addr + esize, rt2, print_format, lane);
4254 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4255 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
4256 }
4257 break;
4258 default:
4259 VIXL_UNIMPLEMENTED();
4260 }
4261
4262 if (addr_mode == PostIndex) {
4263 int rm = instr->GetRm();
4264 int lane_size = LaneSizeInBytesFromFormat(vf);
4265 WriteXRegister(instr->GetRn(),
4266 addr +
4267 ((rm == 31) ? (scale * lane_size) : ReadXRegister(rm)));
4268 }
4269}
4270
4271
4272void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
4273 NEONLoadStoreSingleStructHelper(instr, Offset);
4274}
4275
4276
4277void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
4278 const Instruction* instr) {
4279 NEONLoadStoreSingleStructHelper(instr, PostIndex);
4280}
4281
4282
4283void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
4284 SimVRegister& rd = ReadVRegister(instr->GetRd());
4285 int cmode = instr->GetNEONCmode();
4286 int cmode_3_1 = (cmode >> 1) & 7;
4287 int cmode_3 = (cmode >> 3) & 1;
4288 int cmode_2 = (cmode >> 2) & 1;
4289 int cmode_1 = (cmode >> 1) & 1;
4290 int cmode_0 = cmode & 1;
4291 int q = instr->GetNEONQ();
4292 int op_bit = instr->GetNEONModImmOp();
4293 uint64_t imm8 = instr->GetImmNEONabcdefgh();
4294
4295 // Find the format and immediate value
4296 uint64_t imm = 0;
4297 VectorFormat vform = kFormatUndefined;
4298 switch (cmode_3_1) {
4299 case 0x0:
4300 case 0x1:
4301 case 0x2:
4302 case 0x3:
4303 vform = (q == 1) ? kFormat4S : kFormat2S;
4304 imm = imm8 << (8 * cmode_3_1);
4305 break;
4306 case 0x4:
4307 case 0x5:
4308 vform = (q == 1) ? kFormat8H : kFormat4H;
4309 imm = imm8 << (8 * cmode_1);
4310 break;
4311 case 0x6:
4312 vform = (q == 1) ? kFormat4S : kFormat2S;
4313 if (cmode_0 == 0) {
4314 imm = imm8 << 8 | 0x000000ff;
4315 } else {
4316 imm = imm8 << 16 | 0x0000ffff;
4317 }
4318 break;
4319 case 0x7:
4320 if (cmode_0 == 0 && op_bit == 0) {
4321 vform = q ? kFormat16B : kFormat8B;
4322 imm = imm8;
4323 } else if (cmode_0 == 0 && op_bit == 1) {
4324 vform = q ? kFormat2D : kFormat1D;
4325 imm = 0;
4326 for (int i = 0; i < 8; ++i) {
4327 if (imm8 & (1 << i)) {
4328 imm |= (UINT64_C(0xff) << (8 * i));
4329 }
4330 }
4331 } else { // cmode_0 == 1, cmode == 0xf.
4332 if (op_bit == 0) {
4333 vform = q ? kFormat4S : kFormat2S;
4334 imm = FloatToRawbits(instr->GetImmNEONFP32());
4335 } else if (q == 1) {
4336 vform = kFormat2D;
4337 imm = DoubleToRawbits(instr->GetImmNEONFP64());
4338 } else {
4339 VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
4340 VisitUnallocated(instr);
4341 }
4342 }
4343 break;
4344 default:
4345 VIXL_UNREACHABLE();
4346 break;
4347 }
4348
4349 // Find the operation
4350 NEONModifiedImmediateOp op;
4351 if (cmode_3 == 0) {
4352 if (cmode_0 == 0) {
4353 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4354 } else { // cmode<0> == '1'
4355 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4356 }
4357 } else { // cmode<3> == '1'
4358 if (cmode_2 == 0) {
4359 if (cmode_0 == 0) {
4360 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4361 } else { // cmode<0> == '1'
4362 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4363 }
4364 } else { // cmode<2> == '1'
4365 if (cmode_1 == 0) {
4366 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4367 } else { // cmode<1> == '1'
4368 if (cmode_0 == 0) {
4369 op = NEONModifiedImmediate_MOVI;
4370 } else { // cmode<0> == '1'
4371 op = NEONModifiedImmediate_MOVI;
4372 }
4373 }
4374 }
4375 }
4376
4377 // Call the logic function
4378 if (op == NEONModifiedImmediate_ORR) {
4379 orr(vform, rd, rd, imm);
4380 } else if (op == NEONModifiedImmediate_BIC) {
4381 bic(vform, rd, rd, imm);
4382 } else if (op == NEONModifiedImmediate_MOVI) {
4383 movi(vform, rd, imm);
4384 } else if (op == NEONModifiedImmediate_MVNI) {
4385 mvni(vform, rd, imm);
4386 } else {
4387 VisitUnimplemented(instr);
4388 }
4389}
4390
4391
4392void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
4393 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4394 VectorFormat vf = nfd.GetVectorFormat();
4395
4396 SimVRegister& rd = ReadVRegister(instr->GetRd());
4397 SimVRegister& rn = ReadVRegister(instr->GetRn());
4398
4399 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
4400 // These instructions all use a two bit size field, except NOT and RBIT,
4401 // which use the field to encode the operation.
4402 switch (instr->Mask(NEONScalar2RegMiscMask)) {
4403 case NEON_CMEQ_zero_scalar:
4404 cmp(vf, rd, rn, 0, eq);
4405 break;
4406 case NEON_CMGE_zero_scalar:
4407 cmp(vf, rd, rn, 0, ge);
4408 break;
4409 case NEON_CMGT_zero_scalar:
4410 cmp(vf, rd, rn, 0, gt);
4411 break;
4412 case NEON_CMLT_zero_scalar:
4413 cmp(vf, rd, rn, 0, lt);
4414 break;
4415 case NEON_CMLE_zero_scalar:
4416 cmp(vf, rd, rn, 0, le);
4417 break;
4418 case NEON_ABS_scalar:
4419 abs(vf, rd, rn);
4420 break;
4421 case NEON_SQABS_scalar:
4422 abs(vf, rd, rn).SignedSaturate(vf);
4423 break;
4424 case NEON_NEG_scalar:
4425 neg(vf, rd, rn);
4426 break;
4427 case NEON_SQNEG_scalar:
4428 neg(vf, rd, rn).SignedSaturate(vf);
4429 break;
4430 case NEON_SUQADD_scalar:
4431 suqadd(vf, rd, rn);
4432 break;
4433 case NEON_USQADD_scalar:
4434 usqadd(vf, rd, rn);
4435 break;
4436 default:
4437 VIXL_UNIMPLEMENTED();
4438 break;
4439 }
4440 } else {
4441 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
4442 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4443
4444 // These instructions all use a one bit size field, except SQXTUN, SQXTN
4445 // and UQXTN, which use a two bit size field.
4446 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
4447 case NEON_FRECPE_scalar:
4448 frecpe(fpf, rd, rn, fpcr_rounding);
4449 break;
4450 case NEON_FRECPX_scalar:
4451 frecpx(fpf, rd, rn);
4452 break;
4453 case NEON_FRSQRTE_scalar:
4454 frsqrte(fpf, rd, rn);
4455 break;
4456 case NEON_FCMGT_zero_scalar:
4457 fcmp_zero(fpf, rd, rn, gt);
4458 break;
4459 case NEON_FCMGE_zero_scalar:
4460 fcmp_zero(fpf, rd, rn, ge);
4461 break;
4462 case NEON_FCMEQ_zero_scalar:
4463 fcmp_zero(fpf, rd, rn, eq);
4464 break;
4465 case NEON_FCMLE_zero_scalar:
4466 fcmp_zero(fpf, rd, rn, le);
4467 break;
4468 case NEON_FCMLT_zero_scalar:
4469 fcmp_zero(fpf, rd, rn, lt);
4470 break;
4471 case NEON_SCVTF_scalar:
4472 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4473 break;
4474 case NEON_UCVTF_scalar:
4475 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4476 break;
4477 case NEON_FCVTNS_scalar:
4478 fcvts(fpf, rd, rn, FPTieEven);
4479 break;
4480 case NEON_FCVTNU_scalar:
4481 fcvtu(fpf, rd, rn, FPTieEven);
4482 break;
4483 case NEON_FCVTPS_scalar:
4484 fcvts(fpf, rd, rn, FPPositiveInfinity);
4485 break;
4486 case NEON_FCVTPU_scalar:
4487 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4488 break;
4489 case NEON_FCVTMS_scalar:
4490 fcvts(fpf, rd, rn, FPNegativeInfinity);
4491 break;
4492 case NEON_FCVTMU_scalar:
4493 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4494 break;
4495 case NEON_FCVTZS_scalar:
4496 fcvts(fpf, rd, rn, FPZero);
4497 break;
4498 case NEON_FCVTZU_scalar:
4499 fcvtu(fpf, rd, rn, FPZero);
4500 break;
4501 case NEON_FCVTAS_scalar:
4502 fcvts(fpf, rd, rn, FPTieAway);
4503 break;
4504 case NEON_FCVTAU_scalar:
4505 fcvtu(fpf, rd, rn, FPTieAway);
4506 break;
4507 case NEON_FCVTXN_scalar:
4508 // Unlike all of the other FP instructions above, fcvtxn encodes dest
4509 // size S as size<0>=1. There's only one case, so we ignore the form.
4510 VIXL_ASSERT(instr->ExtractBit(22) == 1);
4511 fcvtxn(kFormatS, rd, rn);
4512 break;
4513 default:
4514 switch (instr->Mask(NEONScalar2RegMiscMask)) {
4515 case NEON_SQXTN_scalar:
4516 sqxtn(vf, rd, rn);
4517 break;
4518 case NEON_UQXTN_scalar:
4519 uqxtn(vf, rd, rn);
4520 break;
4521 case NEON_SQXTUN_scalar:
4522 sqxtun(vf, rd, rn);
4523 break;
4524 default:
4525 VIXL_UNIMPLEMENTED();
4526 }
4527 }
4528 }
4529}
4530
4531
4532void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
4533 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
4534 VectorFormat vf = nfd.GetVectorFormat();
4535
4536 SimVRegister& rd = ReadVRegister(instr->GetRd());
4537 SimVRegister& rn = ReadVRegister(instr->GetRn());
4538 SimVRegister& rm = ReadVRegister(instr->GetRm());
4539 switch (instr->Mask(NEONScalar3DiffMask)) {
4540 case NEON_SQDMLAL_scalar:
4541 sqdmlal(vf, rd, rn, rm);
4542 break;
4543 case NEON_SQDMLSL_scalar:
4544 sqdmlsl(vf, rd, rn, rm);
4545 break;
4546 case NEON_SQDMULL_scalar:
4547 sqdmull(vf, rd, rn, rm);
4548 break;
4549 default:
4550 VIXL_UNIMPLEMENTED();
4551 }
4552}
4553
4554
4555void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
4556 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4557 VectorFormat vf = nfd.GetVectorFormat();
4558
4559 SimVRegister& rd = ReadVRegister(instr->GetRd());
4560 SimVRegister& rn = ReadVRegister(instr->GetRn());
4561 SimVRegister& rm = ReadVRegister(instr->GetRm());
4562
4563 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
4564 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
4565 switch (instr->Mask(NEONScalar3SameFPMask)) {
4566 case NEON_FMULX_scalar:
4567 fmulx(vf, rd, rn, rm);
4568 break;
4569 case NEON_FACGE_scalar:
4570 fabscmp(vf, rd, rn, rm, ge);
4571 break;
4572 case NEON_FACGT_scalar:
4573 fabscmp(vf, rd, rn, rm, gt);
4574 break;
4575 case NEON_FCMEQ_scalar:
4576 fcmp(vf, rd, rn, rm, eq);
4577 break;
4578 case NEON_FCMGE_scalar:
4579 fcmp(vf, rd, rn, rm, ge);
4580 break;
4581 case NEON_FCMGT_scalar:
4582 fcmp(vf, rd, rn, rm, gt);
4583 break;
4584 case NEON_FRECPS_scalar:
4585 frecps(vf, rd, rn, rm);
4586 break;
4587 case NEON_FRSQRTS_scalar:
4588 frsqrts(vf, rd, rn, rm);
4589 break;
4590 case NEON_FABD_scalar:
4591 fabd(vf, rd, rn, rm);
4592 break;
4593 default:
4594 VIXL_UNIMPLEMENTED();
4595 }
4596 } else {
4597 switch (instr->Mask(NEONScalar3SameMask)) {
4598 case NEON_ADD_scalar:
4599 add(vf, rd, rn, rm);
4600 break;
4601 case NEON_SUB_scalar:
4602 sub(vf, rd, rn, rm);
4603 break;
4604 case NEON_CMEQ_scalar:
4605 cmp(vf, rd, rn, rm, eq);
4606 break;
4607 case NEON_CMGE_scalar:
4608 cmp(vf, rd, rn, rm, ge);
4609 break;
4610 case NEON_CMGT_scalar:
4611 cmp(vf, rd, rn, rm, gt);
4612 break;
4613 case NEON_CMHI_scalar:
4614 cmp(vf, rd, rn, rm, hi);
4615 break;
4616 case NEON_CMHS_scalar:
4617 cmp(vf, rd, rn, rm, hs);
4618 break;
4619 case NEON_CMTST_scalar:
4620 cmptst(vf, rd, rn, rm);
4621 break;
4622 case NEON_USHL_scalar:
4623 ushl(vf, rd, rn, rm);
4624 break;
4625 case NEON_SSHL_scalar:
4626 sshl(vf, rd, rn, rm);
4627 break;
4628 case NEON_SQDMULH_scalar:
4629 sqdmulh(vf, rd, rn, rm);
4630 break;
4631 case NEON_SQRDMULH_scalar:
4632 sqrdmulh(vf, rd, rn, rm);
4633 break;
4634 case NEON_UQADD_scalar:
4635 add(vf, rd, rn, rm).UnsignedSaturate(vf);
4636 break;
4637 case NEON_SQADD_scalar:
4638 add(vf, rd, rn, rm).SignedSaturate(vf);
4639 break;
4640 case NEON_UQSUB_scalar:
4641 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
4642 break;
4643 case NEON_SQSUB_scalar:
4644 sub(vf, rd, rn, rm).SignedSaturate(vf);
4645 break;
4646 case NEON_UQSHL_scalar:
4647 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
4648 break;
4649 case NEON_SQSHL_scalar:
4650 sshl(vf, rd, rn, rm).SignedSaturate(vf);
4651 break;
4652 case NEON_URSHL_scalar:
4653 ushl(vf, rd, rn, rm).Round(vf);
4654 break;
4655 case NEON_SRSHL_scalar:
4656 sshl(vf, rd, rn, rm).Round(vf);
4657 break;
4658 case NEON_UQRSHL_scalar:
4659 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
4660 break;
4661 case NEON_SQRSHL_scalar:
4662 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
4663 break;
4664 default:
4665 VIXL_UNIMPLEMENTED();
4666 }
4667 }
4668}
4669
4670
4671void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
4672 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
4673 VectorFormat vf = nfd.GetVectorFormat();
4674 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
4675
4676 SimVRegister& rd = ReadVRegister(instr->GetRd());
4677 SimVRegister& rn = ReadVRegister(instr->GetRn());
4678 ByElementOp Op = NULL;
4679
4680 int rm_reg = instr->GetRm();
4681 int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
4682 if (instr->GetNEONSize() == 1) {
4683 rm_reg &= 0xf;
4684 index = (index << 1) | instr->GetNEONM();
4685 }
4686
4687 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
4688 case NEON_SQDMULL_byelement_scalar:
4689 Op = &Simulator::sqdmull;
4690 break;
4691 case NEON_SQDMLAL_byelement_scalar:
4692 Op = &Simulator::sqdmlal;
4693 break;
4694 case NEON_SQDMLSL_byelement_scalar:
4695 Op = &Simulator::sqdmlsl;
4696 break;
4697 case NEON_SQDMULH_byelement_scalar:
4698 Op = &Simulator::sqdmulh;
4699 vf = vf_r;
4700 break;
4701 case NEON_SQRDMULH_byelement_scalar:
4702 Op = &Simulator::sqrdmulh;
4703 vf = vf_r;
4704 break;
4705 default:
4706 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
4707 index = instr->GetNEONH();
4708 if ((instr->GetFPType() & 1) == 0) {
4709 index = (index << 1) | instr->GetNEONL();
4710 }
4711 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
4712 case NEON_FMUL_byelement_scalar:
4713 Op = &Simulator::fmul;
4714 break;
4715 case NEON_FMLA_byelement_scalar:
4716 Op = &Simulator::fmla;
4717 break;
4718 case NEON_FMLS_byelement_scalar:
4719 Op = &Simulator::fmls;
4720 break;
4721 case NEON_FMULX_byelement_scalar:
4722 Op = &Simulator::fmulx;
4723 break;
4724 default:
4725 VIXL_UNIMPLEMENTED();
4726 }
4727 }
4728
4729 (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
4730}
4731
4732
4733void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
4734 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
4735 VectorFormat vf = nfd.GetVectorFormat();
4736
4737 SimVRegister& rd = ReadVRegister(instr->GetRd());
4738 SimVRegister& rn = ReadVRegister(instr->GetRn());
4739
4740 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
4741 int imm5 = instr->GetImmNEON5();
4742 int tz = CountTrailingZeros(imm5, 32);
4743 int rn_index = imm5 >> (tz + 1);
4744 dup_element(vf, rd, rn, rn_index);
4745 } else {
4746 VIXL_UNIMPLEMENTED();
4747 }
4748}
4749
4750
4751void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
4752 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
4753 VectorFormat vf = nfd.GetVectorFormat();
4754
4755 SimVRegister& rd = ReadVRegister(instr->GetRd());
4756 SimVRegister& rn = ReadVRegister(instr->GetRn());
4757 switch (instr->Mask(NEONScalarPairwiseMask)) {
4758 case NEON_ADDP_scalar:
4759 addp(vf, rd, rn);
4760 break;
4761 case NEON_FADDP_scalar:
4762 faddp(vf, rd, rn);
4763 break;
4764 case NEON_FMAXP_scalar:
4765 fmaxp(vf, rd, rn);
4766 break;
4767 case NEON_FMAXNMP_scalar:
4768 fmaxnmp(vf, rd, rn);
4769 break;
4770 case NEON_FMINP_scalar:
4771 fminp(vf, rd, rn);
4772 break;
4773 case NEON_FMINNMP_scalar:
4774 fminnmp(vf, rd, rn);
4775 break;
4776 default:
4777 VIXL_UNIMPLEMENTED();
4778 }
4779}
4780
4781
4782void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
4783 SimVRegister& rd = ReadVRegister(instr->GetRd());
4784 SimVRegister& rn = ReadVRegister(instr->GetRn());
4785 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4786
4787 static const NEONFormatMap map = {{22, 21, 20, 19},
4788 {NF_UNDEF,
4789 NF_B,
4790 NF_H,
4791 NF_H,
4792 NF_S,
4793 NF_S,
4794 NF_S,
4795 NF_S,
4796 NF_D,
4797 NF_D,
4798 NF_D,
4799 NF_D,
4800 NF_D,
4801 NF_D,
4802 NF_D,
4803 NF_D}};
4804 NEONFormatDecoder nfd(instr, &map);
4805 VectorFormat vf = nfd.GetVectorFormat();
4806
4807 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
4808 int immhimmb = instr->GetImmNEONImmhImmb();
4809 int right_shift = (16 << highestSetBit) - immhimmb;
4810 int left_shift = immhimmb - (8 << highestSetBit);
4811 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
4812 case NEON_SHL_scalar:
4813 shl(vf, rd, rn, left_shift);
4814 break;
4815 case NEON_SLI_scalar:
4816 sli(vf, rd, rn, left_shift);
4817 break;
4818 case NEON_SQSHL_imm_scalar:
4819 sqshl(vf, rd, rn, left_shift);
4820 break;
4821 case NEON_UQSHL_imm_scalar:
4822 uqshl(vf, rd, rn, left_shift);
4823 break;
4824 case NEON_SQSHLU_scalar:
4825 sqshlu(vf, rd, rn, left_shift);
4826 break;
4827 case NEON_SRI_scalar:
4828 sri(vf, rd, rn, right_shift);
4829 break;
4830 case NEON_SSHR_scalar:
4831 sshr(vf, rd, rn, right_shift);
4832 break;
4833 case NEON_USHR_scalar:
4834 ushr(vf, rd, rn, right_shift);
4835 break;
4836 case NEON_SRSHR_scalar:
4837 sshr(vf, rd, rn, right_shift).Round(vf);
4838 break;
4839 case NEON_URSHR_scalar:
4840 ushr(vf, rd, rn, right_shift).Round(vf);
4841 break;
4842 case NEON_SSRA_scalar:
4843 ssra(vf, rd, rn, right_shift);
4844 break;
4845 case NEON_USRA_scalar:
4846 usra(vf, rd, rn, right_shift);
4847 break;
4848 case NEON_SRSRA_scalar:
4849 srsra(vf, rd, rn, right_shift);
4850 break;
4851 case NEON_URSRA_scalar:
4852 ursra(vf, rd, rn, right_shift);
4853 break;
4854 case NEON_UQSHRN_scalar:
4855 uqshrn(vf, rd, rn, right_shift);
4856 break;
4857 case NEON_UQRSHRN_scalar:
4858 uqrshrn(vf, rd, rn, right_shift);
4859 break;
4860 case NEON_SQSHRN_scalar:
4861 sqshrn(vf, rd, rn, right_shift);
4862 break;
4863 case NEON_SQRSHRN_scalar:
4864 sqrshrn(vf, rd, rn, right_shift);
4865 break;
4866 case NEON_SQSHRUN_scalar:
4867 sqshrun(vf, rd, rn, right_shift);
4868 break;
4869 case NEON_SQRSHRUN_scalar:
4870 sqrshrun(vf, rd, rn, right_shift);
4871 break;
4872 case NEON_FCVTZS_imm_scalar:
4873 fcvts(vf, rd, rn, FPZero, right_shift);
4874 break;
4875 case NEON_FCVTZU_imm_scalar:
4876 fcvtu(vf, rd, rn, FPZero, right_shift);
4877 break;
4878 case NEON_SCVTF_imm_scalar:
4879 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
4880 break;
4881 case NEON_UCVTF_imm_scalar:
4882 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
4883 break;
4884 default:
4885 VIXL_UNIMPLEMENTED();
4886 }
4887}
4888
4889
4890void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
4891 SimVRegister& rd = ReadVRegister(instr->GetRd());
4892 SimVRegister& rn = ReadVRegister(instr->GetRn());
4893 FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
4894
4895 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
4896 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
4897 static const NEONFormatMap map = {{22, 21, 20, 19, 30},
4898 {NF_UNDEF,
4899 NF_UNDEF,
4900 NF_8B,
4901 NF_16B,
4902 NF_4H,
4903 NF_8H,
4904 NF_4H,
4905 NF_8H,
4906 NF_2S,
4907 NF_4S,
4908 NF_2S,
4909 NF_4S,
4910 NF_2S,
4911 NF_4S,
4912 NF_2S,
4913 NF_4S,
4914 NF_UNDEF,
4915 NF_2D,
4916 NF_UNDEF,
4917 NF_2D,
4918 NF_UNDEF,
4919 NF_2D,
4920 NF_UNDEF,
4921 NF_2D,
4922 NF_UNDEF,
4923 NF_2D,
4924 NF_UNDEF,
4925 NF_2D,
4926 NF_UNDEF,
4927 NF_2D,
4928 NF_UNDEF,
4929 NF_2D}};
4930 NEONFormatDecoder nfd(instr, &map);
4931 VectorFormat vf = nfd.GetVectorFormat();
4932
4933 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
4934 static const NEONFormatMap map_l =
4935 {{22, 21, 20, 19},
4936 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
4937 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
4938
4939 int highestSetBit = HighestSetBitPosition(instr->GetImmNEONImmh());
4940 int immhimmb = instr->GetImmNEONImmhImmb();
4941 int right_shift = (16 << highestSetBit) - immhimmb;
4942 int left_shift = immhimmb - (8 << highestSetBit);
4943
4944 switch (instr->Mask(NEONShiftImmediateMask)) {
4945 case NEON_SHL:
4946 shl(vf, rd, rn, left_shift);
4947 break;
4948 case NEON_SLI:
4949 sli(vf, rd, rn, left_shift);
4950 break;
4951 case NEON_SQSHLU:
4952 sqshlu(vf, rd, rn, left_shift);
4953 break;
4954 case NEON_SRI:
4955 sri(vf, rd, rn, right_shift);
4956 break;
4957 case NEON_SSHR:
4958 sshr(vf, rd, rn, right_shift);
4959 break;
4960 case NEON_USHR:
4961 ushr(vf, rd, rn, right_shift);
4962 break;
4963 case NEON_SRSHR:
4964 sshr(vf, rd, rn, right_shift).Round(vf);
4965 break;
4966 case NEON_URSHR:
4967 ushr(vf, rd, rn, right_shift).Round(vf);
4968 break;
4969 case NEON_SSRA:
4970 ssra(vf, rd, rn, right_shift);
4971 break;
4972 case NEON_USRA:
4973 usra(vf, rd, rn, right_shift);
4974 break;
4975 case NEON_SRSRA:
4976 srsra(vf, rd, rn, right_shift);
4977 break;
4978 case NEON_URSRA:
4979 ursra(vf, rd, rn, right_shift);
4980 break;
4981 case NEON_SQSHL_imm:
4982 sqshl(vf, rd, rn, left_shift);
4983 break;
4984 case NEON_UQSHL_imm:
4985 uqshl(vf, rd, rn, left_shift);
4986 break;
4987 case NEON_SCVTF_imm:
4988 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
4989 break;
4990 case NEON_UCVTF_imm:
4991 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
4992 break;
4993 case NEON_FCVTZS_imm:
4994 fcvts(vf, rd, rn, FPZero, right_shift);
4995 break;
4996 case NEON_FCVTZU_imm:
4997 fcvtu(vf, rd, rn, FPZero, right_shift);
4998 break;
4999 case NEON_SSHLL:
5000 vf = vf_l;
5001 if (instr->Mask(NEON_Q)) {
5002 sshll2(vf, rd, rn, left_shift);
5003 } else {
5004 sshll(vf, rd, rn, left_shift);
5005 }
5006 break;
5007 case NEON_USHLL:
5008 vf = vf_l;
5009 if (instr->Mask(NEON_Q)) {
5010 ushll2(vf, rd, rn, left_shift);
5011 } else {
5012 ushll(vf, rd, rn, left_shift);
5013 }
5014 break;
5015 case NEON_SHRN:
5016 if (instr->Mask(NEON_Q)) {
5017 shrn2(vf, rd, rn, right_shift);
5018 } else {
5019 shrn(vf, rd, rn, right_shift);
5020 }
5021 break;
5022 case NEON_RSHRN:
5023 if (instr->Mask(NEON_Q)) {
5024 rshrn2(vf, rd, rn, right_shift);
5025 } else {
5026 rshrn(vf, rd, rn, right_shift);
5027 }
5028 break;
5029 case NEON_UQSHRN:
5030 if (instr->Mask(NEON_Q)) {
5031 uqshrn2(vf, rd, rn, right_shift);
5032 } else {
5033 uqshrn(vf, rd, rn, right_shift);
5034 }
5035 break;
5036 case NEON_UQRSHRN:
5037 if (instr->Mask(NEON_Q)) {
5038 uqrshrn2(vf, rd, rn, right_shift);
5039 } else {
5040 uqrshrn(vf, rd, rn, right_shift);
5041 }
5042 break;
5043 case NEON_SQSHRN:
5044 if (instr->Mask(NEON_Q)) {
5045 sqshrn2(vf, rd, rn, right_shift);
5046 } else {
5047 sqshrn(vf, rd, rn, right_shift);
5048 }
5049 break;
5050 case NEON_SQRSHRN:
5051 if (instr->Mask(NEON_Q)) {
5052 sqrshrn2(vf, rd, rn, right_shift);
5053 } else {
5054 sqrshrn(vf, rd, rn, right_shift);
5055 }
5056 break;
5057 case NEON_SQSHRUN:
5058 if (instr->Mask(NEON_Q)) {
5059 sqshrun2(vf, rd, rn, right_shift);
5060 } else {
5061 sqshrun(vf, rd, rn, right_shift);
5062 }
5063 break;
5064 case NEON_SQRSHRUN:
5065 if (instr->Mask(NEON_Q)) {
5066 sqrshrun2(vf, rd, rn, right_shift);
5067 } else {
5068 sqrshrun(vf, rd, rn, right_shift);
5069 }
5070 break;
5071 default:
5072 VIXL_UNIMPLEMENTED();
5073 }
5074}
5075
5076
5077void Simulator::VisitNEONTable(const Instruction* instr) {
5078 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5079 VectorFormat vf = nfd.GetVectorFormat();
5080
5081 SimVRegister& rd = ReadVRegister(instr->GetRd());
5082 SimVRegister& rn = ReadVRegister(instr->GetRn());
5083 SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
5084 SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
5085 SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
5086 SimVRegister& rm = ReadVRegister(instr->GetRm());
5087
5088 switch (instr->Mask(NEONTableMask)) {
5089 case NEON_TBL_1v:
5090 tbl(vf, rd, rn, rm);
5091 break;
5092 case NEON_TBL_2v:
5093 tbl(vf, rd, rn, rn2, rm);
5094 break;
5095 case NEON_TBL_3v:
5096 tbl(vf, rd, rn, rn2, rn3, rm);
5097 break;
5098 case NEON_TBL_4v:
5099 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
5100 break;
5101 case NEON_TBX_1v:
5102 tbx(vf, rd, rn, rm);
5103 break;
5104 case NEON_TBX_2v:
5105 tbx(vf, rd, rn, rn2, rm);
5106 break;
5107 case NEON_TBX_3v:
5108 tbx(vf, rd, rn, rn2, rn3, rm);
5109 break;
5110 case NEON_TBX_4v:
5111 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
5112 break;
5113 default:
5114 VIXL_UNIMPLEMENTED();
5115 }
5116}
5117
5118
5119void Simulator::VisitNEONPerm(const Instruction* instr) {
5120 NEONFormatDecoder nfd(instr);
5121 VectorFormat vf = nfd.GetVectorFormat();
5122
5123 SimVRegister& rd = ReadVRegister(instr->GetRd());
5124 SimVRegister& rn = ReadVRegister(instr->GetRn());
5125 SimVRegister& rm = ReadVRegister(instr->GetRm());
5126
5127 switch (instr->Mask(NEONPermMask)) {
5128 case NEON_TRN1:
5129 trn1(vf, rd, rn, rm);
5130 break;
5131 case NEON_TRN2:
5132 trn2(vf, rd, rn, rm);
5133 break;
5134 case NEON_UZP1:
5135 uzp1(vf, rd, rn, rm);
5136 break;
5137 case NEON_UZP2:
5138 uzp2(vf, rd, rn, rm);
5139 break;
5140 case NEON_ZIP1:
5141 zip1(vf, rd, rn, rm);
5142 break;
5143 case NEON_ZIP2:
5144 zip2(vf, rd, rn, rm);
5145 break;
5146 default:
5147 VIXL_UNIMPLEMENTED();
5148 }
5149}
5150
5151
5152void Simulator::DoUnreachable(const Instruction* instr) {
5153 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
5154 (instr->GetImmException() == kUnreachableOpcode));
5155
5156 fprintf(stream_,
5157 "Hit UNREACHABLE marker at pc=%p.\n",
5158 reinterpret_cast<const void*>(instr));
5159 abort();
5160}
5161
5162
5163void Simulator::DoTrace(const Instruction* instr) {
5164 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
5165 (instr->GetImmException() == kTraceOpcode));
5166
5167 // Read the arguments encoded inline in the instruction stream.
5168 uint32_t parameters;
5169 uint32_t command;
5170
5171 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
5172 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
5173 memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
5174
5175 switch (command) {
5176 case TRACE_ENABLE:
5177 SetTraceParameters(GetTraceParameters() | parameters);
5178 break;
5179 case TRACE_DISABLE:
5180 SetTraceParameters(GetTraceParameters() & ~parameters);
5181 break;
5182 default:
5183 VIXL_UNREACHABLE();
5184 }
5185
5186 WritePc(instr->GetInstructionAtOffset(kTraceLength));
5187}
5188
5189
5190void Simulator::DoLog(const Instruction* instr) {
5191 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
5192 (instr->GetImmException() == kLogOpcode));
5193
5194 // Read the arguments encoded inline in the instruction stream.
5195 uint32_t parameters;
5196
5197 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
5198 memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
5199
5200 // We don't support a one-shot LOG_DISASM.
5201 VIXL_ASSERT((parameters & LOG_DISASM) == 0);
5202 // Print the requested information.
5203 if (parameters & LOG_SYSREGS) PrintSystemRegisters();
5204 if (parameters & LOG_REGS) PrintRegisters();
5205 if (parameters & LOG_VREGS) PrintVRegisters();
5206
5207 WritePc(instr->GetInstructionAtOffset(kLogLength));
5208}
5209
5210
5211void Simulator::DoPrintf(const Instruction* instr) {
5212 VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
5213 (instr->GetImmException() == kPrintfOpcode));
5214
5215 // Read the arguments encoded inline in the instruction stream.
5216 uint32_t arg_count;
5217 uint32_t arg_pattern_list;
5218 VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
5219 memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
5220 memcpy(&arg_pattern_list,
5221 instr + kPrintfArgPatternListOffset,
5222 sizeof(arg_pattern_list));
5223
5224 VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
5225 VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
5226
5227 // We need to call the host printf function with a set of arguments defined by
5228 // arg_pattern_list. Because we don't know the types and sizes of the
5229 // arguments, this is very difficult to do in a robust and portable way. To
5230 // work around the problem, we pick apart the format string, and print one
5231 // format placeholder at a time.
5232
5233 // Allocate space for the format string. We take a copy, so we can modify it.
5234 // Leave enough space for one extra character per expected argument (plus the
5235 // '\0' termination).
5236 const char* format_base = ReadRegister<const char*>(0);
5237 VIXL_ASSERT(format_base != NULL);
5238 size_t length = strlen(format_base) + 1;
5239 char* const format = new char[length + arg_count];
5240
5241 // A list of chunks, each with exactly one format placeholder.
5242 const char* chunks[kPrintfMaxArgCount];
5243
5244 // Copy the format string and search for format placeholders.
5245 uint32_t placeholder_count = 0;
5246 char* format_scratch = format;
5247 for (size_t i = 0; i < length; i++) {
5248 if (format_base[i] != '%') {
5249 *format_scratch++ = format_base[i];
5250 } else {
5251 if (format_base[i + 1] == '%') {
5252 // Ignore explicit "%%" sequences.
5253 *format_scratch++ = format_base[i];
5254 i++;
5255 // Chunks after the first are passed as format strings to printf, so we
5256 // need to escape '%' characters in those chunks.
5257 if (placeholder_count > 0) *format_scratch++ = format_base[i];
5258 } else {
5259 VIXL_CHECK(placeholder_count < arg_count);
5260 // Insert '\0' before placeholders, and store their locations.
5261 *format_scratch++ = '\0';
5262 chunks[placeholder_count++] = format_scratch;
5263 *format_scratch++ = format_base[i];
5264 }
5265 }
5266 }
5267 VIXL_CHECK(placeholder_count == arg_count);
5268
5269 // Finally, call printf with each chunk, passing the appropriate register
5270 // argument. Normally, printf returns the number of bytes transmitted, so we
5271 // can emulate a single printf call by adding the result from each chunk. If
5272 // any call returns a negative (error) value, though, just return that value.
5273
5274 printf("%s", clr_printf);
5275
5276 // Because '\0' is inserted before each placeholder, the first string in
5277 // 'format' contains no format placeholders and should be printed literally.
5278 int result = printf("%s", format);
5279 int pcs_r = 1; // Start at x1. x0 holds the format string.
5280 int pcs_f = 0; // Start at d0.
5281 if (result >= 0) {
5282 for (uint32_t i = 0; i < placeholder_count; i++) {
5283 int part_result = -1;
5284
5285 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
5286 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
5287 switch (arg_pattern) {
5288 case kPrintfArgW:
5289 part_result = printf(chunks[i], ReadWRegister(pcs_r++));
5290 break;
5291 case kPrintfArgX:
5292 part_result = printf(chunks[i], ReadXRegister(pcs_r++));
5293 break;
5294 case kPrintfArgD:
5295 part_result = printf(chunks[i], ReadDRegister(pcs_f++));
5296 break;
5297 default:
5298 VIXL_UNREACHABLE();
5299 }
5300
5301 if (part_result < 0) {
5302 // Handle error values.
5303 result = part_result;
5304 break;
5305 }
5306
5307 result += part_result;
5308 }
5309 }
5310
5311 printf("%s", clr_normal);
5312
5313 // Printf returns its result in x0 (just like the C library's printf).
5314 WriteXRegister(0, result);
5315
5316 // The printf parameters are inlined in the code, so skip them.
5317 WritePc(instr->GetInstructionAtOffset(kPrintfLength));
5318
5319 // Set LR as if we'd just called a native printf function.
5320 WriteLr(ReadPc());
5321
5322 delete[] format;
5323}
5324
Alexandre Rames064e02d2016-07-12 11:53:13 +01005325
Alexandre Ramesca73ba02016-07-28 09:16:03 +01005326#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
Alexandre Rames064e02d2016-07-12 11:53:13 +01005327void Simulator::DoRuntimeCall(const Instruction* instr) {
Alexandre Rames0d2a3d52016-08-15 14:24:44 +01005328 VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
Alexandre Rames064e02d2016-07-12 11:53:13 +01005329 // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
5330 // to call are passed inlined in the assembly.
Alexandre Rames0d2a3d52016-08-15 14:24:44 +01005331 uintptr_t call_wrapper_address =
5332 Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset);
5333 uintptr_t function_address =
5334 Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset);
Alexandre Rames064e02d2016-07-12 11:53:13 +01005335 auto runtime_call_wrapper =
Jacob Bramley482d4df2016-08-05 16:58:17 +01005336 reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
Alexandre Rames0d2a3d52016-08-15 14:24:44 +01005337 runtime_call_wrapper(this, function_address);
Alexandre Rames064e02d2016-07-12 11:53:13 +01005338 WritePc(instr->GetInstructionAtOffset(kRuntimeCallLength));
5339}
5340#else
5341void Simulator::DoRuntimeCall(const Instruction* instr) {
5342 USE(instr);
5343 VIXL_UNREACHABLE();
5344}
5345#endif
5346
Alexandre Ramesd3832962016-07-04 15:03:43 +01005347} // namespace aarch64
5348} // namespace vixl
5349
Pierre Langlois1e85b7f2016-08-05 14:20:36 +01005350#endif // VIXL_INCLUDE_SIMULATOR_AARCH64