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