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 #ifndef VIXL_A64_ASSEMBLER_A64_H_ 28 #define VIXL_A64_ASSEMBLER_A64_H_ 29 30 31 #include "vixl/globals.h" 32 #include "vixl/invalset.h" 33 #include "vixl/utils.h" 34 #include "vixl/code-buffer.h" 35 #include "vixl/a64/instructions-a64.h" 36 37 namespace vixl { 38 39 typedef uint64_t RegList; 40 static const int kRegListSizeInBits = sizeof(RegList) * 8; 41 42 43 // Registers. 44 45 // Some CPURegister methods can return Register or VRegister types, so we need 46 // to declare them in advance. 47 class Register; 48 class VRegister; 49 50 class CPURegister { 51 public: 52 enum RegisterType { 53 // The kInvalid value is used to detect uninitialized static instances, 54 // which are always zero-initialized before any constructors are called. 55 kInvalid = 0, 56 kRegister, 57 kVRegister, 58 kFPRegister = kVRegister, 59 kNoRegister 60 }; 61 62 CPURegister() : code_(0), size_(0), type_(kNoRegister) { 63 VIXL_ASSERT(!IsValid()); 64 VIXL_ASSERT(IsNone()); 65 } 66 67 CPURegister(unsigned code, unsigned size, RegisterType type) 68 : code_(code), size_(size), type_(type) { 69 VIXL_ASSERT(IsValidOrNone()); 70 } 71 72 unsigned code() const { 73 VIXL_ASSERT(IsValid()); 74 return code_; 75 } 76 77 RegisterType type() const { 78 VIXL_ASSERT(IsValidOrNone()); 79 return type_; 80 } 81 82 RegList Bit() const { 83 VIXL_ASSERT(code_ < (sizeof(RegList) * 8)); 84 return IsValid() ? (static_cast<RegList>(1) << code_) : 0; 85 } 86 87 unsigned size() const { 88 VIXL_ASSERT(IsValid()); 89 return size_; 90 } 91 92 int SizeInBytes() const { 93 VIXL_ASSERT(IsValid()); 94 VIXL_ASSERT(size() % 8 == 0); 95 return size_ / 8; 96 } 97 98 int SizeInBits() const { 99 VIXL_ASSERT(IsValid()); 100 return size_; 101 } 102 103 bool Is8Bits() const { 104 VIXL_ASSERT(IsValid()); 105 return size_ == 8; 106 } 107 108 bool Is16Bits() const { 109 VIXL_ASSERT(IsValid()); 110 return size_ == 16; 111 } 112 113 bool Is32Bits() const { 114 VIXL_ASSERT(IsValid()); 115 return size_ == 32; 116 } 117 118 bool Is64Bits() const { 119 VIXL_ASSERT(IsValid()); 120 return size_ == 64; 121 } 122 123 bool Is128Bits() const { 124 VIXL_ASSERT(IsValid()); 125 return size_ == 128; 126 } 127 128 bool IsValid() const { 129 if (IsValidRegister() || IsValidVRegister()) { 130 VIXL_ASSERT(!IsNone()); 131 return true; 132 } else { 133 VIXL_ASSERT(IsNone()); 134 return false; 135 } 136 } 137 138 bool IsValidRegister() const { 139 return IsRegister() && 140 ((size_ == kWRegSize) || (size_ == kXRegSize)) && 141 ((code_ < kNumberOfRegisters) || (code_ == kSPRegInternalCode)); 142 } 143 144 bool IsValidVRegister() const { 145 return IsVRegister() && 146 ((size_ == kBRegSize) || (size_ == kHRegSize) || 147 (size_ == kSRegSize) || (size_ == kDRegSize) || 148 (size_ == kQRegSize)) && 149 (code_ < kNumberOfVRegisters); 150 } 151 152 bool IsValidFPRegister() const { 153 return IsFPRegister() && (code_ < kNumberOfVRegisters); 154 } 155 156 bool IsNone() const { 157 // kNoRegister types should always have size 0 and code 0. 158 VIXL_ASSERT((type_ != kNoRegister) || (code_ == 0)); 159 VIXL_ASSERT((type_ != kNoRegister) || (size_ == 0)); 160 161 return type_ == kNoRegister; 162 } 163 164 bool Aliases(const CPURegister& other) const { 165 VIXL_ASSERT(IsValidOrNone() && other.IsValidOrNone()); 166 return (code_ == other.code_) && (type_ == other.type_); 167 } 168 169 bool Is(const CPURegister& other) const { 170 VIXL_ASSERT(IsValidOrNone() && other.IsValidOrNone()); 171 return Aliases(other) && (size_ == other.size_); 172 } 173 174 bool IsZero() const { 175 VIXL_ASSERT(IsValid()); 176 return IsRegister() && (code_ == kZeroRegCode); 177 } 178 179 bool IsSP() const { 180 VIXL_ASSERT(IsValid()); 181 return IsRegister() && (code_ == kSPRegInternalCode); 182 } 183 184 bool IsRegister() const { 185 return type_ == kRegister; 186 } 187 188 bool IsVRegister() const { 189 return type_ == kVRegister; 190 } 191 192 bool IsFPRegister() const { 193 return IsS() || IsD(); 194 } 195 196 bool IsW() const { return IsValidRegister() && Is32Bits(); } 197 bool IsX() const { return IsValidRegister() && Is64Bits(); } 198 199 // These assertions ensure that the size and type of the register are as 200 // described. They do not consider the number of lanes that make up a vector. 201 // So, for example, Is8B() implies IsD(), and Is1D() implies IsD, but IsD() 202 // does not imply Is1D() or Is8B(). 203 // Check the number of lanes, ie. the format of the vector, using methods such 204 // as Is8B(), Is1D(), etc. in the VRegister class. 205 bool IsV() const { return IsVRegister(); } 206 bool IsB() const { return IsV() && Is8Bits(); } 207 bool IsH() const { return IsV() && Is16Bits(); } 208 bool IsS() const { return IsV() && Is32Bits(); } 209 bool IsD() const { return IsV() && Is64Bits(); } 210 bool IsQ() const { return IsV() && Is128Bits(); } 211 212 const Register& W() const; 213 const Register& X() const; 214 const VRegister& V() const; 215 const VRegister& B() const; 216 const VRegister& H() const; 217 const VRegister& S() const; 218 const VRegister& D() const; 219 const VRegister& Q() const; 220 221 bool IsSameSizeAndType(const CPURegister& other) const { 222 return (size_ == other.size_) && (type_ == other.type_); 223 } 224 225 protected: 226 unsigned code_; 227 unsigned size_; 228 RegisterType type_; 229 230 private: 231 bool IsValidOrNone() const { 232 return IsValid() || IsNone(); 233 } 234 }; 235 236 237 class Register : public CPURegister { 238 public: 239 Register() : CPURegister() {} 240 explicit Register(const CPURegister& other) 241 : CPURegister(other.code(), other.size(), other.type()) { 242 VIXL_ASSERT(IsValidRegister()); 243 } 244 Register(unsigned code, unsigned size) 245 : CPURegister(code, size, kRegister) {} 246 247 bool IsValid() const { 248 VIXL_ASSERT(IsRegister() || IsNone()); 249 return IsValidRegister(); 250 } 251 252 static const Register& WRegFromCode(unsigned code); 253 static const Register& XRegFromCode(unsigned code); 254 255 private: 256 static const Register wregisters[]; 257 static const Register xregisters[]; 258 }; 259 260 261 class VRegister : public CPURegister { 262 public: 263 VRegister() : CPURegister(), lanes_(1) {} 264 explicit VRegister(const CPURegister& other) 265 : CPURegister(other.code(), other.size(), other.type()), lanes_(1) { 266 VIXL_ASSERT(IsValidVRegister()); 267 VIXL_ASSERT(IsPowerOf2(lanes_) && (lanes_ <= 16)); 268 } 269 VRegister(unsigned code, unsigned size, unsigned lanes = 1) 270 : CPURegister(code, size, kVRegister), lanes_(lanes) { 271 VIXL_ASSERT(IsPowerOf2(lanes_) && (lanes_ <= 16)); 272 } 273 VRegister(unsigned code, VectorFormat format) 274 : CPURegister(code, RegisterSizeInBitsFromFormat(format), kVRegister), 275 lanes_(IsVectorFormat(format) ? LaneCountFromFormat(format) : 1) { 276 VIXL_ASSERT(IsPowerOf2(lanes_) && (lanes_ <= 16)); 277 } 278 279 bool IsValid() const { 280 VIXL_ASSERT(IsVRegister() || IsNone()); 281 return IsValidVRegister(); 282 } 283 284 static const VRegister& BRegFromCode(unsigned code); 285 static const VRegister& HRegFromCode(unsigned code); 286 static const VRegister& SRegFromCode(unsigned code); 287 static const VRegister& DRegFromCode(unsigned code); 288 static const VRegister& QRegFromCode(unsigned code); 289 static const VRegister& VRegFromCode(unsigned code); 290 291 VRegister V8B() const { return VRegister(code_, kDRegSize, 8); } 292 VRegister V16B() const { return VRegister(code_, kQRegSize, 16); } 293 VRegister V4H() const { return VRegister(code_, kDRegSize, 4); } 294 VRegister V8H() const { return VRegister(code_, kQRegSize, 8); } 295 VRegister V2S() const { return VRegister(code_, kDRegSize, 2); } 296 VRegister V4S() const { return VRegister(code_, kQRegSize, 4); } 297 VRegister V2D() const { return VRegister(code_, kQRegSize, 2); } 298 VRegister V1D() const { return VRegister(code_, kDRegSize, 1); } 299 300 bool Is8B() const { return (Is64Bits() && (lanes_ == 8)); } 301 bool Is16B() const { return (Is128Bits() && (lanes_ == 16)); } 302 bool Is4H() const { return (Is64Bits() && (lanes_ == 4)); } 303 bool Is8H() const { return (Is128Bits() && (lanes_ == 8)); } 304 bool Is2S() const { return (Is64Bits() && (lanes_ == 2)); } 305 bool Is4S() const { return (Is128Bits() && (lanes_ == 4)); } 306 bool Is1D() const { return (Is64Bits() && (lanes_ == 1)); } 307 bool Is2D() const { return (Is128Bits() && (lanes_ == 2)); } 308 309 // For consistency, we assert the number of lanes of these scalar registers, 310 // even though there are no vectors of equivalent total size with which they 311 // could alias. 312 bool Is1B() const { 313 VIXL_ASSERT(!(Is8Bits() && IsVector())); 314 return Is8Bits(); 315 } 316 bool Is1H() const { 317 VIXL_ASSERT(!(Is16Bits() && IsVector())); 318 return Is16Bits(); 319 } 320 bool Is1S() const { 321 VIXL_ASSERT(!(Is32Bits() && IsVector())); 322 return Is32Bits(); 323 } 324 325 bool IsLaneSizeB() const { return LaneSizeInBits() == kBRegSize; } 326 bool IsLaneSizeH() const { return LaneSizeInBits() == kHRegSize; } 327 bool IsLaneSizeS() const { return LaneSizeInBits() == kSRegSize; } 328 bool IsLaneSizeD() const { return LaneSizeInBits() == kDRegSize; } 329 330 int lanes() const { 331 return lanes_; 332 } 333 334 bool IsScalar() const { 335 return lanes_ == 1; 336 } 337 338 bool IsVector() const { 339 return lanes_ > 1; 340 } 341 342 bool IsSameFormat(const VRegister& other) const { 343 return (size_ == other.size_) && (lanes_ == other.lanes_); 344 } 345 346 unsigned LaneSizeInBytes() const { 347 return SizeInBytes() / lanes_; 348 } 349 350 unsigned LaneSizeInBits() const { 351 return LaneSizeInBytes() * 8; 352 } 353 354 private: 355 static const VRegister bregisters[]; 356 static const VRegister hregisters[]; 357 static const VRegister sregisters[]; 358 static const VRegister dregisters[]; 359 static const VRegister qregisters[]; 360 static const VRegister vregisters[]; 361 int lanes_; 362 }; 363 364 365 // Backward compatibility for FPRegisters. 366 typedef VRegister FPRegister; 367 368 // No*Reg is used to indicate an unused argument, or an error case. Note that 369 // these all compare equal (using the Is() method). The Register and VRegister 370 // variants are provided for convenience. 371 const Register NoReg; 372 const VRegister NoVReg; 373 const FPRegister NoFPReg; // For backward compatibility. 374 const CPURegister NoCPUReg; 375 376 377 #define DEFINE_REGISTERS(N) \ 378 const Register w##N(N, kWRegSize); \ 379 const Register x##N(N, kXRegSize); 380 REGISTER_CODE_LIST(DEFINE_REGISTERS) 381 #undef DEFINE_REGISTERS 382 const Register wsp(kSPRegInternalCode, kWRegSize); 383 const Register sp(kSPRegInternalCode, kXRegSize); 384 385 386 #define DEFINE_VREGISTERS(N) \ 387 const VRegister b##N(N, kBRegSize); \ 388 const VRegister h##N(N, kHRegSize); \ 389 const VRegister s##N(N, kSRegSize); \ 390 const VRegister d##N(N, kDRegSize); \ 391 const VRegister q##N(N, kQRegSize); \ 392 const VRegister v##N(N, kQRegSize); 393 REGISTER_CODE_LIST(DEFINE_VREGISTERS) 394 #undef DEFINE_VREGISTERS 395 396 397 // Registers aliases. 398 const Register ip0 = x16; 399 const Register ip1 = x17; 400 const Register lr = x30; 401 const Register xzr = x31; 402 const Register wzr = w31; 403 404 405 // AreAliased returns true if any of the named registers overlap. Arguments 406 // set to NoReg are ignored. The system stack pointer may be specified. 407 bool AreAliased(const CPURegister& reg1, 408 const CPURegister& reg2, 409 const CPURegister& reg3 = NoReg, 410 const CPURegister& reg4 = NoReg, 411 const CPURegister& reg5 = NoReg, 412 const CPURegister& reg6 = NoReg, 413 const CPURegister& reg7 = NoReg, 414 const CPURegister& reg8 = NoReg); 415 416 417 // AreSameSizeAndType returns true if all of the specified registers have the 418 // same size, and are of the same type. The system stack pointer may be 419 // specified. Arguments set to NoReg are ignored, as are any subsequent 420 // arguments. At least one argument (reg1) must be valid (not NoCPUReg). 421 bool AreSameSizeAndType(const CPURegister& reg1, 422 const CPURegister& reg2, 423 const CPURegister& reg3 = NoCPUReg, 424 const CPURegister& reg4 = NoCPUReg, 425 const CPURegister& reg5 = NoCPUReg, 426 const CPURegister& reg6 = NoCPUReg, 427 const CPURegister& reg7 = NoCPUReg, 428 const CPURegister& reg8 = NoCPUReg); 429 430 431 // AreSameFormat returns true if all of the specified VRegisters have the same 432 // vector format. Arguments set to NoReg are ignored, as are any subsequent 433 // arguments. At least one argument (reg1) must be valid (not NoVReg). 434 bool AreSameFormat(const VRegister& reg1, 435 const VRegister& reg2, 436 const VRegister& reg3 = NoVReg, 437 const VRegister& reg4 = NoVReg); 438 439 440 // AreConsecutive returns true if all of the specified VRegisters are 441 // consecutive in the register file. Arguments set to NoReg are ignored, as are 442 // any subsequent arguments. At least one argument (reg1) must be valid 443 // (not NoVReg). 444 bool AreConsecutive(const VRegister& reg1, 445 const VRegister& reg2, 446 const VRegister& reg3 = NoVReg, 447 const VRegister& reg4 = NoVReg); 448 449 450 // Lists of registers. 451 class CPURegList { 452 public: 453 explicit CPURegList(CPURegister reg1, 454 CPURegister reg2 = NoCPUReg, 455 CPURegister reg3 = NoCPUReg, 456 CPURegister reg4 = NoCPUReg) 457 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), 458 size_(reg1.size()), type_(reg1.type()) { 459 VIXL_ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4)); 460 VIXL_ASSERT(IsValid()); 461 } 462 463 CPURegList(CPURegister::RegisterType type, unsigned size, RegList list) 464 : list_(list), size_(size), type_(type) { 465 VIXL_ASSERT(IsValid()); 466 } 467 468 CPURegList(CPURegister::RegisterType type, unsigned size, 469 unsigned first_reg, unsigned last_reg) 470 : size_(size), type_(type) { 471 VIXL_ASSERT(((type == CPURegister::kRegister) && 472 (last_reg < kNumberOfRegisters)) || 473 ((type == CPURegister::kVRegister) && 474 (last_reg < kNumberOfVRegisters))); 475 VIXL_ASSERT(last_reg >= first_reg); 476 list_ = (UINT64_C(1) << (last_reg + 1)) - 1; 477 list_ &= ~((UINT64_C(1) << first_reg) - 1); 478 VIXL_ASSERT(IsValid()); 479 } 480 481 CPURegister::RegisterType type() const { 482 VIXL_ASSERT(IsValid()); 483 return type_; 484 } 485 486 // Combine another CPURegList into this one. Registers that already exist in 487 // this list are left unchanged. The type and size of the registers in the 488 // 'other' list must match those in this list. 489 void Combine(const CPURegList& other) { 490 VIXL_ASSERT(IsValid()); 491 VIXL_ASSERT(other.type() == type_); 492 VIXL_ASSERT(other.RegisterSizeInBits() == size_); 493 list_ |= other.list(); 494 } 495 496 // Remove every register in the other CPURegList from this one. Registers that 497 // do not exist in this list are ignored. The type and size of the registers 498 // in the 'other' list must match those in this list. 499 void Remove(const CPURegList& other) { 500 VIXL_ASSERT(IsValid()); 501 VIXL_ASSERT(other.type() == type_); 502 VIXL_ASSERT(other.RegisterSizeInBits() == size_); 503 list_ &= ~other.list(); 504 } 505 506 // Variants of Combine and Remove which take a single register. 507 void Combine(const CPURegister& other) { 508 VIXL_ASSERT(other.type() == type_); 509 VIXL_ASSERT(other.size() == size_); 510 Combine(other.code()); 511 } 512 513 void Remove(const CPURegister& other) { 514 VIXL_ASSERT(other.type() == type_); 515 VIXL_ASSERT(other.size() == size_); 516 Remove(other.code()); 517 } 518 519 // Variants of Combine and Remove which take a single register by its code; 520 // the type and size of the register is inferred from this list. 521 void Combine(int code) { 522 VIXL_ASSERT(IsValid()); 523 VIXL_ASSERT(CPURegister(code, size_, type_).IsValid()); 524 list_ |= (UINT64_C(1) << code); 525 } 526 527 void Remove(int code) { 528 VIXL_ASSERT(IsValid()); 529 VIXL_ASSERT(CPURegister(code, size_, type_).IsValid()); 530 list_ &= ~(UINT64_C(1) << code); 531 } 532 533 static CPURegList Union(const CPURegList& list_1, const CPURegList& list_2) { 534 VIXL_ASSERT(list_1.type_ == list_2.type_); 535 VIXL_ASSERT(list_1.size_ == list_2.size_); 536 return CPURegList(list_1.type_, list_1.size_, list_1.list_ | list_2.list_); 537 } 538 static CPURegList Union(const CPURegList& list_1, 539 const CPURegList& list_2, 540 const CPURegList& list_3); 541 static CPURegList Union(const CPURegList& list_1, 542 const CPURegList& list_2, 543 const CPURegList& list_3, 544 const CPURegList& list_4); 545 546 static CPURegList Intersection(const CPURegList& list_1, 547 const CPURegList& list_2) { 548 VIXL_ASSERT(list_1.type_ == list_2.type_); 549 VIXL_ASSERT(list_1.size_ == list_2.size_); 550 return CPURegList(list_1.type_, list_1.size_, list_1.list_ & list_2.list_); 551 } 552 static CPURegList Intersection(const CPURegList& list_1, 553 const CPURegList& list_2, 554 const CPURegList& list_3); 555 static CPURegList Intersection(const CPURegList& list_1, 556 const CPURegList& list_2, 557 const CPURegList& list_3, 558 const CPURegList& list_4); 559 560 bool Overlaps(const CPURegList& other) const { 561 return (type_ == other.type_) && ((list_ & other.list_) != 0); 562 } 563 564 RegList list() const { 565 VIXL_ASSERT(IsValid()); 566 return list_; 567 } 568 569 void set_list(RegList new_list) { 570 VIXL_ASSERT(IsValid()); 571 list_ = new_list; 572 } 573 574 // Remove all callee-saved registers from the list. This can be useful when 575 // preparing registers for an AAPCS64 function call, for example. 576 void RemoveCalleeSaved(); 577 578 CPURegister PopLowestIndex(); 579 CPURegister PopHighestIndex(); 580 581 // AAPCS64 callee-saved registers. 582 static CPURegList GetCalleeSaved(unsigned size = kXRegSize); 583 static CPURegList GetCalleeSavedV(unsigned size = kDRegSize); 584 585 // AAPCS64 caller-saved registers. Note that this includes lr. 586 // TODO(all): Determine how we handle d8-d15 being callee-saved, but the top 587 // 64-bits being caller-saved. 588 static CPURegList GetCallerSaved(unsigned size = kXRegSize); 589 static CPURegList GetCallerSavedV(unsigned size = kDRegSize); 590 591 bool IsEmpty() const { 592 VIXL_ASSERT(IsValid()); 593 return list_ == 0; 594 } 595 596 bool IncludesAliasOf(const CPURegister& other) const { 597 VIXL_ASSERT(IsValid()); 598 return (type_ == other.type()) && ((other.Bit() & list_) != 0); 599 } 600 601 bool IncludesAliasOf(int code) const { 602 VIXL_ASSERT(IsValid()); 603 return ((code & list_) != 0); 604 } 605 606 int Count() const { 607 VIXL_ASSERT(IsValid()); 608 return CountSetBits(list_); 609 } 610 611 unsigned RegisterSizeInBits() const { 612 VIXL_ASSERT(IsValid()); 613 return size_; 614 } 615 616 unsigned RegisterSizeInBytes() const { 617 int size_in_bits = RegisterSizeInBits(); 618 VIXL_ASSERT((size_in_bits % 8) == 0); 619 return size_in_bits / 8; 620 } 621 622 unsigned TotalSizeInBytes() const { 623 VIXL_ASSERT(IsValid()); 624 return RegisterSizeInBytes() * Count(); 625 } 626 627 private: 628 RegList list_; 629 unsigned size_; 630 CPURegister::RegisterType type_; 631 632 bool IsValid() const; 633 }; 634 635 636 // AAPCS64 callee-saved registers. 637 extern const CPURegList kCalleeSaved; 638 extern const CPURegList kCalleeSavedV; 639 640 641 // AAPCS64 caller-saved registers. Note that this includes lr. 642 extern const CPURegList kCallerSaved; 643 extern const CPURegList kCallerSavedV; 644 645 646 // Operand. 647 class Operand { 648 public: 649 // #<immediate> 650 // where <immediate> is int64_t. 651 // This is allowed to be an implicit constructor because Operand is 652 // a wrapper class that doesn't normally perform any type conversion. 653 Operand(int64_t immediate = 0); // NOLINT(runtime/explicit) 654 655 // rm, {<shift> #<shift_amount>} 656 // where <shift> is one of {LSL, LSR, ASR, ROR}. 657 // <shift_amount> is uint6_t. 658 // This is allowed to be an implicit constructor because Operand is 659 // a wrapper class that doesn't normally perform any type conversion. 660 Operand(Register reg, 661 Shift shift = LSL, 662 unsigned shift_amount = 0); // NOLINT(runtime/explicit) 663 664 // rm, {<extend> {#<shift_amount>}} 665 // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}. 666 // <shift_amount> is uint2_t. 667 explicit Operand(Register reg, Extend extend, unsigned shift_amount = 0); 668 669 bool IsImmediate() const; 670 bool IsShiftedRegister() const; 671 bool IsExtendedRegister() const; 672 bool IsZero() const; 673 674 // This returns an LSL shift (<= 4) operand as an equivalent extend operand, 675 // which helps in the encoding of instructions that use the stack pointer. 676 Operand ToExtendedRegister() const; 677 678 int64_t immediate() const { 679 VIXL_ASSERT(IsImmediate()); 680 return immediate_; 681 } 682 683 Register reg() const { 684 VIXL_ASSERT(IsShiftedRegister() || IsExtendedRegister()); 685 return reg_; 686 } 687 688 Shift shift() const { 689 VIXL_ASSERT(IsShiftedRegister()); 690 return shift_; 691 } 692 693 Extend extend() const { 694 VIXL_ASSERT(IsExtendedRegister()); 695 return extend_; 696 } 697 698 unsigned shift_amount() const { 699 VIXL_ASSERT(IsShiftedRegister() || IsExtendedRegister()); 700 return shift_amount_; 701 } 702 703 private: 704 int64_t immediate_; 705 Register reg_; 706 Shift shift_; 707 Extend extend_; 708 unsigned shift_amount_; 709 }; 710 711 712 // MemOperand represents the addressing mode of a load or store instruction. 713 class MemOperand { 714 public: 715 explicit MemOperand(Register base, 716 int64_t offset = 0, 717 AddrMode addrmode = Offset); 718 MemOperand(Register base, 719 Register regoffset, 720 Shift shift = LSL, 721 unsigned shift_amount = 0); 722 MemOperand(Register base, 723 Register regoffset, 724 Extend extend, 725 unsigned shift_amount = 0); 726 MemOperand(Register base, 727 const Operand& offset, 728 AddrMode addrmode = Offset); 729 730 const Register& base() const { return base_; } 731 const Register& regoffset() const { return regoffset_; } 732 int64_t offset() const { return offset_; } 733 AddrMode addrmode() const { return addrmode_; } 734 Shift shift() const { return shift_; } 735 Extend extend() const { return extend_; } 736 unsigned shift_amount() const { return shift_amount_; } 737 bool IsImmediateOffset() const; 738 bool IsRegisterOffset() const; 739 bool IsPreIndex() const; 740 bool IsPostIndex() const; 741 742 void AddOffset(int64_t offset); 743 744 private: 745 Register base_; 746 Register regoffset_; 747 int64_t offset_; 748 AddrMode addrmode_; 749 Shift shift_; 750 Extend extend_; 751 unsigned shift_amount_; 752 }; 753 754 755 class LabelTestHelper; // Forward declaration. 756 757 758 class Label { 759 public: 760 Label() : location_(kLocationUnbound) {} 761 ~Label() { 762 // If the label has been linked to, it needs to be bound to a target. 763 VIXL_ASSERT(!IsLinked() || IsBound()); 764 } 765 766 bool IsBound() const { return location_ >= 0; } 767 bool IsLinked() const { return !links_.empty(); } 768 769 ptrdiff_t location() const { return location_; } 770 771 static const int kNPreallocatedLinks = 4; 772 static const ptrdiff_t kInvalidLinkKey = PTRDIFF_MAX; 773 static const size_t kReclaimFrom = 512; 774 static const size_t kReclaimFactor = 2; 775 776 typedef InvalSet<ptrdiff_t, 777 kNPreallocatedLinks, 778 ptrdiff_t, 779 kInvalidLinkKey, 780 kReclaimFrom, 781 kReclaimFactor> LinksSetBase; 782 typedef InvalSetIterator<LinksSetBase> LabelLinksIteratorBase; 783 784 private: 785 class LinksSet : public LinksSetBase { 786 public: 787 LinksSet() : LinksSetBase() {} 788 }; 789 790 // Allows iterating over the links of a label. The behaviour is undefined if 791 // the list of links is modified in any way while iterating. 792 class LabelLinksIterator : public LabelLinksIteratorBase { 793 public: 794 explicit LabelLinksIterator(Label* label) 795 : LabelLinksIteratorBase(&label->links_) {} 796 }; 797 798 void Bind(ptrdiff_t location) { 799 // Labels can only be bound once. 800 VIXL_ASSERT(!IsBound()); 801 location_ = location; 802 } 803 804 void AddLink(ptrdiff_t instruction) { 805 // If a label is bound, the assembler already has the information it needs 806 // to write the instruction, so there is no need to add it to links_. 807 VIXL_ASSERT(!IsBound()); 808 links_.insert(instruction); 809 } 810 811 void DeleteLink(ptrdiff_t instruction) { 812 links_.erase(instruction); 813 } 814 815 void ClearAllLinks() { 816 links_.clear(); 817 } 818 819 // TODO: The comment below considers average case complexity for our 820 // usual use-cases. The elements of interest are: 821 // - Branches to a label are emitted in order: branch instructions to a label 822 // are generated at an offset in the code generation buffer greater than any 823 // other branch to that same label already generated. As an example, this can 824 // be broken when an instruction is patched to become a branch. Note that the 825 // code will still work, but the complexity considerations below may locally 826 // not apply any more. 827 // - Veneers are generated in order: for multiple branches of the same type 828 // branching to the same unbound label going out of range, veneers are 829 // generated in growing order of the branch instruction offset from the start 830 // of the buffer. 831 // 832 // When creating a veneer for a branch going out of range, the link for this 833 // branch needs to be removed from this `links_`. Since all branches are 834 // tracked in one underlying InvalSet, the complexity for this deletion is the 835 // same as for finding the element, ie. O(n), where n is the number of links 836 // in the set. 837 // This could be reduced to O(1) by using the same trick as used when tracking 838 // branch information for veneers: split the container to use one set per type 839 // of branch. With that setup, when a veneer is created and the link needs to 840 // be deleted, if the two points above hold, it must be the minimum element of 841 // the set for its type of branch, and that minimum element will be accessible 842 // in O(1). 843 844 // The offsets of the instructions that have linked to this label. 845 LinksSet links_; 846 // The label location. 847 ptrdiff_t location_; 848 849 static const ptrdiff_t kLocationUnbound = -1; 850 851 // It is not safe to copy labels, so disable the copy constructor and operator 852 // by declaring them private (without an implementation). 853 Label(const Label&); 854 void operator=(const Label&); 855 856 // The Assembler class is responsible for binding and linking labels, since 857 // the stored offsets need to be consistent with the Assembler's buffer. 858 friend class Assembler; 859 // The MacroAssembler and VeneerPool handle resolution of branches to distant 860 // targets. 861 friend class MacroAssembler; 862 friend class VeneerPool; 863 }; 864 865 866 // Required InvalSet template specialisations. 867 #define INVAL_SET_TEMPLATE_PARAMETERS \ 868 ptrdiff_t, \ 869 Label::kNPreallocatedLinks, \ 870 ptrdiff_t, \ 871 Label::kInvalidLinkKey, \ 872 Label::kReclaimFrom, \ 873 Label::kReclaimFactor 874 template<> 875 inline ptrdiff_t InvalSet<INVAL_SET_TEMPLATE_PARAMETERS>::Key( 876 const ptrdiff_t& element) { 877 return element; 878 } 879 template<> 880 inline void InvalSet<INVAL_SET_TEMPLATE_PARAMETERS>::SetKey( 881 ptrdiff_t* element, ptrdiff_t key) { 882 *element = key; 883 } 884 #undef INVAL_SET_TEMPLATE_PARAMETERS 885 886 887 // A literal is a 32-bit or 64-bit piece of data stored in the instruction 888 // stream and loaded through a pc relative load. The same literal can be 889 // referred to by multiple instructions but a literal can only reside at one 890 // place in memory. A literal can be used by a load before or after being 891 // placed in memory. 892 // 893 // Internally an offset of 0 is associated with a literal which has been 894 // neither used nor placed. Then two possibilities arise: 895 // 1) the label is placed, the offset (stored as offset + 1) is used to 896 // resolve any subsequent load using the label. 897 // 2) the label is not placed and offset is the offset of the last load using 898 // the literal (stored as -offset -1). If multiple loads refer to this 899 // literal then the last load holds the offset of the preceding load and 900 // all loads form a chain. Once the offset is placed all the loads in the 901 // chain are resolved and future loads fall back to possibility 1. 902 class RawLiteral { 903 public: 904 RawLiteral() : size_(0), offset_(0), low64_(0), high64_(0) {} 905 906 size_t size() { 907 VIXL_STATIC_ASSERT(kDRegSizeInBytes == kXRegSizeInBytes); 908 VIXL_STATIC_ASSERT(kSRegSizeInBytes == kWRegSizeInBytes); 909 VIXL_ASSERT((size_ == kXRegSizeInBytes) || 910 (size_ == kWRegSizeInBytes) || 911 (size_ == kQRegSizeInBytes)); 912 return size_; 913 } 914 uint64_t raw_value128_low64() { 915 VIXL_ASSERT(size_ == kQRegSizeInBytes); 916 return low64_; 917 } 918 uint64_t raw_value128_high64() { 919 VIXL_ASSERT(size_ == kQRegSizeInBytes); 920 return high64_; 921 } 922 uint64_t raw_value64() { 923 VIXL_ASSERT(size_ == kXRegSizeInBytes); 924 VIXL_ASSERT(high64_ == 0); 925 return low64_; 926 } 927 uint32_t raw_value32() { 928 VIXL_ASSERT(size_ == kWRegSizeInBytes); 929 VIXL_ASSERT(high64_ == 0); 930 VIXL_ASSERT(is_uint32(low64_) || is_int32(low64_)); 931 return static_cast<uint32_t>(low64_); 932 } 933 bool IsUsed() { return offset_ < 0; } 934 bool IsPlaced() { return offset_ > 0; } 935 936 protected: 937 ptrdiff_t offset() { 938 VIXL_ASSERT(IsPlaced()); 939 return offset_ - 1; 940 } 941 void set_offset(ptrdiff_t offset) { 942 VIXL_ASSERT(offset >= 0); 943 VIXL_ASSERT(IsWordAligned(offset)); 944 VIXL_ASSERT(!IsPlaced()); 945 offset_ = offset + 1; 946 } 947 ptrdiff_t last_use() { 948 VIXL_ASSERT(IsUsed()); 949 return -offset_ - 1; 950 } 951 void set_last_use(ptrdiff_t offset) { 952 VIXL_ASSERT(offset >= 0); 953 VIXL_ASSERT(IsWordAligned(offset)); 954 VIXL_ASSERT(!IsPlaced()); 955 offset_ = -offset - 1; 956 } 957 958 size_t size_; 959 ptrdiff_t offset_; 960 uint64_t low64_; 961 uint64_t high64_; 962 963 friend class Assembler; 964 }; 965 966 967 template <typename T> 968 class Literal : public RawLiteral { 969 public: 970 explicit Literal(T value) { 971 VIXL_STATIC_ASSERT(sizeof(T) <= kXRegSizeInBytes); 972 size_ = sizeof(value); 973 memcpy(&low64_, &value, sizeof(value)); 974 } 975 976 Literal(T high64, T low64) { 977 VIXL_STATIC_ASSERT(sizeof(T) == (kQRegSizeInBytes / 2)); 978 size_ = kQRegSizeInBytes; 979 memcpy(&low64_, &low64, sizeof(low64)); 980 memcpy(&high64_, &high64, sizeof(high64)); 981 } 982 }; 983 984 985 // Control whether or not position-independent code should be emitted. 986 enum PositionIndependentCodeOption { 987 // All code generated will be position-independent; all branches and 988 // references to labels generated with the Label class will use PC-relative 989 // addressing. 990 PositionIndependentCode, 991 992 // Allow VIXL to generate code that refers to absolute addresses. With this 993 // option, it will not be possible to copy the code buffer and run it from a 994 // different address; code must be generated in its final location. 995 PositionDependentCode, 996 997 // Allow VIXL to assume that the bottom 12 bits of the address will be 998 // constant, but that the top 48 bits may change. This allows `adrp` to 999 // function in systems which copy code between pages, but otherwise maintain 1000 // 4KB page alignment. 1001 PageOffsetDependentCode 1002 }; 1003 1004 1005 // Control how scaled- and unscaled-offset loads and stores are generated. 1006 enum LoadStoreScalingOption { 1007 // Prefer scaled-immediate-offset instructions, but emit unscaled-offset, 1008 // register-offset, pre-index or post-index instructions if necessary. 1009 PreferScaledOffset, 1010 1011 // Prefer unscaled-immediate-offset instructions, but emit scaled-offset, 1012 // register-offset, pre-index or post-index instructions if necessary. 1013 PreferUnscaledOffset, 1014 1015 // Require scaled-immediate-offset instructions. 1016 RequireScaledOffset, 1017 1018 // Require unscaled-immediate-offset instructions. 1019 RequireUnscaledOffset 1020 }; 1021 1022 1023 // Assembler. 1024 class Assembler { 1025 public: 1026 Assembler(size_t capacity, 1027 PositionIndependentCodeOption pic = PositionIndependentCode); 1028 Assembler(byte* buffer, size_t capacity, 1029 PositionIndependentCodeOption pic = PositionIndependentCode); 1030 1031 // The destructor asserts that one of the following is true: 1032 // * The Assembler object has not been used. 1033 // * Nothing has been emitted since the last Reset() call. 1034 // * Nothing has been emitted since the last FinalizeCode() call. 1035 ~Assembler(); 1036 1037 // System functions. 1038 1039 // Start generating code from the beginning of the buffer, discarding any code 1040 // and data that has already been emitted into the buffer. 1041 void Reset(); 1042 1043 // Finalize a code buffer of generated instructions. This function must be 1044 // called before executing or copying code from the buffer. 1045 void FinalizeCode(); 1046 1047 // Label. 1048 // Bind a label to the current PC. 1049 void bind(Label* label); 1050 1051 // Bind a label to a specified offset from the start of the buffer. 1052 void BindToOffset(Label* label, ptrdiff_t offset); 1053 1054 // Place a literal at the current PC. 1055 void place(RawLiteral* literal); 1056 1057 ptrdiff_t CursorOffset() const { 1058 return buffer_->CursorOffset(); 1059 } 1060 1061 ptrdiff_t BufferEndOffset() const { 1062 return static_cast<ptrdiff_t>(buffer_->capacity()); 1063 } 1064 1065 // Return the address of an offset in the buffer. 1066 template <typename T> 1067 T GetOffsetAddress(ptrdiff_t offset) { 1068 VIXL_STATIC_ASSERT(sizeof(T) >= sizeof(uintptr_t)); 1069 return buffer_->GetOffsetAddress<T>(offset); 1070 } 1071 1072 // Return the address of a bound label. 1073 template <typename T> 1074 T GetLabelAddress(const Label * label) { 1075 VIXL_ASSERT(label->IsBound()); 1076 VIXL_STATIC_ASSERT(sizeof(T) >= sizeof(uintptr_t)); 1077 return GetOffsetAddress<T>(label->location()); 1078 } 1079 1080 // Return the address of the cursor. 1081 template <typename T> 1082 T GetCursorAddress() { 1083 VIXL_STATIC_ASSERT(sizeof(T) >= sizeof(uintptr_t)); 1084 return GetOffsetAddress<T>(CursorOffset()); 1085 } 1086 1087 // Return the address of the start of the buffer. 1088 template <typename T> 1089 T GetStartAddress() { 1090 VIXL_STATIC_ASSERT(sizeof(T) >= sizeof(uintptr_t)); 1091 return GetOffsetAddress<T>(0); 1092 } 1093 1094 Instruction* InstructionAt(ptrdiff_t instruction_offset) { 1095 return GetOffsetAddress<Instruction*>(instruction_offset); 1096 } 1097 1098 ptrdiff_t InstructionOffset(Instruction* instruction) { 1099 VIXL_STATIC_ASSERT(sizeof(*instruction) == 1); 1100 ptrdiff_t offset = instruction - GetStartAddress<Instruction*>(); 1101 VIXL_ASSERT((0 <= offset) && 1102 (offset < static_cast<ptrdiff_t>(BufferCapacity()))); 1103 return offset; 1104 } 1105 1106 // Instruction set functions. 1107 1108 // Branch / Jump instructions. 1109 // Branch to register. 1110 void br(const Register& xn); 1111 1112 // Branch with link to register. 1113 void blr(const Register& xn); 1114 1115 // Branch to register with return hint. 1116 void ret(const Register& xn = lr); 1117 1118 // Unconditional branch to label. 1119 void b(Label* label); 1120 1121 // Conditional branch to label. 1122 void b(Label* label, Condition cond); 1123 1124 // Unconditional branch to PC offset. 1125 void b(int imm26); 1126 1127 // Conditional branch to PC offset. 1128 void b(int imm19, Condition cond); 1129 1130 // Branch with link to label. 1131 void bl(Label* label); 1132 1133 // Branch with link to PC offset. 1134 void bl(int imm26); 1135 1136 // Compare and branch to label if zero. 1137 void cbz(const Register& rt, Label* label); 1138 1139 // Compare and branch to PC offset if zero. 1140 void cbz(const Register& rt, int imm19); 1141 1142 // Compare and branch to label if not zero. 1143 void cbnz(const Register& rt, Label* label); 1144 1145 // Compare and branch to PC offset if not zero. 1146 void cbnz(const Register& rt, int imm19); 1147 1148 // Table lookup from one register. 1149 void tbl(const VRegister& vd, 1150 const VRegister& vn, 1151 const VRegister& vm); 1152 1153 // Table lookup from two registers. 1154 void tbl(const VRegister& vd, 1155 const VRegister& vn, 1156 const VRegister& vn2, 1157 const VRegister& vm); 1158 1159 // Table lookup from three registers. 1160 void tbl(const VRegister& vd, 1161 const VRegister& vn, 1162 const VRegister& vn2, 1163 const VRegister& vn3, 1164 const VRegister& vm); 1165 1166 // Table lookup from four registers. 1167 void tbl(const VRegister& vd, 1168 const VRegister& vn, 1169 const VRegister& vn2, 1170 const VRegister& vn3, 1171 const VRegister& vn4, 1172 const VRegister& vm); 1173 1174 // Table lookup extension from one register. 1175 void tbx(const VRegister& vd, 1176 const VRegister& vn, 1177 const VRegister& vm); 1178 1179 // Table lookup extension from two registers. 1180 void tbx(const VRegister& vd, 1181 const VRegister& vn, 1182 const VRegister& vn2, 1183 const VRegister& vm); 1184 1185 // Table lookup extension from three registers. 1186 void tbx(const VRegister& vd, 1187 const VRegister& vn, 1188 const VRegister& vn2, 1189 const VRegister& vn3, 1190 const VRegister& vm); 1191 1192 // Table lookup extension from four registers. 1193 void tbx(const VRegister& vd, 1194 const VRegister& vn, 1195 const VRegister& vn2, 1196 const VRegister& vn3, 1197 const VRegister& vn4, 1198 const VRegister& vm); 1199 1200 // Test bit and branch to label if zero. 1201 void tbz(const Register& rt, unsigned bit_pos, Label* label); 1202 1203 // Test bit and branch to PC offset if zero. 1204 void tbz(const Register& rt, unsigned bit_pos, int imm14); 1205 1206 // Test bit and branch to label if not zero. 1207 void tbnz(const Register& rt, unsigned bit_pos, Label* label); 1208 1209 // Test bit and branch to PC offset if not zero. 1210 void tbnz(const Register& rt, unsigned bit_pos, int imm14); 1211 1212 // Address calculation instructions. 1213 // Calculate a PC-relative address. Unlike for branches the offset in adr is 1214 // unscaled (i.e. the result can be unaligned). 1215 1216 // Calculate the address of a label. 1217 void adr(const Register& rd, Label* label); 1218 1219 // Calculate the address of a PC offset. 1220 void adr(const Register& rd, int imm21); 1221 1222 // Calculate the page address of a label. 1223 void adrp(const Register& rd, Label* label); 1224 1225 // Calculate the page address of a PC offset. 1226 void adrp(const Register& rd, int imm21); 1227 1228 // Data Processing instructions. 1229 // Add. 1230 void add(const Register& rd, 1231 const Register& rn, 1232 const Operand& operand); 1233 1234 // Add and update status flags. 1235 void adds(const Register& rd, 1236 const Register& rn, 1237 const Operand& operand); 1238 1239 // Compare negative. 1240 void cmn(const Register& rn, const Operand& operand); 1241 1242 // Subtract. 1243 void sub(const Register& rd, 1244 const Register& rn, 1245 const Operand& operand); 1246 1247 // Subtract and update status flags. 1248 void subs(const Register& rd, 1249 const Register& rn, 1250 const Operand& operand); 1251 1252 // Compare. 1253 void cmp(const Register& rn, const Operand& operand); 1254 1255 // Negate. 1256 void neg(const Register& rd, 1257 const Operand& operand); 1258 1259 // Negate and update status flags. 1260 void negs(const Register& rd, 1261 const Operand& operand); 1262 1263 // Add with carry bit. 1264 void adc(const Register& rd, 1265 const Register& rn, 1266 const Operand& operand); 1267 1268 // Add with carry bit and update status flags. 1269 void adcs(const Register& rd, 1270 const Register& rn, 1271 const Operand& operand); 1272 1273 // Subtract with carry bit. 1274 void sbc(const Register& rd, 1275 const Register& rn, 1276 const Operand& operand); 1277 1278 // Subtract with carry bit and update status flags. 1279 void sbcs(const Register& rd, 1280 const Register& rn, 1281 const Operand& operand); 1282 1283 // Negate with carry bit. 1284 void ngc(const Register& rd, 1285 const Operand& operand); 1286 1287 // Negate with carry bit and update status flags. 1288 void ngcs(const Register& rd, 1289 const Operand& operand); 1290 1291 // Logical instructions. 1292 // Bitwise and (A & B). 1293 void and_(const Register& rd, 1294 const Register& rn, 1295 const Operand& operand); 1296 1297 // Bitwise and (A & B) and update status flags. 1298 void ands(const Register& rd, 1299 const Register& rn, 1300 const Operand& operand); 1301 1302 // Bit test and set flags. 1303 void tst(const Register& rn, const Operand& operand); 1304 1305 // Bit clear (A & ~B). 1306 void bic(const Register& rd, 1307 const Register& rn, 1308 const Operand& operand); 1309 1310 // Bit clear (A & ~B) and update status flags. 1311 void bics(const Register& rd, 1312 const Register& rn, 1313 const Operand& operand); 1314 1315 // Bitwise or (A | B). 1316 void orr(const Register& rd, const Register& rn, const Operand& operand); 1317 1318 // Bitwise nor (A | ~B). 1319 void orn(const Register& rd, const Register& rn, const Operand& operand); 1320 1321 // Bitwise eor/xor (A ^ B). 1322 void eor(const Register& rd, const Register& rn, const Operand& operand); 1323 1324 // Bitwise enor/xnor (A ^ ~B). 1325 void eon(const Register& rd, const Register& rn, const Operand& operand); 1326 1327 // Logical shift left by variable. 1328 void lslv(const Register& rd, const Register& rn, const Register& rm); 1329 1330 // Logical shift right by variable. 1331 void lsrv(const Register& rd, const Register& rn, const Register& rm); 1332 1333 // Arithmetic shift right by variable. 1334 void asrv(const Register& rd, const Register& rn, const Register& rm); 1335 1336 // Rotate right by variable. 1337 void rorv(const Register& rd, const Register& rn, const Register& rm); 1338 1339 // Bitfield instructions. 1340 // Bitfield move. 1341 void bfm(const Register& rd, 1342 const Register& rn, 1343 unsigned immr, 1344 unsigned imms); 1345 1346 // Signed bitfield move. 1347 void sbfm(const Register& rd, 1348 const Register& rn, 1349 unsigned immr, 1350 unsigned imms); 1351 1352 // Unsigned bitfield move. 1353 void ubfm(const Register& rd, 1354 const Register& rn, 1355 unsigned immr, 1356 unsigned imms); 1357 1358 // Bfm aliases. 1359 // Bitfield insert. 1360 void bfi(const Register& rd, 1361 const Register& rn, 1362 unsigned lsb, 1363 unsigned width) { 1364 VIXL_ASSERT(width >= 1); 1365 VIXL_ASSERT(lsb + width <= rn.size()); 1366 bfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); 1367 } 1368 1369 // Bitfield extract and insert low. 1370 void bfxil(const Register& rd, 1371 const Register& rn, 1372 unsigned lsb, 1373 unsigned width) { 1374 VIXL_ASSERT(width >= 1); 1375 VIXL_ASSERT(lsb + width <= rn.size()); 1376 bfm(rd, rn, lsb, lsb + width - 1); 1377 } 1378 1379 // Sbfm aliases. 1380 // Arithmetic shift right. 1381 void asr(const Register& rd, const Register& rn, unsigned shift) { 1382 VIXL_ASSERT(shift < rd.size()); 1383 sbfm(rd, rn, shift, rd.size() - 1); 1384 } 1385 1386 // Signed bitfield insert with zero at right. 1387 void sbfiz(const Register& rd, 1388 const Register& rn, 1389 unsigned lsb, 1390 unsigned width) { 1391 VIXL_ASSERT(width >= 1); 1392 VIXL_ASSERT(lsb + width <= rn.size()); 1393 sbfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); 1394 } 1395 1396 // Signed bitfield extract. 1397 void sbfx(const Register& rd, 1398 const Register& rn, 1399 unsigned lsb, 1400 unsigned width) { 1401 VIXL_ASSERT(width >= 1); 1402 VIXL_ASSERT(lsb + width <= rn.size()); 1403 sbfm(rd, rn, lsb, lsb + width - 1); 1404 } 1405 1406 // Signed extend byte. 1407 void sxtb(const Register& rd, const Register& rn) { 1408 sbfm(rd, rn, 0, 7); 1409 } 1410 1411 // Signed extend halfword. 1412 void sxth(const Register& rd, const Register& rn) { 1413 sbfm(rd, rn, 0, 15); 1414 } 1415 1416 // Signed extend word. 1417 void sxtw(const Register& rd, const Register& rn) { 1418 sbfm(rd, rn, 0, 31); 1419 } 1420 1421 // Ubfm aliases. 1422 // Logical shift left. 1423 void lsl(const Register& rd, const Register& rn, unsigned shift) { 1424 unsigned reg_size = rd.size(); 1425 VIXL_ASSERT(shift < reg_size); 1426 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1); 1427 } 1428 1429 // Logical shift right. 1430 void lsr(const Register& rd, const Register& rn, unsigned shift) { 1431 VIXL_ASSERT(shift < rd.size()); 1432 ubfm(rd, rn, shift, rd.size() - 1); 1433 } 1434 1435 // Unsigned bitfield insert with zero at right. 1436 void ubfiz(const Register& rd, 1437 const Register& rn, 1438 unsigned lsb, 1439 unsigned width) { 1440 VIXL_ASSERT(width >= 1); 1441 VIXL_ASSERT(lsb + width <= rn.size()); 1442 ubfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); 1443 } 1444 1445 // Unsigned bitfield extract. 1446 void ubfx(const Register& rd, 1447 const Register& rn, 1448 unsigned lsb, 1449 unsigned width) { 1450 VIXL_ASSERT(width >= 1); 1451 VIXL_ASSERT(lsb + width <= rn.size()); 1452 ubfm(rd, rn, lsb, lsb + width - 1); 1453 } 1454 1455 // Unsigned extend byte. 1456 void uxtb(const Register& rd, const Register& rn) { 1457 ubfm(rd, rn, 0, 7); 1458 } 1459 1460 // Unsigned extend halfword. 1461 void uxth(const Register& rd, const Register& rn) { 1462 ubfm(rd, rn, 0, 15); 1463 } 1464 1465 // Unsigned extend word. 1466 void uxtw(const Register& rd, const Register& rn) { 1467 ubfm(rd, rn, 0, 31); 1468 } 1469 1470 // Extract. 1471 void extr(const Register& rd, 1472 const Register& rn, 1473 const Register& rm, 1474 unsigned lsb); 1475 1476 // Conditional select: rd = cond ? rn : rm. 1477 void csel(const Register& rd, 1478 const Register& rn, 1479 const Register& rm, 1480 Condition cond); 1481 1482 // Conditional select increment: rd = cond ? rn : rm + 1. 1483 void csinc(const Register& rd, 1484 const Register& rn, 1485 const Register& rm, 1486 Condition cond); 1487 1488 // Conditional select inversion: rd = cond ? rn : ~rm. 1489 void csinv(const Register& rd, 1490 const Register& rn, 1491 const Register& rm, 1492 Condition cond); 1493 1494 // Conditional select negation: rd = cond ? rn : -rm. 1495 void csneg(const Register& rd, 1496 const Register& rn, 1497 const Register& rm, 1498 Condition cond); 1499 1500 // Conditional set: rd = cond ? 1 : 0. 1501 void cset(const Register& rd, Condition cond); 1502 1503 // Conditional set mask: rd = cond ? -1 : 0. 1504 void csetm(const Register& rd, Condition cond); 1505 1506 // Conditional increment: rd = cond ? rn + 1 : rn. 1507 void cinc(const Register& rd, const Register& rn, Condition cond); 1508 1509 // Conditional invert: rd = cond ? ~rn : rn. 1510 void cinv(const Register& rd, const Register& rn, Condition cond); 1511 1512 // Conditional negate: rd = cond ? -rn : rn. 1513 void cneg(const Register& rd, const Register& rn, Condition cond); 1514 1515 // Rotate right. 1516 void ror(const Register& rd, const Register& rs, unsigned shift) { 1517 extr(rd, rs, rs, shift); 1518 } 1519 1520 // Conditional comparison. 1521 // Conditional compare negative. 1522 void ccmn(const Register& rn, 1523 const Operand& operand, 1524 StatusFlags nzcv, 1525 Condition cond); 1526 1527 // Conditional compare. 1528 void ccmp(const Register& rn, 1529 const Operand& operand, 1530 StatusFlags nzcv, 1531 Condition cond); 1532 1533 // CRC-32 checksum from byte. 1534 void crc32b(const Register& rd, 1535 const Register& rn, 1536 const Register& rm); 1537 1538 // CRC-32 checksum from half-word. 1539 void crc32h(const Register& rd, 1540 const Register& rn, 1541 const Register& rm); 1542 1543 // CRC-32 checksum from word. 1544 void crc32w(const Register& rd, 1545 const Register& rn, 1546 const Register& rm); 1547 1548 // CRC-32 checksum from double word. 1549 void crc32x(const Register& rd, 1550 const Register& rn, 1551 const Register& rm); 1552 1553 // CRC-32 C checksum from byte. 1554 void crc32cb(const Register& rd, 1555 const Register& rn, 1556 const Register& rm); 1557 1558 // CRC-32 C checksum from half-word. 1559 void crc32ch(const Register& rd, 1560 const Register& rn, 1561 const Register& rm); 1562 1563 // CRC-32 C checksum from word. 1564 void crc32cw(const Register& rd, 1565 const Register& rn, 1566 const Register& rm); 1567 1568 // CRC-32C checksum from double word. 1569 void crc32cx(const Register& rd, 1570 const Register& rn, 1571 const Register& rm); 1572 1573 // Multiply. 1574 void mul(const Register& rd, const Register& rn, const Register& rm); 1575 1576 // Negated multiply. 1577 void mneg(const Register& rd, const Register& rn, const Register& rm); 1578 1579 // Signed long multiply: 32 x 32 -> 64-bit. 1580 void smull(const Register& rd, const Register& rn, const Register& rm); 1581 1582 // Signed multiply high: 64 x 64 -> 64-bit <127:64>. 1583 void smulh(const Register& xd, const Register& xn, const Register& xm); 1584 1585 // Multiply and accumulate. 1586 void madd(const Register& rd, 1587 const Register& rn, 1588 const Register& rm, 1589 const Register& ra); 1590 1591 // Multiply and subtract. 1592 void msub(const Register& rd, 1593 const Register& rn, 1594 const Register& rm, 1595 const Register& ra); 1596 1597 // Signed long multiply and accumulate: 32 x 32 + 64 -> 64-bit. 1598 void smaddl(const Register& rd, 1599 const Register& rn, 1600 const Register& rm, 1601 const Register& ra); 1602 1603 // Unsigned long multiply and accumulate: 32 x 32 + 64 -> 64-bit. 1604 void umaddl(const Register& rd, 1605 const Register& rn, 1606 const Register& rm, 1607 const Register& ra); 1608 1609 // Unsigned long multiply: 32 x 32 -> 64-bit. 1610 void umull(const Register& rd, 1611 const Register& rn, 1612 const Register& rm) { 1613 umaddl(rd, rn, rm, xzr); 1614 } 1615 1616 // Unsigned multiply high: 64 x 64 -> 64-bit <127:64>. 1617 void umulh(const Register& xd, 1618 const Register& xn, 1619 const Register& xm); 1620 1621 // Signed long multiply and subtract: 64 - (32 x 32) -> 64-bit. 1622 void smsubl(const Register& rd, 1623 const Register& rn, 1624 const Register& rm, 1625 const Register& ra); 1626 1627 // Unsigned long multiply and subtract: 64 - (32 x 32) -> 64-bit. 1628 void umsubl(const Register& rd, 1629 const Register& rn, 1630 const Register& rm, 1631 const Register& ra); 1632 1633 // Signed integer divide. 1634 void sdiv(const Register& rd, const Register& rn, const Register& rm); 1635 1636 // Unsigned integer divide. 1637 void udiv(const Register& rd, const Register& rn, const Register& rm); 1638 1639 // Bit reverse. 1640 void rbit(const Register& rd, const Register& rn); 1641 1642 // Reverse bytes in 16-bit half words. 1643 void rev16(const Register& rd, const Register& rn); 1644 1645 // Reverse bytes in 32-bit words. 1646 void rev32(const Register& rd, const Register& rn); 1647 1648 // Reverse bytes. 1649 void rev(const Register& rd, const Register& rn); 1650 1651 // Count leading zeroes. 1652 void clz(const Register& rd, const Register& rn); 1653 1654 // Count leading sign bits. 1655 void cls(const Register& rd, const Register& rn); 1656 1657 // Memory instructions. 1658 // Load integer or FP register. 1659 void ldr(const CPURegister& rt, const MemOperand& src, 1660 LoadStoreScalingOption option = PreferScaledOffset); 1661 1662 // Store integer or FP register. 1663 void str(const CPURegister& rt, const MemOperand& dst, 1664 LoadStoreScalingOption option = PreferScaledOffset); 1665 1666 // Load word with sign extension. 1667 void ldrsw(const Register& rt, const MemOperand& src, 1668 LoadStoreScalingOption option = PreferScaledOffset); 1669 1670 // Load byte. 1671 void ldrb(const Register& rt, const MemOperand& src, 1672 LoadStoreScalingOption option = PreferScaledOffset); 1673 1674 // Store byte. 1675 void strb(const Register& rt, const MemOperand& dst, 1676 LoadStoreScalingOption option = PreferScaledOffset); 1677 1678 // Load byte with sign extension. 1679 void ldrsb(const Register& rt, const MemOperand& src, 1680 LoadStoreScalingOption option = PreferScaledOffset); 1681 1682 // Load half-word. 1683 void ldrh(const Register& rt, const MemOperand& src, 1684 LoadStoreScalingOption option = PreferScaledOffset); 1685 1686 // Store half-word. 1687 void strh(const Register& rt, const MemOperand& dst, 1688 LoadStoreScalingOption option = PreferScaledOffset); 1689 1690 // Load half-word with sign extension. 1691 void ldrsh(const Register& rt, const MemOperand& src, 1692 LoadStoreScalingOption option = PreferScaledOffset); 1693 1694 // Load integer or FP register (with unscaled offset). 1695 void ldur(const CPURegister& rt, const MemOperand& src, 1696 LoadStoreScalingOption option = PreferUnscaledOffset); 1697 1698 // Store integer or FP register (with unscaled offset). 1699 void stur(const CPURegister& rt, const MemOperand& src, 1700 LoadStoreScalingOption option = PreferUnscaledOffset); 1701 1702 // Load word with sign extension. 1703 void ldursw(const Register& rt, const MemOperand& src, 1704 LoadStoreScalingOption option = PreferUnscaledOffset); 1705 1706 // Load byte (with unscaled offset). 1707 void ldurb(const Register& rt, const MemOperand& src, 1708 LoadStoreScalingOption option = PreferUnscaledOffset); 1709 1710 // Store byte (with unscaled offset). 1711 void sturb(const Register& rt, const MemOperand& dst, 1712 LoadStoreScalingOption option = PreferUnscaledOffset); 1713 1714 // Load byte with sign extension (and unscaled offset). 1715 void ldursb(const Register& rt, const MemOperand& src, 1716 LoadStoreScalingOption option = PreferUnscaledOffset); 1717 1718 // Load half-word (with unscaled offset). 1719 void ldurh(const Register& rt, const MemOperand& src, 1720 LoadStoreScalingOption option = PreferUnscaledOffset); 1721 1722 // Store half-word (with unscaled offset). 1723 void sturh(const Register& rt, const MemOperand& dst, 1724 LoadStoreScalingOption option = PreferUnscaledOffset); 1725 1726 // Load half-word with sign extension (and unscaled offset). 1727 void ldursh(const Register& rt, const MemOperand& src, 1728 LoadStoreScalingOption option = PreferUnscaledOffset); 1729 1730 // Load integer or FP register pair. 1731 void ldp(const CPURegister& rt, const CPURegister& rt2, 1732 const MemOperand& src); 1733 1734 // Store integer or FP register pair. 1735 void stp(const CPURegister& rt, const CPURegister& rt2, 1736 const MemOperand& dst); 1737 1738 // Load word pair with sign extension. 1739 void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src); 1740 1741 // Load integer or FP register pair, non-temporal. 1742 void ldnp(const CPURegister& rt, const CPURegister& rt2, 1743 const MemOperand& src); 1744 1745 // Store integer or FP register pair, non-temporal. 1746 void stnp(const CPURegister& rt, const CPURegister& rt2, 1747 const MemOperand& dst); 1748 1749 // Load integer or FP register from literal pool. 1750 void ldr(const CPURegister& rt, RawLiteral* literal); 1751 1752 // Load word with sign extension from literal pool. 1753 void ldrsw(const Register& rt, RawLiteral* literal); 1754 1755 // Load integer or FP register from pc + imm19 << 2. 1756 void ldr(const CPURegister& rt, int imm19); 1757 1758 // Load word with sign extension from pc + imm19 << 2. 1759 void ldrsw(const Register& rt, int imm19); 1760 1761 // Store exclusive byte. 1762 void stxrb(const Register& rs, const Register& rt, const MemOperand& dst); 1763 1764 // Store exclusive half-word. 1765 void stxrh(const Register& rs, const Register& rt, const MemOperand& dst); 1766 1767 // Store exclusive register. 1768 void stxr(const Register& rs, const Register& rt, const MemOperand& dst); 1769 1770 // Load exclusive byte. 1771 void ldxrb(const Register& rt, const MemOperand& src); 1772 1773 // Load exclusive half-word. 1774 void ldxrh(const Register& rt, const MemOperand& src); 1775 1776 // Load exclusive register. 1777 void ldxr(const Register& rt, const MemOperand& src); 1778 1779 // Store exclusive register pair. 1780 void stxp(const Register& rs, 1781 const Register& rt, 1782 const Register& rt2, 1783 const MemOperand& dst); 1784 1785 // Load exclusive register pair. 1786 void ldxp(const Register& rt, const Register& rt2, const MemOperand& src); 1787 1788 // Store-release exclusive byte. 1789 void stlxrb(const Register& rs, const Register& rt, const MemOperand& dst); 1790 1791 // Store-release exclusive half-word. 1792 void stlxrh(const Register& rs, const Register& rt, const MemOperand& dst); 1793 1794 // Store-release exclusive register. 1795 void stlxr(const Register& rs, const Register& rt, const MemOperand& dst); 1796 1797 // Load-acquire exclusive byte. 1798 void ldaxrb(const Register& rt, const MemOperand& src); 1799 1800 // Load-acquire exclusive half-word. 1801 void ldaxrh(const Register& rt, const MemOperand& src); 1802 1803 // Load-acquire exclusive register. 1804 void ldaxr(const Register& rt, const MemOperand& src); 1805 1806 // Store-release exclusive register pair. 1807 void stlxp(const Register& rs, 1808 const Register& rt, 1809 const Register& rt2, 1810 const MemOperand& dst); 1811 1812 // Load-acquire exclusive register pair. 1813 void ldaxp(const Register& rt, const Register& rt2, const MemOperand& src); 1814 1815 // Store-release byte. 1816 void stlrb(const Register& rt, const MemOperand& dst); 1817 1818 // Store-release half-word. 1819 void stlrh(const Register& rt, const MemOperand& dst); 1820 1821 // Store-release register. 1822 void stlr(const Register& rt, const MemOperand& dst); 1823 1824 // Load-acquire byte. 1825 void ldarb(const Register& rt, const MemOperand& src); 1826 1827 // Load-acquire half-word. 1828 void ldarh(const Register& rt, const MemOperand& src); 1829 1830 // Load-acquire register. 1831 void ldar(const Register& rt, const MemOperand& src); 1832 1833 // Prefetch memory. 1834 void prfm(PrefetchOperation op, const MemOperand& addr, 1835 LoadStoreScalingOption option = PreferScaledOffset); 1836 1837 // Prefetch memory (with unscaled offset). 1838 void prfum(PrefetchOperation op, const MemOperand& addr, 1839 LoadStoreScalingOption option = PreferUnscaledOffset); 1840 1841 // Prefetch memory in the literal pool. 1842 void prfm(PrefetchOperation op, RawLiteral* literal); 1843 1844 // Prefetch from pc + imm19 << 2. 1845 void prfm(PrefetchOperation op, int imm19); 1846 1847 // Move instructions. The default shift of -1 indicates that the move 1848 // instruction will calculate an appropriate 16-bit immediate and left shift 1849 // that is equal to the 64-bit immediate argument. If an explicit left shift 1850 // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value. 1851 // 1852 // For movk, an explicit shift can be used to indicate which half word should 1853 // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant 1854 // half word with zero, whereas movk(x0, 0, 48) will overwrite the 1855 // most-significant. 1856 1857 // Move immediate and keep. 1858 void movk(const Register& rd, uint64_t imm, int shift = -1) { 1859 MoveWide(rd, imm, shift, MOVK); 1860 } 1861 1862 // Move inverted immediate. 1863 void movn(const Register& rd, uint64_t imm, int shift = -1) { 1864 MoveWide(rd, imm, shift, MOVN); 1865 } 1866 1867 // Move immediate. 1868 void movz(const Register& rd, uint64_t imm, int shift = -1) { 1869 MoveWide(rd, imm, shift, MOVZ); 1870 } 1871 1872 // Misc instructions. 1873 // Monitor debug-mode breakpoint. 1874 void brk(int code); 1875 1876 // Halting debug-mode breakpoint. 1877 void hlt(int code); 1878 1879 // Generate exception targeting EL1. 1880 void svc(int code); 1881 1882 // Move register to register. 1883 void mov(const Register& rd, const Register& rn); 1884 1885 // Move inverted operand to register. 1886 void mvn(const Register& rd, const Operand& operand); 1887 1888 // System instructions. 1889 // Move to register from system register. 1890 void mrs(const Register& rt, SystemRegister sysreg); 1891 1892 // Move from register to system register. 1893 void msr(SystemRegister sysreg, const Register& rt); 1894 1895 // System instruction. 1896 void sys(int op1, int crn, int crm, int op2, const Register& rt = xzr); 1897 1898 // System instruction with pre-encoded op (op1:crn:crm:op2). 1899 void sys(int op, const Register& rt = xzr); 1900 1901 // System data cache operation. 1902 void dc(DataCacheOp op, const Register& rt); 1903 1904 // System instruction cache operation. 1905 void ic(InstructionCacheOp op, const Register& rt); 1906 1907 // System hint. 1908 void hint(SystemHint code); 1909 1910 // Clear exclusive monitor. 1911 void clrex(int imm4 = 0xf); 1912 1913 // Data memory barrier. 1914 void dmb(BarrierDomain domain, BarrierType type); 1915 1916 // Data synchronization barrier. 1917 void dsb(BarrierDomain domain, BarrierType type); 1918 1919 // Instruction synchronization barrier. 1920 void isb(); 1921 1922 // Alias for system instructions. 1923 // No-op. 1924 void nop() { 1925 hint(NOP); 1926 } 1927 1928 // FP and NEON instructions. 1929 // Move double precision immediate to FP register. 1930 void fmov(const VRegister& vd, double imm); 1931 1932 // Move single precision immediate to FP register. 1933 void fmov(const VRegister& vd, float imm); 1934 1935 // Move FP register to register. 1936 void fmov(const Register& rd, const VRegister& fn); 1937 1938 // Move register to FP register. 1939 void fmov(const VRegister& vd, const Register& rn); 1940 1941 // Move FP register to FP register. 1942 void fmov(const VRegister& vd, const VRegister& fn); 1943 1944 // Move 64-bit register to top half of 128-bit FP register. 1945 void fmov(const VRegister& vd, int index, const Register& rn); 1946 1947 // Move top half of 128-bit FP register to 64-bit register. 1948 void fmov(const Register& rd, const VRegister& vn, int index); 1949 1950 // FP add. 1951 void fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm); 1952 1953 // FP subtract. 1954 void fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm); 1955 1956 // FP multiply. 1957 void fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm); 1958 1959 // FP fused multiply-add. 1960 void fmadd(const VRegister& vd, 1961 const VRegister& vn, 1962 const VRegister& vm, 1963 const VRegister& va); 1964 1965 // FP fused multiply-subtract. 1966 void fmsub(const VRegister& vd, 1967 const VRegister& vn, 1968 const VRegister& vm, 1969 const VRegister& va); 1970 1971 // FP fused multiply-add and negate. 1972 void fnmadd(const VRegister& vd, 1973 const VRegister& vn, 1974 const VRegister& vm, 1975 const VRegister& va); 1976 1977 // FP fused multiply-subtract and negate. 1978 void fnmsub(const VRegister& vd, 1979 const VRegister& vn, 1980 const VRegister& vm, 1981 const VRegister& va); 1982 1983 // FP multiply-negate scalar. 1984 void fnmul(const VRegister& vd, 1985 const VRegister& vn, 1986 const VRegister& vm); 1987 1988 // FP reciprocal exponent scalar. 1989 void frecpx(const VRegister& vd, 1990 const VRegister& vn); 1991 1992 // FP divide. 1993 void fdiv(const VRegister& vd, const VRegister& fn, const VRegister& vm); 1994 1995 // FP maximum. 1996 void fmax(const VRegister& vd, const VRegister& fn, const VRegister& vm); 1997 1998 // FP minimum. 1999 void fmin(const VRegister& vd, const VRegister& fn, const VRegister& vm); 2000 2001 // FP maximum number. 2002 void fmaxnm(const VRegister& vd, const VRegister& fn, const VRegister& vm); 2003 2004 // FP minimum number. 2005 void fminnm(const VRegister& vd, const VRegister& fn, const VRegister& vm); 2006 2007 // FP absolute. 2008 void fabs(const VRegister& vd, const VRegister& vn); 2009 2010 // FP negate. 2011 void fneg(const VRegister& vd, const VRegister& vn); 2012 2013 // FP square root. 2014 void fsqrt(const VRegister& vd, const VRegister& vn); 2015 2016 // FP round to integer, nearest with ties to away. 2017 void frinta(const VRegister& vd, const VRegister& vn); 2018 2019 // FP round to integer, implicit rounding. 2020 void frinti(const VRegister& vd, const VRegister& vn); 2021 2022 // FP round to integer, toward minus infinity. 2023 void frintm(const VRegister& vd, const VRegister& vn); 2024 2025 // FP round to integer, nearest with ties to even. 2026 void frintn(const VRegister& vd, const VRegister& vn); 2027 2028 // FP round to integer, toward plus infinity. 2029 void frintp(const VRegister& vd, const VRegister& vn); 2030 2031 // FP round to integer, exact, implicit rounding. 2032 void frintx(const VRegister& vd, const VRegister& vn); 2033 2034 // FP round to integer, towards zero. 2035 void frintz(const VRegister& vd, const VRegister& vn); 2036 2037 void FPCompareMacro(const VRegister& vn, 2038 double value, 2039 FPTrapFlags trap); 2040 2041 void FPCompareMacro(const VRegister& vn, 2042 const VRegister& vm, 2043 FPTrapFlags trap); 2044 2045 // FP compare registers. 2046 void fcmp(const VRegister& vn, const VRegister& vm); 2047 2048 // FP compare immediate. 2049 void fcmp(const VRegister& vn, double value); 2050 2051 void FPCCompareMacro(const VRegister& vn, 2052 const VRegister& vm, 2053 StatusFlags nzcv, 2054 Condition cond, 2055 FPTrapFlags trap); 2056 2057 // FP conditional compare. 2058 void fccmp(const VRegister& vn, 2059 const VRegister& vm, 2060 StatusFlags nzcv, 2061 Condition cond); 2062 2063 // FP signaling compare registers. 2064 void fcmpe(const VRegister& vn, const VRegister& vm); 2065 2066 // FP signaling compare immediate. 2067 void fcmpe(const VRegister& vn, double value); 2068 2069 // FP conditional signaling compare. 2070 void fccmpe(const VRegister& vn, 2071 const VRegister& vm, 2072 StatusFlags nzcv, 2073 Condition cond); 2074 2075 // FP conditional select. 2076 void fcsel(const VRegister& vd, 2077 const VRegister& vn, 2078 const VRegister& vm, 2079 Condition cond); 2080 2081 // Common FP Convert functions. 2082 void NEONFPConvertToInt(const Register& rd, 2083 const VRegister& vn, 2084 Instr op); 2085 void NEONFPConvertToInt(const VRegister& vd, 2086 const VRegister& vn, 2087 Instr op); 2088 2089 // FP convert between precisions. 2090 void fcvt(const VRegister& vd, const VRegister& vn); 2091 2092 // FP convert to higher precision. 2093 void fcvtl(const VRegister& vd, const VRegister& vn); 2094 2095 // FP convert to higher precision (second part). 2096 void fcvtl2(const VRegister& vd, const VRegister& vn); 2097 2098 // FP convert to lower precision. 2099 void fcvtn(const VRegister& vd, const VRegister& vn); 2100 2101 // FP convert to lower prevision (second part). 2102 void fcvtn2(const VRegister& vd, const VRegister& vn); 2103 2104 // FP convert to lower precision, rounding to odd. 2105 void fcvtxn(const VRegister& vd, const VRegister& vn); 2106 2107 // FP convert to lower precision, rounding to odd (second part). 2108 void fcvtxn2(const VRegister& vd, const VRegister& vn); 2109 2110 // FP convert to signed integer, nearest with ties to away. 2111 void fcvtas(const Register& rd, const VRegister& vn); 2112 2113 // FP convert to unsigned integer, nearest with ties to away. 2114 void fcvtau(const Register& rd, const VRegister& vn); 2115 2116 // FP convert to signed integer, nearest with ties to away. 2117 void fcvtas(const VRegister& vd, const VRegister& vn); 2118 2119 // FP convert to unsigned integer, nearest with ties to away. 2120 void fcvtau(const VRegister& vd, const VRegister& vn); 2121 2122 // FP convert to signed integer, round towards -infinity. 2123 void fcvtms(const Register& rd, const VRegister& vn); 2124 2125 // FP convert to unsigned integer, round towards -infinity. 2126 void fcvtmu(const Register& rd, const VRegister& vn); 2127 2128 // FP convert to signed integer, round towards -infinity. 2129 void fcvtms(const VRegister& vd, const VRegister& vn); 2130 2131 // FP convert to unsigned integer, round towards -infinity. 2132 void fcvtmu(const VRegister& vd, const VRegister& vn); 2133 2134 // FP convert to signed integer, nearest with ties to even. 2135 void fcvtns(const Register& rd, const VRegister& vn); 2136 2137 // FP convert to unsigned integer, nearest with ties to even. 2138 void fcvtnu(const Register& rd, const VRegister& vn); 2139 2140 // FP convert to signed integer, nearest with ties to even. 2141 void fcvtns(const VRegister& rd, const VRegister& vn); 2142 2143 // FP convert to unsigned integer, nearest with ties to even. 2144 void fcvtnu(const VRegister& rd, const VRegister& vn); 2145 2146 // FP convert to signed integer or fixed-point, round towards zero. 2147 void fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0); 2148 2149 // FP convert to unsigned integer or fixed-point, round towards zero. 2150 void fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0); 2151 2152 // FP convert to signed integer or fixed-point, round towards zero. 2153 void fcvtzs(const VRegister& vd, const VRegister& vn, int fbits = 0); 2154 2155 // FP convert to unsigned integer or fixed-point, round towards zero. 2156 void fcvtzu(const VRegister& vd, const VRegister& vn, int fbits = 0); 2157 2158 // FP convert to signed integer, round towards +infinity. 2159 void fcvtps(const Register& rd, const VRegister& vn); 2160 2161 // FP convert to unsigned integer, round towards +infinity. 2162 void fcvtpu(const Register& rd, const VRegister& vn); 2163 2164 // FP convert to signed integer, round towards +infinity. 2165 void fcvtps(const VRegister& vd, const VRegister& vn); 2166 2167 // FP convert to unsigned integer, round towards +infinity. 2168 void fcvtpu(const VRegister& vd, const VRegister& vn); 2169 2170 // Convert signed integer or fixed point to FP. 2171 void scvtf(const VRegister& fd, const Register& rn, int fbits = 0); 2172 2173 // Convert unsigned integer or fixed point to FP. 2174 void ucvtf(const VRegister& fd, const Register& rn, int fbits = 0); 2175 2176 // Convert signed integer or fixed-point to FP. 2177 void scvtf(const VRegister& fd, const VRegister& vn, int fbits = 0); 2178 2179 // Convert unsigned integer or fixed-point to FP. 2180 void ucvtf(const VRegister& fd, const VRegister& vn, int fbits = 0); 2181 2182 // Unsigned absolute difference. 2183 void uabd(const VRegister& vd, 2184 const VRegister& vn, 2185 const VRegister& vm); 2186 2187 // Signed absolute difference. 2188 void sabd(const VRegister& vd, 2189 const VRegister& vn, 2190 const VRegister& vm); 2191 2192 // Unsigned absolute difference and accumulate. 2193 void uaba(const VRegister& vd, 2194 const VRegister& vn, 2195 const VRegister& vm); 2196 2197 // Signed absolute difference and accumulate. 2198 void saba(const VRegister& vd, 2199 const VRegister& vn, 2200 const VRegister& vm); 2201 2202 // Add. 2203 void add(const VRegister& vd, 2204 const VRegister& vn, 2205 const VRegister& vm); 2206 2207 // Subtract. 2208 void sub(const VRegister& vd, 2209 const VRegister& vn, 2210 const VRegister& vm); 2211 2212 // Unsigned halving add. 2213 void uhadd(const VRegister& vd, 2214 const VRegister& vn, 2215 const VRegister& vm); 2216 2217 // Signed halving add. 2218 void shadd(const VRegister& vd, 2219 const VRegister& vn, 2220 const VRegister& vm); 2221 2222 // Unsigned rounding halving add. 2223 void urhadd(const VRegister& vd, 2224 const VRegister& vn, 2225 const VRegister& vm); 2226 2227 // Signed rounding halving add. 2228 void srhadd(const VRegister& vd, 2229 const VRegister& vn, 2230 const VRegister& vm); 2231 2232 // Unsigned halving sub. 2233 void uhsub(const VRegister& vd, 2234 const VRegister& vn, 2235 const VRegister& vm); 2236 2237 // Signed halving sub. 2238 void shsub(const VRegister& vd, 2239 const VRegister& vn, 2240 const VRegister& vm); 2241 2242 // Unsigned saturating add. 2243 void uqadd(const VRegister& vd, 2244 const VRegister& vn, 2245 const VRegister& vm); 2246 2247 // Signed saturating add. 2248 void sqadd(const VRegister& vd, 2249 const VRegister& vn, 2250 const VRegister& vm); 2251 2252 // Unsigned saturating subtract. 2253 void uqsub(const VRegister& vd, 2254 const VRegister& vn, 2255 const VRegister& vm); 2256 2257 // Signed saturating subtract. 2258 void sqsub(const VRegister& vd, 2259 const VRegister& vn, 2260 const VRegister& vm); 2261 2262 // Add pairwise. 2263 void addp(const VRegister& vd, 2264 const VRegister& vn, 2265 const VRegister& vm); 2266 2267 // Add pair of elements scalar. 2268 void addp(const VRegister& vd, 2269 const VRegister& vn); 2270 2271 // Multiply-add to accumulator. 2272 void mla(const VRegister& vd, 2273 const VRegister& vn, 2274 const VRegister& vm); 2275 2276 // Multiply-subtract to accumulator. 2277 void mls(const VRegister& vd, 2278 const VRegister& vn, 2279 const VRegister& vm); 2280 2281 // Multiply. 2282 void mul(const VRegister& vd, 2283 const VRegister& vn, 2284 const VRegister& vm); 2285 2286 // Multiply by scalar element. 2287 void mul(const VRegister& vd, 2288 const VRegister& vn, 2289 const VRegister& vm, 2290 int vm_index); 2291 2292 // Multiply-add by scalar element. 2293 void mla(const VRegister& vd, 2294 const VRegister& vn, 2295 const VRegister& vm, 2296 int vm_index); 2297 2298 // Multiply-subtract by scalar element. 2299 void mls(const VRegister& vd, 2300 const VRegister& vn, 2301 const VRegister& vm, 2302 int vm_index); 2303 2304 // Signed long multiply-add by scalar element. 2305 void smlal(const VRegister& vd, 2306 const VRegister& vn, 2307 const VRegister& vm, 2308 int vm_index); 2309 2310 // Signed long multiply-add by scalar element (second part). 2311 void smlal2(const VRegister& vd, 2312 const VRegister& vn, 2313 const VRegister& vm, 2314 int vm_index); 2315 2316 // Unsigned long multiply-add by scalar element. 2317 void umlal(const VRegister& vd, 2318 const VRegister& vn, 2319 const VRegister& vm, 2320 int vm_index); 2321 2322 // Unsigned long multiply-add by scalar element (second part). 2323 void umlal2(const VRegister& vd, 2324 const VRegister& vn, 2325 const VRegister& vm, 2326 int vm_index); 2327 2328 // Signed long multiply-sub by scalar element. 2329 void smlsl(const VRegister& vd, 2330 const VRegister& vn, 2331 const VRegister& vm, 2332 int vm_index); 2333 2334 // Signed long multiply-sub by scalar element (second part). 2335 void smlsl2(const VRegister& vd, 2336 const VRegister& vn, 2337 const VRegister& vm, 2338 int vm_index); 2339 2340 // Unsigned long multiply-sub by scalar element. 2341 void umlsl(const VRegister& vd, 2342 const VRegister& vn, 2343 const VRegister& vm, 2344 int vm_index); 2345 2346 // Unsigned long multiply-sub by scalar element (second part). 2347 void umlsl2(const VRegister& vd, 2348 const VRegister& vn, 2349 const VRegister& vm, 2350 int vm_index); 2351 2352 // Signed long multiply by scalar element. 2353 void smull(const VRegister& vd, 2354 const VRegister& vn, 2355 const VRegister& vm, 2356 int vm_index); 2357 2358 // Signed long multiply by scalar element (second part). 2359 void smull2(const VRegister& vd, 2360 const VRegister& vn, 2361 const VRegister& vm, 2362 int vm_index); 2363 2364 // Unsigned long multiply by scalar element. 2365 void umull(const VRegister& vd, 2366 const VRegister& vn, 2367 const VRegister& vm, 2368 int vm_index); 2369 2370 // Unsigned long multiply by scalar element (second part). 2371 void umull2(const VRegister& vd, 2372 const VRegister& vn, 2373 const VRegister& vm, 2374 int vm_index); 2375 2376 // Signed saturating double long multiply by element. 2377 void sqdmull(const VRegister& vd, 2378 const VRegister& vn, 2379 const VRegister& vm, 2380 int vm_index); 2381 2382 // Signed saturating double long multiply by element (second part). 2383 void sqdmull2(const VRegister& vd, 2384 const VRegister& vn, 2385 const VRegister& vm, 2386 int vm_index); 2387 2388 // Signed saturating doubling long multiply-add by element. 2389 void sqdmlal(const VRegister& vd, 2390 const VRegister& vn, 2391 const VRegister& vm, 2392 int vm_index); 2393 2394 // Signed saturating doubling long multiply-add by element (second part). 2395 void sqdmlal2(const VRegister& vd, 2396 const VRegister& vn, 2397 const VRegister& vm, 2398 int vm_index); 2399 2400 // Signed saturating doubling long multiply-sub by element. 2401 void sqdmlsl(const VRegister& vd, 2402 const VRegister& vn, 2403 const VRegister& vm, 2404 int vm_index); 2405 2406 // Signed saturating doubling long multiply-sub by element (second part). 2407 void sqdmlsl2(const VRegister& vd, 2408 const VRegister& vn, 2409 const VRegister& vm, 2410 int vm_index); 2411 2412 // Compare equal. 2413 void cmeq(const VRegister& vd, 2414 const VRegister& vn, 2415 const VRegister& vm); 2416 2417 // Compare signed greater than or equal. 2418 void cmge(const VRegister& vd, 2419 const VRegister& vn, 2420 const VRegister& vm); 2421 2422 // Compare signed greater than. 2423 void cmgt(const VRegister& vd, 2424 const VRegister& vn, 2425 const VRegister& vm); 2426 2427 // Compare unsigned higher. 2428 void cmhi(const VRegister& vd, 2429 const VRegister& vn, 2430 const VRegister& vm); 2431 2432 // Compare unsigned higher or same. 2433 void cmhs(const VRegister& vd, 2434 const VRegister& vn, 2435 const VRegister& vm); 2436 2437 // Compare bitwise test bits nonzero. 2438 void cmtst(const VRegister& vd, 2439 const VRegister& vn, 2440 const VRegister& vm); 2441 2442 // Compare bitwise to zero. 2443 void cmeq(const VRegister& vd, 2444 const VRegister& vn, 2445 int value); 2446 2447 // Compare signed greater than or equal to zero. 2448 void cmge(const VRegister& vd, 2449 const VRegister& vn, 2450 int value); 2451 2452 // Compare signed greater than zero. 2453 void cmgt(const VRegister& vd, 2454 const VRegister& vn, 2455 int value); 2456 2457 // Compare signed less than or equal to zero. 2458 void cmle(const VRegister& vd, 2459 const VRegister& vn, 2460 int value); 2461 2462 // Compare signed less than zero. 2463 void cmlt(const VRegister& vd, 2464 const VRegister& vn, 2465 int value); 2466 2467 // Signed shift left by register. 2468 void sshl(const VRegister& vd, 2469 const VRegister& vn, 2470 const VRegister& vm); 2471 2472 // Unsigned shift left by register. 2473 void ushl(const VRegister& vd, 2474 const VRegister& vn, 2475 const VRegister& vm); 2476 2477 // Signed saturating shift left by register. 2478 void sqshl(const VRegister& vd, 2479 const VRegister& vn, 2480 const VRegister& vm); 2481 2482 // Unsigned saturating shift left by register. 2483 void uqshl(const VRegister& vd, 2484 const VRegister& vn, 2485 const VRegister& vm); 2486 2487 // Signed rounding shift left by register. 2488 void srshl(const VRegister& vd, 2489 const VRegister& vn, 2490 const VRegister& vm); 2491 2492 // Unsigned rounding shift left by register. 2493 void urshl(const VRegister& vd, 2494 const VRegister& vn, 2495 const VRegister& vm); 2496 2497 // Signed saturating rounding shift left by register. 2498 void sqrshl(const VRegister& vd, 2499 const VRegister& vn, 2500 const VRegister& vm); 2501 2502 // Unsigned saturating rounding shift left by register. 2503 void uqrshl(const VRegister& vd, 2504 const VRegister& vn, 2505 const VRegister& vm); 2506 2507 // Bitwise and. 2508 void and_(const VRegister& vd, 2509 const VRegister& vn, 2510 const VRegister& vm); 2511 2512 // Bitwise or. 2513 void orr(const VRegister& vd, 2514 const VRegister& vn, 2515 const VRegister& vm); 2516 2517 // Bitwise or immediate. 2518 void orr(const VRegister& vd, 2519 const int imm8, 2520 const int left_shift = 0); 2521 2522 // Move register to register. 2523 void mov(const VRegister& vd, 2524 const VRegister& vn); 2525 2526 // Bitwise orn. 2527 void orn(const VRegister& vd, 2528 const VRegister& vn, 2529 const VRegister& vm); 2530 2531 // Bitwise eor. 2532 void eor(const VRegister& vd, 2533 const VRegister& vn, 2534 const VRegister& vm); 2535 2536 // Bit clear immediate. 2537 void bic(const VRegister& vd, 2538 const int imm8, 2539 const int left_shift = 0); 2540 2541 // Bit clear. 2542 void bic(const VRegister& vd, 2543 const VRegister& vn, 2544 const VRegister& vm); 2545 2546 // Bitwise insert if false. 2547 void bif(const VRegister& vd, 2548 const VRegister& vn, 2549 const VRegister& vm); 2550 2551 // Bitwise insert if true. 2552 void bit(const VRegister& vd, 2553 const VRegister& vn, 2554 const VRegister& vm); 2555 2556 // Bitwise select. 2557 void bsl(const VRegister& vd, 2558 const VRegister& vn, 2559 const VRegister& vm); 2560 2561 // Polynomial multiply. 2562 void pmul(const VRegister& vd, 2563 const VRegister& vn, 2564 const VRegister& vm); 2565 2566 // Vector move immediate. 2567 void movi(const VRegister& vd, 2568 const uint64_t imm, 2569 Shift shift = LSL, 2570 const int shift_amount = 0); 2571 2572 // Bitwise not. 2573 void mvn(const VRegister& vd, 2574 const VRegister& vn); 2575 2576 // Vector move inverted immediate. 2577 void mvni(const VRegister& vd, 2578 const int imm8, 2579 Shift shift = LSL, 2580 const int shift_amount = 0); 2581 2582 // Signed saturating accumulate of unsigned value. 2583 void suqadd(const VRegister& vd, 2584 const VRegister& vn); 2585 2586 // Unsigned saturating accumulate of signed value. 2587 void usqadd(const VRegister& vd, 2588 const VRegister& vn); 2589 2590 // Absolute value. 2591 void abs(const VRegister& vd, 2592 const VRegister& vn); 2593 2594 // Signed saturating absolute value. 2595 void sqabs(const VRegister& vd, 2596 const VRegister& vn); 2597 2598 // Negate. 2599 void neg(const VRegister& vd, 2600 const VRegister& vn); 2601 2602 // Signed saturating negate. 2603 void sqneg(const VRegister& vd, 2604 const VRegister& vn); 2605 2606 // Bitwise not. 2607 void not_(const VRegister& vd, 2608 const VRegister& vn); 2609 2610 // Extract narrow. 2611 void xtn(const VRegister& vd, 2612 const VRegister& vn); 2613 2614 // Extract narrow (second part). 2615 void xtn2(const VRegister& vd, 2616 const VRegister& vn); 2617 2618 // Signed saturating extract narrow. 2619 void sqxtn(const VRegister& vd, 2620 const VRegister& vn); 2621 2622 // Signed saturating extract narrow (second part). 2623 void sqxtn2(const VRegister& vd, 2624 const VRegister& vn); 2625 2626 // Unsigned saturating extract narrow. 2627 void uqxtn(const VRegister& vd, 2628 const VRegister& vn); 2629 2630 // Unsigned saturating extract narrow (second part). 2631 void uqxtn2(const VRegister& vd, 2632 const VRegister& vn); 2633 2634 // Signed saturating extract unsigned narrow. 2635 void sqxtun(const VRegister& vd, 2636 const VRegister& vn); 2637 2638 // Signed saturating extract unsigned narrow (second part). 2639 void sqxtun2(const VRegister& vd, 2640 const VRegister& vn); 2641 2642 // Extract vector from pair of vectors. 2643 void ext(const VRegister& vd, 2644 const VRegister& vn, 2645 const VRegister& vm, 2646 int index); 2647 2648 // Duplicate vector element to vector or scalar. 2649 void dup(const VRegister& vd, 2650 const VRegister& vn, 2651 int vn_index); 2652 2653 // Move vector element to scalar. 2654 void mov(const VRegister& vd, 2655 const VRegister& vn, 2656 int vn_index); 2657 2658 // Duplicate general-purpose register to vector. 2659 void dup(const VRegister& vd, 2660 const Register& rn); 2661 2662 // Insert vector element from another vector element. 2663 void ins(const VRegister& vd, 2664 int vd_index, 2665 const VRegister& vn, 2666 int vn_index); 2667 2668 // Move vector element to another vector element. 2669 void mov(const VRegister& vd, 2670 int vd_index, 2671 const VRegister& vn, 2672 int vn_index); 2673 2674 // Insert vector element from general-purpose register. 2675 void ins(const VRegister& vd, 2676 int vd_index, 2677 const Register& rn); 2678 2679 // Move general-purpose register to a vector element. 2680 void mov(const VRegister& vd, 2681 int vd_index, 2682 const Register& rn); 2683 2684 // Unsigned move vector element to general-purpose register. 2685 void umov(const Register& rd, 2686 const VRegister& vn, 2687 int vn_index); 2688 2689 // Move vector element to general-purpose register. 2690 void mov(const Register& rd, 2691 const VRegister& vn, 2692 int vn_index); 2693 2694 // Signed move vector element to general-purpose register. 2695 void smov(const Register& rd, 2696 const VRegister& vn, 2697 int vn_index); 2698 2699 // One-element structure load to one register. 2700 void ld1(const VRegister& vt, 2701 const MemOperand& src); 2702 2703 // One-element structure load to two registers. 2704 void ld1(const VRegister& vt, 2705 const VRegister& vt2, 2706 const MemOperand& src); 2707 2708 // One-element structure load to three registers. 2709 void ld1(const VRegister& vt, 2710 const VRegister& vt2, 2711 const VRegister& vt3, 2712 const MemOperand& src); 2713 2714 // One-element structure load to four registers. 2715 void ld1(const VRegister& vt, 2716 const VRegister& vt2, 2717 const VRegister& vt3, 2718 const VRegister& vt4, 2719 const MemOperand& src); 2720 2721 // One-element single structure load to one lane. 2722 void ld1(const VRegister& vt, 2723 int lane, 2724 const MemOperand& src); 2725 2726 // One-element single structure load to all lanes. 2727 void ld1r(const VRegister& vt, 2728 const MemOperand& src); 2729 2730 // Two-element structure load. 2731 void ld2(const VRegister& vt, 2732 const VRegister& vt2, 2733 const MemOperand& src); 2734 2735 // Two-element single structure load to one lane. 2736 void ld2(const VRegister& vt, 2737 const VRegister& vt2, 2738 int lane, 2739 const MemOperand& src); 2740 2741 // Two-element single structure load to all lanes. 2742 void ld2r(const VRegister& vt, 2743 const VRegister& vt2, 2744 const MemOperand& src); 2745 2746 // Three-element structure load. 2747 void ld3(const VRegister& vt, 2748 const VRegister& vt2, 2749 const VRegister& vt3, 2750 const MemOperand& src); 2751 2752 // Three-element single structure load to one lane. 2753 void ld3(const VRegister& vt, 2754 const VRegister& vt2, 2755 const VRegister& vt3, 2756 int lane, 2757 const MemOperand& src); 2758 2759 // Three-element single structure load to all lanes. 2760 void ld3r(const VRegister& vt, 2761 const VRegister& vt2, 2762 const VRegister& vt3, 2763 const MemOperand& src); 2764 2765 // Four-element structure load. 2766 void ld4(const VRegister& vt, 2767 const VRegister& vt2, 2768 const VRegister& vt3, 2769 const VRegister& vt4, 2770 const MemOperand& src); 2771 2772 // Four-element single structure load to one lane. 2773 void ld4(const VRegister& vt, 2774 const VRegister& vt2, 2775 const VRegister& vt3, 2776 const VRegister& vt4, 2777 int lane, 2778 const MemOperand& src); 2779 2780 // Four-element single structure load to all lanes. 2781 void ld4r(const VRegister& vt, 2782 const VRegister& vt2, 2783 const VRegister& vt3, 2784 const VRegister& vt4, 2785 const MemOperand& src); 2786 2787 // Count leading sign bits. 2788 void cls(const VRegister& vd, 2789 const VRegister& vn); 2790 2791 // Count leading zero bits (vector). 2792 void clz(const VRegister& vd, 2793 const VRegister& vn); 2794 2795 // Population count per byte. 2796 void cnt(const VRegister& vd, 2797 const VRegister& vn); 2798 2799 // Reverse bit order. 2800 void rbit(const VRegister& vd, 2801 const VRegister& vn); 2802 2803 // Reverse elements in 16-bit halfwords. 2804 void rev16(const VRegister& vd, 2805 const VRegister& vn); 2806 2807 // Reverse elements in 32-bit words. 2808 void rev32(const VRegister& vd, 2809 const VRegister& vn); 2810 2811 // Reverse elements in 64-bit doublewords. 2812 void rev64(const VRegister& vd, 2813 const VRegister& vn); 2814 2815 // Unsigned reciprocal square root estimate. 2816 void ursqrte(const VRegister& vd, 2817 const VRegister& vn); 2818 2819 // Unsigned reciprocal estimate. 2820 void urecpe(const VRegister& vd, 2821 const VRegister& vn); 2822 2823 // Signed pairwise long add. 2824 void saddlp(const VRegister& vd, 2825 const VRegister& vn); 2826 2827 // Unsigned pairwise long add. 2828 void uaddlp(const VRegister& vd, 2829 const VRegister& vn); 2830 2831 // Signed pairwise long add and accumulate. 2832 void sadalp(const VRegister& vd, 2833 const VRegister& vn); 2834 2835 // Unsigned pairwise long add and accumulate. 2836 void uadalp(const VRegister& vd, 2837 const VRegister& vn); 2838 2839 // Shift left by immediate. 2840 void shl(const VRegister& vd, 2841 const VRegister& vn, 2842 int shift); 2843 2844 // Signed saturating shift left by immediate. 2845 void sqshl(const VRegister& vd, 2846 const VRegister& vn, 2847 int shift); 2848 2849 // Signed saturating shift left unsigned by immediate. 2850 void sqshlu(const VRegister& vd, 2851 const VRegister& vn, 2852 int shift); 2853 2854 // Unsigned saturating shift left by immediate. 2855 void uqshl(const VRegister& vd, 2856 const VRegister& vn, 2857 int shift); 2858 2859 // Signed shift left long by immediate. 2860 void sshll(const VRegister& vd, 2861 const VRegister& vn, 2862 int shift); 2863 2864 // Signed shift left long by immediate (second part). 2865 void sshll2(const VRegister& vd, 2866 const VRegister& vn, 2867 int shift); 2868 2869 // Signed extend long. 2870 void sxtl(const VRegister& vd, 2871 const VRegister& vn); 2872 2873 // Signed extend long (second part). 2874 void sxtl2(const VRegister& vd, 2875 const VRegister& vn); 2876 2877 // Unsigned shift left long by immediate. 2878 void ushll(const VRegister& vd, 2879 const VRegister& vn, 2880 int shift); 2881 2882 // Unsigned shift left long by immediate (second part). 2883 void ushll2(const VRegister& vd, 2884 const VRegister& vn, 2885 int shift); 2886 2887 // Shift left long by element size. 2888 void shll(const VRegister& vd, 2889 const VRegister& vn, 2890 int shift); 2891 2892 // Shift left long by element size (second part). 2893 void shll2(const VRegister& vd, 2894 const VRegister& vn, 2895 int shift); 2896 2897 // Unsigned extend long. 2898 void uxtl(const VRegister& vd, 2899 const VRegister& vn); 2900 2901 // Unsigned extend long (second part). 2902 void uxtl2(const VRegister& vd, 2903 const VRegister& vn); 2904 2905 // Shift left by immediate and insert. 2906 void sli(const VRegister& vd, 2907 const VRegister& vn, 2908 int shift); 2909 2910 // Shift right by immediate and insert. 2911 void sri(const VRegister& vd, 2912 const VRegister& vn, 2913 int shift); 2914 2915 // Signed maximum. 2916 void smax(const VRegister& vd, 2917 const VRegister& vn, 2918 const VRegister& vm); 2919 2920 // Signed pairwise maximum. 2921 void smaxp(const VRegister& vd, 2922 const VRegister& vn, 2923 const VRegister& vm); 2924 2925 // Add across vector. 2926 void addv(const VRegister& vd, 2927 const VRegister& vn); 2928 2929 // Signed add long across vector. 2930 void saddlv(const VRegister& vd, 2931 const VRegister& vn); 2932 2933 // Unsigned add long across vector. 2934 void uaddlv(const VRegister& vd, 2935 const VRegister& vn); 2936 2937 // FP maximum number across vector. 2938 void fmaxnmv(const VRegister& vd, 2939 const VRegister& vn); 2940 2941 // FP maximum across vector. 2942 void fmaxv(const VRegister& vd, 2943 const VRegister& vn); 2944 2945 // FP minimum number across vector. 2946 void fminnmv(const VRegister& vd, 2947 const VRegister& vn); 2948 2949 // FP minimum across vector. 2950 void fminv(const VRegister& vd, 2951 const VRegister& vn); 2952 2953 // Signed maximum across vector. 2954 void smaxv(const VRegister& vd, 2955 const VRegister& vn); 2956 2957 // Signed minimum. 2958 void smin(const VRegister& vd, 2959 const VRegister& vn, 2960 const VRegister& vm); 2961 2962 // Signed minimum pairwise. 2963 void sminp(const VRegister& vd, 2964 const VRegister& vn, 2965 const VRegister& vm); 2966 2967 // Signed minimum across vector. 2968 void sminv(const VRegister& vd, 2969 const VRegister& vn); 2970 2971 // One-element structure store from one register. 2972 void st1(const VRegister& vt, 2973 const MemOperand& src); 2974 2975 // One-element structure store from two registers. 2976 void st1(const VRegister& vt, 2977 const VRegister& vt2, 2978 const MemOperand& src); 2979 2980 // One-element structure store from three registers. 2981 void st1(const VRegister& vt, 2982 const VRegister& vt2, 2983 const VRegister& vt3, 2984 const MemOperand& src); 2985 2986 // One-element structure store from four registers. 2987 void st1(const VRegister& vt, 2988 const VRegister& vt2, 2989 const VRegister& vt3, 2990 const VRegister& vt4, 2991 const MemOperand& src); 2992 2993 // One-element single structure store from one lane. 2994 void st1(const VRegister& vt, 2995 int lane, 2996 const MemOperand& src); 2997 2998 // Two-element structure store from two registers. 2999 void st2(const VRegister& vt, 3000 const VRegister& vt2, 3001 const MemOperand& src); 3002 3003 // Two-element single structure store from two lanes. 3004 void st2(const VRegister& vt, 3005 const VRegister& vt2, 3006 int lane, 3007 const MemOperand& src); 3008 3009 // Three-element structure store from three registers. 3010 void st3(const VRegister& vt, 3011 const VRegister& vt2, 3012 const VRegister& vt3, 3013 const MemOperand& src); 3014 3015 // Three-element single structure store from three lanes. 3016 void st3(const VRegister& vt, 3017 const VRegister& vt2, 3018 const VRegister& vt3, 3019 int lane, 3020 const MemOperand& src); 3021 3022 // Four-element structure store from four registers. 3023 void st4(const VRegister& vt, 3024 const VRegister& vt2, 3025 const VRegister& vt3, 3026 const VRegister& vt4, 3027 const MemOperand& src); 3028 3029 // Four-element single structure store from four lanes. 3030 void st4(const VRegister& vt, 3031 const VRegister& vt2, 3032 const VRegister& vt3, 3033 const VRegister& vt4, 3034 int lane, 3035 const MemOperand& src); 3036 3037 // Unsigned add long. 3038 void uaddl(const VRegister& vd, 3039 const VRegister& vn, 3040 const VRegister& vm); 3041 3042 // Unsigned add long (second part). 3043 void uaddl2(const VRegister& vd, 3044 const VRegister& vn, 3045 const VRegister& vm); 3046 3047 // Unsigned add wide. 3048 void uaddw(const VRegister& vd, 3049 const VRegister& vn, 3050 const VRegister& vm); 3051 3052 // Unsigned add wide (second part). 3053 void uaddw2(const VRegister& vd, 3054 const VRegister& vn, 3055 const VRegister& vm); 3056 3057 // Signed add long. 3058 void saddl(const VRegister& vd, 3059 const VRegister& vn, 3060 const VRegister& vm); 3061 3062 // Signed add long (second part). 3063 void saddl2(const VRegister& vd, 3064 const VRegister& vn, 3065 const VRegister& vm); 3066 3067 // Signed add wide. 3068 void saddw(const VRegister& vd, 3069 const VRegister& vn, 3070 const VRegister& vm); 3071 3072 // Signed add wide (second part). 3073 void saddw2(const VRegister& vd, 3074 const VRegister& vn, 3075 const VRegister& vm); 3076 3077 // Unsigned subtract long. 3078 void usubl(const VRegister& vd, 3079 const VRegister& vn, 3080 const VRegister& vm); 3081 3082 // Unsigned subtract long (second part). 3083 void usubl2(const VRegister& vd, 3084 const VRegister& vn, 3085 const VRegister& vm); 3086 3087 // Unsigned subtract wide. 3088 void usubw(const VRegister& vd, 3089 const VRegister& vn, 3090 const VRegister& vm); 3091 3092 // Unsigned subtract wide (second part). 3093 void usubw2(const VRegister& vd, 3094 const VRegister& vn, 3095 const VRegister& vm); 3096 3097 // Signed subtract long. 3098 void ssubl(const VRegister& vd, 3099 const VRegister& vn, 3100 const VRegister& vm); 3101 3102 // Signed subtract long (second part). 3103 void ssubl2(const VRegister& vd, 3104 const VRegister& vn, 3105 const VRegister& vm); 3106 3107 // Signed integer subtract wide. 3108 void ssubw(const VRegister& vd, 3109 const VRegister& vn, 3110 const VRegister& vm); 3111 3112 // Signed integer subtract wide (second part). 3113 void ssubw2(const VRegister& vd, 3114 const VRegister& vn, 3115 const VRegister& vm); 3116 3117 // Unsigned maximum. 3118 void umax(const VRegister& vd, 3119 const VRegister& vn, 3120 const VRegister& vm); 3121 3122 // Unsigned pairwise maximum. 3123 void umaxp(const VRegister& vd, 3124 const VRegister& vn, 3125 const VRegister& vm); 3126 3127 // Unsigned maximum across vector. 3128 void umaxv(const VRegister& vd, 3129 const VRegister& vn); 3130 3131 // Unsigned minimum. 3132 void umin(const VRegister& vd, 3133 const VRegister& vn, 3134 const VRegister& vm); 3135 3136 // Unsigned pairwise minimum. 3137 void uminp(const VRegister& vd, 3138 const VRegister& vn, 3139 const VRegister& vm); 3140 3141 // Unsigned minimum across vector. 3142 void uminv(const VRegister& vd, 3143 const VRegister& vn); 3144 3145 // Transpose vectors (primary). 3146 void trn1(const VRegister& vd, 3147 const VRegister& vn, 3148 const VRegister& vm); 3149 3150 // Transpose vectors (secondary). 3151 void trn2(const VRegister& vd, 3152 const VRegister& vn, 3153 const VRegister& vm); 3154 3155 // Unzip vectors (primary). 3156 void uzp1(const VRegister& vd, 3157 const VRegister& vn, 3158 const VRegister& vm); 3159 3160 // Unzip vectors (secondary). 3161 void uzp2(const VRegister& vd, 3162 const VRegister& vn, 3163 const VRegister& vm); 3164 3165 // Zip vectors (primary). 3166 void zip1(const VRegister& vd, 3167 const VRegister& vn, 3168 const VRegister& vm); 3169 3170 // Zip vectors (secondary). 3171 void zip2(const VRegister& vd, 3172 const VRegister& vn, 3173 const VRegister& vm); 3174 3175 // Signed shift right by immediate. 3176 void sshr(const VRegister& vd, 3177 const VRegister& vn, 3178 int shift); 3179 3180 // Unsigned shift right by immediate. 3181 void ushr(const VRegister& vd, 3182 const VRegister& vn, 3183 int shift); 3184 3185 // Signed rounding shift right by immediate. 3186 void srshr(const VRegister& vd, 3187 const VRegister& vn, 3188 int shift); 3189 3190 // Unsigned rounding shift right by immediate. 3191 void urshr(const VRegister& vd, 3192 const VRegister& vn, 3193 int shift); 3194 3195 // Signed shift right by immediate and accumulate. 3196 void ssra(const VRegister& vd, 3197 const VRegister& vn, 3198 int shift); 3199 3200 // Unsigned shift right by immediate and accumulate. 3201 void usra(const VRegister& vd, 3202 const VRegister& vn, 3203 int shift); 3204 3205 // Signed rounding shift right by immediate and accumulate. 3206 void srsra(const VRegister& vd, 3207 const VRegister& vn, 3208 int shift); 3209 3210 // Unsigned rounding shift right by immediate and accumulate. 3211 void ursra(const VRegister& vd, 3212 const VRegister& vn, 3213 int shift); 3214 3215 // Shift right narrow by immediate. 3216 void shrn(const VRegister& vd, 3217 const VRegister& vn, 3218 int shift); 3219 3220 // Shift right narrow by immediate (second part). 3221 void shrn2(const VRegister& vd, 3222 const VRegister& vn, 3223 int shift); 3224 3225 // Rounding shift right narrow by immediate. 3226 void rshrn(const VRegister& vd, 3227 const VRegister& vn, 3228 int shift); 3229 3230 // Rounding shift right narrow by immediate (second part). 3231 void rshrn2(const VRegister& vd, 3232 const VRegister& vn, 3233 int shift); 3234 3235 // Unsigned saturating shift right narrow by immediate. 3236 void uqshrn(const VRegister& vd, 3237 const VRegister& vn, 3238 int shift); 3239 3240 // Unsigned saturating shift right narrow by immediate (second part). 3241 void uqshrn2(const VRegister& vd, 3242 const VRegister& vn, 3243 int shift); 3244 3245 // Unsigned saturating rounding shift right narrow by immediate. 3246 void uqrshrn(const VRegister& vd, 3247 const VRegister& vn, 3248 int shift); 3249 3250 // Unsigned saturating rounding shift right narrow by immediate (second part). 3251 void uqrshrn2(const VRegister& vd, 3252 const VRegister& vn, 3253 int shift); 3254 3255 // Signed saturating shift right narrow by immediate. 3256 void sqshrn(const VRegister& vd, 3257 const VRegister& vn, 3258 int shift); 3259 3260 // Signed saturating shift right narrow by immediate (second part). 3261 void sqshrn2(const VRegister& vd, 3262 const VRegister& vn, 3263 int shift); 3264 3265 // Signed saturating rounded shift right narrow by immediate. 3266 void sqrshrn(const VRegister& vd, 3267 const VRegister& vn, 3268 int shift); 3269 3270 // Signed saturating rounded shift right narrow by immediate (second part). 3271 void sqrshrn2(const VRegister& vd, 3272 const VRegister& vn, 3273 int shift); 3274 3275 // Signed saturating shift right unsigned narrow by immediate. 3276 void sqshrun(const VRegister& vd, 3277 const VRegister& vn, 3278 int shift); 3279 3280 // Signed saturating shift right unsigned narrow by immediate (second part). 3281 void sqshrun2(const VRegister& vd, 3282 const VRegister& vn, 3283 int shift); 3284 3285 // Signed sat rounded shift right unsigned narrow by immediate. 3286 void sqrshrun(const VRegister& vd, 3287 const VRegister& vn, 3288 int shift); 3289 3290 // Signed sat rounded shift right unsigned narrow by immediate (second part). 3291 void sqrshrun2(const VRegister& vd, 3292 const VRegister& vn, 3293 int shift); 3294 3295 // FP reciprocal step. 3296 void frecps(const VRegister& vd, 3297 const VRegister& vn, 3298 const VRegister& vm); 3299 3300 // FP reciprocal estimate. 3301 void frecpe(const VRegister& vd, 3302 const VRegister& vn); 3303 3304 // FP reciprocal square root estimate. 3305 void frsqrte(const VRegister& vd, 3306 const VRegister& vn); 3307 3308 // FP reciprocal square root step. 3309 void frsqrts(const VRegister& vd, 3310 const VRegister& vn, 3311 const VRegister& vm); 3312 3313 // Signed absolute difference and accumulate long. 3314 void sabal(const VRegister& vd, 3315 const VRegister& vn, 3316 const VRegister& vm); 3317 3318 // Signed absolute difference and accumulate long (second part). 3319 void sabal2(const VRegister& vd, 3320 const VRegister& vn, 3321 const VRegister& vm); 3322 3323 // Unsigned absolute difference and accumulate long. 3324 void uabal(const VRegister& vd, 3325 const VRegister& vn, 3326 const VRegister& vm); 3327 3328 // Unsigned absolute difference and accumulate long (second part). 3329 void uabal2(const VRegister& vd, 3330 const VRegister& vn, 3331 const VRegister& vm); 3332 3333 // Signed absolute difference long. 3334 void sabdl(const VRegister& vd, 3335 const VRegister& vn, 3336 const VRegister& vm); 3337 3338 // Signed absolute difference long (second part). 3339 void sabdl2(const VRegister& vd, 3340 const VRegister& vn, 3341 const VRegister& vm); 3342 3343 // Unsigned absolute difference long. 3344 void uabdl(const VRegister& vd, 3345 const VRegister& vn, 3346 const VRegister& vm); 3347 3348 // Unsigned absolute difference long (second part). 3349 void uabdl2(const VRegister& vd, 3350 const VRegister& vn, 3351 const VRegister& vm); 3352 3353 // Polynomial multiply long. 3354 void pmull(const VRegister& vd, 3355 const VRegister& vn, 3356 const VRegister& vm); 3357 3358 // Polynomial multiply long (second part). 3359 void pmull2(const VRegister& vd, 3360 const VRegister& vn, 3361 const VRegister& vm); 3362 3363 // Signed long multiply-add. 3364 void smlal(const VRegister& vd, 3365 const VRegister& vn, 3366 const VRegister& vm); 3367 3368 // Signed long multiply-add (second part). 3369 void smlal2(const VRegister& vd, 3370 const VRegister& vn, 3371 const VRegister& vm); 3372 3373 // Unsigned long multiply-add. 3374 void umlal(const VRegister& vd, 3375 const VRegister& vn, 3376 const VRegister& vm); 3377 3378 // Unsigned long multiply-add (second part). 3379 void umlal2(const VRegister& vd, 3380 const VRegister& vn, 3381 const VRegister& vm); 3382 3383 // Signed long multiply-sub. 3384 void smlsl(const VRegister& vd, 3385 const VRegister& vn, 3386 const VRegister& vm); 3387 3388 // Signed long multiply-sub (second part). 3389 void smlsl2(const VRegister& vd, 3390 const VRegister& vn, 3391 const VRegister& vm); 3392 3393 // Unsigned long multiply-sub. 3394 void umlsl(const VRegister& vd, 3395 const VRegister& vn, 3396 const VRegister& vm); 3397 3398 // Unsigned long multiply-sub (second part). 3399 void umlsl2(const VRegister& vd, 3400 const VRegister& vn, 3401 const VRegister& vm); 3402 3403 // Signed long multiply. 3404 void smull(const VRegister& vd, 3405 const VRegister& vn, 3406 const VRegister& vm); 3407 3408 // Signed long multiply (second part). 3409 void smull2(const VRegister& vd, 3410 const VRegister& vn, 3411 const VRegister& vm); 3412 3413 // Signed saturating doubling long multiply-add. 3414 void sqdmlal(const VRegister& vd, 3415 const VRegister& vn, 3416 const VRegister& vm); 3417 3418 // Signed saturating doubling long multiply-add (second part). 3419 void sqdmlal2(const VRegister& vd, 3420 const VRegister& vn, 3421 const VRegister& vm); 3422 3423 // Signed saturating doubling long multiply-subtract. 3424 void sqdmlsl(const VRegister& vd, 3425 const VRegister& vn, 3426 const VRegister& vm); 3427 3428 // Signed saturating doubling long multiply-subtract (second part). 3429 void sqdmlsl2(const VRegister& vd, 3430 const VRegister& vn, 3431 const VRegister& vm); 3432 3433 // Signed saturating doubling long multiply. 3434 void sqdmull(const VRegister& vd, 3435 const VRegister& vn, 3436 const VRegister& vm); 3437 3438 // Signed saturating doubling long multiply (second part). 3439 void sqdmull2(const VRegister& vd, 3440 const VRegister& vn, 3441 const VRegister& vm); 3442 3443 // Signed saturating doubling multiply returning high half. 3444 void sqdmulh(const VRegister& vd, 3445 const VRegister& vn, 3446 const VRegister& vm); 3447 3448 // Signed saturating rounding doubling multiply returning high half. 3449 void sqrdmulh(const VRegister& vd, 3450 const VRegister& vn, 3451 const VRegister& vm); 3452 3453 // Signed saturating doubling multiply element returning high half. 3454 void sqdmulh(const VRegister& vd, 3455 const VRegister& vn, 3456 const VRegister& vm, 3457 int vm_index); 3458 3459 // Signed saturating rounding doubling multiply element returning high half. 3460 void sqrdmulh(const VRegister& vd, 3461 const VRegister& vn, 3462 const VRegister& vm, 3463 int vm_index); 3464 3465 // Unsigned long multiply long. 3466 void umull(const VRegister& vd, 3467 const VRegister& vn, 3468 const VRegister& vm); 3469 3470 // Unsigned long multiply (second part). 3471 void umull2(const VRegister& vd, 3472 const VRegister& vn, 3473 const VRegister& vm); 3474 3475 // Add narrow returning high half. 3476 void addhn(const VRegister& vd, 3477 const VRegister& vn, 3478 const VRegister& vm); 3479 3480 // Add narrow returning high half (second part). 3481 void addhn2(const VRegister& vd, 3482 const VRegister& vn, 3483 const VRegister& vm); 3484 3485 // Rounding add narrow returning high half. 3486 void raddhn(const VRegister& vd, 3487 const VRegister& vn, 3488 const VRegister& vm); 3489 3490 // Rounding add narrow returning high half (second part). 3491 void raddhn2(const VRegister& vd, 3492 const VRegister& vn, 3493 const VRegister& vm); 3494 3495 // Subtract narrow returning high half. 3496 void subhn(const VRegister& vd, 3497 const VRegister& vn, 3498 const VRegister& vm); 3499 3500 // Subtract narrow returning high half (second part). 3501 void subhn2(const VRegister& vd, 3502 const VRegister& vn, 3503 const VRegister& vm); 3504 3505 // Rounding subtract narrow returning high half. 3506 void rsubhn(const VRegister& vd, 3507 const VRegister& vn, 3508 const VRegister& vm); 3509 3510 // Rounding subtract narrow returning high half (second part). 3511 void rsubhn2(const VRegister& vd, 3512 const VRegister& vn, 3513 const VRegister& vm); 3514 3515 // FP vector multiply accumulate. 3516 void fmla(const VRegister& vd, 3517 const VRegister& vn, 3518 const VRegister& vm); 3519 3520 // FP vector multiply subtract. 3521 void fmls(const VRegister& vd, 3522 const VRegister& vn, 3523 const VRegister& vm); 3524 3525 // FP vector multiply extended. 3526 void fmulx(const VRegister& vd, 3527 const VRegister& vn, 3528 const VRegister& vm); 3529 3530 // FP absolute greater than or equal. 3531 void facge(const VRegister& vd, 3532 const VRegister& vn, 3533 const VRegister& vm); 3534 3535 // FP absolute greater than. 3536 void facgt(const VRegister& vd, 3537 const VRegister& vn, 3538 const VRegister& vm); 3539 3540 // FP multiply by element. 3541 void fmul(const VRegister& vd, 3542 const VRegister& vn, 3543 const VRegister& vm, 3544 int vm_index); 3545 3546 // FP fused multiply-add to accumulator by element. 3547 void fmla(const VRegister& vd, 3548 const VRegister& vn, 3549 const VRegister& vm, 3550 int vm_index); 3551 3552 // FP fused multiply-sub from accumulator by element. 3553 void fmls(const VRegister& vd, 3554 const VRegister& vn, 3555 const VRegister& vm, 3556 int vm_index); 3557 3558 // FP multiply extended by element. 3559 void fmulx(const VRegister& vd, 3560 const VRegister& vn, 3561 const VRegister& vm, 3562 int vm_index); 3563 3564 // FP compare equal. 3565 void fcmeq(const VRegister& vd, 3566 const VRegister& vn, 3567 const VRegister& vm); 3568 3569 // FP greater than. 3570 void fcmgt(const VRegister& vd, 3571 const VRegister& vn, 3572 const VRegister& vm); 3573 3574 // FP greater than or equal. 3575 void fcmge(const VRegister& vd, 3576 const VRegister& vn, 3577 const VRegister& vm); 3578 3579 // FP compare equal to zero. 3580 void fcmeq(const VRegister& vd, 3581 const VRegister& vn, 3582 double imm); 3583 3584 // FP greater than zero. 3585 void fcmgt(const VRegister& vd, 3586 const VRegister& vn, 3587 double imm); 3588 3589 // FP greater than or equal to zero. 3590 void fcmge(const VRegister& vd, 3591 const VRegister& vn, 3592 double imm); 3593 3594 // FP less than or equal to zero. 3595 void fcmle(const VRegister& vd, 3596 const VRegister& vn, 3597 double imm); 3598 3599 // FP less than to zero. 3600 void fcmlt(const VRegister& vd, 3601 const VRegister& vn, 3602 double imm); 3603 3604 // FP absolute difference. 3605 void fabd(const VRegister& vd, 3606 const VRegister& vn, 3607 const VRegister& vm); 3608 3609 // FP pairwise add vector. 3610 void faddp(const VRegister& vd, 3611 const VRegister& vn, 3612 const VRegister& vm); 3613 3614 // FP pairwise add scalar. 3615 void faddp(const VRegister& vd, 3616 const VRegister& vn); 3617 3618 // FP pairwise maximum vector. 3619 void fmaxp(const VRegister& vd, 3620 const VRegister& vn, 3621 const VRegister& vm); 3622 3623 // FP pairwise maximum scalar. 3624 void fmaxp(const VRegister& vd, 3625 const VRegister& vn); 3626 3627 // FP pairwise minimum vector. 3628 void fminp(const VRegister& vd, 3629 const VRegister& vn, 3630 const VRegister& vm); 3631 3632 // FP pairwise minimum scalar. 3633 void fminp(const VRegister& vd, 3634 const VRegister& vn); 3635 3636 // FP pairwise maximum number vector. 3637 void fmaxnmp(const VRegister& vd, 3638 const VRegister& vn, 3639 const VRegister& vm); 3640 3641 // FP pairwise maximum number scalar. 3642 void fmaxnmp(const VRegister& vd, 3643 const VRegister& vn); 3644 3645 // FP pairwise minimum number vector. 3646 void fminnmp(const VRegister& vd, 3647 const VRegister& vn, 3648 const VRegister& vm); 3649 3650 // FP pairwise minimum number scalar. 3651 void fminnmp(const VRegister& vd, 3652 const VRegister& vn); 3653 3654 // Emit generic instructions. 3655 // Emit raw instructions into the instruction stream. 3656 void dci(Instr raw_inst) { Emit(raw_inst); } 3657 3658 // Emit 32 bits of data into the instruction stream. 3659 void dc32(uint32_t data) { 3660 VIXL_ASSERT(buffer_monitor_ > 0); 3661 buffer_->Emit32(data); 3662 } 3663 3664 // Emit 64 bits of data into the instruction stream. 3665 void dc64(uint64_t data) { 3666 VIXL_ASSERT(buffer_monitor_ > 0); 3667 buffer_->Emit64(data); 3668 } 3669 3670 // Copy a string into the instruction stream, including the terminating NULL 3671 // character. The instruction pointer is then aligned correctly for 3672 // subsequent instructions. 3673 void EmitString(const char * string) { 3674 VIXL_ASSERT(string != NULL); 3675 VIXL_ASSERT(buffer_monitor_ > 0); 3676 3677 buffer_->EmitString(string); 3678 buffer_->Align(); 3679 } 3680 3681 // Code generation helpers. 3682 3683 // Register encoding. 3684 static Instr Rd(CPURegister rd) { 3685 VIXL_ASSERT(rd.code() != kSPRegInternalCode); 3686 return rd.code() << Rd_offset; 3687 } 3688 3689 static Instr Rn(CPURegister rn) { 3690 VIXL_ASSERT(rn.code() != kSPRegInternalCode); 3691 return rn.code() << Rn_offset; 3692 } 3693 3694 static Instr Rm(CPURegister rm) { 3695 VIXL_ASSERT(rm.code() != kSPRegInternalCode); 3696 return rm.code() << Rm_offset; 3697 } 3698 3699 static Instr RmNot31(CPURegister rm) { 3700 VIXL_ASSERT(rm.code() != kSPRegInternalCode); 3701 VIXL_ASSERT(!rm.IsZero()); 3702 return Rm(rm); 3703 } 3704 3705 static Instr Ra(CPURegister ra) { 3706 VIXL_ASSERT(ra.code() != kSPRegInternalCode); 3707 return ra.code() << Ra_offset; 3708 } 3709 3710 static Instr Rt(CPURegister rt) { 3711 VIXL_ASSERT(rt.code() != kSPRegInternalCode); 3712 return rt.code() << Rt_offset; 3713 } 3714 3715 static Instr Rt2(CPURegister rt2) { 3716 VIXL_ASSERT(rt2.code() != kSPRegInternalCode); 3717 return rt2.code() << Rt2_offset; 3718 } 3719 3720 static Instr Rs(CPURegister rs) { 3721 VIXL_ASSERT(rs.code() != kSPRegInternalCode); 3722 return rs.code() << Rs_offset; 3723 } 3724 3725 // These encoding functions allow the stack pointer to be encoded, and 3726 // disallow the zero register. 3727 static Instr RdSP(Register rd) { 3728 VIXL_ASSERT(!rd.IsZero()); 3729 return (rd.code() & kRegCodeMask) << Rd_offset; 3730 } 3731 3732 static Instr RnSP(Register rn) { 3733 VIXL_ASSERT(!rn.IsZero()); 3734 return (rn.code() & kRegCodeMask) << Rn_offset; 3735 } 3736 3737 // Flags encoding. 3738 static Instr Flags(FlagsUpdate S) { 3739 if (S == SetFlags) { 3740 return 1 << FlagsUpdate_offset; 3741 } else if (S == LeaveFlags) { 3742 return 0 << FlagsUpdate_offset; 3743 } 3744 VIXL_UNREACHABLE(); 3745 return 0; 3746 } 3747 3748 static Instr Cond(Condition cond) { 3749 return cond << Condition_offset; 3750 } 3751 3752 // PC-relative address encoding. 3753 static Instr ImmPCRelAddress(int imm21) { 3754 VIXL_ASSERT(is_int21(imm21)); 3755 Instr imm = static_cast<Instr>(truncate_to_int21(imm21)); 3756 Instr immhi = (imm >> ImmPCRelLo_width) << ImmPCRelHi_offset; 3757 Instr immlo = imm << ImmPCRelLo_offset; 3758 return (immhi & ImmPCRelHi_mask) | (immlo & ImmPCRelLo_mask); 3759 } 3760 3761 // Branch encoding. 3762 static Instr ImmUncondBranch(int imm26) { 3763 VIXL_ASSERT(is_int26(imm26)); 3764 return truncate_to_int26(imm26) << ImmUncondBranch_offset; 3765 } 3766 3767 static Instr ImmCondBranch(int imm19) { 3768 VIXL_ASSERT(is_int19(imm19)); 3769 return truncate_to_int19(imm19) << ImmCondBranch_offset; 3770 } 3771 3772 static Instr ImmCmpBranch(int imm19) { 3773 VIXL_ASSERT(is_int19(imm19)); 3774 return truncate_to_int19(imm19) << ImmCmpBranch_offset; 3775 } 3776 3777 static Instr ImmTestBranch(int imm14) { 3778 VIXL_ASSERT(is_int14(imm14)); 3779 return truncate_to_int14(imm14) << ImmTestBranch_offset; 3780 } 3781 3782 static Instr ImmTestBranchBit(unsigned bit_pos) { 3783 VIXL_ASSERT(is_uint6(bit_pos)); 3784 // Subtract five from the shift offset, as we need bit 5 from bit_pos. 3785 unsigned b5 = bit_pos << (ImmTestBranchBit5_offset - 5); 3786 unsigned b40 = bit_pos << ImmTestBranchBit40_offset; 3787 b5 &= ImmTestBranchBit5_mask; 3788 b40 &= ImmTestBranchBit40_mask; 3789 return b5 | b40; 3790 } 3791 3792 // Data Processing encoding. 3793 static Instr SF(Register rd) { 3794 return rd.Is64Bits() ? SixtyFourBits : ThirtyTwoBits; 3795 } 3796 3797 static Instr ImmAddSub(int64_t imm) { 3798 VIXL_ASSERT(IsImmAddSub(imm)); 3799 if (is_uint12(imm)) { // No shift required. 3800 return imm << ImmAddSub_offset; 3801 } else { 3802 return ((imm >> 12) << ImmAddSub_offset) | (1 << ShiftAddSub_offset); 3803 } 3804 } 3805 3806 static Instr ImmS(unsigned imms, unsigned reg_size) { 3807 VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(imms)) || 3808 ((reg_size == kWRegSize) && is_uint5(imms))); 3809 USE(reg_size); 3810 return imms << ImmS_offset; 3811 } 3812 3813 static Instr ImmR(unsigned immr, unsigned reg_size) { 3814 VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || 3815 ((reg_size == kWRegSize) && is_uint5(immr))); 3816 USE(reg_size); 3817 VIXL_ASSERT(is_uint6(immr)); 3818 return immr << ImmR_offset; 3819 } 3820 3821 static Instr ImmSetBits(unsigned imms, unsigned reg_size) { 3822 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); 3823 VIXL_ASSERT(is_uint6(imms)); 3824 VIXL_ASSERT((reg_size == kXRegSize) || is_uint6(imms + 3)); 3825 USE(reg_size); 3826 return imms << ImmSetBits_offset; 3827 } 3828 3829 static Instr ImmRotate(unsigned immr, unsigned reg_size) { 3830 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); 3831 VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || 3832 ((reg_size == kWRegSize) && is_uint5(immr))); 3833 USE(reg_size); 3834 return immr << ImmRotate_offset; 3835 } 3836 3837 static Instr ImmLLiteral(int imm19) { 3838 VIXL_ASSERT(is_int19(imm19)); 3839 return truncate_to_int19(imm19) << ImmLLiteral_offset; 3840 } 3841 3842 static Instr BitN(unsigned bitn, unsigned reg_size) { 3843 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); 3844 VIXL_ASSERT((reg_size == kXRegSize) || (bitn == 0)); 3845 USE(reg_size); 3846 return bitn << BitN_offset; 3847 } 3848 3849 static Instr ShiftDP(Shift shift) { 3850 VIXL_ASSERT(shift == LSL || shift == LSR || shift == ASR || shift == ROR); 3851 return shift << ShiftDP_offset; 3852 } 3853 3854 static Instr ImmDPShift(unsigned amount) { 3855 VIXL_ASSERT(is_uint6(amount)); 3856 return amount << ImmDPShift_offset; 3857 } 3858 3859 static Instr ExtendMode(Extend extend) { 3860 return extend << ExtendMode_offset; 3861 } 3862 3863 static Instr ImmExtendShift(unsigned left_shift) { 3864 VIXL_ASSERT(left_shift <= 4); 3865 return left_shift << ImmExtendShift_offset; 3866 } 3867 3868 static Instr ImmCondCmp(unsigned imm) { 3869 VIXL_ASSERT(is_uint5(imm)); 3870 return imm << ImmCondCmp_offset; 3871 } 3872 3873 static Instr Nzcv(StatusFlags nzcv) { 3874 return ((nzcv >> Flags_offset) & 0xf) << Nzcv_offset; 3875 } 3876 3877 // MemOperand offset encoding. 3878 static Instr ImmLSUnsigned(int imm12) { 3879 VIXL_ASSERT(is_uint12(imm12)); 3880 return imm12 << ImmLSUnsigned_offset; 3881 } 3882 3883 static Instr ImmLS(int imm9) { 3884 VIXL_ASSERT(is_int9(imm9)); 3885 return truncate_to_int9(imm9) << ImmLS_offset; 3886 } 3887 3888 static Instr ImmLSPair(int imm7, unsigned access_size) { 3889 VIXL_ASSERT(((imm7 >> access_size) << access_size) == imm7); 3890 int scaled_imm7 = imm7 >> access_size; 3891 VIXL_ASSERT(is_int7(scaled_imm7)); 3892 return truncate_to_int7(scaled_imm7) << ImmLSPair_offset; 3893 } 3894 3895 static Instr ImmShiftLS(unsigned shift_amount) { 3896 VIXL_ASSERT(is_uint1(shift_amount)); 3897 return shift_amount << ImmShiftLS_offset; 3898 } 3899 3900 static Instr ImmPrefetchOperation(int imm5) { 3901 VIXL_ASSERT(is_uint5(imm5)); 3902 return imm5 << ImmPrefetchOperation_offset; 3903 } 3904 3905 static Instr ImmException(int imm16) { 3906 VIXL_ASSERT(is_uint16(imm16)); 3907 return imm16 << ImmException_offset; 3908 } 3909 3910 static Instr ImmSystemRegister(int imm15) { 3911 VIXL_ASSERT(is_uint15(imm15)); 3912 return imm15 << ImmSystemRegister_offset; 3913 } 3914 3915 static Instr ImmHint(int imm7) { 3916 VIXL_ASSERT(is_uint7(imm7)); 3917 return imm7 << ImmHint_offset; 3918 } 3919 3920 static Instr CRm(int imm4) { 3921 VIXL_ASSERT(is_uint4(imm4)); 3922 return imm4 << CRm_offset; 3923 } 3924 3925 static Instr CRn(int imm4) { 3926 VIXL_ASSERT(is_uint4(imm4)); 3927 return imm4 << CRn_offset; 3928 } 3929 3930 static Instr SysOp(int imm14) { 3931 VIXL_ASSERT(is_uint14(imm14)); 3932 return imm14 << SysOp_offset; 3933 } 3934 3935 static Instr ImmSysOp1(int imm3) { 3936 VIXL_ASSERT(is_uint3(imm3)); 3937 return imm3 << SysOp1_offset; 3938 } 3939 3940 static Instr ImmSysOp2(int imm3) { 3941 VIXL_ASSERT(is_uint3(imm3)); 3942 return imm3 << SysOp2_offset; 3943 } 3944 3945 static Instr ImmBarrierDomain(int imm2) { 3946 VIXL_ASSERT(is_uint2(imm2)); 3947 return imm2 << ImmBarrierDomain_offset; 3948 } 3949 3950 static Instr ImmBarrierType(int imm2) { 3951 VIXL_ASSERT(is_uint2(imm2)); 3952 return imm2 << ImmBarrierType_offset; 3953 } 3954 3955 // Move immediates encoding. 3956 static Instr ImmMoveWide(uint64_t imm) { 3957 VIXL_ASSERT(is_uint16(imm)); 3958 return imm << ImmMoveWide_offset; 3959 } 3960 3961 static Instr ShiftMoveWide(int64_t shift) { 3962 VIXL_ASSERT(is_uint2(shift)); 3963 return shift << ShiftMoveWide_offset; 3964 } 3965 3966 // FP Immediates. 3967 static Instr ImmFP32(float imm); 3968 static Instr ImmFP64(double imm); 3969 3970 // FP register type. 3971 static Instr FPType(FPRegister fd) { 3972 return fd.Is64Bits() ? FP64 : FP32; 3973 } 3974 3975 static Instr FPScale(unsigned scale) { 3976 VIXL_ASSERT(is_uint6(scale)); 3977 return scale << FPScale_offset; 3978 } 3979 3980 // Immediate field checking helpers. 3981 static bool IsImmAddSub(int64_t immediate); 3982 static bool IsImmConditionalCompare(int64_t immediate); 3983 static bool IsImmFP32(float imm); 3984 static bool IsImmFP64(double imm); 3985 static bool IsImmLogical(uint64_t value, 3986 unsigned width, 3987 unsigned* n = NULL, 3988 unsigned* imm_s = NULL, 3989 unsigned* imm_r = NULL); 3990 static bool IsImmLSPair(int64_t offset, unsigned access_size); 3991 static bool IsImmLSScaled(int64_t offset, unsigned access_size); 3992 static bool IsImmLSUnscaled(int64_t offset); 3993 static bool IsImmMovn(uint64_t imm, unsigned reg_size); 3994 static bool IsImmMovz(uint64_t imm, unsigned reg_size); 3995 3996 // Instruction bits for vector format in data processing operations. 3997 static Instr VFormat(VRegister vd) { 3998 if (vd.Is64Bits()) { 3999 switch (vd.lanes()) { 4000 case 2: return NEON_2S; 4001 case 4: return NEON_4H; 4002 case 8: return NEON_8B; 4003 default: return 0xffffffff; 4004 } 4005 } else { 4006 VIXL_ASSERT(vd.Is128Bits()); 4007 switch (vd.lanes()) { 4008 case 2: return NEON_2D; 4009 case 4: return NEON_4S; 4010 case 8: return NEON_8H; 4011 case 16: return NEON_16B; 4012 default: return 0xffffffff; 4013 } 4014 } 4015 } 4016 4017 // Instruction bits for vector format in floating point data processing 4018 // operations. 4019 static Instr FPFormat(VRegister vd) { 4020 if (vd.lanes() == 1) { 4021 // Floating point scalar formats. 4022 VIXL_ASSERT(vd.Is32Bits() || vd.Is64Bits()); 4023 return vd.Is64Bits() ? FP64 : FP32; 4024 } 4025 4026 // Two lane floating point vector formats. 4027 if (vd.lanes() == 2) { 4028 VIXL_ASSERT(vd.Is64Bits() || vd.Is128Bits()); 4029 return vd.Is128Bits() ? NEON_FP_2D : NEON_FP_2S; 4030 } 4031 4032 // Four lane floating point vector format. 4033 VIXL_ASSERT((vd.lanes() == 4) && vd.Is128Bits()); 4034 return NEON_FP_4S; 4035 } 4036 4037 // Instruction bits for vector format in load and store operations. 4038 static Instr LSVFormat(VRegister vd) { 4039 if (vd.Is64Bits()) { 4040 switch (vd.lanes()) { 4041 case 1: return LS_NEON_1D; 4042 case 2: return LS_NEON_2S; 4043 case 4: return LS_NEON_4H; 4044 case 8: return LS_NEON_8B; 4045 default: return 0xffffffff; 4046 } 4047 } else { 4048 VIXL_ASSERT(vd.Is128Bits()); 4049 switch (vd.lanes()) { 4050 case 2: return LS_NEON_2D; 4051 case 4: return LS_NEON_4S; 4052 case 8: return LS_NEON_8H; 4053 case 16: return LS_NEON_16B; 4054 default: return 0xffffffff; 4055 } 4056 } 4057 } 4058 4059 // Instruction bits for scalar format in data processing operations. 4060 static Instr SFormat(VRegister vd) { 4061 VIXL_ASSERT(vd.lanes() == 1); 4062 switch (vd.SizeInBytes()) { 4063 case 1: return NEON_B; 4064 case 2: return NEON_H; 4065 case 4: return NEON_S; 4066 case 8: return NEON_D; 4067 default: return 0xffffffff; 4068 } 4069 } 4070 4071 static Instr ImmNEONHLM(int index, int num_bits) { 4072 int h, l, m; 4073 if (num_bits == 3) { 4074 VIXL_ASSERT(is_uint3(index)); 4075 h = (index >> 2) & 1; 4076 l = (index >> 1) & 1; 4077 m = (index >> 0) & 1; 4078 } else if (num_bits == 2) { 4079 VIXL_ASSERT(is_uint2(index)); 4080 h = (index >> 1) & 1; 4081 l = (index >> 0) & 1; 4082 m = 0; 4083 } else { 4084 VIXL_ASSERT(is_uint1(index) && (num_bits == 1)); 4085 h = (index >> 0) & 1; 4086 l = 0; 4087 m = 0; 4088 } 4089 return (h << NEONH_offset) | (l << NEONL_offset) | (m << NEONM_offset); 4090 } 4091 4092 static Instr ImmNEONExt(int imm4) { 4093 VIXL_ASSERT(is_uint4(imm4)); 4094 return imm4 << ImmNEONExt_offset; 4095 } 4096 4097 static Instr ImmNEON5(Instr format, int index) { 4098 VIXL_ASSERT(is_uint4(index)); 4099 int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format)); 4100 int imm5 = (index << (s + 1)) | (1 << s); 4101 return imm5 << ImmNEON5_offset; 4102 } 4103 4104 static Instr ImmNEON4(Instr format, int index) { 4105 VIXL_ASSERT(is_uint4(index)); 4106 int s = LaneSizeInBytesLog2FromFormat(static_cast<VectorFormat>(format)); 4107 int imm4 = index << s; 4108 return imm4 << ImmNEON4_offset; 4109 } 4110 4111 static Instr ImmNEONabcdefgh(int imm8) { 4112 VIXL_ASSERT(is_uint8(imm8)); 4113 Instr instr; 4114 instr = ((imm8 >> 5) & 7) << ImmNEONabc_offset; 4115 instr |= (imm8 & 0x1f) << ImmNEONdefgh_offset; 4116 return instr; 4117 } 4118 4119 static Instr NEONCmode(int cmode) { 4120 VIXL_ASSERT(is_uint4(cmode)); 4121 return cmode << NEONCmode_offset; 4122 } 4123 4124 static Instr NEONModImmOp(int op) { 4125 VIXL_ASSERT(is_uint1(op)); 4126 return op << NEONModImmOp_offset; 4127 } 4128 4129 // Size of the code generated since label to the current position. 4130 size_t SizeOfCodeGeneratedSince(Label* label) const { 4131 VIXL_ASSERT(label->IsBound()); 4132 return buffer_->OffsetFrom(label->location()); 4133 } 4134 4135 size_t SizeOfCodeGenerated() const { 4136 return buffer_->CursorOffset(); 4137 } 4138 4139 size_t BufferCapacity() const { return buffer_->capacity(); } 4140 4141 size_t RemainingBufferSpace() const { return buffer_->RemainingBytes(); } 4142 4143 void EnsureSpaceFor(size_t amount) { 4144 if (buffer_->RemainingBytes() < amount) { 4145 size_t capacity = buffer_->capacity(); 4146 size_t size = buffer_->CursorOffset(); 4147 do { 4148 // TODO(all): refine. 4149 capacity *= 2; 4150 } while ((capacity - size) < amount); 4151 buffer_->Grow(capacity); 4152 } 4153 } 4154 4155 #ifdef VIXL_DEBUG 4156 void AcquireBuffer() { 4157 VIXL_ASSERT(buffer_monitor_ >= 0); 4158 buffer_monitor_++; 4159 } 4160 4161 void ReleaseBuffer() { 4162 buffer_monitor_--; 4163 VIXL_ASSERT(buffer_monitor_ >= 0); 4164 } 4165 #endif 4166 4167 PositionIndependentCodeOption pic() const { 4168 return pic_; 4169 } 4170 4171 bool AllowPageOffsetDependentCode() const { 4172 return (pic() == PageOffsetDependentCode) || 4173 (pic() == PositionDependentCode); 4174 } 4175 4176 static const Register& AppropriateZeroRegFor(const CPURegister& reg) { 4177 return reg.Is64Bits() ? xzr : wzr; 4178 } 4179 4180 4181 protected: 4182 void LoadStore(const CPURegister& rt, 4183 const MemOperand& addr, 4184 LoadStoreOp op, 4185 LoadStoreScalingOption option = PreferScaledOffset); 4186 4187 void LoadStorePair(const CPURegister& rt, 4188 const CPURegister& rt2, 4189 const MemOperand& addr, 4190 LoadStorePairOp op); 4191 void LoadStoreStruct(const VRegister& vt, 4192 const MemOperand& addr, 4193 NEONLoadStoreMultiStructOp op); 4194 void LoadStoreStruct1(const VRegister& vt, 4195 int reg_count, 4196 const MemOperand& addr); 4197 void LoadStoreStructSingle(const VRegister& vt, 4198 uint32_t lane, 4199 const MemOperand& addr, 4200 NEONLoadStoreSingleStructOp op); 4201 void LoadStoreStructSingleAllLanes(const VRegister& vt, 4202 const MemOperand& addr, 4203 NEONLoadStoreSingleStructOp op); 4204 void LoadStoreStructVerify(const VRegister& vt, 4205 const MemOperand& addr, 4206 Instr op); 4207 4208 void Prefetch(PrefetchOperation op, 4209 const MemOperand& addr, 4210 LoadStoreScalingOption option = PreferScaledOffset); 4211 4212 // TODO(all): The third parameter should be passed by reference but gcc 4.8.2 4213 // reports a bogus uninitialised warning then. 4214 void Logical(const Register& rd, 4215 const Register& rn, 4216 const Operand operand, 4217 LogicalOp op); 4218 void LogicalImmediate(const Register& rd, 4219 const Register& rn, 4220 unsigned n, 4221 unsigned imm_s, 4222 unsigned imm_r, 4223 LogicalOp op); 4224 4225 void ConditionalCompare(const Register& rn, 4226 const Operand& operand, 4227 StatusFlags nzcv, 4228 Condition cond, 4229 ConditionalCompareOp op); 4230 4231 void AddSubWithCarry(const Register& rd, 4232 const Register& rn, 4233 const Operand& operand, 4234 FlagsUpdate S, 4235 AddSubWithCarryOp op); 4236 4237 4238 // Functions for emulating operands not directly supported by the instruction 4239 // set. 4240 void EmitShift(const Register& rd, 4241 const Register& rn, 4242 Shift shift, 4243 unsigned amount); 4244 void EmitExtendShift(const Register& rd, 4245 const Register& rn, 4246 Extend extend, 4247 unsigned left_shift); 4248 4249 void AddSub(const Register& rd, 4250 const Register& rn, 4251 const Operand& operand, 4252 FlagsUpdate S, 4253 AddSubOp op); 4254 4255 void NEONTable(const VRegister& vd, 4256 const VRegister& vn, 4257 const VRegister& vm, 4258 NEONTableOp op); 4259 4260 // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified 4261 // registers. Only simple loads are supported; sign- and zero-extension (such 4262 // as in LDPSW_x or LDRB_w) are not supported. 4263 static LoadStoreOp LoadOpFor(const CPURegister& rt); 4264 static LoadStorePairOp LoadPairOpFor(const CPURegister& rt, 4265 const CPURegister& rt2); 4266 static LoadStoreOp StoreOpFor(const CPURegister& rt); 4267 static LoadStorePairOp StorePairOpFor(const CPURegister& rt, 4268 const CPURegister& rt2); 4269 static LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor( 4270 const CPURegister& rt, const CPURegister& rt2); 4271 static LoadStorePairNonTemporalOp StorePairNonTemporalOpFor( 4272 const CPURegister& rt, const CPURegister& rt2); 4273 static LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt); 4274 4275 4276 private: 4277 static uint32_t FP32ToImm8(float imm); 4278 static uint32_t FP64ToImm8(double imm); 4279 4280 // Instruction helpers. 4281 void MoveWide(const Register& rd, 4282 uint64_t imm, 4283 int shift, 4284 MoveWideImmediateOp mov_op); 4285 void DataProcShiftedRegister(const Register& rd, 4286 const Register& rn, 4287 const Operand& operand, 4288 FlagsUpdate S, 4289 Instr op); 4290 void DataProcExtendedRegister(const Register& rd, 4291 const Register& rn, 4292 const Operand& operand, 4293 FlagsUpdate S, 4294 Instr op); 4295 void LoadStorePairNonTemporal(const CPURegister& rt, 4296 const CPURegister& rt2, 4297 const MemOperand& addr, 4298 LoadStorePairNonTemporalOp op); 4299 void LoadLiteral(const CPURegister& rt, uint64_t imm, LoadLiteralOp op); 4300 void ConditionalSelect(const Register& rd, 4301 const Register& rn, 4302 const Register& rm, 4303 Condition cond, 4304 ConditionalSelectOp op); 4305 void DataProcessing1Source(const Register& rd, 4306 const Register& rn, 4307 DataProcessing1SourceOp op); 4308 void DataProcessing3Source(const Register& rd, 4309 const Register& rn, 4310 const Register& rm, 4311 const Register& ra, 4312 DataProcessing3SourceOp op); 4313 void FPDataProcessing1Source(const VRegister& fd, 4314 const VRegister& fn, 4315 FPDataProcessing1SourceOp op); 4316 void FPDataProcessing3Source(const VRegister& fd, 4317 const VRegister& fn, 4318 const VRegister& fm, 4319 const VRegister& fa, 4320 FPDataProcessing3SourceOp op); 4321 void NEONAcrossLanesL(const VRegister& vd, 4322 const VRegister& vn, 4323 NEONAcrossLanesOp op); 4324 void NEONAcrossLanes(const VRegister& vd, 4325 const VRegister& vn, 4326 NEONAcrossLanesOp op); 4327 void NEONModifiedImmShiftLsl(const VRegister& vd, 4328 const int imm8, 4329 const int left_shift, 4330 NEONModifiedImmediateOp op); 4331 void NEONModifiedImmShiftMsl(const VRegister& vd, 4332 const int imm8, 4333 const int shift_amount, 4334 NEONModifiedImmediateOp op); 4335 void NEONFP2Same(const VRegister& vd, 4336 const VRegister& vn, 4337 Instr vop); 4338 void NEON3Same(const VRegister& vd, 4339 const VRegister& vn, 4340 const VRegister& vm, 4341 NEON3SameOp vop); 4342 void NEONFP3Same(const VRegister& vd, 4343 const VRegister& vn, 4344 const VRegister& vm, 4345 Instr op); 4346 void NEON3DifferentL(const VRegister& vd, 4347 const VRegister& vn, 4348 const VRegister& vm, 4349 NEON3DifferentOp vop); 4350 void NEON3DifferentW(const VRegister& vd, 4351 const VRegister& vn, 4352 const VRegister& vm, 4353 NEON3DifferentOp vop); 4354 void NEON3DifferentHN(const VRegister& vd, 4355 const VRegister& vn, 4356 const VRegister& vm, 4357 NEON3DifferentOp vop); 4358 void NEONFP2RegMisc(const VRegister& vd, 4359 const VRegister& vn, 4360 NEON2RegMiscOp vop, 4361 double value = 0.0); 4362 void NEON2RegMisc(const VRegister& vd, 4363 const VRegister& vn, 4364 NEON2RegMiscOp vop, 4365 int value = 0); 4366 void NEONFP2RegMisc(const VRegister& vd, 4367 const VRegister& vn, 4368 Instr op); 4369 void NEONAddlp(const VRegister& vd, 4370 const VRegister& vn, 4371 NEON2RegMiscOp op); 4372 void NEONPerm(const VRegister& vd, 4373 const VRegister& vn, 4374 const VRegister& vm, 4375 NEONPermOp op); 4376 void NEONFPByElement(const VRegister& vd, 4377 const VRegister& vn, 4378 const VRegister& vm, 4379 int vm_index, 4380 NEONByIndexedElementOp op); 4381 void NEONByElement(const VRegister& vd, 4382 const VRegister& vn, 4383 const VRegister& vm, 4384 int vm_index, 4385 NEONByIndexedElementOp op); 4386 void NEONByElementL(const VRegister& vd, 4387 const VRegister& vn, 4388 const VRegister& vm, 4389 int vm_index, 4390 NEONByIndexedElementOp op); 4391 void NEONShiftImmediate(const VRegister& vd, 4392 const VRegister& vn, 4393 NEONShiftImmediateOp op, 4394 int immh_immb); 4395 void NEONShiftLeftImmediate(const VRegister& vd, 4396 const VRegister& vn, 4397 int shift, 4398 NEONShiftImmediateOp op); 4399 void NEONShiftRightImmediate(const VRegister& vd, 4400 const VRegister& vn, 4401 int shift, 4402 NEONShiftImmediateOp op); 4403 void NEONShiftImmediateL(const VRegister& vd, 4404 const VRegister& vn, 4405 int shift, 4406 NEONShiftImmediateOp op); 4407 void NEONShiftImmediateN(const VRegister& vd, 4408 const VRegister& vn, 4409 int shift, 4410 NEONShiftImmediateOp op); 4411 void NEONXtn(const VRegister& vd, 4412 const VRegister& vn, 4413 NEON2RegMiscOp vop); 4414 4415 Instr LoadStoreStructAddrModeField(const MemOperand& addr); 4416 4417 // Encode the specified MemOperand for the specified access size and scaling 4418 // preference. 4419 Instr LoadStoreMemOperand(const MemOperand& addr, 4420 unsigned access_size, 4421 LoadStoreScalingOption option); 4422 4423 // Link the current (not-yet-emitted) instruction to the specified label, then 4424 // return an offset to be encoded in the instruction. If the label is not yet 4425 // bound, an offset of 0 is returned. 4426 ptrdiff_t LinkAndGetByteOffsetTo(Label * label); 4427 ptrdiff_t LinkAndGetInstructionOffsetTo(Label * label); 4428 ptrdiff_t LinkAndGetPageOffsetTo(Label * label); 4429 4430 // A common implementation for the LinkAndGet<Type>OffsetTo helpers. 4431 template <int element_shift> 4432 ptrdiff_t LinkAndGetOffsetTo(Label* label); 4433 4434 // Literal load offset are in words (32-bit). 4435 ptrdiff_t LinkAndGetWordOffsetTo(RawLiteral* literal); 4436 4437 // Emit the instruction in buffer_. 4438 void Emit(Instr instruction) { 4439 VIXL_STATIC_ASSERT(sizeof(instruction) == kInstructionSize); 4440 VIXL_ASSERT(buffer_monitor_ > 0); 4441 buffer_->Emit32(instruction); 4442 } 4443 4444 // Buffer where the code is emitted. 4445 CodeBuffer* buffer_; 4446 PositionIndependentCodeOption pic_; 4447 4448 #ifdef VIXL_DEBUG 4449 int64_t buffer_monitor_; 4450 #endif 4451 }; 4452 4453 4454 // All Assembler emits MUST acquire/release the underlying code buffer. The 4455 // helper scope below will do so and optionally ensure the buffer is big enough 4456 // to receive the emit. It is possible to request the scope not to perform any 4457 // checks (kNoCheck) if for example it is known in advance the buffer size is 4458 // adequate or there is some other size checking mechanism in place. 4459 class CodeBufferCheckScope { 4460 public: 4461 // Tell whether or not the scope needs to ensure the associated CodeBuffer 4462 // has enough space for the requested size. 4463 enum CheckPolicy { 4464 kNoCheck, 4465 kCheck 4466 }; 4467 4468 // Tell whether or not the scope should assert the amount of code emitted 4469 // within the scope is consistent with the requested amount. 4470 enum AssertPolicy { 4471 kNoAssert, // No assert required. 4472 kExactSize, // The code emitted must be exactly size bytes. 4473 kMaximumSize // The code emitted must be at most size bytes. 4474 }; 4475 4476 CodeBufferCheckScope(Assembler* assm, 4477 size_t size, 4478 CheckPolicy check_policy = kCheck, 4479 AssertPolicy assert_policy = kMaximumSize) 4480 : assm_(assm) { 4481 if (check_policy == kCheck) assm->EnsureSpaceFor(size); 4482 #ifdef VIXL_DEBUG 4483 assm->bind(&start_); 4484 size_ = size; 4485 assert_policy_ = assert_policy; 4486 assm->AcquireBuffer(); 4487 #else 4488 USE(assert_policy); 4489 #endif 4490 } 4491 4492 // This is a shortcut for CodeBufferCheckScope(assm, 0, kNoCheck, kNoAssert). 4493 explicit CodeBufferCheckScope(Assembler* assm) : assm_(assm) { 4494 #ifdef VIXL_DEBUG 4495 size_ = 0; 4496 assert_policy_ = kNoAssert; 4497 assm->AcquireBuffer(); 4498 #endif 4499 } 4500 4501 ~CodeBufferCheckScope() { 4502 #ifdef VIXL_DEBUG 4503 assm_->ReleaseBuffer(); 4504 switch (assert_policy_) { 4505 case kNoAssert: break; 4506 case kExactSize: 4507 VIXL_ASSERT(assm_->SizeOfCodeGeneratedSince(&start_) == size_); 4508 break; 4509 case kMaximumSize: 4510 VIXL_ASSERT(assm_->SizeOfCodeGeneratedSince(&start_) <= size_); 4511 break; 4512 default: 4513 VIXL_UNREACHABLE(); 4514 } 4515 #endif 4516 } 4517 4518 protected: 4519 Assembler* assm_; 4520 #ifdef VIXL_DEBUG 4521 Label start_; 4522 size_t size_; 4523 AssertPolicy assert_policy_; 4524 #endif 4525 }; 4526 4527 } // namespace vixl 4528 4529 #endif // VIXL_A64_ASSEMBLER_A64_H_ 4530