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