1 // Copyright 2015, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifndef VIXL_AARCH64_MACRO_ASSEMBLER_AARCH64_H_ 28 #define VIXL_AARCH64_MACRO_ASSEMBLER_AARCH64_H_ 29 30 #include <algorithm> 31 #include <limits> 32 33 #include "../code-generation-scopes-vixl.h" 34 #include "../globals-vixl.h" 35 #include "../macro-assembler-interface.h" 36 37 #include "assembler-aarch64.h" 38 #include "debugger-aarch64.h" 39 #include "instrument-aarch64.h" 40 // Required in order to generate debugging instructions for the simulator. This 41 // is needed regardless of whether the simulator is included or not, since 42 // generating simulator specific instructions is controlled at runtime. 43 #include "simulator-constants-aarch64.h" 44 45 46 #define LS_MACRO_LIST(V) \ 47 V(Ldrb, Register&, rt, LDRB_w) \ 48 V(Strb, Register&, rt, STRB_w) \ 49 V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w) \ 50 V(Ldrh, Register&, rt, LDRH_w) \ 51 V(Strh, Register&, rt, STRH_w) \ 52 V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w) \ 53 V(Ldr, CPURegister&, rt, LoadOpFor(rt)) \ 54 V(Str, CPURegister&, rt, StoreOpFor(rt)) \ 55 V(Ldrsw, Register&, rt, LDRSW_x) 56 57 58 #define LSPAIR_MACRO_LIST(V) \ 59 V(Ldp, CPURegister&, rt, rt2, LoadPairOpFor(rt, rt2)) \ 60 V(Stp, CPURegister&, rt, rt2, StorePairOpFor(rt, rt2)) \ 61 V(Ldpsw, CPURegister&, rt, rt2, LDPSW_x) 62 63 namespace vixl { 64 namespace aarch64 { 65 66 // Forward declaration 67 class MacroAssembler; 68 class UseScratchRegisterScope; 69 70 class Pool { 71 public: 72 explicit Pool(MacroAssembler* masm) 73 : checkpoint_(kNoCheckpointRequired), masm_(masm) { 74 Reset(); 75 } 76 77 void Reset() { 78 checkpoint_ = kNoCheckpointRequired; 79 monitor_ = 0; 80 } 81 82 void Block() { monitor_++; } 83 void Release(); 84 bool IsBlocked() const { return monitor_ != 0; } 85 86 static const ptrdiff_t kNoCheckpointRequired = PTRDIFF_MAX; 87 88 void SetNextCheckpoint(ptrdiff_t checkpoint); 89 ptrdiff_t GetCheckpoint() const { return checkpoint_; } 90 VIXL_DEPRECATED("GetCheckpoint", ptrdiff_t checkpoint() const) { 91 return GetCheckpoint(); 92 } 93 94 enum EmitOption { kBranchRequired, kNoBranchRequired }; 95 96 protected: 97 // Next buffer offset at which a check is required for this pool. 98 ptrdiff_t checkpoint_; 99 // Indicates whether the emission of this pool is blocked. 100 int monitor_; 101 // The MacroAssembler using this pool. 102 MacroAssembler* masm_; 103 }; 104 105 106 class LiteralPool : public Pool { 107 public: 108 explicit LiteralPool(MacroAssembler* masm); 109 ~LiteralPool(); 110 void Reset(); 111 112 void AddEntry(RawLiteral* literal); 113 bool IsEmpty() const { return entries_.empty(); } 114 size_t GetSize() const; 115 VIXL_DEPRECATED("GetSize", size_t Size() const) { return GetSize(); } 116 117 size_t GetMaxSize() const; 118 VIXL_DEPRECATED("GetMaxSize", size_t MaxSize() const) { return GetMaxSize(); } 119 120 size_t GetOtherPoolsMaxSize() const; 121 VIXL_DEPRECATED("GetOtherPoolsMaxSize", size_t OtherPoolsMaxSize() const) { 122 return GetOtherPoolsMaxSize(); 123 } 124 125 void CheckEmitFor(size_t amount, EmitOption option = kBranchRequired); 126 void Emit(EmitOption option = kNoBranchRequired); 127 128 void SetNextRecommendedCheckpoint(ptrdiff_t offset); 129 ptrdiff_t GetNextRecommendedCheckpoint(); 130 VIXL_DEPRECATED("GetNextRecommendedCheckpoint", 131 ptrdiff_t NextRecommendedCheckpoint()) { 132 return GetNextRecommendedCheckpoint(); 133 } 134 135 void UpdateFirstUse(ptrdiff_t use_position); 136 137 void DeleteOnDestruction(RawLiteral* literal) { 138 deleted_on_destruction_.push_back(literal); 139 } 140 141 // Recommended not exact since the pool can be blocked for short periods. 142 static const ptrdiff_t kRecommendedLiteralPoolRange = 128 * KBytes; 143 144 private: 145 std::vector<RawLiteral*> entries_; 146 size_t size_; 147 ptrdiff_t first_use_; 148 // The parent class `Pool` provides a `checkpoint_`, which is the buffer 149 // offset before which a check *must* occur. This recommended checkpoint 150 // indicates when we would like to start emitting the constant pool. The 151 // MacroAssembler can, but does not have to, check the buffer when the 152 // checkpoint is reached. 153 ptrdiff_t recommended_checkpoint_; 154 155 std::vector<RawLiteral*> deleted_on_destruction_; 156 }; 157 158 159 inline size_t LiteralPool::GetSize() const { 160 // Account for the pool header. 161 return size_ + kInstructionSize; 162 } 163 164 165 inline size_t LiteralPool::GetMaxSize() const { 166 // Account for the potential branch over the pool. 167 return GetSize() + kInstructionSize; 168 } 169 170 171 inline ptrdiff_t LiteralPool::GetNextRecommendedCheckpoint() { 172 return first_use_ + kRecommendedLiteralPoolRange; 173 } 174 175 176 class VeneerPool : public Pool { 177 public: 178 explicit VeneerPool(MacroAssembler* masm) : Pool(masm) {} 179 180 void Reset(); 181 182 void Block() { monitor_++; } 183 void Release(); 184 bool IsBlocked() const { return monitor_ != 0; } 185 bool IsEmpty() const { return unresolved_branches_.IsEmpty(); } 186 187 class BranchInfo { 188 public: 189 BranchInfo() 190 : max_reachable_pc_(0), 191 pc_offset_(0), 192 label_(NULL), 193 branch_type_(UnknownBranchType) {} 194 BranchInfo(ptrdiff_t offset, Label* label, ImmBranchType branch_type) 195 : pc_offset_(offset), label_(label), branch_type_(branch_type) { 196 max_reachable_pc_ = 197 pc_offset_ + Instruction::GetImmBranchForwardRange(branch_type_); 198 } 199 200 static bool IsValidComparison(const BranchInfo& branch_1, 201 const BranchInfo& branch_2) { 202 // BranchInfo are always compared against against other objects with 203 // the same branch type. 204 if (branch_1.branch_type_ != branch_2.branch_type_) { 205 return false; 206 } 207 // Since we should never have two branch infos with the same offsets, it 208 // first looks like we should check that offsets are different. However 209 // the operators may also be used to *search* for a branch info in the 210 // set. 211 bool same_offsets = (branch_1.pc_offset_ == branch_2.pc_offset_); 212 return (!same_offsets || 213 ((branch_1.label_ == branch_2.label_) && 214 (branch_1.max_reachable_pc_ == branch_2.max_reachable_pc_))); 215 } 216 217 // We must provide comparison operators to work with InvalSet. 218 bool operator==(const BranchInfo& other) const { 219 VIXL_ASSERT(IsValidComparison(*this, other)); 220 return pc_offset_ == other.pc_offset_; 221 } 222 bool operator<(const BranchInfo& other) const { 223 VIXL_ASSERT(IsValidComparison(*this, other)); 224 return pc_offset_ < other.pc_offset_; 225 } 226 bool operator<=(const BranchInfo& other) const { 227 VIXL_ASSERT(IsValidComparison(*this, other)); 228 return pc_offset_ <= other.pc_offset_; 229 } 230 bool operator>(const BranchInfo& other) const { 231 VIXL_ASSERT(IsValidComparison(*this, other)); 232 return pc_offset_ > other.pc_offset_; 233 } 234 235 // Maximum position reachable by the branch using a positive branch offset. 236 ptrdiff_t max_reachable_pc_; 237 // Offset of the branch in the code generation buffer. 238 ptrdiff_t pc_offset_; 239 // The label branched to. 240 Label* label_; 241 ImmBranchType branch_type_; 242 }; 243 244 bool BranchTypeUsesVeneers(ImmBranchType type) { 245 return (type != UnknownBranchType) && (type != UncondBranchType); 246 } 247 248 void RegisterUnresolvedBranch(ptrdiff_t branch_pos, 249 Label* label, 250 ImmBranchType branch_type); 251 void DeleteUnresolvedBranchInfoForLabel(Label* label); 252 253 bool ShouldEmitVeneer(int64_t max_reachable_pc, size_t amount); 254 bool ShouldEmitVeneers(size_t amount) { 255 return ShouldEmitVeneer(unresolved_branches_.GetFirstLimit(), amount); 256 } 257 258 void CheckEmitFor(size_t amount, EmitOption option = kBranchRequired); 259 void Emit(EmitOption option, size_t margin); 260 261 // The code size generated for a veneer. Currently one branch instruction. 262 // This is for code size checking purposes, and can be extended in the future 263 // for example if we decide to add nops between the veneers. 264 static const int kVeneerCodeSize = 1 * kInstructionSize; 265 // The maximum size of code other than veneers that can be generated when 266 // emitting a veneer pool. Currently there can be an additional branch to jump 267 // over the pool. 268 static const int kPoolNonVeneerCodeSize = 1 * kInstructionSize; 269 270 void UpdateNextCheckPoint() { SetNextCheckpoint(GetNextCheckPoint()); } 271 272 int GetNumberOfPotentialVeneers() const { 273 return static_cast<int>(unresolved_branches_.GetSize()); 274 } 275 VIXL_DEPRECATED("GetNumberOfPotentialVeneers", 276 int NumberOfPotentialVeneers() const) { 277 return GetNumberOfPotentialVeneers(); 278 } 279 280 size_t GetMaxSize() const { 281 return kPoolNonVeneerCodeSize + 282 unresolved_branches_.GetSize() * kVeneerCodeSize; 283 } 284 VIXL_DEPRECATED("GetMaxSize", size_t MaxSize() const) { return GetMaxSize(); } 285 286 size_t GetOtherPoolsMaxSize() const; 287 VIXL_DEPRECATED("GetOtherPoolsMaxSize", size_t OtherPoolsMaxSize() const) { 288 return GetOtherPoolsMaxSize(); 289 } 290 291 static const int kNPreallocatedInfos = 4; 292 static const ptrdiff_t kInvalidOffset = PTRDIFF_MAX; 293 static const size_t kReclaimFrom = 128; 294 static const size_t kReclaimFactor = 16; 295 296 private: 297 typedef InvalSet<BranchInfo, 298 kNPreallocatedInfos, 299 ptrdiff_t, 300 kInvalidOffset, 301 kReclaimFrom, 302 kReclaimFactor> BranchInfoTypedSetBase; 303 typedef InvalSetIterator<BranchInfoTypedSetBase> BranchInfoTypedSetIterBase; 304 305 class BranchInfoTypedSet : public BranchInfoTypedSetBase { 306 public: 307 BranchInfoTypedSet() : BranchInfoTypedSetBase() {} 308 309 ptrdiff_t GetFirstLimit() { 310 if (empty()) { 311 return kInvalidOffset; 312 } 313 return GetMinElementKey(); 314 } 315 VIXL_DEPRECATED("GetFirstLimit", ptrdiff_t FirstLimit()) { 316 return GetFirstLimit(); 317 } 318 }; 319 320 class BranchInfoTypedSetIterator : public BranchInfoTypedSetIterBase { 321 public: 322 BranchInfoTypedSetIterator() : BranchInfoTypedSetIterBase(NULL) {} 323 explicit BranchInfoTypedSetIterator(BranchInfoTypedSet* typed_set) 324 : BranchInfoTypedSetIterBase(typed_set) {} 325 326 // TODO: Remove these and use the STL-like interface instead. 327 using BranchInfoTypedSetIterBase::Advance; 328 using BranchInfoTypedSetIterBase::Current; 329 }; 330 331 class BranchInfoSet { 332 public: 333 void insert(BranchInfo branch_info) { 334 ImmBranchType type = branch_info.branch_type_; 335 VIXL_ASSERT(IsValidBranchType(type)); 336 typed_set_[BranchIndexFromType(type)].insert(branch_info); 337 } 338 339 void erase(BranchInfo branch_info) { 340 if (IsValidBranchType(branch_info.branch_type_)) { 341 int index = 342 BranchInfoSet::BranchIndexFromType(branch_info.branch_type_); 343 typed_set_[index].erase(branch_info); 344 } 345 } 346 347 size_t GetSize() const { 348 size_t res = 0; 349 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) { 350 res += typed_set_[i].size(); 351 } 352 return res; 353 } 354 VIXL_DEPRECATED("GetSize", size_t size() const) { return GetSize(); } 355 356 bool IsEmpty() const { 357 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) { 358 if (!typed_set_[i].empty()) { 359 return false; 360 } 361 } 362 return true; 363 } 364 VIXL_DEPRECATED("IsEmpty", bool empty() const) { return IsEmpty(); } 365 366 ptrdiff_t GetFirstLimit() { 367 ptrdiff_t res = kInvalidOffset; 368 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) { 369 res = std::min(res, typed_set_[i].GetFirstLimit()); 370 } 371 return res; 372 } 373 VIXL_DEPRECATED("GetFirstLimit", ptrdiff_t FirstLimit()) { 374 return GetFirstLimit(); 375 } 376 377 void Reset() { 378 for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) { 379 typed_set_[i].clear(); 380 } 381 } 382 383 static ImmBranchType BranchTypeFromIndex(int index) { 384 switch (index) { 385 case 0: 386 return CondBranchType; 387 case 1: 388 return CompareBranchType; 389 case 2: 390 return TestBranchType; 391 default: 392 VIXL_UNREACHABLE(); 393 return UnknownBranchType; 394 } 395 } 396 static int BranchIndexFromType(ImmBranchType branch_type) { 397 switch (branch_type) { 398 case CondBranchType: 399 return 0; 400 case CompareBranchType: 401 return 1; 402 case TestBranchType: 403 return 2; 404 default: 405 VIXL_UNREACHABLE(); 406 return 0; 407 } 408 } 409 410 bool IsValidBranchType(ImmBranchType branch_type) { 411 return (branch_type != UnknownBranchType) && 412 (branch_type != UncondBranchType); 413 } 414 415 private: 416 static const int kNumberOfTrackedBranchTypes = 3; 417 BranchInfoTypedSet typed_set_[kNumberOfTrackedBranchTypes]; 418 419 friend class VeneerPool; 420 friend class BranchInfoSetIterator; 421 }; 422 423 class BranchInfoSetIterator { 424 public: 425 explicit BranchInfoSetIterator(BranchInfoSet* set) : set_(set) { 426 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) { 427 new (&sub_iterator_[i]) 428 BranchInfoTypedSetIterator(&(set_->typed_set_[i])); 429 } 430 } 431 432 VeneerPool::BranchInfo* Current() { 433 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) { 434 if (!sub_iterator_[i].Done()) { 435 return sub_iterator_[i].Current(); 436 } 437 } 438 VIXL_UNREACHABLE(); 439 return NULL; 440 } 441 442 void Advance() { 443 VIXL_ASSERT(!Done()); 444 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) { 445 if (!sub_iterator_[i].Done()) { 446 sub_iterator_[i].Advance(); 447 return; 448 } 449 } 450 VIXL_UNREACHABLE(); 451 } 452 453 bool Done() const { 454 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) { 455 if (!sub_iterator_[i].Done()) return false; 456 } 457 return true; 458 } 459 460 void AdvanceToNextType() { 461 VIXL_ASSERT(!Done()); 462 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) { 463 if (!sub_iterator_[i].Done()) { 464 sub_iterator_[i].Finish(); 465 return; 466 } 467 } 468 VIXL_UNREACHABLE(); 469 } 470 471 void DeleteCurrentAndAdvance() { 472 for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) { 473 if (!sub_iterator_[i].Done()) { 474 sub_iterator_[i].DeleteCurrentAndAdvance(); 475 return; 476 } 477 } 478 } 479 480 private: 481 BranchInfoSet* set_; 482 BranchInfoTypedSetIterator 483 sub_iterator_[BranchInfoSet::kNumberOfTrackedBranchTypes]; 484 }; 485 486 ptrdiff_t GetNextCheckPoint() { 487 if (unresolved_branches_.IsEmpty()) { 488 return kNoCheckpointRequired; 489 } else { 490 return unresolved_branches_.GetFirstLimit(); 491 } 492 } 493 VIXL_DEPRECATED("GetNextCheckPoint", ptrdiff_t NextCheckPoint()) { 494 return GetNextCheckPoint(); 495 } 496 497 // Information about unresolved (forward) branches. 498 BranchInfoSet unresolved_branches_; 499 }; 500 501 502 // Helper for common Emission checks. 503 // The macro-instruction maps to a single instruction. 504 class SingleEmissionCheckScope : public EmissionCheckScope { 505 public: 506 explicit SingleEmissionCheckScope(MacroAssemblerInterface* masm) 507 : EmissionCheckScope(masm, kInstructionSize) {} 508 }; 509 510 511 // The macro instruction is a "typical" macro-instruction. Typical macro- 512 // instruction only emit a few instructions, a few being defined as 8 here. 513 class MacroEmissionCheckScope : public EmissionCheckScope { 514 public: 515 explicit MacroEmissionCheckScope(MacroAssemblerInterface* masm) 516 : EmissionCheckScope(masm, kTypicalMacroInstructionMaxSize) {} 517 518 private: 519 static const size_t kTypicalMacroInstructionMaxSize = 8 * kInstructionSize; 520 }; 521 522 523 enum BranchType { 524 // Copies of architectural conditions. 525 // The associated conditions can be used in place of those, the code will 526 // take care of reinterpreting them with the correct type. 527 integer_eq = eq, 528 integer_ne = ne, 529 integer_hs = hs, 530 integer_lo = lo, 531 integer_mi = mi, 532 integer_pl = pl, 533 integer_vs = vs, 534 integer_vc = vc, 535 integer_hi = hi, 536 integer_ls = ls, 537 integer_ge = ge, 538 integer_lt = lt, 539 integer_gt = gt, 540 integer_le = le, 541 integer_al = al, 542 integer_nv = nv, 543 544 // These two are *different* from the architectural codes al and nv. 545 // 'always' is used to generate unconditional branches. 546 // 'never' is used to not generate a branch (generally as the inverse 547 // branch type of 'always). 548 always, 549 never, 550 // cbz and cbnz 551 reg_zero, 552 reg_not_zero, 553 // tbz and tbnz 554 reg_bit_clear, 555 reg_bit_set, 556 557 // Aliases. 558 kBranchTypeFirstCondition = eq, 559 kBranchTypeLastCondition = nv, 560 kBranchTypeFirstUsingReg = reg_zero, 561 kBranchTypeFirstUsingBit = reg_bit_clear 562 }; 563 564 565 enum DiscardMoveMode { kDontDiscardForSameWReg, kDiscardForSameWReg }; 566 567 568 class MacroAssembler : public Assembler, public MacroAssemblerInterface { 569 public: 570 explicit MacroAssembler( 571 PositionIndependentCodeOption pic = PositionIndependentCode); 572 MacroAssembler(size_t capacity, 573 PositionIndependentCodeOption pic = PositionIndependentCode); 574 MacroAssembler(byte* buffer, 575 size_t capacity, 576 PositionIndependentCodeOption pic = PositionIndependentCode); 577 ~MacroAssembler(); 578 579 virtual vixl::internal::AssemblerBase* AsAssemblerBase() VIXL_OVERRIDE { 580 return this; 581 } 582 583 // Start generating code from the beginning of the buffer, discarding any code 584 // and data that has already been emitted into the buffer. 585 // 586 // In order to avoid any accidental transfer of state, Reset ASSERTs that the 587 // constant pool is not blocked. 588 void Reset(); 589 590 // Finalize a code buffer of generated instructions. This function must be 591 // called before executing or copying code from the buffer. 592 void FinalizeCode(); 593 594 595 // Constant generation helpers. 596 // These functions return the number of instructions required to move the 597 // immediate into the destination register. Also, if the masm pointer is 598 // non-null, it generates the code to do so. 599 // The two features are implemented using one function to avoid duplication of 600 // the logic. 601 // The function can be used to evaluate the cost of synthesizing an 602 // instruction using 'mov immediate' instructions. A user might prefer loading 603 // a constant using the literal pool instead of using multiple 'mov immediate' 604 // instructions. 605 static int MoveImmediateHelper(MacroAssembler* masm, 606 const Register& rd, 607 uint64_t imm); 608 static bool OneInstrMoveImmediateHelper(MacroAssembler* masm, 609 const Register& dst, 610 int64_t imm); 611 612 613 // Logical macros. 614 void And(const Register& rd, const Register& rn, const Operand& operand); 615 void Ands(const Register& rd, const Register& rn, const Operand& operand); 616 void Bic(const Register& rd, const Register& rn, const Operand& operand); 617 void Bics(const Register& rd, const Register& rn, const Operand& operand); 618 void Orr(const Register& rd, const Register& rn, const Operand& operand); 619 void Orn(const Register& rd, const Register& rn, const Operand& operand); 620 void Eor(const Register& rd, const Register& rn, const Operand& operand); 621 void Eon(const Register& rd, const Register& rn, const Operand& operand); 622 void Tst(const Register& rn, const Operand& operand); 623 void LogicalMacro(const Register& rd, 624 const Register& rn, 625 const Operand& operand, 626 LogicalOp op); 627 628 // Add and sub macros. 629 void Add(const Register& rd, 630 const Register& rn, 631 const Operand& operand, 632 FlagsUpdate S = LeaveFlags); 633 void Adds(const Register& rd, const Register& rn, const Operand& operand); 634 void Sub(const Register& rd, 635 const Register& rn, 636 const Operand& operand, 637 FlagsUpdate S = LeaveFlags); 638 void Subs(const Register& rd, const Register& rn, const Operand& operand); 639 void Cmn(const Register& rn, const Operand& operand); 640 void Cmp(const Register& rn, const Operand& operand); 641 void Neg(const Register& rd, const Operand& operand); 642 void Negs(const Register& rd, const Operand& operand); 643 644 void AddSubMacro(const Register& rd, 645 const Register& rn, 646 const Operand& operand, 647 FlagsUpdate S, 648 AddSubOp op); 649 650 // Add/sub with carry macros. 651 void Adc(const Register& rd, const Register& rn, const Operand& operand); 652 void Adcs(const Register& rd, const Register& rn, const Operand& operand); 653 void Sbc(const Register& rd, const Register& rn, const Operand& operand); 654 void Sbcs(const Register& rd, const Register& rn, const Operand& operand); 655 void Ngc(const Register& rd, const Operand& operand); 656 void Ngcs(const Register& rd, const Operand& operand); 657 void AddSubWithCarryMacro(const Register& rd, 658 const Register& rn, 659 const Operand& operand, 660 FlagsUpdate S, 661 AddSubWithCarryOp op); 662 663 // Move macros. 664 void Mov(const Register& rd, uint64_t imm); 665 void Mov(const Register& rd, 666 const Operand& operand, 667 DiscardMoveMode discard_mode = kDontDiscardForSameWReg); 668 void Mvn(const Register& rd, uint64_t imm) { 669 Mov(rd, (rd.GetSizeInBits() == kXRegSize) ? ~imm : (~imm & kWRegMask)); 670 } 671 void Mvn(const Register& rd, const Operand& operand); 672 673 // Try to move an immediate into the destination register in a single 674 // instruction. Returns true for success, and updates the contents of dst. 675 // Returns false, otherwise. 676 bool TryOneInstrMoveImmediate(const Register& dst, int64_t imm); 677 678 // Move an immediate into register dst, and return an Operand object for 679 // use with a subsequent instruction that accepts a shift. The value moved 680 // into dst is not necessarily equal to imm; it may have had a shifting 681 // operation applied to it that will be subsequently undone by the shift 682 // applied in the Operand. 683 Operand MoveImmediateForShiftedOp(const Register& dst, int64_t imm); 684 685 void Move(const GenericOperand& dst, const GenericOperand& src); 686 687 // Synthesises the address represented by a MemOperand into a register. 688 void ComputeAddress(const Register& dst, const MemOperand& mem_op); 689 690 // Conditional macros. 691 void Ccmp(const Register& rn, 692 const Operand& operand, 693 StatusFlags nzcv, 694 Condition cond); 695 void Ccmn(const Register& rn, 696 const Operand& operand, 697 StatusFlags nzcv, 698 Condition cond); 699 void ConditionalCompareMacro(const Register& rn, 700 const Operand& operand, 701 StatusFlags nzcv, 702 Condition cond, 703 ConditionalCompareOp op); 704 705 // On return, the boolean values pointed to will indicate whether `left` and 706 // `right` should be synthesised in a temporary register. 707 static void GetCselSynthesisInformation(const Register& rd, 708 const Operand& left, 709 const Operand& right, 710 bool* should_synthesise_left, 711 bool* should_synthesise_right) { 712 // Note that the helper does not need to look at the condition. 713 CselHelper(NULL, 714 rd, 715 left, 716 right, 717 eq, 718 should_synthesise_left, 719 should_synthesise_right); 720 } 721 722 void Csel(const Register& rd, 723 const Operand& left, 724 const Operand& right, 725 Condition cond) { 726 CselHelper(this, rd, left, right, cond); 727 } 728 729 // Load/store macros. 730 #define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \ 731 void FN(const REGTYPE REG, const MemOperand& addr); 732 LS_MACRO_LIST(DECLARE_FUNCTION) 733 #undef DECLARE_FUNCTION 734 735 void LoadStoreMacro(const CPURegister& rt, 736 const MemOperand& addr, 737 LoadStoreOp op); 738 739 #define DECLARE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \ 740 void FN(const REGTYPE REG, const REGTYPE REG2, const MemOperand& addr); 741 LSPAIR_MACRO_LIST(DECLARE_FUNCTION) 742 #undef DECLARE_FUNCTION 743 744 void LoadStorePairMacro(const CPURegister& rt, 745 const CPURegister& rt2, 746 const MemOperand& addr, 747 LoadStorePairOp op); 748 749 void Prfm(PrefetchOperation op, const MemOperand& addr); 750 751 // Push or pop up to 4 registers of the same width to or from the stack, 752 // using the current stack pointer as set by SetStackPointer. 753 // 754 // If an argument register is 'NoReg', all further arguments are also assumed 755 // to be 'NoReg', and are thus not pushed or popped. 756 // 757 // Arguments are ordered such that "Push(a, b);" is functionally equivalent 758 // to "Push(a); Push(b);". 759 // 760 // It is valid to push the same register more than once, and there is no 761 // restriction on the order in which registers are specified. 762 // 763 // It is not valid to pop into the same register more than once in one 764 // operation, not even into the zero register. 765 // 766 // If the current stack pointer (as set by SetStackPointer) is sp, then it 767 // must be aligned to 16 bytes on entry and the total size of the specified 768 // registers must also be a multiple of 16 bytes. 769 // 770 // Even if the current stack pointer is not the system stack pointer (sp), 771 // Push (and derived methods) will still modify the system stack pointer in 772 // order to comply with ABI rules about accessing memory below the system 773 // stack pointer. 774 // 775 // Other than the registers passed into Pop, the stack pointer and (possibly) 776 // the system stack pointer, these methods do not modify any other registers. 777 void Push(const CPURegister& src0, 778 const CPURegister& src1 = NoReg, 779 const CPURegister& src2 = NoReg, 780 const CPURegister& src3 = NoReg); 781 void Pop(const CPURegister& dst0, 782 const CPURegister& dst1 = NoReg, 783 const CPURegister& dst2 = NoReg, 784 const CPURegister& dst3 = NoReg); 785 786 // Alternative forms of Push and Pop, taking a RegList or CPURegList that 787 // specifies the registers that are to be pushed or popped. Higher-numbered 788 // registers are associated with higher memory addresses (as in the A32 push 789 // and pop instructions). 790 // 791 // (Push|Pop)SizeRegList allow you to specify the register size as a 792 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are 793 // supported. 794 // 795 // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred. 796 void PushCPURegList(CPURegList registers); 797 void PopCPURegList(CPURegList registers); 798 799 void PushSizeRegList( 800 RegList registers, 801 unsigned reg_size, 802 CPURegister::RegisterType type = CPURegister::kRegister) { 803 PushCPURegList(CPURegList(type, reg_size, registers)); 804 } 805 void PopSizeRegList(RegList registers, 806 unsigned reg_size, 807 CPURegister::RegisterType type = CPURegister::kRegister) { 808 PopCPURegList(CPURegList(type, reg_size, registers)); 809 } 810 void PushXRegList(RegList regs) { PushSizeRegList(regs, kXRegSize); } 811 void PopXRegList(RegList regs) { PopSizeRegList(regs, kXRegSize); } 812 void PushWRegList(RegList regs) { PushSizeRegList(regs, kWRegSize); } 813 void PopWRegList(RegList regs) { PopSizeRegList(regs, kWRegSize); } 814 void PushDRegList(RegList regs) { 815 PushSizeRegList(regs, kDRegSize, CPURegister::kVRegister); 816 } 817 void PopDRegList(RegList regs) { 818 PopSizeRegList(regs, kDRegSize, CPURegister::kVRegister); 819 } 820 void PushSRegList(RegList regs) { 821 PushSizeRegList(regs, kSRegSize, CPURegister::kVRegister); 822 } 823 void PopSRegList(RegList regs) { 824 PopSizeRegList(regs, kSRegSize, CPURegister::kVRegister); 825 } 826 827 // Push the specified register 'count' times. 828 void PushMultipleTimes(int count, Register src); 829 830 // Poke 'src' onto the stack. The offset is in bytes. 831 // 832 // If the current stack pointer (as set by SetStackPointer) is sp, then sp 833 // must be aligned to 16 bytes. 834 void Poke(const Register& src, const Operand& offset); 835 836 // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes. 837 // 838 // If the current stack pointer (as set by SetStackPointer) is sp, then sp 839 // must be aligned to 16 bytes. 840 void Peek(const Register& dst, const Operand& offset); 841 842 // Alternative forms of Peek and Poke, taking a RegList or CPURegList that 843 // specifies the registers that are to be pushed or popped. Higher-numbered 844 // registers are associated with higher memory addresses. 845 // 846 // (Peek|Poke)SizeRegList allow you to specify the register size as a 847 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are 848 // supported. 849 // 850 // Otherwise, (Peek|Poke)(CPU|X|W|D|S)RegList is preferred. 851 void PeekCPURegList(CPURegList registers, int64_t offset) { 852 LoadCPURegList(registers, MemOperand(StackPointer(), offset)); 853 } 854 void PokeCPURegList(CPURegList registers, int64_t offset) { 855 StoreCPURegList(registers, MemOperand(StackPointer(), offset)); 856 } 857 858 void PeekSizeRegList( 859 RegList registers, 860 int64_t offset, 861 unsigned reg_size, 862 CPURegister::RegisterType type = CPURegister::kRegister) { 863 PeekCPURegList(CPURegList(type, reg_size, registers), offset); 864 } 865 void PokeSizeRegList( 866 RegList registers, 867 int64_t offset, 868 unsigned reg_size, 869 CPURegister::RegisterType type = CPURegister::kRegister) { 870 PokeCPURegList(CPURegList(type, reg_size, registers), offset); 871 } 872 void PeekXRegList(RegList regs, int64_t offset) { 873 PeekSizeRegList(regs, offset, kXRegSize); 874 } 875 void PokeXRegList(RegList regs, int64_t offset) { 876 PokeSizeRegList(regs, offset, kXRegSize); 877 } 878 void PeekWRegList(RegList regs, int64_t offset) { 879 PeekSizeRegList(regs, offset, kWRegSize); 880 } 881 void PokeWRegList(RegList regs, int64_t offset) { 882 PokeSizeRegList(regs, offset, kWRegSize); 883 } 884 void PeekDRegList(RegList regs, int64_t offset) { 885 PeekSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister); 886 } 887 void PokeDRegList(RegList regs, int64_t offset) { 888 PokeSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister); 889 } 890 void PeekSRegList(RegList regs, int64_t offset) { 891 PeekSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister); 892 } 893 void PokeSRegList(RegList regs, int64_t offset) { 894 PokeSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister); 895 } 896 897 898 // Claim or drop stack space without actually accessing memory. 899 // 900 // If the current stack pointer (as set by SetStackPointer) is sp, then it 901 // must be aligned to 16 bytes and the size claimed or dropped must be a 902 // multiple of 16 bytes. 903 void Claim(const Operand& size); 904 void Drop(const Operand& size); 905 906 // Preserve the callee-saved registers (as defined by AAPCS64). 907 // 908 // Higher-numbered registers are pushed before lower-numbered registers, and 909 // thus get higher addresses. 910 // Floating-point registers are pushed before general-purpose registers, and 911 // thus get higher addresses. 912 // 913 // This method must not be called unless StackPointer() is sp, and it is 914 // aligned to 16 bytes. 915 void PushCalleeSavedRegisters(); 916 917 // Restore the callee-saved registers (as defined by AAPCS64). 918 // 919 // Higher-numbered registers are popped after lower-numbered registers, and 920 // thus come from higher addresses. 921 // Floating-point registers are popped after general-purpose registers, and 922 // thus come from higher addresses. 923 // 924 // This method must not be called unless StackPointer() is sp, and it is 925 // aligned to 16 bytes. 926 void PopCalleeSavedRegisters(); 927 928 void LoadCPURegList(CPURegList registers, const MemOperand& src); 929 void StoreCPURegList(CPURegList registers, const MemOperand& dst); 930 931 // Remaining instructions are simple pass-through calls to the assembler. 932 void Adr(const Register& rd, Label* label) { 933 VIXL_ASSERT(allow_macro_instructions_); 934 VIXL_ASSERT(!rd.IsZero()); 935 SingleEmissionCheckScope guard(this); 936 adr(rd, label); 937 } 938 void Adrp(const Register& rd, Label* label) { 939 VIXL_ASSERT(allow_macro_instructions_); 940 VIXL_ASSERT(!rd.IsZero()); 941 SingleEmissionCheckScope guard(this); 942 adrp(rd, label); 943 } 944 void Asr(const Register& rd, const Register& rn, unsigned shift) { 945 VIXL_ASSERT(allow_macro_instructions_); 946 VIXL_ASSERT(!rd.IsZero()); 947 VIXL_ASSERT(!rn.IsZero()); 948 SingleEmissionCheckScope guard(this); 949 asr(rd, rn, shift); 950 } 951 void Asr(const Register& rd, const Register& rn, const Register& rm) { 952 VIXL_ASSERT(allow_macro_instructions_); 953 VIXL_ASSERT(!rd.IsZero()); 954 VIXL_ASSERT(!rn.IsZero()); 955 VIXL_ASSERT(!rm.IsZero()); 956 SingleEmissionCheckScope guard(this); 957 asrv(rd, rn, rm); 958 } 959 960 // Branch type inversion relies on these relations. 961 VIXL_STATIC_ASSERT((reg_zero == (reg_not_zero ^ 1)) && 962 (reg_bit_clear == (reg_bit_set ^ 1)) && 963 (always == (never ^ 1))); 964 965 BranchType InvertBranchType(BranchType type) { 966 if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) { 967 return static_cast<BranchType>( 968 InvertCondition(static_cast<Condition>(type))); 969 } else { 970 return static_cast<BranchType>(type ^ 1); 971 } 972 } 973 974 void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1); 975 976 void B(Label* label); 977 void B(Label* label, Condition cond); 978 void B(Condition cond, Label* label) { B(label, cond); } 979 void Bfm(const Register& rd, 980 const Register& rn, 981 unsigned immr, 982 unsigned imms) { 983 VIXL_ASSERT(allow_macro_instructions_); 984 VIXL_ASSERT(!rd.IsZero()); 985 VIXL_ASSERT(!rn.IsZero()); 986 SingleEmissionCheckScope guard(this); 987 bfm(rd, rn, immr, imms); 988 } 989 void Bfi(const Register& rd, 990 const Register& rn, 991 unsigned lsb, 992 unsigned width) { 993 VIXL_ASSERT(allow_macro_instructions_); 994 VIXL_ASSERT(!rd.IsZero()); 995 VIXL_ASSERT(!rn.IsZero()); 996 SingleEmissionCheckScope guard(this); 997 bfi(rd, rn, lsb, width); 998 } 999 void Bfxil(const Register& rd, 1000 const Register& rn, 1001 unsigned lsb, 1002 unsigned width) { 1003 VIXL_ASSERT(allow_macro_instructions_); 1004 VIXL_ASSERT(!rd.IsZero()); 1005 VIXL_ASSERT(!rn.IsZero()); 1006 SingleEmissionCheckScope guard(this); 1007 bfxil(rd, rn, lsb, width); 1008 } 1009 void Bind(Label* label); 1010 // Bind a label to a specified offset from the start of the buffer. 1011 void BindToOffset(Label* label, ptrdiff_t offset); 1012 void Bl(Label* label) { 1013 VIXL_ASSERT(allow_macro_instructions_); 1014 SingleEmissionCheckScope guard(this); 1015 bl(label); 1016 } 1017 void Blr(const Register& xn) { 1018 VIXL_ASSERT(allow_macro_instructions_); 1019 VIXL_ASSERT(!xn.IsZero()); 1020 SingleEmissionCheckScope guard(this); 1021 blr(xn); 1022 } 1023 void Br(const Register& xn) { 1024 VIXL_ASSERT(allow_macro_instructions_); 1025 VIXL_ASSERT(!xn.IsZero()); 1026 SingleEmissionCheckScope guard(this); 1027 br(xn); 1028 } 1029 void Brk(int code = 0) { 1030 VIXL_ASSERT(allow_macro_instructions_); 1031 SingleEmissionCheckScope guard(this); 1032 brk(code); 1033 } 1034 void Cbnz(const Register& rt, Label* label); 1035 void Cbz(const Register& rt, Label* label); 1036 void Cinc(const Register& rd, const Register& rn, Condition cond) { 1037 VIXL_ASSERT(allow_macro_instructions_); 1038 VIXL_ASSERT(!rd.IsZero()); 1039 VIXL_ASSERT(!rn.IsZero()); 1040 SingleEmissionCheckScope guard(this); 1041 cinc(rd, rn, cond); 1042 } 1043 void Cinv(const Register& rd, const Register& rn, Condition cond) { 1044 VIXL_ASSERT(allow_macro_instructions_); 1045 VIXL_ASSERT(!rd.IsZero()); 1046 VIXL_ASSERT(!rn.IsZero()); 1047 SingleEmissionCheckScope guard(this); 1048 cinv(rd, rn, cond); 1049 } 1050 void Clrex() { 1051 VIXL_ASSERT(allow_macro_instructions_); 1052 SingleEmissionCheckScope guard(this); 1053 clrex(); 1054 } 1055 void Cls(const Register& rd, const Register& rn) { 1056 VIXL_ASSERT(allow_macro_instructions_); 1057 VIXL_ASSERT(!rd.IsZero()); 1058 VIXL_ASSERT(!rn.IsZero()); 1059 SingleEmissionCheckScope guard(this); 1060 cls(rd, rn); 1061 } 1062 void Clz(const Register& rd, const Register& rn) { 1063 VIXL_ASSERT(allow_macro_instructions_); 1064 VIXL_ASSERT(!rd.IsZero()); 1065 VIXL_ASSERT(!rn.IsZero()); 1066 SingleEmissionCheckScope guard(this); 1067 clz(rd, rn); 1068 } 1069 void Cneg(const Register& rd, const Register& rn, Condition cond) { 1070 VIXL_ASSERT(allow_macro_instructions_); 1071 VIXL_ASSERT(!rd.IsZero()); 1072 VIXL_ASSERT(!rn.IsZero()); 1073 SingleEmissionCheckScope guard(this); 1074 cneg(rd, rn, cond); 1075 } 1076 void Cset(const Register& rd, Condition cond) { 1077 VIXL_ASSERT(allow_macro_instructions_); 1078 VIXL_ASSERT(!rd.IsZero()); 1079 SingleEmissionCheckScope guard(this); 1080 cset(rd, cond); 1081 } 1082 void Csetm(const Register& rd, Condition cond) { 1083 VIXL_ASSERT(allow_macro_instructions_); 1084 VIXL_ASSERT(!rd.IsZero()); 1085 SingleEmissionCheckScope guard(this); 1086 csetm(rd, cond); 1087 } 1088 void Csinc(const Register& rd, 1089 const Register& rn, 1090 const Register& rm, 1091 Condition cond) { 1092 VIXL_ASSERT(allow_macro_instructions_); 1093 VIXL_ASSERT(!rd.IsZero()); 1094 VIXL_ASSERT(!rn.IsZero()); 1095 VIXL_ASSERT(!rm.IsZero()); 1096 VIXL_ASSERT((cond != al) && (cond != nv)); 1097 SingleEmissionCheckScope guard(this); 1098 csinc(rd, rn, rm, cond); 1099 } 1100 void Csinv(const Register& rd, 1101 const Register& rn, 1102 const Register& rm, 1103 Condition cond) { 1104 VIXL_ASSERT(allow_macro_instructions_); 1105 VIXL_ASSERT(!rd.IsZero()); 1106 VIXL_ASSERT(!rn.IsZero()); 1107 VIXL_ASSERT(!rm.IsZero()); 1108 VIXL_ASSERT((cond != al) && (cond != nv)); 1109 SingleEmissionCheckScope guard(this); 1110 csinv(rd, rn, rm, cond); 1111 } 1112 void Csneg(const Register& rd, 1113 const Register& rn, 1114 const Register& rm, 1115 Condition cond) { 1116 VIXL_ASSERT(allow_macro_instructions_); 1117 VIXL_ASSERT(!rd.IsZero()); 1118 VIXL_ASSERT(!rn.IsZero()); 1119 VIXL_ASSERT(!rm.IsZero()); 1120 VIXL_ASSERT((cond != al) && (cond != nv)); 1121 SingleEmissionCheckScope guard(this); 1122 csneg(rd, rn, rm, cond); 1123 } 1124 void Dmb(BarrierDomain domain, BarrierType type) { 1125 VIXL_ASSERT(allow_macro_instructions_); 1126 SingleEmissionCheckScope guard(this); 1127 dmb(domain, type); 1128 } 1129 void Dsb(BarrierDomain domain, BarrierType type) { 1130 VIXL_ASSERT(allow_macro_instructions_); 1131 SingleEmissionCheckScope guard(this); 1132 dsb(domain, type); 1133 } 1134 void Extr(const Register& rd, 1135 const Register& rn, 1136 const Register& rm, 1137 unsigned lsb) { 1138 VIXL_ASSERT(allow_macro_instructions_); 1139 VIXL_ASSERT(!rd.IsZero()); 1140 VIXL_ASSERT(!rn.IsZero()); 1141 VIXL_ASSERT(!rm.IsZero()); 1142 SingleEmissionCheckScope guard(this); 1143 extr(rd, rn, rm, lsb); 1144 } 1145 void Fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1146 VIXL_ASSERT(allow_macro_instructions_); 1147 SingleEmissionCheckScope guard(this); 1148 fadd(vd, vn, vm); 1149 } 1150 void Fccmp(const VRegister& vn, 1151 const VRegister& vm, 1152 StatusFlags nzcv, 1153 Condition cond, 1154 FPTrapFlags trap = DisableTrap) { 1155 VIXL_ASSERT(allow_macro_instructions_); 1156 VIXL_ASSERT((cond != al) && (cond != nv)); 1157 SingleEmissionCheckScope guard(this); 1158 FPCCompareMacro(vn, vm, nzcv, cond, trap); 1159 } 1160 void Fccmpe(const VRegister& vn, 1161 const VRegister& vm, 1162 StatusFlags nzcv, 1163 Condition cond) { 1164 Fccmp(vn, vm, nzcv, cond, EnableTrap); 1165 } 1166 void Fcmp(const VRegister& vn, 1167 const VRegister& vm, 1168 FPTrapFlags trap = DisableTrap) { 1169 VIXL_ASSERT(allow_macro_instructions_); 1170 SingleEmissionCheckScope guard(this); 1171 FPCompareMacro(vn, vm, trap); 1172 } 1173 void Fcmp(const VRegister& vn, double value, FPTrapFlags trap = DisableTrap); 1174 void Fcmpe(const VRegister& vn, double value); 1175 void Fcmpe(const VRegister& vn, const VRegister& vm) { 1176 Fcmp(vn, vm, EnableTrap); 1177 } 1178 void Fcsel(const VRegister& vd, 1179 const VRegister& vn, 1180 const VRegister& vm, 1181 Condition cond) { 1182 VIXL_ASSERT(allow_macro_instructions_); 1183 VIXL_ASSERT((cond != al) && (cond != nv)); 1184 SingleEmissionCheckScope guard(this); 1185 fcsel(vd, vn, vm, cond); 1186 } 1187 void Fcvt(const VRegister& vd, const VRegister& vn) { 1188 VIXL_ASSERT(allow_macro_instructions_); 1189 SingleEmissionCheckScope guard(this); 1190 fcvt(vd, vn); 1191 } 1192 void Fcvtl(const VRegister& vd, const VRegister& vn) { 1193 VIXL_ASSERT(allow_macro_instructions_); 1194 SingleEmissionCheckScope guard(this); 1195 fcvtl(vd, vn); 1196 } 1197 void Fcvtl2(const VRegister& vd, const VRegister& vn) { 1198 VIXL_ASSERT(allow_macro_instructions_); 1199 SingleEmissionCheckScope guard(this); 1200 fcvtl2(vd, vn); 1201 } 1202 void Fcvtn(const VRegister& vd, const VRegister& vn) { 1203 VIXL_ASSERT(allow_macro_instructions_); 1204 SingleEmissionCheckScope guard(this); 1205 fcvtn(vd, vn); 1206 } 1207 void Fcvtn2(const VRegister& vd, const VRegister& vn) { 1208 VIXL_ASSERT(allow_macro_instructions_); 1209 SingleEmissionCheckScope guard(this); 1210 fcvtn2(vd, vn); 1211 } 1212 void Fcvtxn(const VRegister& vd, const VRegister& vn) { 1213 VIXL_ASSERT(allow_macro_instructions_); 1214 SingleEmissionCheckScope guard(this); 1215 fcvtxn(vd, vn); 1216 } 1217 void Fcvtxn2(const VRegister& vd, const VRegister& vn) { 1218 VIXL_ASSERT(allow_macro_instructions_); 1219 SingleEmissionCheckScope guard(this); 1220 fcvtxn2(vd, vn); 1221 } 1222 void Fcvtas(const Register& rd, const VRegister& vn) { 1223 VIXL_ASSERT(allow_macro_instructions_); 1224 VIXL_ASSERT(!rd.IsZero()); 1225 SingleEmissionCheckScope guard(this); 1226 fcvtas(rd, vn); 1227 } 1228 void Fcvtau(const Register& rd, const VRegister& vn) { 1229 VIXL_ASSERT(allow_macro_instructions_); 1230 VIXL_ASSERT(!rd.IsZero()); 1231 SingleEmissionCheckScope guard(this); 1232 fcvtau(rd, vn); 1233 } 1234 void Fcvtms(const Register& rd, const VRegister& vn) { 1235 VIXL_ASSERT(allow_macro_instructions_); 1236 VIXL_ASSERT(!rd.IsZero()); 1237 SingleEmissionCheckScope guard(this); 1238 fcvtms(rd, vn); 1239 } 1240 void Fcvtmu(const Register& rd, const VRegister& vn) { 1241 VIXL_ASSERT(allow_macro_instructions_); 1242 VIXL_ASSERT(!rd.IsZero()); 1243 SingleEmissionCheckScope guard(this); 1244 fcvtmu(rd, vn); 1245 } 1246 void Fcvtns(const Register& rd, const VRegister& vn) { 1247 VIXL_ASSERT(allow_macro_instructions_); 1248 VIXL_ASSERT(!rd.IsZero()); 1249 SingleEmissionCheckScope guard(this); 1250 fcvtns(rd, vn); 1251 } 1252 void Fcvtnu(const Register& rd, const VRegister& vn) { 1253 VIXL_ASSERT(allow_macro_instructions_); 1254 VIXL_ASSERT(!rd.IsZero()); 1255 SingleEmissionCheckScope guard(this); 1256 fcvtnu(rd, vn); 1257 } 1258 void Fcvtps(const Register& rd, const VRegister& vn) { 1259 VIXL_ASSERT(allow_macro_instructions_); 1260 VIXL_ASSERT(!rd.IsZero()); 1261 SingleEmissionCheckScope guard(this); 1262 fcvtps(rd, vn); 1263 } 1264 void Fcvtpu(const Register& rd, const VRegister& vn) { 1265 VIXL_ASSERT(allow_macro_instructions_); 1266 VIXL_ASSERT(!rd.IsZero()); 1267 SingleEmissionCheckScope guard(this); 1268 fcvtpu(rd, vn); 1269 } 1270 void Fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0) { 1271 VIXL_ASSERT(allow_macro_instructions_); 1272 VIXL_ASSERT(!rd.IsZero()); 1273 SingleEmissionCheckScope guard(this); 1274 fcvtzs(rd, vn, fbits); 1275 } 1276 void Fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0) { 1277 VIXL_ASSERT(allow_macro_instructions_); 1278 VIXL_ASSERT(!rd.IsZero()); 1279 SingleEmissionCheckScope guard(this); 1280 fcvtzu(rd, vn, fbits); 1281 } 1282 void Fdiv(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1283 VIXL_ASSERT(allow_macro_instructions_); 1284 SingleEmissionCheckScope guard(this); 1285 fdiv(vd, vn, vm); 1286 } 1287 void Fmax(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1288 VIXL_ASSERT(allow_macro_instructions_); 1289 SingleEmissionCheckScope guard(this); 1290 fmax(vd, vn, vm); 1291 } 1292 void Fmaxnm(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1293 VIXL_ASSERT(allow_macro_instructions_); 1294 SingleEmissionCheckScope guard(this); 1295 fmaxnm(vd, vn, vm); 1296 } 1297 void Fmin(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1298 VIXL_ASSERT(allow_macro_instructions_); 1299 SingleEmissionCheckScope guard(this); 1300 fmin(vd, vn, vm); 1301 } 1302 void Fminnm(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1303 VIXL_ASSERT(allow_macro_instructions_); 1304 SingleEmissionCheckScope guard(this); 1305 fminnm(vd, vn, vm); 1306 } 1307 void Fmov(const VRegister& vd, const VRegister& vn) { 1308 VIXL_ASSERT(allow_macro_instructions_); 1309 SingleEmissionCheckScope guard(this); 1310 // Only emit an instruction if vd and vn are different, and they are both D 1311 // registers. fmov(s0, s0) is not a no-op because it clears the top word of 1312 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears 1313 // the top of q0, but VRegister does not currently support Q registers. 1314 if (!vd.Is(vn) || !vd.Is64Bits()) { 1315 fmov(vd, vn); 1316 } 1317 } 1318 void Fmov(const VRegister& vd, const Register& rn) { 1319 VIXL_ASSERT(allow_macro_instructions_); 1320 VIXL_ASSERT(!rn.IsZero()); 1321 SingleEmissionCheckScope guard(this); 1322 fmov(vd, rn); 1323 } 1324 void Fmov(const VRegister& vd, const XRegister& xn) { 1325 Fmov(vd, Register(xn)); 1326 } 1327 void Fmov(const VRegister& vd, const WRegister& wn) { 1328 Fmov(vd, Register(wn)); 1329 } 1330 void Fmov(const VRegister& vd, int index, const Register& rn) { 1331 VIXL_ASSERT(allow_macro_instructions_); 1332 SingleEmissionCheckScope guard(this); 1333 fmov(vd, index, rn); 1334 } 1335 void Fmov(const Register& rd, const VRegister& vn, int index) { 1336 VIXL_ASSERT(allow_macro_instructions_); 1337 SingleEmissionCheckScope guard(this); 1338 fmov(rd, vn, index); 1339 } 1340 1341 // Provide explicit double and float interfaces for FP immediate moves, rather 1342 // than relying on implicit C++ casts. This allows signalling NaNs to be 1343 // preserved when the immediate matches the format of vd. Most systems convert 1344 // signalling NaNs to quiet NaNs when converting between float and double. 1345 void Fmov(VRegister vd, double imm); 1346 void Fmov(VRegister vd, float imm); 1347 // Provide a template to allow other types to be converted automatically. 1348 template <typename T> 1349 void Fmov(VRegister vd, T imm) { 1350 VIXL_ASSERT(allow_macro_instructions_); 1351 Fmov(vd, static_cast<double>(imm)); 1352 } 1353 void Fmov(Register rd, VRegister vn) { 1354 VIXL_ASSERT(allow_macro_instructions_); 1355 VIXL_ASSERT(!rd.IsZero()); 1356 SingleEmissionCheckScope guard(this); 1357 fmov(rd, vn); 1358 } 1359 void Fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1360 VIXL_ASSERT(allow_macro_instructions_); 1361 SingleEmissionCheckScope guard(this); 1362 fmul(vd, vn, vm); 1363 } 1364 void Fnmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1365 VIXL_ASSERT(allow_macro_instructions_); 1366 SingleEmissionCheckScope guard(this); 1367 fnmul(vd, vn, vm); 1368 } 1369 void Fmadd(const VRegister& vd, 1370 const VRegister& vn, 1371 const VRegister& vm, 1372 const VRegister& va) { 1373 VIXL_ASSERT(allow_macro_instructions_); 1374 SingleEmissionCheckScope guard(this); 1375 fmadd(vd, vn, vm, va); 1376 } 1377 void Fmsub(const VRegister& vd, 1378 const VRegister& vn, 1379 const VRegister& vm, 1380 const VRegister& va) { 1381 VIXL_ASSERT(allow_macro_instructions_); 1382 SingleEmissionCheckScope guard(this); 1383 fmsub(vd, vn, vm, va); 1384 } 1385 void Fnmadd(const VRegister& vd, 1386 const VRegister& vn, 1387 const VRegister& vm, 1388 const VRegister& va) { 1389 VIXL_ASSERT(allow_macro_instructions_); 1390 SingleEmissionCheckScope guard(this); 1391 fnmadd(vd, vn, vm, va); 1392 } 1393 void Fnmsub(const VRegister& vd, 1394 const VRegister& vn, 1395 const VRegister& vm, 1396 const VRegister& va) { 1397 VIXL_ASSERT(allow_macro_instructions_); 1398 SingleEmissionCheckScope guard(this); 1399 fnmsub(vd, vn, vm, va); 1400 } 1401 void Fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1402 VIXL_ASSERT(allow_macro_instructions_); 1403 SingleEmissionCheckScope guard(this); 1404 fsub(vd, vn, vm); 1405 } 1406 void Hint(SystemHint code) { 1407 VIXL_ASSERT(allow_macro_instructions_); 1408 SingleEmissionCheckScope guard(this); 1409 hint(code); 1410 } 1411 void Hlt(int code) { 1412 VIXL_ASSERT(allow_macro_instructions_); 1413 SingleEmissionCheckScope guard(this); 1414 hlt(code); 1415 } 1416 void Isb() { 1417 VIXL_ASSERT(allow_macro_instructions_); 1418 SingleEmissionCheckScope guard(this); 1419 isb(); 1420 } 1421 void Ldar(const Register& rt, const MemOperand& src) { 1422 VIXL_ASSERT(allow_macro_instructions_); 1423 SingleEmissionCheckScope guard(this); 1424 ldar(rt, src); 1425 } 1426 void Ldarb(const Register& rt, const MemOperand& src) { 1427 VIXL_ASSERT(allow_macro_instructions_); 1428 SingleEmissionCheckScope guard(this); 1429 ldarb(rt, src); 1430 } 1431 void Ldarh(const Register& rt, const MemOperand& src) { 1432 VIXL_ASSERT(allow_macro_instructions_); 1433 SingleEmissionCheckScope guard(this); 1434 ldarh(rt, src); 1435 } 1436 void Ldaxp(const Register& rt, const Register& rt2, const MemOperand& src) { 1437 VIXL_ASSERT(allow_macro_instructions_); 1438 VIXL_ASSERT(!rt.Aliases(rt2)); 1439 SingleEmissionCheckScope guard(this); 1440 ldaxp(rt, rt2, src); 1441 } 1442 void Ldaxr(const Register& rt, const MemOperand& src) { 1443 VIXL_ASSERT(allow_macro_instructions_); 1444 SingleEmissionCheckScope guard(this); 1445 ldaxr(rt, src); 1446 } 1447 void Ldaxrb(const Register& rt, const MemOperand& src) { 1448 VIXL_ASSERT(allow_macro_instructions_); 1449 SingleEmissionCheckScope guard(this); 1450 ldaxrb(rt, src); 1451 } 1452 void Ldaxrh(const Register& rt, const MemOperand& src) { 1453 VIXL_ASSERT(allow_macro_instructions_); 1454 SingleEmissionCheckScope guard(this); 1455 ldaxrh(rt, src); 1456 } 1457 void Ldnp(const CPURegister& rt, 1458 const CPURegister& rt2, 1459 const MemOperand& src) { 1460 VIXL_ASSERT(allow_macro_instructions_); 1461 SingleEmissionCheckScope guard(this); 1462 ldnp(rt, rt2, src); 1463 } 1464 // Provide both double and float interfaces for FP immediate loads, rather 1465 // than relying on implicit C++ casts. This allows signalling NaNs to be 1466 // preserved when the immediate matches the format of fd. Most systems convert 1467 // signalling NaNs to quiet NaNs when converting between float and double. 1468 void Ldr(const VRegister& vt, double imm) { 1469 VIXL_ASSERT(allow_macro_instructions_); 1470 SingleEmissionCheckScope guard(this); 1471 RawLiteral* literal; 1472 if (vt.IsD()) { 1473 literal = new Literal<double>(imm, 1474 &literal_pool_, 1475 RawLiteral::kDeletedOnPlacementByPool); 1476 } else { 1477 literal = new Literal<float>(static_cast<float>(imm), 1478 &literal_pool_, 1479 RawLiteral::kDeletedOnPlacementByPool); 1480 } 1481 ldr(vt, literal); 1482 } 1483 void Ldr(const VRegister& vt, float imm) { 1484 VIXL_ASSERT(allow_macro_instructions_); 1485 SingleEmissionCheckScope guard(this); 1486 RawLiteral* literal; 1487 if (vt.IsS()) { 1488 literal = new Literal<float>(imm, 1489 &literal_pool_, 1490 RawLiteral::kDeletedOnPlacementByPool); 1491 } else { 1492 literal = new Literal<double>(static_cast<double>(imm), 1493 &literal_pool_, 1494 RawLiteral::kDeletedOnPlacementByPool); 1495 } 1496 ldr(vt, literal); 1497 } 1498 void Ldr(const VRegister& vt, uint64_t high64, uint64_t low64) { 1499 VIXL_ASSERT(allow_macro_instructions_); 1500 VIXL_ASSERT(vt.IsQ()); 1501 SingleEmissionCheckScope guard(this); 1502 ldr(vt, 1503 new Literal<uint64_t>(high64, 1504 low64, 1505 &literal_pool_, 1506 RawLiteral::kDeletedOnPlacementByPool)); 1507 } 1508 void Ldr(const Register& rt, uint64_t imm) { 1509 VIXL_ASSERT(allow_macro_instructions_); 1510 VIXL_ASSERT(!rt.IsZero()); 1511 SingleEmissionCheckScope guard(this); 1512 RawLiteral* literal; 1513 if (rt.Is64Bits()) { 1514 literal = new Literal<uint64_t>(imm, 1515 &literal_pool_, 1516 RawLiteral::kDeletedOnPlacementByPool); 1517 } else { 1518 VIXL_ASSERT(rt.Is32Bits()); 1519 VIXL_ASSERT(IsUint32(imm) || IsInt32(imm)); 1520 literal = new Literal<uint32_t>(static_cast<uint32_t>(imm), 1521 &literal_pool_, 1522 RawLiteral::kDeletedOnPlacementByPool); 1523 } 1524 ldr(rt, literal); 1525 } 1526 void Ldrsw(const Register& rt, uint32_t imm) { 1527 VIXL_ASSERT(allow_macro_instructions_); 1528 VIXL_ASSERT(!rt.IsZero()); 1529 SingleEmissionCheckScope guard(this); 1530 ldrsw(rt, 1531 new Literal<uint32_t>(imm, 1532 &literal_pool_, 1533 RawLiteral::kDeletedOnPlacementByPool)); 1534 } 1535 void Ldr(const CPURegister& rt, RawLiteral* literal) { 1536 VIXL_ASSERT(allow_macro_instructions_); 1537 SingleEmissionCheckScope guard(this); 1538 ldr(rt, literal); 1539 } 1540 void Ldrsw(const Register& rt, RawLiteral* literal) { 1541 VIXL_ASSERT(allow_macro_instructions_); 1542 SingleEmissionCheckScope guard(this); 1543 ldrsw(rt, literal); 1544 } 1545 void Ldxp(const Register& rt, const Register& rt2, const MemOperand& src) { 1546 VIXL_ASSERT(allow_macro_instructions_); 1547 VIXL_ASSERT(!rt.Aliases(rt2)); 1548 SingleEmissionCheckScope guard(this); 1549 ldxp(rt, rt2, src); 1550 } 1551 void Ldxr(const Register& rt, const MemOperand& src) { 1552 VIXL_ASSERT(allow_macro_instructions_); 1553 SingleEmissionCheckScope guard(this); 1554 ldxr(rt, src); 1555 } 1556 void Ldxrb(const Register& rt, const MemOperand& src) { 1557 VIXL_ASSERT(allow_macro_instructions_); 1558 SingleEmissionCheckScope guard(this); 1559 ldxrb(rt, src); 1560 } 1561 void Ldxrh(const Register& rt, const MemOperand& src) { 1562 VIXL_ASSERT(allow_macro_instructions_); 1563 SingleEmissionCheckScope guard(this); 1564 ldxrh(rt, src); 1565 } 1566 void Lsl(const Register& rd, const Register& rn, unsigned shift) { 1567 VIXL_ASSERT(allow_macro_instructions_); 1568 VIXL_ASSERT(!rd.IsZero()); 1569 VIXL_ASSERT(!rn.IsZero()); 1570 SingleEmissionCheckScope guard(this); 1571 lsl(rd, rn, shift); 1572 } 1573 void Lsl(const Register& rd, const Register& rn, const Register& rm) { 1574 VIXL_ASSERT(allow_macro_instructions_); 1575 VIXL_ASSERT(!rd.IsZero()); 1576 VIXL_ASSERT(!rn.IsZero()); 1577 VIXL_ASSERT(!rm.IsZero()); 1578 SingleEmissionCheckScope guard(this); 1579 lslv(rd, rn, rm); 1580 } 1581 void Lsr(const Register& rd, const Register& rn, unsigned shift) { 1582 VIXL_ASSERT(allow_macro_instructions_); 1583 VIXL_ASSERT(!rd.IsZero()); 1584 VIXL_ASSERT(!rn.IsZero()); 1585 SingleEmissionCheckScope guard(this); 1586 lsr(rd, rn, shift); 1587 } 1588 void Lsr(const Register& rd, const Register& rn, const Register& rm) { 1589 VIXL_ASSERT(allow_macro_instructions_); 1590 VIXL_ASSERT(!rd.IsZero()); 1591 VIXL_ASSERT(!rn.IsZero()); 1592 VIXL_ASSERT(!rm.IsZero()); 1593 SingleEmissionCheckScope guard(this); 1594 lsrv(rd, rn, rm); 1595 } 1596 void Madd(const Register& rd, 1597 const Register& rn, 1598 const Register& rm, 1599 const Register& ra) { 1600 VIXL_ASSERT(allow_macro_instructions_); 1601 VIXL_ASSERT(!rd.IsZero()); 1602 VIXL_ASSERT(!rn.IsZero()); 1603 VIXL_ASSERT(!rm.IsZero()); 1604 VIXL_ASSERT(!ra.IsZero()); 1605 SingleEmissionCheckScope guard(this); 1606 madd(rd, rn, rm, ra); 1607 } 1608 void Mneg(const Register& rd, const Register& rn, const Register& rm) { 1609 VIXL_ASSERT(allow_macro_instructions_); 1610 VIXL_ASSERT(!rd.IsZero()); 1611 VIXL_ASSERT(!rn.IsZero()); 1612 VIXL_ASSERT(!rm.IsZero()); 1613 SingleEmissionCheckScope guard(this); 1614 mneg(rd, rn, rm); 1615 } 1616 void Mov(const Register& rd, 1617 const Register& rn, 1618 DiscardMoveMode discard_mode = kDontDiscardForSameWReg) { 1619 VIXL_ASSERT(allow_macro_instructions_); 1620 // Emit a register move only if the registers are distinct, or if they are 1621 // not X registers. 1622 // 1623 // Note that mov(w0, w0) is not a no-op because it clears the top word of 1624 // x0. A flag is provided (kDiscardForSameWReg) if a move between the same W 1625 // registers is not required to clear the top word of the X register. In 1626 // this case, the instruction is discarded. 1627 // 1628 // If the sp is an operand, add #0 is emitted, otherwise, orr #0. 1629 if (!rd.Is(rn) || 1630 (rd.Is32Bits() && (discard_mode == kDontDiscardForSameWReg))) { 1631 SingleEmissionCheckScope guard(this); 1632 mov(rd, rn); 1633 } 1634 } 1635 void Movk(const Register& rd, uint64_t imm, int shift = -1) { 1636 VIXL_ASSERT(allow_macro_instructions_); 1637 VIXL_ASSERT(!rd.IsZero()); 1638 SingleEmissionCheckScope guard(this); 1639 movk(rd, imm, shift); 1640 } 1641 void Mrs(const Register& rt, SystemRegister sysreg) { 1642 VIXL_ASSERT(allow_macro_instructions_); 1643 VIXL_ASSERT(!rt.IsZero()); 1644 SingleEmissionCheckScope guard(this); 1645 mrs(rt, sysreg); 1646 } 1647 void Msr(SystemRegister sysreg, const Register& rt) { 1648 VIXL_ASSERT(allow_macro_instructions_); 1649 VIXL_ASSERT(!rt.IsZero()); 1650 SingleEmissionCheckScope guard(this); 1651 msr(sysreg, rt); 1652 } 1653 void Sys(int op1, int crn, int crm, int op2, const Register& rt = xzr) { 1654 VIXL_ASSERT(allow_macro_instructions_); 1655 SingleEmissionCheckScope guard(this); 1656 sys(op1, crn, crm, op2, rt); 1657 } 1658 void Dc(DataCacheOp op, const Register& rt) { 1659 VIXL_ASSERT(allow_macro_instructions_); 1660 SingleEmissionCheckScope guard(this); 1661 dc(op, rt); 1662 } 1663 void Ic(InstructionCacheOp op, const Register& rt) { 1664 VIXL_ASSERT(allow_macro_instructions_); 1665 SingleEmissionCheckScope guard(this); 1666 ic(op, rt); 1667 } 1668 void Msub(const Register& rd, 1669 const Register& rn, 1670 const Register& rm, 1671 const Register& ra) { 1672 VIXL_ASSERT(allow_macro_instructions_); 1673 VIXL_ASSERT(!rd.IsZero()); 1674 VIXL_ASSERT(!rn.IsZero()); 1675 VIXL_ASSERT(!rm.IsZero()); 1676 VIXL_ASSERT(!ra.IsZero()); 1677 SingleEmissionCheckScope guard(this); 1678 msub(rd, rn, rm, ra); 1679 } 1680 void Mul(const Register& rd, const Register& rn, const Register& rm) { 1681 VIXL_ASSERT(allow_macro_instructions_); 1682 VIXL_ASSERT(!rd.IsZero()); 1683 VIXL_ASSERT(!rn.IsZero()); 1684 VIXL_ASSERT(!rm.IsZero()); 1685 SingleEmissionCheckScope guard(this); 1686 mul(rd, rn, rm); 1687 } 1688 void Nop() { 1689 VIXL_ASSERT(allow_macro_instructions_); 1690 SingleEmissionCheckScope guard(this); 1691 nop(); 1692 } 1693 void Rbit(const Register& rd, const Register& rn) { 1694 VIXL_ASSERT(allow_macro_instructions_); 1695 VIXL_ASSERT(!rd.IsZero()); 1696 VIXL_ASSERT(!rn.IsZero()); 1697 SingleEmissionCheckScope guard(this); 1698 rbit(rd, rn); 1699 } 1700 void Ret(const Register& xn = lr) { 1701 VIXL_ASSERT(allow_macro_instructions_); 1702 VIXL_ASSERT(!xn.IsZero()); 1703 SingleEmissionCheckScope guard(this); 1704 ret(xn); 1705 } 1706 void Rev(const Register& rd, const Register& rn) { 1707 VIXL_ASSERT(allow_macro_instructions_); 1708 VIXL_ASSERT(!rd.IsZero()); 1709 VIXL_ASSERT(!rn.IsZero()); 1710 SingleEmissionCheckScope guard(this); 1711 rev(rd, rn); 1712 } 1713 void Rev16(const Register& rd, const Register& rn) { 1714 VIXL_ASSERT(allow_macro_instructions_); 1715 VIXL_ASSERT(!rd.IsZero()); 1716 VIXL_ASSERT(!rn.IsZero()); 1717 SingleEmissionCheckScope guard(this); 1718 rev16(rd, rn); 1719 } 1720 void Rev32(const Register& rd, const Register& rn) { 1721 VIXL_ASSERT(allow_macro_instructions_); 1722 VIXL_ASSERT(!rd.IsZero()); 1723 VIXL_ASSERT(!rn.IsZero()); 1724 SingleEmissionCheckScope guard(this); 1725 rev32(rd, rn); 1726 } 1727 void Ror(const Register& rd, const Register& rs, unsigned shift) { 1728 VIXL_ASSERT(allow_macro_instructions_); 1729 VIXL_ASSERT(!rd.IsZero()); 1730 VIXL_ASSERT(!rs.IsZero()); 1731 SingleEmissionCheckScope guard(this); 1732 ror(rd, rs, shift); 1733 } 1734 void Ror(const Register& rd, const Register& rn, const Register& rm) { 1735 VIXL_ASSERT(allow_macro_instructions_); 1736 VIXL_ASSERT(!rd.IsZero()); 1737 VIXL_ASSERT(!rn.IsZero()); 1738 VIXL_ASSERT(!rm.IsZero()); 1739 SingleEmissionCheckScope guard(this); 1740 rorv(rd, rn, rm); 1741 } 1742 void Sbfiz(const Register& rd, 1743 const Register& rn, 1744 unsigned lsb, 1745 unsigned width) { 1746 VIXL_ASSERT(allow_macro_instructions_); 1747 VIXL_ASSERT(!rd.IsZero()); 1748 VIXL_ASSERT(!rn.IsZero()); 1749 SingleEmissionCheckScope guard(this); 1750 sbfiz(rd, rn, lsb, width); 1751 } 1752 void Sbfm(const Register& rd, 1753 const Register& rn, 1754 unsigned immr, 1755 unsigned imms) { 1756 VIXL_ASSERT(allow_macro_instructions_); 1757 VIXL_ASSERT(!rd.IsZero()); 1758 VIXL_ASSERT(!rn.IsZero()); 1759 SingleEmissionCheckScope guard(this); 1760 sbfm(rd, rn, immr, imms); 1761 } 1762 void Sbfx(const Register& rd, 1763 const Register& rn, 1764 unsigned lsb, 1765 unsigned width) { 1766 VIXL_ASSERT(allow_macro_instructions_); 1767 VIXL_ASSERT(!rd.IsZero()); 1768 VIXL_ASSERT(!rn.IsZero()); 1769 SingleEmissionCheckScope guard(this); 1770 sbfx(rd, rn, lsb, width); 1771 } 1772 void Scvtf(const VRegister& vd, const Register& rn, int fbits = 0) { 1773 VIXL_ASSERT(allow_macro_instructions_); 1774 VIXL_ASSERT(!rn.IsZero()); 1775 SingleEmissionCheckScope guard(this); 1776 scvtf(vd, rn, fbits); 1777 } 1778 void Sdiv(const Register& rd, const Register& rn, const Register& rm) { 1779 VIXL_ASSERT(allow_macro_instructions_); 1780 VIXL_ASSERT(!rd.IsZero()); 1781 VIXL_ASSERT(!rn.IsZero()); 1782 VIXL_ASSERT(!rm.IsZero()); 1783 SingleEmissionCheckScope guard(this); 1784 sdiv(rd, rn, rm); 1785 } 1786 void Smaddl(const Register& rd, 1787 const Register& rn, 1788 const Register& rm, 1789 const Register& ra) { 1790 VIXL_ASSERT(allow_macro_instructions_); 1791 VIXL_ASSERT(!rd.IsZero()); 1792 VIXL_ASSERT(!rn.IsZero()); 1793 VIXL_ASSERT(!rm.IsZero()); 1794 VIXL_ASSERT(!ra.IsZero()); 1795 SingleEmissionCheckScope guard(this); 1796 smaddl(rd, rn, rm, ra); 1797 } 1798 void Smsubl(const Register& rd, 1799 const Register& rn, 1800 const Register& rm, 1801 const Register& ra) { 1802 VIXL_ASSERT(allow_macro_instructions_); 1803 VIXL_ASSERT(!rd.IsZero()); 1804 VIXL_ASSERT(!rn.IsZero()); 1805 VIXL_ASSERT(!rm.IsZero()); 1806 VIXL_ASSERT(!ra.IsZero()); 1807 SingleEmissionCheckScope guard(this); 1808 smsubl(rd, rn, rm, ra); 1809 } 1810 void Smull(const Register& rd, const Register& rn, const Register& rm) { 1811 VIXL_ASSERT(allow_macro_instructions_); 1812 VIXL_ASSERT(!rd.IsZero()); 1813 VIXL_ASSERT(!rn.IsZero()); 1814 VIXL_ASSERT(!rm.IsZero()); 1815 SingleEmissionCheckScope guard(this); 1816 smull(rd, rn, rm); 1817 } 1818 void Smulh(const Register& xd, const Register& xn, const Register& xm) { 1819 VIXL_ASSERT(allow_macro_instructions_); 1820 VIXL_ASSERT(!xd.IsZero()); 1821 VIXL_ASSERT(!xn.IsZero()); 1822 VIXL_ASSERT(!xm.IsZero()); 1823 SingleEmissionCheckScope guard(this); 1824 smulh(xd, xn, xm); 1825 } 1826 void Stlr(const Register& rt, const MemOperand& dst) { 1827 VIXL_ASSERT(allow_macro_instructions_); 1828 SingleEmissionCheckScope guard(this); 1829 stlr(rt, dst); 1830 } 1831 void Stlrb(const Register& rt, const MemOperand& dst) { 1832 VIXL_ASSERT(allow_macro_instructions_); 1833 SingleEmissionCheckScope guard(this); 1834 stlrb(rt, dst); 1835 } 1836 void Stlrh(const Register& rt, const MemOperand& dst) { 1837 VIXL_ASSERT(allow_macro_instructions_); 1838 SingleEmissionCheckScope guard(this); 1839 stlrh(rt, dst); 1840 } 1841 void Stlxp(const Register& rs, 1842 const Register& rt, 1843 const Register& rt2, 1844 const MemOperand& dst) { 1845 VIXL_ASSERT(allow_macro_instructions_); 1846 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1847 VIXL_ASSERT(!rs.Aliases(rt)); 1848 VIXL_ASSERT(!rs.Aliases(rt2)); 1849 SingleEmissionCheckScope guard(this); 1850 stlxp(rs, rt, rt2, dst); 1851 } 1852 void Stlxr(const Register& rs, const Register& rt, const MemOperand& dst) { 1853 VIXL_ASSERT(allow_macro_instructions_); 1854 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1855 VIXL_ASSERT(!rs.Aliases(rt)); 1856 SingleEmissionCheckScope guard(this); 1857 stlxr(rs, rt, dst); 1858 } 1859 void Stlxrb(const Register& rs, const Register& rt, const MemOperand& dst) { 1860 VIXL_ASSERT(allow_macro_instructions_); 1861 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1862 VIXL_ASSERT(!rs.Aliases(rt)); 1863 SingleEmissionCheckScope guard(this); 1864 stlxrb(rs, rt, dst); 1865 } 1866 void Stlxrh(const Register& rs, const Register& rt, const MemOperand& dst) { 1867 VIXL_ASSERT(allow_macro_instructions_); 1868 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1869 VIXL_ASSERT(!rs.Aliases(rt)); 1870 SingleEmissionCheckScope guard(this); 1871 stlxrh(rs, rt, dst); 1872 } 1873 void Stnp(const CPURegister& rt, 1874 const CPURegister& rt2, 1875 const MemOperand& dst) { 1876 VIXL_ASSERT(allow_macro_instructions_); 1877 SingleEmissionCheckScope guard(this); 1878 stnp(rt, rt2, dst); 1879 } 1880 void Stxp(const Register& rs, 1881 const Register& rt, 1882 const Register& rt2, 1883 const MemOperand& dst) { 1884 VIXL_ASSERT(allow_macro_instructions_); 1885 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1886 VIXL_ASSERT(!rs.Aliases(rt)); 1887 VIXL_ASSERT(!rs.Aliases(rt2)); 1888 SingleEmissionCheckScope guard(this); 1889 stxp(rs, rt, rt2, dst); 1890 } 1891 void Stxr(const Register& rs, const Register& rt, const MemOperand& dst) { 1892 VIXL_ASSERT(allow_macro_instructions_); 1893 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1894 VIXL_ASSERT(!rs.Aliases(rt)); 1895 SingleEmissionCheckScope guard(this); 1896 stxr(rs, rt, dst); 1897 } 1898 void Stxrb(const Register& rs, const Register& rt, const MemOperand& dst) { 1899 VIXL_ASSERT(allow_macro_instructions_); 1900 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1901 VIXL_ASSERT(!rs.Aliases(rt)); 1902 SingleEmissionCheckScope guard(this); 1903 stxrb(rs, rt, dst); 1904 } 1905 void Stxrh(const Register& rs, const Register& rt, const MemOperand& dst) { 1906 VIXL_ASSERT(allow_macro_instructions_); 1907 VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister())); 1908 VIXL_ASSERT(!rs.Aliases(rt)); 1909 SingleEmissionCheckScope guard(this); 1910 stxrh(rs, rt, dst); 1911 } 1912 void Svc(int code) { 1913 VIXL_ASSERT(allow_macro_instructions_); 1914 SingleEmissionCheckScope guard(this); 1915 svc(code); 1916 } 1917 void Sxtb(const Register& rd, const Register& rn) { 1918 VIXL_ASSERT(allow_macro_instructions_); 1919 VIXL_ASSERT(!rd.IsZero()); 1920 VIXL_ASSERT(!rn.IsZero()); 1921 SingleEmissionCheckScope guard(this); 1922 sxtb(rd, rn); 1923 } 1924 void Sxth(const Register& rd, const Register& rn) { 1925 VIXL_ASSERT(allow_macro_instructions_); 1926 VIXL_ASSERT(!rd.IsZero()); 1927 VIXL_ASSERT(!rn.IsZero()); 1928 SingleEmissionCheckScope guard(this); 1929 sxth(rd, rn); 1930 } 1931 void Sxtw(const Register& rd, const Register& rn) { 1932 VIXL_ASSERT(allow_macro_instructions_); 1933 VIXL_ASSERT(!rd.IsZero()); 1934 VIXL_ASSERT(!rn.IsZero()); 1935 SingleEmissionCheckScope guard(this); 1936 sxtw(rd, rn); 1937 } 1938 void Tbl(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1939 VIXL_ASSERT(allow_macro_instructions_); 1940 SingleEmissionCheckScope guard(this); 1941 tbl(vd, vn, vm); 1942 } 1943 void Tbl(const VRegister& vd, 1944 const VRegister& vn, 1945 const VRegister& vn2, 1946 const VRegister& vm) { 1947 VIXL_ASSERT(allow_macro_instructions_); 1948 SingleEmissionCheckScope guard(this); 1949 tbl(vd, vn, vn2, vm); 1950 } 1951 void Tbl(const VRegister& vd, 1952 const VRegister& vn, 1953 const VRegister& vn2, 1954 const VRegister& vn3, 1955 const VRegister& vm) { 1956 VIXL_ASSERT(allow_macro_instructions_); 1957 SingleEmissionCheckScope guard(this); 1958 tbl(vd, vn, vn2, vn3, vm); 1959 } 1960 void Tbl(const VRegister& vd, 1961 const VRegister& vn, 1962 const VRegister& vn2, 1963 const VRegister& vn3, 1964 const VRegister& vn4, 1965 const VRegister& vm) { 1966 VIXL_ASSERT(allow_macro_instructions_); 1967 SingleEmissionCheckScope guard(this); 1968 tbl(vd, vn, vn2, vn3, vn4, vm); 1969 } 1970 void Tbx(const VRegister& vd, const VRegister& vn, const VRegister& vm) { 1971 VIXL_ASSERT(allow_macro_instructions_); 1972 SingleEmissionCheckScope guard(this); 1973 tbx(vd, vn, vm); 1974 } 1975 void Tbx(const VRegister& vd, 1976 const VRegister& vn, 1977 const VRegister& vn2, 1978 const VRegister& vm) { 1979 VIXL_ASSERT(allow_macro_instructions_); 1980 SingleEmissionCheckScope guard(this); 1981 tbx(vd, vn, vn2, vm); 1982 } 1983 void Tbx(const VRegister& vd, 1984 const VRegister& vn, 1985 const VRegister& vn2, 1986 const VRegister& vn3, 1987 const VRegister& vm) { 1988 VIXL_ASSERT(allow_macro_instructions_); 1989 SingleEmissionCheckScope guard(this); 1990 tbx(vd, vn, vn2, vn3, vm); 1991 } 1992 void Tbx(const VRegister& vd, 1993 const VRegister& vn, 1994 const VRegister& vn2, 1995 const VRegister& vn3, 1996 const VRegister& vn4, 1997 const VRegister& vm) { 1998 VIXL_ASSERT(allow_macro_instructions_); 1999 SingleEmissionCheckScope guard(this); 2000 tbx(vd, vn, vn2, vn3, vn4, vm); 2001 } 2002 void Tbnz(const Register& rt, unsigned bit_pos, Label* label); 2003 void Tbz(const Register& rt, unsigned bit_pos, Label* label); 2004 void Ubfiz(const Register& rd, 2005 const Register& rn, 2006 unsigned lsb, 2007 unsigned width) { 2008 VIXL_ASSERT(allow_macro_instructions_); 2009 VIXL_ASSERT(!rd.IsZero()); 2010 VIXL_ASSERT(!rn.IsZero()); 2011 SingleEmissionCheckScope guard(this); 2012 ubfiz(rd, rn, lsb, width); 2013 } 2014 void Ubfm(const Register& rd, 2015 const Register& rn, 2016 unsigned immr, 2017 unsigned imms) { 2018 VIXL_ASSERT(allow_macro_instructions_); 2019 VIXL_ASSERT(!rd.IsZero()); 2020 VIXL_ASSERT(!rn.IsZero()); 2021 SingleEmissionCheckScope guard(this); 2022 ubfm(rd, rn, immr, imms); 2023 } 2024 void Ubfx(const Register& rd, 2025 const Register& rn, 2026 unsigned lsb, 2027 unsigned width) { 2028 VIXL_ASSERT(allow_macro_instructions_); 2029 VIXL_ASSERT(!rd.IsZero()); 2030 VIXL_ASSERT(!rn.IsZero()); 2031 SingleEmissionCheckScope guard(this); 2032 ubfx(rd, rn, lsb, width); 2033 } 2034 void Ucvtf(const VRegister& vd, const Register& rn, int fbits = 0) { 2035 VIXL_ASSERT(allow_macro_instructions_); 2036 VIXL_ASSERT(!rn.IsZero()); 2037 SingleEmissionCheckScope guard(this); 2038 ucvtf(vd, rn, fbits); 2039 } 2040 void Udiv(const Register& rd, const Register& rn, const Register& rm) { 2041 VIXL_ASSERT(allow_macro_instructions_); 2042 VIXL_ASSERT(!rd.IsZero()); 2043 VIXL_ASSERT(!rn.IsZero()); 2044 VIXL_ASSERT(!rm.IsZero()); 2045 SingleEmissionCheckScope guard(this); 2046 udiv(rd, rn, rm); 2047 } 2048 void Umaddl(const Register& rd, 2049 const Register& rn, 2050 const Register& rm, 2051 const Register& ra) { 2052 VIXL_ASSERT(allow_macro_instructions_); 2053 VIXL_ASSERT(!rd.IsZero()); 2054 VIXL_ASSERT(!rn.IsZero()); 2055 VIXL_ASSERT(!rm.IsZero()); 2056 VIXL_ASSERT(!ra.IsZero()); 2057 SingleEmissionCheckScope guard(this); 2058 umaddl(rd, rn, rm, ra); 2059 } 2060 void Umull(const Register& rd, const Register& rn, const Register& rm) { 2061 VIXL_ASSERT(allow_macro_instructions_); 2062 VIXL_ASSERT(!rd.IsZero()); 2063 VIXL_ASSERT(!rn.IsZero()); 2064 VIXL_ASSERT(!rm.IsZero()); 2065 SingleEmissionCheckScope guard(this); 2066 umull(rd, rn, rm); 2067 } 2068 void Umulh(const Register& xd, const Register& xn, const Register& xm) { 2069 VIXL_ASSERT(allow_macro_instructions_); 2070 VIXL_ASSERT(!xd.IsZero()); 2071 VIXL_ASSERT(!xn.IsZero()); 2072 VIXL_ASSERT(!xm.IsZero()); 2073 SingleEmissionCheckScope guard(this); 2074 umulh(xd, xn, xm); 2075 } 2076 void Umsubl(const Register& rd, 2077 const Register& rn, 2078 const Register& rm, 2079 const Register& ra) { 2080 VIXL_ASSERT(allow_macro_instructions_); 2081 VIXL_ASSERT(!rd.IsZero()); 2082 VIXL_ASSERT(!rn.IsZero()); 2083 VIXL_ASSERT(!rm.IsZero()); 2084 VIXL_ASSERT(!ra.IsZero()); 2085 SingleEmissionCheckScope guard(this); 2086 umsubl(rd, rn, rm, ra); 2087 } 2088 void Unreachable() { 2089 VIXL_ASSERT(allow_macro_instructions_); 2090 SingleEmissionCheckScope guard(this); 2091 if (generate_simulator_code_) { 2092 hlt(kUnreachableOpcode); 2093 } else { 2094 // Branch to 0 to generate a segfault. 2095 // lr - kInstructionSize is the address of the offending instruction. 2096 blr(xzr); 2097 } 2098 } 2099 void Uxtb(const Register& rd, const Register& rn) { 2100 VIXL_ASSERT(allow_macro_instructions_); 2101 VIXL_ASSERT(!rd.IsZero()); 2102 VIXL_ASSERT(!rn.IsZero()); 2103 SingleEmissionCheckScope guard(this); 2104 uxtb(rd, rn); 2105 } 2106 void Uxth(const Register& rd, const Register& rn) { 2107 VIXL_ASSERT(allow_macro_instructions_); 2108 VIXL_ASSERT(!rd.IsZero()); 2109 VIXL_ASSERT(!rn.IsZero()); 2110 SingleEmissionCheckScope guard(this); 2111 uxth(rd, rn); 2112 } 2113 void Uxtw(const Register& rd, const Register& rn) { 2114 VIXL_ASSERT(allow_macro_instructions_); 2115 VIXL_ASSERT(!rd.IsZero()); 2116 VIXL_ASSERT(!rn.IsZero()); 2117 SingleEmissionCheckScope guard(this); 2118 uxtw(rd, rn); 2119 } 2120 2121 // NEON 3 vector register instructions. 2122 #define NEON_3VREG_MACRO_LIST(V) \ 2123 V(add, Add) \ 2124 V(addhn, Addhn) \ 2125 V(addhn2, Addhn2) \ 2126 V(addp, Addp) \ 2127 V(and_, And) \ 2128 V(bic, Bic) \ 2129 V(bif, Bif) \ 2130 V(bit, Bit) \ 2131 V(bsl, Bsl) \ 2132 V(cmeq, Cmeq) \ 2133 V(cmge, Cmge) \ 2134 V(cmgt, Cmgt) \ 2135 V(cmhi, Cmhi) \ 2136 V(cmhs, Cmhs) \ 2137 V(cmtst, Cmtst) \ 2138 V(eor, Eor) \ 2139 V(fabd, Fabd) \ 2140 V(facge, Facge) \ 2141 V(facgt, Facgt) \ 2142 V(faddp, Faddp) \ 2143 V(fcmeq, Fcmeq) \ 2144 V(fcmge, Fcmge) \ 2145 V(fcmgt, Fcmgt) \ 2146 V(fmaxnmp, Fmaxnmp) \ 2147 V(fmaxp, Fmaxp) \ 2148 V(fminnmp, Fminnmp) \ 2149 V(fminp, Fminp) \ 2150 V(fmla, Fmla) \ 2151 V(fmls, Fmls) \ 2152 V(fmulx, Fmulx) \ 2153 V(frecps, Frecps) \ 2154 V(frsqrts, Frsqrts) \ 2155 V(mla, Mla) \ 2156 V(mls, Mls) \ 2157 V(mul, Mul) \ 2158 V(orn, Orn) \ 2159 V(orr, Orr) \ 2160 V(pmul, Pmul) \ 2161 V(pmull, Pmull) \ 2162 V(pmull2, Pmull2) \ 2163 V(raddhn, Raddhn) \ 2164 V(raddhn2, Raddhn2) \ 2165 V(rsubhn, Rsubhn) \ 2166 V(rsubhn2, Rsubhn2) \ 2167 V(saba, Saba) \ 2168 V(sabal, Sabal) \ 2169 V(sabal2, Sabal2) \ 2170 V(sabd, Sabd) \ 2171 V(sabdl, Sabdl) \ 2172 V(sabdl2, Sabdl2) \ 2173 V(saddl, Saddl) \ 2174 V(saddl2, Saddl2) \ 2175 V(saddw, Saddw) \ 2176 V(saddw2, Saddw2) \ 2177 V(shadd, Shadd) \ 2178 V(shsub, Shsub) \ 2179 V(smax, Smax) \ 2180 V(smaxp, Smaxp) \ 2181 V(smin, Smin) \ 2182 V(sminp, Sminp) \ 2183 V(smlal, Smlal) \ 2184 V(smlal2, Smlal2) \ 2185 V(smlsl, Smlsl) \ 2186 V(smlsl2, Smlsl2) \ 2187 V(smull, Smull) \ 2188 V(smull2, Smull2) \ 2189 V(sqadd, Sqadd) \ 2190 V(sqdmlal, Sqdmlal) \ 2191 V(sqdmlal2, Sqdmlal2) \ 2192 V(sqdmlsl, Sqdmlsl) \ 2193 V(sqdmlsl2, Sqdmlsl2) \ 2194 V(sqdmulh, Sqdmulh) \ 2195 V(sqdmull, Sqdmull) \ 2196 V(sqdmull2, Sqdmull2) \ 2197 V(sqrdmulh, Sqrdmulh) \ 2198 V(sqrshl, Sqrshl) \ 2199 V(sqshl, Sqshl) \ 2200 V(sqsub, Sqsub) \ 2201 V(srhadd, Srhadd) \ 2202 V(srshl, Srshl) \ 2203 V(sshl, Sshl) \ 2204 V(ssubl, Ssubl) \ 2205 V(ssubl2, Ssubl2) \ 2206 V(ssubw, Ssubw) \ 2207 V(ssubw2, Ssubw2) \ 2208 V(sub, Sub) \ 2209 V(subhn, Subhn) \ 2210 V(subhn2, Subhn2) \ 2211 V(trn1, Trn1) \ 2212 V(trn2, Trn2) \ 2213 V(uaba, Uaba) \ 2214 V(uabal, Uabal) \ 2215 V(uabal2, Uabal2) \ 2216 V(uabd, Uabd) \ 2217 V(uabdl, Uabdl) \ 2218 V(uabdl2, Uabdl2) \ 2219 V(uaddl, Uaddl) \ 2220 V(uaddl2, Uaddl2) \ 2221 V(uaddw, Uaddw) \ 2222 V(uaddw2, Uaddw2) \ 2223 V(uhadd, Uhadd) \ 2224 V(uhsub, Uhsub) \ 2225 V(umax, Umax) \ 2226 V(umaxp, Umaxp) \ 2227 V(umin, Umin) \ 2228 V(uminp, Uminp) \ 2229 V(umlal, Umlal) \ 2230 V(umlal2, Umlal2) \ 2231 V(umlsl, Umlsl) \ 2232 V(umlsl2, Umlsl2) \ 2233 V(umull, Umull) \ 2234 V(umull2, Umull2) \ 2235 V(uqadd, Uqadd) \ 2236 V(uqrshl, Uqrshl) \ 2237 V(uqshl, Uqshl) \ 2238 V(uqsub, Uqsub) \ 2239 V(urhadd, Urhadd) \ 2240 V(urshl, Urshl) \ 2241 V(ushl, Ushl) \ 2242 V(usubl, Usubl) \ 2243 V(usubl2, Usubl2) \ 2244 V(usubw, Usubw) \ 2245 V(usubw2, Usubw2) \ 2246 V(uzp1, Uzp1) \ 2247 V(uzp2, Uzp2) \ 2248 V(zip1, Zip1) \ 2249 V(zip2, Zip2) 2250 2251 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 2252 void MASM(const VRegister& vd, const VRegister& vn, const VRegister& vm) { \ 2253 VIXL_ASSERT(allow_macro_instructions_); \ 2254 SingleEmissionCheckScope guard(this); \ 2255 ASM(vd, vn, vm); \ 2256 } 2257 NEON_3VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 2258 #undef DEFINE_MACRO_ASM_FUNC 2259 2260 // NEON 2 vector register instructions. 2261 #define NEON_2VREG_MACRO_LIST(V) \ 2262 V(abs, Abs) \ 2263 V(addp, Addp) \ 2264 V(addv, Addv) \ 2265 V(cls, Cls) \ 2266 V(clz, Clz) \ 2267 V(cnt, Cnt) \ 2268 V(fabs, Fabs) \ 2269 V(faddp, Faddp) \ 2270 V(fcvtas, Fcvtas) \ 2271 V(fcvtau, Fcvtau) \ 2272 V(fcvtms, Fcvtms) \ 2273 V(fcvtmu, Fcvtmu) \ 2274 V(fcvtns, Fcvtns) \ 2275 V(fcvtnu, Fcvtnu) \ 2276 V(fcvtps, Fcvtps) \ 2277 V(fcvtpu, Fcvtpu) \ 2278 V(fmaxnmp, Fmaxnmp) \ 2279 V(fmaxnmv, Fmaxnmv) \ 2280 V(fmaxp, Fmaxp) \ 2281 V(fmaxv, Fmaxv) \ 2282 V(fminnmp, Fminnmp) \ 2283 V(fminnmv, Fminnmv) \ 2284 V(fminp, Fminp) \ 2285 V(fminv, Fminv) \ 2286 V(fneg, Fneg) \ 2287 V(frecpe, Frecpe) \ 2288 V(frecpx, Frecpx) \ 2289 V(frinta, Frinta) \ 2290 V(frinti, Frinti) \ 2291 V(frintm, Frintm) \ 2292 V(frintn, Frintn) \ 2293 V(frintp, Frintp) \ 2294 V(frintx, Frintx) \ 2295 V(frintz, Frintz) \ 2296 V(frsqrte, Frsqrte) \ 2297 V(fsqrt, Fsqrt) \ 2298 V(mov, Mov) \ 2299 V(mvn, Mvn) \ 2300 V(neg, Neg) \ 2301 V(not_, Not) \ 2302 V(rbit, Rbit) \ 2303 V(rev16, Rev16) \ 2304 V(rev32, Rev32) \ 2305 V(rev64, Rev64) \ 2306 V(sadalp, Sadalp) \ 2307 V(saddlp, Saddlp) \ 2308 V(saddlv, Saddlv) \ 2309 V(smaxv, Smaxv) \ 2310 V(sminv, Sminv) \ 2311 V(sqabs, Sqabs) \ 2312 V(sqneg, Sqneg) \ 2313 V(sqxtn, Sqxtn) \ 2314 V(sqxtn2, Sqxtn2) \ 2315 V(sqxtun, Sqxtun) \ 2316 V(sqxtun2, Sqxtun2) \ 2317 V(suqadd, Suqadd) \ 2318 V(sxtl, Sxtl) \ 2319 V(sxtl2, Sxtl2) \ 2320 V(uadalp, Uadalp) \ 2321 V(uaddlp, Uaddlp) \ 2322 V(uaddlv, Uaddlv) \ 2323 V(umaxv, Umaxv) \ 2324 V(uminv, Uminv) \ 2325 V(uqxtn, Uqxtn) \ 2326 V(uqxtn2, Uqxtn2) \ 2327 V(urecpe, Urecpe) \ 2328 V(ursqrte, Ursqrte) \ 2329 V(usqadd, Usqadd) \ 2330 V(uxtl, Uxtl) \ 2331 V(uxtl2, Uxtl2) \ 2332 V(xtn, Xtn) \ 2333 V(xtn2, Xtn2) 2334 2335 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 2336 void MASM(const VRegister& vd, const VRegister& vn) { \ 2337 VIXL_ASSERT(allow_macro_instructions_); \ 2338 SingleEmissionCheckScope guard(this); \ 2339 ASM(vd, vn); \ 2340 } 2341 NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 2342 #undef DEFINE_MACRO_ASM_FUNC 2343 2344 // NEON 2 vector register with immediate instructions. 2345 #define NEON_2VREG_FPIMM_MACRO_LIST(V) \ 2346 V(fcmeq, Fcmeq) \ 2347 V(fcmge, Fcmge) \ 2348 V(fcmgt, Fcmgt) \ 2349 V(fcmle, Fcmle) \ 2350 V(fcmlt, Fcmlt) 2351 2352 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 2353 void MASM(const VRegister& vd, const VRegister& vn, double imm) { \ 2354 VIXL_ASSERT(allow_macro_instructions_); \ 2355 SingleEmissionCheckScope guard(this); \ 2356 ASM(vd, vn, imm); \ 2357 } 2358 NEON_2VREG_FPIMM_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 2359 #undef DEFINE_MACRO_ASM_FUNC 2360 2361 // NEON by element instructions. 2362 #define NEON_BYELEMENT_MACRO_LIST(V) \ 2363 V(fmul, Fmul) \ 2364 V(fmla, Fmla) \ 2365 V(fmls, Fmls) \ 2366 V(fmulx, Fmulx) \ 2367 V(mul, Mul) \ 2368 V(mla, Mla) \ 2369 V(mls, Mls) \ 2370 V(sqdmulh, Sqdmulh) \ 2371 V(sqrdmulh, Sqrdmulh) \ 2372 V(sqdmull, Sqdmull) \ 2373 V(sqdmull2, Sqdmull2) \ 2374 V(sqdmlal, Sqdmlal) \ 2375 V(sqdmlal2, Sqdmlal2) \ 2376 V(sqdmlsl, Sqdmlsl) \ 2377 V(sqdmlsl2, Sqdmlsl2) \ 2378 V(smull, Smull) \ 2379 V(smull2, Smull2) \ 2380 V(smlal, Smlal) \ 2381 V(smlal2, Smlal2) \ 2382 V(smlsl, Smlsl) \ 2383 V(smlsl2, Smlsl2) \ 2384 V(umull, Umull) \ 2385 V(umull2, Umull2) \ 2386 V(umlal, Umlal) \ 2387 V(umlal2, Umlal2) \ 2388 V(umlsl, Umlsl) \ 2389 V(umlsl2, Umlsl2) 2390 2391 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 2392 void MASM(const VRegister& vd, \ 2393 const VRegister& vn, \ 2394 const VRegister& vm, \ 2395 int vm_index) { \ 2396 VIXL_ASSERT(allow_macro_instructions_); \ 2397 SingleEmissionCheckScope guard(this); \ 2398 ASM(vd, vn, vm, vm_index); \ 2399 } 2400 NEON_BYELEMENT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 2401 #undef DEFINE_MACRO_ASM_FUNC 2402 2403 #define NEON_2VREG_SHIFT_MACRO_LIST(V) \ 2404 V(rshrn, Rshrn) \ 2405 V(rshrn2, Rshrn2) \ 2406 V(shl, Shl) \ 2407 V(shll, Shll) \ 2408 V(shll2, Shll2) \ 2409 V(shrn, Shrn) \ 2410 V(shrn2, Shrn2) \ 2411 V(sli, Sli) \ 2412 V(sqrshrn, Sqrshrn) \ 2413 V(sqrshrn2, Sqrshrn2) \ 2414 V(sqrshrun, Sqrshrun) \ 2415 V(sqrshrun2, Sqrshrun2) \ 2416 V(sqshl, Sqshl) \ 2417 V(sqshlu, Sqshlu) \ 2418 V(sqshrn, Sqshrn) \ 2419 V(sqshrn2, Sqshrn2) \ 2420 V(sqshrun, Sqshrun) \ 2421 V(sqshrun2, Sqshrun2) \ 2422 V(sri, Sri) \ 2423 V(srshr, Srshr) \ 2424 V(srsra, Srsra) \ 2425 V(sshll, Sshll) \ 2426 V(sshll2, Sshll2) \ 2427 V(sshr, Sshr) \ 2428 V(ssra, Ssra) \ 2429 V(uqrshrn, Uqrshrn) \ 2430 V(uqrshrn2, Uqrshrn2) \ 2431 V(uqshl, Uqshl) \ 2432 V(uqshrn, Uqshrn) \ 2433 V(uqshrn2, Uqshrn2) \ 2434 V(urshr, Urshr) \ 2435 V(ursra, Ursra) \ 2436 V(ushll, Ushll) \ 2437 V(ushll2, Ushll2) \ 2438 V(ushr, Ushr) \ 2439 V(usra, Usra) 2440 2441 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM) \ 2442 void MASM(const VRegister& vd, const VRegister& vn, int shift) { \ 2443 VIXL_ASSERT(allow_macro_instructions_); \ 2444 SingleEmissionCheckScope guard(this); \ 2445 ASM(vd, vn, shift); \ 2446 } 2447 NEON_2VREG_SHIFT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC) 2448 #undef DEFINE_MACRO_ASM_FUNC 2449 2450 void Bic(const VRegister& vd, const int imm8, const int left_shift = 0) { 2451 VIXL_ASSERT(allow_macro_instructions_); 2452 SingleEmissionCheckScope guard(this); 2453 bic(vd, imm8, left_shift); 2454 } 2455 void Cmeq(const VRegister& vd, const VRegister& vn, int imm) { 2456 VIXL_ASSERT(allow_macro_instructions_); 2457 SingleEmissionCheckScope guard(this); 2458 cmeq(vd, vn, imm); 2459 } 2460 void Cmge(const VRegister& vd, const VRegister& vn, int imm) { 2461 VIXL_ASSERT(allow_macro_instructions_); 2462 SingleEmissionCheckScope guard(this); 2463 cmge(vd, vn, imm); 2464 } 2465 void Cmgt(const VRegister& vd, const VRegister& vn, int imm) { 2466 VIXL_ASSERT(allow_macro_instructions_); 2467 SingleEmissionCheckScope guard(this); 2468 cmgt(vd, vn, imm); 2469 } 2470 void Cmle(const VRegister& vd, const VRegister& vn, int imm) { 2471 VIXL_ASSERT(allow_macro_instructions_); 2472 SingleEmissionCheckScope guard(this); 2473 cmle(vd, vn, imm); 2474 } 2475 void Cmlt(const VRegister& vd, const VRegister& vn, int imm) { 2476 VIXL_ASSERT(allow_macro_instructions_); 2477 SingleEmissionCheckScope guard(this); 2478 cmlt(vd, vn, imm); 2479 } 2480 void Dup(const VRegister& vd, const VRegister& vn, int index) { 2481 VIXL_ASSERT(allow_macro_instructions_); 2482 SingleEmissionCheckScope guard(this); 2483 dup(vd, vn, index); 2484 } 2485 void Dup(const VRegister& vd, const Register& rn) { 2486 VIXL_ASSERT(allow_macro_instructions_); 2487 SingleEmissionCheckScope guard(this); 2488 dup(vd, rn); 2489 } 2490 void Ext(const VRegister& vd, 2491 const VRegister& vn, 2492 const VRegister& vm, 2493 int index) { 2494 VIXL_ASSERT(allow_macro_instructions_); 2495 SingleEmissionCheckScope guard(this); 2496 ext(vd, vn, vm, index); 2497 } 2498 void Ins(const VRegister& vd, 2499 int vd_index, 2500 const VRegister& vn, 2501 int vn_index) { 2502 VIXL_ASSERT(allow_macro_instructions_); 2503 SingleEmissionCheckScope guard(this); 2504 ins(vd, vd_index, vn, vn_index); 2505 } 2506 void Ins(const VRegister& vd, int vd_index, const Register& rn) { 2507 VIXL_ASSERT(allow_macro_instructions_); 2508 SingleEmissionCheckScope guard(this); 2509 ins(vd, vd_index, rn); 2510 } 2511 void Ld1(const VRegister& vt, const MemOperand& src) { 2512 VIXL_ASSERT(allow_macro_instructions_); 2513 SingleEmissionCheckScope guard(this); 2514 ld1(vt, src); 2515 } 2516 void Ld1(const VRegister& vt, const VRegister& vt2, const MemOperand& src) { 2517 VIXL_ASSERT(allow_macro_instructions_); 2518 SingleEmissionCheckScope guard(this); 2519 ld1(vt, vt2, src); 2520 } 2521 void Ld1(const VRegister& vt, 2522 const VRegister& vt2, 2523 const VRegister& vt3, 2524 const MemOperand& src) { 2525 VIXL_ASSERT(allow_macro_instructions_); 2526 SingleEmissionCheckScope guard(this); 2527 ld1(vt, vt2, vt3, src); 2528 } 2529 void Ld1(const VRegister& vt, 2530 const VRegister& vt2, 2531 const VRegister& vt3, 2532 const VRegister& vt4, 2533 const MemOperand& src) { 2534 VIXL_ASSERT(allow_macro_instructions_); 2535 SingleEmissionCheckScope guard(this); 2536 ld1(vt, vt2, vt3, vt4, src); 2537 } 2538 void Ld1(const VRegister& vt, int lane, const MemOperand& src) { 2539 VIXL_ASSERT(allow_macro_instructions_); 2540 SingleEmissionCheckScope guard(this); 2541 ld1(vt, lane, src); 2542 } 2543 void Ld1r(const VRegister& vt, const MemOperand& src) { 2544 VIXL_ASSERT(allow_macro_instructions_); 2545 SingleEmissionCheckScope guard(this); 2546 ld1r(vt, src); 2547 } 2548 void Ld2(const VRegister& vt, const VRegister& vt2, const MemOperand& src) { 2549 VIXL_ASSERT(allow_macro_instructions_); 2550 SingleEmissionCheckScope guard(this); 2551 ld2(vt, vt2, src); 2552 } 2553 void Ld2(const VRegister& vt, 2554 const VRegister& vt2, 2555 int lane, 2556 const MemOperand& src) { 2557 VIXL_ASSERT(allow_macro_instructions_); 2558 SingleEmissionCheckScope guard(this); 2559 ld2(vt, vt2, lane, src); 2560 } 2561 void Ld2r(const VRegister& vt, const VRegister& vt2, const MemOperand& src) { 2562 VIXL_ASSERT(allow_macro_instructions_); 2563 SingleEmissionCheckScope guard(this); 2564 ld2r(vt, vt2, src); 2565 } 2566 void Ld3(const VRegister& vt, 2567 const VRegister& vt2, 2568 const VRegister& vt3, 2569 const MemOperand& src) { 2570 VIXL_ASSERT(allow_macro_instructions_); 2571 SingleEmissionCheckScope guard(this); 2572 ld3(vt, vt2, vt3, src); 2573 } 2574 void Ld3(const VRegister& vt, 2575 const VRegister& vt2, 2576 const VRegister& vt3, 2577 int lane, 2578 const MemOperand& src) { 2579 VIXL_ASSERT(allow_macro_instructions_); 2580 SingleEmissionCheckScope guard(this); 2581 ld3(vt, vt2, vt3, lane, src); 2582 } 2583 void Ld3r(const VRegister& vt, 2584 const VRegister& vt2, 2585 const VRegister& vt3, 2586 const MemOperand& src) { 2587 VIXL_ASSERT(allow_macro_instructions_); 2588 SingleEmissionCheckScope guard(this); 2589 ld3r(vt, vt2, vt3, src); 2590 } 2591 void Ld4(const VRegister& vt, 2592 const VRegister& vt2, 2593 const VRegister& vt3, 2594 const VRegister& vt4, 2595 const MemOperand& src) { 2596 VIXL_ASSERT(allow_macro_instructions_); 2597 SingleEmissionCheckScope guard(this); 2598 ld4(vt, vt2, vt3, vt4, src); 2599 } 2600 void Ld4(const VRegister& vt, 2601 const VRegister& vt2, 2602 const VRegister& vt3, 2603 const VRegister& vt4, 2604 int lane, 2605 const MemOperand& src) { 2606 VIXL_ASSERT(allow_macro_instructions_); 2607 SingleEmissionCheckScope guard(this); 2608 ld4(vt, vt2, vt3, vt4, lane, src); 2609 } 2610 void Ld4r(const VRegister& vt, 2611 const VRegister& vt2, 2612 const VRegister& vt3, 2613 const VRegister& vt4, 2614 const MemOperand& src) { 2615 VIXL_ASSERT(allow_macro_instructions_); 2616 SingleEmissionCheckScope guard(this); 2617 ld4r(vt, vt2, vt3, vt4, src); 2618 } 2619 void Mov(const VRegister& vd, 2620 int vd_index, 2621 const VRegister& vn, 2622 int vn_index) { 2623 VIXL_ASSERT(allow_macro_instructions_); 2624 SingleEmissionCheckScope guard(this); 2625 mov(vd, vd_index, vn, vn_index); 2626 } 2627 void Mov(const VRegister& vd, const VRegister& vn, int index) { 2628 VIXL_ASSERT(allow_macro_instructions_); 2629 SingleEmissionCheckScope guard(this); 2630 mov(vd, vn, index); 2631 } 2632 void Mov(const VRegister& vd, int vd_index, const Register& rn) { 2633 VIXL_ASSERT(allow_macro_instructions_); 2634 SingleEmissionCheckScope guard(this); 2635 mov(vd, vd_index, rn); 2636 } 2637 void Mov(const Register& rd, const VRegister& vn, int vn_index) { 2638 VIXL_ASSERT(allow_macro_instructions_); 2639 SingleEmissionCheckScope guard(this); 2640 mov(rd, vn, vn_index); 2641 } 2642 void Movi(const VRegister& vd, 2643 uint64_t imm, 2644 Shift shift = LSL, 2645 int shift_amount = 0); 2646 void Movi(const VRegister& vd, uint64_t hi, uint64_t lo); 2647 void Mvni(const VRegister& vd, 2648 const int imm8, 2649 Shift shift = LSL, 2650 const int shift_amount = 0) { 2651 VIXL_ASSERT(allow_macro_instructions_); 2652 SingleEmissionCheckScope guard(this); 2653 mvni(vd, imm8, shift, shift_amount); 2654 } 2655 void Orr(const VRegister& vd, const int imm8, const int left_shift = 0) { 2656 VIXL_ASSERT(allow_macro_instructions_); 2657 SingleEmissionCheckScope guard(this); 2658 orr(vd, imm8, left_shift); 2659 } 2660 void Scvtf(const VRegister& vd, const VRegister& vn, int fbits = 0) { 2661 VIXL_ASSERT(allow_macro_instructions_); 2662 SingleEmissionCheckScope guard(this); 2663 scvtf(vd, vn, fbits); 2664 } 2665 void Ucvtf(const VRegister& vd, const VRegister& vn, int fbits = 0) { 2666 VIXL_ASSERT(allow_macro_instructions_); 2667 SingleEmissionCheckScope guard(this); 2668 ucvtf(vd, vn, fbits); 2669 } 2670 void Fcvtzs(const VRegister& vd, const VRegister& vn, int fbits = 0) { 2671 VIXL_ASSERT(allow_macro_instructions_); 2672 SingleEmissionCheckScope guard(this); 2673 fcvtzs(vd, vn, fbits); 2674 } 2675 void Fcvtzu(const VRegister& vd, const VRegister& vn, int fbits = 0) { 2676 VIXL_ASSERT(allow_macro_instructions_); 2677 SingleEmissionCheckScope guard(this); 2678 fcvtzu(vd, vn, fbits); 2679 } 2680 void St1(const VRegister& vt, const MemOperand& dst) { 2681 VIXL_ASSERT(allow_macro_instructions_); 2682 SingleEmissionCheckScope guard(this); 2683 st1(vt, dst); 2684 } 2685 void St1(const VRegister& vt, const VRegister& vt2, const MemOperand& dst) { 2686 VIXL_ASSERT(allow_macro_instructions_); 2687 SingleEmissionCheckScope guard(this); 2688 st1(vt, vt2, dst); 2689 } 2690 void St1(const VRegister& vt, 2691 const VRegister& vt2, 2692 const VRegister& vt3, 2693 const MemOperand& dst) { 2694 VIXL_ASSERT(allow_macro_instructions_); 2695 SingleEmissionCheckScope guard(this); 2696 st1(vt, vt2, vt3, dst); 2697 } 2698 void St1(const VRegister& vt, 2699 const VRegister& vt2, 2700 const VRegister& vt3, 2701 const VRegister& vt4, 2702 const MemOperand& dst) { 2703 VIXL_ASSERT(allow_macro_instructions_); 2704 SingleEmissionCheckScope guard(this); 2705 st1(vt, vt2, vt3, vt4, dst); 2706 } 2707 void St1(const VRegister& vt, int lane, const MemOperand& dst) { 2708 VIXL_ASSERT(allow_macro_instructions_); 2709 SingleEmissionCheckScope guard(this); 2710 st1(vt, lane, dst); 2711 } 2712 void St2(const VRegister& vt, const VRegister& vt2, const MemOperand& dst) { 2713 VIXL_ASSERT(allow_macro_instructions_); 2714 SingleEmissionCheckScope guard(this); 2715 st2(vt, vt2, dst); 2716 } 2717 void St3(const VRegister& vt, 2718 const VRegister& vt2, 2719 const VRegister& vt3, 2720 const MemOperand& dst) { 2721 VIXL_ASSERT(allow_macro_instructions_); 2722 SingleEmissionCheckScope guard(this); 2723 st3(vt, vt2, vt3, dst); 2724 } 2725 void St4(const VRegister& vt, 2726 const VRegister& vt2, 2727 const VRegister& vt3, 2728 const VRegister& vt4, 2729 const MemOperand& dst) { 2730 VIXL_ASSERT(allow_macro_instructions_); 2731 SingleEmissionCheckScope guard(this); 2732 st4(vt, vt2, vt3, vt4, dst); 2733 } 2734 void St2(const VRegister& vt, 2735 const VRegister& vt2, 2736 int lane, 2737 const MemOperand& dst) { 2738 VIXL_ASSERT(allow_macro_instructions_); 2739 SingleEmissionCheckScope guard(this); 2740 st2(vt, vt2, lane, dst); 2741 } 2742 void St3(const VRegister& vt, 2743 const VRegister& vt2, 2744 const VRegister& vt3, 2745 int lane, 2746 const MemOperand& dst) { 2747 VIXL_ASSERT(allow_macro_instructions_); 2748 SingleEmissionCheckScope guard(this); 2749 st3(vt, vt2, vt3, lane, dst); 2750 } 2751 void St4(const VRegister& vt, 2752 const VRegister& vt2, 2753 const VRegister& vt3, 2754 const VRegister& vt4, 2755 int lane, 2756 const MemOperand& dst) { 2757 VIXL_ASSERT(allow_macro_instructions_); 2758 SingleEmissionCheckScope guard(this); 2759 st4(vt, vt2, vt3, vt4, lane, dst); 2760 } 2761 void Smov(const Register& rd, const VRegister& vn, int vn_index) { 2762 VIXL_ASSERT(allow_macro_instructions_); 2763 SingleEmissionCheckScope guard(this); 2764 smov(rd, vn, vn_index); 2765 } 2766 void Umov(const Register& rd, const VRegister& vn, int vn_index) { 2767 VIXL_ASSERT(allow_macro_instructions_); 2768 SingleEmissionCheckScope guard(this); 2769 umov(rd, vn, vn_index); 2770 } 2771 void Crc32b(const Register& rd, const Register& rn, const Register& rm) { 2772 VIXL_ASSERT(allow_macro_instructions_); 2773 SingleEmissionCheckScope guard(this); 2774 crc32b(rd, rn, rm); 2775 } 2776 void Crc32h(const Register& rd, const Register& rn, const Register& rm) { 2777 VIXL_ASSERT(allow_macro_instructions_); 2778 SingleEmissionCheckScope guard(this); 2779 crc32h(rd, rn, rm); 2780 } 2781 void Crc32w(const Register& rd, const Register& rn, const Register& rm) { 2782 VIXL_ASSERT(allow_macro_instructions_); 2783 SingleEmissionCheckScope guard(this); 2784 crc32w(rd, rn, rm); 2785 } 2786 void Crc32x(const Register& rd, const Register& rn, const Register& rm) { 2787 VIXL_ASSERT(allow_macro_instructions_); 2788 SingleEmissionCheckScope guard(this); 2789 crc32x(rd, rn, rm); 2790 } 2791 void Crc32cb(const Register& rd, const Register& rn, const Register& rm) { 2792 VIXL_ASSERT(allow_macro_instructions_); 2793 SingleEmissionCheckScope guard(this); 2794 crc32cb(rd, rn, rm); 2795 } 2796 void Crc32ch(const Register& rd, const Register& rn, const Register& rm) { 2797 VIXL_ASSERT(allow_macro_instructions_); 2798 SingleEmissionCheckScope guard(this); 2799 crc32ch(rd, rn, rm); 2800 } 2801 void Crc32cw(const Register& rd, const Register& rn, const Register& rm) { 2802 VIXL_ASSERT(allow_macro_instructions_); 2803 SingleEmissionCheckScope guard(this); 2804 crc32cw(rd, rn, rm); 2805 } 2806 void Crc32cx(const Register& rd, const Register& rn, const Register& rm) { 2807 VIXL_ASSERT(allow_macro_instructions_); 2808 SingleEmissionCheckScope guard(this); 2809 crc32cx(rd, rn, rm); 2810 } 2811 2812 template <typename T> 2813 Literal<T>* CreateLiteralDestroyedWithPool(T value) { 2814 return new Literal<T>(value, 2815 &literal_pool_, 2816 RawLiteral::kDeletedOnPoolDestruction); 2817 } 2818 2819 template <typename T> 2820 Literal<T>* CreateLiteralDestroyedWithPool(T high64, T low64) { 2821 return new Literal<T>(high64, 2822 low64, 2823 &literal_pool_, 2824 RawLiteral::kDeletedOnPoolDestruction); 2825 } 2826 2827 // Push the system stack pointer (sp) down to allow the same to be done to 2828 // the current stack pointer (according to StackPointer()). This must be 2829 // called _before_ accessing the memory. 2830 // 2831 // This is necessary when pushing or otherwise adding things to the stack, to 2832 // satisfy the AAPCS64 constraint that the memory below the system stack 2833 // pointer is not accessed. 2834 // 2835 // This method asserts that StackPointer() is not sp, since the call does 2836 // not make sense in that context. 2837 // 2838 // TODO: This method can only accept values of 'space' that can be encoded in 2839 // one instruction. Refer to the implementation for details. 2840 void BumpSystemStackPointer(const Operand& space); 2841 2842 virtual bool AllowMacroInstructions() const VIXL_OVERRIDE { 2843 return allow_macro_instructions_; 2844 } 2845 2846 virtual bool ArePoolsBlocked() const VIXL_OVERRIDE { 2847 return IsLiteralPoolBlocked() && IsVeneerPoolBlocked(); 2848 } 2849 2850 void SetGenerateSimulatorCode(bool value) { 2851 generate_simulator_code_ = value; 2852 } 2853 2854 bool GenerateSimulatorCode() const { return generate_simulator_code_; } 2855 2856 size_t GetLiteralPoolSize() const { return literal_pool_.GetSize(); } 2857 VIXL_DEPRECATED("GetLiteralPoolSize", size_t LiteralPoolSize() const) { 2858 return GetLiteralPoolSize(); 2859 } 2860 2861 size_t GetLiteralPoolMaxSize() const { return literal_pool_.GetMaxSize(); } 2862 VIXL_DEPRECATED("GetLiteralPoolMaxSize", size_t LiteralPoolMaxSize() const) { 2863 return GetLiteralPoolMaxSize(); 2864 } 2865 2866 size_t GetVeneerPoolMaxSize() const { return veneer_pool_.GetMaxSize(); } 2867 VIXL_DEPRECATED("GetVeneerPoolMaxSize", size_t VeneerPoolMaxSize() const) { 2868 return GetVeneerPoolMaxSize(); 2869 } 2870 2871 // The number of unresolved branches that may require a veneer. 2872 int GetNumberOfPotentialVeneers() const { 2873 return veneer_pool_.GetNumberOfPotentialVeneers(); 2874 } 2875 VIXL_DEPRECATED("GetNumberOfPotentialVeneers", 2876 int NumberOfPotentialVeneers() const) { 2877 return GetNumberOfPotentialVeneers(); 2878 } 2879 2880 ptrdiff_t GetNextCheckPoint() const { 2881 ptrdiff_t next_checkpoint_for_pools = 2882 std::min(literal_pool_.GetCheckpoint(), veneer_pool_.GetCheckpoint()); 2883 return std::min(next_checkpoint_for_pools, 2884 static_cast<ptrdiff_t>(GetBuffer().GetCapacity())); 2885 } 2886 VIXL_DEPRECATED("GetNextCheckPoint", ptrdiff_t NextCheckPoint()) { 2887 return GetNextCheckPoint(); 2888 } 2889 2890 void EmitLiteralPool(LiteralPool::EmitOption option) { 2891 if (!literal_pool_.IsEmpty()) literal_pool_.Emit(option); 2892 2893 checkpoint_ = GetNextCheckPoint(); 2894 recommended_checkpoint_ = literal_pool_.GetNextRecommendedCheckpoint(); 2895 } 2896 2897 void CheckEmitFor(size_t amount); 2898 void EnsureEmitFor(size_t amount) { 2899 ptrdiff_t offset = amount; 2900 ptrdiff_t max_pools_size = 2901 literal_pool_.GetMaxSize() + veneer_pool_.GetMaxSize(); 2902 ptrdiff_t cursor = GetCursorOffset(); 2903 if ((cursor >= recommended_checkpoint_) || 2904 ((cursor + offset + max_pools_size) >= checkpoint_)) { 2905 CheckEmitFor(amount); 2906 } 2907 } 2908 2909 void CheckEmitPoolsFor(size_t amount); 2910 virtual void EnsureEmitPoolsFor(size_t amount) VIXL_OVERRIDE { 2911 ptrdiff_t offset = amount; 2912 ptrdiff_t max_pools_size = 2913 literal_pool_.GetMaxSize() + veneer_pool_.GetMaxSize(); 2914 ptrdiff_t cursor = GetCursorOffset(); 2915 if ((cursor >= recommended_checkpoint_) || 2916 ((cursor + offset + max_pools_size) >= checkpoint_)) { 2917 CheckEmitPoolsFor(amount); 2918 } 2919 } 2920 2921 // Set the current stack pointer, but don't generate any code. 2922 void SetStackPointer(const Register& stack_pointer) { 2923 VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(stack_pointer)); 2924 sp_ = stack_pointer; 2925 } 2926 2927 // Return the current stack pointer, as set by SetStackPointer. 2928 const Register& StackPointer() const { return sp_; } 2929 2930 CPURegList* GetScratchRegisterList() { return &tmp_list_; } 2931 VIXL_DEPRECATED("GetScratchRegisterList", CPURegList* TmpList()) { 2932 return GetScratchRegisterList(); 2933 } 2934 2935 CPURegList* GetScratchFPRegisterList() { return &fptmp_list_; } 2936 VIXL_DEPRECATED("GetScratchFPRegisterList", CPURegList* FPTmpList()) { 2937 return GetScratchFPRegisterList(); 2938 } 2939 2940 // Get or set the current (most-deeply-nested) UseScratchRegisterScope. 2941 void SetCurrentScratchRegisterScope(UseScratchRegisterScope* scope) { 2942 current_scratch_scope_ = scope; 2943 } 2944 UseScratchRegisterScope* GetCurrentScratchRegisterScope() { 2945 return current_scratch_scope_; 2946 } 2947 2948 // Like printf, but print at run-time from generated code. 2949 // 2950 // The caller must ensure that arguments for floating-point placeholders 2951 // (such as %e, %f or %g) are VRegisters in format 1S or 1D, and that 2952 // arguments for integer placeholders are Registers. 2953 // 2954 // At the moment it is only possible to print the value of sp if it is the 2955 // current stack pointer. Otherwise, the MacroAssembler will automatically 2956 // update sp on every push (using BumpSystemStackPointer), so determining its 2957 // value is difficult. 2958 // 2959 // Format placeholders that refer to more than one argument, or to a specific 2960 // argument, are not supported. This includes formats like "%1$d" or "%.*d". 2961 // 2962 // This function automatically preserves caller-saved registers so that 2963 // calling code can use Printf at any point without having to worry about 2964 // corruption. The preservation mechanism generates a lot of code. If this is 2965 // a problem, preserve the important registers manually and then call 2966 // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are 2967 // implicitly preserved. 2968 void Printf(const char* format, 2969 CPURegister arg0 = NoCPUReg, 2970 CPURegister arg1 = NoCPUReg, 2971 CPURegister arg2 = NoCPUReg, 2972 CPURegister arg3 = NoCPUReg); 2973 2974 // Like Printf, but don't preserve any caller-saved registers, not even 'lr'. 2975 // 2976 // The return code from the system printf call will be returned in x0. 2977 void PrintfNoPreserve(const char* format, 2978 const CPURegister& arg0 = NoCPUReg, 2979 const CPURegister& arg1 = NoCPUReg, 2980 const CPURegister& arg2 = NoCPUReg, 2981 const CPURegister& arg3 = NoCPUReg); 2982 2983 // Trace control when running the debug simulator. 2984 // 2985 // For example: 2986 // 2987 // __ Trace(LOG_REGS, TRACE_ENABLE); 2988 // Will add registers to the trace if it wasn't already the case. 2989 // 2990 // __ Trace(LOG_DISASM, TRACE_DISABLE); 2991 // Will stop logging disassembly. It has no effect if the disassembly wasn't 2992 // already being logged. 2993 void Trace(TraceParameters parameters, TraceCommand command); 2994 2995 // Log the requested data independently of what is being traced. 2996 // 2997 // For example: 2998 // 2999 // __ Log(LOG_FLAGS) 3000 // Will output the flags. 3001 void Log(TraceParameters parameters); 3002 3003 // Enable or disable instrumentation when an Instrument visitor is attached to 3004 // the simulator. 3005 void EnableInstrumentation(); 3006 void DisableInstrumentation(); 3007 3008 // Add a marker to the instrumentation data produced by an Instrument visitor. 3009 // The name is a two character string that will be attached to the marker in 3010 // the output data. 3011 void AnnotateInstrumentation(const char* marker_name); 3012 3013 LiteralPool* GetLiteralPool() { return &literal_pool_; } 3014 3015 // Support for simulated runtime calls. 3016 3017 // `CallRuntime` requires variadic templating, that is only available from 3018 // C++11. 3019 #if __cplusplus >= 201103L 3020 #define VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT 3021 #endif // #if __cplusplus >= 201103L 3022 3023 #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT 3024 template <typename R, typename... P> 3025 void CallRuntime(R (*function)(P...)); 3026 #endif // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT 3027 3028 protected: 3029 void BlockLiteralPool() { literal_pool_.Block(); } 3030 void ReleaseLiteralPool() { literal_pool_.Release(); } 3031 bool IsLiteralPoolBlocked() const { return literal_pool_.IsBlocked(); } 3032 void BlockVeneerPool() { veneer_pool_.Block(); } 3033 void ReleaseVeneerPool() { veneer_pool_.Release(); } 3034 bool IsVeneerPoolBlocked() const { return veneer_pool_.IsBlocked(); } 3035 3036 virtual void BlockPools() VIXL_OVERRIDE { 3037 BlockLiteralPool(); 3038 BlockVeneerPool(); 3039 } 3040 3041 virtual void ReleasePools() VIXL_OVERRIDE { 3042 ReleaseLiteralPool(); 3043 ReleaseVeneerPool(); 3044 } 3045 3046 // The scopes below need to able to block and release a particular pool. 3047 // TODO: Consider removing those scopes or move them to 3048 // code-generation-scopes-vixl.h. 3049 friend class BlockPoolsScope; 3050 friend class BlockLiteralPoolScope; 3051 friend class BlockVeneerPoolScope; 3052 3053 virtual void SetAllowMacroInstructions(bool value) VIXL_OVERRIDE { 3054 allow_macro_instructions_ = value; 3055 } 3056 3057 // Helper used to query information about code generation and to generate 3058 // code for `csel`. 3059 // Here and for the related helpers below: 3060 // - Code is generated when `masm` is not `NULL`. 3061 // - On return and when set, `should_synthesise_left` and 3062 // `should_synthesise_right` will indicate whether `left` and `right` 3063 // should be synthesized in a temporary register. 3064 static void CselHelper(MacroAssembler* masm, 3065 const Register& rd, 3066 Operand left, 3067 Operand right, 3068 Condition cond, 3069 bool* should_synthesise_left = NULL, 3070 bool* should_synthesise_right = NULL); 3071 3072 // The helper returns `true` if it can handle the specified arguments. 3073 // Also see comments for `CselHelper()`. 3074 static bool CselSubHelperTwoImmediates(MacroAssembler* masm, 3075 const Register& rd, 3076 int64_t left, 3077 int64_t right, 3078 Condition cond, 3079 bool* should_synthesise_left, 3080 bool* should_synthesise_right); 3081 3082 // See comments for `CselHelper()`. 3083 static bool CselSubHelperTwoOrderedImmediates(MacroAssembler* masm, 3084 const Register& rd, 3085 int64_t left, 3086 int64_t right, 3087 Condition cond); 3088 3089 // See comments for `CselHelper()`. 3090 static void CselSubHelperRightSmallImmediate(MacroAssembler* masm, 3091 UseScratchRegisterScope* temps, 3092 const Register& rd, 3093 const Operand& left, 3094 const Operand& right, 3095 Condition cond, 3096 bool* should_synthesise_left); 3097 3098 private: 3099 // The actual Push and Pop implementations. These don't generate any code 3100 // other than that required for the push or pop. This allows 3101 // (Push|Pop)CPURegList to bundle together setup code for a large block of 3102 // registers. 3103 // 3104 // Note that size is per register, and is specified in bytes. 3105 void PushHelper(int count, 3106 int size, 3107 const CPURegister& src0, 3108 const CPURegister& src1, 3109 const CPURegister& src2, 3110 const CPURegister& src3); 3111 void PopHelper(int count, 3112 int size, 3113 const CPURegister& dst0, 3114 const CPURegister& dst1, 3115 const CPURegister& dst2, 3116 const CPURegister& dst3); 3117 3118 void Movi16bitHelper(const VRegister& vd, uint64_t imm); 3119 void Movi32bitHelper(const VRegister& vd, uint64_t imm); 3120 void Movi64bitHelper(const VRegister& vd, uint64_t imm); 3121 3122 // Perform necessary maintenance operations before a push or pop. 3123 // 3124 // Note that size is per register, and is specified in bytes. 3125 void PrepareForPush(int count, int size); 3126 void PrepareForPop(int count, int size); 3127 3128 // The actual implementation of load and store operations for CPURegList. 3129 enum LoadStoreCPURegListAction { kLoad, kStore }; 3130 void LoadStoreCPURegListHelper(LoadStoreCPURegListAction operation, 3131 CPURegList registers, 3132 const MemOperand& mem); 3133 // Returns a MemOperand suitable for loading or storing a CPURegList at `dst`. 3134 // This helper may allocate registers from `scratch_scope` and generate code 3135 // to compute an intermediate address. The resulting MemOperand is only valid 3136 // as long as `scratch_scope` remains valid. 3137 MemOperand BaseMemOperandForLoadStoreCPURegList( 3138 const CPURegList& registers, 3139 const MemOperand& mem, 3140 UseScratchRegisterScope* scratch_scope); 3141 3142 bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) { 3143 return !Instruction::IsValidImmPCOffset(branch_type, 3144 label->GetLocation() - 3145 GetCursorOffset()); 3146 } 3147 3148 // Tell whether any of the macro instruction can be used. When false the 3149 // MacroAssembler will assert if a method which can emit a variable number 3150 // of instructions is called. 3151 bool allow_macro_instructions_; 3152 3153 // Indicates whether we should generate simulator or native code. 3154 bool generate_simulator_code_; 3155 3156 // The register to use as a stack pointer for stack operations. 3157 Register sp_; 3158 3159 // Scratch registers available for use by the MacroAssembler. 3160 CPURegList tmp_list_; 3161 CPURegList fptmp_list_; 3162 3163 UseScratchRegisterScope* current_scratch_scope_; 3164 3165 LiteralPool literal_pool_; 3166 VeneerPool veneer_pool_; 3167 3168 ptrdiff_t checkpoint_; 3169 ptrdiff_t recommended_checkpoint_; 3170 3171 friend class Pool; 3172 friend class LiteralPool; 3173 }; 3174 3175 3176 inline size_t VeneerPool::GetOtherPoolsMaxSize() const { 3177 return masm_->GetLiteralPoolMaxSize(); 3178 } 3179 3180 3181 inline size_t LiteralPool::GetOtherPoolsMaxSize() const { 3182 return masm_->GetVeneerPoolMaxSize(); 3183 } 3184 3185 3186 inline void LiteralPool::SetNextRecommendedCheckpoint(ptrdiff_t offset) { 3187 masm_->recommended_checkpoint_ = 3188 std::min(masm_->recommended_checkpoint_, offset); 3189 recommended_checkpoint_ = offset; 3190 } 3191 3192 class InstructionAccurateScope : public ExactAssemblyScope { 3193 public: 3194 VIXL_DEPRECATED("ExactAssemblyScope", 3195 InstructionAccurateScope(MacroAssembler* masm, 3196 int64_t count, 3197 SizePolicy size_policy = kExactSize)) 3198 : ExactAssemblyScope(masm, count * kInstructionSize, size_policy) {} 3199 }; 3200 3201 class BlockLiteralPoolScope { 3202 public: 3203 explicit BlockLiteralPoolScope(MacroAssembler* masm) : masm_(masm) { 3204 masm_->BlockLiteralPool(); 3205 } 3206 3207 ~BlockLiteralPoolScope() { masm_->ReleaseLiteralPool(); } 3208 3209 private: 3210 MacroAssembler* masm_; 3211 }; 3212 3213 3214 class BlockVeneerPoolScope { 3215 public: 3216 explicit BlockVeneerPoolScope(MacroAssembler* masm) : masm_(masm) { 3217 masm_->BlockVeneerPool(); 3218 } 3219 3220 ~BlockVeneerPoolScope() { masm_->ReleaseVeneerPool(); } 3221 3222 private: 3223 MacroAssembler* masm_; 3224 }; 3225 3226 3227 class BlockPoolsScope { 3228 public: 3229 explicit BlockPoolsScope(MacroAssembler* masm) : masm_(masm) { 3230 masm_->BlockPools(); 3231 } 3232 3233 ~BlockPoolsScope() { masm_->ReleasePools(); } 3234 3235 private: 3236 MacroAssembler* masm_; 3237 }; 3238 3239 3240 // This scope utility allows scratch registers to be managed safely. The 3241 // MacroAssembler's GetScratchRegisterList() (and GetScratchFPRegisterList()) is 3242 // used as a pool of scratch registers. These registers can be allocated on 3243 // demand, and will be returned at the end of the scope. 3244 // 3245 // When the scope ends, the MacroAssembler's lists will be restored to their 3246 // original state, even if the lists were modified by some other means. 3247 class UseScratchRegisterScope { 3248 public: 3249 // This constructor implicitly calls `Open` to initialise the scope (`masm` 3250 // must not be `NULL`), so it is ready to use immediately after it has been 3251 // constructed. 3252 explicit UseScratchRegisterScope(MacroAssembler* masm) 3253 : masm_(NULL), parent_(NULL), old_available_(0), old_availablefp_(0) { 3254 Open(masm); 3255 } 3256 // This constructor does not implicitly initialise the scope. Instead, the 3257 // user is required to explicitly call the `Open` function before using the 3258 // scope. 3259 UseScratchRegisterScope() 3260 : masm_(NULL), parent_(NULL), old_available_(0), old_availablefp_(0) {} 3261 3262 // This function performs the actual initialisation work. 3263 void Open(MacroAssembler* masm); 3264 3265 // The destructor always implicitly calls the `Close` function. 3266 ~UseScratchRegisterScope() { Close(); } 3267 3268 // This function performs the cleaning-up work. It must succeed even if the 3269 // scope has not been opened. It is safe to call multiple times. 3270 void Close(); 3271 3272 3273 bool IsAvailable(const CPURegister& reg) const; 3274 3275 3276 // Take a register from the appropriate temps list. It will be returned 3277 // automatically when the scope ends. 3278 Register AcquireW() { 3279 return AcquireNextAvailable(masm_->GetScratchRegisterList()).W(); 3280 } 3281 Register AcquireX() { 3282 return AcquireNextAvailable(masm_->GetScratchRegisterList()).X(); 3283 } 3284 VRegister AcquireS() { 3285 return AcquireNextAvailable(masm_->GetScratchFPRegisterList()).S(); 3286 } 3287 VRegister AcquireD() { 3288 return AcquireNextAvailable(masm_->GetScratchFPRegisterList()).D(); 3289 } 3290 3291 3292 Register AcquireRegisterOfSize(int size_in_bits); 3293 Register AcquireSameSizeAs(const Register& reg) { 3294 return AcquireRegisterOfSize(reg.GetSizeInBits()); 3295 } 3296 VRegister AcquireVRegisterOfSize(int size_in_bits); 3297 VRegister AcquireSameSizeAs(const VRegister& reg) { 3298 return AcquireVRegisterOfSize(reg.GetSizeInBits()); 3299 } 3300 CPURegister AcquireCPURegisterOfSize(int size_in_bits) { 3301 return masm_->GetScratchRegisterList()->IsEmpty() 3302 ? CPURegister(AcquireVRegisterOfSize(size_in_bits)) 3303 : CPURegister(AcquireRegisterOfSize(size_in_bits)); 3304 } 3305 3306 3307 // Explicitly release an acquired (or excluded) register, putting it back in 3308 // the appropriate temps list. 3309 void Release(const CPURegister& reg); 3310 3311 3312 // Make the specified registers available as scratch registers for the 3313 // duration of this scope. 3314 void Include(const CPURegList& list); 3315 void Include(const Register& reg1, 3316 const Register& reg2 = NoReg, 3317 const Register& reg3 = NoReg, 3318 const Register& reg4 = NoReg); 3319 void Include(const VRegister& reg1, 3320 const VRegister& reg2 = NoVReg, 3321 const VRegister& reg3 = NoVReg, 3322 const VRegister& reg4 = NoVReg); 3323 3324 3325 // Make sure that the specified registers are not available in this scope. 3326 // This can be used to prevent helper functions from using sensitive 3327 // registers, for example. 3328 void Exclude(const CPURegList& list); 3329 void Exclude(const Register& reg1, 3330 const Register& reg2 = NoReg, 3331 const Register& reg3 = NoReg, 3332 const Register& reg4 = NoReg); 3333 void Exclude(const VRegister& reg1, 3334 const VRegister& reg2 = NoVReg, 3335 const VRegister& reg3 = NoVReg, 3336 const VRegister& reg4 = NoVReg); 3337 void Exclude(const CPURegister& reg1, 3338 const CPURegister& reg2 = NoCPUReg, 3339 const CPURegister& reg3 = NoCPUReg, 3340 const CPURegister& reg4 = NoCPUReg); 3341 3342 3343 // Prevent any scratch registers from being used in this scope. 3344 void ExcludeAll(); 3345 3346 private: 3347 static CPURegister AcquireNextAvailable(CPURegList* available); 3348 3349 static void ReleaseByCode(CPURegList* available, int code); 3350 3351 static void ReleaseByRegList(CPURegList* available, RegList regs); 3352 3353 static void IncludeByRegList(CPURegList* available, RegList exclude); 3354 3355 static void ExcludeByRegList(CPURegList* available, RegList exclude); 3356 3357 // The MacroAssembler maintains a list of available scratch registers, and 3358 // also keeps track of the most recently-opened scope so that on destruction 3359 // we can check that scopes do not outlive their parents. 3360 MacroAssembler* masm_; 3361 UseScratchRegisterScope* parent_; 3362 3363 // The state of the available lists at the start of this scope. 3364 RegList old_available_; // kRegister 3365 RegList old_availablefp_; // kVRegister 3366 3367 // Disallow copy constructor and operator=. 3368 VIXL_DEBUG_NO_RETURN UseScratchRegisterScope(const UseScratchRegisterScope&) { 3369 VIXL_UNREACHABLE(); 3370 } 3371 VIXL_DEBUG_NO_RETURN void operator=(const UseScratchRegisterScope&) { 3372 VIXL_UNREACHABLE(); 3373 } 3374 }; 3375 3376 // Variadic templating is only available from C++11. 3377 #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT 3378 3379 // `R` stands for 'return type', and `P` for 'parameter types'. 3380 template <typename R, typename... P> 3381 void MacroAssembler::CallRuntime(R (*function)(P...)) { 3382 if (generate_simulator_code_) { 3383 #ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT 3384 uintptr_t runtime_call_wrapper_address = reinterpret_cast<uintptr_t>( 3385 &(Simulator::RuntimeCallStructHelper<R, P...>::Wrapper)); 3386 uintptr_t function_address = reinterpret_cast<uintptr_t>(function); 3387 3388 EmissionCheckScope guard(this, 3389 kInstructionSize + 2 * kRuntimeCallAddressSize, 3390 CodeBufferCheckScope::kExactSize); 3391 Label start; 3392 bind(&start); 3393 { 3394 ExactAssemblyScope scope(this, kInstructionSize); 3395 hlt(kRuntimeCallOpcode); 3396 } 3397 VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == 3398 kRuntimeCallWrapperOffset); 3399 dc(runtime_call_wrapper_address); 3400 VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == 3401 kRuntimeCallFunctionOffset); 3402 dc(function_address); 3403 VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == 3404 kRuntimeCallFunctionOffset + kRuntimeCallAddressSize); 3405 #else 3406 VIXL_UNREACHABLE(); 3407 #endif // #ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT 3408 } else { 3409 UseScratchRegisterScope temps(this); 3410 Register temp = temps.AcquireX(); 3411 Mov(temp, reinterpret_cast<uint64_t>(function)); 3412 Blr(temp); 3413 } 3414 } 3415 3416 #endif // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT 3417 3418 } // namespace aarch64 3419 3420 // Required InvalSet template specialisations. 3421 // TODO: These template specialisations should not live in this file. Move 3422 // VeneerPool out of the aarch64 namespace in order to share its implementation 3423 // later. 3424 template <> 3425 inline ptrdiff_t InvalSet<aarch64::VeneerPool::BranchInfo, 3426 aarch64::VeneerPool::kNPreallocatedInfos, 3427 ptrdiff_t, 3428 aarch64::VeneerPool::kInvalidOffset, 3429 aarch64::VeneerPool::kReclaimFrom, 3430 aarch64::VeneerPool::kReclaimFactor>:: 3431 GetKey(const aarch64::VeneerPool::BranchInfo& branch_info) { 3432 return branch_info.max_reachable_pc_; 3433 } 3434 template <> 3435 inline void InvalSet<aarch64::VeneerPool::BranchInfo, 3436 aarch64::VeneerPool::kNPreallocatedInfos, 3437 ptrdiff_t, 3438 aarch64::VeneerPool::kInvalidOffset, 3439 aarch64::VeneerPool::kReclaimFrom, 3440 aarch64::VeneerPool::kReclaimFactor>:: 3441 SetKey(aarch64::VeneerPool::BranchInfo* branch_info, ptrdiff_t key) { 3442 branch_info->max_reachable_pc_ = key; 3443 } 3444 3445 } // namespace vixl 3446 3447 #endif // VIXL_AARCH64_MACRO_ASSEMBLER_AARCH64_H_ 3448