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