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