1 // Copyright 2013, 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 #include <list> 31 32 #include "globals-vixl.h" 33 #include "utils-vixl.h" 34 #include "a64/instructions-a64.h" 35 36 namespace vixl { 37 38 typedef uint64_t RegList; 39 static const int kRegListSizeInBits = sizeof(RegList) * 8; 40 41 42 // Registers. 43 44 // Some CPURegister methods can return Register and FPRegister types, so we 45 // need to declare them in advance. 46 class Register; 47 class FPRegister; 48 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 kFPRegister, 58 kNoRegister 59 }; 60 CPURegister()61 CPURegister() : code_(0), size_(0), type_(kNoRegister) { 62 VIXL_ASSERT(!IsValid()); 63 VIXL_ASSERT(IsNone()); 64 } 65 CPURegister(unsigned code,unsigned size,RegisterType type)66 CPURegister(unsigned code, unsigned size, RegisterType type) 67 : code_(code), size_(size), type_(type) { 68 VIXL_ASSERT(IsValidOrNone()); 69 } 70 code()71 unsigned code() const { 72 VIXL_ASSERT(IsValid()); 73 return code_; 74 } 75 type()76 RegisterType type() const { 77 VIXL_ASSERT(IsValidOrNone()); 78 return type_; 79 } 80 Bit()81 RegList Bit() const { 82 VIXL_ASSERT(code_ < (sizeof(RegList) * 8)); 83 return IsValid() ? (static_cast<RegList>(1) << code_) : 0; 84 } 85 size()86 unsigned size() const { 87 VIXL_ASSERT(IsValid()); 88 return size_; 89 } 90 SizeInBytes()91 int SizeInBytes() const { 92 VIXL_ASSERT(IsValid()); 93 VIXL_ASSERT(size() % 8 == 0); 94 return size_ / 8; 95 } 96 SizeInBits()97 int SizeInBits() const { 98 VIXL_ASSERT(IsValid()); 99 return size_; 100 } 101 Is32Bits()102 bool Is32Bits() const { 103 VIXL_ASSERT(IsValid()); 104 return size_ == 32; 105 } 106 Is64Bits()107 bool Is64Bits() const { 108 VIXL_ASSERT(IsValid()); 109 return size_ == 64; 110 } 111 IsValid()112 bool IsValid() const { 113 if (IsValidRegister() || IsValidFPRegister()) { 114 VIXL_ASSERT(!IsNone()); 115 return true; 116 } else { 117 VIXL_ASSERT(IsNone()); 118 return false; 119 } 120 } 121 IsValidRegister()122 bool IsValidRegister() const { 123 return IsRegister() && 124 ((size_ == kWRegSize) || (size_ == kXRegSize)) && 125 ((code_ < kNumberOfRegisters) || (code_ == kSPRegInternalCode)); 126 } 127 IsValidFPRegister()128 bool IsValidFPRegister() const { 129 return IsFPRegister() && 130 ((size_ == kSRegSize) || (size_ == kDRegSize)) && 131 (code_ < kNumberOfFPRegisters); 132 } 133 IsNone()134 bool IsNone() const { 135 // kNoRegister types should always have size 0 and code 0. 136 VIXL_ASSERT((type_ != kNoRegister) || (code_ == 0)); 137 VIXL_ASSERT((type_ != kNoRegister) || (size_ == 0)); 138 139 return type_ == kNoRegister; 140 } 141 Aliases(const CPURegister & other)142 bool Aliases(const CPURegister& other) const { 143 VIXL_ASSERT(IsValidOrNone() && other.IsValidOrNone()); 144 return (code_ == other.code_) && (type_ == other.type_); 145 } 146 Is(const CPURegister & other)147 bool Is(const CPURegister& other) const { 148 VIXL_ASSERT(IsValidOrNone() && other.IsValidOrNone()); 149 return Aliases(other) && (size_ == other.size_); 150 } 151 IsZero()152 inline bool IsZero() const { 153 VIXL_ASSERT(IsValid()); 154 return IsRegister() && (code_ == kZeroRegCode); 155 } 156 IsSP()157 inline bool IsSP() const { 158 VIXL_ASSERT(IsValid()); 159 return IsRegister() && (code_ == kSPRegInternalCode); 160 } 161 IsRegister()162 inline bool IsRegister() const { 163 return type_ == kRegister; 164 } 165 IsFPRegister()166 inline bool IsFPRegister() const { 167 return type_ == kFPRegister; 168 } 169 170 const Register& W() const; 171 const Register& X() const; 172 const FPRegister& S() const; 173 const FPRegister& D() const; 174 IsSameSizeAndType(const CPURegister & other)175 inline bool IsSameSizeAndType(const CPURegister& other) const { 176 return (size_ == other.size_) && (type_ == other.type_); 177 } 178 179 protected: 180 unsigned code_; 181 unsigned size_; 182 RegisterType type_; 183 184 private: IsValidOrNone()185 bool IsValidOrNone() const { 186 return IsValid() || IsNone(); 187 } 188 }; 189 190 191 class Register : public CPURegister { 192 public: Register()193 explicit Register() : CPURegister() {} Register(const CPURegister & other)194 inline explicit Register(const CPURegister& other) 195 : CPURegister(other.code(), other.size(), other.type()) { 196 VIXL_ASSERT(IsValidRegister()); 197 } Register(unsigned code,unsigned size)198 explicit Register(unsigned code, unsigned size) 199 : CPURegister(code, size, kRegister) {} 200 IsValid()201 bool IsValid() const { 202 VIXL_ASSERT(IsRegister() || IsNone()); 203 return IsValidRegister(); 204 } 205 206 static const Register& WRegFromCode(unsigned code); 207 static const Register& XRegFromCode(unsigned code); 208 209 // V8 compatibility. 210 static const int kNumRegisters = kNumberOfRegisters; 211 static const int kNumAllocatableRegisters = kNumberOfRegisters - 1; 212 213 private: 214 static const Register wregisters[]; 215 static const Register xregisters[]; 216 }; 217 218 219 class FPRegister : public CPURegister { 220 public: FPRegister()221 inline FPRegister() : CPURegister() {} FPRegister(const CPURegister & other)222 inline explicit FPRegister(const CPURegister& other) 223 : CPURegister(other.code(), other.size(), other.type()) { 224 VIXL_ASSERT(IsValidFPRegister()); 225 } FPRegister(unsigned code,unsigned size)226 inline FPRegister(unsigned code, unsigned size) 227 : CPURegister(code, size, kFPRegister) {} 228 IsValid()229 bool IsValid() const { 230 VIXL_ASSERT(IsFPRegister() || IsNone()); 231 return IsValidFPRegister(); 232 } 233 234 static const FPRegister& SRegFromCode(unsigned code); 235 static const FPRegister& DRegFromCode(unsigned code); 236 237 // V8 compatibility. 238 static const int kNumRegisters = kNumberOfFPRegisters; 239 static const int kNumAllocatableRegisters = kNumberOfFPRegisters - 1; 240 241 private: 242 static const FPRegister sregisters[]; 243 static const FPRegister dregisters[]; 244 }; 245 246 247 // No*Reg is used to indicate an unused argument, or an error case. Note that 248 // these all compare equal (using the Is() method). The Register and FPRegister 249 // variants are provided for convenience. 250 const Register NoReg; 251 const FPRegister NoFPReg; 252 const CPURegister NoCPUReg; 253 254 255 #define DEFINE_REGISTERS(N) \ 256 const Register w##N(N, kWRegSize); \ 257 const Register x##N(N, kXRegSize); 258 REGISTER_CODE_LIST(DEFINE_REGISTERS) 259 #undef DEFINE_REGISTERS 260 const Register wsp(kSPRegInternalCode, kWRegSize); 261 const Register sp(kSPRegInternalCode, kXRegSize); 262 263 264 #define DEFINE_FPREGISTERS(N) \ 265 const FPRegister s##N(N, kSRegSize); \ 266 const FPRegister d##N(N, kDRegSize); 267 REGISTER_CODE_LIST(DEFINE_FPREGISTERS) 268 #undef DEFINE_FPREGISTERS 269 270 271 // Registers aliases. 272 const Register ip0 = x16; 273 const Register ip1 = x17; 274 const Register lr = x30; 275 const Register xzr = x31; 276 const Register wzr = w31; 277 278 279 // AreAliased returns true if any of the named registers overlap. Arguments 280 // set to NoReg are ignored. The system stack pointer may be specified. 281 bool AreAliased(const CPURegister& reg1, 282 const CPURegister& reg2, 283 const CPURegister& reg3 = NoReg, 284 const CPURegister& reg4 = NoReg, 285 const CPURegister& reg5 = NoReg, 286 const CPURegister& reg6 = NoReg, 287 const CPURegister& reg7 = NoReg, 288 const CPURegister& reg8 = NoReg); 289 290 291 // AreSameSizeAndType returns true if all of the specified registers have the 292 // same size, and are of the same type. The system stack pointer may be 293 // specified. Arguments set to NoReg are ignored, as are any subsequent 294 // arguments. At least one argument (reg1) must be valid (not NoCPUReg). 295 bool AreSameSizeAndType(const CPURegister& reg1, 296 const CPURegister& reg2, 297 const CPURegister& reg3 = NoCPUReg, 298 const CPURegister& reg4 = NoCPUReg, 299 const CPURegister& reg5 = NoCPUReg, 300 const CPURegister& reg6 = NoCPUReg, 301 const CPURegister& reg7 = NoCPUReg, 302 const CPURegister& reg8 = NoCPUReg); 303 304 305 // Lists of registers. 306 class CPURegList { 307 public: 308 inline explicit CPURegList(CPURegister reg1, 309 CPURegister reg2 = NoCPUReg, 310 CPURegister reg3 = NoCPUReg, 311 CPURegister reg4 = NoCPUReg) 312 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), 313 size_(reg1.size()), type_(reg1.type()) { 314 VIXL_ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4)); 315 VIXL_ASSERT(IsValid()); 316 } 317 CPURegList(CPURegister::RegisterType type,unsigned size,RegList list)318 inline CPURegList(CPURegister::RegisterType type, unsigned size, RegList list) 319 : list_(list), size_(size), type_(type) { 320 VIXL_ASSERT(IsValid()); 321 } 322 CPURegList(CPURegister::RegisterType type,unsigned size,unsigned first_reg,unsigned last_reg)323 inline CPURegList(CPURegister::RegisterType type, unsigned size, 324 unsigned first_reg, unsigned last_reg) 325 : size_(size), type_(type) { 326 VIXL_ASSERT(((type == CPURegister::kRegister) && 327 (last_reg < kNumberOfRegisters)) || 328 ((type == CPURegister::kFPRegister) && 329 (last_reg < kNumberOfFPRegisters))); 330 VIXL_ASSERT(last_reg >= first_reg); 331 list_ = (UINT64_C(1) << (last_reg + 1)) - 1; 332 list_ &= ~((UINT64_C(1) << first_reg) - 1); 333 VIXL_ASSERT(IsValid()); 334 } 335 type()336 inline CPURegister::RegisterType type() const { 337 VIXL_ASSERT(IsValid()); 338 return type_; 339 } 340 341 // Combine another CPURegList into this one. Registers that already exist in 342 // this list are left unchanged. The type and size of the registers in the 343 // 'other' list must match those in this list. Combine(const CPURegList & other)344 void Combine(const CPURegList& other) { 345 VIXL_ASSERT(IsValid()); 346 VIXL_ASSERT(other.type() == type_); 347 VIXL_ASSERT(other.RegisterSizeInBits() == size_); 348 list_ |= other.list(); 349 } 350 351 // Remove every register in the other CPURegList from this one. Registers that 352 // do not exist in this list are ignored. The type and size of the registers 353 // in the 'other' list must match those in this list. Remove(const CPURegList & other)354 void Remove(const CPURegList& other) { 355 VIXL_ASSERT(IsValid()); 356 VIXL_ASSERT(other.type() == type_); 357 VIXL_ASSERT(other.RegisterSizeInBits() == size_); 358 list_ &= ~other.list(); 359 } 360 361 // Variants of Combine and Remove which take a single register. Combine(const CPURegister & other)362 inline void Combine(const CPURegister& other) { 363 VIXL_ASSERT(other.type() == type_); 364 VIXL_ASSERT(other.size() == size_); 365 Combine(other.code()); 366 } 367 Remove(const CPURegister & other)368 inline void Remove(const CPURegister& other) { 369 VIXL_ASSERT(other.type() == type_); 370 VIXL_ASSERT(other.size() == size_); 371 Remove(other.code()); 372 } 373 374 // Variants of Combine and Remove which take a single register by its code; 375 // the type and size of the register is inferred from this list. Combine(int code)376 inline void Combine(int code) { 377 VIXL_ASSERT(IsValid()); 378 VIXL_ASSERT(CPURegister(code, size_, type_).IsValid()); 379 list_ |= (UINT64_C(1) << code); 380 } 381 Remove(int code)382 inline void Remove(int code) { 383 VIXL_ASSERT(IsValid()); 384 VIXL_ASSERT(CPURegister(code, size_, type_).IsValid()); 385 list_ &= ~(UINT64_C(1) << code); 386 } 387 list()388 inline RegList list() const { 389 VIXL_ASSERT(IsValid()); 390 return list_; 391 } 392 set_list(RegList new_list)393 inline void set_list(RegList new_list) { 394 VIXL_ASSERT(IsValid()); 395 list_ = new_list; 396 } 397 398 // Remove all callee-saved registers from the list. This can be useful when 399 // preparing registers for an AAPCS64 function call, for example. 400 void RemoveCalleeSaved(); 401 402 CPURegister PopLowestIndex(); 403 CPURegister PopHighestIndex(); 404 405 // AAPCS64 callee-saved registers. 406 static CPURegList GetCalleeSaved(unsigned size = kXRegSize); 407 static CPURegList GetCalleeSavedFP(unsigned size = kDRegSize); 408 409 // AAPCS64 caller-saved registers. Note that this includes lr. 410 static CPURegList GetCallerSaved(unsigned size = kXRegSize); 411 static CPURegList GetCallerSavedFP(unsigned size = kDRegSize); 412 IsEmpty()413 inline bool IsEmpty() const { 414 VIXL_ASSERT(IsValid()); 415 return list_ == 0; 416 } 417 IncludesAliasOf(const CPURegister & other)418 inline bool IncludesAliasOf(const CPURegister& other) const { 419 VIXL_ASSERT(IsValid()); 420 return (type_ == other.type()) && ((other.Bit() & list_) != 0); 421 } 422 IncludesAliasOf(int code)423 inline bool IncludesAliasOf(int code) const { 424 VIXL_ASSERT(IsValid()); 425 return ((code & list_) != 0); 426 } 427 Count()428 inline int Count() const { 429 VIXL_ASSERT(IsValid()); 430 return CountSetBits(list_, kRegListSizeInBits); 431 } 432 RegisterSizeInBits()433 inline unsigned RegisterSizeInBits() const { 434 VIXL_ASSERT(IsValid()); 435 return size_; 436 } 437 RegisterSizeInBytes()438 inline unsigned RegisterSizeInBytes() const { 439 int size_in_bits = RegisterSizeInBits(); 440 VIXL_ASSERT((size_in_bits % 8) == 0); 441 return size_in_bits / 8; 442 } 443 TotalSizeInBytes()444 inline unsigned TotalSizeInBytes() const { 445 VIXL_ASSERT(IsValid()); 446 return RegisterSizeInBytes() * Count(); 447 } 448 449 private: 450 RegList list_; 451 unsigned size_; 452 CPURegister::RegisterType type_; 453 454 bool IsValid() const; 455 }; 456 457 458 // AAPCS64 callee-saved registers. 459 extern const CPURegList kCalleeSaved; 460 extern const CPURegList kCalleeSavedFP; 461 462 463 // AAPCS64 caller-saved registers. Note that this includes lr. 464 extern const CPURegList kCallerSaved; 465 extern const CPURegList kCallerSavedFP; 466 467 468 // Operand. 469 class Operand { 470 public: 471 // #<immediate> 472 // where <immediate> is int64_t. 473 // This is allowed to be an implicit constructor because Operand is 474 // a wrapper class that doesn't normally perform any type conversion. 475 Operand(int64_t immediate); // NOLINT(runtime/explicit) 476 477 // rm, {<shift> #<shift_amount>} 478 // where <shift> is one of {LSL, LSR, ASR, ROR}. 479 // <shift_amount> is uint6_t. 480 // This is allowed to be an implicit constructor because Operand is 481 // a wrapper class that doesn't normally perform any type conversion. 482 Operand(Register reg, 483 Shift shift = LSL, 484 unsigned shift_amount = 0); // NOLINT(runtime/explicit) 485 486 // rm, {<extend> {#<shift_amount>}} 487 // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}. 488 // <shift_amount> is uint2_t. 489 explicit Operand(Register reg, Extend extend, unsigned shift_amount = 0); 490 491 bool IsImmediate() const; 492 bool IsShiftedRegister() const; 493 bool IsExtendedRegister() const; 494 bool IsZero() const; 495 496 // This returns an LSL shift (<= 4) operand as an equivalent extend operand, 497 // which helps in the encoding of instructions that use the stack pointer. 498 Operand ToExtendedRegister() const; 499 immediate()500 int64_t immediate() const { 501 VIXL_ASSERT(IsImmediate()); 502 return immediate_; 503 } 504 reg()505 Register reg() const { 506 VIXL_ASSERT(IsShiftedRegister() || IsExtendedRegister()); 507 return reg_; 508 } 509 shift()510 Shift shift() const { 511 VIXL_ASSERT(IsShiftedRegister()); 512 return shift_; 513 } 514 extend()515 Extend extend() const { 516 VIXL_ASSERT(IsExtendedRegister()); 517 return extend_; 518 } 519 shift_amount()520 unsigned shift_amount() const { 521 VIXL_ASSERT(IsShiftedRegister() || IsExtendedRegister()); 522 return shift_amount_; 523 } 524 525 private: 526 int64_t immediate_; 527 Register reg_; 528 Shift shift_; 529 Extend extend_; 530 unsigned shift_amount_; 531 }; 532 533 534 // MemOperand represents the addressing mode of a load or store instruction. 535 class MemOperand { 536 public: 537 explicit MemOperand(Register base, 538 ptrdiff_t offset = 0, 539 AddrMode addrmode = Offset); 540 explicit MemOperand(Register base, 541 Register regoffset, 542 Shift shift = LSL, 543 unsigned shift_amount = 0); 544 explicit MemOperand(Register base, 545 Register regoffset, 546 Extend extend, 547 unsigned shift_amount = 0); 548 explicit MemOperand(Register base, 549 const Operand& offset, 550 AddrMode addrmode = Offset); 551 base()552 const Register& base() const { return base_; } regoffset()553 const Register& regoffset() const { return regoffset_; } offset()554 ptrdiff_t offset() const { return offset_; } addrmode()555 AddrMode addrmode() const { return addrmode_; } shift()556 Shift shift() const { return shift_; } extend()557 Extend extend() const { return extend_; } shift_amount()558 unsigned shift_amount() const { return shift_amount_; } 559 bool IsImmediateOffset() const; 560 bool IsRegisterOffset() const; 561 bool IsPreIndex() const; 562 bool IsPostIndex() const; 563 564 private: 565 Register base_; 566 Register regoffset_; 567 ptrdiff_t offset_; 568 AddrMode addrmode_; 569 Shift shift_; 570 Extend extend_; 571 unsigned shift_amount_; 572 }; 573 574 575 class Label { 576 public: Label()577 Label() : is_bound_(false), link_(NULL), target_(NULL) {} ~Label()578 ~Label() { 579 // If the label has been linked to, it needs to be bound to a target. 580 VIXL_ASSERT(!IsLinked() || IsBound()); 581 } 582 link()583 inline Instruction* link() const { return link_; } target()584 inline Instruction* target() const { return target_; } 585 IsBound()586 inline bool IsBound() const { return is_bound_; } IsLinked()587 inline bool IsLinked() const { return link_ != NULL; } 588 set_link(Instruction * new_link)589 inline void set_link(Instruction* new_link) { link_ = new_link; } 590 591 static const int kEndOfChain = 0; 592 593 private: 594 // Indicates if the label has been bound, ie its location is fixed. 595 bool is_bound_; 596 // Branches instructions branching to this label form a chained list, with 597 // their offset indicating where the next instruction is located. 598 // link_ points to the latest branch instruction generated branching to this 599 // branch. 600 // If link_ is not NULL, the label has been linked to. 601 Instruction* link_; 602 // The label location. 603 Instruction* target_; 604 605 friend class Assembler; 606 }; 607 608 609 // TODO: Obtain better values for these, based on real-world data. 610 const int kLiteralPoolCheckInterval = 4 * KBytes; 611 const int kRecommendedLiteralPoolRange = 2 * kLiteralPoolCheckInterval; 612 613 614 // Control whether a branch over the literal pool should also be emitted. This 615 // is needed if the literal pool has to be emitted in the middle of the JITted 616 // code. 617 enum LiteralPoolEmitOption { 618 JumpRequired, 619 NoJumpRequired 620 }; 621 622 623 // Literal pool entry. 624 class Literal { 625 public: Literal(Instruction * pc,uint64_t imm,unsigned size)626 Literal(Instruction* pc, uint64_t imm, unsigned size) 627 : pc_(pc), value_(imm), size_(size) {} 628 629 private: 630 Instruction* pc_; 631 int64_t value_; 632 unsigned size_; 633 634 friend class Assembler; 635 }; 636 637 638 // Assembler. 639 class Assembler { 640 public: 641 Assembler(byte* buffer, unsigned buffer_size); 642 643 // The destructor asserts that one of the following is true: 644 // * The Assembler object has not been used. 645 // * Nothing has been emitted since the last Reset() call. 646 // * Nothing has been emitted since the last FinalizeCode() call. 647 ~Assembler(); 648 649 // System functions. 650 651 // Start generating code from the beginning of the buffer, discarding any code 652 // and data that has already been emitted into the buffer. 653 // 654 // In order to avoid any accidental transfer of state, Reset ASSERTs that the 655 // constant pool is not blocked. 656 void Reset(); 657 658 // Finalize a code buffer of generated instructions. This function must be 659 // called before executing or copying code from the buffer. 660 void FinalizeCode(); 661 662 // Label. 663 // Bind a label to the current PC. 664 void bind(Label* label); 665 int UpdateAndGetByteOffsetTo(Label* label); UpdateAndGetInstructionOffsetTo(Label * label)666 inline int UpdateAndGetInstructionOffsetTo(Label* label) { 667 VIXL_ASSERT(Label::kEndOfChain == 0); 668 return UpdateAndGetByteOffsetTo(label) >> kInstructionSizeLog2; 669 } 670 671 672 // Instruction set functions. 673 674 // Branch / Jump instructions. 675 // Branch to register. 676 void br(const Register& xn); 677 678 // Branch with link to register. 679 void blr(const Register& xn); 680 681 // Branch to register with return hint. 682 void ret(const Register& xn = lr); 683 684 // Unconditional branch to label. 685 void b(Label* label); 686 687 // Conditional branch to label. 688 void b(Label* label, Condition cond); 689 690 // Unconditional branch to PC offset. 691 void b(int imm26); 692 693 // Conditional branch to PC offset. 694 void b(int imm19, Condition cond); 695 696 // Branch with link to label. 697 void bl(Label* label); 698 699 // Branch with link to PC offset. 700 void bl(int imm26); 701 702 // Compare and branch to label if zero. 703 void cbz(const Register& rt, Label* label); 704 705 // Compare and branch to PC offset if zero. 706 void cbz(const Register& rt, int imm19); 707 708 // Compare and branch to label if not zero. 709 void cbnz(const Register& rt, Label* label); 710 711 // Compare and branch to PC offset if not zero. 712 void cbnz(const Register& rt, int imm19); 713 714 // Test bit and branch to label if zero. 715 void tbz(const Register& rt, unsigned bit_pos, Label* label); 716 717 // Test bit and branch to PC offset if zero. 718 void tbz(const Register& rt, unsigned bit_pos, int imm14); 719 720 // Test bit and branch to label if not zero. 721 void tbnz(const Register& rt, unsigned bit_pos, Label* label); 722 723 // Test bit and branch to PC offset if not zero. 724 void tbnz(const Register& rt, unsigned bit_pos, int imm14); 725 726 // Address calculation instructions. 727 // Calculate a PC-relative address. Unlike for branches the offset in adr is 728 // unscaled (i.e. the result can be unaligned). 729 730 // Calculate the address of a label. 731 void adr(const Register& rd, Label* label); 732 733 // Calculate the address of a PC offset. 734 void adr(const Register& rd, int imm21); 735 736 // Data Processing instructions. 737 // Add. 738 void add(const Register& rd, 739 const Register& rn, 740 const Operand& operand); 741 742 // Add and update status flags. 743 void adds(const Register& rd, 744 const Register& rn, 745 const Operand& operand); 746 747 // Compare negative. 748 void cmn(const Register& rn, const Operand& operand); 749 750 // Subtract. 751 void sub(const Register& rd, 752 const Register& rn, 753 const Operand& operand); 754 755 // Subtract and update status flags. 756 void subs(const Register& rd, 757 const Register& rn, 758 const Operand& operand); 759 760 // Compare. 761 void cmp(const Register& rn, const Operand& operand); 762 763 // Negate. 764 void neg(const Register& rd, 765 const Operand& operand); 766 767 // Negate and update status flags. 768 void negs(const Register& rd, 769 const Operand& operand); 770 771 // Add with carry bit. 772 void adc(const Register& rd, 773 const Register& rn, 774 const Operand& operand); 775 776 // Add with carry bit and update status flags. 777 void adcs(const Register& rd, 778 const Register& rn, 779 const Operand& operand); 780 781 // Subtract with carry bit. 782 void sbc(const Register& rd, 783 const Register& rn, 784 const Operand& operand); 785 786 // Subtract with carry bit and update status flags. 787 void sbcs(const Register& rd, 788 const Register& rn, 789 const Operand& operand); 790 791 // Negate with carry bit. 792 void ngc(const Register& rd, 793 const Operand& operand); 794 795 // Negate with carry bit and update status flags. 796 void ngcs(const Register& rd, 797 const Operand& operand); 798 799 // Logical instructions. 800 // Bitwise and (A & B). 801 void and_(const Register& rd, 802 const Register& rn, 803 const Operand& operand); 804 805 // Bitwise and (A & B) and update status flags. 806 void ands(const Register& rd, 807 const Register& rn, 808 const Operand& operand); 809 810 // Bit test and set flags. 811 void tst(const Register& rn, const Operand& operand); 812 813 // Bit clear (A & ~B). 814 void bic(const Register& rd, 815 const Register& rn, 816 const Operand& operand); 817 818 // Bit clear (A & ~B) and update status flags. 819 void bics(const Register& rd, 820 const Register& rn, 821 const Operand& operand); 822 823 // Bitwise or (A | B). 824 void orr(const Register& rd, const Register& rn, const Operand& operand); 825 826 // Bitwise nor (A | ~B). 827 void orn(const Register& rd, const Register& rn, const Operand& operand); 828 829 // Bitwise eor/xor (A ^ B). 830 void eor(const Register& rd, const Register& rn, const Operand& operand); 831 832 // Bitwise enor/xnor (A ^ ~B). 833 void eon(const Register& rd, const Register& rn, const Operand& operand); 834 835 // Logical shift left by variable. 836 void lslv(const Register& rd, const Register& rn, const Register& rm); 837 838 // Logical shift right by variable. 839 void lsrv(const Register& rd, const Register& rn, const Register& rm); 840 841 // Arithmetic shift right by variable. 842 void asrv(const Register& rd, const Register& rn, const Register& rm); 843 844 // Rotate right by variable. 845 void rorv(const Register& rd, const Register& rn, const Register& rm); 846 847 // Bitfield instructions. 848 // Bitfield move. 849 void bfm(const Register& rd, 850 const Register& rn, 851 unsigned immr, 852 unsigned imms); 853 854 // Signed bitfield move. 855 void sbfm(const Register& rd, 856 const Register& rn, 857 unsigned immr, 858 unsigned imms); 859 860 // Unsigned bitfield move. 861 void ubfm(const Register& rd, 862 const Register& rn, 863 unsigned immr, 864 unsigned imms); 865 866 // Bfm aliases. 867 // Bitfield insert. bfi(const Register & rd,const Register & rn,unsigned lsb,unsigned width)868 inline void bfi(const Register& rd, 869 const Register& rn, 870 unsigned lsb, 871 unsigned width) { 872 VIXL_ASSERT(width >= 1); 873 VIXL_ASSERT(lsb + width <= rn.size()); 874 bfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); 875 } 876 877 // Bitfield extract and insert low. bfxil(const Register & rd,const Register & rn,unsigned lsb,unsigned width)878 inline void bfxil(const Register& rd, 879 const Register& rn, 880 unsigned lsb, 881 unsigned width) { 882 VIXL_ASSERT(width >= 1); 883 VIXL_ASSERT(lsb + width <= rn.size()); 884 bfm(rd, rn, lsb, lsb + width - 1); 885 } 886 887 // Sbfm aliases. 888 // Arithmetic shift right. asr(const Register & rd,const Register & rn,unsigned shift)889 inline void asr(const Register& rd, const Register& rn, unsigned shift) { 890 VIXL_ASSERT(shift < rd.size()); 891 sbfm(rd, rn, shift, rd.size() - 1); 892 } 893 894 // Signed bitfield insert with zero at right. sbfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)895 inline void sbfiz(const Register& rd, 896 const Register& rn, 897 unsigned lsb, 898 unsigned width) { 899 VIXL_ASSERT(width >= 1); 900 VIXL_ASSERT(lsb + width <= rn.size()); 901 sbfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); 902 } 903 904 // Signed bitfield extract. sbfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)905 inline void sbfx(const Register& rd, 906 const Register& rn, 907 unsigned lsb, 908 unsigned width) { 909 VIXL_ASSERT(width >= 1); 910 VIXL_ASSERT(lsb + width <= rn.size()); 911 sbfm(rd, rn, lsb, lsb + width - 1); 912 } 913 914 // Signed extend byte. sxtb(const Register & rd,const Register & rn)915 inline void sxtb(const Register& rd, const Register& rn) { 916 sbfm(rd, rn, 0, 7); 917 } 918 919 // Signed extend halfword. sxth(const Register & rd,const Register & rn)920 inline void sxth(const Register& rd, const Register& rn) { 921 sbfm(rd, rn, 0, 15); 922 } 923 924 // Signed extend word. sxtw(const Register & rd,const Register & rn)925 inline void sxtw(const Register& rd, const Register& rn) { 926 sbfm(rd, rn, 0, 31); 927 } 928 929 // Ubfm aliases. 930 // Logical shift left. lsl(const Register & rd,const Register & rn,unsigned shift)931 inline void lsl(const Register& rd, const Register& rn, unsigned shift) { 932 unsigned reg_size = rd.size(); 933 VIXL_ASSERT(shift < reg_size); 934 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1); 935 } 936 937 // Logical shift right. lsr(const Register & rd,const Register & rn,unsigned shift)938 inline void lsr(const Register& rd, const Register& rn, unsigned shift) { 939 VIXL_ASSERT(shift < rd.size()); 940 ubfm(rd, rn, shift, rd.size() - 1); 941 } 942 943 // Unsigned bitfield insert with zero at right. ubfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)944 inline void ubfiz(const Register& rd, 945 const Register& rn, 946 unsigned lsb, 947 unsigned width) { 948 VIXL_ASSERT(width >= 1); 949 VIXL_ASSERT(lsb + width <= rn.size()); 950 ubfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); 951 } 952 953 // Unsigned bitfield extract. ubfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)954 inline void ubfx(const Register& rd, 955 const Register& rn, 956 unsigned lsb, 957 unsigned width) { 958 VIXL_ASSERT(width >= 1); 959 VIXL_ASSERT(lsb + width <= rn.size()); 960 ubfm(rd, rn, lsb, lsb + width - 1); 961 } 962 963 // Unsigned extend byte. uxtb(const Register & rd,const Register & rn)964 inline void uxtb(const Register& rd, const Register& rn) { 965 ubfm(rd, rn, 0, 7); 966 } 967 968 // Unsigned extend halfword. uxth(const Register & rd,const Register & rn)969 inline void uxth(const Register& rd, const Register& rn) { 970 ubfm(rd, rn, 0, 15); 971 } 972 973 // Unsigned extend word. uxtw(const Register & rd,const Register & rn)974 inline void uxtw(const Register& rd, const Register& rn) { 975 ubfm(rd, rn, 0, 31); 976 } 977 978 // Extract. 979 void extr(const Register& rd, 980 const Register& rn, 981 const Register& rm, 982 unsigned lsb); 983 984 // Conditional select: rd = cond ? rn : rm. 985 void csel(const Register& rd, 986 const Register& rn, 987 const Register& rm, 988 Condition cond); 989 990 // Conditional select increment: rd = cond ? rn : rm + 1. 991 void csinc(const Register& rd, 992 const Register& rn, 993 const Register& rm, 994 Condition cond); 995 996 // Conditional select inversion: rd = cond ? rn : ~rm. 997 void csinv(const Register& rd, 998 const Register& rn, 999 const Register& rm, 1000 Condition cond); 1001 1002 // Conditional select negation: rd = cond ? rn : -rm. 1003 void csneg(const Register& rd, 1004 const Register& rn, 1005 const Register& rm, 1006 Condition cond); 1007 1008 // Conditional set: rd = cond ? 1 : 0. 1009 void cset(const Register& rd, Condition cond); 1010 1011 // Conditional set mask: rd = cond ? -1 : 0. 1012 void csetm(const Register& rd, Condition cond); 1013 1014 // Conditional increment: rd = cond ? rn + 1 : rn. 1015 void cinc(const Register& rd, const Register& rn, Condition cond); 1016 1017 // Conditional invert: rd = cond ? ~rn : rn. 1018 void cinv(const Register& rd, const Register& rn, Condition cond); 1019 1020 // Conditional negate: rd = cond ? -rn : rn. 1021 void cneg(const Register& rd, const Register& rn, Condition cond); 1022 1023 // Rotate right. ror(const Register & rd,const Register & rs,unsigned shift)1024 inline void ror(const Register& rd, const Register& rs, unsigned shift) { 1025 extr(rd, rs, rs, shift); 1026 } 1027 1028 // Conditional comparison. 1029 // Conditional compare negative. 1030 void ccmn(const Register& rn, 1031 const Operand& operand, 1032 StatusFlags nzcv, 1033 Condition cond); 1034 1035 // Conditional compare. 1036 void ccmp(const Register& rn, 1037 const Operand& operand, 1038 StatusFlags nzcv, 1039 Condition cond); 1040 1041 // Multiply. 1042 void mul(const Register& rd, const Register& rn, const Register& rm); 1043 1044 // Negated multiply. 1045 void mneg(const Register& rd, const Register& rn, const Register& rm); 1046 1047 // Signed long multiply: 32 x 32 -> 64-bit. 1048 void smull(const Register& rd, const Register& rn, const Register& rm); 1049 1050 // Signed multiply high: 64 x 64 -> 64-bit <127:64>. 1051 void smulh(const Register& xd, const Register& xn, const Register& xm); 1052 1053 // Multiply and accumulate. 1054 void madd(const Register& rd, 1055 const Register& rn, 1056 const Register& rm, 1057 const Register& ra); 1058 1059 // Multiply and subtract. 1060 void msub(const Register& rd, 1061 const Register& rn, 1062 const Register& rm, 1063 const Register& ra); 1064 1065 // Signed long multiply and accumulate: 32 x 32 + 64 -> 64-bit. 1066 void smaddl(const Register& rd, 1067 const Register& rn, 1068 const Register& rm, 1069 const Register& ra); 1070 1071 // Unsigned long multiply and accumulate: 32 x 32 + 64 -> 64-bit. 1072 void umaddl(const Register& rd, 1073 const Register& rn, 1074 const Register& rm, 1075 const Register& ra); 1076 1077 // Signed long multiply and subtract: 64 - (32 x 32) -> 64-bit. 1078 void smsubl(const Register& rd, 1079 const Register& rn, 1080 const Register& rm, 1081 const Register& ra); 1082 1083 // Unsigned long multiply and subtract: 64 - (32 x 32) -> 64-bit. 1084 void umsubl(const Register& rd, 1085 const Register& rn, 1086 const Register& rm, 1087 const Register& ra); 1088 1089 // Signed integer divide. 1090 void sdiv(const Register& rd, const Register& rn, const Register& rm); 1091 1092 // Unsigned integer divide. 1093 void udiv(const Register& rd, const Register& rn, const Register& rm); 1094 1095 // Bit reverse. 1096 void rbit(const Register& rd, const Register& rn); 1097 1098 // Reverse bytes in 16-bit half words. 1099 void rev16(const Register& rd, const Register& rn); 1100 1101 // Reverse bytes in 32-bit words. 1102 void rev32(const Register& rd, const Register& rn); 1103 1104 // Reverse bytes. 1105 void rev(const Register& rd, const Register& rn); 1106 1107 // Count leading zeroes. 1108 void clz(const Register& rd, const Register& rn); 1109 1110 // Count leading sign bits. 1111 void cls(const Register& rd, const Register& rn); 1112 1113 // Memory instructions. 1114 // Load integer or FP register. 1115 void ldr(const CPURegister& rt, const MemOperand& src); 1116 1117 // Store integer or FP register. 1118 void str(const CPURegister& rt, const MemOperand& dst); 1119 1120 // Load word with sign extension. 1121 void ldrsw(const Register& rt, const MemOperand& src); 1122 1123 // Load byte. 1124 void ldrb(const Register& rt, const MemOperand& src); 1125 1126 // Store byte. 1127 void strb(const Register& rt, const MemOperand& dst); 1128 1129 // Load byte with sign extension. 1130 void ldrsb(const Register& rt, const MemOperand& src); 1131 1132 // Load half-word. 1133 void ldrh(const Register& rt, const MemOperand& src); 1134 1135 // Store half-word. 1136 void strh(const Register& rt, const MemOperand& dst); 1137 1138 // Load half-word with sign extension. 1139 void ldrsh(const Register& rt, const MemOperand& src); 1140 1141 // Load integer or FP register pair. 1142 void ldp(const CPURegister& rt, const CPURegister& rt2, 1143 const MemOperand& src); 1144 1145 // Store integer or FP register pair. 1146 void stp(const CPURegister& rt, const CPURegister& rt2, 1147 const MemOperand& dst); 1148 1149 // Load word pair with sign extension. 1150 void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src); 1151 1152 // Load integer or FP register pair, non-temporal. 1153 void ldnp(const CPURegister& rt, const CPURegister& rt2, 1154 const MemOperand& src); 1155 1156 // Store integer or FP register pair, non-temporal. 1157 void stnp(const CPURegister& rt, const CPURegister& rt2, 1158 const MemOperand& dst); 1159 1160 // Load literal to register. 1161 void ldr(const Register& rt, uint64_t imm); 1162 1163 // Load double precision floating point literal to FP register. 1164 void ldr(const FPRegister& ft, double imm); 1165 1166 // Load single precision floating point literal to FP register. 1167 void ldr(const FPRegister& ft, float imm); 1168 1169 // Move instructions. The default shift of -1 indicates that the move 1170 // instruction will calculate an appropriate 16-bit immediate and left shift 1171 // that is equal to the 64-bit immediate argument. If an explicit left shift 1172 // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value. 1173 // 1174 // For movk, an explicit shift can be used to indicate which half word should 1175 // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant 1176 // half word with zero, whereas movk(x0, 0, 48) will overwrite the 1177 // most-significant. 1178 1179 // Move immediate and keep. 1180 void movk(const Register& rd, uint64_t imm, int shift = -1) { 1181 MoveWide(rd, imm, shift, MOVK); 1182 } 1183 1184 // Move inverted immediate. 1185 void movn(const Register& rd, uint64_t imm, int shift = -1) { 1186 MoveWide(rd, imm, shift, MOVN); 1187 } 1188 1189 // Move immediate. 1190 void movz(const Register& rd, uint64_t imm, int shift = -1) { 1191 MoveWide(rd, imm, shift, MOVZ); 1192 } 1193 1194 // Misc instructions. 1195 // Monitor debug-mode breakpoint. 1196 void brk(int code); 1197 1198 // Halting debug-mode breakpoint. 1199 void hlt(int code); 1200 1201 // Move register to register. 1202 void mov(const Register& rd, const Register& rn); 1203 1204 // Move inverted operand to register. 1205 void mvn(const Register& rd, const Operand& operand); 1206 1207 // System instructions. 1208 // Move to register from system register. 1209 void mrs(const Register& rt, SystemRegister sysreg); 1210 1211 // Move from register to system register. 1212 void msr(SystemRegister sysreg, const Register& rt); 1213 1214 // System hint. 1215 void hint(SystemHint code); 1216 1217 // Data memory barrier. 1218 void dmb(BarrierDomain domain, BarrierType type); 1219 1220 // Data synchronization barrier. 1221 void dsb(BarrierDomain domain, BarrierType type); 1222 1223 // Instruction synchronization barrier. 1224 void isb(); 1225 1226 // Alias for system instructions. 1227 // No-op. nop()1228 void nop() { 1229 hint(NOP); 1230 } 1231 1232 // FP instructions. 1233 // Move double precision immediate to FP register. 1234 void fmov(const FPRegister& fd, double imm); 1235 1236 // Move single precision immediate to FP register. 1237 void fmov(const FPRegister& fd, float imm); 1238 1239 // Move FP register to register. 1240 void fmov(const Register& rd, const FPRegister& fn); 1241 1242 // Move register to FP register. 1243 void fmov(const FPRegister& fd, const Register& rn); 1244 1245 // Move FP register to FP register. 1246 void fmov(const FPRegister& fd, const FPRegister& fn); 1247 1248 // FP add. 1249 void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1250 1251 // FP subtract. 1252 void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1253 1254 // FP multiply. 1255 void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1256 1257 // FP fused multiply and add. 1258 void fmadd(const FPRegister& fd, 1259 const FPRegister& fn, 1260 const FPRegister& fm, 1261 const FPRegister& fa); 1262 1263 // FP fused multiply and subtract. 1264 void fmsub(const FPRegister& fd, 1265 const FPRegister& fn, 1266 const FPRegister& fm, 1267 const FPRegister& fa); 1268 1269 // FP fused multiply, add and negate. 1270 void fnmadd(const FPRegister& fd, 1271 const FPRegister& fn, 1272 const FPRegister& fm, 1273 const FPRegister& fa); 1274 1275 // FP fused multiply, subtract and negate. 1276 void fnmsub(const FPRegister& fd, 1277 const FPRegister& fn, 1278 const FPRegister& fm, 1279 const FPRegister& fa); 1280 1281 // FP divide. 1282 void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1283 1284 // FP maximum. 1285 void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1286 1287 // FP minimum. 1288 void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1289 1290 // FP maximum number. 1291 void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1292 1293 // FP minimum number. 1294 void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1295 1296 // FP absolute. 1297 void fabs(const FPRegister& fd, const FPRegister& fn); 1298 1299 // FP negate. 1300 void fneg(const FPRegister& fd, const FPRegister& fn); 1301 1302 // FP square root. 1303 void fsqrt(const FPRegister& fd, const FPRegister& fn); 1304 1305 // FP round to integer (nearest with ties to away). 1306 void frinta(const FPRegister& fd, const FPRegister& fn); 1307 1308 // FP round to integer (toward minus infinity). 1309 void frintm(const FPRegister& fd, const FPRegister& fn); 1310 1311 // FP round to integer (nearest with ties to even). 1312 void frintn(const FPRegister& fd, const FPRegister& fn); 1313 1314 // FP round to integer (towards zero). 1315 void frintz(const FPRegister& fd, const FPRegister& fn); 1316 1317 // FP compare registers. 1318 void fcmp(const FPRegister& fn, const FPRegister& fm); 1319 1320 // FP compare immediate. 1321 void fcmp(const FPRegister& fn, double value); 1322 1323 // FP conditional compare. 1324 void fccmp(const FPRegister& fn, 1325 const FPRegister& fm, 1326 StatusFlags nzcv, 1327 Condition cond); 1328 1329 // FP conditional select. 1330 void fcsel(const FPRegister& fd, 1331 const FPRegister& fn, 1332 const FPRegister& fm, 1333 Condition cond); 1334 1335 // Common FP Convert function. 1336 void FPConvertToInt(const Register& rd, 1337 const FPRegister& fn, 1338 FPIntegerConvertOp op); 1339 1340 // FP convert between single and double precision. 1341 void fcvt(const FPRegister& fd, const FPRegister& fn); 1342 1343 // Convert FP to signed integer (nearest with ties to away). 1344 void fcvtas(const Register& rd, const FPRegister& fn); 1345 1346 // Convert FP to unsigned integer (nearest with ties to away). 1347 void fcvtau(const Register& rd, const FPRegister& fn); 1348 1349 // Convert FP to signed integer (round towards -infinity). 1350 void fcvtms(const Register& rd, const FPRegister& fn); 1351 1352 // Convert FP to unsigned integer (round towards -infinity). 1353 void fcvtmu(const Register& rd, const FPRegister& fn); 1354 1355 // Convert FP to signed integer (nearest with ties to even). 1356 void fcvtns(const Register& rd, const FPRegister& fn); 1357 1358 // Convert FP to unsigned integer (nearest with ties to even). 1359 void fcvtnu(const Register& rd, const FPRegister& fn); 1360 1361 // Convert FP to signed integer (round towards zero). 1362 void fcvtzs(const Register& rd, const FPRegister& fn); 1363 1364 // Convert FP to unsigned integer (round towards zero). 1365 void fcvtzu(const Register& rd, const FPRegister& fn); 1366 1367 // Convert signed integer or fixed point to FP. 1368 void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); 1369 1370 // Convert unsigned integer or fixed point to FP. 1371 void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); 1372 1373 // Emit generic instructions. 1374 // Emit raw instructions into the instruction stream. dci(Instr raw_inst)1375 inline void dci(Instr raw_inst) { Emit(raw_inst); } 1376 1377 // Emit 32 bits of data into the instruction stream. dc32(uint32_t data)1378 inline void dc32(uint32_t data) { EmitData(&data, sizeof(data)); } 1379 1380 // Emit 64 bits of data into the instruction stream. dc64(uint64_t data)1381 inline void dc64(uint64_t data) { EmitData(&data, sizeof(data)); } 1382 1383 // Copy a string into the instruction stream, including the terminating NULL 1384 // character. The instruction pointer (pc_) is then aligned correctly for 1385 // subsequent instructions. EmitStringData(const char * string)1386 void EmitStringData(const char * string) { 1387 VIXL_ASSERT(string != NULL); 1388 1389 size_t len = strlen(string) + 1; 1390 EmitData(string, len); 1391 1392 // Pad with NULL characters until pc_ is aligned. 1393 const char pad[] = {'\0', '\0', '\0', '\0'}; 1394 VIXL_STATIC_ASSERT(sizeof(pad) == kInstructionSize); 1395 Instruction* next_pc = AlignUp(pc_, kInstructionSize); 1396 EmitData(&pad, next_pc - pc_); 1397 } 1398 1399 // Code generation helpers. 1400 1401 // Register encoding. Rd(CPURegister rd)1402 static Instr Rd(CPURegister rd) { 1403 VIXL_ASSERT(rd.code() != kSPRegInternalCode); 1404 return rd.code() << Rd_offset; 1405 } 1406 Rn(CPURegister rn)1407 static Instr Rn(CPURegister rn) { 1408 VIXL_ASSERT(rn.code() != kSPRegInternalCode); 1409 return rn.code() << Rn_offset; 1410 } 1411 Rm(CPURegister rm)1412 static Instr Rm(CPURegister rm) { 1413 VIXL_ASSERT(rm.code() != kSPRegInternalCode); 1414 return rm.code() << Rm_offset; 1415 } 1416 Ra(CPURegister ra)1417 static Instr Ra(CPURegister ra) { 1418 VIXL_ASSERT(ra.code() != kSPRegInternalCode); 1419 return ra.code() << Ra_offset; 1420 } 1421 Rt(CPURegister rt)1422 static Instr Rt(CPURegister rt) { 1423 VIXL_ASSERT(rt.code() != kSPRegInternalCode); 1424 return rt.code() << Rt_offset; 1425 } 1426 Rt2(CPURegister rt2)1427 static Instr Rt2(CPURegister rt2) { 1428 VIXL_ASSERT(rt2.code() != kSPRegInternalCode); 1429 return rt2.code() << Rt2_offset; 1430 } 1431 1432 // These encoding functions allow the stack pointer to be encoded, and 1433 // disallow the zero register. RdSP(Register rd)1434 static Instr RdSP(Register rd) { 1435 VIXL_ASSERT(!rd.IsZero()); 1436 return (rd.code() & kRegCodeMask) << Rd_offset; 1437 } 1438 RnSP(Register rn)1439 static Instr RnSP(Register rn) { 1440 VIXL_ASSERT(!rn.IsZero()); 1441 return (rn.code() & kRegCodeMask) << Rn_offset; 1442 } 1443 1444 // Flags encoding. Flags(FlagsUpdate S)1445 static Instr Flags(FlagsUpdate S) { 1446 if (S == SetFlags) { 1447 return 1 << FlagsUpdate_offset; 1448 } else if (S == LeaveFlags) { 1449 return 0 << FlagsUpdate_offset; 1450 } 1451 VIXL_UNREACHABLE(); 1452 return 0; 1453 } 1454 Cond(Condition cond)1455 static Instr Cond(Condition cond) { 1456 return cond << Condition_offset; 1457 } 1458 1459 // PC-relative address encoding. ImmPCRelAddress(int imm21)1460 static Instr ImmPCRelAddress(int imm21) { 1461 VIXL_ASSERT(is_int21(imm21)); 1462 Instr imm = static_cast<Instr>(truncate_to_int21(imm21)); 1463 Instr immhi = (imm >> ImmPCRelLo_width) << ImmPCRelHi_offset; 1464 Instr immlo = imm << ImmPCRelLo_offset; 1465 return (immhi & ImmPCRelHi_mask) | (immlo & ImmPCRelLo_mask); 1466 } 1467 1468 // Branch encoding. ImmUncondBranch(int imm26)1469 static Instr ImmUncondBranch(int imm26) { 1470 VIXL_ASSERT(is_int26(imm26)); 1471 return truncate_to_int26(imm26) << ImmUncondBranch_offset; 1472 } 1473 ImmCondBranch(int imm19)1474 static Instr ImmCondBranch(int imm19) { 1475 VIXL_ASSERT(is_int19(imm19)); 1476 return truncate_to_int19(imm19) << ImmCondBranch_offset; 1477 } 1478 ImmCmpBranch(int imm19)1479 static Instr ImmCmpBranch(int imm19) { 1480 VIXL_ASSERT(is_int19(imm19)); 1481 return truncate_to_int19(imm19) << ImmCmpBranch_offset; 1482 } 1483 ImmTestBranch(int imm14)1484 static Instr ImmTestBranch(int imm14) { 1485 VIXL_ASSERT(is_int14(imm14)); 1486 return truncate_to_int14(imm14) << ImmTestBranch_offset; 1487 } 1488 ImmTestBranchBit(unsigned bit_pos)1489 static Instr ImmTestBranchBit(unsigned bit_pos) { 1490 VIXL_ASSERT(is_uint6(bit_pos)); 1491 // Subtract five from the shift offset, as we need bit 5 from bit_pos. 1492 unsigned b5 = bit_pos << (ImmTestBranchBit5_offset - 5); 1493 unsigned b40 = bit_pos << ImmTestBranchBit40_offset; 1494 b5 &= ImmTestBranchBit5_mask; 1495 b40 &= ImmTestBranchBit40_mask; 1496 return b5 | b40; 1497 } 1498 1499 // Data Processing encoding. SF(Register rd)1500 static Instr SF(Register rd) { 1501 return rd.Is64Bits() ? SixtyFourBits : ThirtyTwoBits; 1502 } 1503 ImmAddSub(int64_t imm)1504 static Instr ImmAddSub(int64_t imm) { 1505 VIXL_ASSERT(IsImmAddSub(imm)); 1506 if (is_uint12(imm)) { // No shift required. 1507 return imm << ImmAddSub_offset; 1508 } else { 1509 return ((imm >> 12) << ImmAddSub_offset) | (1 << ShiftAddSub_offset); 1510 } 1511 } 1512 ImmS(unsigned imms,unsigned reg_size)1513 static inline Instr ImmS(unsigned imms, unsigned reg_size) { 1514 VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(imms)) || 1515 ((reg_size == kWRegSize) && is_uint5(imms))); 1516 USE(reg_size); 1517 return imms << ImmS_offset; 1518 } 1519 ImmR(unsigned immr,unsigned reg_size)1520 static inline Instr ImmR(unsigned immr, unsigned reg_size) { 1521 VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || 1522 ((reg_size == kWRegSize) && is_uint5(immr))); 1523 USE(reg_size); 1524 VIXL_ASSERT(is_uint6(immr)); 1525 return immr << ImmR_offset; 1526 } 1527 ImmSetBits(unsigned imms,unsigned reg_size)1528 static inline Instr ImmSetBits(unsigned imms, unsigned reg_size) { 1529 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); 1530 VIXL_ASSERT(is_uint6(imms)); 1531 VIXL_ASSERT((reg_size == kXRegSize) || is_uint6(imms + 3)); 1532 USE(reg_size); 1533 return imms << ImmSetBits_offset; 1534 } 1535 ImmRotate(unsigned immr,unsigned reg_size)1536 static inline Instr ImmRotate(unsigned immr, unsigned reg_size) { 1537 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); 1538 VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || 1539 ((reg_size == kWRegSize) && is_uint5(immr))); 1540 USE(reg_size); 1541 return immr << ImmRotate_offset; 1542 } 1543 ImmLLiteral(int imm19)1544 static inline Instr ImmLLiteral(int imm19) { 1545 VIXL_ASSERT(is_int19(imm19)); 1546 return truncate_to_int19(imm19) << ImmLLiteral_offset; 1547 } 1548 BitN(unsigned bitn,unsigned reg_size)1549 static inline Instr BitN(unsigned bitn, unsigned reg_size) { 1550 VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); 1551 VIXL_ASSERT((reg_size == kXRegSize) || (bitn == 0)); 1552 USE(reg_size); 1553 return bitn << BitN_offset; 1554 } 1555 ShiftDP(Shift shift)1556 static Instr ShiftDP(Shift shift) { 1557 VIXL_ASSERT(shift == LSL || shift == LSR || shift == ASR || shift == ROR); 1558 return shift << ShiftDP_offset; 1559 } 1560 ImmDPShift(unsigned amount)1561 static Instr ImmDPShift(unsigned amount) { 1562 VIXL_ASSERT(is_uint6(amount)); 1563 return amount << ImmDPShift_offset; 1564 } 1565 ExtendMode(Extend extend)1566 static Instr ExtendMode(Extend extend) { 1567 return extend << ExtendMode_offset; 1568 } 1569 ImmExtendShift(unsigned left_shift)1570 static Instr ImmExtendShift(unsigned left_shift) { 1571 VIXL_ASSERT(left_shift <= 4); 1572 return left_shift << ImmExtendShift_offset; 1573 } 1574 ImmCondCmp(unsigned imm)1575 static Instr ImmCondCmp(unsigned imm) { 1576 VIXL_ASSERT(is_uint5(imm)); 1577 return imm << ImmCondCmp_offset; 1578 } 1579 Nzcv(StatusFlags nzcv)1580 static Instr Nzcv(StatusFlags nzcv) { 1581 return ((nzcv >> Flags_offset) & 0xf) << Nzcv_offset; 1582 } 1583 1584 // MemOperand offset encoding. ImmLSUnsigned(int imm12)1585 static Instr ImmLSUnsigned(int imm12) { 1586 VIXL_ASSERT(is_uint12(imm12)); 1587 return imm12 << ImmLSUnsigned_offset; 1588 } 1589 ImmLS(int imm9)1590 static Instr ImmLS(int imm9) { 1591 VIXL_ASSERT(is_int9(imm9)); 1592 return truncate_to_int9(imm9) << ImmLS_offset; 1593 } 1594 ImmLSPair(int imm7,LSDataSize size)1595 static Instr ImmLSPair(int imm7, LSDataSize size) { 1596 VIXL_ASSERT(((imm7 >> size) << size) == imm7); 1597 int scaled_imm7 = imm7 >> size; 1598 VIXL_ASSERT(is_int7(scaled_imm7)); 1599 return truncate_to_int7(scaled_imm7) << ImmLSPair_offset; 1600 } 1601 ImmShiftLS(unsigned shift_amount)1602 static Instr ImmShiftLS(unsigned shift_amount) { 1603 VIXL_ASSERT(is_uint1(shift_amount)); 1604 return shift_amount << ImmShiftLS_offset; 1605 } 1606 ImmException(int imm16)1607 static Instr ImmException(int imm16) { 1608 VIXL_ASSERT(is_uint16(imm16)); 1609 return imm16 << ImmException_offset; 1610 } 1611 ImmSystemRegister(int imm15)1612 static Instr ImmSystemRegister(int imm15) { 1613 VIXL_ASSERT(is_uint15(imm15)); 1614 return imm15 << ImmSystemRegister_offset; 1615 } 1616 ImmHint(int imm7)1617 static Instr ImmHint(int imm7) { 1618 VIXL_ASSERT(is_uint7(imm7)); 1619 return imm7 << ImmHint_offset; 1620 } 1621 ImmBarrierDomain(int imm2)1622 static Instr ImmBarrierDomain(int imm2) { 1623 VIXL_ASSERT(is_uint2(imm2)); 1624 return imm2 << ImmBarrierDomain_offset; 1625 } 1626 ImmBarrierType(int imm2)1627 static Instr ImmBarrierType(int imm2) { 1628 VIXL_ASSERT(is_uint2(imm2)); 1629 return imm2 << ImmBarrierType_offset; 1630 } 1631 CalcLSDataSize(LoadStoreOp op)1632 static LSDataSize CalcLSDataSize(LoadStoreOp op) { 1633 VIXL_ASSERT((SizeLS_offset + SizeLS_width) == (kInstructionSize * 8)); 1634 return static_cast<LSDataSize>(op >> SizeLS_offset); 1635 } 1636 1637 // Move immediates encoding. ImmMoveWide(uint64_t imm)1638 static Instr ImmMoveWide(uint64_t imm) { 1639 VIXL_ASSERT(is_uint16(imm)); 1640 return imm << ImmMoveWide_offset; 1641 } 1642 ShiftMoveWide(int64_t shift)1643 static Instr ShiftMoveWide(int64_t shift) { 1644 VIXL_ASSERT(is_uint2(shift)); 1645 return shift << ShiftMoveWide_offset; 1646 } 1647 1648 // FP Immediates. 1649 static Instr ImmFP32(float imm); 1650 static Instr ImmFP64(double imm); 1651 1652 // FP register type. FPType(FPRegister fd)1653 static Instr FPType(FPRegister fd) { 1654 return fd.Is64Bits() ? FP64 : FP32; 1655 } 1656 FPScale(unsigned scale)1657 static Instr FPScale(unsigned scale) { 1658 VIXL_ASSERT(is_uint6(scale)); 1659 return scale << FPScale_offset; 1660 } 1661 1662 // Size of the code generated in bytes SizeOfCodeGenerated()1663 uint64_t SizeOfCodeGenerated() const { 1664 VIXL_ASSERT((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_))); 1665 return pc_ - buffer_; 1666 } 1667 1668 // Size of the code generated since label to the current position. SizeOfCodeGeneratedSince(Label * label)1669 uint64_t SizeOfCodeGeneratedSince(Label* label) const { 1670 VIXL_ASSERT(label->IsBound()); 1671 VIXL_ASSERT((pc_ >= label->target()) && (pc_ < (buffer_ + buffer_size_))); 1672 return pc_ - label->target(); 1673 } 1674 1675 BlockLiteralPool()1676 inline void BlockLiteralPool() { 1677 literal_pool_monitor_++; 1678 } 1679 ReleaseLiteralPool()1680 inline void ReleaseLiteralPool() { 1681 if (--literal_pool_monitor_ == 0) { 1682 // Has the literal pool been blocked for too long? 1683 VIXL_ASSERT(literals_.empty() || 1684 (pc_ < (literals_.back()->pc_ + kMaxLoadLiteralRange))); 1685 } 1686 } 1687 IsLiteralPoolBlocked()1688 inline bool IsLiteralPoolBlocked() { 1689 return literal_pool_monitor_ != 0; 1690 } 1691 1692 void CheckLiteralPool(LiteralPoolEmitOption option = JumpRequired); 1693 void EmitLiteralPool(LiteralPoolEmitOption option = NoJumpRequired); 1694 size_t LiteralPoolSize(); 1695 1696 protected: AppropriateZeroRegFor(const CPURegister & reg)1697 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const { 1698 return reg.Is64Bits() ? xzr : wzr; 1699 } 1700 1701 1702 void LoadStore(const CPURegister& rt, 1703 const MemOperand& addr, 1704 LoadStoreOp op); 1705 static bool IsImmLSUnscaled(ptrdiff_t offset); 1706 static bool IsImmLSScaled(ptrdiff_t offset, LSDataSize size); 1707 1708 void Logical(const Register& rd, 1709 const Register& rn, 1710 const Operand& operand, 1711 LogicalOp op); 1712 void LogicalImmediate(const Register& rd, 1713 const Register& rn, 1714 unsigned n, 1715 unsigned imm_s, 1716 unsigned imm_r, 1717 LogicalOp op); 1718 static bool IsImmLogical(uint64_t value, 1719 unsigned width, 1720 unsigned* n, 1721 unsigned* imm_s, 1722 unsigned* imm_r); 1723 1724 void ConditionalCompare(const Register& rn, 1725 const Operand& operand, 1726 StatusFlags nzcv, 1727 Condition cond, 1728 ConditionalCompareOp op); 1729 static bool IsImmConditionalCompare(int64_t immediate); 1730 1731 void AddSubWithCarry(const Register& rd, 1732 const Register& rn, 1733 const Operand& operand, 1734 FlagsUpdate S, 1735 AddSubWithCarryOp op); 1736 1737 static bool IsImmFP32(float imm); 1738 static bool IsImmFP64(double imm); 1739 1740 // Functions for emulating operands not directly supported by the instruction 1741 // set. 1742 void EmitShift(const Register& rd, 1743 const Register& rn, 1744 Shift shift, 1745 unsigned amount); 1746 void EmitExtendShift(const Register& rd, 1747 const Register& rn, 1748 Extend extend, 1749 unsigned left_shift); 1750 1751 void AddSub(const Register& rd, 1752 const Register& rn, 1753 const Operand& operand, 1754 FlagsUpdate S, 1755 AddSubOp op); 1756 static bool IsImmAddSub(int64_t immediate); 1757 1758 // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified 1759 // registers. Only simple loads are supported; sign- and zero-extension (such 1760 // as in LDPSW_x or LDRB_w) are not supported. 1761 static LoadStoreOp LoadOpFor(const CPURegister& rt); 1762 static LoadStorePairOp LoadPairOpFor(const CPURegister& rt, 1763 const CPURegister& rt2); 1764 static LoadStoreOp StoreOpFor(const CPURegister& rt); 1765 static LoadStorePairOp StorePairOpFor(const CPURegister& rt, 1766 const CPURegister& rt2); 1767 static LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor( 1768 const CPURegister& rt, const CPURegister& rt2); 1769 static LoadStorePairNonTemporalOp StorePairNonTemporalOpFor( 1770 const CPURegister& rt, const CPURegister& rt2); 1771 1772 1773 private: 1774 // Instruction helpers. 1775 void MoveWide(const Register& rd, 1776 uint64_t imm, 1777 int shift, 1778 MoveWideImmediateOp mov_op); 1779 void DataProcShiftedRegister(const Register& rd, 1780 const Register& rn, 1781 const Operand& operand, 1782 FlagsUpdate S, 1783 Instr op); 1784 void DataProcExtendedRegister(const Register& rd, 1785 const Register& rn, 1786 const Operand& operand, 1787 FlagsUpdate S, 1788 Instr op); 1789 void LoadStorePair(const CPURegister& rt, 1790 const CPURegister& rt2, 1791 const MemOperand& addr, 1792 LoadStorePairOp op); 1793 void LoadStorePairNonTemporal(const CPURegister& rt, 1794 const CPURegister& rt2, 1795 const MemOperand& addr, 1796 LoadStorePairNonTemporalOp op); 1797 void LoadLiteral(const CPURegister& rt, uint64_t imm, LoadLiteralOp op); 1798 void ConditionalSelect(const Register& rd, 1799 const Register& rn, 1800 const Register& rm, 1801 Condition cond, 1802 ConditionalSelectOp op); 1803 void DataProcessing1Source(const Register& rd, 1804 const Register& rn, 1805 DataProcessing1SourceOp op); 1806 void DataProcessing3Source(const Register& rd, 1807 const Register& rn, 1808 const Register& rm, 1809 const Register& ra, 1810 DataProcessing3SourceOp op); 1811 void FPDataProcessing1Source(const FPRegister& fd, 1812 const FPRegister& fn, 1813 FPDataProcessing1SourceOp op); 1814 void FPDataProcessing2Source(const FPRegister& fd, 1815 const FPRegister& fn, 1816 const FPRegister& fm, 1817 FPDataProcessing2SourceOp op); 1818 void FPDataProcessing3Source(const FPRegister& fd, 1819 const FPRegister& fn, 1820 const FPRegister& fm, 1821 const FPRegister& fa, 1822 FPDataProcessing3SourceOp op); 1823 1824 void RecordLiteral(int64_t imm, unsigned size); 1825 1826 // Emit the instruction at pc_. Emit(Instr instruction)1827 void Emit(Instr instruction) { 1828 VIXL_STATIC_ASSERT(sizeof(*pc_) == 1); 1829 VIXL_STATIC_ASSERT(sizeof(instruction) == kInstructionSize); 1830 VIXL_ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_)); 1831 1832 #ifdef DEBUG 1833 finalized_ = false; 1834 #endif 1835 1836 memcpy(pc_, &instruction, sizeof(instruction)); 1837 pc_ += sizeof(instruction); 1838 CheckBufferSpace(); 1839 } 1840 1841 // Emit data inline in the instruction stream. EmitData(void const * data,unsigned size)1842 void EmitData(void const * data, unsigned size) { 1843 VIXL_STATIC_ASSERT(sizeof(*pc_) == 1); 1844 VIXL_ASSERT((pc_ + size) <= (buffer_ + buffer_size_)); 1845 1846 #ifdef DEBUG 1847 finalized_ = false; 1848 #endif 1849 1850 // TODO: Record this 'instruction' as data, so that it can be disassembled 1851 // correctly. 1852 memcpy(pc_, data, size); 1853 pc_ += size; 1854 CheckBufferSpace(); 1855 } 1856 CheckBufferSpace()1857 inline void CheckBufferSpace() { 1858 VIXL_ASSERT(pc_ < (buffer_ + buffer_size_)); 1859 if (pc_ > next_literal_pool_check_) { 1860 CheckLiteralPool(); 1861 } 1862 } 1863 1864 // The buffer into which code and relocation info are generated. 1865 Instruction* buffer_; 1866 // Buffer size, in bytes. 1867 unsigned buffer_size_; 1868 Instruction* pc_; 1869 std::list<Literal*> literals_; 1870 Instruction* next_literal_pool_check_; 1871 unsigned literal_pool_monitor_; 1872 1873 friend class BlockLiteralPoolScope; 1874 1875 #ifdef DEBUG 1876 bool finalized_; 1877 #endif 1878 }; 1879 1880 class BlockLiteralPoolScope { 1881 public: BlockLiteralPoolScope(Assembler * assm)1882 explicit BlockLiteralPoolScope(Assembler* assm) : assm_(assm) { 1883 assm_->BlockLiteralPool(); 1884 } 1885 ~BlockLiteralPoolScope()1886 ~BlockLiteralPoolScope() { 1887 assm_->ReleaseLiteralPool(); 1888 } 1889 1890 private: 1891 Assembler* assm_; 1892 }; 1893 } // namespace vixl 1894 1895 #endif // VIXL_A64_ASSEMBLER_A64_H_ 1896