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 // Required for runtime call support.
39 // TODO: Break this dependency. We should be able to separate out the necessary
40 // parts so that we don't need to include the whole simulator header.
41 #include "simulator-aarch64.h"
42 // Required in order to generate debugging instructions for the simulator. This
43 // is needed regardless of whether the simulator is included or not, since
44 // generating simulator specific instructions is controlled at runtime.
45 #include "simulator-constants-aarch64.h"
46 
47 
48 #define LS_MACRO_LIST(V)                                     \
49   V(Ldrb, Register&, rt, LDRB_w)                             \
50   V(Strb, Register&, rt, STRB_w)                             \
51   V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w) \
52   V(Ldrh, Register&, rt, LDRH_w)                             \
53   V(Strh, Register&, rt, STRH_w)                             \
54   V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w) \
55   V(Ldr, CPURegister&, rt, LoadOpFor(rt))                    \
56   V(Str, CPURegister&, rt, StoreOpFor(rt))                   \
57   V(Ldrsw, Register&, rt, LDRSW_x)
58 
59 
60 #define LSPAIR_MACRO_LIST(V)                             \
61   V(Ldp, CPURegister&, rt, rt2, LoadPairOpFor(rt, rt2))  \
62   V(Stp, CPURegister&, rt, rt2, StorePairOpFor(rt, rt2)) \
63   V(Ldpsw, Register&, rt, rt2, LDPSW_x)
64 
65 namespace vixl {
66 namespace aarch64 {
67 
68 // Forward declaration
69 class MacroAssembler;
70 class UseScratchRegisterScope;
71 
72 class Pool {
73  public:
Pool(MacroAssembler * masm)74   explicit Pool(MacroAssembler* masm)
75       : checkpoint_(kNoCheckpointRequired), masm_(masm) {
76     Reset();
77   }
78 
Reset()79   void Reset() {
80     checkpoint_ = kNoCheckpointRequired;
81     monitor_ = 0;
82   }
83 
Block()84   void Block() { monitor_++; }
85   void Release();
IsBlocked()86   bool IsBlocked() const { return monitor_ != 0; }
87 
88   static const ptrdiff_t kNoCheckpointRequired = PTRDIFF_MAX;
89 
90   void SetNextCheckpoint(ptrdiff_t checkpoint);
GetCheckpoint()91   ptrdiff_t GetCheckpoint() const { return checkpoint_; }
92   VIXL_DEPRECATED("GetCheckpoint", ptrdiff_t checkpoint() const) {
93     return GetCheckpoint();
94   }
95 
96   enum EmitOption { kBranchRequired, kNoBranchRequired };
97 
98  protected:
99   // Next buffer offset at which a check is required for this pool.
100   ptrdiff_t checkpoint_;
101   // Indicates whether the emission of this pool is blocked.
102   int monitor_;
103   // The MacroAssembler using this pool.
104   MacroAssembler* masm_;
105 };
106 
107 
108 class LiteralPool : public Pool {
109  public:
110   explicit LiteralPool(MacroAssembler* masm);
111   ~LiteralPool() VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION;
112   void Reset();
113 
114   void AddEntry(RawLiteral* literal);
IsEmpty()115   bool IsEmpty() const { return entries_.empty(); }
116   size_t GetSize() const;
117   VIXL_DEPRECATED("GetSize", size_t Size() const) { return GetSize(); }
118 
119   size_t GetMaxSize() const;
120   VIXL_DEPRECATED("GetMaxSize", size_t MaxSize() const) { return GetMaxSize(); }
121 
122   size_t GetOtherPoolsMaxSize() const;
123   VIXL_DEPRECATED("GetOtherPoolsMaxSize", size_t OtherPoolsMaxSize() const) {
124     return GetOtherPoolsMaxSize();
125   }
126 
127   void CheckEmitFor(size_t amount, EmitOption option = kBranchRequired);
128   // Check whether we need to emit the literal pool in order to be able to
129   // safely emit a branch with a given range.
130   void CheckEmitForBranch(size_t range);
131   void Emit(EmitOption option = kNoBranchRequired);
132 
133   void SetNextRecommendedCheckpoint(ptrdiff_t offset);
134   ptrdiff_t GetNextRecommendedCheckpoint();
135   VIXL_DEPRECATED("GetNextRecommendedCheckpoint",
136                   ptrdiff_t NextRecommendedCheckpoint()) {
137     return GetNextRecommendedCheckpoint();
138   }
139 
140   void UpdateFirstUse(ptrdiff_t use_position);
141 
DeleteOnDestruction(RawLiteral * literal)142   void DeleteOnDestruction(RawLiteral* literal) {
143     deleted_on_destruction_.push_back(literal);
144   }
145 
146   // Recommended not exact since the pool can be blocked for short periods.
147   static const ptrdiff_t kRecommendedLiteralPoolRange = 128 * KBytes;
148 
149  private:
150   std::vector<RawLiteral*> entries_;
151   size_t size_;
152   ptrdiff_t first_use_;
153   // The parent class `Pool` provides a `checkpoint_`, which is the buffer
154   // offset before which a check *must* occur. This recommended checkpoint
155   // indicates when we would like to start emitting the constant pool. The
156   // MacroAssembler can, but does not have to, check the buffer when the
157   // checkpoint is reached.
158   ptrdiff_t recommended_checkpoint_;
159 
160   std::vector<RawLiteral*> deleted_on_destruction_;
161 };
162 
163 
GetSize()164 inline size_t LiteralPool::GetSize() const {
165   // Account for the pool header.
166   return size_ + kInstructionSize;
167 }
168 
169 
GetMaxSize()170 inline size_t LiteralPool::GetMaxSize() const {
171   // Account for the potential branch over the pool.
172   return GetSize() + kInstructionSize;
173 }
174 
175 
GetNextRecommendedCheckpoint()176 inline ptrdiff_t LiteralPool::GetNextRecommendedCheckpoint() {
177   return first_use_ + kRecommendedLiteralPoolRange;
178 }
179 
180 
181 class VeneerPool : public Pool {
182  public:
VeneerPool(MacroAssembler * masm)183   explicit VeneerPool(MacroAssembler* masm) : Pool(masm) {}
184 
185   void Reset();
186 
Block()187   void Block() { monitor_++; }
188   void Release();
IsBlocked()189   bool IsBlocked() const { return monitor_ != 0; }
IsEmpty()190   bool IsEmpty() const { return unresolved_branches_.IsEmpty(); }
191 
192   class BranchInfo {
193    public:
BranchInfo()194     BranchInfo()
195         : first_unreacheable_pc_(0),
196           pc_offset_(0),
197           label_(NULL),
198           branch_type_(UnknownBranchType) {}
BranchInfo(ptrdiff_t offset,Label * label,ImmBranchType branch_type)199     BranchInfo(ptrdiff_t offset, Label* label, ImmBranchType branch_type)
200         : pc_offset_(offset), label_(label), branch_type_(branch_type) {
201       first_unreacheable_pc_ =
202           pc_offset_ + Instruction::GetImmBranchForwardRange(branch_type_);
203     }
204 
IsValidComparison(const BranchInfo & branch_1,const BranchInfo & branch_2)205     static bool IsValidComparison(const BranchInfo& branch_1,
206                                   const BranchInfo& branch_2) {
207       // BranchInfo are always compared against against other objects with
208       // the same branch type.
209       if (branch_1.branch_type_ != branch_2.branch_type_) {
210         return false;
211       }
212       // Since we should never have two branch infos with the same offsets, it
213       // first looks like we should check that offsets are different. However
214       // the operators may also be used to *search* for a branch info in the
215       // set.
216       bool same_offsets = (branch_1.pc_offset_ == branch_2.pc_offset_);
217       return (!same_offsets || ((branch_1.label_ == branch_2.label_) &&
218                                 (branch_1.first_unreacheable_pc_ ==
219                                  branch_2.first_unreacheable_pc_)));
220     }
221 
222     // We must provide comparison operators to work with InvalSet.
223     bool operator==(const BranchInfo& other) const {
224       VIXL_ASSERT(IsValidComparison(*this, other));
225       return pc_offset_ == other.pc_offset_;
226     }
227     bool operator<(const BranchInfo& other) const {
228       VIXL_ASSERT(IsValidComparison(*this, other));
229       return pc_offset_ < other.pc_offset_;
230     }
231     bool operator<=(const BranchInfo& other) const {
232       VIXL_ASSERT(IsValidComparison(*this, other));
233       return pc_offset_ <= other.pc_offset_;
234     }
235     bool operator>(const BranchInfo& other) const {
236       VIXL_ASSERT(IsValidComparison(*this, other));
237       return pc_offset_ > other.pc_offset_;
238     }
239 
240     // First instruction position that is not reachable by the branch using a
241     // positive branch offset.
242     ptrdiff_t first_unreacheable_pc_;
243     // Offset of the branch in the code generation buffer.
244     ptrdiff_t pc_offset_;
245     // The label branched to.
246     Label* label_;
247     ImmBranchType branch_type_;
248   };
249 
BranchTypeUsesVeneers(ImmBranchType type)250   bool BranchTypeUsesVeneers(ImmBranchType type) {
251     return (type != UnknownBranchType) && (type != UncondBranchType);
252   }
253 
254   void RegisterUnresolvedBranch(ptrdiff_t branch_pos,
255                                 Label* label,
256                                 ImmBranchType branch_type);
257   void DeleteUnresolvedBranchInfoForLabel(Label* label);
258 
259   bool ShouldEmitVeneer(int64_t first_unreacheable_pc, size_t amount);
ShouldEmitVeneers(size_t amount)260   bool ShouldEmitVeneers(size_t amount) {
261     return ShouldEmitVeneer(unresolved_branches_.GetFirstLimit(), amount);
262   }
263 
264   void CheckEmitFor(size_t amount, EmitOption option = kBranchRequired);
265   void Emit(EmitOption option, size_t margin);
266 
267   // The code size generated for a veneer. Currently one branch instruction.
268   // This is for code size checking purposes, and can be extended in the future
269   // for example if we decide to add nops between the veneers.
270   static const int kVeneerCodeSize = 1 * kInstructionSize;
271   // The maximum size of code other than veneers that can be generated when
272   // emitting a veneer pool. Currently there can be an additional branch to jump
273   // over the pool.
274   static const int kPoolNonVeneerCodeSize = 1 * kInstructionSize;
275 
UpdateNextCheckPoint()276   void UpdateNextCheckPoint() { SetNextCheckpoint(GetNextCheckPoint()); }
277 
GetNumberOfPotentialVeneers()278   int GetNumberOfPotentialVeneers() const {
279     return static_cast<int>(unresolved_branches_.GetSize());
280   }
281   VIXL_DEPRECATED("GetNumberOfPotentialVeneers",
NumberOfPotentialVeneers()282                   int NumberOfPotentialVeneers() const) {
283     return GetNumberOfPotentialVeneers();
284   }
285 
GetMaxSize()286   size_t GetMaxSize() const {
287     return kPoolNonVeneerCodeSize +
288            unresolved_branches_.GetSize() * kVeneerCodeSize;
289   }
290   VIXL_DEPRECATED("GetMaxSize", size_t MaxSize() const) { return GetMaxSize(); }
291 
292   size_t GetOtherPoolsMaxSize() const;
293   VIXL_DEPRECATED("GetOtherPoolsMaxSize", size_t OtherPoolsMaxSize() const) {
294     return GetOtherPoolsMaxSize();
295   }
296 
297   static const int kNPreallocatedInfos = 4;
298   static const ptrdiff_t kInvalidOffset = PTRDIFF_MAX;
299   static const size_t kReclaimFrom = 128;
300   static const size_t kReclaimFactor = 16;
301 
302  private:
303   typedef InvalSet<BranchInfo,
304                    kNPreallocatedInfos,
305                    ptrdiff_t,
306                    kInvalidOffset,
307                    kReclaimFrom,
308                    kReclaimFactor>
309       BranchInfoTypedSetBase;
310   typedef InvalSetIterator<BranchInfoTypedSetBase> BranchInfoTypedSetIterBase;
311 
312   class BranchInfoTypedSet : public BranchInfoTypedSetBase {
313    public:
BranchInfoTypedSet()314     BranchInfoTypedSet() : BranchInfoTypedSetBase() {}
315 
GetFirstLimit()316     ptrdiff_t GetFirstLimit() {
317       if (empty()) {
318         return kInvalidOffset;
319       }
320       return GetMinElementKey();
321     }
322     VIXL_DEPRECATED("GetFirstLimit", ptrdiff_t FirstLimit()) {
323       return GetFirstLimit();
324     }
325   };
326 
327   class BranchInfoTypedSetIterator : public BranchInfoTypedSetIterBase {
328    public:
BranchInfoTypedSetIterator()329     BranchInfoTypedSetIterator() : BranchInfoTypedSetIterBase(NULL) {}
BranchInfoTypedSetIterator(BranchInfoTypedSet * typed_set)330     explicit BranchInfoTypedSetIterator(BranchInfoTypedSet* typed_set)
331         : BranchInfoTypedSetIterBase(typed_set) {}
332 
333     // TODO: Remove these and use the STL-like interface instead.
334     using BranchInfoTypedSetIterBase::Advance;
335     using BranchInfoTypedSetIterBase::Current;
336   };
337 
338   class BranchInfoSet {
339    public:
insert(BranchInfo branch_info)340     void insert(BranchInfo branch_info) {
341       ImmBranchType type = branch_info.branch_type_;
342       VIXL_ASSERT(IsValidBranchType(type));
343       typed_set_[BranchIndexFromType(type)].insert(branch_info);
344     }
345 
erase(BranchInfo branch_info)346     void erase(BranchInfo branch_info) {
347       if (IsValidBranchType(branch_info.branch_type_)) {
348         int index =
349             BranchInfoSet::BranchIndexFromType(branch_info.branch_type_);
350         typed_set_[index].erase(branch_info);
351       }
352     }
353 
GetSize()354     size_t GetSize() const {
355       size_t res = 0;
356       for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
357         res += typed_set_[i].size();
358       }
359       return res;
360     }
361     VIXL_DEPRECATED("GetSize", size_t size() const) { return GetSize(); }
362 
IsEmpty()363     bool IsEmpty() const {
364       for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
365         if (!typed_set_[i].empty()) {
366           return false;
367         }
368       }
369       return true;
370     }
empty()371     VIXL_DEPRECATED("IsEmpty", bool empty() const) { return IsEmpty(); }
372 
GetFirstLimit()373     ptrdiff_t GetFirstLimit() {
374       ptrdiff_t res = kInvalidOffset;
375       for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
376         res = std::min(res, typed_set_[i].GetFirstLimit());
377       }
378       return res;
379     }
380     VIXL_DEPRECATED("GetFirstLimit", ptrdiff_t FirstLimit()) {
381       return GetFirstLimit();
382     }
383 
Reset()384     void Reset() {
385       for (int i = 0; i < kNumberOfTrackedBranchTypes; i++) {
386         typed_set_[i].clear();
387       }
388     }
389 
BranchTypeFromIndex(int index)390     static ImmBranchType BranchTypeFromIndex(int index) {
391       switch (index) {
392         case 0:
393           return CondBranchType;
394         case 1:
395           return CompareBranchType;
396         case 2:
397           return TestBranchType;
398         default:
399           VIXL_UNREACHABLE();
400           return UnknownBranchType;
401       }
402     }
BranchIndexFromType(ImmBranchType branch_type)403     static int BranchIndexFromType(ImmBranchType branch_type) {
404       switch (branch_type) {
405         case CondBranchType:
406           return 0;
407         case CompareBranchType:
408           return 1;
409         case TestBranchType:
410           return 2;
411         default:
412           VIXL_UNREACHABLE();
413           return 0;
414       }
415     }
416 
IsValidBranchType(ImmBranchType branch_type)417     bool IsValidBranchType(ImmBranchType branch_type) {
418       return (branch_type != UnknownBranchType) &&
419              (branch_type != UncondBranchType);
420     }
421 
422    private:
423     static const int kNumberOfTrackedBranchTypes = 3;
424     BranchInfoTypedSet typed_set_[kNumberOfTrackedBranchTypes];
425 
426     friend class VeneerPool;
427     friend class BranchInfoSetIterator;
428   };
429 
430   class BranchInfoSetIterator {
431    public:
BranchInfoSetIterator(BranchInfoSet * set)432     explicit BranchInfoSetIterator(BranchInfoSet* set) : set_(set) {
433       for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
434         new (&sub_iterator_[i])
435             BranchInfoTypedSetIterator(&(set_->typed_set_[i]));
436       }
437     }
438 
Current()439     VeneerPool::BranchInfo* Current() {
440       for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
441         if (!sub_iterator_[i].Done()) {
442           return sub_iterator_[i].Current();
443         }
444       }
445       VIXL_UNREACHABLE();
446       return NULL;
447     }
448 
Advance()449     void Advance() {
450       VIXL_ASSERT(!Done());
451       for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
452         if (!sub_iterator_[i].Done()) {
453           sub_iterator_[i].Advance();
454           return;
455         }
456       }
457       VIXL_UNREACHABLE();
458     }
459 
Done()460     bool Done() const {
461       for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
462         if (!sub_iterator_[i].Done()) return false;
463       }
464       return true;
465     }
466 
AdvanceToNextType()467     void AdvanceToNextType() {
468       VIXL_ASSERT(!Done());
469       for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
470         if (!sub_iterator_[i].Done()) {
471           sub_iterator_[i].Finish();
472           return;
473         }
474       }
475       VIXL_UNREACHABLE();
476     }
477 
DeleteCurrentAndAdvance()478     void DeleteCurrentAndAdvance() {
479       for (int i = 0; i < BranchInfoSet::kNumberOfTrackedBranchTypes; i++) {
480         if (!sub_iterator_[i].Done()) {
481           sub_iterator_[i].DeleteCurrentAndAdvance();
482           return;
483         }
484       }
485     }
486 
487    private:
488     BranchInfoSet* set_;
489     BranchInfoTypedSetIterator
490         sub_iterator_[BranchInfoSet::kNumberOfTrackedBranchTypes];
491   };
492 
GetNextCheckPoint()493   ptrdiff_t GetNextCheckPoint() {
494     if (unresolved_branches_.IsEmpty()) {
495       return kNoCheckpointRequired;
496     } else {
497       return unresolved_branches_.GetFirstLimit();
498     }
499   }
500   VIXL_DEPRECATED("GetNextCheckPoint", ptrdiff_t NextCheckPoint()) {
501     return GetNextCheckPoint();
502   }
503 
504   // Information about unresolved (forward) branches.
505   BranchInfoSet unresolved_branches_;
506 };
507 
508 
509 // Helper for common Emission checks.
510 // The macro-instruction maps to a single instruction.
511 class SingleEmissionCheckScope : public EmissionCheckScope {
512  public:
SingleEmissionCheckScope(MacroAssemblerInterface * masm)513   explicit SingleEmissionCheckScope(MacroAssemblerInterface* masm)
514       : EmissionCheckScope(masm, kInstructionSize) {}
515 };
516 
517 
518 // The macro instruction is a "typical" macro-instruction. Typical macro-
519 // instruction only emit a few instructions, a few being defined as 8 here.
520 class MacroEmissionCheckScope : public EmissionCheckScope {
521  public:
MacroEmissionCheckScope(MacroAssemblerInterface * masm)522   explicit MacroEmissionCheckScope(MacroAssemblerInterface* masm)
523       : EmissionCheckScope(masm, kTypicalMacroInstructionMaxSize) {}
524 
525  private:
526   static const size_t kTypicalMacroInstructionMaxSize = 8 * kInstructionSize;
527 };
528 
529 
530 // This scope simplifies the handling of the SVE `movprfx` instruction.
531 //
532 // If dst.Aliases(src):
533 // - Start an ExactAssemblyScope(masm, kInstructionSize).
534 // Otherwise:
535 // - Start an ExactAssemblyScope(masm, 2 * kInstructionSize).
536 // - Generate a suitable `movprfx` instruction.
537 //
538 // In both cases, the ExactAssemblyScope is left with enough remaining space for
539 // exactly one destructive instruction.
540 class MovprfxHelperScope : public ExactAssemblyScope {
541  public:
542   inline MovprfxHelperScope(MacroAssembler* masm,
543                             const ZRegister& dst,
544                             const ZRegister& src);
545 
546   inline MovprfxHelperScope(MacroAssembler* masm,
547                             const ZRegister& dst,
548                             const PRegister& pg,
549                             const ZRegister& src);
550 
551   // TODO: Implement constructors that examine _all_ sources. If `dst` aliases
552   // any other source register, we can't use `movprfx`. This isn't obviously
553   // useful, but the MacroAssembler should not generate invalid code for it.
554   // Valid behaviour can be implemented using `mov`.
555   //
556   // The best way to handle this in an instruction-agnostic way is probably to
557   // use variadic templates.
558 
559  private:
ShouldGenerateMovprfx(const ZRegister & dst,const ZRegister & src)560   inline bool ShouldGenerateMovprfx(const ZRegister& dst,
561                                     const ZRegister& src) {
562     VIXL_ASSERT(AreSameLaneSize(dst, src));
563     return !dst.Aliases(src);
564   }
565 
ShouldGenerateMovprfx(const ZRegister & dst,const PRegister & pg,const ZRegister & src)566   inline bool ShouldGenerateMovprfx(const ZRegister& dst,
567                                     const PRegister& pg,
568                                     const ZRegister& src) {
569     VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());
570     // We need to emit movprfx in two cases:
571     //  1. To give a predicated merging unary instruction zeroing predication.
572     //  2. To make destructive instructions constructive.
573     //
574     // There are no predicated zeroing instructions that can take movprfx, so we
575     // will never generate an unnecessary movprfx with this logic.
576     return pg.IsZeroing() || ShouldGenerateMovprfx(dst, src);
577   }
578 };
579 
580 
581 enum BranchType {
582   // Copies of architectural conditions.
583   // The associated conditions can be used in place of those, the code will
584   // take care of reinterpreting them with the correct type.
585   integer_eq = eq,
586   integer_ne = ne,
587   integer_hs = hs,
588   integer_lo = lo,
589   integer_mi = mi,
590   integer_pl = pl,
591   integer_vs = vs,
592   integer_vc = vc,
593   integer_hi = hi,
594   integer_ls = ls,
595   integer_ge = ge,
596   integer_lt = lt,
597   integer_gt = gt,
598   integer_le = le,
599   integer_al = al,
600   integer_nv = nv,
601 
602   // These two are *different* from the architectural codes al and nv.
603   // 'always' is used to generate unconditional branches.
604   // 'never' is used to not generate a branch (generally as the inverse
605   // branch type of 'always).
606   always,
607   never,
608   // cbz and cbnz
609   reg_zero,
610   reg_not_zero,
611   // tbz and tbnz
612   reg_bit_clear,
613   reg_bit_set,
614 
615   // Aliases.
616   kBranchTypeFirstCondition = eq,
617   kBranchTypeLastCondition = nv,
618   kBranchTypeFirstUsingReg = reg_zero,
619   kBranchTypeFirstUsingBit = reg_bit_clear,
620 
621   // SVE branch conditions.
622   integer_none = eq,
623   integer_any = ne,
624   integer_nlast = cs,
625   integer_last = cc,
626   integer_first = mi,
627   integer_nfrst = pl,
628   integer_pmore = hi,
629   integer_plast = ls,
630   integer_tcont = ge,
631   integer_tstop = lt
632 };
633 
634 
635 enum DiscardMoveMode { kDontDiscardForSameWReg, kDiscardForSameWReg };
636 
637 // The macro assembler supports moving automatically pre-shifted immediates for
638 // arithmetic and logical instructions, and then applying a post shift in the
639 // instruction to undo the modification, in order to reduce the code emitted for
640 // an operation. For example:
641 //
642 //  Add(x0, x0, 0x1f7de) => movz x16, 0xfbef; add x0, x0, x16, lsl #1.
643 //
644 // This optimisation can be only partially applied when the stack pointer is an
645 // operand or destination, so this enumeration is used to control the shift.
646 enum PreShiftImmMode {
647   kNoShift,          // Don't pre-shift.
648   kLimitShiftForSP,  // Limit pre-shift for add/sub extend use.
649   kAnyShift          // Allow any pre-shift.
650 };
651 
652 enum FPMacroNaNPropagationOption {
653   // The default option. This generates a run-time error in macros that respect
654   // this option.
655   NoFPMacroNaNPropagationSelected,
656   // For example, Fmin(result, NaN(a), NaN(b)) always selects NaN(a) if both
657   // NaN(a) and NaN(b) are both quiet, or both are signalling, at the
658   // cost of extra code generation in some cases.
659   StrictNaNPropagation,
660   // For example, Fmin(result, NaN(a), NaN(b)) selects either NaN, but using the
661   // fewest instructions.
662   FastNaNPropagation
663 };
664 
665 class MacroAssembler : public Assembler, public MacroAssemblerInterface {
666  public:
667   explicit MacroAssembler(
668       PositionIndependentCodeOption pic = PositionIndependentCode);
669   MacroAssembler(size_t capacity,
670                  PositionIndependentCodeOption pic = PositionIndependentCode);
671   MacroAssembler(byte* buffer,
672                  size_t capacity,
673                  PositionIndependentCodeOption pic = PositionIndependentCode);
674   ~MacroAssembler();
675 
676   enum FinalizeOption {
677     kFallThrough,  // There may be more code to execute after calling Finalize.
678     kUnreachable   // Anything generated after calling Finalize is unreachable.
679   };
680 
AsAssemblerBase()681   virtual vixl::internal::AssemblerBase* AsAssemblerBase() VIXL_OVERRIDE {
682     return this;
683   }
684 
685   // TODO(pools): implement these functions.
EmitPoolHeader()686   virtual void EmitPoolHeader() VIXL_OVERRIDE {}
EmitPoolFooter()687   virtual void EmitPoolFooter() VIXL_OVERRIDE {}
EmitPaddingBytes(int n)688   virtual void EmitPaddingBytes(int n) VIXL_OVERRIDE { USE(n); }
EmitNopBytes(int n)689   virtual void EmitNopBytes(int n) VIXL_OVERRIDE { USE(n); }
690 
691   // Start generating code from the beginning of the buffer, discarding any code
692   // and data that has already been emitted into the buffer.
693   //
694   // In order to avoid any accidental transfer of state, Reset ASSERTs that the
695   // constant pool is not blocked.
696   void Reset();
697 
698   // Finalize a code buffer of generated instructions. This function must be
699   // called before executing or copying code from the buffer. By default,
700   // anything generated after this should not be reachable (the last instruction
701   // generated is an unconditional branch). If you need to generate more code,
702   // then set `option` to kFallThrough.
703   void FinalizeCode(FinalizeOption option = kUnreachable);
704 
705 
706   // Constant generation helpers.
707   // These functions return the number of instructions required to move the
708   // immediate into the destination register. Also, if the masm pointer is
709   // non-null, it generates the code to do so.
710   // The two features are implemented using one function to avoid duplication of
711   // the logic.
712   // The function can be used to evaluate the cost of synthesizing an
713   // instruction using 'mov immediate' instructions. A user might prefer loading
714   // a constant using the literal pool instead of using multiple 'mov immediate'
715   // instructions.
716   static int MoveImmediateHelper(MacroAssembler* masm,
717                                  const Register& rd,
718                                  uint64_t imm);
719   static bool OneInstrMoveImmediateHelper(MacroAssembler* masm,
720                                           const Register& dst,
721                                           uint64_t imm);
722 
723 
724   // Logical macros.
725   void And(const Register& rd, const Register& rn, const Operand& operand);
726   void Ands(const Register& rd, const Register& rn, const Operand& operand);
727   void Bic(const Register& rd, const Register& rn, const Operand& operand);
728   void Bics(const Register& rd, const Register& rn, const Operand& operand);
729   void Orr(const Register& rd, const Register& rn, const Operand& operand);
730   void Orn(const Register& rd, const Register& rn, const Operand& operand);
731   void Eor(const Register& rd, const Register& rn, const Operand& operand);
732   void Eon(const Register& rd, const Register& rn, const Operand& operand);
733   void Tst(const Register& rn, const Operand& operand);
734   void LogicalMacro(const Register& rd,
735                     const Register& rn,
736                     const Operand& operand,
737                     LogicalOp op);
738 
739   // Add and sub macros.
740   void Add(const Register& rd,
741            const Register& rn,
742            const Operand& operand,
743            FlagsUpdate S = LeaveFlags);
744   void Adds(const Register& rd, const Register& rn, const Operand& operand);
745   void Sub(const Register& rd,
746            const Register& rn,
747            const Operand& operand,
748            FlagsUpdate S = LeaveFlags);
749   void Subs(const Register& rd, const Register& rn, const Operand& operand);
750   void Cmn(const Register& rn, const Operand& operand);
751   void Cmp(const Register& rn, const Operand& operand);
752   void Neg(const Register& rd, const Operand& operand);
753   void Negs(const Register& rd, const Operand& operand);
754 
755   void AddSubMacro(const Register& rd,
756                    const Register& rn,
757                    const Operand& operand,
758                    FlagsUpdate S,
759                    AddSubOp op);
760 
761   // Add/sub with carry macros.
762   void Adc(const Register& rd, const Register& rn, const Operand& operand);
763   void Adcs(const Register& rd, const Register& rn, const Operand& operand);
764   void Sbc(const Register& rd, const Register& rn, const Operand& operand);
765   void Sbcs(const Register& rd, const Register& rn, const Operand& operand);
766   void Ngc(const Register& rd, const Operand& operand);
767   void Ngcs(const Register& rd, const Operand& operand);
768   void AddSubWithCarryMacro(const Register& rd,
769                             const Register& rn,
770                             const Operand& operand,
771                             FlagsUpdate S,
772                             AddSubWithCarryOp op);
773 
774   void Rmif(const Register& xn, unsigned shift, StatusFlags flags);
775   void Setf8(const Register& wn);
776   void Setf16(const Register& wn);
777 
778   // Move macros.
779   void Mov(const Register& rd, uint64_t imm);
780   void Mov(const Register& rd,
781            const Operand& operand,
782            DiscardMoveMode discard_mode = kDontDiscardForSameWReg);
Mvn(const Register & rd,uint64_t imm)783   void Mvn(const Register& rd, uint64_t imm) {
784     Mov(rd, (rd.GetSizeInBits() == kXRegSize) ? ~imm : (~imm & kWRegMask));
785   }
786   void Mvn(const Register& rd, const Operand& operand);
787 
788   // Try to move an immediate into the destination register in a single
789   // instruction. Returns true for success, and updates the contents of dst.
790   // Returns false, otherwise.
791   bool TryOneInstrMoveImmediate(const Register& dst, uint64_t imm);
792 
793   // Move an immediate into register dst, and return an Operand object for
794   // use with a subsequent instruction that accepts a shift. The value moved
795   // into dst is not necessarily equal to imm; it may have had a shifting
796   // operation applied to it that will be subsequently undone by the shift
797   // applied in the Operand.
798   Operand MoveImmediateForShiftedOp(const Register& dst,
799                                     uint64_t imm,
800                                     PreShiftImmMode mode);
801 
802   void Move(const GenericOperand& dst, const GenericOperand& src);
803 
804   // Synthesises the address represented by a MemOperand into a register.
805   void ComputeAddress(const Register& dst, const MemOperand& mem_op);
806 
807   // Conditional macros.
808   void Ccmp(const Register& rn,
809             const Operand& operand,
810             StatusFlags nzcv,
811             Condition cond);
812   void Ccmn(const Register& rn,
813             const Operand& operand,
814             StatusFlags nzcv,
815             Condition cond);
816   void ConditionalCompareMacro(const Register& rn,
817                                const Operand& operand,
818                                StatusFlags nzcv,
819                                Condition cond,
820                                ConditionalCompareOp op);
821 
822   // On return, the boolean values pointed to will indicate whether `left` and
823   // `right` should be synthesised in a temporary register.
GetCselSynthesisInformation(const Register & rd,const Operand & left,const Operand & right,bool * should_synthesise_left,bool * should_synthesise_right)824   static void GetCselSynthesisInformation(const Register& rd,
825                                           const Operand& left,
826                                           const Operand& right,
827                                           bool* should_synthesise_left,
828                                           bool* should_synthesise_right) {
829     // Note that the helper does not need to look at the condition.
830     CselHelper(NULL,
831                rd,
832                left,
833                right,
834                eq,
835                should_synthesise_left,
836                should_synthesise_right);
837   }
838 
Csel(const Register & rd,const Operand & left,const Operand & right,Condition cond)839   void Csel(const Register& rd,
840             const Operand& left,
841             const Operand& right,
842             Condition cond) {
843     CselHelper(this, rd, left, right, cond);
844   }
845 
846 // Load/store macros.
847 #define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \
848   void FN(const REGTYPE REG, const MemOperand& addr);
849   LS_MACRO_LIST(DECLARE_FUNCTION)
850 #undef DECLARE_FUNCTION
851 
852   void LoadStoreMacro(const CPURegister& rt,
853                       const MemOperand& addr,
854                       LoadStoreOp op);
855 
856 #define DECLARE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \
857   void FN(const REGTYPE REG, const REGTYPE REG2, const MemOperand& addr);
858   LSPAIR_MACRO_LIST(DECLARE_FUNCTION)
859 #undef DECLARE_FUNCTION
860 
861   void LoadStorePairMacro(const CPURegister& rt,
862                           const CPURegister& rt2,
863                           const MemOperand& addr,
864                           LoadStorePairOp op);
865 
866   void Prfm(PrefetchOperation op, const MemOperand& addr);
867 
868   // Push or pop up to 4 registers of the same width to or from the stack,
869   // using the current stack pointer as set by SetStackPointer.
870   //
871   // If an argument register is 'NoReg', all further arguments are also assumed
872   // to be 'NoReg', and are thus not pushed or popped.
873   //
874   // Arguments are ordered such that "Push(a, b);" is functionally equivalent
875   // to "Push(a); Push(b);".
876   //
877   // It is valid to push the same register more than once, and there is no
878   // restriction on the order in which registers are specified.
879   //
880   // It is not valid to pop into the same register more than once in one
881   // operation, not even into the zero register.
882   //
883   // If the current stack pointer (as set by SetStackPointer) is sp, then it
884   // must be aligned to 16 bytes on entry and the total size of the specified
885   // registers must also be a multiple of 16 bytes.
886   //
887   // Even if the current stack pointer is not the system stack pointer (sp),
888   // Push (and derived methods) will still modify the system stack pointer in
889   // order to comply with ABI rules about accessing memory below the system
890   // stack pointer.
891   //
892   // Other than the registers passed into Pop, the stack pointer and (possibly)
893   // the system stack pointer, these methods do not modify any other registers.
894   void Push(const CPURegister& src0,
895             const CPURegister& src1 = NoReg,
896             const CPURegister& src2 = NoReg,
897             const CPURegister& src3 = NoReg);
898   void Pop(const CPURegister& dst0,
899            const CPURegister& dst1 = NoReg,
900            const CPURegister& dst2 = NoReg,
901            const CPURegister& dst3 = NoReg);
902 
903   // Alternative forms of Push and Pop, taking a RegList or CPURegList that
904   // specifies the registers that are to be pushed or popped. Higher-numbered
905   // registers are associated with higher memory addresses (as in the A32 push
906   // and pop instructions).
907   //
908   // (Push|Pop)SizeRegList allow you to specify the register size as a
909   // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
910   // supported.
911   //
912   // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred.
913   void PushCPURegList(CPURegList registers);
914   void PopCPURegList(CPURegList registers);
915 
916   void PushSizeRegList(
917       RegList registers,
918       unsigned reg_size,
919       CPURegister::RegisterType type = CPURegister::kRegister) {
920     PushCPURegList(CPURegList(type, reg_size, registers));
921   }
922   void PopSizeRegList(RegList registers,
923                       unsigned reg_size,
924                       CPURegister::RegisterType type = CPURegister::kRegister) {
925     PopCPURegList(CPURegList(type, reg_size, registers));
926   }
PushXRegList(RegList regs)927   void PushXRegList(RegList regs) { PushSizeRegList(regs, kXRegSize); }
PopXRegList(RegList regs)928   void PopXRegList(RegList regs) { PopSizeRegList(regs, kXRegSize); }
PushWRegList(RegList regs)929   void PushWRegList(RegList regs) { PushSizeRegList(regs, kWRegSize); }
PopWRegList(RegList regs)930   void PopWRegList(RegList regs) { PopSizeRegList(regs, kWRegSize); }
PushDRegList(RegList regs)931   void PushDRegList(RegList regs) {
932     PushSizeRegList(regs, kDRegSize, CPURegister::kVRegister);
933   }
PopDRegList(RegList regs)934   void PopDRegList(RegList regs) {
935     PopSizeRegList(regs, kDRegSize, CPURegister::kVRegister);
936   }
PushSRegList(RegList regs)937   void PushSRegList(RegList regs) {
938     PushSizeRegList(regs, kSRegSize, CPURegister::kVRegister);
939   }
PopSRegList(RegList regs)940   void PopSRegList(RegList regs) {
941     PopSizeRegList(regs, kSRegSize, CPURegister::kVRegister);
942   }
943 
944   // Push the specified register 'count' times.
945   void PushMultipleTimes(int count, Register src);
946 
947   // Poke 'src' onto the stack. The offset is in bytes.
948   //
949   // If the current stack pointer (as set by SetStackPointer) is sp, then sp
950   // must be aligned to 16 bytes.
951   void Poke(const Register& src, const Operand& offset);
952 
953   // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes.
954   //
955   // If the current stack pointer (as set by SetStackPointer) is sp, then sp
956   // must be aligned to 16 bytes.
957   void Peek(const Register& dst, const Operand& offset);
958 
959   // Alternative forms of Peek and Poke, taking a RegList or CPURegList that
960   // specifies the registers that are to be pushed or popped. Higher-numbered
961   // registers are associated with higher memory addresses.
962   //
963   // (Peek|Poke)SizeRegList allow you to specify the register size as a
964   // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
965   // supported.
966   //
967   // Otherwise, (Peek|Poke)(CPU|X|W|D|S)RegList is preferred.
PeekCPURegList(CPURegList registers,int64_t offset)968   void PeekCPURegList(CPURegList registers, int64_t offset) {
969     LoadCPURegList(registers, MemOperand(StackPointer(), offset));
970   }
PokeCPURegList(CPURegList registers,int64_t offset)971   void PokeCPURegList(CPURegList registers, int64_t offset) {
972     StoreCPURegList(registers, MemOperand(StackPointer(), offset));
973   }
974 
975   void PeekSizeRegList(
976       RegList registers,
977       int64_t offset,
978       unsigned reg_size,
979       CPURegister::RegisterType type = CPURegister::kRegister) {
980     PeekCPURegList(CPURegList(type, reg_size, registers), offset);
981   }
982   void PokeSizeRegList(
983       RegList registers,
984       int64_t offset,
985       unsigned reg_size,
986       CPURegister::RegisterType type = CPURegister::kRegister) {
987     PokeCPURegList(CPURegList(type, reg_size, registers), offset);
988   }
PeekXRegList(RegList regs,int64_t offset)989   void PeekXRegList(RegList regs, int64_t offset) {
990     PeekSizeRegList(regs, offset, kXRegSize);
991   }
PokeXRegList(RegList regs,int64_t offset)992   void PokeXRegList(RegList regs, int64_t offset) {
993     PokeSizeRegList(regs, offset, kXRegSize);
994   }
PeekWRegList(RegList regs,int64_t offset)995   void PeekWRegList(RegList regs, int64_t offset) {
996     PeekSizeRegList(regs, offset, kWRegSize);
997   }
PokeWRegList(RegList regs,int64_t offset)998   void PokeWRegList(RegList regs, int64_t offset) {
999     PokeSizeRegList(regs, offset, kWRegSize);
1000   }
PeekDRegList(RegList regs,int64_t offset)1001   void PeekDRegList(RegList regs, int64_t offset) {
1002     PeekSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister);
1003   }
PokeDRegList(RegList regs,int64_t offset)1004   void PokeDRegList(RegList regs, int64_t offset) {
1005     PokeSizeRegList(regs, offset, kDRegSize, CPURegister::kVRegister);
1006   }
PeekSRegList(RegList regs,int64_t offset)1007   void PeekSRegList(RegList regs, int64_t offset) {
1008     PeekSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister);
1009   }
PokeSRegList(RegList regs,int64_t offset)1010   void PokeSRegList(RegList regs, int64_t offset) {
1011     PokeSizeRegList(regs, offset, kSRegSize, CPURegister::kVRegister);
1012   }
1013 
1014 
1015   // Claim or drop stack space without actually accessing memory.
1016   //
1017   // If the current stack pointer (as set by SetStackPointer) is sp, then it
1018   // must be aligned to 16 bytes and the size claimed or dropped must be a
1019   // multiple of 16 bytes.
1020   void Claim(const Operand& size);
1021   void Drop(const Operand& size);
1022 
1023   // As above, but for multiples of the SVE vector length.
ClaimVL(int64_t multiplier)1024   void ClaimVL(int64_t multiplier) {
1025     // We never need to worry about sp alignment because the VL is always a
1026     // multiple of 16.
1027     VIXL_STATIC_ASSERT((kZRegMinSizeInBytes % 16) == 0);
1028     VIXL_ASSERT(multiplier >= 0);
1029     Addvl(sp, sp, -multiplier);
1030   }
DropVL(int64_t multiplier)1031   void DropVL(int64_t multiplier) {
1032     VIXL_STATIC_ASSERT((kZRegMinSizeInBytes % 16) == 0);
1033     VIXL_ASSERT(multiplier >= 0);
1034     Addvl(sp, sp, multiplier);
1035   }
1036 
1037   // Preserve the callee-saved registers (as defined by AAPCS64).
1038   //
1039   // Higher-numbered registers are pushed before lower-numbered registers, and
1040   // thus get higher addresses.
1041   // Floating-point registers are pushed before general-purpose registers, and
1042   // thus get higher addresses.
1043   //
1044   // This method must not be called unless StackPointer() is sp, and it is
1045   // aligned to 16 bytes.
1046   void PushCalleeSavedRegisters();
1047 
1048   // Restore the callee-saved registers (as defined by AAPCS64).
1049   //
1050   // Higher-numbered registers are popped after lower-numbered registers, and
1051   // thus come from higher addresses.
1052   // Floating-point registers are popped after general-purpose registers, and
1053   // thus come from higher addresses.
1054   //
1055   // This method must not be called unless StackPointer() is sp, and it is
1056   // aligned to 16 bytes.
1057   void PopCalleeSavedRegisters();
1058 
1059   void LoadCPURegList(CPURegList registers, const MemOperand& src);
1060   void StoreCPURegList(CPURegList registers, const MemOperand& dst);
1061 
1062   // Remaining instructions are simple pass-through calls to the assembler.
Adr(const Register & rd,Label * label)1063   void Adr(const Register& rd, Label* label) {
1064     VIXL_ASSERT(allow_macro_instructions_);
1065     VIXL_ASSERT(!rd.IsZero());
1066     SingleEmissionCheckScope guard(this);
1067     adr(rd, label);
1068   }
Adrp(const Register & rd,Label * label)1069   void Adrp(const Register& rd, Label* label) {
1070     VIXL_ASSERT(allow_macro_instructions_);
1071     VIXL_ASSERT(!rd.IsZero());
1072     SingleEmissionCheckScope guard(this);
1073     adrp(rd, label);
1074   }
Asr(const Register & rd,const Register & rn,unsigned shift)1075   void Asr(const Register& rd, const Register& rn, unsigned shift) {
1076     VIXL_ASSERT(allow_macro_instructions_);
1077     VIXL_ASSERT(!rd.IsZero());
1078     VIXL_ASSERT(!rn.IsZero());
1079     SingleEmissionCheckScope guard(this);
1080     asr(rd, rn, shift);
1081   }
Asr(const Register & rd,const Register & rn,const Register & rm)1082   void Asr(const Register& rd, const Register& rn, const Register& rm) {
1083     VIXL_ASSERT(allow_macro_instructions_);
1084     VIXL_ASSERT(!rd.IsZero());
1085     VIXL_ASSERT(!rn.IsZero());
1086     VIXL_ASSERT(!rm.IsZero());
1087     SingleEmissionCheckScope guard(this);
1088     asrv(rd, rn, rm);
1089   }
1090 
1091   // Branch type inversion relies on these relations.
1092   VIXL_STATIC_ASSERT((reg_zero == (reg_not_zero ^ 1)) &&
1093                      (reg_bit_clear == (reg_bit_set ^ 1)) &&
1094                      (always == (never ^ 1)));
1095 
InvertBranchType(BranchType type)1096   BranchType InvertBranchType(BranchType type) {
1097     if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
1098       return static_cast<BranchType>(
1099           InvertCondition(static_cast<Condition>(type)));
1100     } else {
1101       return static_cast<BranchType>(type ^ 1);
1102     }
1103   }
1104 
1105   void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1);
1106 
1107   void B(Label* label);
1108   void B(Label* label, Condition cond);
B(Condition cond,Label * label)1109   void B(Condition cond, Label* label) { B(label, cond); }
Bfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)1110   void Bfm(const Register& rd,
1111            const Register& rn,
1112            unsigned immr,
1113            unsigned imms) {
1114     VIXL_ASSERT(allow_macro_instructions_);
1115     VIXL_ASSERT(!rd.IsZero());
1116     VIXL_ASSERT(!rn.IsZero());
1117     SingleEmissionCheckScope guard(this);
1118     bfm(rd, rn, immr, imms);
1119   }
Bfi(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1120   void Bfi(const Register& rd,
1121            const Register& rn,
1122            unsigned lsb,
1123            unsigned width) {
1124     VIXL_ASSERT(allow_macro_instructions_);
1125     VIXL_ASSERT(!rd.IsZero());
1126     VIXL_ASSERT(!rn.IsZero());
1127     SingleEmissionCheckScope guard(this);
1128     bfi(rd, rn, lsb, width);
1129   }
Bfc(const Register & rd,unsigned lsb,unsigned width)1130   void Bfc(const Register& rd, unsigned lsb, unsigned width) {
1131     VIXL_ASSERT(allow_macro_instructions_);
1132     VIXL_ASSERT(!rd.IsZero());
1133     SingleEmissionCheckScope guard(this);
1134     bfc(rd, lsb, width);
1135   }
Bfxil(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1136   void Bfxil(const Register& rd,
1137              const Register& rn,
1138              unsigned lsb,
1139              unsigned width) {
1140     VIXL_ASSERT(allow_macro_instructions_);
1141     VIXL_ASSERT(!rd.IsZero());
1142     VIXL_ASSERT(!rn.IsZero());
1143     SingleEmissionCheckScope guard(this);
1144     bfxil(rd, rn, lsb, width);
1145   }
1146   void Bind(Label* label, BranchTargetIdentifier id = EmitBTI_none);
1147   // Bind a label to a specified offset from the start of the buffer.
1148   void BindToOffset(Label* label, ptrdiff_t offset);
Bl(Label * label)1149   void Bl(Label* label) {
1150     VIXL_ASSERT(allow_macro_instructions_);
1151     SingleEmissionCheckScope guard(this);
1152     bl(label);
1153   }
Blr(const Register & xn)1154   void Blr(const Register& xn) {
1155     VIXL_ASSERT(allow_macro_instructions_);
1156     VIXL_ASSERT(!xn.IsZero());
1157     SingleEmissionCheckScope guard(this);
1158     blr(xn);
1159   }
Br(const Register & xn)1160   void Br(const Register& xn) {
1161     VIXL_ASSERT(allow_macro_instructions_);
1162     VIXL_ASSERT(!xn.IsZero());
1163     SingleEmissionCheckScope guard(this);
1164     br(xn);
1165   }
Braaz(const Register & xn)1166   void Braaz(const Register& xn) {
1167     VIXL_ASSERT(allow_macro_instructions_);
1168     SingleEmissionCheckScope guard(this);
1169     braaz(xn);
1170   }
Brabz(const Register & xn)1171   void Brabz(const Register& xn) {
1172     VIXL_ASSERT(allow_macro_instructions_);
1173     SingleEmissionCheckScope guard(this);
1174     brabz(xn);
1175   }
Blraaz(const Register & xn)1176   void Blraaz(const Register& xn) {
1177     VIXL_ASSERT(allow_macro_instructions_);
1178     SingleEmissionCheckScope guard(this);
1179     blraaz(xn);
1180   }
Blrabz(const Register & xn)1181   void Blrabz(const Register& xn) {
1182     VIXL_ASSERT(allow_macro_instructions_);
1183     SingleEmissionCheckScope guard(this);
1184     blrabz(xn);
1185   }
Retaa()1186   void Retaa() {
1187     VIXL_ASSERT(allow_macro_instructions_);
1188     SingleEmissionCheckScope guard(this);
1189     retaa();
1190   }
Retab()1191   void Retab() {
1192     VIXL_ASSERT(allow_macro_instructions_);
1193     SingleEmissionCheckScope guard(this);
1194     retab();
1195   }
Braa(const Register & xn,const Register & xm)1196   void Braa(const Register& xn, const Register& xm) {
1197     VIXL_ASSERT(allow_macro_instructions_);
1198     SingleEmissionCheckScope guard(this);
1199     braa(xn, xm);
1200   }
Brab(const Register & xn,const Register & xm)1201   void Brab(const Register& xn, const Register& xm) {
1202     VIXL_ASSERT(allow_macro_instructions_);
1203     SingleEmissionCheckScope guard(this);
1204     brab(xn, xm);
1205   }
Blraa(const Register & xn,const Register & xm)1206   void Blraa(const Register& xn, const Register& xm) {
1207     VIXL_ASSERT(allow_macro_instructions_);
1208     SingleEmissionCheckScope guard(this);
1209     blraa(xn, xm);
1210   }
Blrab(const Register & xn,const Register & xm)1211   void Blrab(const Register& xn, const Register& xm) {
1212     VIXL_ASSERT(allow_macro_instructions_);
1213     SingleEmissionCheckScope guard(this);
1214     blrab(xn, xm);
1215   }
1216   void Brk(int code = 0) {
1217     VIXL_ASSERT(allow_macro_instructions_);
1218     SingleEmissionCheckScope guard(this);
1219     brk(code);
1220   }
1221   void Cbnz(const Register& rt, Label* label);
1222   void Cbz(const Register& rt, Label* label);
Cinc(const Register & rd,const Register & rn,Condition cond)1223   void Cinc(const Register& rd, const Register& rn, Condition cond) {
1224     VIXL_ASSERT(allow_macro_instructions_);
1225     VIXL_ASSERT(!rd.IsZero());
1226     VIXL_ASSERT(!rn.IsZero());
1227     SingleEmissionCheckScope guard(this);
1228     cinc(rd, rn, cond);
1229   }
Cinv(const Register & rd,const Register & rn,Condition cond)1230   void Cinv(const Register& rd, const Register& rn, Condition cond) {
1231     VIXL_ASSERT(allow_macro_instructions_);
1232     VIXL_ASSERT(!rd.IsZero());
1233     VIXL_ASSERT(!rn.IsZero());
1234     SingleEmissionCheckScope guard(this);
1235     cinv(rd, rn, cond);
1236   }
1237 
1238 #define PAUTH_SYSTEM_MODES(V) \
1239   V(az)                       \
1240   V(bz)                       \
1241   V(asp)                      \
1242   V(bsp)
1243 
1244 #define DEFINE_MACRO_ASM_FUNCS(SUFFIX)      \
1245   void Paci##SUFFIX() {                     \
1246     VIXL_ASSERT(allow_macro_instructions_); \
1247     SingleEmissionCheckScope guard(this);   \
1248     paci##SUFFIX();                         \
1249   }                                         \
1250   void Auti##SUFFIX() {                     \
1251     VIXL_ASSERT(allow_macro_instructions_); \
1252     SingleEmissionCheckScope guard(this);   \
1253     auti##SUFFIX();                         \
1254   }
1255 
PAUTH_SYSTEM_MODES(DEFINE_MACRO_ASM_FUNCS)1256   PAUTH_SYSTEM_MODES(DEFINE_MACRO_ASM_FUNCS)
1257 #undef DEFINE_MACRO_ASM_FUNCS
1258 
1259   // The 1716 pac and aut instructions encourage people to use x16 and x17
1260   // directly, perhaps without realising that this is forbidden. For example:
1261   //
1262   //     UseScratchRegisterScope temps(&masm);
1263   //     Register temp = temps.AcquireX();  // temp will be x16
1264   //     __ Mov(x17, ptr);
1265   //     __ Mov(x16, modifier);  // Will override temp!
1266   //     __ Pacia1716();
1267   //
1268   // To work around this issue, you must exclude x16 and x17 from the scratch
1269   // register list. You may need to replace them with other registers:
1270   //
1271   //     UseScratchRegisterScope temps(&masm);
1272   //     temps.Exclude(x16, x17);
1273   //     temps.Include(x10, x11);
1274   //     __ Mov(x17, ptr);
1275   //     __ Mov(x16, modifier);
1276   //     __ Pacia1716();
1277   void Pacia1716() {
1278     VIXL_ASSERT(allow_macro_instructions_);
1279     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x16));
1280     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x17));
1281     SingleEmissionCheckScope guard(this);
1282     pacia1716();
1283   }
Pacib1716()1284   void Pacib1716() {
1285     VIXL_ASSERT(allow_macro_instructions_);
1286     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x16));
1287     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x17));
1288     SingleEmissionCheckScope guard(this);
1289     pacib1716();
1290   }
Autia1716()1291   void Autia1716() {
1292     VIXL_ASSERT(allow_macro_instructions_);
1293     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x16));
1294     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x17));
1295     SingleEmissionCheckScope guard(this);
1296     autia1716();
1297   }
Autib1716()1298   void Autib1716() {
1299     VIXL_ASSERT(allow_macro_instructions_);
1300     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x16));
1301     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(x17));
1302     SingleEmissionCheckScope guard(this);
1303     autib1716();
1304   }
Xpaclri()1305   void Xpaclri() {
1306     VIXL_ASSERT(allow_macro_instructions_);
1307     SingleEmissionCheckScope guard(this);
1308     xpaclri();
1309   }
Clrex()1310   void Clrex() {
1311     VIXL_ASSERT(allow_macro_instructions_);
1312     SingleEmissionCheckScope guard(this);
1313     clrex();
1314   }
Cls(const Register & rd,const Register & rn)1315   void Cls(const Register& rd, const Register& rn) {
1316     VIXL_ASSERT(allow_macro_instructions_);
1317     VIXL_ASSERT(!rd.IsZero());
1318     VIXL_ASSERT(!rn.IsZero());
1319     SingleEmissionCheckScope guard(this);
1320     cls(rd, rn);
1321   }
Clz(const Register & rd,const Register & rn)1322   void Clz(const Register& rd, const Register& rn) {
1323     VIXL_ASSERT(allow_macro_instructions_);
1324     VIXL_ASSERT(!rd.IsZero());
1325     VIXL_ASSERT(!rn.IsZero());
1326     SingleEmissionCheckScope guard(this);
1327     clz(rd, rn);
1328   }
Cneg(const Register & rd,const Register & rn,Condition cond)1329   void Cneg(const Register& rd, const Register& rn, Condition cond) {
1330     VIXL_ASSERT(allow_macro_instructions_);
1331     VIXL_ASSERT(!rd.IsZero());
1332     VIXL_ASSERT(!rn.IsZero());
1333     SingleEmissionCheckScope guard(this);
1334     cneg(rd, rn, cond);
1335   }
Esb()1336   void Esb() {
1337     VIXL_ASSERT(allow_macro_instructions_);
1338     SingleEmissionCheckScope guard(this);
1339     esb();
1340   }
Csdb()1341   void Csdb() {
1342     VIXL_ASSERT(allow_macro_instructions_);
1343     SingleEmissionCheckScope guard(this);
1344     csdb();
1345   }
Cset(const Register & rd,Condition cond)1346   void Cset(const Register& rd, Condition cond) {
1347     VIXL_ASSERT(allow_macro_instructions_);
1348     VIXL_ASSERT(!rd.IsZero());
1349     SingleEmissionCheckScope guard(this);
1350     cset(rd, cond);
1351   }
Csetm(const Register & rd,Condition cond)1352   void Csetm(const Register& rd, Condition cond) {
1353     VIXL_ASSERT(allow_macro_instructions_);
1354     VIXL_ASSERT(!rd.IsZero());
1355     SingleEmissionCheckScope guard(this);
1356     csetm(rd, cond);
1357   }
Csinc(const Register & rd,const Register & rn,const Register & rm,Condition cond)1358   void Csinc(const Register& rd,
1359              const Register& rn,
1360              const Register& rm,
1361              Condition cond) {
1362     VIXL_ASSERT(allow_macro_instructions_);
1363     VIXL_ASSERT(!rd.IsZero());
1364     VIXL_ASSERT((cond != al) && (cond != nv));
1365     SingleEmissionCheckScope guard(this);
1366     csinc(rd, rn, rm, cond);
1367   }
Csinv(const Register & rd,const Register & rn,const Register & rm,Condition cond)1368   void Csinv(const Register& rd,
1369              const Register& rn,
1370              const Register& rm,
1371              Condition cond) {
1372     VIXL_ASSERT(allow_macro_instructions_);
1373     VIXL_ASSERT(!rd.IsZero());
1374     VIXL_ASSERT((cond != al) && (cond != nv));
1375     SingleEmissionCheckScope guard(this);
1376     csinv(rd, rn, rm, cond);
1377   }
Csneg(const Register & rd,const Register & rn,const Register & rm,Condition cond)1378   void Csneg(const Register& rd,
1379              const Register& rn,
1380              const Register& rm,
1381              Condition cond) {
1382     VIXL_ASSERT(allow_macro_instructions_);
1383     VIXL_ASSERT(!rd.IsZero());
1384     VIXL_ASSERT((cond != al) && (cond != nv));
1385     SingleEmissionCheckScope guard(this);
1386     csneg(rd, rn, rm, cond);
1387   }
Dmb(BarrierDomain domain,BarrierType type)1388   void Dmb(BarrierDomain domain, BarrierType type) {
1389     VIXL_ASSERT(allow_macro_instructions_);
1390     SingleEmissionCheckScope guard(this);
1391     dmb(domain, type);
1392   }
Dsb(BarrierDomain domain,BarrierType type)1393   void Dsb(BarrierDomain domain, BarrierType type) {
1394     VIXL_ASSERT(allow_macro_instructions_);
1395     SingleEmissionCheckScope guard(this);
1396     dsb(domain, type);
1397   }
Extr(const Register & rd,const Register & rn,const Register & rm,unsigned lsb)1398   void Extr(const Register& rd,
1399             const Register& rn,
1400             const Register& rm,
1401             unsigned lsb) {
1402     VIXL_ASSERT(allow_macro_instructions_);
1403     VIXL_ASSERT(!rd.IsZero());
1404     VIXL_ASSERT(!rn.IsZero());
1405     VIXL_ASSERT(!rm.IsZero());
1406     SingleEmissionCheckScope guard(this);
1407     extr(rd, rn, rm, lsb);
1408   }
Fadd(const VRegister & vd,const VRegister & vn,const VRegister & vm)1409   void Fadd(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1410     VIXL_ASSERT(allow_macro_instructions_);
1411     SingleEmissionCheckScope guard(this);
1412     fadd(vd, vn, vm);
1413   }
1414   void Fccmp(const VRegister& vn,
1415              const VRegister& vm,
1416              StatusFlags nzcv,
1417              Condition cond,
1418              FPTrapFlags trap = DisableTrap) {
1419     VIXL_ASSERT(allow_macro_instructions_);
1420     VIXL_ASSERT((cond != al) && (cond != nv));
1421     SingleEmissionCheckScope guard(this);
1422     FPCCompareMacro(vn, vm, nzcv, cond, trap);
1423   }
Fccmpe(const VRegister & vn,const VRegister & vm,StatusFlags nzcv,Condition cond)1424   void Fccmpe(const VRegister& vn,
1425               const VRegister& vm,
1426               StatusFlags nzcv,
1427               Condition cond) {
1428     Fccmp(vn, vm, nzcv, cond, EnableTrap);
1429   }
1430   void Fcmp(const VRegister& vn,
1431             const VRegister& vm,
1432             FPTrapFlags trap = DisableTrap) {
1433     VIXL_ASSERT(allow_macro_instructions_);
1434     SingleEmissionCheckScope guard(this);
1435     FPCompareMacro(vn, vm, trap);
1436   }
1437   void Fcmp(const VRegister& vn, double value, FPTrapFlags trap = DisableTrap);
1438   void Fcmpe(const VRegister& vn, double value);
Fcmpe(const VRegister & vn,const VRegister & vm)1439   void Fcmpe(const VRegister& vn, const VRegister& vm) {
1440     Fcmp(vn, vm, EnableTrap);
1441   }
Fcsel(const VRegister & vd,const VRegister & vn,const VRegister & vm,Condition cond)1442   void Fcsel(const VRegister& vd,
1443              const VRegister& vn,
1444              const VRegister& vm,
1445              Condition cond) {
1446     VIXL_ASSERT(allow_macro_instructions_);
1447     VIXL_ASSERT((cond != al) && (cond != nv));
1448     SingleEmissionCheckScope guard(this);
1449     fcsel(vd, vn, vm, cond);
1450   }
Fcvt(const VRegister & vd,const VRegister & vn)1451   void Fcvt(const VRegister& vd, const VRegister& vn) {
1452     VIXL_ASSERT(allow_macro_instructions_);
1453     SingleEmissionCheckScope guard(this);
1454     fcvt(vd, vn);
1455   }
Fcvtl(const VRegister & vd,const VRegister & vn)1456   void Fcvtl(const VRegister& vd, const VRegister& vn) {
1457     VIXL_ASSERT(allow_macro_instructions_);
1458     SingleEmissionCheckScope guard(this);
1459     fcvtl(vd, vn);
1460   }
Fcvtl2(const VRegister & vd,const VRegister & vn)1461   void Fcvtl2(const VRegister& vd, const VRegister& vn) {
1462     VIXL_ASSERT(allow_macro_instructions_);
1463     SingleEmissionCheckScope guard(this);
1464     fcvtl2(vd, vn);
1465   }
Fcvtn(const VRegister & vd,const VRegister & vn)1466   void Fcvtn(const VRegister& vd, const VRegister& vn) {
1467     VIXL_ASSERT(allow_macro_instructions_);
1468     SingleEmissionCheckScope guard(this);
1469     fcvtn(vd, vn);
1470   }
Fcvtn2(const VRegister & vd,const VRegister & vn)1471   void Fcvtn2(const VRegister& vd, const VRegister& vn) {
1472     VIXL_ASSERT(allow_macro_instructions_);
1473     SingleEmissionCheckScope guard(this);
1474     fcvtn2(vd, vn);
1475   }
Fcvtxn(const VRegister & vd,const VRegister & vn)1476   void Fcvtxn(const VRegister& vd, const VRegister& vn) {
1477     VIXL_ASSERT(allow_macro_instructions_);
1478     SingleEmissionCheckScope guard(this);
1479     fcvtxn(vd, vn);
1480   }
Fcvtxn2(const VRegister & vd,const VRegister & vn)1481   void Fcvtxn2(const VRegister& vd, const VRegister& vn) {
1482     VIXL_ASSERT(allow_macro_instructions_);
1483     SingleEmissionCheckScope guard(this);
1484     fcvtxn2(vd, vn);
1485   }
Fcvtas(const Register & rd,const VRegister & vn)1486   void Fcvtas(const Register& rd, const VRegister& vn) {
1487     VIXL_ASSERT(allow_macro_instructions_);
1488     VIXL_ASSERT(!rd.IsZero());
1489     SingleEmissionCheckScope guard(this);
1490     fcvtas(rd, vn);
1491   }
Fcvtau(const Register & rd,const VRegister & vn)1492   void Fcvtau(const Register& rd, const VRegister& vn) {
1493     VIXL_ASSERT(allow_macro_instructions_);
1494     VIXL_ASSERT(!rd.IsZero());
1495     SingleEmissionCheckScope guard(this);
1496     fcvtau(rd, vn);
1497   }
Fcvtms(const Register & rd,const VRegister & vn)1498   void Fcvtms(const Register& rd, const VRegister& vn) {
1499     VIXL_ASSERT(allow_macro_instructions_);
1500     VIXL_ASSERT(!rd.IsZero());
1501     SingleEmissionCheckScope guard(this);
1502     fcvtms(rd, vn);
1503   }
Fcvtmu(const Register & rd,const VRegister & vn)1504   void Fcvtmu(const Register& rd, const VRegister& vn) {
1505     VIXL_ASSERT(allow_macro_instructions_);
1506     VIXL_ASSERT(!rd.IsZero());
1507     SingleEmissionCheckScope guard(this);
1508     fcvtmu(rd, vn);
1509   }
Fcvtns(const Register & rd,const VRegister & vn)1510   void Fcvtns(const Register& rd, const VRegister& vn) {
1511     VIXL_ASSERT(allow_macro_instructions_);
1512     VIXL_ASSERT(!rd.IsZero());
1513     SingleEmissionCheckScope guard(this);
1514     fcvtns(rd, vn);
1515   }
Fcvtnu(const Register & rd,const VRegister & vn)1516   void Fcvtnu(const Register& rd, const VRegister& vn) {
1517     VIXL_ASSERT(allow_macro_instructions_);
1518     VIXL_ASSERT(!rd.IsZero());
1519     SingleEmissionCheckScope guard(this);
1520     fcvtnu(rd, vn);
1521   }
Fcvtps(const Register & rd,const VRegister & vn)1522   void Fcvtps(const Register& rd, const VRegister& vn) {
1523     VIXL_ASSERT(allow_macro_instructions_);
1524     VIXL_ASSERT(!rd.IsZero());
1525     SingleEmissionCheckScope guard(this);
1526     fcvtps(rd, vn);
1527   }
Fcvtpu(const Register & rd,const VRegister & vn)1528   void Fcvtpu(const Register& rd, const VRegister& vn) {
1529     VIXL_ASSERT(allow_macro_instructions_);
1530     VIXL_ASSERT(!rd.IsZero());
1531     SingleEmissionCheckScope guard(this);
1532     fcvtpu(rd, vn);
1533   }
1534   void Fcvtzs(const Register& rd, const VRegister& vn, int fbits = 0) {
1535     VIXL_ASSERT(allow_macro_instructions_);
1536     VIXL_ASSERT(!rd.IsZero());
1537     SingleEmissionCheckScope guard(this);
1538     fcvtzs(rd, vn, fbits);
1539   }
Fjcvtzs(const Register & rd,const VRegister & vn)1540   void Fjcvtzs(const Register& rd, const VRegister& vn) {
1541     VIXL_ASSERT(allow_macro_instructions_);
1542     VIXL_ASSERT(!rd.IsZero());
1543     SingleEmissionCheckScope guard(this);
1544     fjcvtzs(rd, vn);
1545   }
1546   void Fcvtzu(const Register& rd, const VRegister& vn, int fbits = 0) {
1547     VIXL_ASSERT(allow_macro_instructions_);
1548     VIXL_ASSERT(!rd.IsZero());
1549     SingleEmissionCheckScope guard(this);
1550     fcvtzu(rd, vn, fbits);
1551   }
Fdiv(const VRegister & vd,const VRegister & vn,const VRegister & vm)1552   void Fdiv(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1553     VIXL_ASSERT(allow_macro_instructions_);
1554     SingleEmissionCheckScope guard(this);
1555     fdiv(vd, vn, vm);
1556   }
Fmax(const VRegister & vd,const VRegister & vn,const VRegister & vm)1557   void Fmax(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1558     VIXL_ASSERT(allow_macro_instructions_);
1559     SingleEmissionCheckScope guard(this);
1560     fmax(vd, vn, vm);
1561   }
Fmaxnm(const VRegister & vd,const VRegister & vn,const VRegister & vm)1562   void Fmaxnm(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1563     VIXL_ASSERT(allow_macro_instructions_);
1564     SingleEmissionCheckScope guard(this);
1565     fmaxnm(vd, vn, vm);
1566   }
Fmin(const VRegister & vd,const VRegister & vn,const VRegister & vm)1567   void Fmin(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1568     VIXL_ASSERT(allow_macro_instructions_);
1569     SingleEmissionCheckScope guard(this);
1570     fmin(vd, vn, vm);
1571   }
Fminnm(const VRegister & vd,const VRegister & vn,const VRegister & vm)1572   void Fminnm(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1573     VIXL_ASSERT(allow_macro_instructions_);
1574     SingleEmissionCheckScope guard(this);
1575     fminnm(vd, vn, vm);
1576   }
Fmov(const VRegister & vd,const VRegister & vn)1577   void Fmov(const VRegister& vd, const VRegister& vn) {
1578     VIXL_ASSERT(allow_macro_instructions_);
1579     SingleEmissionCheckScope guard(this);
1580     // TODO: Use DiscardMoveMode to allow this move to be elided if vd.Is(vn).
1581     fmov(vd, vn);
1582   }
Fmov(const VRegister & vd,const Register & rn)1583   void Fmov(const VRegister& vd, const Register& rn) {
1584     VIXL_ASSERT(allow_macro_instructions_);
1585     VIXL_ASSERT(!rn.IsZero());
1586     SingleEmissionCheckScope guard(this);
1587     fmov(vd, rn);
1588   }
Fmov(const VRegister & vd,int index,const Register & rn)1589   void Fmov(const VRegister& vd, int index, const Register& rn) {
1590     VIXL_ASSERT(allow_macro_instructions_);
1591     SingleEmissionCheckScope guard(this);
1592     if (vd.Is1D() && (index == 0)) {
1593       mov(vd, index, rn);
1594     } else {
1595       fmov(vd, index, rn);
1596     }
1597   }
Fmov(const Register & rd,const VRegister & vn,int index)1598   void Fmov(const Register& rd, const VRegister& vn, int index) {
1599     VIXL_ASSERT(allow_macro_instructions_);
1600     SingleEmissionCheckScope guard(this);
1601     if (vn.Is1D() && (index == 0)) {
1602       mov(rd, vn, index);
1603     } else {
1604       fmov(rd, vn, index);
1605     }
1606   }
1607 
1608   // Provide explicit double and float interfaces for FP immediate moves, rather
1609   // than relying on implicit C++ casts. This allows signalling NaNs to be
1610   // preserved when the immediate matches the format of vd. Most systems convert
1611   // signalling NaNs to quiet NaNs when converting between float and double.
1612   void Fmov(VRegister vd, double imm);
1613   void Fmov(VRegister vd, float imm);
1614   void Fmov(VRegister vd, const Float16 imm);
1615   // Provide a template to allow other types to be converted automatically.
1616   template <typename T>
Fmov(VRegister vd,T imm)1617   void Fmov(VRegister vd, T imm) {
1618     VIXL_ASSERT(allow_macro_instructions_);
1619     Fmov(vd, static_cast<double>(imm));
1620   }
Fmov(Register rd,VRegister vn)1621   void Fmov(Register rd, VRegister vn) {
1622     VIXL_ASSERT(allow_macro_instructions_);
1623     VIXL_ASSERT(!rd.IsZero());
1624     SingleEmissionCheckScope guard(this);
1625     fmov(rd, vn);
1626   }
Fmul(const VRegister & vd,const VRegister & vn,const VRegister & vm)1627   void Fmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1628     VIXL_ASSERT(allow_macro_instructions_);
1629     SingleEmissionCheckScope guard(this);
1630     fmul(vd, vn, vm);
1631   }
Fnmul(const VRegister & vd,const VRegister & vn,const VRegister & vm)1632   void Fnmul(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1633     VIXL_ASSERT(allow_macro_instructions_);
1634     SingleEmissionCheckScope guard(this);
1635     fnmul(vd, vn, vm);
1636   }
Fmadd(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)1637   void Fmadd(const VRegister& vd,
1638              const VRegister& vn,
1639              const VRegister& vm,
1640              const VRegister& va) {
1641     VIXL_ASSERT(allow_macro_instructions_);
1642     SingleEmissionCheckScope guard(this);
1643     fmadd(vd, vn, vm, va);
1644   }
Fmsub(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)1645   void Fmsub(const VRegister& vd,
1646              const VRegister& vn,
1647              const VRegister& vm,
1648              const VRegister& va) {
1649     VIXL_ASSERT(allow_macro_instructions_);
1650     SingleEmissionCheckScope guard(this);
1651     fmsub(vd, vn, vm, va);
1652   }
Fnmadd(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)1653   void Fnmadd(const VRegister& vd,
1654               const VRegister& vn,
1655               const VRegister& vm,
1656               const VRegister& va) {
1657     VIXL_ASSERT(allow_macro_instructions_);
1658     SingleEmissionCheckScope guard(this);
1659     fnmadd(vd, vn, vm, va);
1660   }
Fnmsub(const VRegister & vd,const VRegister & vn,const VRegister & vm,const VRegister & va)1661   void Fnmsub(const VRegister& vd,
1662               const VRegister& vn,
1663               const VRegister& vm,
1664               const VRegister& va) {
1665     VIXL_ASSERT(allow_macro_instructions_);
1666     SingleEmissionCheckScope guard(this);
1667     fnmsub(vd, vn, vm, va);
1668   }
Fsub(const VRegister & vd,const VRegister & vn,const VRegister & vm)1669   void Fsub(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
1670     VIXL_ASSERT(allow_macro_instructions_);
1671     SingleEmissionCheckScope guard(this);
1672     fsub(vd, vn, vm);
1673   }
Hint(SystemHint code)1674   void Hint(SystemHint code) {
1675     VIXL_ASSERT(allow_macro_instructions_);
1676     SingleEmissionCheckScope guard(this);
1677     hint(code);
1678   }
Hint(int imm7)1679   void Hint(int imm7) {
1680     VIXL_ASSERT(allow_macro_instructions_);
1681     SingleEmissionCheckScope guard(this);
1682     hint(imm7);
1683   }
Hlt(int code)1684   void Hlt(int code) {
1685     VIXL_ASSERT(allow_macro_instructions_);
1686     SingleEmissionCheckScope guard(this);
1687     hlt(code);
1688   }
Isb()1689   void Isb() {
1690     VIXL_ASSERT(allow_macro_instructions_);
1691     SingleEmissionCheckScope guard(this);
1692     isb();
1693   }
Ldar(const Register & rt,const MemOperand & src)1694   void Ldar(const Register& rt, const MemOperand& src) {
1695     VIXL_ASSERT(allow_macro_instructions_);
1696     SingleEmissionCheckScope guard(this);
1697     ldar(rt, src);
1698   }
Ldarb(const Register & rt,const MemOperand & src)1699   void Ldarb(const Register& rt, const MemOperand& src) {
1700     VIXL_ASSERT(allow_macro_instructions_);
1701     SingleEmissionCheckScope guard(this);
1702     ldarb(rt, src);
1703   }
Ldarh(const Register & rt,const MemOperand & src)1704   void Ldarh(const Register& rt, const MemOperand& src) {
1705     VIXL_ASSERT(allow_macro_instructions_);
1706     SingleEmissionCheckScope guard(this);
1707     ldarh(rt, src);
1708   }
Ldlar(const Register & rt,const MemOperand & src)1709   void Ldlar(const Register& rt, const MemOperand& src) {
1710     VIXL_ASSERT(allow_macro_instructions_);
1711     SingleEmissionCheckScope guard(this);
1712     ldlar(rt, src);
1713   }
Ldlarb(const Register & rt,const MemOperand & src)1714   void Ldlarb(const Register& rt, const MemOperand& src) {
1715     VIXL_ASSERT(allow_macro_instructions_);
1716     SingleEmissionCheckScope guard(this);
1717     ldlarb(rt, src);
1718   }
Ldlarh(const Register & rt,const MemOperand & src)1719   void Ldlarh(const Register& rt, const MemOperand& src) {
1720     VIXL_ASSERT(allow_macro_instructions_);
1721     SingleEmissionCheckScope guard(this);
1722     ldlarh(rt, src);
1723   }
Ldaxp(const Register & rt,const Register & rt2,const MemOperand & src)1724   void Ldaxp(const Register& rt, const Register& rt2, const MemOperand& src) {
1725     VIXL_ASSERT(allow_macro_instructions_);
1726     VIXL_ASSERT(!rt.Aliases(rt2));
1727     SingleEmissionCheckScope guard(this);
1728     ldaxp(rt, rt2, src);
1729   }
Ldaxr(const Register & rt,const MemOperand & src)1730   void Ldaxr(const Register& rt, const MemOperand& src) {
1731     VIXL_ASSERT(allow_macro_instructions_);
1732     SingleEmissionCheckScope guard(this);
1733     ldaxr(rt, src);
1734   }
Ldaxrb(const Register & rt,const MemOperand & src)1735   void Ldaxrb(const Register& rt, const MemOperand& src) {
1736     VIXL_ASSERT(allow_macro_instructions_);
1737     SingleEmissionCheckScope guard(this);
1738     ldaxrb(rt, src);
1739   }
Ldaxrh(const Register & rt,const MemOperand & src)1740   void Ldaxrh(const Register& rt, const MemOperand& src) {
1741     VIXL_ASSERT(allow_macro_instructions_);
1742     SingleEmissionCheckScope guard(this);
1743     ldaxrh(rt, src);
1744   }
1745 
1746 // clang-format off
1747 #define COMPARE_AND_SWAP_SINGLE_MACRO_LIST(V) \
1748   V(cas,    Cas)                              \
1749   V(casa,   Casa)                             \
1750   V(casl,   Casl)                             \
1751   V(casal,  Casal)                            \
1752   V(casb,   Casb)                             \
1753   V(casab,  Casab)                            \
1754   V(caslb,  Caslb)                            \
1755   V(casalb, Casalb)                           \
1756   V(cash,   Cash)                             \
1757   V(casah,  Casah)                            \
1758   V(caslh,  Caslh)                            \
1759   V(casalh, Casalh)
1760 // clang-format on
1761 
1762 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)                                     \
1763   void MASM(const Register& rs, const Register& rt, const MemOperand& src) { \
1764     VIXL_ASSERT(allow_macro_instructions_);                                  \
1765     SingleEmissionCheckScope guard(this);                                    \
1766     ASM(rs, rt, src);                                                        \
1767   }
1768   COMPARE_AND_SWAP_SINGLE_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
1769 #undef DEFINE_MACRO_ASM_FUNC
1770 
1771 
1772 // clang-format off
1773 #define COMPARE_AND_SWAP_PAIR_MACRO_LIST(V) \
1774   V(casp,   Casp)                           \
1775   V(caspa,  Caspa)                          \
1776   V(caspl,  Caspl)                          \
1777   V(caspal, Caspal)
1778 // clang-format on
1779 
1780 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)    \
1781   void MASM(const Register& rs,             \
1782             const Register& rs2,            \
1783             const Register& rt,             \
1784             const Register& rt2,            \
1785             const MemOperand& src) {        \
1786     VIXL_ASSERT(allow_macro_instructions_); \
1787     SingleEmissionCheckScope guard(this);   \
1788     ASM(rs, rs2, rt, rt2, src);             \
1789   }
COMPARE_AND_SWAP_PAIR_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)1790   COMPARE_AND_SWAP_PAIR_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
1791 #undef DEFINE_MACRO_ASM_FUNC
1792 
1793 // These macros generate all the variations of the atomic memory operations,
1794 // e.g. ldadd, ldadda, ldaddb, staddl, etc.
1795 
1796 // clang-format off
1797 #define ATOMIC_MEMORY_SIMPLE_MACRO_LIST(V, DEF, MASM_PRE, ASM_PRE) \
1798   V(DEF, MASM_PRE##add,  ASM_PRE##add)                             \
1799   V(DEF, MASM_PRE##clr,  ASM_PRE##clr)                             \
1800   V(DEF, MASM_PRE##eor,  ASM_PRE##eor)                             \
1801   V(DEF, MASM_PRE##set,  ASM_PRE##set)                             \
1802   V(DEF, MASM_PRE##smax, ASM_PRE##smax)                            \
1803   V(DEF, MASM_PRE##smin, ASM_PRE##smin)                            \
1804   V(DEF, MASM_PRE##umax, ASM_PRE##umax)                            \
1805   V(DEF, MASM_PRE##umin, ASM_PRE##umin)
1806 
1807 #define ATOMIC_MEMORY_STORE_MACRO_MODES(V, MASM, ASM) \
1808   V(MASM,     ASM)                                    \
1809   V(MASM##l,  ASM##l)                                 \
1810   V(MASM##b,  ASM##b)                                 \
1811   V(MASM##lb, ASM##lb)                                \
1812   V(MASM##h,  ASM##h)                                 \
1813   V(MASM##lh, ASM##lh)
1814 
1815 #define ATOMIC_MEMORY_LOAD_MACRO_MODES(V, MASM, ASM) \
1816   ATOMIC_MEMORY_STORE_MACRO_MODES(V, MASM, ASM)      \
1817   V(MASM##a,   ASM##a)                               \
1818   V(MASM##al,  ASM##al)                              \
1819   V(MASM##ab,  ASM##ab)                              \
1820   V(MASM##alb, ASM##alb)                             \
1821   V(MASM##ah,  ASM##ah)                              \
1822   V(MASM##alh, ASM##alh)
1823 // clang-format on
1824 
1825 #define DEFINE_MACRO_LOAD_ASM_FUNC(MASM, ASM)                                \
1826   void MASM(const Register& rs, const Register& rt, const MemOperand& src) { \
1827     VIXL_ASSERT(allow_macro_instructions_);                                  \
1828     SingleEmissionCheckScope guard(this);                                    \
1829     ASM(rs, rt, src);                                                        \
1830   }
1831 #define DEFINE_MACRO_STORE_ASM_FUNC(MASM, ASM)           \
1832   void MASM(const Register& rs, const MemOperand& src) { \
1833     VIXL_ASSERT(allow_macro_instructions_);              \
1834     SingleEmissionCheckScope guard(this);                \
1835     ASM(rs, src);                                        \
1836   }
1837 
1838   ATOMIC_MEMORY_SIMPLE_MACRO_LIST(ATOMIC_MEMORY_LOAD_MACRO_MODES,
1839                                   DEFINE_MACRO_LOAD_ASM_FUNC,
1840                                   Ld,
1841                                   ld)
1842   ATOMIC_MEMORY_SIMPLE_MACRO_LIST(ATOMIC_MEMORY_STORE_MACRO_MODES,
1843                                   DEFINE_MACRO_STORE_ASM_FUNC,
1844                                   St,
1845                                   st)
1846 
1847 #define DEFINE_MACRO_SWP_ASM_FUNC(MASM, ASM)                                 \
1848   void MASM(const Register& rs, const Register& rt, const MemOperand& src) { \
1849     VIXL_ASSERT(allow_macro_instructions_);                                  \
1850     SingleEmissionCheckScope guard(this);                                    \
1851     ASM(rs, rt, src);                                                        \
1852   }
1853 
1854   ATOMIC_MEMORY_LOAD_MACRO_MODES(DEFINE_MACRO_SWP_ASM_FUNC, Swp, swp)
1855 
1856 #undef DEFINE_MACRO_LOAD_ASM_FUNC
1857 #undef DEFINE_MACRO_STORE_ASM_FUNC
1858 #undef DEFINE_MACRO_SWP_ASM_FUNC
1859 
1860   void Ldaprb(const Register& rt, const MemOperand& src) {
1861     VIXL_ASSERT(allow_macro_instructions_);
1862     SingleEmissionCheckScope guard(this);
1863     VIXL_ASSERT(src.IsImmediateOffset());
1864     if (src.GetOffset() == 0) {
1865       ldaprb(rt, src);
1866     } else {
1867       ldapurb(rt, src);
1868     }
1869   }
1870 
Ldapursb(const Register & rt,const MemOperand & src)1871   void Ldapursb(const Register& rt, const MemOperand& src) {
1872     VIXL_ASSERT(allow_macro_instructions_);
1873     SingleEmissionCheckScope guard(this);
1874     ldapursb(rt, src);
1875   }
1876 
Ldaprh(const Register & rt,const MemOperand & src)1877   void Ldaprh(const Register& rt, const MemOperand& src) {
1878     VIXL_ASSERT(allow_macro_instructions_);
1879     SingleEmissionCheckScope guard(this);
1880     VIXL_ASSERT(src.IsImmediateOffset());
1881     if (src.GetOffset() == 0) {
1882       ldaprh(rt, src);
1883     } else {
1884       ldapurh(rt, src);
1885     }
1886   }
1887 
Ldapursh(const Register & rt,const MemOperand & src)1888   void Ldapursh(const Register& rt, const MemOperand& src) {
1889     VIXL_ASSERT(allow_macro_instructions_);
1890     SingleEmissionCheckScope guard(this);
1891     ldapursh(rt, src);
1892   }
1893 
Ldapr(const Register & rt,const MemOperand & src)1894   void Ldapr(const Register& rt, const MemOperand& src) {
1895     VIXL_ASSERT(allow_macro_instructions_);
1896     SingleEmissionCheckScope guard(this);
1897     VIXL_ASSERT(src.IsImmediateOffset());
1898     if (src.GetOffset() == 0) {
1899       ldapr(rt, src);
1900     } else {
1901       ldapur(rt, src);
1902     }
1903   }
1904 
Ldapursw(const Register & rt,const MemOperand & src)1905   void Ldapursw(const Register& rt, const MemOperand& src) {
1906     VIXL_ASSERT(allow_macro_instructions_);
1907     SingleEmissionCheckScope guard(this);
1908     ldapursw(rt, src);
1909   }
1910 
Ldnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)1911   void Ldnp(const CPURegister& rt,
1912             const CPURegister& rt2,
1913             const MemOperand& src) {
1914     VIXL_ASSERT(allow_macro_instructions_);
1915     SingleEmissionCheckScope guard(this);
1916     ldnp(rt, rt2, src);
1917   }
1918   // Provide both double and float interfaces for FP immediate loads, rather
1919   // than relying on implicit C++ casts. This allows signalling NaNs to be
1920   // preserved when the immediate matches the format of fd. Most systems convert
1921   // signalling NaNs to quiet NaNs when converting between float and double.
Ldr(const VRegister & vt,double imm)1922   void Ldr(const VRegister& vt, double imm) {
1923     VIXL_ASSERT(allow_macro_instructions_);
1924     SingleEmissionCheckScope guard(this);
1925     RawLiteral* literal;
1926     if (vt.IsD()) {
1927       literal = new Literal<double>(imm,
1928                                     &literal_pool_,
1929                                     RawLiteral::kDeletedOnPlacementByPool);
1930     } else {
1931       literal = new Literal<float>(static_cast<float>(imm),
1932                                    &literal_pool_,
1933                                    RawLiteral::kDeletedOnPlacementByPool);
1934     }
1935     ldr(vt, literal);
1936   }
Ldr(const VRegister & vt,float imm)1937   void Ldr(const VRegister& vt, float imm) {
1938     VIXL_ASSERT(allow_macro_instructions_);
1939     SingleEmissionCheckScope guard(this);
1940     RawLiteral* literal;
1941     if (vt.IsS()) {
1942       literal = new Literal<float>(imm,
1943                                    &literal_pool_,
1944                                    RawLiteral::kDeletedOnPlacementByPool);
1945     } else {
1946       literal = new Literal<double>(static_cast<double>(imm),
1947                                     &literal_pool_,
1948                                     RawLiteral::kDeletedOnPlacementByPool);
1949     }
1950     ldr(vt, literal);
1951   }
Ldr(const VRegister & vt,uint64_t high64,uint64_t low64)1952   void Ldr(const VRegister& vt, uint64_t high64, uint64_t low64) {
1953     VIXL_ASSERT(allow_macro_instructions_);
1954     VIXL_ASSERT(vt.IsQ());
1955     SingleEmissionCheckScope guard(this);
1956     ldr(vt,
1957         new Literal<uint64_t>(high64,
1958                               low64,
1959                               &literal_pool_,
1960                               RawLiteral::kDeletedOnPlacementByPool));
1961   }
Ldr(const Register & rt,uint64_t imm)1962   void Ldr(const Register& rt, uint64_t imm) {
1963     VIXL_ASSERT(allow_macro_instructions_);
1964     VIXL_ASSERT(!rt.IsZero());
1965     SingleEmissionCheckScope guard(this);
1966     RawLiteral* literal;
1967     if (rt.Is64Bits()) {
1968       literal = new Literal<uint64_t>(imm,
1969                                       &literal_pool_,
1970                                       RawLiteral::kDeletedOnPlacementByPool);
1971     } else {
1972       VIXL_ASSERT(rt.Is32Bits());
1973       VIXL_ASSERT(IsUint32(imm) || IsInt32(imm));
1974       literal = new Literal<uint32_t>(static_cast<uint32_t>(imm),
1975                                       &literal_pool_,
1976                                       RawLiteral::kDeletedOnPlacementByPool);
1977     }
1978     ldr(rt, literal);
1979   }
Ldrsw(const Register & rt,uint32_t imm)1980   void Ldrsw(const Register& rt, uint32_t imm) {
1981     VIXL_ASSERT(allow_macro_instructions_);
1982     VIXL_ASSERT(!rt.IsZero());
1983     SingleEmissionCheckScope guard(this);
1984     ldrsw(rt,
1985           new Literal<uint32_t>(imm,
1986                                 &literal_pool_,
1987                                 RawLiteral::kDeletedOnPlacementByPool));
1988   }
Ldr(const CPURegister & rt,RawLiteral * literal)1989   void Ldr(const CPURegister& rt, RawLiteral* literal) {
1990     VIXL_ASSERT(allow_macro_instructions_);
1991     SingleEmissionCheckScope guard(this);
1992     ldr(rt, literal);
1993   }
Ldrsw(const Register & rt,RawLiteral * literal)1994   void Ldrsw(const Register& rt, RawLiteral* literal) {
1995     VIXL_ASSERT(allow_macro_instructions_);
1996     SingleEmissionCheckScope guard(this);
1997     ldrsw(rt, literal);
1998   }
Ldxp(const Register & rt,const Register & rt2,const MemOperand & src)1999   void Ldxp(const Register& rt, const Register& rt2, const MemOperand& src) {
2000     VIXL_ASSERT(allow_macro_instructions_);
2001     VIXL_ASSERT(!rt.Aliases(rt2));
2002     SingleEmissionCheckScope guard(this);
2003     ldxp(rt, rt2, src);
2004   }
Ldxr(const Register & rt,const MemOperand & src)2005   void Ldxr(const Register& rt, const MemOperand& src) {
2006     VIXL_ASSERT(allow_macro_instructions_);
2007     SingleEmissionCheckScope guard(this);
2008     ldxr(rt, src);
2009   }
Ldxrb(const Register & rt,const MemOperand & src)2010   void Ldxrb(const Register& rt, const MemOperand& src) {
2011     VIXL_ASSERT(allow_macro_instructions_);
2012     SingleEmissionCheckScope guard(this);
2013     ldxrb(rt, src);
2014   }
Ldxrh(const Register & rt,const MemOperand & src)2015   void Ldxrh(const Register& rt, const MemOperand& src) {
2016     VIXL_ASSERT(allow_macro_instructions_);
2017     SingleEmissionCheckScope guard(this);
2018     ldxrh(rt, src);
2019   }
Lsl(const Register & rd,const Register & rn,unsigned shift)2020   void Lsl(const Register& rd, const Register& rn, unsigned shift) {
2021     VIXL_ASSERT(allow_macro_instructions_);
2022     VIXL_ASSERT(!rd.IsZero());
2023     VIXL_ASSERT(!rn.IsZero());
2024     SingleEmissionCheckScope guard(this);
2025     lsl(rd, rn, shift);
2026   }
Lsl(const Register & rd,const Register & rn,const Register & rm)2027   void Lsl(const Register& rd, const Register& rn, const Register& rm) {
2028     VIXL_ASSERT(allow_macro_instructions_);
2029     VIXL_ASSERT(!rd.IsZero());
2030     VIXL_ASSERT(!rn.IsZero());
2031     VIXL_ASSERT(!rm.IsZero());
2032     SingleEmissionCheckScope guard(this);
2033     lslv(rd, rn, rm);
2034   }
Lsr(const Register & rd,const Register & rn,unsigned shift)2035   void Lsr(const Register& rd, const Register& rn, unsigned shift) {
2036     VIXL_ASSERT(allow_macro_instructions_);
2037     VIXL_ASSERT(!rd.IsZero());
2038     VIXL_ASSERT(!rn.IsZero());
2039     SingleEmissionCheckScope guard(this);
2040     lsr(rd, rn, shift);
2041   }
Lsr(const Register & rd,const Register & rn,const Register & rm)2042   void Lsr(const Register& rd, const Register& rn, const Register& rm) {
2043     VIXL_ASSERT(allow_macro_instructions_);
2044     VIXL_ASSERT(!rd.IsZero());
2045     VIXL_ASSERT(!rn.IsZero());
2046     VIXL_ASSERT(!rm.IsZero());
2047     SingleEmissionCheckScope guard(this);
2048     lsrv(rd, rn, rm);
2049   }
Ldraa(const Register & xt,const MemOperand & src)2050   void Ldraa(const Register& xt, const MemOperand& src) {
2051     VIXL_ASSERT(allow_macro_instructions_);
2052     SingleEmissionCheckScope guard(this);
2053     ldraa(xt, src);
2054   }
Ldrab(const Register & xt,const MemOperand & src)2055   void Ldrab(const Register& xt, const MemOperand& src) {
2056     VIXL_ASSERT(allow_macro_instructions_);
2057     SingleEmissionCheckScope guard(this);
2058     ldrab(xt, src);
2059   }
Madd(const Register & rd,const Register & rn,const Register & rm,const Register & ra)2060   void Madd(const Register& rd,
2061             const Register& rn,
2062             const Register& rm,
2063             const Register& ra) {
2064     VIXL_ASSERT(allow_macro_instructions_);
2065     VIXL_ASSERT(!rd.IsZero());
2066     VIXL_ASSERT(!rn.IsZero());
2067     VIXL_ASSERT(!rm.IsZero());
2068     VIXL_ASSERT(!ra.IsZero());
2069     SingleEmissionCheckScope guard(this);
2070     madd(rd, rn, rm, ra);
2071   }
Mneg(const Register & rd,const Register & rn,const Register & rm)2072   void Mneg(const Register& rd, const Register& rn, const Register& rm) {
2073     VIXL_ASSERT(allow_macro_instructions_);
2074     VIXL_ASSERT(!rd.IsZero());
2075     VIXL_ASSERT(!rn.IsZero());
2076     VIXL_ASSERT(!rm.IsZero());
2077     SingleEmissionCheckScope guard(this);
2078     mneg(rd, rn, rm);
2079   }
2080   void Mov(const Register& rd,
2081            const Register& rn,
2082            DiscardMoveMode discard_mode = kDontDiscardForSameWReg) {
2083     VIXL_ASSERT(allow_macro_instructions_);
2084     // Emit a register move only if the registers are distinct, or if they are
2085     // not X registers.
2086     //
2087     // Note that mov(w0, w0) is not a no-op because it clears the top word of
2088     // x0. A flag is provided (kDiscardForSameWReg) if a move between the same W
2089     // registers is not required to clear the top word of the X register. In
2090     // this case, the instruction is discarded.
2091     //
2092     // If the sp is an operand, add #0 is emitted, otherwise, orr #0.
2093     if (!rd.Is(rn) ||
2094         (rd.Is32Bits() && (discard_mode == kDontDiscardForSameWReg))) {
2095       SingleEmissionCheckScope guard(this);
2096       mov(rd, rn);
2097     }
2098   }
2099   void Movk(const Register& rd, uint64_t imm, int shift = -1) {
2100     VIXL_ASSERT(allow_macro_instructions_);
2101     VIXL_ASSERT(!rd.IsZero());
2102     SingleEmissionCheckScope guard(this);
2103     movk(rd, imm, shift);
2104   }
Mrs(const Register & rt,SystemRegister sysreg)2105   void Mrs(const Register& rt, SystemRegister sysreg) {
2106     VIXL_ASSERT(allow_macro_instructions_);
2107     VIXL_ASSERT(!rt.IsZero());
2108     SingleEmissionCheckScope guard(this);
2109     mrs(rt, sysreg);
2110   }
Msr(SystemRegister sysreg,const Register & rt)2111   void Msr(SystemRegister sysreg, const Register& rt) {
2112     VIXL_ASSERT(allow_macro_instructions_);
2113     VIXL_ASSERT(!rt.IsZero());
2114     SingleEmissionCheckScope guard(this);
2115     msr(sysreg, rt);
2116   }
Cfinv()2117   void Cfinv() {
2118     VIXL_ASSERT(allow_macro_instructions_);
2119     SingleEmissionCheckScope guard(this);
2120     cfinv();
2121   }
Axflag()2122   void Axflag() {
2123     VIXL_ASSERT(allow_macro_instructions_);
2124     SingleEmissionCheckScope guard(this);
2125     axflag();
2126   }
Xaflag()2127   void Xaflag() {
2128     VIXL_ASSERT(allow_macro_instructions_);
2129     SingleEmissionCheckScope guard(this);
2130     xaflag();
2131   }
2132   void Sys(int op1, int crn, int crm, int op2, const Register& rt = xzr) {
2133     VIXL_ASSERT(allow_macro_instructions_);
2134     SingleEmissionCheckScope guard(this);
2135     sys(op1, crn, crm, op2, rt);
2136   }
Dc(DataCacheOp op,const Register & rt)2137   void Dc(DataCacheOp op, const Register& rt) {
2138     VIXL_ASSERT(allow_macro_instructions_);
2139     SingleEmissionCheckScope guard(this);
2140     dc(op, rt);
2141   }
Ic(InstructionCacheOp op,const Register & rt)2142   void Ic(InstructionCacheOp op, const Register& rt) {
2143     VIXL_ASSERT(allow_macro_instructions_);
2144     SingleEmissionCheckScope guard(this);
2145     ic(op, rt);
2146   }
Msub(const Register & rd,const Register & rn,const Register & rm,const Register & ra)2147   void Msub(const Register& rd,
2148             const Register& rn,
2149             const Register& rm,
2150             const Register& ra) {
2151     VIXL_ASSERT(allow_macro_instructions_);
2152     VIXL_ASSERT(!rd.IsZero());
2153     VIXL_ASSERT(!rn.IsZero());
2154     VIXL_ASSERT(!rm.IsZero());
2155     VIXL_ASSERT(!ra.IsZero());
2156     SingleEmissionCheckScope guard(this);
2157     msub(rd, rn, rm, ra);
2158   }
Mul(const Register & rd,const Register & rn,const Register & rm)2159   void Mul(const Register& rd, const Register& rn, const Register& rm) {
2160     VIXL_ASSERT(allow_macro_instructions_);
2161     VIXL_ASSERT(!rd.IsZero());
2162     VIXL_ASSERT(!rn.IsZero());
2163     VIXL_ASSERT(!rm.IsZero());
2164     SingleEmissionCheckScope guard(this);
2165     mul(rd, rn, rm);
2166   }
Nop()2167   void Nop() {
2168     VIXL_ASSERT(allow_macro_instructions_);
2169     SingleEmissionCheckScope guard(this);
2170     nop();
2171   }
Rbit(const Register & rd,const Register & rn)2172   void Rbit(const Register& rd, const Register& rn) {
2173     VIXL_ASSERT(allow_macro_instructions_);
2174     VIXL_ASSERT(!rd.IsZero());
2175     VIXL_ASSERT(!rn.IsZero());
2176     SingleEmissionCheckScope guard(this);
2177     rbit(rd, rn);
2178   }
2179   void Ret(const Register& xn = lr) {
2180     VIXL_ASSERT(allow_macro_instructions_);
2181     VIXL_ASSERT(!xn.IsZero());
2182     SingleEmissionCheckScope guard(this);
2183     ret(xn);
2184   }
Rev(const Register & rd,const Register & rn)2185   void Rev(const Register& rd, const Register& rn) {
2186     VIXL_ASSERT(allow_macro_instructions_);
2187     VIXL_ASSERT(!rd.IsZero());
2188     VIXL_ASSERT(!rn.IsZero());
2189     SingleEmissionCheckScope guard(this);
2190     rev(rd, rn);
2191   }
Rev16(const Register & rd,const Register & rn)2192   void Rev16(const Register& rd, const Register& rn) {
2193     VIXL_ASSERT(allow_macro_instructions_);
2194     VIXL_ASSERT(!rd.IsZero());
2195     VIXL_ASSERT(!rn.IsZero());
2196     SingleEmissionCheckScope guard(this);
2197     rev16(rd, rn);
2198   }
Rev32(const Register & rd,const Register & rn)2199   void Rev32(const Register& rd, const Register& rn) {
2200     VIXL_ASSERT(allow_macro_instructions_);
2201     VIXL_ASSERT(!rd.IsZero());
2202     VIXL_ASSERT(!rn.IsZero());
2203     SingleEmissionCheckScope guard(this);
2204     rev32(rd, rn);
2205   }
Rev64(const Register & rd,const Register & rn)2206   void Rev64(const Register& rd, const Register& rn) {
2207     VIXL_ASSERT(allow_macro_instructions_);
2208     VIXL_ASSERT(!rd.IsZero());
2209     VIXL_ASSERT(!rn.IsZero());
2210     SingleEmissionCheckScope guard(this);
2211     rev64(rd, rn);
2212   }
2213 
2214 #define PAUTH_MASM_VARIATIONS(V) \
2215   V(Paci, paci)                  \
2216   V(Pacd, pacd)                  \
2217   V(Auti, auti)                  \
2218   V(Autd, autd)
2219 
2220 #define DEFINE_MACRO_ASM_FUNCS(MASM_PRE, ASM_PRE)            \
2221   void MASM_PRE##a(const Register& xd, const Register& xn) { \
2222     VIXL_ASSERT(allow_macro_instructions_);                  \
2223     SingleEmissionCheckScope guard(this);                    \
2224     ASM_PRE##a(xd, xn);                                      \
2225   }                                                          \
2226   void MASM_PRE##za(const Register& xd) {                    \
2227     VIXL_ASSERT(allow_macro_instructions_);                  \
2228     SingleEmissionCheckScope guard(this);                    \
2229     ASM_PRE##za(xd);                                         \
2230   }                                                          \
2231   void MASM_PRE##b(const Register& xd, const Register& xn) { \
2232     VIXL_ASSERT(allow_macro_instructions_);                  \
2233     SingleEmissionCheckScope guard(this);                    \
2234     ASM_PRE##b(xd, xn);                                      \
2235   }                                                          \
2236   void MASM_PRE##zb(const Register& xd) {                    \
2237     VIXL_ASSERT(allow_macro_instructions_);                  \
2238     SingleEmissionCheckScope guard(this);                    \
2239     ASM_PRE##zb(xd);                                         \
2240   }
2241 
PAUTH_MASM_VARIATIONS(DEFINE_MACRO_ASM_FUNCS)2242   PAUTH_MASM_VARIATIONS(DEFINE_MACRO_ASM_FUNCS)
2243 #undef DEFINE_MACRO_ASM_FUNCS
2244 
2245   void Pacga(const Register& xd, const Register& xn, const Register& xm) {
2246     VIXL_ASSERT(allow_macro_instructions_);
2247     SingleEmissionCheckScope guard(this);
2248     pacga(xd, xn, xm);
2249   }
2250 
Xpaci(const Register & xd)2251   void Xpaci(const Register& xd) {
2252     VIXL_ASSERT(allow_macro_instructions_);
2253     SingleEmissionCheckScope guard(this);
2254     xpaci(xd);
2255   }
2256 
Xpacd(const Register & xd)2257   void Xpacd(const Register& xd) {
2258     VIXL_ASSERT(allow_macro_instructions_);
2259     SingleEmissionCheckScope guard(this);
2260     xpacd(xd);
2261   }
Ror(const Register & rd,const Register & rs,unsigned shift)2262   void Ror(const Register& rd, const Register& rs, unsigned shift) {
2263     VIXL_ASSERT(allow_macro_instructions_);
2264     VIXL_ASSERT(!rd.IsZero());
2265     VIXL_ASSERT(!rs.IsZero());
2266     SingleEmissionCheckScope guard(this);
2267     ror(rd, rs, shift);
2268   }
Ror(const Register & rd,const Register & rn,const Register & rm)2269   void Ror(const Register& rd, const Register& rn, const Register& rm) {
2270     VIXL_ASSERT(allow_macro_instructions_);
2271     VIXL_ASSERT(!rd.IsZero());
2272     VIXL_ASSERT(!rn.IsZero());
2273     VIXL_ASSERT(!rm.IsZero());
2274     SingleEmissionCheckScope guard(this);
2275     rorv(rd, rn, rm);
2276   }
Sbfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)2277   void Sbfiz(const Register& rd,
2278              const Register& rn,
2279              unsigned lsb,
2280              unsigned width) {
2281     VIXL_ASSERT(allow_macro_instructions_);
2282     VIXL_ASSERT(!rd.IsZero());
2283     VIXL_ASSERT(!rn.IsZero());
2284     SingleEmissionCheckScope guard(this);
2285     sbfiz(rd, rn, lsb, width);
2286   }
Sbfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)2287   void Sbfm(const Register& rd,
2288             const Register& rn,
2289             unsigned immr,
2290             unsigned imms) {
2291     VIXL_ASSERT(allow_macro_instructions_);
2292     VIXL_ASSERT(!rd.IsZero());
2293     VIXL_ASSERT(!rn.IsZero());
2294     SingleEmissionCheckScope guard(this);
2295     sbfm(rd, rn, immr, imms);
2296   }
Sbfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)2297   void Sbfx(const Register& rd,
2298             const Register& rn,
2299             unsigned lsb,
2300             unsigned width) {
2301     VIXL_ASSERT(allow_macro_instructions_);
2302     VIXL_ASSERT(!rd.IsZero());
2303     VIXL_ASSERT(!rn.IsZero());
2304     SingleEmissionCheckScope guard(this);
2305     sbfx(rd, rn, lsb, width);
2306   }
2307   void Scvtf(const VRegister& vd, const Register& rn, int fbits = 0) {
2308     VIXL_ASSERT(allow_macro_instructions_);
2309     VIXL_ASSERT(!rn.IsZero());
2310     SingleEmissionCheckScope guard(this);
2311     scvtf(vd, rn, fbits);
2312   }
Sdiv(const Register & rd,const Register & rn,const Register & rm)2313   void Sdiv(const Register& rd, const Register& rn, const Register& rm) {
2314     VIXL_ASSERT(allow_macro_instructions_);
2315     VIXL_ASSERT(!rd.IsZero());
2316     VIXL_ASSERT(!rn.IsZero());
2317     VIXL_ASSERT(!rm.IsZero());
2318     SingleEmissionCheckScope guard(this);
2319     sdiv(rd, rn, rm);
2320   }
Smaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)2321   void Smaddl(const Register& rd,
2322               const Register& rn,
2323               const Register& rm,
2324               const Register& ra) {
2325     VIXL_ASSERT(allow_macro_instructions_);
2326     VIXL_ASSERT(!rd.IsZero());
2327     VIXL_ASSERT(!rn.IsZero());
2328     VIXL_ASSERT(!rm.IsZero());
2329     VIXL_ASSERT(!ra.IsZero());
2330     SingleEmissionCheckScope guard(this);
2331     smaddl(rd, rn, rm, ra);
2332   }
Smsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)2333   void Smsubl(const Register& rd,
2334               const Register& rn,
2335               const Register& rm,
2336               const Register& ra) {
2337     VIXL_ASSERT(allow_macro_instructions_);
2338     VIXL_ASSERT(!rd.IsZero());
2339     VIXL_ASSERT(!rn.IsZero());
2340     VIXL_ASSERT(!rm.IsZero());
2341     VIXL_ASSERT(!ra.IsZero());
2342     SingleEmissionCheckScope guard(this);
2343     smsubl(rd, rn, rm, ra);
2344   }
Smull(const Register & rd,const Register & rn,const Register & rm)2345   void Smull(const Register& rd, const Register& rn, const Register& rm) {
2346     VIXL_ASSERT(allow_macro_instructions_);
2347     VIXL_ASSERT(!rd.IsZero());
2348     VIXL_ASSERT(!rn.IsZero());
2349     VIXL_ASSERT(!rm.IsZero());
2350     SingleEmissionCheckScope guard(this);
2351     smull(rd, rn, rm);
2352   }
Smulh(const Register & xd,const Register & xn,const Register & xm)2353   void Smulh(const Register& xd, const Register& xn, const Register& xm) {
2354     VIXL_ASSERT(allow_macro_instructions_);
2355     VIXL_ASSERT(!xd.IsZero());
2356     VIXL_ASSERT(!xn.IsZero());
2357     VIXL_ASSERT(!xm.IsZero());
2358     SingleEmissionCheckScope guard(this);
2359     smulh(xd, xn, xm);
2360   }
Stlr(const Register & rt,const MemOperand & dst)2361   void Stlr(const Register& rt, const MemOperand& dst) {
2362     VIXL_ASSERT(allow_macro_instructions_);
2363     SingleEmissionCheckScope guard(this);
2364     VIXL_ASSERT(dst.IsImmediateOffset());
2365     if (dst.GetOffset() == 0) {
2366       stlr(rt, dst);
2367     } else {
2368       stlur(rt, dst);
2369     }
2370   }
Stlrb(const Register & rt,const MemOperand & dst)2371   void Stlrb(const Register& rt, const MemOperand& dst) {
2372     VIXL_ASSERT(allow_macro_instructions_);
2373     SingleEmissionCheckScope guard(this);
2374     VIXL_ASSERT(dst.IsImmediateOffset());
2375     if (dst.GetOffset() == 0) {
2376       stlrb(rt, dst);
2377     } else {
2378       stlurb(rt, dst);
2379     }
2380   }
Stlrh(const Register & rt,const MemOperand & dst)2381   void Stlrh(const Register& rt, const MemOperand& dst) {
2382     VIXL_ASSERT(allow_macro_instructions_);
2383     SingleEmissionCheckScope guard(this);
2384     VIXL_ASSERT(dst.IsImmediateOffset());
2385     if (dst.GetOffset() == 0) {
2386       stlrh(rt, dst);
2387     } else {
2388       stlurh(rt, dst);
2389     }
2390   }
Stllr(const Register & rt,const MemOperand & dst)2391   void Stllr(const Register& rt, const MemOperand& dst) {
2392     VIXL_ASSERT(allow_macro_instructions_);
2393     SingleEmissionCheckScope guard(this);
2394     stllr(rt, dst);
2395   }
Stllrb(const Register & rt,const MemOperand & dst)2396   void Stllrb(const Register& rt, const MemOperand& dst) {
2397     VIXL_ASSERT(allow_macro_instructions_);
2398     SingleEmissionCheckScope guard(this);
2399     stllrb(rt, dst);
2400   }
Stllrh(const Register & rt,const MemOperand & dst)2401   void Stllrh(const Register& rt, const MemOperand& dst) {
2402     VIXL_ASSERT(allow_macro_instructions_);
2403     SingleEmissionCheckScope guard(this);
2404     stllrh(rt, dst);
2405   }
Stlxp(const Register & rs,const Register & rt,const Register & rt2,const MemOperand & dst)2406   void Stlxp(const Register& rs,
2407              const Register& rt,
2408              const Register& rt2,
2409              const MemOperand& dst) {
2410     VIXL_ASSERT(allow_macro_instructions_);
2411     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2412     VIXL_ASSERT(!rs.Aliases(rt));
2413     VIXL_ASSERT(!rs.Aliases(rt2));
2414     SingleEmissionCheckScope guard(this);
2415     stlxp(rs, rt, rt2, dst);
2416   }
Stlxr(const Register & rs,const Register & rt,const MemOperand & dst)2417   void Stlxr(const Register& rs, const Register& rt, const MemOperand& dst) {
2418     VIXL_ASSERT(allow_macro_instructions_);
2419     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2420     VIXL_ASSERT(!rs.Aliases(rt));
2421     SingleEmissionCheckScope guard(this);
2422     stlxr(rs, rt, dst);
2423   }
Stlxrb(const Register & rs,const Register & rt,const MemOperand & dst)2424   void Stlxrb(const Register& rs, const Register& rt, const MemOperand& dst) {
2425     VIXL_ASSERT(allow_macro_instructions_);
2426     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2427     VIXL_ASSERT(!rs.Aliases(rt));
2428     SingleEmissionCheckScope guard(this);
2429     stlxrb(rs, rt, dst);
2430   }
Stlxrh(const Register & rs,const Register & rt,const MemOperand & dst)2431   void Stlxrh(const Register& rs, const Register& rt, const MemOperand& dst) {
2432     VIXL_ASSERT(allow_macro_instructions_);
2433     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2434     VIXL_ASSERT(!rs.Aliases(rt));
2435     SingleEmissionCheckScope guard(this);
2436     stlxrh(rs, rt, dst);
2437   }
Stnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)2438   void Stnp(const CPURegister& rt,
2439             const CPURegister& rt2,
2440             const MemOperand& dst) {
2441     VIXL_ASSERT(allow_macro_instructions_);
2442     SingleEmissionCheckScope guard(this);
2443     stnp(rt, rt2, dst);
2444   }
Stxp(const Register & rs,const Register & rt,const Register & rt2,const MemOperand & dst)2445   void Stxp(const Register& rs,
2446             const Register& rt,
2447             const Register& rt2,
2448             const MemOperand& dst) {
2449     VIXL_ASSERT(allow_macro_instructions_);
2450     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2451     VIXL_ASSERT(!rs.Aliases(rt));
2452     VIXL_ASSERT(!rs.Aliases(rt2));
2453     SingleEmissionCheckScope guard(this);
2454     stxp(rs, rt, rt2, dst);
2455   }
Stxr(const Register & rs,const Register & rt,const MemOperand & dst)2456   void Stxr(const Register& rs, const Register& rt, const MemOperand& dst) {
2457     VIXL_ASSERT(allow_macro_instructions_);
2458     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2459     VIXL_ASSERT(!rs.Aliases(rt));
2460     SingleEmissionCheckScope guard(this);
2461     stxr(rs, rt, dst);
2462   }
Stxrb(const Register & rs,const Register & rt,const MemOperand & dst)2463   void Stxrb(const Register& rs, const Register& rt, const MemOperand& dst) {
2464     VIXL_ASSERT(allow_macro_instructions_);
2465     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2466     VIXL_ASSERT(!rs.Aliases(rt));
2467     SingleEmissionCheckScope guard(this);
2468     stxrb(rs, rt, dst);
2469   }
Stxrh(const Register & rs,const Register & rt,const MemOperand & dst)2470   void Stxrh(const Register& rs, const Register& rt, const MemOperand& dst) {
2471     VIXL_ASSERT(allow_macro_instructions_);
2472     VIXL_ASSERT(!rs.Aliases(dst.GetBaseRegister()));
2473     VIXL_ASSERT(!rs.Aliases(rt));
2474     SingleEmissionCheckScope guard(this);
2475     stxrh(rs, rt, dst);
2476   }
Svc(int code)2477   void Svc(int code) {
2478     VIXL_ASSERT(allow_macro_instructions_);
2479     SingleEmissionCheckScope guard(this);
2480     svc(code);
2481   }
Sxtb(const Register & rd,const Register & rn)2482   void Sxtb(const Register& rd, const Register& rn) {
2483     VIXL_ASSERT(allow_macro_instructions_);
2484     VIXL_ASSERT(!rd.IsZero());
2485     VIXL_ASSERT(!rn.IsZero());
2486     SingleEmissionCheckScope guard(this);
2487     sxtb(rd, rn);
2488   }
Sxth(const Register & rd,const Register & rn)2489   void Sxth(const Register& rd, const Register& rn) {
2490     VIXL_ASSERT(allow_macro_instructions_);
2491     VIXL_ASSERT(!rd.IsZero());
2492     VIXL_ASSERT(!rn.IsZero());
2493     SingleEmissionCheckScope guard(this);
2494     sxth(rd, rn);
2495   }
Sxtw(const Register & rd,const Register & rn)2496   void Sxtw(const Register& rd, const Register& rn) {
2497     VIXL_ASSERT(allow_macro_instructions_);
2498     VIXL_ASSERT(!rd.IsZero());
2499     VIXL_ASSERT(!rn.IsZero());
2500     SingleEmissionCheckScope guard(this);
2501     sxtw(rd, rn);
2502   }
Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vm)2503   void Tbl(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
2504     VIXL_ASSERT(allow_macro_instructions_);
2505     SingleEmissionCheckScope guard(this);
2506     tbl(vd, vn, vm);
2507   }
Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)2508   void Tbl(const VRegister& vd,
2509            const VRegister& vn,
2510            const VRegister& vn2,
2511            const VRegister& vm) {
2512     VIXL_ASSERT(allow_macro_instructions_);
2513     SingleEmissionCheckScope guard(this);
2514     tbl(vd, vn, vn2, vm);
2515   }
Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)2516   void Tbl(const VRegister& vd,
2517            const VRegister& vn,
2518            const VRegister& vn2,
2519            const VRegister& vn3,
2520            const VRegister& vm) {
2521     VIXL_ASSERT(allow_macro_instructions_);
2522     SingleEmissionCheckScope guard(this);
2523     tbl(vd, vn, vn2, vn3, vm);
2524   }
Tbl(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)2525   void Tbl(const VRegister& vd,
2526            const VRegister& vn,
2527            const VRegister& vn2,
2528            const VRegister& vn3,
2529            const VRegister& vn4,
2530            const VRegister& vm) {
2531     VIXL_ASSERT(allow_macro_instructions_);
2532     SingleEmissionCheckScope guard(this);
2533     tbl(vd, vn, vn2, vn3, vn4, vm);
2534   }
Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vm)2535   void Tbx(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
2536     VIXL_ASSERT(allow_macro_instructions_);
2537     SingleEmissionCheckScope guard(this);
2538     tbx(vd, vn, vm);
2539   }
Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vm)2540   void Tbx(const VRegister& vd,
2541            const VRegister& vn,
2542            const VRegister& vn2,
2543            const VRegister& vm) {
2544     VIXL_ASSERT(allow_macro_instructions_);
2545     SingleEmissionCheckScope guard(this);
2546     tbx(vd, vn, vn2, vm);
2547   }
Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vm)2548   void Tbx(const VRegister& vd,
2549            const VRegister& vn,
2550            const VRegister& vn2,
2551            const VRegister& vn3,
2552            const VRegister& vm) {
2553     VIXL_ASSERT(allow_macro_instructions_);
2554     SingleEmissionCheckScope guard(this);
2555     tbx(vd, vn, vn2, vn3, vm);
2556   }
Tbx(const VRegister & vd,const VRegister & vn,const VRegister & vn2,const VRegister & vn3,const VRegister & vn4,const VRegister & vm)2557   void Tbx(const VRegister& vd,
2558            const VRegister& vn,
2559            const VRegister& vn2,
2560            const VRegister& vn3,
2561            const VRegister& vn4,
2562            const VRegister& vm) {
2563     VIXL_ASSERT(allow_macro_instructions_);
2564     SingleEmissionCheckScope guard(this);
2565     tbx(vd, vn, vn2, vn3, vn4, vm);
2566   }
2567   void Tbnz(const Register& rt, unsigned bit_pos, Label* label);
2568   void Tbz(const Register& rt, unsigned bit_pos, Label* label);
Ubfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)2569   void Ubfiz(const Register& rd,
2570              const Register& rn,
2571              unsigned lsb,
2572              unsigned width) {
2573     VIXL_ASSERT(allow_macro_instructions_);
2574     VIXL_ASSERT(!rd.IsZero());
2575     VIXL_ASSERT(!rn.IsZero());
2576     SingleEmissionCheckScope guard(this);
2577     ubfiz(rd, rn, lsb, width);
2578   }
Ubfm(const Register & rd,const Register & rn,unsigned immr,unsigned imms)2579   void Ubfm(const Register& rd,
2580             const Register& rn,
2581             unsigned immr,
2582             unsigned imms) {
2583     VIXL_ASSERT(allow_macro_instructions_);
2584     VIXL_ASSERT(!rd.IsZero());
2585     VIXL_ASSERT(!rn.IsZero());
2586     SingleEmissionCheckScope guard(this);
2587     ubfm(rd, rn, immr, imms);
2588   }
Ubfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)2589   void Ubfx(const Register& rd,
2590             const Register& rn,
2591             unsigned lsb,
2592             unsigned width) {
2593     VIXL_ASSERT(allow_macro_instructions_);
2594     VIXL_ASSERT(!rd.IsZero());
2595     VIXL_ASSERT(!rn.IsZero());
2596     SingleEmissionCheckScope guard(this);
2597     ubfx(rd, rn, lsb, width);
2598   }
2599   void Ucvtf(const VRegister& vd, const Register& rn, int fbits = 0) {
2600     VIXL_ASSERT(allow_macro_instructions_);
2601     VIXL_ASSERT(!rn.IsZero());
2602     SingleEmissionCheckScope guard(this);
2603     ucvtf(vd, rn, fbits);
2604   }
Udiv(const Register & rd,const Register & rn,const Register & rm)2605   void Udiv(const Register& rd, const Register& rn, const Register& rm) {
2606     VIXL_ASSERT(allow_macro_instructions_);
2607     VIXL_ASSERT(!rd.IsZero());
2608     VIXL_ASSERT(!rn.IsZero());
2609     VIXL_ASSERT(!rm.IsZero());
2610     SingleEmissionCheckScope guard(this);
2611     udiv(rd, rn, rm);
2612   }
Umaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)2613   void Umaddl(const Register& rd,
2614               const Register& rn,
2615               const Register& rm,
2616               const Register& ra) {
2617     VIXL_ASSERT(allow_macro_instructions_);
2618     VIXL_ASSERT(!rd.IsZero());
2619     VIXL_ASSERT(!rn.IsZero());
2620     VIXL_ASSERT(!rm.IsZero());
2621     VIXL_ASSERT(!ra.IsZero());
2622     SingleEmissionCheckScope guard(this);
2623     umaddl(rd, rn, rm, ra);
2624   }
Umull(const Register & rd,const Register & rn,const Register & rm)2625   void Umull(const Register& rd, const Register& rn, const Register& rm) {
2626     VIXL_ASSERT(allow_macro_instructions_);
2627     VIXL_ASSERT(!rd.IsZero());
2628     VIXL_ASSERT(!rn.IsZero());
2629     VIXL_ASSERT(!rm.IsZero());
2630     SingleEmissionCheckScope guard(this);
2631     umull(rd, rn, rm);
2632   }
Umulh(const Register & xd,const Register & xn,const Register & xm)2633   void Umulh(const Register& xd, const Register& xn, const Register& xm) {
2634     VIXL_ASSERT(allow_macro_instructions_);
2635     VIXL_ASSERT(!xd.IsZero());
2636     VIXL_ASSERT(!xn.IsZero());
2637     VIXL_ASSERT(!xm.IsZero());
2638     SingleEmissionCheckScope guard(this);
2639     umulh(xd, xn, xm);
2640   }
Umsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)2641   void Umsubl(const Register& rd,
2642               const Register& rn,
2643               const Register& rm,
2644               const Register& ra) {
2645     VIXL_ASSERT(allow_macro_instructions_);
2646     VIXL_ASSERT(!rd.IsZero());
2647     VIXL_ASSERT(!rn.IsZero());
2648     VIXL_ASSERT(!rm.IsZero());
2649     VIXL_ASSERT(!ra.IsZero());
2650     SingleEmissionCheckScope guard(this);
2651     umsubl(rd, rn, rm, ra);
2652   }
Unreachable()2653   void Unreachable() {
2654     VIXL_ASSERT(allow_macro_instructions_);
2655     SingleEmissionCheckScope guard(this);
2656     if (generate_simulator_code_) {
2657       hlt(kUnreachableOpcode);
2658     } else {
2659       // Use the architecturally-defined UDF instruction to abort on hardware,
2660       // because using HLT and BRK tends to make the process difficult to debug.
2661       udf(kUnreachableOpcode);
2662     }
2663   }
Uxtb(const Register & rd,const Register & rn)2664   void Uxtb(const Register& rd, const Register& rn) {
2665     VIXL_ASSERT(allow_macro_instructions_);
2666     VIXL_ASSERT(!rd.IsZero());
2667     VIXL_ASSERT(!rn.IsZero());
2668     SingleEmissionCheckScope guard(this);
2669     uxtb(rd, rn);
2670   }
Uxth(const Register & rd,const Register & rn)2671   void Uxth(const Register& rd, const Register& rn) {
2672     VIXL_ASSERT(allow_macro_instructions_);
2673     VIXL_ASSERT(!rd.IsZero());
2674     VIXL_ASSERT(!rn.IsZero());
2675     SingleEmissionCheckScope guard(this);
2676     uxth(rd, rn);
2677   }
Uxtw(const Register & rd,const Register & rn)2678   void Uxtw(const Register& rd, const Register& rn) {
2679     VIXL_ASSERT(allow_macro_instructions_);
2680     VIXL_ASSERT(!rd.IsZero());
2681     VIXL_ASSERT(!rn.IsZero());
2682     SingleEmissionCheckScope guard(this);
2683     uxtw(rd, rn);
2684   }
2685 
2686 // NEON 3 vector register instructions.
2687 #define NEON_3VREG_MACRO_LIST(V) \
2688   V(add, Add)                    \
2689   V(addhn, Addhn)                \
2690   V(addhn2, Addhn2)              \
2691   V(addp, Addp)                  \
2692   V(and_, And)                   \
2693   V(bic, Bic)                    \
2694   V(bif, Bif)                    \
2695   V(bit, Bit)                    \
2696   V(bsl, Bsl)                    \
2697   V(cmeq, Cmeq)                  \
2698   V(cmge, Cmge)                  \
2699   V(cmgt, Cmgt)                  \
2700   V(cmhi, Cmhi)                  \
2701   V(cmhs, Cmhs)                  \
2702   V(cmtst, Cmtst)                \
2703   V(eor, Eor)                    \
2704   V(fabd, Fabd)                  \
2705   V(facge, Facge)                \
2706   V(facgt, Facgt)                \
2707   V(faddp, Faddp)                \
2708   V(fcmeq, Fcmeq)                \
2709   V(fcmge, Fcmge)                \
2710   V(fcmgt, Fcmgt)                \
2711   V(fmaxnmp, Fmaxnmp)            \
2712   V(fmaxp, Fmaxp)                \
2713   V(fminnmp, Fminnmp)            \
2714   V(fminp, Fminp)                \
2715   V(fmla, Fmla)                  \
2716   V(fmlal, Fmlal)                \
2717   V(fmlal2, Fmlal2)              \
2718   V(fmls, Fmls)                  \
2719   V(fmlsl, Fmlsl)                \
2720   V(fmlsl2, Fmlsl2)              \
2721   V(fmulx, Fmulx)                \
2722   V(frecps, Frecps)              \
2723   V(frsqrts, Frsqrts)            \
2724   V(mla, Mla)                    \
2725   V(mls, Mls)                    \
2726   V(mul, Mul)                    \
2727   V(orn, Orn)                    \
2728   V(orr, Orr)                    \
2729   V(pmul, Pmul)                  \
2730   V(pmull, Pmull)                \
2731   V(pmull2, Pmull2)              \
2732   V(raddhn, Raddhn)              \
2733   V(raddhn2, Raddhn2)            \
2734   V(rsubhn, Rsubhn)              \
2735   V(rsubhn2, Rsubhn2)            \
2736   V(saba, Saba)                  \
2737   V(sabal, Sabal)                \
2738   V(sabal2, Sabal2)              \
2739   V(sabd, Sabd)                  \
2740   V(sabdl, Sabdl)                \
2741   V(sabdl2, Sabdl2)              \
2742   V(saddl, Saddl)                \
2743   V(saddl2, Saddl2)              \
2744   V(saddw, Saddw)                \
2745   V(saddw2, Saddw2)              \
2746   V(shadd, Shadd)                \
2747   V(shsub, Shsub)                \
2748   V(smax, Smax)                  \
2749   V(smaxp, Smaxp)                \
2750   V(smin, Smin)                  \
2751   V(sminp, Sminp)                \
2752   V(smlal, Smlal)                \
2753   V(smlal2, Smlal2)              \
2754   V(smlsl, Smlsl)                \
2755   V(smlsl2, Smlsl2)              \
2756   V(smull, Smull)                \
2757   V(smull2, Smull2)              \
2758   V(sqadd, Sqadd)                \
2759   V(sqdmlal, Sqdmlal)            \
2760   V(sqdmlal2, Sqdmlal2)          \
2761   V(sqdmlsl, Sqdmlsl)            \
2762   V(sqdmlsl2, Sqdmlsl2)          \
2763   V(sqdmulh, Sqdmulh)            \
2764   V(sqdmull, Sqdmull)            \
2765   V(sqdmull2, Sqdmull2)          \
2766   V(sqrdmulh, Sqrdmulh)          \
2767   V(sdot, Sdot)                  \
2768   V(sqrdmlah, Sqrdmlah)          \
2769   V(udot, Udot)                  \
2770   V(sqrdmlsh, Sqrdmlsh)          \
2771   V(sqrshl, Sqrshl)              \
2772   V(sqshl, Sqshl)                \
2773   V(sqsub, Sqsub)                \
2774   V(srhadd, Srhadd)              \
2775   V(srshl, Srshl)                \
2776   V(sshl, Sshl)                  \
2777   V(ssubl, Ssubl)                \
2778   V(ssubl2, Ssubl2)              \
2779   V(ssubw, Ssubw)                \
2780   V(ssubw2, Ssubw2)              \
2781   V(sub, Sub)                    \
2782   V(subhn, Subhn)                \
2783   V(subhn2, Subhn2)              \
2784   V(trn1, Trn1)                  \
2785   V(trn2, Trn2)                  \
2786   V(uaba, Uaba)                  \
2787   V(uabal, Uabal)                \
2788   V(uabal2, Uabal2)              \
2789   V(uabd, Uabd)                  \
2790   V(uabdl, Uabdl)                \
2791   V(uabdl2, Uabdl2)              \
2792   V(uaddl, Uaddl)                \
2793   V(uaddl2, Uaddl2)              \
2794   V(uaddw, Uaddw)                \
2795   V(uaddw2, Uaddw2)              \
2796   V(uhadd, Uhadd)                \
2797   V(uhsub, Uhsub)                \
2798   V(umax, Umax)                  \
2799   V(umaxp, Umaxp)                \
2800   V(umin, Umin)                  \
2801   V(uminp, Uminp)                \
2802   V(umlal, Umlal)                \
2803   V(umlal2, Umlal2)              \
2804   V(umlsl, Umlsl)                \
2805   V(umlsl2, Umlsl2)              \
2806   V(umull, Umull)                \
2807   V(umull2, Umull2)              \
2808   V(uqadd, Uqadd)                \
2809   V(uqrshl, Uqrshl)              \
2810   V(uqshl, Uqshl)                \
2811   V(uqsub, Uqsub)                \
2812   V(urhadd, Urhadd)              \
2813   V(urshl, Urshl)                \
2814   V(ushl, Ushl)                  \
2815   V(usubl, Usubl)                \
2816   V(usubl2, Usubl2)              \
2817   V(usubw, Usubw)                \
2818   V(usubw2, Usubw2)              \
2819   V(uzp1, Uzp1)                  \
2820   V(uzp2, Uzp2)                  \
2821   V(zip1, Zip1)                  \
2822   V(zip2, Zip2)
2823 
2824 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)                                     \
2825   void MASM(const VRegister& vd, const VRegister& vn, const VRegister& vm) { \
2826     VIXL_ASSERT(allow_macro_instructions_);                                  \
2827     SingleEmissionCheckScope guard(this);                                    \
2828     ASM(vd, vn, vm);                                                         \
2829   }
2830   NEON_3VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
2831 #undef DEFINE_MACRO_ASM_FUNC
2832 
2833 // NEON 2 vector register instructions.
2834 #define NEON_2VREG_MACRO_LIST(V) \
2835   V(abs, Abs)                    \
2836   V(addp, Addp)                  \
2837   V(addv, Addv)                  \
2838   V(cls, Cls)                    \
2839   V(clz, Clz)                    \
2840   V(cnt, Cnt)                    \
2841   V(fabs, Fabs)                  \
2842   V(faddp, Faddp)                \
2843   V(fcvtas, Fcvtas)              \
2844   V(fcvtau, Fcvtau)              \
2845   V(fcvtms, Fcvtms)              \
2846   V(fcvtmu, Fcvtmu)              \
2847   V(fcvtns, Fcvtns)              \
2848   V(fcvtnu, Fcvtnu)              \
2849   V(fcvtps, Fcvtps)              \
2850   V(fcvtpu, Fcvtpu)              \
2851   V(fmaxnmp, Fmaxnmp)            \
2852   V(fmaxnmv, Fmaxnmv)            \
2853   V(fmaxp, Fmaxp)                \
2854   V(fmaxv, Fmaxv)                \
2855   V(fminnmp, Fminnmp)            \
2856   V(fminnmv, Fminnmv)            \
2857   V(fminp, Fminp)                \
2858   V(fminv, Fminv)                \
2859   V(fneg, Fneg)                  \
2860   V(frecpe, Frecpe)              \
2861   V(frecpx, Frecpx)              \
2862   V(frint32x, Frint32x)          \
2863   V(frint32z, Frint32z)          \
2864   V(frint64x, Frint64x)          \
2865   V(frint64z, Frint64z)          \
2866   V(frinta, Frinta)              \
2867   V(frinti, Frinti)              \
2868   V(frintm, Frintm)              \
2869   V(frintn, Frintn)              \
2870   V(frintp, Frintp)              \
2871   V(frintx, Frintx)              \
2872   V(frintz, Frintz)              \
2873   V(frsqrte, Frsqrte)            \
2874   V(fsqrt, Fsqrt)                \
2875   V(mov, Mov)                    \
2876   V(mvn, Mvn)                    \
2877   V(neg, Neg)                    \
2878   V(not_, Not)                   \
2879   V(rbit, Rbit)                  \
2880   V(rev16, Rev16)                \
2881   V(rev32, Rev32)                \
2882   V(rev64, Rev64)                \
2883   V(sadalp, Sadalp)              \
2884   V(saddlp, Saddlp)              \
2885   V(saddlv, Saddlv)              \
2886   V(smaxv, Smaxv)                \
2887   V(sminv, Sminv)                \
2888   V(sqabs, Sqabs)                \
2889   V(sqneg, Sqneg)                \
2890   V(sqxtn, Sqxtn)                \
2891   V(sqxtn2, Sqxtn2)              \
2892   V(sqxtun, Sqxtun)              \
2893   V(sqxtun2, Sqxtun2)            \
2894   V(suqadd, Suqadd)              \
2895   V(sxtl, Sxtl)                  \
2896   V(sxtl2, Sxtl2)                \
2897   V(uadalp, Uadalp)              \
2898   V(uaddlp, Uaddlp)              \
2899   V(uaddlv, Uaddlv)              \
2900   V(umaxv, Umaxv)                \
2901   V(uminv, Uminv)                \
2902   V(uqxtn, Uqxtn)                \
2903   V(uqxtn2, Uqxtn2)              \
2904   V(urecpe, Urecpe)              \
2905   V(ursqrte, Ursqrte)            \
2906   V(usqadd, Usqadd)              \
2907   V(uxtl, Uxtl)                  \
2908   V(uxtl2, Uxtl2)                \
2909   V(xtn, Xtn)                    \
2910   V(xtn2, Xtn2)
2911 
2912 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)                \
2913   void MASM(const VRegister& vd, const VRegister& vn) { \
2914     VIXL_ASSERT(allow_macro_instructions_);             \
2915     SingleEmissionCheckScope guard(this);               \
2916     ASM(vd, vn);                                        \
2917   }
NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)2918   NEON_2VREG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
2919 #undef DEFINE_MACRO_ASM_FUNC
2920 
2921 // NEON 2 vector register with immediate instructions.
2922 #define NEON_2VREG_FPIMM_MACRO_LIST(V) \
2923   V(fcmeq, Fcmeq)                      \
2924   V(fcmge, Fcmge)                      \
2925   V(fcmgt, Fcmgt)                      \
2926   V(fcmle, Fcmle)                      \
2927   V(fcmlt, Fcmlt)
2928 
2929 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)                            \
2930   void MASM(const VRegister& vd, const VRegister& vn, double imm) { \
2931     VIXL_ASSERT(allow_macro_instructions_);                         \
2932     SingleEmissionCheckScope guard(this);                           \
2933     ASM(vd, vn, imm);                                               \
2934   }
2935   NEON_2VREG_FPIMM_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
2936 #undef DEFINE_MACRO_ASM_FUNC
2937 
2938 // NEON by element instructions.
2939 #define NEON_BYELEMENT_MACRO_LIST(V) \
2940   V(fmul, Fmul)                      \
2941   V(fmla, Fmla)                      \
2942   V(fmlal, Fmlal)                    \
2943   V(fmlal2, Fmlal2)                  \
2944   V(fmls, Fmls)                      \
2945   V(fmlsl, Fmlsl)                    \
2946   V(fmlsl2, Fmlsl2)                  \
2947   V(fmulx, Fmulx)                    \
2948   V(mul, Mul)                        \
2949   V(mla, Mla)                        \
2950   V(mls, Mls)                        \
2951   V(sqdmulh, Sqdmulh)                \
2952   V(sqrdmulh, Sqrdmulh)              \
2953   V(sdot, Sdot)                      \
2954   V(sqrdmlah, Sqrdmlah)              \
2955   V(udot, Udot)                      \
2956   V(sqrdmlsh, Sqrdmlsh)              \
2957   V(sqdmull, Sqdmull)                \
2958   V(sqdmull2, Sqdmull2)              \
2959   V(sqdmlal, Sqdmlal)                \
2960   V(sqdmlal2, Sqdmlal2)              \
2961   V(sqdmlsl, Sqdmlsl)                \
2962   V(sqdmlsl2, Sqdmlsl2)              \
2963   V(smull, Smull)                    \
2964   V(smull2, Smull2)                  \
2965   V(smlal, Smlal)                    \
2966   V(smlal2, Smlal2)                  \
2967   V(smlsl, Smlsl)                    \
2968   V(smlsl2, Smlsl2)                  \
2969   V(umull, Umull)                    \
2970   V(umull2, Umull2)                  \
2971   V(umlal, Umlal)                    \
2972   V(umlal2, Umlal2)                  \
2973   V(umlsl, Umlsl)                    \
2974   V(umlsl2, Umlsl2)
2975 
2976 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)    \
2977   void MASM(const VRegister& vd,            \
2978             const VRegister& vn,            \
2979             const VRegister& vm,            \
2980             int vm_index) {                 \
2981     VIXL_ASSERT(allow_macro_instructions_); \
2982     SingleEmissionCheckScope guard(this);   \
2983     ASM(vd, vn, vm, vm_index);              \
2984   }
2985   NEON_BYELEMENT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
2986 #undef DEFINE_MACRO_ASM_FUNC
2987 
2988 #define NEON_2VREG_SHIFT_MACRO_LIST(V) \
2989   V(rshrn, Rshrn)                      \
2990   V(rshrn2, Rshrn2)                    \
2991   V(shl, Shl)                          \
2992   V(shll, Shll)                        \
2993   V(shll2, Shll2)                      \
2994   V(shrn, Shrn)                        \
2995   V(shrn2, Shrn2)                      \
2996   V(sli, Sli)                          \
2997   V(sqrshrn, Sqrshrn)                  \
2998   V(sqrshrn2, Sqrshrn2)                \
2999   V(sqrshrun, Sqrshrun)                \
3000   V(sqrshrun2, Sqrshrun2)              \
3001   V(sqshl, Sqshl)                      \
3002   V(sqshlu, Sqshlu)                    \
3003   V(sqshrn, Sqshrn)                    \
3004   V(sqshrn2, Sqshrn2)                  \
3005   V(sqshrun, Sqshrun)                  \
3006   V(sqshrun2, Sqshrun2)                \
3007   V(sri, Sri)                          \
3008   V(srshr, Srshr)                      \
3009   V(srsra, Srsra)                      \
3010   V(sshr, Sshr)                        \
3011   V(ssra, Ssra)                        \
3012   V(uqrshrn, Uqrshrn)                  \
3013   V(uqrshrn2, Uqrshrn2)                \
3014   V(uqshl, Uqshl)                      \
3015   V(uqshrn, Uqshrn)                    \
3016   V(uqshrn2, Uqshrn2)                  \
3017   V(urshr, Urshr)                      \
3018   V(ursra, Ursra)                      \
3019   V(ushr, Ushr)                        \
3020   V(usra, Usra)
3021 
3022 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)                           \
3023   void MASM(const VRegister& vd, const VRegister& vn, int shift) { \
3024     VIXL_ASSERT(allow_macro_instructions_);                        \
3025     SingleEmissionCheckScope guard(this);                          \
3026     ASM(vd, vn, shift);                                            \
3027   }
3028   NEON_2VREG_SHIFT_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
3029 #undef DEFINE_MACRO_ASM_FUNC
3030 
3031 #define NEON_2VREG_SHIFT_LONG_MACRO_LIST(V) \
3032   V(shll, sshll, Sshll)                     \
3033   V(shll, ushll, Ushll)                     \
3034   V(shll2, sshll2, Sshll2)                  \
3035   V(shll2, ushll2, Ushll2)
3036 
3037 #define DEFINE_MACRO_ASM_FUNC(ASM1, ASM2, MASM)                    \
3038   void MASM(const VRegister& vd, const VRegister& vn, int shift) { \
3039     VIXL_ASSERT(allow_macro_instructions_);                        \
3040     SingleEmissionCheckScope guard(this);                          \
3041     if (vn.GetLaneSizeInBits() == static_cast<unsigned>(shift)) {  \
3042       ASM1(vd, vn, shift);                                         \
3043     } else {                                                       \
3044       ASM2(vd, vn, shift);                                         \
3045     }                                                              \
3046   }
3047   NEON_2VREG_SHIFT_LONG_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
3048 #undef DEFINE_MACRO_ASM_FUNC
3049 
3050 // SVE 3 vector register instructions.
3051 #define SVE_3VREG_COMMUTATIVE_MACRO_LIST(V) \
3052   V(add, Add)                               \
3053   V(and_, And)                              \
3054   V(bic, Bic)                               \
3055   V(eor, Eor)                               \
3056   V(mul, Mul)                               \
3057   V(orr, Orr)                               \
3058   V(sabd, Sabd)                             \
3059   V(smax, Smax)                             \
3060   V(smulh, Smulh)                           \
3061   V(smin, Smin)                             \
3062   V(uabd, Uabd)                             \
3063   V(umax, Umax)                             \
3064   V(umin, Umin)                             \
3065   V(umulh, Umulh)
3066 
3067 #define DEFINE_MACRO_ASM_FUNC(ASM, MASM)          \
3068   void MASM(const ZRegister& zd,                  \
3069             const PRegisterM& pg,                 \
3070             const ZRegister& zn,                  \
3071             const ZRegister& zm) {                \
3072     VIXL_ASSERT(allow_macro_instructions_);       \
3073     if (zd.Aliases(zn)) {                         \
3074       SingleEmissionCheckScope guard(this);       \
3075       ASM(zd, pg, zd, zm);                        \
3076     } else if (zd.Aliases(zm)) {                  \
3077       SingleEmissionCheckScope guard(this);       \
3078       ASM(zd, pg, zd, zn);                        \
3079     } else {                                      \
3080       MovprfxHelperScope guard(this, zd, pg, zn); \
3081       ASM(zd, pg, zd, zm);                        \
3082     }                                             \
3083   }
3084   SVE_3VREG_COMMUTATIVE_MACRO_LIST(DEFINE_MACRO_ASM_FUNC)
3085 #undef DEFINE_MACRO_ASM_FUNC
3086 
3087   void Bic(const VRegister& vd, const int imm8, const int left_shift = 0) {
3088     VIXL_ASSERT(allow_macro_instructions_);
3089     SingleEmissionCheckScope guard(this);
3090     bic(vd, imm8, left_shift);
3091   }
Cmeq(const VRegister & vd,const VRegister & vn,int imm)3092   void Cmeq(const VRegister& vd, const VRegister& vn, int imm) {
3093     VIXL_ASSERT(allow_macro_instructions_);
3094     SingleEmissionCheckScope guard(this);
3095     cmeq(vd, vn, imm);
3096   }
Cmge(const VRegister & vd,const VRegister & vn,int imm)3097   void Cmge(const VRegister& vd, const VRegister& vn, int imm) {
3098     VIXL_ASSERT(allow_macro_instructions_);
3099     SingleEmissionCheckScope guard(this);
3100     cmge(vd, vn, imm);
3101   }
Cmgt(const VRegister & vd,const VRegister & vn,int imm)3102   void Cmgt(const VRegister& vd, const VRegister& vn, int imm) {
3103     VIXL_ASSERT(allow_macro_instructions_);
3104     SingleEmissionCheckScope guard(this);
3105     cmgt(vd, vn, imm);
3106   }
Cmle(const VRegister & vd,const VRegister & vn,int imm)3107   void Cmle(const VRegister& vd, const VRegister& vn, int imm) {
3108     VIXL_ASSERT(allow_macro_instructions_);
3109     SingleEmissionCheckScope guard(this);
3110     cmle(vd, vn, imm);
3111   }
Cmlt(const VRegister & vd,const VRegister & vn,int imm)3112   void Cmlt(const VRegister& vd, const VRegister& vn, int imm) {
3113     VIXL_ASSERT(allow_macro_instructions_);
3114     SingleEmissionCheckScope guard(this);
3115     cmlt(vd, vn, imm);
3116   }
Dup(const VRegister & vd,const VRegister & vn,int index)3117   void Dup(const VRegister& vd, const VRegister& vn, int index) {
3118     VIXL_ASSERT(allow_macro_instructions_);
3119     SingleEmissionCheckScope guard(this);
3120     dup(vd, vn, index);
3121   }
Dup(const VRegister & vd,const Register & rn)3122   void Dup(const VRegister& vd, const Register& rn) {
3123     VIXL_ASSERT(allow_macro_instructions_);
3124     SingleEmissionCheckScope guard(this);
3125     dup(vd, rn);
3126   }
Ext(const VRegister & vd,const VRegister & vn,const VRegister & vm,int index)3127   void Ext(const VRegister& vd,
3128            const VRegister& vn,
3129            const VRegister& vm,
3130            int index) {
3131     VIXL_ASSERT(allow_macro_instructions_);
3132     SingleEmissionCheckScope guard(this);
3133     ext(vd, vn, vm, index);
3134   }
Fcadd(const VRegister & vd,const VRegister & vn,const VRegister & vm,int rot)3135   void Fcadd(const VRegister& vd,
3136              const VRegister& vn,
3137              const VRegister& vm,
3138              int rot) {
3139     VIXL_ASSERT(allow_macro_instructions_);
3140     SingleEmissionCheckScope guard(this);
3141     fcadd(vd, vn, vm, rot);
3142   }
Fcmla(const VRegister & vd,const VRegister & vn,const VRegister & vm,int vm_index,int rot)3143   void Fcmla(const VRegister& vd,
3144              const VRegister& vn,
3145              const VRegister& vm,
3146              int vm_index,
3147              int rot) {
3148     VIXL_ASSERT(allow_macro_instructions_);
3149     SingleEmissionCheckScope guard(this);
3150     fcmla(vd, vn, vm, vm_index, rot);
3151   }
Fcmla(const VRegister & vd,const VRegister & vn,const VRegister & vm,int rot)3152   void Fcmla(const VRegister& vd,
3153              const VRegister& vn,
3154              const VRegister& vm,
3155              int rot) {
3156     VIXL_ASSERT(allow_macro_instructions_);
3157     SingleEmissionCheckScope guard(this);
3158     fcmla(vd, vn, vm, rot);
3159   }
Ins(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)3160   void Ins(const VRegister& vd,
3161            int vd_index,
3162            const VRegister& vn,
3163            int vn_index) {
3164     VIXL_ASSERT(allow_macro_instructions_);
3165     SingleEmissionCheckScope guard(this);
3166     ins(vd, vd_index, vn, vn_index);
3167   }
Ins(const VRegister & vd,int vd_index,const Register & rn)3168   void Ins(const VRegister& vd, int vd_index, const Register& rn) {
3169     VIXL_ASSERT(allow_macro_instructions_);
3170     SingleEmissionCheckScope guard(this);
3171     ins(vd, vd_index, rn);
3172   }
Ld1(const VRegister & vt,const MemOperand & src)3173   void Ld1(const VRegister& vt, const MemOperand& src) {
3174     VIXL_ASSERT(allow_macro_instructions_);
3175     SingleEmissionCheckScope guard(this);
3176     ld1(vt, src);
3177   }
Ld1(const VRegister & vt,const VRegister & vt2,const MemOperand & src)3178   void Ld1(const VRegister& vt, const VRegister& vt2, const MemOperand& src) {
3179     VIXL_ASSERT(allow_macro_instructions_);
3180     SingleEmissionCheckScope guard(this);
3181     ld1(vt, vt2, src);
3182   }
Ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)3183   void Ld1(const VRegister& vt,
3184            const VRegister& vt2,
3185            const VRegister& vt3,
3186            const MemOperand& src) {
3187     VIXL_ASSERT(allow_macro_instructions_);
3188     SingleEmissionCheckScope guard(this);
3189     ld1(vt, vt2, vt3, src);
3190   }
Ld1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)3191   void Ld1(const VRegister& vt,
3192            const VRegister& vt2,
3193            const VRegister& vt3,
3194            const VRegister& vt4,
3195            const MemOperand& src) {
3196     VIXL_ASSERT(allow_macro_instructions_);
3197     SingleEmissionCheckScope guard(this);
3198     ld1(vt, vt2, vt3, vt4, src);
3199   }
Ld1(const VRegister & vt,int lane,const MemOperand & src)3200   void Ld1(const VRegister& vt, int lane, const MemOperand& src) {
3201     VIXL_ASSERT(allow_macro_instructions_);
3202     SingleEmissionCheckScope guard(this);
3203     ld1(vt, lane, src);
3204   }
Ld1r(const VRegister & vt,const MemOperand & src)3205   void Ld1r(const VRegister& vt, const MemOperand& src) {
3206     VIXL_ASSERT(allow_macro_instructions_);
3207     SingleEmissionCheckScope guard(this);
3208     ld1r(vt, src);
3209   }
Ld2(const VRegister & vt,const VRegister & vt2,const MemOperand & src)3210   void Ld2(const VRegister& vt, const VRegister& vt2, const MemOperand& src) {
3211     VIXL_ASSERT(allow_macro_instructions_);
3212     SingleEmissionCheckScope guard(this);
3213     ld2(vt, vt2, src);
3214   }
Ld2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & src)3215   void Ld2(const VRegister& vt,
3216            const VRegister& vt2,
3217            int lane,
3218            const MemOperand& src) {
3219     VIXL_ASSERT(allow_macro_instructions_);
3220     SingleEmissionCheckScope guard(this);
3221     ld2(vt, vt2, lane, src);
3222   }
Ld2r(const VRegister & vt,const VRegister & vt2,const MemOperand & src)3223   void Ld2r(const VRegister& vt, const VRegister& vt2, const MemOperand& src) {
3224     VIXL_ASSERT(allow_macro_instructions_);
3225     SingleEmissionCheckScope guard(this);
3226     ld2r(vt, vt2, src);
3227   }
Ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)3228   void Ld3(const VRegister& vt,
3229            const VRegister& vt2,
3230            const VRegister& vt3,
3231            const MemOperand& src) {
3232     VIXL_ASSERT(allow_macro_instructions_);
3233     SingleEmissionCheckScope guard(this);
3234     ld3(vt, vt2, vt3, src);
3235   }
Ld3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & src)3236   void Ld3(const VRegister& vt,
3237            const VRegister& vt2,
3238            const VRegister& vt3,
3239            int lane,
3240            const MemOperand& src) {
3241     VIXL_ASSERT(allow_macro_instructions_);
3242     SingleEmissionCheckScope guard(this);
3243     ld3(vt, vt2, vt3, lane, src);
3244   }
Ld3r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & src)3245   void Ld3r(const VRegister& vt,
3246             const VRegister& vt2,
3247             const VRegister& vt3,
3248             const MemOperand& src) {
3249     VIXL_ASSERT(allow_macro_instructions_);
3250     SingleEmissionCheckScope guard(this);
3251     ld3r(vt, vt2, vt3, src);
3252   }
Ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)3253   void Ld4(const VRegister& vt,
3254            const VRegister& vt2,
3255            const VRegister& vt3,
3256            const VRegister& vt4,
3257            const MemOperand& src) {
3258     VIXL_ASSERT(allow_macro_instructions_);
3259     SingleEmissionCheckScope guard(this);
3260     ld4(vt, vt2, vt3, vt4, src);
3261   }
Ld4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & src)3262   void Ld4(const VRegister& vt,
3263            const VRegister& vt2,
3264            const VRegister& vt3,
3265            const VRegister& vt4,
3266            int lane,
3267            const MemOperand& src) {
3268     VIXL_ASSERT(allow_macro_instructions_);
3269     SingleEmissionCheckScope guard(this);
3270     ld4(vt, vt2, vt3, vt4, lane, src);
3271   }
Ld4r(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & src)3272   void Ld4r(const VRegister& vt,
3273             const VRegister& vt2,
3274             const VRegister& vt3,
3275             const VRegister& vt4,
3276             const MemOperand& src) {
3277     VIXL_ASSERT(allow_macro_instructions_);
3278     SingleEmissionCheckScope guard(this);
3279     ld4r(vt, vt2, vt3, vt4, src);
3280   }
Mov(const VRegister & vd,int vd_index,const VRegister & vn,int vn_index)3281   void Mov(const VRegister& vd,
3282            int vd_index,
3283            const VRegister& vn,
3284            int vn_index) {
3285     VIXL_ASSERT(allow_macro_instructions_);
3286     SingleEmissionCheckScope guard(this);
3287     mov(vd, vd_index, vn, vn_index);
3288   }
Mov(const VRegister & vd,const VRegister & vn,int index)3289   void Mov(const VRegister& vd, const VRegister& vn, int index) {
3290     VIXL_ASSERT(allow_macro_instructions_);
3291     SingleEmissionCheckScope guard(this);
3292     mov(vd, vn, index);
3293   }
Mov(const VRegister & vd,int vd_index,const Register & rn)3294   void Mov(const VRegister& vd, int vd_index, const Register& rn) {
3295     VIXL_ASSERT(allow_macro_instructions_);
3296     SingleEmissionCheckScope guard(this);
3297     mov(vd, vd_index, rn);
3298   }
Mov(const Register & rd,const VRegister & vn,int vn_index)3299   void Mov(const Register& rd, const VRegister& vn, int vn_index) {
3300     VIXL_ASSERT(allow_macro_instructions_);
3301     SingleEmissionCheckScope guard(this);
3302     mov(rd, vn, vn_index);
3303   }
3304   void Movi(const VRegister& vd,
3305             uint64_t imm,
3306             Shift shift = LSL,
3307             int shift_amount = 0);
3308   void Movi(const VRegister& vd, uint64_t hi, uint64_t lo);
3309   void Mvni(const VRegister& vd,
3310             const int imm8,
3311             Shift shift = LSL,
3312             const int shift_amount = 0) {
3313     VIXL_ASSERT(allow_macro_instructions_);
3314     SingleEmissionCheckScope guard(this);
3315     mvni(vd, imm8, shift, shift_amount);
3316   }
3317   void Orr(const VRegister& vd, const int imm8, const int left_shift = 0) {
3318     VIXL_ASSERT(allow_macro_instructions_);
3319     SingleEmissionCheckScope guard(this);
3320     orr(vd, imm8, left_shift);
3321   }
3322   void Scvtf(const VRegister& vd, const VRegister& vn, int fbits = 0) {
3323     VIXL_ASSERT(allow_macro_instructions_);
3324     SingleEmissionCheckScope guard(this);
3325     scvtf(vd, vn, fbits);
3326   }
3327   void Ucvtf(const VRegister& vd, const VRegister& vn, int fbits = 0) {
3328     VIXL_ASSERT(allow_macro_instructions_);
3329     SingleEmissionCheckScope guard(this);
3330     ucvtf(vd, vn, fbits);
3331   }
3332   void Fcvtzs(const VRegister& vd, const VRegister& vn, int fbits = 0) {
3333     VIXL_ASSERT(allow_macro_instructions_);
3334     SingleEmissionCheckScope guard(this);
3335     fcvtzs(vd, vn, fbits);
3336   }
3337   void Fcvtzu(const VRegister& vd, const VRegister& vn, int fbits = 0) {
3338     VIXL_ASSERT(allow_macro_instructions_);
3339     SingleEmissionCheckScope guard(this);
3340     fcvtzu(vd, vn, fbits);
3341   }
St1(const VRegister & vt,const MemOperand & dst)3342   void St1(const VRegister& vt, const MemOperand& dst) {
3343     VIXL_ASSERT(allow_macro_instructions_);
3344     SingleEmissionCheckScope guard(this);
3345     st1(vt, dst);
3346   }
St1(const VRegister & vt,const VRegister & vt2,const MemOperand & dst)3347   void St1(const VRegister& vt, const VRegister& vt2, const MemOperand& dst) {
3348     VIXL_ASSERT(allow_macro_instructions_);
3349     SingleEmissionCheckScope guard(this);
3350     st1(vt, vt2, dst);
3351   }
St1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & dst)3352   void St1(const VRegister& vt,
3353            const VRegister& vt2,
3354            const VRegister& vt3,
3355            const MemOperand& dst) {
3356     VIXL_ASSERT(allow_macro_instructions_);
3357     SingleEmissionCheckScope guard(this);
3358     st1(vt, vt2, vt3, dst);
3359   }
St1(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & dst)3360   void St1(const VRegister& vt,
3361            const VRegister& vt2,
3362            const VRegister& vt3,
3363            const VRegister& vt4,
3364            const MemOperand& dst) {
3365     VIXL_ASSERT(allow_macro_instructions_);
3366     SingleEmissionCheckScope guard(this);
3367     st1(vt, vt2, vt3, vt4, dst);
3368   }
St1(const VRegister & vt,int lane,const MemOperand & dst)3369   void St1(const VRegister& vt, int lane, const MemOperand& dst) {
3370     VIXL_ASSERT(allow_macro_instructions_);
3371     SingleEmissionCheckScope guard(this);
3372     st1(vt, lane, dst);
3373   }
St2(const VRegister & vt,const VRegister & vt2,const MemOperand & dst)3374   void St2(const VRegister& vt, const VRegister& vt2, const MemOperand& dst) {
3375     VIXL_ASSERT(allow_macro_instructions_);
3376     SingleEmissionCheckScope guard(this);
3377     st2(vt, vt2, dst);
3378   }
St3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const MemOperand & dst)3379   void St3(const VRegister& vt,
3380            const VRegister& vt2,
3381            const VRegister& vt3,
3382            const MemOperand& dst) {
3383     VIXL_ASSERT(allow_macro_instructions_);
3384     SingleEmissionCheckScope guard(this);
3385     st3(vt, vt2, vt3, dst);
3386   }
St4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,const MemOperand & dst)3387   void St4(const VRegister& vt,
3388            const VRegister& vt2,
3389            const VRegister& vt3,
3390            const VRegister& vt4,
3391            const MemOperand& dst) {
3392     VIXL_ASSERT(allow_macro_instructions_);
3393     SingleEmissionCheckScope guard(this);
3394     st4(vt, vt2, vt3, vt4, dst);
3395   }
St2(const VRegister & vt,const VRegister & vt2,int lane,const MemOperand & dst)3396   void St2(const VRegister& vt,
3397            const VRegister& vt2,
3398            int lane,
3399            const MemOperand& dst) {
3400     VIXL_ASSERT(allow_macro_instructions_);
3401     SingleEmissionCheckScope guard(this);
3402     st2(vt, vt2, lane, dst);
3403   }
St3(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,int lane,const MemOperand & dst)3404   void St3(const VRegister& vt,
3405            const VRegister& vt2,
3406            const VRegister& vt3,
3407            int lane,
3408            const MemOperand& dst) {
3409     VIXL_ASSERT(allow_macro_instructions_);
3410     SingleEmissionCheckScope guard(this);
3411     st3(vt, vt2, vt3, lane, dst);
3412   }
St4(const VRegister & vt,const VRegister & vt2,const VRegister & vt3,const VRegister & vt4,int lane,const MemOperand & dst)3413   void St4(const VRegister& vt,
3414            const VRegister& vt2,
3415            const VRegister& vt3,
3416            const VRegister& vt4,
3417            int lane,
3418            const MemOperand& dst) {
3419     VIXL_ASSERT(allow_macro_instructions_);
3420     SingleEmissionCheckScope guard(this);
3421     st4(vt, vt2, vt3, vt4, lane, dst);
3422   }
Smov(const Register & rd,const VRegister & vn,int vn_index)3423   void Smov(const Register& rd, const VRegister& vn, int vn_index) {
3424     VIXL_ASSERT(allow_macro_instructions_);
3425     SingleEmissionCheckScope guard(this);
3426     smov(rd, vn, vn_index);
3427   }
Umov(const Register & rd,const VRegister & vn,int vn_index)3428   void Umov(const Register& rd, const VRegister& vn, int vn_index) {
3429     VIXL_ASSERT(allow_macro_instructions_);
3430     SingleEmissionCheckScope guard(this);
3431     umov(rd, vn, vn_index);
3432   }
Crc32b(const Register & rd,const Register & rn,const Register & rm)3433   void Crc32b(const Register& rd, const Register& rn, const Register& rm) {
3434     VIXL_ASSERT(allow_macro_instructions_);
3435     SingleEmissionCheckScope guard(this);
3436     crc32b(rd, rn, rm);
3437   }
Crc32h(const Register & rd,const Register & rn,const Register & rm)3438   void Crc32h(const Register& rd, const Register& rn, const Register& rm) {
3439     VIXL_ASSERT(allow_macro_instructions_);
3440     SingleEmissionCheckScope guard(this);
3441     crc32h(rd, rn, rm);
3442   }
Crc32w(const Register & rd,const Register & rn,const Register & rm)3443   void Crc32w(const Register& rd, const Register& rn, const Register& rm) {
3444     VIXL_ASSERT(allow_macro_instructions_);
3445     SingleEmissionCheckScope guard(this);
3446     crc32w(rd, rn, rm);
3447   }
Crc32x(const Register & rd,const Register & rn,const Register & rm)3448   void Crc32x(const Register& rd, const Register& rn, const Register& rm) {
3449     VIXL_ASSERT(allow_macro_instructions_);
3450     SingleEmissionCheckScope guard(this);
3451     crc32x(rd, rn, rm);
3452   }
Crc32cb(const Register & rd,const Register & rn,const Register & rm)3453   void Crc32cb(const Register& rd, const Register& rn, const Register& rm) {
3454     VIXL_ASSERT(allow_macro_instructions_);
3455     SingleEmissionCheckScope guard(this);
3456     crc32cb(rd, rn, rm);
3457   }
Crc32ch(const Register & rd,const Register & rn,const Register & rm)3458   void Crc32ch(const Register& rd, const Register& rn, const Register& rm) {
3459     VIXL_ASSERT(allow_macro_instructions_);
3460     SingleEmissionCheckScope guard(this);
3461     crc32ch(rd, rn, rm);
3462   }
Crc32cw(const Register & rd,const Register & rn,const Register & rm)3463   void Crc32cw(const Register& rd, const Register& rn, const Register& rm) {
3464     VIXL_ASSERT(allow_macro_instructions_);
3465     SingleEmissionCheckScope guard(this);
3466     crc32cw(rd, rn, rm);
3467   }
Crc32cx(const Register & rd,const Register & rn,const Register & rm)3468   void Crc32cx(const Register& rd, const Register& rn, const Register& rm) {
3469     VIXL_ASSERT(allow_macro_instructions_);
3470     SingleEmissionCheckScope guard(this);
3471     crc32cx(rd, rn, rm);
3472   }
3473 
3474   // Scalable Vector Extensions.
Abs(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3475   void Abs(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
3476     VIXL_ASSERT(allow_macro_instructions_);
3477     SingleEmissionCheckScope guard(this);
3478     abs(zd, pg, zn);
3479   }
Add(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)3480   void Add(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
3481     VIXL_ASSERT(allow_macro_instructions_);
3482     SingleEmissionCheckScope guard(this);
3483     add(zd, zn, zm);
3484   }
Add(const ZRegister & zd,const ZRegister & zn,IntegerOperand imm)3485   void Add(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm) {
3486     VIXL_ASSERT(allow_macro_instructions_);
3487     AddSubHelper(kAddImmediate, zd, zn, imm);
3488   }
3489   void Addpl(const Register& xd, const Register& xn, int64_t multiplier);
3490   void Addvl(const Register& xd, const Register& xn, int64_t multiplier);
3491   // Note that unlike the core ISA, SVE's `adr` is not PC-relative.
Adr(const ZRegister & zd,const SVEMemOperand & addr)3492   void Adr(const ZRegister& zd, const SVEMemOperand& addr) {
3493     VIXL_ASSERT(allow_macro_instructions_);
3494     SingleEmissionCheckScope guard(this);
3495     adr(zd, addr);
3496   }
And(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3497   void And(const PRegisterWithLaneSize& pd,
3498            const PRegisterZ& pg,
3499            const PRegisterWithLaneSize& pn,
3500            const PRegisterWithLaneSize& pm) {
3501     VIXL_ASSERT(allow_macro_instructions_);
3502     SingleEmissionCheckScope guard(this);
3503     and_(pd, pg, pn, pm);
3504   }
And(const ZRegister & zd,const ZRegister & zn,uint64_t imm)3505   void And(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
3506     VIXL_ASSERT(allow_macro_instructions_);
3507     SingleEmissionCheckScope guard(this);
3508     if (IsImmLogical(imm, zd.GetLaneSizeInBits())) {
3509       and_(zd, zn, imm);
3510     } else {
3511       // TODO: Synthesise the immediate once 'Mov' is implemented.
3512       VIXL_UNIMPLEMENTED();
3513     }
3514   }
And(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)3515   void And(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
3516     VIXL_ASSERT(allow_macro_instructions_);
3517     VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
3518     SingleEmissionCheckScope guard(this);
3519     and_(zd.VnD(), zn.VnD(), zm.VnD());
3520   }
Ands(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3521   void Ands(const PRegisterWithLaneSize& pd,
3522             const PRegisterZ& pg,
3523             const PRegisterWithLaneSize& pn,
3524             const PRegisterWithLaneSize& pm) {
3525     VIXL_ASSERT(allow_macro_instructions_);
3526     SingleEmissionCheckScope guard(this);
3527     ands(pd, pg, pn, pm);
3528   }
Andv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)3529   void Andv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
3530     VIXL_ASSERT(allow_macro_instructions_);
3531     SingleEmissionCheckScope guard(this);
3532     andv(vd, pg, zn);
3533   }
Asr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)3534   void Asr(const ZRegister& zd,
3535            const PRegisterM& pg,
3536            const ZRegister& zn,
3537            int shift) {
3538     VIXL_ASSERT(allow_macro_instructions_);
3539     MovprfxHelperScope guard(this, zd, pg, zn);
3540     asr(zd, pg, zd, shift);
3541   }
3542   void Asr(const ZRegister& zd,
3543            const PRegisterM& pg,
3544            const ZRegister& zn,
3545            const ZRegister& zm);
Asr(const ZRegister & zd,const ZRegister & zn,int shift)3546   void Asr(const ZRegister& zd, const ZRegister& zn, int shift) {
3547     VIXL_ASSERT(allow_macro_instructions_);
3548     SingleEmissionCheckScope guard(this);
3549     asr(zd, zn, shift);
3550   }
Asr(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)3551   void Asr(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
3552     VIXL_ASSERT(allow_macro_instructions_);
3553     SingleEmissionCheckScope guard(this);
3554     asr(zd, zn, zm);
3555   }
Asrd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)3556   void Asrd(const ZRegister& zd,
3557             const PRegisterM& pg,
3558             const ZRegister& zn,
3559             int shift) {
3560     VIXL_ASSERT(allow_macro_instructions_);
3561     MovprfxHelperScope guard(this, zd, pg, zn);
3562     asrd(zd, pg, zd, shift);
3563   }
Bic(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3564   void Bic(const PRegisterWithLaneSize& pd,
3565            const PRegisterZ& pg,
3566            const PRegisterWithLaneSize& pn,
3567            const PRegisterWithLaneSize& pm) {
3568     VIXL_ASSERT(allow_macro_instructions_);
3569     SingleEmissionCheckScope guard(this);
3570     bic(pd, pg, pn, pm);
3571   }
Bic(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)3572   void Bic(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
3573     VIXL_ASSERT(allow_macro_instructions_);
3574     VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
3575     SingleEmissionCheckScope guard(this);
3576     bic(zd.VnD(), zn.VnD(), zm.VnD());
3577   }
Bic(const ZRegister & zd,const ZRegister & zn,uint64_t imm)3578   void Bic(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
3579     VIXL_ASSERT(allow_macro_instructions_);
3580     SingleEmissionCheckScope guard(this);
3581     if (IsImmLogical(imm, zd.GetLaneSizeInBits())) {
3582       bic(zd, zn, imm);
3583     } else {
3584       // TODO: Synthesise the immediate once 'Mov' is implemented.
3585       VIXL_UNIMPLEMENTED();
3586     }
3587   }
Bics(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3588   void Bics(const PRegisterWithLaneSize& pd,
3589             const PRegisterZ& pg,
3590             const PRegisterWithLaneSize& pn,
3591             const PRegisterWithLaneSize& pm) {
3592     VIXL_ASSERT(allow_macro_instructions_);
3593     SingleEmissionCheckScope guard(this);
3594     bics(pd, pg, pn, pm);
3595   }
Brka(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn)3596   void Brka(const PRegisterWithLaneSize& pd,
3597             const PRegister& pg,
3598             const PRegisterWithLaneSize& pn) {
3599     VIXL_ASSERT(allow_macro_instructions_);
3600     SingleEmissionCheckScope guard(this);
3601     brka(pd, pg, pn);
3602   }
Brkas(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)3603   void Brkas(const PRegisterWithLaneSize& pd,
3604              const PRegisterZ& pg,
3605              const PRegisterWithLaneSize& pn) {
3606     VIXL_ASSERT(allow_macro_instructions_);
3607     SingleEmissionCheckScope guard(this);
3608     brkas(pd, pg, pn);
3609   }
Brkb(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn)3610   void Brkb(const PRegisterWithLaneSize& pd,
3611             const PRegister& pg,
3612             const PRegisterWithLaneSize& pn) {
3613     VIXL_ASSERT(allow_macro_instructions_);
3614     SingleEmissionCheckScope guard(this);
3615     brkb(pd, pg, pn);
3616   }
Brkbs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)3617   void Brkbs(const PRegisterWithLaneSize& pd,
3618              const PRegisterZ& pg,
3619              const PRegisterWithLaneSize& pn) {
3620     VIXL_ASSERT(allow_macro_instructions_);
3621     SingleEmissionCheckScope guard(this);
3622     brkbs(pd, pg, pn);
3623   }
Brkn(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3624   void Brkn(const PRegisterWithLaneSize& pd,
3625             const PRegisterZ& pg,
3626             const PRegisterWithLaneSize& pn,
3627             const PRegisterWithLaneSize& pm) {
3628     VIXL_ASSERT(allow_macro_instructions_);
3629     if (!pd.Aliases(pm)) {
3630       Mov(pd, pm);
3631     }
3632     SingleEmissionCheckScope guard(this);
3633     brkn(pd, pg, pn, pd);
3634   }
Brkns(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3635   void Brkns(const PRegisterWithLaneSize& pd,
3636              const PRegisterZ& pg,
3637              const PRegisterWithLaneSize& pn,
3638              const PRegisterWithLaneSize& pm) {
3639     VIXL_ASSERT(allow_macro_instructions_);
3640     if (!pd.Aliases(pm)) {
3641       Mov(pd, pm);
3642     }
3643     SingleEmissionCheckScope guard(this);
3644     brkns(pd, pg, pn, pd);
3645   }
Brkpa(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3646   void Brkpa(const PRegisterWithLaneSize& pd,
3647              const PRegisterZ& pg,
3648              const PRegisterWithLaneSize& pn,
3649              const PRegisterWithLaneSize& pm) {
3650     VIXL_ASSERT(allow_macro_instructions_);
3651     SingleEmissionCheckScope guard(this);
3652     brkpa(pd, pg, pn, pm);
3653   }
Brkpas(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3654   void Brkpas(const PRegisterWithLaneSize& pd,
3655               const PRegisterZ& pg,
3656               const PRegisterWithLaneSize& pn,
3657               const PRegisterWithLaneSize& pm) {
3658     VIXL_ASSERT(allow_macro_instructions_);
3659     SingleEmissionCheckScope guard(this);
3660     brkpas(pd, pg, pn, pm);
3661   }
Brkpb(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3662   void Brkpb(const PRegisterWithLaneSize& pd,
3663              const PRegisterZ& pg,
3664              const PRegisterWithLaneSize& pn,
3665              const PRegisterWithLaneSize& pm) {
3666     VIXL_ASSERT(allow_macro_instructions_);
3667     SingleEmissionCheckScope guard(this);
3668     brkpb(pd, pg, pn, pm);
3669   }
Brkpbs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)3670   void Brkpbs(const PRegisterWithLaneSize& pd,
3671               const PRegisterZ& pg,
3672               const PRegisterWithLaneSize& pn,
3673               const PRegisterWithLaneSize& pm) {
3674     VIXL_ASSERT(allow_macro_instructions_);
3675     SingleEmissionCheckScope guard(this);
3676     brkpbs(pd, pg, pn, pm);
3677   }
Clasta(const Register & rd,const PRegister & pg,const Register & rn,const ZRegister & zm)3678   void Clasta(const Register& rd,
3679               const PRegister& pg,
3680               const Register& rn,
3681               const ZRegister& zm) {
3682     VIXL_ASSERT(allow_macro_instructions_);
3683     SingleEmissionCheckScope guard(this);
3684     clasta(rd, pg, rn, zm);
3685   }
Clasta(const VRegister & vd,const PRegister & pg,const VRegister & vn,const ZRegister & zm)3686   void Clasta(const VRegister& vd,
3687               const PRegister& pg,
3688               const VRegister& vn,
3689               const ZRegister& zm) {
3690     VIXL_ASSERT(allow_macro_instructions_);
3691     SingleEmissionCheckScope guard(this);
3692     clasta(vd, pg, vn, zm);
3693   }
3694   void Clasta(const ZRegister& zd,
3695               const PRegister& pg,
3696               const ZRegister& zn,
3697               const ZRegister& zm);
Clastb(const Register & rd,const PRegister & pg,const Register & rn,const ZRegister & zm)3698   void Clastb(const Register& rd,
3699               const PRegister& pg,
3700               const Register& rn,
3701               const ZRegister& zm) {
3702     VIXL_ASSERT(allow_macro_instructions_);
3703     SingleEmissionCheckScope guard(this);
3704     clastb(rd, pg, rn, zm);
3705   }
Clastb(const VRegister & vd,const PRegister & pg,const VRegister & vn,const ZRegister & zm)3706   void Clastb(const VRegister& vd,
3707               const PRegister& pg,
3708               const VRegister& vn,
3709               const ZRegister& zm) {
3710     VIXL_ASSERT(allow_macro_instructions_);
3711     SingleEmissionCheckScope guard(this);
3712     clastb(vd, pg, vn, zm);
3713   }
3714   void Clastb(const ZRegister& zd,
3715               const PRegister& pg,
3716               const ZRegister& zn,
3717               const ZRegister& zm);
Cls(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3718   void Cls(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
3719     VIXL_ASSERT(allow_macro_instructions_);
3720     SingleEmissionCheckScope guard(this);
3721     cls(zd, pg, zn);
3722   }
Clz(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3723   void Clz(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
3724     VIXL_ASSERT(allow_macro_instructions_);
3725     SingleEmissionCheckScope guard(this);
3726     clz(zd, pg, zn);
3727   }
Cmpeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3728   void Cmpeq(const PRegisterWithLaneSize& pd,
3729              const PRegisterZ& pg,
3730              const ZRegister& zn,
3731              const ZRegister& zm) {
3732     VIXL_ASSERT(allow_macro_instructions_);
3733     SingleEmissionCheckScope guard(this);
3734     cmpeq(pd, pg, zn, zm);
3735   }
Cmpeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3736   void Cmpeq(const PRegisterWithLaneSize& pd,
3737              const PRegisterZ& pg,
3738              const ZRegister& zn,
3739              IntegerOperand imm) {
3740     VIXL_ASSERT(allow_macro_instructions_);
3741     int imm5;
3742     if (imm.TryEncodeAsIntNForLane<5>(zn, &imm5)) {
3743       SingleEmissionCheckScope guard(this);
3744       cmpeq(pd, pg, zn, imm5);
3745     } else {
3746       CompareHelper(eq, pd, pg, zn, imm);
3747     }
3748   }
Cmpge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3749   void Cmpge(const PRegisterWithLaneSize& pd,
3750              const PRegisterZ& pg,
3751              const ZRegister& zn,
3752              const ZRegister& zm) {
3753     VIXL_ASSERT(allow_macro_instructions_);
3754     SingleEmissionCheckScope guard(this);
3755     cmpge(pd, pg, zn, zm);
3756   }
Cmpge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3757   void Cmpge(const PRegisterWithLaneSize& pd,
3758              const PRegisterZ& pg,
3759              const ZRegister& zn,
3760              IntegerOperand imm) {
3761     VIXL_ASSERT(allow_macro_instructions_);
3762     int imm5;
3763     if (imm.TryEncodeAsIntNForLane<5>(zn, &imm5)) {
3764       SingleEmissionCheckScope guard(this);
3765       cmpge(pd, pg, zn, imm5);
3766     } else {
3767       CompareHelper(ge, pd, pg, zn, imm);
3768     }
3769   }
Cmpgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3770   void Cmpgt(const PRegisterWithLaneSize& pd,
3771              const PRegisterZ& pg,
3772              const ZRegister& zn,
3773              const ZRegister& zm) {
3774     VIXL_ASSERT(allow_macro_instructions_);
3775     SingleEmissionCheckScope guard(this);
3776     cmpgt(pd, pg, zn, zm);
3777   }
Cmpgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3778   void Cmpgt(const PRegisterWithLaneSize& pd,
3779              const PRegisterZ& pg,
3780              const ZRegister& zn,
3781              IntegerOperand imm) {
3782     VIXL_ASSERT(allow_macro_instructions_);
3783     int imm5;
3784     if (imm.TryEncodeAsIntNForLane<5>(zn, &imm5)) {
3785       SingleEmissionCheckScope guard(this);
3786       cmpgt(pd, pg, zn, imm5);
3787     } else {
3788       CompareHelper(gt, pd, pg, zn, imm);
3789     }
3790   }
Cmphi(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3791   void Cmphi(const PRegisterWithLaneSize& pd,
3792              const PRegisterZ& pg,
3793              const ZRegister& zn,
3794              const ZRegister& zm) {
3795     VIXL_ASSERT(allow_macro_instructions_);
3796     SingleEmissionCheckScope guard(this);
3797     cmphi(pd, pg, zn, zm);
3798   }
Cmphi(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3799   void Cmphi(const PRegisterWithLaneSize& pd,
3800              const PRegisterZ& pg,
3801              const ZRegister& zn,
3802              IntegerOperand imm) {
3803     VIXL_ASSERT(allow_macro_instructions_);
3804     if (imm.IsUintN(7)) {
3805       SingleEmissionCheckScope guard(this);
3806       cmphi(pd, pg, zn, static_cast<unsigned>(imm.AsUintN(7)));
3807     } else {
3808       CompareHelper(hi, pd, pg, zn, imm);
3809     }
3810   }
Cmphs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3811   void Cmphs(const PRegisterWithLaneSize& pd,
3812              const PRegisterZ& pg,
3813              const ZRegister& zn,
3814              const ZRegister& zm) {
3815     VIXL_ASSERT(allow_macro_instructions_);
3816     SingleEmissionCheckScope guard(this);
3817     cmphs(pd, pg, zn, zm);
3818   }
Cmphs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3819   void Cmphs(const PRegisterWithLaneSize& pd,
3820              const PRegisterZ& pg,
3821              const ZRegister& zn,
3822              IntegerOperand imm) {
3823     if (imm.IsUintN(7)) {
3824       SingleEmissionCheckScope guard(this);
3825       cmphs(pd, pg, zn, static_cast<unsigned>(imm.AsUintN(7)));
3826     } else {
3827       CompareHelper(hs, pd, pg, zn, imm);
3828     }
3829   }
Cmple(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3830   void Cmple(const PRegisterWithLaneSize& pd,
3831              const PRegisterZ& pg,
3832              const ZRegister& zn,
3833              const ZRegister& zm) {
3834     VIXL_ASSERT(allow_macro_instructions_);
3835     SingleEmissionCheckScope guard(this);
3836     cmple(pd, pg, zn, zm);
3837   }
Cmple(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3838   void Cmple(const PRegisterWithLaneSize& pd,
3839              const PRegisterZ& pg,
3840              const ZRegister& zn,
3841              IntegerOperand imm) {
3842     VIXL_ASSERT(allow_macro_instructions_);
3843     int imm5;
3844     if (imm.TryEncodeAsIntNForLane<5>(zn, &imm5)) {
3845       SingleEmissionCheckScope guard(this);
3846       cmple(pd, pg, zn, imm5);
3847     } else {
3848       CompareHelper(le, pd, pg, zn, imm);
3849     }
3850   }
Cmplo(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3851   void Cmplo(const PRegisterWithLaneSize& pd,
3852              const PRegisterZ& pg,
3853              const ZRegister& zn,
3854              const ZRegister& zm) {
3855     VIXL_ASSERT(allow_macro_instructions_);
3856     SingleEmissionCheckScope guard(this);
3857     cmplo(pd, pg, zn, zm);
3858   }
Cmplo(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3859   void Cmplo(const PRegisterWithLaneSize& pd,
3860              const PRegisterZ& pg,
3861              const ZRegister& zn,
3862              IntegerOperand imm) {
3863     if (imm.IsUintN(7)) {
3864       SingleEmissionCheckScope guard(this);
3865       cmplo(pd, pg, zn, static_cast<unsigned>(imm.AsUintN(7)));
3866     } else {
3867       CompareHelper(lo, pd, pg, zn, imm);
3868     }
3869   }
Cmpls(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3870   void Cmpls(const PRegisterWithLaneSize& pd,
3871              const PRegisterZ& pg,
3872              const ZRegister& zn,
3873              const ZRegister& zm) {
3874     VIXL_ASSERT(allow_macro_instructions_);
3875     SingleEmissionCheckScope guard(this);
3876     cmpls(pd, pg, zn, zm);
3877   }
Cmpls(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3878   void Cmpls(const PRegisterWithLaneSize& pd,
3879              const PRegisterZ& pg,
3880              const ZRegister& zn,
3881              IntegerOperand imm) {
3882     if (imm.IsUintN(7)) {
3883       SingleEmissionCheckScope guard(this);
3884       cmpls(pd, pg, zn, static_cast<unsigned>(imm.AsUintN(7)));
3885     } else {
3886       CompareHelper(ls, pd, pg, zn, imm);
3887     }
3888   }
Cmplt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3889   void Cmplt(const PRegisterWithLaneSize& pd,
3890              const PRegisterZ& pg,
3891              const ZRegister& zn,
3892              const ZRegister& zm) {
3893     VIXL_ASSERT(allow_macro_instructions_);
3894     SingleEmissionCheckScope guard(this);
3895     cmplt(pd, pg, zn, zm);
3896   }
Cmplt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3897   void Cmplt(const PRegisterWithLaneSize& pd,
3898              const PRegisterZ& pg,
3899              const ZRegister& zn,
3900              IntegerOperand imm) {
3901     VIXL_ASSERT(allow_macro_instructions_);
3902     int imm5;
3903     if (imm.TryEncodeAsIntNForLane<5>(zn, &imm5)) {
3904       SingleEmissionCheckScope guard(this);
3905       cmplt(pd, pg, zn, imm5);
3906     } else {
3907       CompareHelper(lt, pd, pg, zn, imm);
3908     }
3909   }
Cmpne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)3910   void Cmpne(const PRegisterWithLaneSize& pd,
3911              const PRegisterZ& pg,
3912              const ZRegister& zn,
3913              const ZRegister& zm) {
3914     VIXL_ASSERT(allow_macro_instructions_);
3915     SingleEmissionCheckScope guard(this);
3916     cmpne(pd, pg, zn, zm);
3917   }
Cmpne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,IntegerOperand imm)3918   void Cmpne(const PRegisterWithLaneSize& pd,
3919              const PRegisterZ& pg,
3920              const ZRegister& zn,
3921              IntegerOperand imm) {
3922     VIXL_ASSERT(allow_macro_instructions_);
3923     int imm5;
3924     if (imm.TryEncodeAsIntNForLane<5>(zn, &imm5)) {
3925       SingleEmissionCheckScope guard(this);
3926       cmpne(pd, pg, zn, imm5);
3927     } else {
3928       CompareHelper(ne, pd, pg, zn, imm);
3929     }
3930   }
Cnot(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3931   void Cnot(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
3932     VIXL_ASSERT(allow_macro_instructions_);
3933     SingleEmissionCheckScope guard(this);
3934     cnot(zd, pg, zn);
3935   }
Cnt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)3936   void Cnt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
3937     VIXL_ASSERT(allow_macro_instructions_);
3938     SingleEmissionCheckScope guard(this);
3939     cnt(zd, pg, zn);
3940   }
3941   void Cntb(const Register& rd, int pattern = SVE_ALL, int multiplier = 1) {
3942     VIXL_ASSERT(allow_macro_instructions_);
3943     SingleEmissionCheckScope guard(this);
3944     cntb(rd, pattern, multiplier);
3945   }
3946   void Cntd(const Register& rd, int pattern = SVE_ALL, int multiplier = 1) {
3947     VIXL_ASSERT(allow_macro_instructions_);
3948     SingleEmissionCheckScope guard(this);
3949     cntd(rd, pattern, multiplier);
3950   }
3951   void Cnth(const Register& rd, int pattern = SVE_ALL, int multiplier = 1) {
3952     VIXL_ASSERT(allow_macro_instructions_);
3953     SingleEmissionCheckScope guard(this);
3954     cnth(rd, pattern, multiplier);
3955   }
Cntp(const Register & rd,const PRegister & pg,const PRegisterWithLaneSize & pn)3956   void Cntp(const Register& rd,
3957             const PRegister& pg,
3958             const PRegisterWithLaneSize& pn) {
3959     VIXL_ASSERT(allow_macro_instructions_);
3960     SingleEmissionCheckScope guard(this);
3961     // The `cntp` instruction architecturally takes an X register, but the
3962     // result will always be in the range [0, kPRegMaxSize] (and therefore
3963     // always fits in a W register), so we can accept a W-sized rd here.
3964     cntp(rd.X(), pg, pn);
3965   }
3966   void Cntw(const Register& rd, int pattern = SVE_ALL, int multiplier = 1) {
3967     VIXL_ASSERT(allow_macro_instructions_);
3968     SingleEmissionCheckScope guard(this);
3969     cntw(rd, pattern, multiplier);
3970   }
Compact(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)3971   void Compact(const ZRegister& zd, const PRegister& pg, const ZRegister& zn) {
3972     VIXL_ASSERT(allow_macro_instructions_);
3973     SingleEmissionCheckScope guard(this);
3974     compact(zd, pg, zn);
3975   }
3976   void Cpy(const ZRegister& zd, const PRegister& pg, IntegerOperand imm);
Cpy(const ZRegister & zd,const PRegisterM & pg,const Register & rn)3977   void Cpy(const ZRegister& zd, const PRegisterM& pg, const Register& rn) {
3978     VIXL_ASSERT(allow_macro_instructions_);
3979     SingleEmissionCheckScope guard(this);
3980     cpy(zd, pg, rn);
3981   }
Cpy(const ZRegister & zd,const PRegisterM & pg,const VRegister & vn)3982   void Cpy(const ZRegister& zd, const PRegisterM& pg, const VRegister& vn) {
3983     VIXL_ASSERT(allow_macro_instructions_);
3984     SingleEmissionCheckScope guard(this);
3985     cpy(zd, pg, vn);
3986   }
Ctermeq(const Register & rn,const Register & rm)3987   void Ctermeq(const Register& rn, const Register& rm) {
3988     VIXL_ASSERT(allow_macro_instructions_);
3989     SingleEmissionCheckScope guard(this);
3990     ctermeq(rn, rm);
3991   }
Ctermne(const Register & rn,const Register & rm)3992   void Ctermne(const Register& rn, const Register& rm) {
3993     VIXL_ASSERT(allow_macro_instructions_);
3994     SingleEmissionCheckScope guard(this);
3995     ctermne(rn, rm);
3996   }
3997   void Decb(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
3998     VIXL_ASSERT(allow_macro_instructions_);
3999     SingleEmissionCheckScope guard(this);
4000     decb(rdn, pattern, multiplier);
4001   }
4002   void Decd(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
4003     VIXL_ASSERT(allow_macro_instructions_);
4004     SingleEmissionCheckScope guard(this);
4005     decd(rdn, pattern, multiplier);
4006   }
4007   void Decd(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
4008     VIXL_ASSERT(allow_macro_instructions_);
4009     SingleEmissionCheckScope guard(this);
4010     decd(zdn, pattern, multiplier);
4011   }
4012   void Dech(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
4013     VIXL_ASSERT(allow_macro_instructions_);
4014     SingleEmissionCheckScope guard(this);
4015     dech(rdn, pattern, multiplier);
4016   }
4017   void Dech(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
4018     VIXL_ASSERT(allow_macro_instructions_);
4019     SingleEmissionCheckScope guard(this);
4020     dech(zdn, pattern, multiplier);
4021   }
Decp(const Register & rdn,const PRegisterWithLaneSize & pg)4022   void Decp(const Register& rdn, const PRegisterWithLaneSize& pg) {
4023     VIXL_ASSERT(allow_macro_instructions_);
4024     SingleEmissionCheckScope guard(this);
4025     decp(rdn, pg);
4026   }
Decp(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)4027   void Decp(const ZRegister& zd, const PRegister& pg, const ZRegister& zn) {
4028     VIXL_ASSERT(allow_macro_instructions_);
4029     VIXL_ASSERT(AreSameFormat(zd, zn));
4030     // `decp` writes every lane, so use an unpredicated movprfx.
4031     MovprfxHelperScope guard(this, zd, zn);
4032     decp(zd, pg);
4033   }
Decp(const ZRegister & zdn,const PRegister & pg)4034   void Decp(const ZRegister& zdn, const PRegister& pg) { Decp(zdn, pg, zdn); }
4035   void Decw(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
4036     VIXL_ASSERT(allow_macro_instructions_);
4037     SingleEmissionCheckScope guard(this);
4038     decw(rdn, pattern, multiplier);
4039   }
4040   void Decw(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
4041     VIXL_ASSERT(allow_macro_instructions_);
4042     SingleEmissionCheckScope guard(this);
4043     decw(zdn, pattern, multiplier);
4044   }
Dup(const ZRegister & zd,const Register & xn)4045   void Dup(const ZRegister& zd, const Register& xn) {
4046     VIXL_ASSERT(allow_macro_instructions_);
4047     SingleEmissionCheckScope guard(this);
4048     dup(zd, xn);
4049   }
Dup(const ZRegister & zd,const ZRegister & zn,int index)4050   void Dup(const ZRegister& zd, const ZRegister& zn, int index) {
4051     VIXL_ASSERT(allow_macro_instructions_);
4052     SingleEmissionCheckScope guard(this);
4053     dup(zd, zn, index);
4054   }
4055   void Dup(const ZRegister& zd, IntegerOperand imm);
Eon(const ZRegister & zd,const ZRegister & zn,uint64_t imm)4056   void Eon(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
4057     VIXL_ASSERT(allow_macro_instructions_);
4058     SingleEmissionCheckScope guard(this);
4059     if (IsImmLogical(imm, zd.GetLaneSizeInBits())) {
4060       eon(zd, zn, imm);
4061     } else {
4062       // TODO: Synthesise the immediate once 'Mov' is implemented.
4063       VIXL_UNIMPLEMENTED();
4064     }
4065   }
Eor(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)4066   void Eor(const PRegisterWithLaneSize& pd,
4067            const PRegisterZ& pg,
4068            const PRegisterWithLaneSize& pn,
4069            const PRegisterWithLaneSize& pm) {
4070     VIXL_ASSERT(allow_macro_instructions_);
4071     SingleEmissionCheckScope guard(this);
4072     eor(pd, pg, pn, pm);
4073   }
Eor(const ZRegister & zd,const ZRegister & zn,uint64_t imm)4074   void Eor(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
4075     VIXL_ASSERT(allow_macro_instructions_);
4076     SingleEmissionCheckScope guard(this);
4077     if (IsImmLogical(imm, zd.GetLaneSizeInBits())) {
4078       eor(zd, zn, imm);
4079     } else {
4080       // TODO: Synthesise the immediate once 'Mov' is implemented.
4081       VIXL_UNIMPLEMENTED();
4082     }
4083   }
Eor(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4084   void Eor(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4085     VIXL_ASSERT(allow_macro_instructions_);
4086     VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
4087     SingleEmissionCheckScope guard(this);
4088     eor(zd.VnD(), zn.VnD(), zm.VnD());
4089   }
Eors(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)4090   void Eors(const PRegisterWithLaneSize& pd,
4091             const PRegisterZ& pg,
4092             const PRegisterWithLaneSize& pn,
4093             const PRegisterWithLaneSize& pm) {
4094     VIXL_ASSERT(allow_macro_instructions_);
4095     SingleEmissionCheckScope guard(this);
4096     eors(pd, pg, pn, pm);
4097   }
Eorv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4098   void Eorv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4099     VIXL_ASSERT(allow_macro_instructions_);
4100     SingleEmissionCheckScope guard(this);
4101     eorv(vd, pg, zn);
4102   }
4103   void Ext(const ZRegister& zd,
4104            const ZRegister& zn,
4105            const ZRegister& zm,
4106            unsigned offset);
4107   void Fabd(const ZRegister& zd,
4108             const PRegisterM& pg,
4109             const ZRegister& zn,
4110             const ZRegister& zm,
4111             FPMacroNaNPropagationOption nan_option);
Fabs(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4112   void Fabs(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4113     VIXL_ASSERT(allow_macro_instructions_);
4114     SingleEmissionCheckScope guard(this);
4115     fabs(zd, pg, zn);
4116   }
Facge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4117   void Facge(const PRegisterWithLaneSize& pd,
4118              const PRegisterZ& pg,
4119              const ZRegister& zn,
4120              const ZRegister& zm) {
4121     VIXL_ASSERT(allow_macro_instructions_);
4122     SingleEmissionCheckScope guard(this);
4123     facge(pd, pg, zn, zm);
4124   }
Facgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4125   void Facgt(const PRegisterWithLaneSize& pd,
4126              const PRegisterZ& pg,
4127              const ZRegister& zn,
4128              const ZRegister& zm) {
4129     VIXL_ASSERT(allow_macro_instructions_);
4130     SingleEmissionCheckScope guard(this);
4131     facgt(pd, pg, zn, zm);
4132   }
Facle(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4133   void Facle(const PRegisterWithLaneSize& pd,
4134              const PRegisterZ& pg,
4135              const ZRegister& zn,
4136              const ZRegister& zm) {
4137     VIXL_ASSERT(allow_macro_instructions_);
4138     SingleEmissionCheckScope guard(this);
4139     facge(pd, pg, zm, zn);
4140   }
Faclt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4141   void Faclt(const PRegisterWithLaneSize& pd,
4142              const PRegisterZ& pg,
4143              const ZRegister& zn,
4144              const ZRegister& zm) {
4145     VIXL_ASSERT(allow_macro_instructions_);
4146     SingleEmissionCheckScope guard(this);
4147     facgt(pd, pg, zm, zn);
4148   }
Fadd(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)4149   void Fadd(const ZRegister& zd,
4150             const PRegisterM& pg,
4151             const ZRegister& zn,
4152             double imm) {
4153     VIXL_ASSERT(allow_macro_instructions_);
4154     MovprfxHelperScope guard(this, zd, pg, zn);
4155     fadd(zd, pg, zd, imm);
4156   }
4157   void Fadd(const ZRegister& zd,
4158             const PRegisterM& pg,
4159             const ZRegister& zn,
4160             const ZRegister& zm,
4161             FPMacroNaNPropagationOption nan_option);
Fadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4162   void Fadd(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4163     VIXL_ASSERT(allow_macro_instructions_);
4164     SingleEmissionCheckScope guard(this);
4165     fadd(zd, zn, zm);
4166   }
Fadda(const VRegister & vd,const PRegister & pg,const VRegister & vn,const ZRegister & zm)4167   void Fadda(const VRegister& vd,
4168              const PRegister& pg,
4169              const VRegister& vn,
4170              const ZRegister& zm) {
4171     VIXL_ASSERT(allow_macro_instructions_);
4172     SingleEmissionCheckScope guard(this);
4173     fadda(vd, pg, vn, zm);
4174   }
Faddv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4175   void Faddv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4176     VIXL_ASSERT(allow_macro_instructions_);
4177     SingleEmissionCheckScope guard(this);
4178     faddv(vd, pg, zn);
4179   }
4180   void Fcadd(const ZRegister& zd,
4181              const PRegisterM& pg,
4182              const ZRegister& zn,
4183              const ZRegister& zm,
4184              int rot);
Fcmeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)4185   void Fcmeq(const PRegisterWithLaneSize& pd,
4186              const PRegisterZ& pg,
4187              const ZRegister& zn,
4188              double zero) {
4189     VIXL_ASSERT(allow_macro_instructions_);
4190     SingleEmissionCheckScope guard(this);
4191     if (zero == 0.0) {
4192       fcmeq(pd, pg, zn, zero);
4193     } else {
4194       // TODO: Synthesise other immediates.
4195       VIXL_UNIMPLEMENTED();
4196     }
4197   }
Fcmeq(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4198   void Fcmeq(const PRegisterWithLaneSize& pd,
4199              const PRegisterZ& pg,
4200              const ZRegister& zn,
4201              const ZRegister& zm) {
4202     VIXL_ASSERT(allow_macro_instructions_);
4203     SingleEmissionCheckScope guard(this);
4204     fcmeq(pd, pg, zn, zm);
4205   }
Fcmge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)4206   void Fcmge(const PRegisterWithLaneSize& pd,
4207              const PRegisterZ& pg,
4208              const ZRegister& zn,
4209              double zero) {
4210     VIXL_ASSERT(allow_macro_instructions_);
4211     SingleEmissionCheckScope guard(this);
4212     if (zero == 0.0) {
4213       fcmge(pd, pg, zn, zero);
4214     } else {
4215       // TODO: Synthesise other immediates.
4216       VIXL_UNIMPLEMENTED();
4217     }
4218   }
Fcmge(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4219   void Fcmge(const PRegisterWithLaneSize& pd,
4220              const PRegisterZ& pg,
4221              const ZRegister& zn,
4222              const ZRegister& zm) {
4223     VIXL_ASSERT(allow_macro_instructions_);
4224     SingleEmissionCheckScope guard(this);
4225     fcmge(pd, pg, zn, zm);
4226   }
Fcmgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)4227   void Fcmgt(const PRegisterWithLaneSize& pd,
4228              const PRegisterZ& pg,
4229              const ZRegister& zn,
4230              double zero) {
4231     VIXL_ASSERT(allow_macro_instructions_);
4232     SingleEmissionCheckScope guard(this);
4233     if (zero == 0.0) {
4234       fcmgt(pd, pg, zn, zero);
4235     } else {
4236       // TODO: Synthesise other immediates.
4237       VIXL_UNIMPLEMENTED();
4238     }
4239   }
Fcmgt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4240   void Fcmgt(const PRegisterWithLaneSize& pd,
4241              const PRegisterZ& pg,
4242              const ZRegister& zn,
4243              const ZRegister& zm) {
4244     VIXL_ASSERT(allow_macro_instructions_);
4245     SingleEmissionCheckScope guard(this);
4246     fcmgt(pd, pg, zn, zm);
4247   }
Fcmla(const ZRegister & zda,const PRegisterM & pg,const ZRegister & zn,const ZRegister & zm,int rot)4248   void Fcmla(const ZRegister& zda,
4249              const PRegisterM& pg,
4250              const ZRegister& zn,
4251              const ZRegister& zm,
4252              int rot) {
4253     VIXL_ASSERT(allow_macro_instructions_);
4254     MovprfxHelperScope guard(this, zda, pg, zda);
4255     fcmla(zda, pg, zn, zm, rot);
4256   }
Fcmla(const ZRegister & zda,const ZRegister & zn,const ZRegister & zm,int index,int rot)4257   void Fcmla(const ZRegister& zda,
4258              const ZRegister& zn,
4259              const ZRegister& zm,
4260              int index,
4261              int rot) {
4262     VIXL_ASSERT(allow_macro_instructions_);
4263     SingleEmissionCheckScope guard(this);
4264     fcmla(zda, zn, zm, index, rot);
4265   }
Fcmle(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)4266   void Fcmle(const PRegisterWithLaneSize& pd,
4267              const PRegisterZ& pg,
4268              const ZRegister& zn,
4269              double zero) {
4270     VIXL_ASSERT(allow_macro_instructions_);
4271     SingleEmissionCheckScope guard(this);
4272     if (zero == 0.0) {
4273       fcmle(pd, pg, zn, zero);
4274     } else {
4275       // TODO: Synthesise other immediates.
4276       VIXL_UNIMPLEMENTED();
4277     }
4278   }
Fcmle(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4279   void Fcmle(const PRegisterWithLaneSize& pd,
4280              const PRegisterZ& pg,
4281              const ZRegister& zn,
4282              const ZRegister& zm) {
4283     VIXL_ASSERT(allow_macro_instructions_);
4284     SingleEmissionCheckScope guard(this);
4285     fcmge(pd, pg, zm, zn);
4286   }
Fcmlt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)4287   void Fcmlt(const PRegisterWithLaneSize& pd,
4288              const PRegisterZ& pg,
4289              const ZRegister& zn,
4290              double zero) {
4291     VIXL_ASSERT(allow_macro_instructions_);
4292     SingleEmissionCheckScope guard(this);
4293     if (zero == 0.0) {
4294       fcmlt(pd, pg, zn, zero);
4295     } else {
4296       // TODO: Synthesise other immediates.
4297       VIXL_UNIMPLEMENTED();
4298     }
4299   }
Fcmlt(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4300   void Fcmlt(const PRegisterWithLaneSize& pd,
4301              const PRegisterZ& pg,
4302              const ZRegister& zn,
4303              const ZRegister& zm) {
4304     VIXL_ASSERT(allow_macro_instructions_);
4305     SingleEmissionCheckScope guard(this);
4306     fcmgt(pd, pg, zm, zn);
4307   }
Fcmne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,double zero)4308   void Fcmne(const PRegisterWithLaneSize& pd,
4309              const PRegisterZ& pg,
4310              const ZRegister& zn,
4311              double zero) {
4312     VIXL_ASSERT(allow_macro_instructions_);
4313     SingleEmissionCheckScope guard(this);
4314     if (zero == 0.0) {
4315       fcmne(pd, pg, zn, zero);
4316     } else {
4317       // TODO: Synthesise other immediates.
4318       VIXL_UNIMPLEMENTED();
4319     }
4320   }
Fcmne(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4321   void Fcmne(const PRegisterWithLaneSize& pd,
4322              const PRegisterZ& pg,
4323              const ZRegister& zn,
4324              const ZRegister& zm) {
4325     VIXL_ASSERT(allow_macro_instructions_);
4326     SingleEmissionCheckScope guard(this);
4327     fcmne(pd, pg, zn, zm);
4328   }
Fcmuo(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const ZRegister & zn,const ZRegister & zm)4329   void Fcmuo(const PRegisterWithLaneSize& pd,
4330              const PRegisterZ& pg,
4331              const ZRegister& zn,
4332              const ZRegister& zm) {
4333     VIXL_ASSERT(allow_macro_instructions_);
4334     SingleEmissionCheckScope guard(this);
4335     fcmuo(pd, pg, zn, zm);
4336   }
4337   void Fcpy(const ZRegister& zd, const PRegisterM& pg, double imm);
4338   void Fcpy(const ZRegister& zd, const PRegisterM& pg, float imm);
4339   void Fcpy(const ZRegister& zd, const PRegisterM& pg, Float16 imm);
Fcvt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4340   void Fcvt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4341     VIXL_ASSERT(allow_macro_instructions_);
4342     SingleEmissionCheckScope guard(this);
4343     fcvt(zd, pg, zn);
4344   }
Fcvt(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4345   void Fcvt(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4346     VIXL_ASSERT(allow_macro_instructions_);
4347     // The element type in this predicated movprfx is determined by the larger
4348     // type between the source and destination.
4349     int lane_size = std::max(zd.GetLaneSizeInBits(), zn.GetLaneSizeInBits());
4350     MovprfxHelperScope guard(this,
4351                              zd.WithLaneSize(lane_size),
4352                              pg,
4353                              zn.WithLaneSize(lane_size));
4354     fcvt(zd, pg.Merging(), zn);
4355   }
Fcvtzs(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4356   void Fcvtzs(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4357     VIXL_ASSERT(allow_macro_instructions_);
4358     SingleEmissionCheckScope guard(this);
4359     fcvtzs(zd, pg, zn);
4360   }
Fcvtzu(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4361   void Fcvtzu(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4362     VIXL_ASSERT(allow_macro_instructions_);
4363     SingleEmissionCheckScope guard(this);
4364     fcvtzu(zd, pg, zn);
4365   }
4366   void Fdiv(const ZRegister& zd,
4367             const PRegisterM& pg,
4368             const ZRegister& zn,
4369             const ZRegister& zm);
4370   void Fdup(const ZRegister& zd, double imm);
4371   void Fdup(const ZRegister& zd, float imm);
4372   void Fdup(const ZRegister& zd, Float16 imm);
Fexpa(const ZRegister & zd,const ZRegister & zn)4373   void Fexpa(const ZRegister& zd, const ZRegister& zn) {
4374     VIXL_ASSERT(allow_macro_instructions_);
4375     SingleEmissionCheckScope guard(this);
4376     fexpa(zd, zn);
4377   }
Fmad(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)4378   void Fmad(const ZRegister& zdn,
4379             const PRegisterM& pg,
4380             const ZRegister& zm,
4381             const ZRegister& za) {
4382     VIXL_ASSERT(allow_macro_instructions_);
4383     SingleEmissionCheckScope guard(this);
4384     fmad(zdn, pg, zm, za);
4385   }
Fmax(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)4386   void Fmax(const ZRegister& zd,
4387             const PRegisterM& pg,
4388             const ZRegister& zn,
4389             double imm) {
4390     VIXL_ASSERT(allow_macro_instructions_);
4391     MovprfxHelperScope guard(this, zd, pg, zn);
4392     fmax(zd, pg, zd, imm);
4393   }
4394   void Fmax(
4395       const ZRegister& zd,
4396       const PRegisterM& pg,
4397       const ZRegister& zn,
4398       const ZRegister& zm,
4399       FPMacroNaNPropagationOption nan_option = NoFPMacroNaNPropagationSelected);
Fmaxnm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)4400   void Fmaxnm(const ZRegister& zd,
4401               const PRegisterM& pg,
4402               const ZRegister& zn,
4403               double imm) {
4404     VIXL_ASSERT(allow_macro_instructions_);
4405     MovprfxHelperScope guard(this, zd, pg, zn);
4406     fmaxnm(zd, pg, zd, imm);
4407   }
4408   void Fmaxnm(const ZRegister& zd,
4409               const PRegisterM& pg,
4410               const ZRegister& zn,
4411               const ZRegister& zm,
4412               FPMacroNaNPropagationOption nan_option);
Fmaxnmv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4413   void Fmaxnmv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4414     VIXL_ASSERT(allow_macro_instructions_);
4415     SingleEmissionCheckScope guard(this);
4416     fmaxnmv(vd, pg, zn);
4417   }
Fmaxv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4418   void Fmaxv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4419     VIXL_ASSERT(allow_macro_instructions_);
4420     SingleEmissionCheckScope guard(this);
4421     fmaxv(vd, pg, zn);
4422   }
Fmin(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)4423   void Fmin(const ZRegister& zd,
4424             const PRegisterM& pg,
4425             const ZRegister& zn,
4426             double imm) {
4427     VIXL_ASSERT(allow_macro_instructions_);
4428     MovprfxHelperScope guard(this, zd, pg, zn);
4429     fmin(zd, pg, zd, imm);
4430   }
4431   void Fmin(
4432       const ZRegister& zd,
4433       const PRegisterM& pg,
4434       const ZRegister& zn,
4435       const ZRegister& zm,
4436       FPMacroNaNPropagationOption nan_option = NoFPMacroNaNPropagationSelected);
Fminnm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)4437   void Fminnm(const ZRegister& zd,
4438               const PRegisterM& pg,
4439               const ZRegister& zn,
4440               double imm) {
4441     VIXL_ASSERT(allow_macro_instructions_);
4442     MovprfxHelperScope guard(this, zd, pg, zn);
4443     fminnm(zd, pg, zd, imm);
4444   }
4445   void Fminnm(const ZRegister& zd,
4446               const PRegisterM& pg,
4447               const ZRegister& zn,
4448               const ZRegister& zm,
4449               FPMacroNaNPropagationOption nan_option);
Fminnmv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4450   void Fminnmv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4451     VIXL_ASSERT(allow_macro_instructions_);
4452     SingleEmissionCheckScope guard(this);
4453     fminnmv(vd, pg, zn);
4454   }
Fminv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4455   void Fminv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4456     VIXL_ASSERT(allow_macro_instructions_);
4457     SingleEmissionCheckScope guard(this);
4458     fminv(vd, pg, zn);
4459   }
4460   // zd = za + (zn * zm)
4461   void Fmla(
4462       const ZRegister& zd,
4463       const PRegisterM& pg,
4464       const ZRegister& za,
4465       const ZRegister& zn,
4466       const ZRegister& zm,
4467       FPMacroNaNPropagationOption nan_option = NoFPMacroNaNPropagationSelected);
4468   void Fmla(const ZRegister& zd,
4469             const ZRegister& za,
4470             const ZRegister& zn,
4471             const ZRegister& zm,
4472             int index);
4473   // zd = za - (zn * zm)
4474   void Fmls(
4475       const ZRegister& zd,
4476       const PRegisterM& pg,
4477       const ZRegister& za,
4478       const ZRegister& zn,
4479       const ZRegister& zm,
4480       FPMacroNaNPropagationOption nan_option = NoFPMacroNaNPropagationSelected);
4481   void Fmls(const ZRegister& zd,
4482             const ZRegister& za,
4483             const ZRegister& zn,
4484             const ZRegister& zm,
4485             int index);
Fmov(const ZRegister & zd,double imm)4486   void Fmov(const ZRegister& zd, double imm) {
4487     VIXL_ASSERT(allow_macro_instructions_);
4488     Fdup(zd, imm);
4489   }
Fmov(const ZRegister & zd,float imm)4490   void Fmov(const ZRegister& zd, float imm) {
4491     VIXL_ASSERT(allow_macro_instructions_);
4492     Fdup(zd, imm);
4493   }
Fmov(const ZRegister & zd,Float16 imm)4494   void Fmov(const ZRegister& zd, Float16 imm) {
4495     VIXL_ASSERT(allow_macro_instructions_);
4496     Fdup(zd, imm);
4497   }
Fmov(const ZRegister & zd,const PRegisterM & pg,double imm)4498   void Fmov(const ZRegister& zd, const PRegisterM& pg, double imm) {
4499     VIXL_ASSERT(allow_macro_instructions_);
4500     Fcpy(zd, pg, imm);
4501   }
Fmov(const ZRegister & zd,const PRegisterM & pg,float imm)4502   void Fmov(const ZRegister& zd, const PRegisterM& pg, float imm) {
4503     VIXL_ASSERT(allow_macro_instructions_);
4504     Fcpy(zd, pg, imm);
4505   }
Fmov(const ZRegister & zd,const PRegisterM & pg,Float16 imm)4506   void Fmov(const ZRegister& zd, const PRegisterM& pg, Float16 imm) {
4507     VIXL_ASSERT(allow_macro_instructions_);
4508     Fcpy(zd, pg, imm);
4509   }
Fmsb(const ZRegister & zdn,const PRegisterM & pg,const ZRegister & zm,const ZRegister & za)4510   void Fmsb(const ZRegister& zdn,
4511             const PRegisterM& pg,
4512             const ZRegister& zm,
4513             const ZRegister& za) {
4514     VIXL_ASSERT(allow_macro_instructions_);
4515     SingleEmissionCheckScope guard(this);
4516     fmsb(zdn, pg, zm, za);
4517   }
Fmul(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)4518   void Fmul(const ZRegister& zd,
4519             const PRegisterM& pg,
4520             const ZRegister& zn,
4521             double imm) {
4522     VIXL_ASSERT(allow_macro_instructions_);
4523     MovprfxHelperScope guard(this, zd, pg, zn);
4524     fmul(zd, pg, zd, imm);
4525   }
4526   void Fmul(const ZRegister& zd,
4527             const PRegisterM& pg,
4528             const ZRegister& zn,
4529             const ZRegister& zm,
4530             FPMacroNaNPropagationOption nan_option);
Fmul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm,unsigned index)4531   void Fmul(const ZRegister& zd,
4532             const ZRegister& zn,
4533             const ZRegister& zm,
4534             unsigned index) {
4535     VIXL_ASSERT(allow_macro_instructions_);
4536     SingleEmissionCheckScope guard(this);
4537     fmul(zd, zn, zm, index);
4538   }
Fmul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4539   void Fmul(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4540     VIXL_ASSERT(allow_macro_instructions_);
4541     SingleEmissionCheckScope guard(this);
4542     fmul(zd, zn, zm);
4543   }
4544   void Fmulx(const ZRegister& zd,
4545              const PRegisterM& pg,
4546              const ZRegister& zn,
4547              const ZRegister& zm,
4548              FPMacroNaNPropagationOption nan_option);
Fneg(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4549   void Fneg(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4550     VIXL_ASSERT(allow_macro_instructions_);
4551     SingleEmissionCheckScope guard(this);
4552     fneg(zd, pg, zn);
4553   }
4554   void Fnmla(
4555       const ZRegister& zda,
4556       const PRegisterM& pg,
4557       const ZRegister& za,
4558       const ZRegister& zn,
4559       const ZRegister& zm,
4560       FPMacroNaNPropagationOption nan_option = NoFPMacroNaNPropagationSelected);
4561   void Fnmls(
4562       const ZRegister& zd,
4563       const PRegisterM& pg,
4564       const ZRegister& za,
4565       const ZRegister& zn,
4566       const ZRegister& zm,
4567       FPMacroNaNPropagationOption nan_option = NoFPMacroNaNPropagationSelected);
Frecpe(const ZRegister & zd,const ZRegister & zn)4568   void Frecpe(const ZRegister& zd, const ZRegister& zn) {
4569     VIXL_ASSERT(allow_macro_instructions_);
4570     SingleEmissionCheckScope guard(this);
4571     frecpe(zd, zn);
4572   }
Frecps(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4573   void Frecps(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4574     VIXL_ASSERT(allow_macro_instructions_);
4575     SingleEmissionCheckScope guard(this);
4576     frecps(zd, zn, zm);
4577   }
Frecpx(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4578   void Frecpx(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4579     VIXL_ASSERT(allow_macro_instructions_);
4580     SingleEmissionCheckScope guard(this);
4581     frecpx(zd, pg, zn);
4582   }
Frecpx(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4583   void Frecpx(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4584     VIXL_ASSERT(allow_macro_instructions_);
4585     MovprfxHelperScope guard(this, zd, pg, zn);
4586     frecpx(zd, pg.Merging(), zn);
4587   }
Frinta(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4588   void Frinta(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4589     VIXL_ASSERT(allow_macro_instructions_);
4590     SingleEmissionCheckScope guard(this);
4591     frinta(zd, pg, zn);
4592   }
Frinta(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4593   void Frinta(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4594     VIXL_ASSERT(allow_macro_instructions_);
4595     MovprfxHelperScope guard(this, zd, pg, zn);
4596     frinta(zd, pg.Merging(), zn);
4597   }
Frinti(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4598   void Frinti(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4599     VIXL_ASSERT(allow_macro_instructions_);
4600     SingleEmissionCheckScope guard(this);
4601     frinti(zd, pg, zn);
4602   }
Frinti(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4603   void Frinti(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4604     VIXL_ASSERT(allow_macro_instructions_);
4605     MovprfxHelperScope guard(this, zd, pg, zn);
4606     frinti(zd, pg.Merging(), zn);
4607   }
Frintm(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4608   void Frintm(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4609     VIXL_ASSERT(allow_macro_instructions_);
4610     SingleEmissionCheckScope guard(this);
4611     frintm(zd, pg, zn);
4612   }
Frintm(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4613   void Frintm(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4614     VIXL_ASSERT(allow_macro_instructions_);
4615     MovprfxHelperScope guard(this, zd, pg, zn);
4616     frintm(zd, pg.Merging(), zn);
4617   }
Frintn(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4618   void Frintn(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4619     VIXL_ASSERT(allow_macro_instructions_);
4620     SingleEmissionCheckScope guard(this);
4621     frintn(zd, pg, zn);
4622   }
Frintn(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4623   void Frintn(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4624     VIXL_ASSERT(allow_macro_instructions_);
4625     MovprfxHelperScope guard(this, zd, pg, zn);
4626     frintn(zd, pg.Merging(), zn);
4627   }
Frintp(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4628   void Frintp(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4629     VIXL_ASSERT(allow_macro_instructions_);
4630     SingleEmissionCheckScope guard(this);
4631     frintp(zd, pg, zn);
4632   }
Frintp(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4633   void Frintp(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4634     VIXL_ASSERT(allow_macro_instructions_);
4635     MovprfxHelperScope guard(this, zd, pg, zn);
4636     frintp(zd, pg.Merging(), zn);
4637   }
Frintx(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4638   void Frintx(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4639     VIXL_ASSERT(allow_macro_instructions_);
4640     SingleEmissionCheckScope guard(this);
4641     frintx(zd, pg, zn);
4642   }
Frintx(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4643   void Frintx(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4644     VIXL_ASSERT(allow_macro_instructions_);
4645     MovprfxHelperScope guard(this, zd, pg, zn);
4646     frintx(zd, pg.Merging(), zn);
4647   }
Frintz(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4648   void Frintz(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4649     VIXL_ASSERT(allow_macro_instructions_);
4650     SingleEmissionCheckScope guard(this);
4651     frintz(zd, pg, zn);
4652   }
Frintz(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4653   void Frintz(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4654     VIXL_ASSERT(allow_macro_instructions_);
4655     MovprfxHelperScope guard(this, zd, pg, zn);
4656     frintz(zd, pg.Merging(), zn);
4657   }
Frsqrte(const ZRegister & zd,const ZRegister & zn)4658   void Frsqrte(const ZRegister& zd, const ZRegister& zn) {
4659     VIXL_ASSERT(allow_macro_instructions_);
4660     SingleEmissionCheckScope guard(this);
4661     frsqrte(zd, zn);
4662   }
Frsqrts(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4663   void Frsqrts(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4664     VIXL_ASSERT(allow_macro_instructions_);
4665     SingleEmissionCheckScope guard(this);
4666     frsqrts(zd, zn, zm);
4667   }
4668   void Fscale(const ZRegister& zd,
4669               const PRegisterM& pg,
4670               const ZRegister& zn,
4671               const ZRegister& zm);
Fsqrt(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)4672   void Fsqrt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
4673     VIXL_ASSERT(allow_macro_instructions_);
4674     SingleEmissionCheckScope guard(this);
4675     fsqrt(zd, pg, zn);
4676   }
Fsqrt(const ZRegister & zd,const PRegisterZ & pg,const ZRegister & zn)4677   void Fsqrt(const ZRegister& zd, const PRegisterZ& pg, const ZRegister& zn) {
4678     VIXL_ASSERT(allow_macro_instructions_);
4679     MovprfxHelperScope guard(this, zd, pg, zn);
4680     fsqrt(zd, pg.Merging(), zn);
4681   }
Fsub(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,double imm)4682   void Fsub(const ZRegister& zd,
4683             const PRegisterM& pg,
4684             const ZRegister& zn,
4685             double imm) {
4686     VIXL_ASSERT(allow_macro_instructions_);
4687     MovprfxHelperScope guard(this, zd, pg, zn);
4688     fsub(zd, pg, zd, imm);
4689   }
Fsub(const ZRegister & zd,const PRegisterM & pg,double imm,const ZRegister & zn)4690   void Fsub(const ZRegister& zd,
4691             const PRegisterM& pg,
4692             double imm,
4693             const ZRegister& zn) {
4694     VIXL_ASSERT(allow_macro_instructions_);
4695     MovprfxHelperScope guard(this, zd, pg, zn);
4696     fsubr(zd, pg, zd, imm);
4697   }
4698   void Fsub(const ZRegister& zd,
4699             const PRegisterM& pg,
4700             const ZRegister& zn,
4701             const ZRegister& zm);
Fsub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4702   void Fsub(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4703     VIXL_ASSERT(allow_macro_instructions_);
4704     SingleEmissionCheckScope guard(this);
4705     fsub(zd, zn, zm);
4706   }
4707   void Ftmad(const ZRegister& zd,
4708              const ZRegister& zn,
4709              const ZRegister& zm,
4710              int imm3);
Ftsmul(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4711   void Ftsmul(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4712     VIXL_ASSERT(allow_macro_instructions_);
4713     SingleEmissionCheckScope guard(this);
4714     ftsmul(zd, zn, zm);
4715   }
Ftssel(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)4716   void Ftssel(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
4717     VIXL_ASSERT(allow_macro_instructions_);
4718     SingleEmissionCheckScope guard(this);
4719     ftssel(zd, zn, zm);
4720   }
4721   void Incb(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
4722     VIXL_ASSERT(allow_macro_instructions_);
4723     SingleEmissionCheckScope guard(this);
4724     incb(rdn, pattern, multiplier);
4725   }
4726   void Incd(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
4727     VIXL_ASSERT(allow_macro_instructions_);
4728     SingleEmissionCheckScope guard(this);
4729     incd(rdn, pattern, multiplier);
4730   }
4731   void Incd(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
4732     VIXL_ASSERT(allow_macro_instructions_);
4733     SingleEmissionCheckScope guard(this);
4734     incd(zdn, pattern, multiplier);
4735   }
4736   void Inch(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
4737     VIXL_ASSERT(allow_macro_instructions_);
4738     SingleEmissionCheckScope guard(this);
4739     inch(rdn, pattern, multiplier);
4740   }
4741   void Inch(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
4742     VIXL_ASSERT(allow_macro_instructions_);
4743     SingleEmissionCheckScope guard(this);
4744     inch(zdn, pattern, multiplier);
4745   }
Incp(const Register & rdn,const PRegisterWithLaneSize & pg)4746   void Incp(const Register& rdn, const PRegisterWithLaneSize& pg) {
4747     VIXL_ASSERT(allow_macro_instructions_);
4748     SingleEmissionCheckScope guard(this);
4749     incp(rdn, pg);
4750   }
Incp(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)4751   void Incp(const ZRegister& zd, const PRegister& pg, const ZRegister& zn) {
4752     VIXL_ASSERT(allow_macro_instructions_);
4753     VIXL_ASSERT(AreSameFormat(zd, zn));
4754     // `incp` writes every lane, so use an unpredicated movprfx.
4755     MovprfxHelperScope guard(this, zd, zn);
4756     incp(zd, pg);
4757   }
Incp(const ZRegister & zdn,const PRegister & pg)4758   void Incp(const ZRegister& zdn, const PRegister& pg) { Incp(zdn, pg, zdn); }
4759   void Incw(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
4760     VIXL_ASSERT(allow_macro_instructions_);
4761     SingleEmissionCheckScope guard(this);
4762     incw(rdn, pattern, multiplier);
4763   }
4764   void Incw(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
4765     VIXL_ASSERT(allow_macro_instructions_);
4766     SingleEmissionCheckScope guard(this);
4767     incw(zdn, pattern, multiplier);
4768   }
4769   void Index(const ZRegister& zd, const Operand& start, const Operand& step);
Insr(const ZRegister & zdn,const Register & rm)4770   void Insr(const ZRegister& zdn, const Register& rm) {
4771     VIXL_ASSERT(allow_macro_instructions_);
4772     SingleEmissionCheckScope guard(this);
4773     insr(zdn, rm);
4774   }
Insr(const ZRegister & zdn,const VRegister & vm)4775   void Insr(const ZRegister& zdn, const VRegister& vm) {
4776     VIXL_ASSERT(allow_macro_instructions_);
4777     SingleEmissionCheckScope guard(this);
4778     insr(zdn, vm);
4779   }
4780   void Insr(const ZRegister& zdn, IntegerOperand imm);
Lasta(const Register & rd,const PRegister & pg,const ZRegister & zn)4781   void Lasta(const Register& rd, const PRegister& pg, const ZRegister& zn) {
4782     VIXL_ASSERT(allow_macro_instructions_);
4783     SingleEmissionCheckScope guard(this);
4784     lasta(rd, pg, zn);
4785   }
Lasta(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4786   void Lasta(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4787     VIXL_ASSERT(allow_macro_instructions_);
4788     SingleEmissionCheckScope guard(this);
4789     lasta(vd, pg, zn);
4790   }
Lastb(const Register & rd,const PRegister & pg,const ZRegister & zn)4791   void Lastb(const Register& rd, const PRegister& pg, const ZRegister& zn) {
4792     VIXL_ASSERT(allow_macro_instructions_);
4793     SingleEmissionCheckScope guard(this);
4794     lastb(rd, pg, zn);
4795   }
Lastb(const VRegister & vd,const PRegister & pg,const ZRegister & zn)4796   void Lastb(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
4797     VIXL_ASSERT(allow_macro_instructions_);
4798     SingleEmissionCheckScope guard(this);
4799     lastb(vd, pg, zn);
4800   }
4801   void Ld1b(const ZRegister& zt,
4802             const PRegisterZ& pg,
4803             const SVEMemOperand& addr);
4804   void Ld1h(const ZRegister& zt,
4805             const PRegisterZ& pg,
4806             const SVEMemOperand& addr);
4807   void Ld1w(const ZRegister& zt,
4808             const PRegisterZ& pg,
4809             const SVEMemOperand& addr);
4810   void Ld1d(const ZRegister& zt,
4811             const PRegisterZ& pg,
4812             const SVEMemOperand& addr);
Ld1rb(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4813   void Ld1rb(const ZRegister& zt,
4814              const PRegisterZ& pg,
4815              const SVEMemOperand& addr) {
4816     VIXL_ASSERT(allow_macro_instructions_);
4817     SVELoadBroadcastImmHelper(zt,
4818                               pg,
4819                               addr,
4820                               &MacroAssembler::ld1rb,
4821                               kBRegSizeInBytes);
4822   }
Ld1rh(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4823   void Ld1rh(const ZRegister& zt,
4824              const PRegisterZ& pg,
4825              const SVEMemOperand& addr) {
4826     VIXL_ASSERT(allow_macro_instructions_);
4827     SVELoadBroadcastImmHelper(zt,
4828                               pg,
4829                               addr,
4830                               &MacroAssembler::ld1rh,
4831                               kHRegSizeInBytes);
4832   }
Ld1rw(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4833   void Ld1rw(const ZRegister& zt,
4834              const PRegisterZ& pg,
4835              const SVEMemOperand& addr) {
4836     VIXL_ASSERT(allow_macro_instructions_);
4837     SVELoadBroadcastImmHelper(zt,
4838                               pg,
4839                               addr,
4840                               &MacroAssembler::ld1rw,
4841                               kSRegSizeInBytes);
4842   }
Ld1rd(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4843   void Ld1rd(const ZRegister& zt,
4844              const PRegisterZ& pg,
4845              const SVEMemOperand& addr) {
4846     VIXL_ASSERT(allow_macro_instructions_);
4847     SVELoadBroadcastImmHelper(zt,
4848                               pg,
4849                               addr,
4850                               &MacroAssembler::ld1rd,
4851                               kDRegSizeInBytes);
4852   }
4853   void Ld1rqb(const ZRegister& zt,
4854               const PRegisterZ& pg,
4855               const SVEMemOperand& addr);
4856   void Ld1rqd(const ZRegister& zt,
4857               const PRegisterZ& pg,
4858               const SVEMemOperand& addr);
4859   void Ld1rqh(const ZRegister& zt,
4860               const PRegisterZ& pg,
4861               const SVEMemOperand& addr);
4862   void Ld1rqw(const ZRegister& zt,
4863               const PRegisterZ& pg,
4864               const SVEMemOperand& addr);
Ld1rsb(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4865   void Ld1rsb(const ZRegister& zt,
4866               const PRegisterZ& pg,
4867               const SVEMemOperand& addr) {
4868     VIXL_ASSERT(allow_macro_instructions_);
4869     SVELoadBroadcastImmHelper(zt,
4870                               pg,
4871                               addr,
4872                               &MacroAssembler::ld1rsb,
4873                               kBRegSizeInBytes);
4874   }
Ld1rsh(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4875   void Ld1rsh(const ZRegister& zt,
4876               const PRegisterZ& pg,
4877               const SVEMemOperand& addr) {
4878     VIXL_ASSERT(allow_macro_instructions_);
4879     SVELoadBroadcastImmHelper(zt,
4880                               pg,
4881                               addr,
4882                               &MacroAssembler::ld1rsh,
4883                               kHRegSizeInBytes);
4884   }
Ld1rsw(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)4885   void Ld1rsw(const ZRegister& zt,
4886               const PRegisterZ& pg,
4887               const SVEMemOperand& addr) {
4888     VIXL_ASSERT(allow_macro_instructions_);
4889     SVELoadBroadcastImmHelper(zt,
4890                               pg,
4891                               addr,
4892                               &MacroAssembler::ld1rsw,
4893                               kSRegSizeInBytes);
4894   }
4895   void Ld1sb(const ZRegister& zt,
4896              const PRegisterZ& pg,
4897              const SVEMemOperand& addr);
4898   void Ld1sh(const ZRegister& zt,
4899              const PRegisterZ& pg,
4900              const SVEMemOperand& addr);
4901   void Ld1sw(const ZRegister& zt,
4902              const PRegisterZ& pg,
4903              const SVEMemOperand& addr);
Ld2b(const ZRegister & zt1,const ZRegister & zt2,const PRegisterZ & pg,const SVEMemOperand & addr)4904   void Ld2b(const ZRegister& zt1,
4905             const ZRegister& zt2,
4906             const PRegisterZ& pg,
4907             const SVEMemOperand& addr) {
4908     VIXL_ASSERT(allow_macro_instructions_);
4909     SingleEmissionCheckScope guard(this);
4910     ld2b(zt1, zt2, pg, addr);
4911   }
Ld2h(const ZRegister & zt1,const ZRegister & zt2,const PRegisterZ & pg,const SVEMemOperand & addr)4912   void Ld2h(const ZRegister& zt1,
4913             const ZRegister& zt2,
4914             const PRegisterZ& pg,
4915             const SVEMemOperand& addr) {
4916     VIXL_ASSERT(allow_macro_instructions_);
4917     SingleEmissionCheckScope guard(this);
4918     ld2h(zt1, zt2, pg, addr);
4919   }
Ld2w(const ZRegister & zt1,const ZRegister & zt2,const PRegisterZ & pg,const SVEMemOperand & addr)4920   void Ld2w(const ZRegister& zt1,
4921             const ZRegister& zt2,
4922             const PRegisterZ& pg,
4923             const SVEMemOperand& addr) {
4924     VIXL_ASSERT(allow_macro_instructions_);
4925     SingleEmissionCheckScope guard(this);
4926     ld2w(zt1, zt2, pg, addr);
4927   }
Ld2d(const ZRegister & zt1,const ZRegister & zt2,const PRegisterZ & pg,const SVEMemOperand & addr)4928   void Ld2d(const ZRegister& zt1,
4929             const ZRegister& zt2,
4930             const PRegisterZ& pg,
4931             const SVEMemOperand& addr) {
4932     VIXL_ASSERT(allow_macro_instructions_);
4933     SingleEmissionCheckScope guard(this);
4934     ld2d(zt1, zt2, pg, addr);
4935   }
Ld3b(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegisterZ & pg,const SVEMemOperand & addr)4936   void Ld3b(const ZRegister& zt1,
4937             const ZRegister& zt2,
4938             const ZRegister& zt3,
4939             const PRegisterZ& pg,
4940             const SVEMemOperand& addr) {
4941     VIXL_ASSERT(allow_macro_instructions_);
4942     SingleEmissionCheckScope guard(this);
4943     ld3b(zt1, zt2, zt3, pg, addr);
4944   }
Ld3h(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegisterZ & pg,const SVEMemOperand & addr)4945   void Ld3h(const ZRegister& zt1,
4946             const ZRegister& zt2,
4947             const ZRegister& zt3,
4948             const PRegisterZ& pg,
4949             const SVEMemOperand& addr) {
4950     VIXL_ASSERT(allow_macro_instructions_);
4951     SingleEmissionCheckScope guard(this);
4952     ld3h(zt1, zt2, zt3, pg, addr);
4953   }
Ld3w(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegisterZ & pg,const SVEMemOperand & addr)4954   void Ld3w(const ZRegister& zt1,
4955             const ZRegister& zt2,
4956             const ZRegister& zt3,
4957             const PRegisterZ& pg,
4958             const SVEMemOperand& addr) {
4959     VIXL_ASSERT(allow_macro_instructions_);
4960     SingleEmissionCheckScope guard(this);
4961     ld3w(zt1, zt2, zt3, pg, addr);
4962   }
Ld3d(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegisterZ & pg,const SVEMemOperand & addr)4963   void Ld3d(const ZRegister& zt1,
4964             const ZRegister& zt2,
4965             const ZRegister& zt3,
4966             const PRegisterZ& pg,
4967             const SVEMemOperand& addr) {
4968     VIXL_ASSERT(allow_macro_instructions_);
4969     SingleEmissionCheckScope guard(this);
4970     ld3d(zt1, zt2, zt3, pg, addr);
4971   }
Ld4b(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegisterZ & pg,const SVEMemOperand & addr)4972   void Ld4b(const ZRegister& zt1,
4973             const ZRegister& zt2,
4974             const ZRegister& zt3,
4975             const ZRegister& zt4,
4976             const PRegisterZ& pg,
4977             const SVEMemOperand& addr) {
4978     VIXL_ASSERT(allow_macro_instructions_);
4979     SingleEmissionCheckScope guard(this);
4980     ld4b(zt1, zt2, zt3, zt4, pg, addr);
4981   }
Ld4h(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegisterZ & pg,const SVEMemOperand & addr)4982   void Ld4h(const ZRegister& zt1,
4983             const ZRegister& zt2,
4984             const ZRegister& zt3,
4985             const ZRegister& zt4,
4986             const PRegisterZ& pg,
4987             const SVEMemOperand& addr) {
4988     VIXL_ASSERT(allow_macro_instructions_);
4989     SingleEmissionCheckScope guard(this);
4990     ld4h(zt1, zt2, zt3, zt4, pg, addr);
4991   }
Ld4w(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegisterZ & pg,const SVEMemOperand & addr)4992   void Ld4w(const ZRegister& zt1,
4993             const ZRegister& zt2,
4994             const ZRegister& zt3,
4995             const ZRegister& zt4,
4996             const PRegisterZ& pg,
4997             const SVEMemOperand& addr) {
4998     VIXL_ASSERT(allow_macro_instructions_);
4999     SingleEmissionCheckScope guard(this);
5000     ld4w(zt1, zt2, zt3, zt4, pg, addr);
5001   }
Ld4d(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegisterZ & pg,const SVEMemOperand & addr)5002   void Ld4d(const ZRegister& zt1,
5003             const ZRegister& zt2,
5004             const ZRegister& zt3,
5005             const ZRegister& zt4,
5006             const PRegisterZ& pg,
5007             const SVEMemOperand& addr) {
5008     VIXL_ASSERT(allow_macro_instructions_);
5009     SingleEmissionCheckScope guard(this);
5010     ld4d(zt1, zt2, zt3, zt4, pg, addr);
5011   }
5012   void Ldff1b(const ZRegister& zt,
5013               const PRegisterZ& pg,
5014               const SVEMemOperand& addr);
5015   void Ldff1h(const ZRegister& zt,
5016               const PRegisterZ& pg,
5017               const SVEMemOperand& addr);
5018   void Ldff1w(const ZRegister& zt,
5019               const PRegisterZ& pg,
5020               const SVEMemOperand& addr);
5021   void Ldff1d(const ZRegister& zt,
5022               const PRegisterZ& pg,
5023               const SVEMemOperand& addr);
5024   void Ldff1sb(const ZRegister& zt,
5025                const PRegisterZ& pg,
5026                const SVEMemOperand& addr);
5027   void Ldff1sh(const ZRegister& zt,
5028                const PRegisterZ& pg,
5029                const SVEMemOperand& addr);
5030   void Ldff1sw(const ZRegister& zt,
5031                const PRegisterZ& pg,
5032                const SVEMemOperand& addr);
Ldff1b(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)5033   void Ldff1b(const ZRegister& zt,
5034               const PRegisterZ& pg,
5035               const Register& xn,
5036               const ZRegister& zm) {
5037     VIXL_ASSERT(allow_macro_instructions_);
5038     SingleEmissionCheckScope guard(this);
5039     ldff1b(zt, pg, xn, zm);
5040   }
Ldff1b(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)5041   void Ldff1b(const ZRegister& zt,
5042               const PRegisterZ& pg,
5043               const ZRegister& zn,
5044               int imm5) {
5045     VIXL_ASSERT(allow_macro_instructions_);
5046     SingleEmissionCheckScope guard(this);
5047     ldff1b(zt, pg, zn, imm5);
5048   }
Ldff1d(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)5049   void Ldff1d(const ZRegister& zt,
5050               const PRegisterZ& pg,
5051               const Register& xn,
5052               const ZRegister& zm) {
5053     VIXL_ASSERT(allow_macro_instructions_);
5054     SingleEmissionCheckScope guard(this);
5055     ldff1d(zt, pg, xn, zm);
5056   }
Ldff1d(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)5057   void Ldff1d(const ZRegister& zt,
5058               const PRegisterZ& pg,
5059               const ZRegister& zn,
5060               int imm5) {
5061     VIXL_ASSERT(allow_macro_instructions_);
5062     SingleEmissionCheckScope guard(this);
5063     ldff1d(zt, pg, zn, imm5);
5064   }
Ldff1h(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)5065   void Ldff1h(const ZRegister& zt,
5066               const PRegisterZ& pg,
5067               const Register& xn,
5068               const ZRegister& zm) {
5069     VIXL_ASSERT(allow_macro_instructions_);
5070     SingleEmissionCheckScope guard(this);
5071     ldff1h(zt, pg, xn, zm);
5072   }
Ldff1h(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)5073   void Ldff1h(const ZRegister& zt,
5074               const PRegisterZ& pg,
5075               const ZRegister& zn,
5076               int imm5) {
5077     VIXL_ASSERT(allow_macro_instructions_);
5078     SingleEmissionCheckScope guard(this);
5079     ldff1h(zt, pg, zn, imm5);
5080   }
Ldff1sb(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)5081   void Ldff1sb(const ZRegister& zt,
5082                const PRegisterZ& pg,
5083                const Register& xn,
5084                const ZRegister& zm) {
5085     VIXL_ASSERT(allow_macro_instructions_);
5086     SingleEmissionCheckScope guard(this);
5087     ldff1sb(zt, pg, xn, zm);
5088   }
Ldff1sb(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)5089   void Ldff1sb(const ZRegister& zt,
5090                const PRegisterZ& pg,
5091                const ZRegister& zn,
5092                int imm5) {
5093     VIXL_ASSERT(allow_macro_instructions_);
5094     SingleEmissionCheckScope guard(this);
5095     ldff1sb(zt, pg, zn, imm5);
5096   }
Ldff1sh(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)5097   void Ldff1sh(const ZRegister& zt,
5098                const PRegisterZ& pg,
5099                const Register& xn,
5100                const ZRegister& zm) {
5101     VIXL_ASSERT(allow_macro_instructions_);
5102     SingleEmissionCheckScope guard(this);
5103     ldff1sh(zt, pg, xn, zm);
5104   }
Ldff1sh(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)5105   void Ldff1sh(const ZRegister& zt,
5106                const PRegisterZ& pg,
5107                const ZRegister& zn,
5108                int imm5) {
5109     VIXL_ASSERT(allow_macro_instructions_);
5110     SingleEmissionCheckScope guard(this);
5111     ldff1sh(zt, pg, zn, imm5);
5112   }
Ldff1sw(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)5113   void Ldff1sw(const ZRegister& zt,
5114                const PRegisterZ& pg,
5115                const Register& xn,
5116                const ZRegister& zm) {
5117     VIXL_ASSERT(allow_macro_instructions_);
5118     SingleEmissionCheckScope guard(this);
5119     ldff1sw(zt, pg, xn, zm);
5120   }
Ldff1sw(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)5121   void Ldff1sw(const ZRegister& zt,
5122                const PRegisterZ& pg,
5123                const ZRegister& zn,
5124                int imm5) {
5125     VIXL_ASSERT(allow_macro_instructions_);
5126     SingleEmissionCheckScope guard(this);
5127     ldff1sw(zt, pg, zn, imm5);
5128   }
Ldff1w(const ZRegister & zt,const PRegisterZ & pg,const Register & xn,const ZRegister & zm)5129   void Ldff1w(const ZRegister& zt,
5130               const PRegisterZ& pg,
5131               const Register& xn,
5132               const ZRegister& zm) {
5133     VIXL_ASSERT(allow_macro_instructions_);
5134     SingleEmissionCheckScope guard(this);
5135     ldff1w(zt, pg, xn, zm);
5136   }
Ldff1w(const ZRegister & zt,const PRegisterZ & pg,const ZRegister & zn,int imm5)5137   void Ldff1w(const ZRegister& zt,
5138               const PRegisterZ& pg,
5139               const ZRegister& zn,
5140               int imm5) {
5141     VIXL_ASSERT(allow_macro_instructions_);
5142     SingleEmissionCheckScope guard(this);
5143     ldff1w(zt, pg, zn, imm5);
5144   }
Ldnf1b(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5145   void Ldnf1b(const ZRegister& zt,
5146               const PRegisterZ& pg,
5147               const SVEMemOperand& addr) {
5148     VIXL_ASSERT(allow_macro_instructions_);
5149     SingleEmissionCheckScope guard(this);
5150     ldnf1b(zt, pg, addr);
5151   }
Ldnf1d(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5152   void Ldnf1d(const ZRegister& zt,
5153               const PRegisterZ& pg,
5154               const SVEMemOperand& addr) {
5155     VIXL_ASSERT(allow_macro_instructions_);
5156     SingleEmissionCheckScope guard(this);
5157     ldnf1d(zt, pg, addr);
5158   }
Ldnf1h(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5159   void Ldnf1h(const ZRegister& zt,
5160               const PRegisterZ& pg,
5161               const SVEMemOperand& addr) {
5162     VIXL_ASSERT(allow_macro_instructions_);
5163     SingleEmissionCheckScope guard(this);
5164     ldnf1h(zt, pg, addr);
5165   }
Ldnf1sb(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5166   void Ldnf1sb(const ZRegister& zt,
5167                const PRegisterZ& pg,
5168                const SVEMemOperand& addr) {
5169     VIXL_ASSERT(allow_macro_instructions_);
5170     SingleEmissionCheckScope guard(this);
5171     ldnf1sb(zt, pg, addr);
5172   }
Ldnf1sh(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5173   void Ldnf1sh(const ZRegister& zt,
5174                const PRegisterZ& pg,
5175                const SVEMemOperand& addr) {
5176     VIXL_ASSERT(allow_macro_instructions_);
5177     SingleEmissionCheckScope guard(this);
5178     ldnf1sh(zt, pg, addr);
5179   }
Ldnf1sw(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5180   void Ldnf1sw(const ZRegister& zt,
5181                const PRegisterZ& pg,
5182                const SVEMemOperand& addr) {
5183     VIXL_ASSERT(allow_macro_instructions_);
5184     SingleEmissionCheckScope guard(this);
5185     ldnf1sw(zt, pg, addr);
5186   }
Ldnf1w(const ZRegister & zt,const PRegisterZ & pg,const SVEMemOperand & addr)5187   void Ldnf1w(const ZRegister& zt,
5188               const PRegisterZ& pg,
5189               const SVEMemOperand& addr) {
5190     VIXL_ASSERT(allow_macro_instructions_);
5191     SingleEmissionCheckScope guard(this);
5192     ldnf1w(zt, pg, addr);
5193   }
5194   void Ldnt1b(const ZRegister& zt,
5195               const PRegisterZ& pg,
5196               const SVEMemOperand& addr);
5197   void Ldnt1d(const ZRegister& zt,
5198               const PRegisterZ& pg,
5199               const SVEMemOperand& addr);
5200   void Ldnt1h(const ZRegister& zt,
5201               const PRegisterZ& pg,
5202               const SVEMemOperand& addr);
5203   void Ldnt1w(const ZRegister& zt,
5204               const PRegisterZ& pg,
5205               const SVEMemOperand& addr);
Ldr(const CPURegister & rt,const SVEMemOperand & addr)5206   void Ldr(const CPURegister& rt, const SVEMemOperand& addr) {
5207     VIXL_ASSERT(allow_macro_instructions_);
5208     SVELoadStoreScalarImmHelper(rt, addr, &MacroAssembler::ldr);
5209   }
Lsl(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)5210   void Lsl(const ZRegister& zd,
5211            const PRegisterM& pg,
5212            const ZRegister& zn,
5213            int shift) {
5214     VIXL_ASSERT(allow_macro_instructions_);
5215     MovprfxHelperScope guard(this, zd, pg, zn);
5216     lsl(zd, pg, zd, shift);
5217   }
5218   void Lsl(const ZRegister& zd,
5219            const PRegisterM& pg,
5220            const ZRegister& zn,
5221            const ZRegister& zm);
Lsl(const ZRegister & zd,const ZRegister & zn,int shift)5222   void Lsl(const ZRegister& zd, const ZRegister& zn, int shift) {
5223     VIXL_ASSERT(allow_macro_instructions_);
5224     SingleEmissionCheckScope guard(this);
5225     lsl(zd, zn, shift);
5226   }
Lsl(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5227   void Lsl(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
5228     VIXL_ASSERT(allow_macro_instructions_);
5229     SingleEmissionCheckScope guard(this);
5230     lsl(zd, zn, zm);
5231   }
Lsr(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn,int shift)5232   void Lsr(const ZRegister& zd,
5233            const PRegisterM& pg,
5234            const ZRegister& zn,
5235            int shift) {
5236     VIXL_ASSERT(allow_macro_instructions_);
5237     MovprfxHelperScope guard(this, zd, pg, zn);
5238     lsr(zd, pg, zd, shift);
5239   }
5240   void Lsr(const ZRegister& zd,
5241            const PRegisterM& pg,
5242            const ZRegister& zn,
5243            const ZRegister& zm);
Lsr(const ZRegister & zd,const ZRegister & zn,int shift)5244   void Lsr(const ZRegister& zd, const ZRegister& zn, int shift) {
5245     VIXL_ASSERT(allow_macro_instructions_);
5246     SingleEmissionCheckScope guard(this);
5247     lsr(zd, zn, shift);
5248   }
Lsr(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5249   void Lsr(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
5250     VIXL_ASSERT(allow_macro_instructions_);
5251     SingleEmissionCheckScope guard(this);
5252     lsr(zd, zn, zm);
5253   }
Mov(const PRegister & pd,const PRegister & pn)5254   void Mov(const PRegister& pd, const PRegister& pn) {
5255     VIXL_ASSERT(allow_macro_instructions_);
5256     SingleEmissionCheckScope guard(this);
5257     mov(pd.VnB(), pn.VnB());
5258   }
Mov(const PRegisterWithLaneSize & pd,const PRegisterM & pg,const PRegisterWithLaneSize & pn)5259   void Mov(const PRegisterWithLaneSize& pd,
5260            const PRegisterM& pg,
5261            const PRegisterWithLaneSize& pn) {
5262     VIXL_ASSERT(allow_macro_instructions_);
5263     SingleEmissionCheckScope guard(this);
5264     mov(pd, pg, pn);
5265   }
Mov(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)5266   void Mov(const PRegisterWithLaneSize& pd,
5267            const PRegisterZ& pg,
5268            const PRegisterWithLaneSize& pn) {
5269     VIXL_ASSERT(allow_macro_instructions_);
5270     SingleEmissionCheckScope guard(this);
5271     mov(pd, pg, pn);
5272   }
Mov(const ZRegister & zd,const Register & xn)5273   void Mov(const ZRegister& zd, const Register& xn) {
5274     VIXL_ASSERT(allow_macro_instructions_);
5275     SingleEmissionCheckScope guard(this);
5276     mov(zd, xn);
5277   }
5278 
Mov(const ZRegister & zd,const VRegister & vn)5279   void Mov(const ZRegister& zd, const VRegister& vn) {
5280     VIXL_ASSERT(allow_macro_instructions_);
5281     SingleEmissionCheckScope guard(this);
5282     mov(zd, vn);
5283   }
5284 
Mov(const ZRegister & zd,const ZRegister & zn)5285   void Mov(const ZRegister& zd, const ZRegister& zn) {
5286     VIXL_ASSERT(allow_macro_instructions_);
5287     SingleEmissionCheckScope guard(this);
5288     mov(zd, zn);
5289   }
Mov(const ZRegister & zd,const ZRegister & zn,unsigned index)5290   void Mov(const ZRegister& zd, const ZRegister& zn, unsigned index) {
5291     VIXL_ASSERT(allow_macro_instructions_);
5292     SingleEmissionCheckScope guard(this);
5293     mov(zd, zn, index);
5294   }
Mov(const ZRegister & zd,const PRegister & pg,IntegerOperand imm)5295   void Mov(const ZRegister& zd, const PRegister& pg, IntegerOperand imm) {
5296     VIXL_ASSERT(allow_macro_instructions_);
5297     Cpy(zd, pg, imm);
5298   }
5299   // TODO: support zeroing predicated moves using movprfx.
Mov(const ZRegister & zd,const PRegisterM & pg,const Register & rn)5300   void Mov(const ZRegister& zd, const PRegisterM& pg, const Register& rn) {
5301     VIXL_ASSERT(allow_macro_instructions_);
5302     SingleEmissionCheckScope guard(this);
5303     mov(zd, pg, rn);
5304   }
Mov(const ZRegister & zd,const PRegisterM & pg,const VRegister & vn)5305   void Mov(const ZRegister& zd, const PRegisterM& pg, const VRegister& vn) {
5306     VIXL_ASSERT(allow_macro_instructions_);
5307     SingleEmissionCheckScope guard(this);
5308     mov(zd, pg, vn);
5309   }
Mov(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5310   void Mov(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5311     VIXL_ASSERT(allow_macro_instructions_);
5312     SingleEmissionCheckScope guard(this);
5313     mov(zd, pg, zn);
5314   }
Mov(const ZRegister & zd,IntegerOperand imm)5315   void Mov(const ZRegister& zd, IntegerOperand imm) {
5316     VIXL_ASSERT(allow_macro_instructions_);
5317     Dup(zd, imm);
5318   }
Movs(const PRegister & pd,const PRegister & pn)5319   void Movs(const PRegister& pd, const PRegister& pn) {
5320     VIXL_ASSERT(allow_macro_instructions_);
5321     SingleEmissionCheckScope guard(this);
5322     movs(pd, pn);
5323   }
Movs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)5324   void Movs(const PRegisterWithLaneSize& pd,
5325             const PRegisterZ& pg,
5326             const PRegisterWithLaneSize& pn) {
5327     VIXL_ASSERT(allow_macro_instructions_);
5328     SingleEmissionCheckScope guard(this);
5329     movs(pd, pg, pn);
5330   }
5331   // zd = za + (zn * zm)
5332   void Mla(const ZRegister& zd,
5333            const PRegisterM& pg,
5334            const ZRegister& za,
5335            const ZRegister& zn,
5336            const ZRegister& zm);
5337   // zd = za - (zn * zm)
5338   void Mls(const ZRegister& zd,
5339            const PRegisterM& pg,
5340            const ZRegister& za,
5341            const ZRegister& zn,
5342            const ZRegister& zm);
5343   void Mul(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm);
Nand(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5344   void Nand(const PRegisterWithLaneSize& pd,
5345             const PRegisterZ& pg,
5346             const PRegisterWithLaneSize& pn,
5347             const PRegisterWithLaneSize& pm) {
5348     VIXL_ASSERT(allow_macro_instructions_);
5349     SingleEmissionCheckScope guard(this);
5350     nand(pd, pg, pn, pm);
5351   }
Nands(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5352   void Nands(const PRegisterWithLaneSize& pd,
5353              const PRegisterZ& pg,
5354              const PRegisterWithLaneSize& pn,
5355              const PRegisterWithLaneSize& pm) {
5356     VIXL_ASSERT(allow_macro_instructions_);
5357     SingleEmissionCheckScope guard(this);
5358     nands(pd, pg, pn, pm);
5359   }
5360   // There is no instruction with this form, but we can implement it using
5361   // `subr`.
Neg(const ZRegister & zd,const ZRegister & zn)5362   void Neg(const ZRegister& zd, const ZRegister& zn) {
5363     VIXL_ASSERT(allow_macro_instructions_);
5364     MovprfxHelperScope guard(this, zd, zn);
5365     subr(zd, zd, 0);
5366   }
Neg(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5367   void Neg(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5368     VIXL_ASSERT(allow_macro_instructions_);
5369     SingleEmissionCheckScope guard(this);
5370     neg(zd, pg, zn);
5371   }
Nor(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5372   void Nor(const PRegisterWithLaneSize& pd,
5373            const PRegisterZ& pg,
5374            const PRegisterWithLaneSize& pn,
5375            const PRegisterWithLaneSize& pm) {
5376     VIXL_ASSERT(allow_macro_instructions_);
5377     SingleEmissionCheckScope guard(this);
5378     nor(pd, pg, pn, pm);
5379   }
Nors(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5380   void Nors(const PRegisterWithLaneSize& pd,
5381             const PRegisterZ& pg,
5382             const PRegisterWithLaneSize& pn,
5383             const PRegisterWithLaneSize& pm) {
5384     VIXL_ASSERT(allow_macro_instructions_);
5385     SingleEmissionCheckScope guard(this);
5386     nors(pd, pg, pn, pm);
5387   }
Not(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)5388   void Not(const PRegisterWithLaneSize& pd,
5389            const PRegisterZ& pg,
5390            const PRegisterWithLaneSize& pn) {
5391     VIXL_ASSERT(allow_macro_instructions_);
5392     SingleEmissionCheckScope guard(this);
5393     not_(pd, pg, pn);
5394   }
Not(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5395   void Not(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5396     VIXL_ASSERT(allow_macro_instructions_);
5397     SingleEmissionCheckScope guard(this);
5398     not_(zd, pg, zn);
5399   }
Nots(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn)5400   void Nots(const PRegisterWithLaneSize& pd,
5401             const PRegisterZ& pg,
5402             const PRegisterWithLaneSize& pn) {
5403     VIXL_ASSERT(allow_macro_instructions_);
5404     SingleEmissionCheckScope guard(this);
5405     nots(pd, pg, pn);
5406   }
Orn(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5407   void Orn(const PRegisterWithLaneSize& pd,
5408            const PRegisterZ& pg,
5409            const PRegisterWithLaneSize& pn,
5410            const PRegisterWithLaneSize& pm) {
5411     VIXL_ASSERT(allow_macro_instructions_);
5412     SingleEmissionCheckScope guard(this);
5413     orn(pd, pg, pn, pm);
5414   }
Orn(const ZRegister & zd,const ZRegister & zn,uint64_t imm)5415   void Orn(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
5416     VIXL_ASSERT(allow_macro_instructions_);
5417     SingleEmissionCheckScope guard(this);
5418     if (IsImmLogical(imm, zd.GetLaneSizeInBits())) {
5419       orn(zd, zn, imm);
5420     } else {
5421       // TODO: Synthesise the immediate once 'Mov' is implemented.
5422       VIXL_UNIMPLEMENTED();
5423     }
5424   }
Orns(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5425   void Orns(const PRegisterWithLaneSize& pd,
5426             const PRegisterZ& pg,
5427             const PRegisterWithLaneSize& pn,
5428             const PRegisterWithLaneSize& pm) {
5429     VIXL_ASSERT(allow_macro_instructions_);
5430     SingleEmissionCheckScope guard(this);
5431     orns(pd, pg, pn, pm);
5432   }
Orr(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5433   void Orr(const PRegisterWithLaneSize& pd,
5434            const PRegisterZ& pg,
5435            const PRegisterWithLaneSize& pn,
5436            const PRegisterWithLaneSize& pm) {
5437     VIXL_ASSERT(allow_macro_instructions_);
5438     SingleEmissionCheckScope guard(this);
5439     orr(pd, pg, pn, pm);
5440   }
Orr(const ZRegister & zd,const ZRegister & zn,uint64_t imm)5441   void Orr(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {
5442     VIXL_ASSERT(allow_macro_instructions_);
5443     SingleEmissionCheckScope guard(this);
5444     if (IsImmLogical(imm, zd.GetLaneSizeInBits())) {
5445       orr(zd, zn, imm);
5446     } else {
5447       // TODO: Synthesise the immediate once 'Mov' is implemented.
5448       VIXL_UNIMPLEMENTED();
5449     }
5450   }
Orr(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5451   void Orr(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
5452     VIXL_ASSERT(allow_macro_instructions_);
5453     VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));
5454     SingleEmissionCheckScope guard(this);
5455     orr(zd.VnD(), zn.VnD(), zm.VnD());
5456   }
Orrs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5457   void Orrs(const PRegisterWithLaneSize& pd,
5458             const PRegisterZ& pg,
5459             const PRegisterWithLaneSize& pn,
5460             const PRegisterWithLaneSize& pm) {
5461     VIXL_ASSERT(allow_macro_instructions_);
5462     SingleEmissionCheckScope guard(this);
5463     orrs(pd, pg, pn, pm);
5464   }
Orv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)5465   void Orv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
5466     VIXL_ASSERT(allow_macro_instructions_);
5467     SingleEmissionCheckScope guard(this);
5468     orv(vd, pg, zn);
5469   }
Pfalse(const PRegister & pd)5470   void Pfalse(const PRegister& pd) {
5471     VIXL_ASSERT(allow_macro_instructions_);
5472     VIXL_ASSERT(pd.IsUnqualified());
5473     SingleEmissionCheckScope guard(this);
5474     // No matter what the lane size is, overall this operation just writes zeros
5475     // throughout the register.
5476     pfalse(pd.VnB());
5477   }
5478   void Pfirst(const PRegisterWithLaneSize& pd,
5479               const PRegister& pg,
5480               const PRegisterWithLaneSize& pn);
5481   void Pnext(const PRegisterWithLaneSize& pd,
5482              const PRegister& pg,
5483              const PRegisterWithLaneSize& pn);
Prfb(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand addr)5484   void Prfb(PrefetchOperation prfop,
5485             const PRegister& pg,
5486             const SVEMemOperand addr) {
5487     VIXL_ASSERT(allow_macro_instructions_);
5488     SingleEmissionCheckScope guard(this);
5489     prfb(prfop, pg, addr);
5490   }
Prfh(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand addr)5491   void Prfh(PrefetchOperation prfop,
5492             const PRegister& pg,
5493             const SVEMemOperand addr) {
5494     VIXL_ASSERT(allow_macro_instructions_);
5495     SingleEmissionCheckScope guard(this);
5496     prfh(prfop, pg, addr);
5497   }
Prfw(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand addr)5498   void Prfw(PrefetchOperation prfop,
5499             const PRegister& pg,
5500             const SVEMemOperand addr) {
5501     VIXL_ASSERT(allow_macro_instructions_);
5502     SingleEmissionCheckScope guard(this);
5503     prfw(prfop, pg, addr);
5504   }
Prfd(PrefetchOperation prfop,const PRegister & pg,const SVEMemOperand addr)5505   void Prfd(PrefetchOperation prfop,
5506             const PRegister& pg,
5507             const SVEMemOperand addr) {
5508     VIXL_ASSERT(allow_macro_instructions_);
5509     SingleEmissionCheckScope guard(this);
5510     prfd(prfop, pg, addr);
5511   }
Ptest(const PRegister & pg,const PRegisterWithLaneSize & pn)5512   void Ptest(const PRegister& pg, const PRegisterWithLaneSize& pn) {
5513     VIXL_ASSERT(allow_macro_instructions_);
5514     SingleEmissionCheckScope guard(this);
5515     ptest(pg, pn);
5516   }
5517   void Ptrue(const PRegisterWithLaneSize& pd,
5518              SVEPredicateConstraint pattern,
5519              FlagsUpdate s);
5520   void Ptrue(const PRegisterWithLaneSize& pd,
5521              SVEPredicateConstraint pattern = SVE_ALL) {
5522     VIXL_ASSERT(allow_macro_instructions_);
5523     SingleEmissionCheckScope guard(this);
5524     ptrue(pd, pattern);
5525   }
5526   void Ptrues(const PRegisterWithLaneSize& pd,
5527               SVEPredicateConstraint pattern = SVE_ALL) {
5528     VIXL_ASSERT(allow_macro_instructions_);
5529     SingleEmissionCheckScope guard(this);
5530     ptrues(pd, pattern);
5531   }
Punpkhi(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn)5532   void Punpkhi(const PRegisterWithLaneSize& pd,
5533                const PRegisterWithLaneSize& pn) {
5534     VIXL_ASSERT(allow_macro_instructions_);
5535     SingleEmissionCheckScope guard(this);
5536     punpkhi(pd, pn);
5537   }
Punpklo(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn)5538   void Punpklo(const PRegisterWithLaneSize& pd,
5539                const PRegisterWithLaneSize& pn) {
5540     VIXL_ASSERT(allow_macro_instructions_);
5541     SingleEmissionCheckScope guard(this);
5542     punpklo(pd, pn);
5543   }
Rbit(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5544   void Rbit(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5545     VIXL_ASSERT(allow_macro_instructions_);
5546     SingleEmissionCheckScope guard(this);
5547     rbit(zd, pg, zn);
5548   }
Rdffr(const PRegister & pd)5549   void Rdffr(const PRegister& pd) {
5550     VIXL_ASSERT(allow_macro_instructions_);
5551     // Although this is essentially just a move, it writes every bit and so can
5552     // only support b-sized lane because other lane sizes would simplicity clear
5553     // bits in `pd`.
5554     VIXL_ASSERT(!pd.HasLaneSize() || pd.IsLaneSizeB());
5555     VIXL_ASSERT(pd.IsUnqualified());
5556     SingleEmissionCheckScope guard(this);
5557     rdffr(pd.VnB());
5558   }
Rdffr(const PRegisterWithLaneSize & pd,const PRegisterZ & pg)5559   void Rdffr(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {
5560     VIXL_ASSERT(allow_macro_instructions_);
5561     SingleEmissionCheckScope guard(this);
5562     rdffr(pd, pg);
5563   }
Rdffrs(const PRegisterWithLaneSize & pd,const PRegisterZ & pg)5564   void Rdffrs(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {
5565     VIXL_ASSERT(allow_macro_instructions_);
5566     SingleEmissionCheckScope guard(this);
5567     rdffrs(pd, pg);
5568   }
5569   // Note that there is no `rdpl` instruction, but this macro emulates it (for
5570   // symmetry with `Rdvl`).
Rdpl(const Register & xd,int64_t multiplier)5571   void Rdpl(const Register& xd, int64_t multiplier) {
5572     VIXL_ASSERT(allow_macro_instructions_);
5573     Addpl(xd, xzr, multiplier);
5574   }
Rdvl(const Register & xd,int64_t multiplier)5575   void Rdvl(const Register& xd, int64_t multiplier) {
5576     VIXL_ASSERT(allow_macro_instructions_);
5577     Addvl(xd, xzr, multiplier);
5578   }
Rev(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn)5579   void Rev(const PRegisterWithLaneSize& pd, const PRegisterWithLaneSize& pn) {
5580     VIXL_ASSERT(allow_macro_instructions_);
5581     SingleEmissionCheckScope guard(this);
5582     rev(pd, pn);
5583   }
Rev(const ZRegister & zd,const ZRegister & zn)5584   void Rev(const ZRegister& zd, const ZRegister& zn) {
5585     VIXL_ASSERT(allow_macro_instructions_);
5586     SingleEmissionCheckScope guard(this);
5587     rev(zd, zn);
5588   }
Revb(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5589   void Revb(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5590     VIXL_ASSERT(allow_macro_instructions_);
5591     SingleEmissionCheckScope guard(this);
5592     revb(zd, pg, zn);
5593   }
Revh(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5594   void Revh(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5595     VIXL_ASSERT(allow_macro_instructions_);
5596     SingleEmissionCheckScope guard(this);
5597     revh(zd, pg, zn);
5598   }
Revw(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5599   void Revw(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5600     VIXL_ASSERT(allow_macro_instructions_);
5601     SingleEmissionCheckScope guard(this);
5602     revw(zd, pg, zn);
5603   }
Saddv(const VRegister & dd,const PRegister & pg,const ZRegister & zn)5604   void Saddv(const VRegister& dd, const PRegister& pg, const ZRegister& zn) {
5605     VIXL_ASSERT(allow_macro_instructions_);
5606     SingleEmissionCheckScope guard(this);
5607     saddv(dd, pg, zn);
5608   }
Scvtf(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)5609   void Scvtf(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
5610     VIXL_ASSERT(allow_macro_instructions_);
5611     SingleEmissionCheckScope guard(this);
5612     scvtf(zd, pg, zn);
5613   }
5614   void Sdiv(const ZRegister& zd,
5615             const PRegisterM& pg,
5616             const ZRegister& zn,
5617             const ZRegister& zm);
5618   void Sdot(const ZRegister& zd,
5619             const ZRegister& za,
5620             const ZRegister& zn,
5621             const ZRegister& zm);
5622   void Sdot(const ZRegister& zd,
5623             const ZRegister& za,
5624             const ZRegister& zn,
5625             const ZRegister& zm,
5626             int index);
Sel(const PRegisterWithLaneSize & pd,const PRegister & pg,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)5627   void Sel(const PRegisterWithLaneSize& pd,
5628            const PRegister& pg,
5629            const PRegisterWithLaneSize& pn,
5630            const PRegisterWithLaneSize& pm) {
5631     VIXL_ASSERT(allow_macro_instructions_);
5632     SingleEmissionCheckScope guard(this);
5633     sel(pd, pg, pn, pm);
5634   }
Sel(const ZRegister & zd,const PRegister & pg,const ZRegister & zn,const ZRegister & zm)5635   void Sel(const ZRegister& zd,
5636            const PRegister& pg,
5637            const ZRegister& zn,
5638            const ZRegister& zm) {
5639     VIXL_ASSERT(allow_macro_instructions_);
5640     SingleEmissionCheckScope guard(this);
5641     sel(zd, pg, zn, zm);
5642   }
Setffr()5643   void Setffr() {
5644     VIXL_ASSERT(allow_macro_instructions_);
5645     SingleEmissionCheckScope guard(this);
5646     setffr();
5647   }
5648   void Smax(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm);
Smaxv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)5649   void Smaxv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
5650     VIXL_ASSERT(allow_macro_instructions_);
5651     SingleEmissionCheckScope guard(this);
5652     smaxv(vd, pg, zn);
5653   }
5654   void Smin(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm);
Sminv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)5655   void Sminv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
5656     VIXL_ASSERT(allow_macro_instructions_);
5657     SingleEmissionCheckScope guard(this);
5658     sminv(vd, pg, zn);
5659   }
5660   void Splice(const ZRegister& zd,
5661               const PRegister& pg,
5662               const ZRegister& zn,
5663               const ZRegister& zm);
Sqadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5664   void Sqadd(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
5665     VIXL_ASSERT(allow_macro_instructions_);
5666     SingleEmissionCheckScope guard(this);
5667     sqadd(zd, zn, zm);
5668   }
Sqadd(const ZRegister & zd,const ZRegister & zn,IntegerOperand imm)5669   void Sqadd(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm) {
5670     VIXL_ASSERT(allow_macro_instructions_);
5671     VIXL_ASSERT(imm.IsUint8() ||
5672                 (imm.IsUint16() && ((imm.AsUint16() & 0xff) == 0)));
5673     MovprfxHelperScope guard(this, zd, zn);
5674     sqadd(zd, zd, imm.AsUint16());
5675   }
5676   void Sqdecb(const Register& xd,
5677               const Register& wn,
5678               int pattern = SVE_ALL,
5679               int multiplier = 1) {
5680     VIXL_ASSERT(allow_macro_instructions_);
5681     SingleEmissionCheckScope guard(this);
5682     sqdecb(xd, wn, pattern, multiplier);
5683   }
5684   void Sqdecb(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5685     VIXL_ASSERT(allow_macro_instructions_);
5686     SingleEmissionCheckScope guard(this);
5687     sqdecb(rdn, pattern, multiplier);
5688   }
5689   void Sqdecd(const Register& xd,
5690               const Register& wn,
5691               int pattern = SVE_ALL,
5692               int multiplier = 1) {
5693     VIXL_ASSERT(allow_macro_instructions_);
5694     SingleEmissionCheckScope guard(this);
5695     sqdecd(xd, wn, pattern, multiplier);
5696   }
5697   void Sqdecd(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5698     VIXL_ASSERT(allow_macro_instructions_);
5699     SingleEmissionCheckScope guard(this);
5700     sqdecd(rdn, pattern, multiplier);
5701   }
5702   void Sqdecd(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
5703     VIXL_ASSERT(allow_macro_instructions_);
5704     SingleEmissionCheckScope guard(this);
5705     sqdecd(zdn, pattern, multiplier);
5706   }
5707   void Sqdech(const Register& xd,
5708               const Register& wn,
5709               int pattern = SVE_ALL,
5710               int multiplier = 1) {
5711     VIXL_ASSERT(allow_macro_instructions_);
5712     SingleEmissionCheckScope guard(this);
5713     sqdech(xd, wn, pattern, multiplier);
5714   }
5715   void Sqdech(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5716     VIXL_ASSERT(allow_macro_instructions_);
5717     SingleEmissionCheckScope guard(this);
5718     sqdech(rdn, pattern, multiplier);
5719   }
5720   void Sqdech(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
5721     VIXL_ASSERT(allow_macro_instructions_);
5722     SingleEmissionCheckScope guard(this);
5723     sqdech(zdn, pattern, multiplier);
5724   }
Sqdecp(const Register & xdn,const PRegisterWithLaneSize & pg,const Register & wdn)5725   void Sqdecp(const Register& xdn,
5726               const PRegisterWithLaneSize& pg,
5727               const Register& wdn) {
5728     VIXL_ASSERT(allow_macro_instructions_);
5729     SingleEmissionCheckScope guard(this);
5730     sqdecp(xdn, pg, wdn);
5731   }
Sqdecp(const Register & xdn,const PRegisterWithLaneSize & pg)5732   void Sqdecp(const Register& xdn, const PRegisterWithLaneSize& pg) {
5733     VIXL_ASSERT(allow_macro_instructions_);
5734     SingleEmissionCheckScope guard(this);
5735     sqdecp(xdn, pg);
5736   }
Sqdecp(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)5737   void Sqdecp(const ZRegister& zd, const PRegister& pg, const ZRegister& zn) {
5738     VIXL_ASSERT(allow_macro_instructions_);
5739     VIXL_ASSERT(AreSameFormat(zd, zn));
5740     // `sqdecp` writes every lane, so use an unpredicated movprfx.
5741     MovprfxHelperScope guard(this, zd, zn);
5742     sqdecp(zd, pg);
5743   }
Sqdecp(const ZRegister & zdn,const PRegister & pg)5744   void Sqdecp(const ZRegister& zdn, const PRegister& pg) {
5745     Sqdecp(zdn, pg, zdn);
5746   }
5747   void Sqdecw(const Register& xd,
5748               const Register& wn,
5749               int pattern = SVE_ALL,
5750               int multiplier = 1) {
5751     VIXL_ASSERT(allow_macro_instructions_);
5752     SingleEmissionCheckScope guard(this);
5753     sqdecw(xd, wn, pattern, multiplier);
5754   }
5755   void Sqdecw(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5756     VIXL_ASSERT(allow_macro_instructions_);
5757     SingleEmissionCheckScope guard(this);
5758     sqdecw(rdn, pattern, multiplier);
5759   }
5760   void Sqdecw(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
5761     VIXL_ASSERT(allow_macro_instructions_);
5762     SingleEmissionCheckScope guard(this);
5763     sqdecw(zdn, pattern, multiplier);
5764   }
5765   void Sqincb(const Register& xd,
5766               const Register& wn,
5767               int pattern = SVE_ALL,
5768               int multiplier = 1) {
5769     VIXL_ASSERT(allow_macro_instructions_);
5770     SingleEmissionCheckScope guard(this);
5771     sqincb(xd, wn, pattern, multiplier);
5772   }
5773   void Sqincb(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5774     VIXL_ASSERT(allow_macro_instructions_);
5775     SingleEmissionCheckScope guard(this);
5776     sqincb(rdn, pattern, multiplier);
5777   }
5778   void Sqincd(const Register& xd,
5779               const Register& wn,
5780               int pattern = SVE_ALL,
5781               int multiplier = 1) {
5782     VIXL_ASSERT(allow_macro_instructions_);
5783     SingleEmissionCheckScope guard(this);
5784     sqincd(xd, wn, pattern, multiplier);
5785   }
5786   void Sqincd(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5787     VIXL_ASSERT(allow_macro_instructions_);
5788     SingleEmissionCheckScope guard(this);
5789     sqincd(rdn, pattern, multiplier);
5790   }
5791   void Sqincd(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
5792     VIXL_ASSERT(allow_macro_instructions_);
5793     SingleEmissionCheckScope guard(this);
5794     sqincd(zdn, pattern, multiplier);
5795   }
5796   void Sqinch(const Register& xd,
5797               const Register& wn,
5798               int pattern = SVE_ALL,
5799               int multiplier = 1) {
5800     VIXL_ASSERT(allow_macro_instructions_);
5801     SingleEmissionCheckScope guard(this);
5802     sqinch(xd, wn, pattern, multiplier);
5803   }
5804   void Sqinch(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5805     VIXL_ASSERT(allow_macro_instructions_);
5806     SingleEmissionCheckScope guard(this);
5807     sqinch(rdn, pattern, multiplier);
5808   }
5809   void Sqinch(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
5810     VIXL_ASSERT(allow_macro_instructions_);
5811     SingleEmissionCheckScope guard(this);
5812     sqinch(zdn, pattern, multiplier);
5813   }
Sqincp(const Register & xdn,const PRegisterWithLaneSize & pg,const Register & wdn)5814   void Sqincp(const Register& xdn,
5815               const PRegisterWithLaneSize& pg,
5816               const Register& wdn) {
5817     VIXL_ASSERT(allow_macro_instructions_);
5818     SingleEmissionCheckScope guard(this);
5819     sqincp(xdn, pg, wdn);
5820   }
Sqincp(const Register & xdn,const PRegisterWithLaneSize & pg)5821   void Sqincp(const Register& xdn, const PRegisterWithLaneSize& pg) {
5822     VIXL_ASSERT(allow_macro_instructions_);
5823     SingleEmissionCheckScope guard(this);
5824     sqincp(xdn, pg);
5825   }
Sqincp(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)5826   void Sqincp(const ZRegister& zd, const PRegister& pg, const ZRegister& zn) {
5827     VIXL_ASSERT(allow_macro_instructions_);
5828     VIXL_ASSERT(AreSameFormat(zd, zn));
5829     // `sqincp` writes every lane, so use an unpredicated movprfx.
5830     MovprfxHelperScope guard(this, zd, zn);
5831     sqincp(zd, pg);
5832   }
Sqincp(const ZRegister & zdn,const PRegister & pg)5833   void Sqincp(const ZRegister& zdn, const PRegister& pg) {
5834     Sqincp(zdn, pg, zdn);
5835   }
5836   void Sqincw(const Register& xd,
5837               const Register& wn,
5838               int pattern = SVE_ALL,
5839               int multiplier = 1) {
5840     VIXL_ASSERT(allow_macro_instructions_);
5841     SingleEmissionCheckScope guard(this);
5842     sqincw(xd, wn, pattern, multiplier);
5843   }
5844   void Sqincw(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
5845     VIXL_ASSERT(allow_macro_instructions_);
5846     SingleEmissionCheckScope guard(this);
5847     sqincw(rdn, pattern, multiplier);
5848   }
5849   void Sqincw(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
5850     VIXL_ASSERT(allow_macro_instructions_);
5851     SingleEmissionCheckScope guard(this);
5852     sqincw(zdn, pattern, multiplier);
5853   }
Sqsub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)5854   void Sqsub(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
5855     VIXL_ASSERT(allow_macro_instructions_);
5856     SingleEmissionCheckScope guard(this);
5857     sqsub(zd, zn, zm);
5858   }
Sqsub(const ZRegister & zd,const ZRegister & zn,IntegerOperand imm)5859   void Sqsub(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm) {
5860     VIXL_ASSERT(allow_macro_instructions_);
5861     VIXL_ASSERT(imm.IsUint8() ||
5862                 (imm.IsUint16() && ((imm.AsUint16() & 0xff) == 0)));
5863     MovprfxHelperScope guard(this, zd, zn);
5864     sqsub(zd, zd, imm.AsUint16());
5865   }
5866   void St1b(const ZRegister& zt,
5867             const PRegister& pg,
5868             const SVEMemOperand& addr);
5869   void St1h(const ZRegister& zt,
5870             const PRegister& pg,
5871             const SVEMemOperand& addr);
5872   void St1w(const ZRegister& zt,
5873             const PRegister& pg,
5874             const SVEMemOperand& addr);
5875   void St1d(const ZRegister& zt,
5876             const PRegister& pg,
5877             const SVEMemOperand& addr);
St2b(const ZRegister & zt1,const ZRegister & zt2,const PRegister & pg,const SVEMemOperand & addr)5878   void St2b(const ZRegister& zt1,
5879             const ZRegister& zt2,
5880             const PRegister& pg,
5881             const SVEMemOperand& addr) {
5882     VIXL_ASSERT(allow_macro_instructions_);
5883     SingleEmissionCheckScope guard(this);
5884     st2b(zt1, zt2, pg, addr);
5885   }
St2h(const ZRegister & zt1,const ZRegister & zt2,const PRegister & pg,const SVEMemOperand & addr)5886   void St2h(const ZRegister& zt1,
5887             const ZRegister& zt2,
5888             const PRegister& pg,
5889             const SVEMemOperand& addr) {
5890     VIXL_ASSERT(allow_macro_instructions_);
5891     SingleEmissionCheckScope guard(this);
5892     st2h(zt1, zt2, pg, addr);
5893   }
St2w(const ZRegister & zt1,const ZRegister & zt2,const PRegister & pg,const SVEMemOperand & addr)5894   void St2w(const ZRegister& zt1,
5895             const ZRegister& zt2,
5896             const PRegister& pg,
5897             const SVEMemOperand& addr) {
5898     VIXL_ASSERT(allow_macro_instructions_);
5899     SingleEmissionCheckScope guard(this);
5900     st2w(zt1, zt2, pg, addr);
5901   }
St2d(const ZRegister & zt1,const ZRegister & zt2,const PRegister & pg,const SVEMemOperand & addr)5902   void St2d(const ZRegister& zt1,
5903             const ZRegister& zt2,
5904             const PRegister& pg,
5905             const SVEMemOperand& addr) {
5906     VIXL_ASSERT(allow_macro_instructions_);
5907     SingleEmissionCheckScope guard(this);
5908     st2d(zt1, zt2, pg, addr);
5909   }
St3b(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegister & pg,const SVEMemOperand & addr)5910   void St3b(const ZRegister& zt1,
5911             const ZRegister& zt2,
5912             const ZRegister& zt3,
5913             const PRegister& pg,
5914             const SVEMemOperand& addr) {
5915     VIXL_ASSERT(allow_macro_instructions_);
5916     SingleEmissionCheckScope guard(this);
5917     st3b(zt1, zt2, zt3, pg, addr);
5918   }
St3h(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegister & pg,const SVEMemOperand & addr)5919   void St3h(const ZRegister& zt1,
5920             const ZRegister& zt2,
5921             const ZRegister& zt3,
5922             const PRegister& pg,
5923             const SVEMemOperand& addr) {
5924     VIXL_ASSERT(allow_macro_instructions_);
5925     SingleEmissionCheckScope guard(this);
5926     st3h(zt1, zt2, zt3, pg, addr);
5927   }
St3w(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegister & pg,const SVEMemOperand & addr)5928   void St3w(const ZRegister& zt1,
5929             const ZRegister& zt2,
5930             const ZRegister& zt3,
5931             const PRegister& pg,
5932             const SVEMemOperand& addr) {
5933     VIXL_ASSERT(allow_macro_instructions_);
5934     SingleEmissionCheckScope guard(this);
5935     st3w(zt1, zt2, zt3, pg, addr);
5936   }
St3d(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const PRegister & pg,const SVEMemOperand & addr)5937   void St3d(const ZRegister& zt1,
5938             const ZRegister& zt2,
5939             const ZRegister& zt3,
5940             const PRegister& pg,
5941             const SVEMemOperand& addr) {
5942     VIXL_ASSERT(allow_macro_instructions_);
5943     SingleEmissionCheckScope guard(this);
5944     st3d(zt1, zt2, zt3, pg, addr);
5945   }
St4b(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegister & pg,const SVEMemOperand & addr)5946   void St4b(const ZRegister& zt1,
5947             const ZRegister& zt2,
5948             const ZRegister& zt3,
5949             const ZRegister& zt4,
5950             const PRegister& pg,
5951             const SVEMemOperand& addr) {
5952     VIXL_ASSERT(allow_macro_instructions_);
5953     SingleEmissionCheckScope guard(this);
5954     st4b(zt1, zt2, zt3, zt4, pg, addr);
5955   }
St4h(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegister & pg,const SVEMemOperand & addr)5956   void St4h(const ZRegister& zt1,
5957             const ZRegister& zt2,
5958             const ZRegister& zt3,
5959             const ZRegister& zt4,
5960             const PRegister& pg,
5961             const SVEMemOperand& addr) {
5962     VIXL_ASSERT(allow_macro_instructions_);
5963     SingleEmissionCheckScope guard(this);
5964     st4h(zt1, zt2, zt3, zt4, pg, addr);
5965   }
St4w(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegister & pg,const SVEMemOperand & addr)5966   void St4w(const ZRegister& zt1,
5967             const ZRegister& zt2,
5968             const ZRegister& zt3,
5969             const ZRegister& zt4,
5970             const PRegister& pg,
5971             const SVEMemOperand& addr) {
5972     VIXL_ASSERT(allow_macro_instructions_);
5973     SingleEmissionCheckScope guard(this);
5974     st4w(zt1, zt2, zt3, zt4, pg, addr);
5975   }
St4d(const ZRegister & zt1,const ZRegister & zt2,const ZRegister & zt3,const ZRegister & zt4,const PRegister & pg,const SVEMemOperand & addr)5976   void St4d(const ZRegister& zt1,
5977             const ZRegister& zt2,
5978             const ZRegister& zt3,
5979             const ZRegister& zt4,
5980             const PRegister& pg,
5981             const SVEMemOperand& addr) {
5982     VIXL_ASSERT(allow_macro_instructions_);
5983     SingleEmissionCheckScope guard(this);
5984     st4d(zt1, zt2, zt3, zt4, pg, addr);
5985   }
5986   void Stnt1b(const ZRegister& zt,
5987               const PRegister& pg,
5988               const SVEMemOperand& addr);
5989   void Stnt1d(const ZRegister& zt,
5990               const PRegister& pg,
5991               const SVEMemOperand& addr);
5992   void Stnt1h(const ZRegister& zt,
5993               const PRegister& pg,
5994               const SVEMemOperand& addr);
5995   void Stnt1w(const ZRegister& zt,
5996               const PRegister& pg,
5997               const SVEMemOperand& addr);
Str(const CPURegister & rt,const SVEMemOperand & addr)5998   void Str(const CPURegister& rt, const SVEMemOperand& addr) {
5999     VIXL_ASSERT(allow_macro_instructions_);
6000     SVELoadStoreScalarImmHelper(rt, addr, &MacroAssembler::str);
6001   }
6002   void Sub(const ZRegister& zd,
6003            const PRegisterM& pg,
6004            const ZRegister& zn,
6005            const ZRegister& zm);
Sub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6006   void Sub(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6007     VIXL_ASSERT(allow_macro_instructions_);
6008     SingleEmissionCheckScope guard(this);
6009     sub(zd, zn, zm);
6010   }
Sub(const ZRegister & zd,const ZRegister & zn,IntegerOperand imm)6011   void Sub(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm) {
6012     VIXL_ASSERT(allow_macro_instructions_);
6013     AddSubHelper(kSubImmediate, zd, zn, imm);
6014   }
6015   void Sub(const ZRegister& zd, IntegerOperand imm, const ZRegister& zm);
Sunpkhi(const ZRegister & zd,const ZRegister & zn)6016   void Sunpkhi(const ZRegister& zd, const ZRegister& zn) {
6017     VIXL_ASSERT(allow_macro_instructions_);
6018     SingleEmissionCheckScope guard(this);
6019     sunpkhi(zd, zn);
6020   }
Sunpklo(const ZRegister & zd,const ZRegister & zn)6021   void Sunpklo(const ZRegister& zd, const ZRegister& zn) {
6022     VIXL_ASSERT(allow_macro_instructions_);
6023     SingleEmissionCheckScope guard(this);
6024     sunpklo(zd, zn);
6025   }
Sxtb(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6026   void Sxtb(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
6027     VIXL_ASSERT(allow_macro_instructions_);
6028     SingleEmissionCheckScope guard(this);
6029     sxtb(zd, pg, zn);
6030   }
Sxth(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6031   void Sxth(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
6032     VIXL_ASSERT(allow_macro_instructions_);
6033     SingleEmissionCheckScope guard(this);
6034     sxth(zd, pg, zn);
6035   }
Sxtw(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6036   void Sxtw(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
6037     VIXL_ASSERT(allow_macro_instructions_);
6038     SingleEmissionCheckScope guard(this);
6039     sxtw(zd, pg, zn);
6040   }
Tbl(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6041   void Tbl(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6042     VIXL_ASSERT(allow_macro_instructions_);
6043     SingleEmissionCheckScope guard(this);
6044     tbl(zd, zn, zm);
6045   }
Trn1(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6046   void Trn1(const PRegisterWithLaneSize& pd,
6047             const PRegisterWithLaneSize& pn,
6048             const PRegisterWithLaneSize& pm) {
6049     VIXL_ASSERT(allow_macro_instructions_);
6050     SingleEmissionCheckScope guard(this);
6051     trn1(pd, pn, pm);
6052   }
Trn1(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6053   void Trn1(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6054     VIXL_ASSERT(allow_macro_instructions_);
6055     SingleEmissionCheckScope guard(this);
6056     trn1(zd, zn, zm);
6057   }
Trn2(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6058   void Trn2(const PRegisterWithLaneSize& pd,
6059             const PRegisterWithLaneSize& pn,
6060             const PRegisterWithLaneSize& pm) {
6061     VIXL_ASSERT(allow_macro_instructions_);
6062     SingleEmissionCheckScope guard(this);
6063     trn2(pd, pn, pm);
6064   }
Trn2(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6065   void Trn2(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6066     VIXL_ASSERT(allow_macro_instructions_);
6067     SingleEmissionCheckScope guard(this);
6068     trn2(zd, zn, zm);
6069   }
Uaddv(const VRegister & dd,const PRegister & pg,const ZRegister & zn)6070   void Uaddv(const VRegister& dd, const PRegister& pg, const ZRegister& zn) {
6071     VIXL_ASSERT(allow_macro_instructions_);
6072     SingleEmissionCheckScope guard(this);
6073     uaddv(dd, pg, zn);
6074   }
Ucvtf(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6075   void Ucvtf(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
6076     VIXL_ASSERT(allow_macro_instructions_);
6077     SingleEmissionCheckScope guard(this);
6078     ucvtf(zd, pg, zn);
6079   }
6080   void Udiv(const ZRegister& zd,
6081             const PRegisterM& pg,
6082             const ZRegister& zn,
6083             const ZRegister& zm);
6084   void Udot(const ZRegister& zd,
6085             const ZRegister& za,
6086             const ZRegister& zn,
6087             const ZRegister& zm);
6088   void Udot(const ZRegister& zd,
6089             const ZRegister& za,
6090             const ZRegister& zn,
6091             const ZRegister& zm,
6092             int index);
6093   void Umax(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm);
Umaxv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)6094   void Umaxv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
6095     VIXL_ASSERT(allow_macro_instructions_);
6096     SingleEmissionCheckScope guard(this);
6097     umaxv(vd, pg, zn);
6098   }
6099   void Umin(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm);
Uminv(const VRegister & vd,const PRegister & pg,const ZRegister & zn)6100   void Uminv(const VRegister& vd, const PRegister& pg, const ZRegister& zn) {
6101     VIXL_ASSERT(allow_macro_instructions_);
6102     SingleEmissionCheckScope guard(this);
6103     uminv(vd, pg, zn);
6104   }
Uqadd(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6105   void Uqadd(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6106     VIXL_ASSERT(allow_macro_instructions_);
6107     SingleEmissionCheckScope guard(this);
6108     uqadd(zd, zn, zm);
6109   }
Uqadd(const ZRegister & zd,const ZRegister & zn,IntegerOperand imm)6110   void Uqadd(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm) {
6111     VIXL_ASSERT(allow_macro_instructions_);
6112     VIXL_ASSERT(imm.IsUint8() ||
6113                 (imm.IsUint16() && ((imm.AsUint16() & 0xff) == 0)));
6114     MovprfxHelperScope guard(this, zd, zn);
6115     uqadd(zd, zd, imm.AsUint16());
6116   }
6117   void Uqdecb(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6118     VIXL_ASSERT(allow_macro_instructions_);
6119     SingleEmissionCheckScope guard(this);
6120     uqdecb(rdn, pattern, multiplier);
6121   }
6122   void Uqdecd(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6123     VIXL_ASSERT(allow_macro_instructions_);
6124     SingleEmissionCheckScope guard(this);
6125     uqdecd(rdn, pattern, multiplier);
6126   }
6127   void Uqdecd(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
6128     VIXL_ASSERT(allow_macro_instructions_);
6129     SingleEmissionCheckScope guard(this);
6130     uqdecd(zdn, pattern, multiplier);
6131   }
6132   void Uqdech(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6133     VIXL_ASSERT(allow_macro_instructions_);
6134     SingleEmissionCheckScope guard(this);
6135     uqdech(rdn, pattern, multiplier);
6136   }
6137   void Uqdech(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
6138     VIXL_ASSERT(allow_macro_instructions_);
6139     SingleEmissionCheckScope guard(this);
6140     uqdech(zdn, pattern, multiplier);
6141   }
6142   // The saturation is based on the size of `rn`. The result is zero-extended
6143   // into `rd`, which must be at least as big.
Uqdecp(const Register & rd,const PRegisterWithLaneSize & pg,const Register & rn)6144   void Uqdecp(const Register& rd,
6145               const PRegisterWithLaneSize& pg,
6146               const Register& rn) {
6147     VIXL_ASSERT(allow_macro_instructions_);
6148     VIXL_ASSERT(rd.Aliases(rn));
6149     VIXL_ASSERT(rd.GetSizeInBytes() >= rn.GetSizeInBytes());
6150     SingleEmissionCheckScope guard(this);
6151     if (rn.Is64Bits()) {
6152       uqdecp(rd, pg);
6153     } else {
6154       // Convert <Xd> into <Wd>, to make this more consistent with Sqdecp.
6155       uqdecp(rd.W(), pg);
6156     }
6157   }
Uqdecp(const Register & rdn,const PRegisterWithLaneSize & pg)6158   void Uqdecp(const Register& rdn, const PRegisterWithLaneSize& pg) {
6159     Uqdecp(rdn, pg, rdn);
6160   }
Uqdecp(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)6161   void Uqdecp(const ZRegister& zd, const PRegister& pg, const ZRegister& zn) {
6162     VIXL_ASSERT(allow_macro_instructions_);
6163     VIXL_ASSERT(AreSameFormat(zd, zn));
6164     // `sqdecp` writes every lane, so use an unpredicated movprfx.
6165     MovprfxHelperScope guard(this, zd, zn);
6166     uqdecp(zd, pg);
6167   }
Uqdecp(const ZRegister & zdn,const PRegister & pg)6168   void Uqdecp(const ZRegister& zdn, const PRegister& pg) {
6169     Uqdecp(zdn, pg, zdn);
6170   }
6171   void Uqdecw(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6172     VIXL_ASSERT(allow_macro_instructions_);
6173     SingleEmissionCheckScope guard(this);
6174     uqdecw(rdn, pattern, multiplier);
6175   }
6176   void Uqdecw(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
6177     VIXL_ASSERT(allow_macro_instructions_);
6178     SingleEmissionCheckScope guard(this);
6179     uqdecw(zdn, pattern, multiplier);
6180   }
6181   void Uqincb(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6182     VIXL_ASSERT(allow_macro_instructions_);
6183     SingleEmissionCheckScope guard(this);
6184     uqincb(rdn, pattern, multiplier);
6185   }
6186   void Uqincd(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6187     VIXL_ASSERT(allow_macro_instructions_);
6188     SingleEmissionCheckScope guard(this);
6189     uqincd(rdn, pattern, multiplier);
6190   }
6191   void Uqincd(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
6192     VIXL_ASSERT(allow_macro_instructions_);
6193     SingleEmissionCheckScope guard(this);
6194     uqincd(zdn, pattern, multiplier);
6195   }
6196   void Uqinch(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6197     VIXL_ASSERT(allow_macro_instructions_);
6198     SingleEmissionCheckScope guard(this);
6199     uqinch(rdn, pattern, multiplier);
6200   }
6201   void Uqinch(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
6202     VIXL_ASSERT(allow_macro_instructions_);
6203     SingleEmissionCheckScope guard(this);
6204     uqinch(zdn, pattern, multiplier);
6205   }
6206   // The saturation is based on the size of `rn`. The result is zero-extended
6207   // into `rd`, which must be at least as big.
Uqincp(const Register & rd,const PRegisterWithLaneSize & pg,const Register & rn)6208   void Uqincp(const Register& rd,
6209               const PRegisterWithLaneSize& pg,
6210               const Register& rn) {
6211     VIXL_ASSERT(allow_macro_instructions_);
6212     VIXL_ASSERT(rd.Aliases(rn));
6213     VIXL_ASSERT(rd.GetSizeInBytes() >= rn.GetSizeInBytes());
6214     SingleEmissionCheckScope guard(this);
6215     if (rn.Is64Bits()) {
6216       uqincp(rd, pg);
6217     } else {
6218       // Convert <Xd> into <Wd>, to make this more consistent with Sqincp.
6219       uqincp(rd.W(), pg);
6220     }
6221   }
Uqincp(const Register & rdn,const PRegisterWithLaneSize & pg)6222   void Uqincp(const Register& rdn, const PRegisterWithLaneSize& pg) {
6223     Uqincp(rdn, pg, rdn);
6224   }
Uqincp(const ZRegister & zd,const PRegister & pg,const ZRegister & zn)6225   void Uqincp(const ZRegister& zd, const PRegister& pg, const ZRegister& zn) {
6226     VIXL_ASSERT(allow_macro_instructions_);
6227     VIXL_ASSERT(AreSameFormat(zd, zn));
6228     // `sqincp` writes every lane, so use an unpredicated movprfx.
6229     MovprfxHelperScope guard(this, zd, zn);
6230     uqincp(zd, pg);
6231   }
Uqincp(const ZRegister & zdn,const PRegister & pg)6232   void Uqincp(const ZRegister& zdn, const PRegister& pg) {
6233     Uqincp(zdn, pg, zdn);
6234   }
6235   void Uqincw(const Register& rdn, int pattern = SVE_ALL, int multiplier = 1) {
6236     VIXL_ASSERT(allow_macro_instructions_);
6237     SingleEmissionCheckScope guard(this);
6238     uqincw(rdn, pattern, multiplier);
6239   }
6240   void Uqincw(const ZRegister& zdn, int pattern = SVE_ALL, int multiplier = 1) {
6241     VIXL_ASSERT(allow_macro_instructions_);
6242     SingleEmissionCheckScope guard(this);
6243     uqincw(zdn, pattern, multiplier);
6244   }
Uqsub(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6245   void Uqsub(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6246     VIXL_ASSERT(allow_macro_instructions_);
6247     SingleEmissionCheckScope guard(this);
6248     uqsub(zd, zn, zm);
6249   }
Uqsub(const ZRegister & zd,const ZRegister & zn,IntegerOperand imm)6250   void Uqsub(const ZRegister& zd, const ZRegister& zn, IntegerOperand imm) {
6251     VIXL_ASSERT(allow_macro_instructions_);
6252     VIXL_ASSERT(imm.IsUint8() ||
6253                 (imm.IsUint16() && ((imm.AsUint16() & 0xff) == 0)));
6254     MovprfxHelperScope guard(this, zd, zn);
6255     uqsub(zd, zd, imm.AsUint16());
6256   }
Uunpkhi(const ZRegister & zd,const ZRegister & zn)6257   void Uunpkhi(const ZRegister& zd, const ZRegister& zn) {
6258     VIXL_ASSERT(allow_macro_instructions_);
6259     SingleEmissionCheckScope guard(this);
6260     uunpkhi(zd, zn);
6261   }
Uunpklo(const ZRegister & zd,const ZRegister & zn)6262   void Uunpklo(const ZRegister& zd, const ZRegister& zn) {
6263     VIXL_ASSERT(allow_macro_instructions_);
6264     SingleEmissionCheckScope guard(this);
6265     uunpklo(zd, zn);
6266   }
Uxtb(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6267   void Uxtb(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
6268     VIXL_ASSERT(allow_macro_instructions_);
6269     SingleEmissionCheckScope guard(this);
6270     uxtb(zd, pg, zn);
6271   }
Uxth(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6272   void Uxth(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
6273     VIXL_ASSERT(allow_macro_instructions_);
6274     SingleEmissionCheckScope guard(this);
6275     uxth(zd, pg, zn);
6276   }
Uxtw(const ZRegister & zd,const PRegisterM & pg,const ZRegister & zn)6277   void Uxtw(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
6278     VIXL_ASSERT(allow_macro_instructions_);
6279     SingleEmissionCheckScope guard(this);
6280     uxtw(zd, pg, zn);
6281   }
Uzp1(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6282   void Uzp1(const PRegisterWithLaneSize& pd,
6283             const PRegisterWithLaneSize& pn,
6284             const PRegisterWithLaneSize& pm) {
6285     VIXL_ASSERT(allow_macro_instructions_);
6286     SingleEmissionCheckScope guard(this);
6287     uzp1(pd, pn, pm);
6288   }
Uzp1(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6289   void Uzp1(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6290     VIXL_ASSERT(allow_macro_instructions_);
6291     SingleEmissionCheckScope guard(this);
6292     uzp1(zd, zn, zm);
6293   }
Uzp2(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6294   void Uzp2(const PRegisterWithLaneSize& pd,
6295             const PRegisterWithLaneSize& pn,
6296             const PRegisterWithLaneSize& pm) {
6297     VIXL_ASSERT(allow_macro_instructions_);
6298     SingleEmissionCheckScope guard(this);
6299     uzp2(pd, pn, pm);
6300   }
Uzp2(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6301   void Uzp2(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6302     VIXL_ASSERT(allow_macro_instructions_);
6303     SingleEmissionCheckScope guard(this);
6304     uzp2(zd, zn, zm);
6305   }
Whilele(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)6306   void Whilele(const PRegisterWithLaneSize& pd,
6307                const Register& rn,
6308                const Register& rm) {
6309     VIXL_ASSERT(allow_macro_instructions_);
6310     SingleEmissionCheckScope guard(this);
6311     whilele(pd, rn, rm);
6312   }
Whilelo(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)6313   void Whilelo(const PRegisterWithLaneSize& pd,
6314                const Register& rn,
6315                const Register& rm) {
6316     VIXL_ASSERT(allow_macro_instructions_);
6317     SingleEmissionCheckScope guard(this);
6318     whilelo(pd, rn, rm);
6319   }
Whilels(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)6320   void Whilels(const PRegisterWithLaneSize& pd,
6321                const Register& rn,
6322                const Register& rm) {
6323     VIXL_ASSERT(allow_macro_instructions_);
6324     SingleEmissionCheckScope guard(this);
6325     whilels(pd, rn, rm);
6326   }
Whilelt(const PRegisterWithLaneSize & pd,const Register & rn,const Register & rm)6327   void Whilelt(const PRegisterWithLaneSize& pd,
6328                const Register& rn,
6329                const Register& rm) {
6330     VIXL_ASSERT(allow_macro_instructions_);
6331     SingleEmissionCheckScope guard(this);
6332     whilelt(pd, rn, rm);
6333   }
Wrffr(const PRegister & pn)6334   void Wrffr(const PRegister& pn) {
6335     VIXL_ASSERT(allow_macro_instructions_);
6336     // Although this is essentially just a move, it writes every bit and so can
6337     // only support b-sized lane because other lane sizes would implicitly clear
6338     // bits in `ffr`.
6339     VIXL_ASSERT(!pn.HasLaneSize() || pn.IsLaneSizeB());
6340     VIXL_ASSERT(pn.IsUnqualified());
6341     SingleEmissionCheckScope guard(this);
6342     wrffr(pn.VnB());
6343   }
Zip1(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6344   void Zip1(const PRegisterWithLaneSize& pd,
6345             const PRegisterWithLaneSize& pn,
6346             const PRegisterWithLaneSize& pm) {
6347     VIXL_ASSERT(allow_macro_instructions_);
6348     SingleEmissionCheckScope guard(this);
6349     zip1(pd, pn, pm);
6350   }
Zip1(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6351   void Zip1(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6352     VIXL_ASSERT(allow_macro_instructions_);
6353     SingleEmissionCheckScope guard(this);
6354     zip1(zd, zn, zm);
6355   }
Zip2(const PRegisterWithLaneSize & pd,const PRegisterWithLaneSize & pn,const PRegisterWithLaneSize & pm)6356   void Zip2(const PRegisterWithLaneSize& pd,
6357             const PRegisterWithLaneSize& pn,
6358             const PRegisterWithLaneSize& pm) {
6359     VIXL_ASSERT(allow_macro_instructions_);
6360     SingleEmissionCheckScope guard(this);
6361     zip2(pd, pn, pm);
6362   }
Zip2(const ZRegister & zd,const ZRegister & zn,const ZRegister & zm)6363   void Zip2(const ZRegister& zd, const ZRegister& zn, const ZRegister& zm) {
6364     VIXL_ASSERT(allow_macro_instructions_);
6365     SingleEmissionCheckScope guard(this);
6366     zip2(zd, zn, zm);
6367   }
6368 
6369   template <typename T>
CreateLiteralDestroyedWithPool(T value)6370   Literal<T>* CreateLiteralDestroyedWithPool(T value) {
6371     return new Literal<T>(value,
6372                           &literal_pool_,
6373                           RawLiteral::kDeletedOnPoolDestruction);
6374   }
6375 
6376   template <typename T>
CreateLiteralDestroyedWithPool(T high64,T low64)6377   Literal<T>* CreateLiteralDestroyedWithPool(T high64, T low64) {
6378     return new Literal<T>(high64,
6379                           low64,
6380                           &literal_pool_,
6381                           RawLiteral::kDeletedOnPoolDestruction);
6382   }
6383 
6384   // Push the system stack pointer (sp) down to allow the same to be done to
6385   // the current stack pointer (according to StackPointer()). This must be
6386   // called _before_ accessing the memory.
6387   //
6388   // This is necessary when pushing or otherwise adding things to the stack, to
6389   // satisfy the AAPCS64 constraint that the memory below the system stack
6390   // pointer is not accessed.
6391   //
6392   // This method asserts that StackPointer() is not sp, since the call does
6393   // not make sense in that context.
6394   //
6395   // TODO: This method can only accept values of 'space' that can be encoded in
6396   // one instruction. Refer to the implementation for details.
6397   void BumpSystemStackPointer(const Operand& space);
6398 
AllowMacroInstructions()6399   virtual bool AllowMacroInstructions() const VIXL_OVERRIDE {
6400     return allow_macro_instructions_;
6401   }
6402 
ArePoolsBlocked()6403   virtual bool ArePoolsBlocked() const VIXL_OVERRIDE {
6404     return IsLiteralPoolBlocked() && IsVeneerPoolBlocked();
6405   }
6406 
SetGenerateSimulatorCode(bool value)6407   void SetGenerateSimulatorCode(bool value) {
6408     generate_simulator_code_ = value;
6409   }
6410 
GenerateSimulatorCode()6411   bool GenerateSimulatorCode() const { return generate_simulator_code_; }
6412 
GetLiteralPoolSize()6413   size_t GetLiteralPoolSize() const { return literal_pool_.GetSize(); }
6414   VIXL_DEPRECATED("GetLiteralPoolSize", size_t LiteralPoolSize() const) {
6415     return GetLiteralPoolSize();
6416   }
6417 
GetLiteralPoolMaxSize()6418   size_t GetLiteralPoolMaxSize() const { return literal_pool_.GetMaxSize(); }
6419   VIXL_DEPRECATED("GetLiteralPoolMaxSize", size_t LiteralPoolMaxSize() const) {
6420     return GetLiteralPoolMaxSize();
6421   }
6422 
GetVeneerPoolMaxSize()6423   size_t GetVeneerPoolMaxSize() const { return veneer_pool_.GetMaxSize(); }
6424   VIXL_DEPRECATED("GetVeneerPoolMaxSize", size_t VeneerPoolMaxSize() const) {
6425     return GetVeneerPoolMaxSize();
6426   }
6427 
6428   // The number of unresolved branches that may require a veneer.
GetNumberOfPotentialVeneers()6429   int GetNumberOfPotentialVeneers() const {
6430     return veneer_pool_.GetNumberOfPotentialVeneers();
6431   }
6432   VIXL_DEPRECATED("GetNumberOfPotentialVeneers",
NumberOfPotentialVeneers()6433                   int NumberOfPotentialVeneers() const) {
6434     return GetNumberOfPotentialVeneers();
6435   }
6436 
GetNextCheckPoint()6437   ptrdiff_t GetNextCheckPoint() const {
6438     ptrdiff_t next_checkpoint_for_pools =
6439         std::min(literal_pool_.GetCheckpoint(), veneer_pool_.GetCheckpoint());
6440     return std::min(next_checkpoint_for_pools,
6441                     static_cast<ptrdiff_t>(GetBuffer().GetCapacity()));
6442   }
6443   VIXL_DEPRECATED("GetNextCheckPoint", ptrdiff_t NextCheckPoint()) {
6444     return GetNextCheckPoint();
6445   }
6446 
EmitLiteralPool(LiteralPool::EmitOption option)6447   void EmitLiteralPool(LiteralPool::EmitOption option) {
6448     if (!literal_pool_.IsEmpty()) literal_pool_.Emit(option);
6449 
6450     checkpoint_ = GetNextCheckPoint();
6451     recommended_checkpoint_ = literal_pool_.GetNextRecommendedCheckpoint();
6452   }
6453 
6454   void CheckEmitFor(size_t amount);
EnsureEmitFor(size_t amount)6455   void EnsureEmitFor(size_t amount) {
6456     ptrdiff_t offset = amount;
6457     ptrdiff_t max_pools_size =
6458         literal_pool_.GetMaxSize() + veneer_pool_.GetMaxSize();
6459     ptrdiff_t cursor = GetCursorOffset();
6460     if ((cursor >= recommended_checkpoint_) ||
6461         ((cursor + offset + max_pools_size) >= checkpoint_)) {
6462       CheckEmitFor(amount);
6463     }
6464   }
6465 
6466   void CheckEmitPoolsFor(size_t amount);
EnsureEmitPoolsFor(size_t amount)6467   virtual void EnsureEmitPoolsFor(size_t amount) VIXL_OVERRIDE {
6468     ptrdiff_t offset = amount;
6469     ptrdiff_t max_pools_size =
6470         literal_pool_.GetMaxSize() + veneer_pool_.GetMaxSize();
6471     ptrdiff_t cursor = GetCursorOffset();
6472     if ((cursor >= recommended_checkpoint_) ||
6473         ((cursor + offset + max_pools_size) >= checkpoint_)) {
6474       CheckEmitPoolsFor(amount);
6475     }
6476   }
6477 
6478   // Set the current stack pointer, but don't generate any code.
SetStackPointer(const Register & stack_pointer)6479   void SetStackPointer(const Register& stack_pointer) {
6480     VIXL_ASSERT(!GetScratchRegisterList()->IncludesAliasOf(stack_pointer));
6481     sp_ = stack_pointer;
6482   }
6483 
6484   // Return the current stack pointer, as set by SetStackPointer.
StackPointer()6485   const Register& StackPointer() const { return sp_; }
6486 
GetScratchRegisterList()6487   CPURegList* GetScratchRegisterList() { return &tmp_list_; }
6488   VIXL_DEPRECATED("GetScratchRegisterList", CPURegList* TmpList()) {
6489     return GetScratchRegisterList();
6490   }
6491 
GetScratchVRegisterList()6492   CPURegList* GetScratchVRegisterList() { return &v_tmp_list_; }
6493   VIXL_DEPRECATED("GetScratchVRegisterList", CPURegList* FPTmpList()) {
6494     return GetScratchVRegisterList();
6495   }
6496 
GetScratchPRegisterList()6497   CPURegList* GetScratchPRegisterList() { return &p_tmp_list_; }
6498 
6499   // Get or set the current (most-deeply-nested) UseScratchRegisterScope.
SetCurrentScratchRegisterScope(UseScratchRegisterScope * scope)6500   void SetCurrentScratchRegisterScope(UseScratchRegisterScope* scope) {
6501     current_scratch_scope_ = scope;
6502   }
GetCurrentScratchRegisterScope()6503   UseScratchRegisterScope* GetCurrentScratchRegisterScope() {
6504     return current_scratch_scope_;
6505   }
6506 
6507   // Like printf, but print at run-time from generated code.
6508   //
6509   // The caller must ensure that arguments for floating-point placeholders
6510   // (such as %e, %f or %g) are VRegisters in format 1S or 1D, and that
6511   // arguments for integer placeholders are Registers.
6512   //
6513   // At the moment it is only possible to print the value of sp if it is the
6514   // current stack pointer. Otherwise, the MacroAssembler will automatically
6515   // update sp on every push (using BumpSystemStackPointer), so determining its
6516   // value is difficult.
6517   //
6518   // Format placeholders that refer to more than one argument, or to a specific
6519   // argument, are not supported. This includes formats like "%1$d" or "%.*d".
6520   //
6521   // This function automatically preserves caller-saved registers so that
6522   // calling code can use Printf at any point without having to worry about
6523   // corruption. The preservation mechanism generates a lot of code. If this is
6524   // a problem, preserve the important registers manually and then call
6525   // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are
6526   // implicitly preserved.
6527   void Printf(const char* format,
6528               CPURegister arg0 = NoCPUReg,
6529               CPURegister arg1 = NoCPUReg,
6530               CPURegister arg2 = NoCPUReg,
6531               CPURegister arg3 = NoCPUReg);
6532 
6533   // Like Printf, but don't preserve any caller-saved registers, not even 'lr'.
6534   //
6535   // The return code from the system printf call will be returned in x0.
6536   void PrintfNoPreserve(const char* format,
6537                         const CPURegister& arg0 = NoCPUReg,
6538                         const CPURegister& arg1 = NoCPUReg,
6539                         const CPURegister& arg2 = NoCPUReg,
6540                         const CPURegister& arg3 = NoCPUReg);
6541 
6542   // Trace control when running the debug simulator.
6543   //
6544   // For example:
6545   //
6546   // __ Trace(LOG_REGS, TRACE_ENABLE);
6547   // Will add registers to the trace if it wasn't already the case.
6548   //
6549   // __ Trace(LOG_DISASM, TRACE_DISABLE);
6550   // Will stop logging disassembly. It has no effect if the disassembly wasn't
6551   // already being logged.
6552   void Trace(TraceParameters parameters, TraceCommand command);
6553 
6554   // Log the requested data independently of what is being traced.
6555   //
6556   // For example:
6557   //
6558   // __ Log(LOG_FLAGS)
6559   // Will output the flags.
6560   void Log(TraceParameters parameters);
6561 
6562   // Enable or disable CPU features dynamically. This mechanism allows users to
6563   // strictly check the use of CPU features in different regions of code.
6564   void SetSimulatorCPUFeatures(const CPUFeatures& features);
6565   void EnableSimulatorCPUFeatures(const CPUFeatures& features);
6566   void DisableSimulatorCPUFeatures(const CPUFeatures& features);
6567   void SaveSimulatorCPUFeatures();
6568   void RestoreSimulatorCPUFeatures();
6569 
GetLiteralPool()6570   LiteralPool* GetLiteralPool() { return &literal_pool_; }
6571 
6572 // Support for simulated runtime calls.
6573 
6574 // `CallRuntime` requires variadic templating, that is only available from
6575 // C++11.
6576 #if __cplusplus >= 201103L
6577 #define VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
6578 #endif  // #if __cplusplus >= 201103L
6579 
6580 #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
6581   template <typename R, typename... P>
6582   void CallRuntimeHelper(R (*function)(P...), RuntimeCallType call_type);
6583 
6584   template <typename R, typename... P>
CallRuntime(R (* function)(P...))6585   void CallRuntime(R (*function)(P...)) {
6586     CallRuntimeHelper(function, kCallRuntime);
6587   }
6588 
6589   template <typename R, typename... P>
TailCallRuntime(R (* function)(P...))6590   void TailCallRuntime(R (*function)(P...)) {
6591     CallRuntimeHelper(function, kTailCallRuntime);
6592   }
6593 #endif  // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
6594 
6595  protected:
BlockLiteralPool()6596   void BlockLiteralPool() { literal_pool_.Block(); }
ReleaseLiteralPool()6597   void ReleaseLiteralPool() { literal_pool_.Release(); }
IsLiteralPoolBlocked()6598   bool IsLiteralPoolBlocked() const { return literal_pool_.IsBlocked(); }
BlockVeneerPool()6599   void BlockVeneerPool() { veneer_pool_.Block(); }
ReleaseVeneerPool()6600   void ReleaseVeneerPool() { veneer_pool_.Release(); }
IsVeneerPoolBlocked()6601   bool IsVeneerPoolBlocked() const { return veneer_pool_.IsBlocked(); }
6602 
BlockPools()6603   virtual void BlockPools() VIXL_OVERRIDE {
6604     BlockLiteralPool();
6605     BlockVeneerPool();
6606   }
6607 
ReleasePools()6608   virtual void ReleasePools() VIXL_OVERRIDE {
6609     ReleaseLiteralPool();
6610     ReleaseVeneerPool();
6611   }
6612 
6613   // The scopes below need to able to block and release a particular pool.
6614   // TODO: Consider removing those scopes or move them to
6615   // code-generation-scopes-vixl.h.
6616   friend class BlockPoolsScope;
6617   friend class BlockLiteralPoolScope;
6618   friend class BlockVeneerPoolScope;
6619 
SetAllowMacroInstructions(bool value)6620   virtual void SetAllowMacroInstructions(bool value) VIXL_OVERRIDE {
6621     allow_macro_instructions_ = value;
6622   }
6623 
6624   // Helper used to query information about code generation and to generate
6625   // code for `csel`.
6626   // Here and for the related helpers below:
6627   // - Code is generated when `masm` is not `NULL`.
6628   // - On return and when set, `should_synthesise_left` and
6629   //   `should_synthesise_right` will indicate whether `left` and `right`
6630   //   should be synthesized in a temporary register.
6631   static void CselHelper(MacroAssembler* masm,
6632                          const Register& rd,
6633                          Operand left,
6634                          Operand right,
6635                          Condition cond,
6636                          bool* should_synthesise_left = NULL,
6637                          bool* should_synthesise_right = NULL);
6638 
6639   // The helper returns `true` if it can handle the specified arguments.
6640   // Also see comments for `CselHelper()`.
6641   static bool CselSubHelperTwoImmediates(MacroAssembler* masm,
6642                                          const Register& rd,
6643                                          int64_t left,
6644                                          int64_t right,
6645                                          Condition cond,
6646                                          bool* should_synthesise_left,
6647                                          bool* should_synthesise_right);
6648 
6649   // See comments for `CselHelper()`.
6650   static bool CselSubHelperTwoOrderedImmediates(MacroAssembler* masm,
6651                                                 const Register& rd,
6652                                                 int64_t left,
6653                                                 int64_t right,
6654                                                 Condition cond);
6655 
6656   // See comments for `CselHelper()`.
6657   static void CselSubHelperRightSmallImmediate(MacroAssembler* masm,
6658                                                UseScratchRegisterScope* temps,
6659                                                const Register& rd,
6660                                                const Operand& left,
6661                                                const Operand& right,
6662                                                Condition cond,
6663                                                bool* should_synthesise_left);
6664 
6665   // Generate code to calculate the address represented by `addr` and write it
6666   // into `xd`. This is used as a common fall-back for out-of-range load and
6667   // store operands.
6668   //
6669   // The vl_divisor_log2 argument is used to scale the VL, for use with
6670   // SVE_MUL_VL.
6671   void CalculateSVEAddress(const Register& xd,
6672                            const SVEMemOperand& addr,
6673                            int vl_divisor_log2 = 0);
6674 
CalculateSVEAddress(const Register & xd,const SVEMemOperand & addr,const CPURegister & rt)6675   void CalculateSVEAddress(const Register& xd,
6676                            const SVEMemOperand& addr,
6677                            const CPURegister& rt) {
6678     VIXL_ASSERT(rt.IsPRegister() || rt.IsZRegister());
6679     int vl_divisor_log2 = rt.IsPRegister() ? kZRegBitsPerPRegBitLog2 : 0;
6680     CalculateSVEAddress(xd, addr, vl_divisor_log2);
6681   }
6682 
SetFPNaNPropagationOption(FPMacroNaNPropagationOption nan_option)6683   void SetFPNaNPropagationOption(FPMacroNaNPropagationOption nan_option) {
6684     fp_nan_propagation_ = nan_option;
6685   }
6686 
ResolveFPNaNPropagationOption(FPMacroNaNPropagationOption * nan_option)6687   void ResolveFPNaNPropagationOption(FPMacroNaNPropagationOption* nan_option) {
6688     // The input option has priority over the option that has set.
6689     if (*nan_option == NoFPMacroNaNPropagationSelected) {
6690       *nan_option = fp_nan_propagation_;
6691     }
6692     VIXL_ASSERT(*nan_option != NoFPMacroNaNPropagationSelected);
6693   }
6694 
6695  private:
6696   // The actual Push and Pop implementations. These don't generate any code
6697   // other than that required for the push or pop. This allows
6698   // (Push|Pop)CPURegList to bundle together setup code for a large block of
6699   // registers.
6700   //
6701   // Note that size is per register, and is specified in bytes.
6702   void PushHelper(int count,
6703                   int size,
6704                   const CPURegister& src0,
6705                   const CPURegister& src1,
6706                   const CPURegister& src2,
6707                   const CPURegister& src3);
6708   void PopHelper(int count,
6709                  int size,
6710                  const CPURegister& dst0,
6711                  const CPURegister& dst1,
6712                  const CPURegister& dst2,
6713                  const CPURegister& dst3);
6714 
6715   void Movi16bitHelper(const VRegister& vd, uint64_t imm);
6716   void Movi32bitHelper(const VRegister& vd, uint64_t imm);
6717   void Movi64bitHelper(const VRegister& vd, uint64_t imm);
6718 
6719   // Perform necessary maintenance operations before a push or pop.
6720   //
6721   // Note that size is per register, and is specified in bytes.
6722   void PrepareForPush(int count, int size);
6723   void PrepareForPop(int count, int size);
6724 
6725   // The actual implementation of load and store operations for CPURegList.
6726   enum LoadStoreCPURegListAction { kLoad, kStore };
6727   void LoadStoreCPURegListHelper(LoadStoreCPURegListAction operation,
6728                                  CPURegList registers,
6729                                  const MemOperand& mem);
6730   // Returns a MemOperand suitable for loading or storing a CPURegList at `dst`.
6731   // This helper may allocate registers from `scratch_scope` and generate code
6732   // to compute an intermediate address. The resulting MemOperand is only valid
6733   // as long as `scratch_scope` remains valid.
6734   MemOperand BaseMemOperandForLoadStoreCPURegList(
6735       const CPURegList& registers,
6736       const MemOperand& mem,
6737       UseScratchRegisterScope* scratch_scope);
6738 
LabelIsOutOfRange(Label * label,ImmBranchType branch_type)6739   bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) {
6740     return !Instruction::IsValidImmPCOffset(branch_type,
6741                                             label->GetLocation() -
6742                                                 GetCursorOffset());
6743   }
6744 
6745   void ConfigureSimulatorCPUFeaturesHelper(const CPUFeatures& features,
6746                                            DebugHltOpcode action);
6747 
6748   void CompareHelper(Condition cond,
6749                      const PRegisterWithLaneSize& pd,
6750                      const PRegisterZ& pg,
6751                      const ZRegister& zn,
6752                      IntegerOperand imm);
6753 
6754   // E.g. Ld1rb.
6755   typedef void (Assembler::*SVELoadBroadcastFn)(const ZRegister& zt,
6756                                                 const PRegisterZ& pg,
6757                                                 const SVEMemOperand& addr);
6758 
6759   void SVELoadBroadcastImmHelper(const ZRegister& zt,
6760                                  const PRegisterZ& pg,
6761                                  const SVEMemOperand& addr,
6762                                  SVELoadBroadcastFn fn,
6763                                  int divisor);
6764 
6765   // E.g. ldr/str
6766   typedef void (Assembler::*SVELoadStoreFn)(const CPURegister& rt,
6767                                             const SVEMemOperand& addr);
6768 
6769   void SVELoadStoreScalarImmHelper(const CPURegister& rt,
6770                                    const SVEMemOperand& addr,
6771                                    SVELoadStoreFn fn);
6772 
6773   typedef void (Assembler::*SVELoad1Fn)(const ZRegister& zt,
6774                                         const PRegisterZ& pg,
6775                                         const SVEMemOperand& addr);
6776   typedef void (Assembler::*SVEStore1Fn)(const ZRegister& zt,
6777                                          const PRegister& pg,
6778                                          const SVEMemOperand& addr);
6779 
6780   // Helper for predicated Z register loads with addressing modes not directly
6781   // encodable in the instruction. The supported_modifier parameter indicates
6782   // which offset modifier the calling instruction encoder supports (eg.
6783   // SVE_MUL_VL). The ratio log2 of VL to memory access size is passed as
6784   // vl_divisor_log2; pass -1 to indicate no dependency.
6785   template <typename Tg, typename Tf>
6786   void SVELoadStoreScalarImmHelper(
6787       const ZRegister& zt,
6788       const Tg& pg,
6789       const SVEMemOperand& addr,
6790       Tf fn,
6791       int imm_bits,
6792       int shift_amount,
6793       SVEOffsetModifier supported_modifier = NO_SVE_OFFSET_MODIFIER,
6794       int vl_divisor_log2 = 0);
6795 
6796   template <typename Tg, typename Tf>
6797   void SVELoadStore1Helper(int msize_in_bytes_log2,
6798                            const ZRegister& zt,
6799                            const Tg& pg,
6800                            const SVEMemOperand& addr,
6801                            Tf fn);
6802 
6803   template <typename Tf>
6804   void SVELoadFFHelper(int msize_in_bytes_log2,
6805                        const ZRegister& zt,
6806                        const PRegisterZ& pg,
6807                        const SVEMemOperand& addr,
6808                        Tf fn);
6809 
6810   typedef void (MacroAssembler::*IntWideImmMacroFn)(const ZRegister& zd,
6811                                                     const ZRegister& zn,
6812                                                     IntegerOperand imm);
6813 
6814   typedef void (Assembler::*IntWideImmShiftFn)(const ZRegister& zd,
6815                                                const ZRegister& zn,
6816                                                int imm,
6817                                                int shift);
6818 
6819   typedef void (Assembler::*IntArithFn)(const ZRegister& zd,
6820                                         const ZRegister& zn,
6821                                         const ZRegister& zm);
6822 
6823   typedef void (Assembler::*IntWideImmFn)(const ZRegister& zd,
6824                                           const ZRegister& zn,
6825                                           int imm);
6826 
6827   typedef void (Assembler::*IntArithIndexFn)(const ZRegister& zd,
6828                                              const ZRegister& zn,
6829                                              const ZRegister& zm,
6830                                              int index);
6831 
6832   typedef void (MacroAssembler::*SVEArithPredicatedFn)(const ZRegister& zd,
6833                                                        const PRegisterM& pg,
6834                                                        const ZRegister& zn,
6835                                                        const ZRegister& zm);
6836 
6837   void IntWideImmHelper(IntWideImmFn imm_fn,
6838                         SVEArithPredicatedFn reg_fn,
6839                         const ZRegister& zd,
6840                         const ZRegister& zn,
6841                         IntegerOperand imm,
6842                         bool is_signed_imm);
6843 
6844   enum AddSubHelperOption { kAddImmediate, kSubImmediate };
6845 
6846   void AddSubHelper(AddSubHelperOption option,
6847                     const ZRegister& zd,
6848                     const ZRegister& zn,
6849                     IntegerOperand imm);
6850 
6851   // Try to emit an add- or sub-like instruction (imm_fn) with `imm`, or the
6852   // corresponding sub- or add-like instruction (n_imm_fn) with a negated `imm`.
6853   // A `movprfx` is automatically generated if one is required. If successful,
6854   // return true. Otherwise, return false.
6855   //
6856   // This helper uses two's complement equivalences, for example treating 0xffff
6857   // as -1 for H-sized lanes.
6858   bool TrySingleAddSub(AddSubHelperOption option,
6859                        const ZRegister& zd,
6860                        const ZRegister& zn,
6861                        IntegerOperand imm);
6862 
6863   void SVESdotUdotHelper(IntArithFn fn,
6864                          const ZRegister& zd,
6865                          const ZRegister& za,
6866                          const ZRegister& zn,
6867                          const ZRegister& zm);
6868 
6869   void SVESdotUdotIndexHelper(IntArithIndexFn fn,
6870                               const ZRegister& zd,
6871                               const ZRegister& za,
6872                               const ZRegister& zn,
6873                               const ZRegister& zm,
6874                               int index);
6875 
6876   // For noncommutative arithmetic operations.
6877   void NoncommutativeArithmeticHelper(const ZRegister& zd,
6878                                       const PRegisterM& pg,
6879                                       const ZRegister& zn,
6880                                       const ZRegister& zm,
6881                                       SVEArithPredicatedFn fn,
6882                                       SVEArithPredicatedFn rev_fn);
6883 
6884   void FPCommutativeArithmeticHelper(const ZRegister& zd,
6885                                      const PRegisterM& pg,
6886                                      const ZRegister& zn,
6887                                      const ZRegister& zm,
6888                                      SVEArithPredicatedFn fn,
6889                                      FPMacroNaNPropagationOption nan_option);
6890 
6891   // Floating-point fused multiply-add vectors (predicated), writing addend.
6892   typedef void (Assembler::*SVEMulAddPredicatedZdaFn)(const ZRegister& zda,
6893                                                       const PRegisterM& pg,
6894                                                       const ZRegister& zn,
6895                                                       const ZRegister& zm);
6896 
6897   // Floating-point fused multiply-add vectors (predicated), writing
6898   // multiplicand.
6899   typedef void (Assembler::*SVEMulAddPredicatedZdnFn)(const ZRegister& zdn,
6900                                                       const PRegisterM& pg,
6901                                                       const ZRegister& zn,
6902                                                       const ZRegister& zm);
6903 
6904   void FPMulAddHelper(const ZRegister& zd,
6905                       const PRegisterM& pg,
6906                       const ZRegister& za,
6907                       const ZRegister& zn,
6908                       const ZRegister& zm,
6909                       SVEMulAddPredicatedZdaFn fn_zda,
6910                       SVEMulAddPredicatedZdnFn fn_zdn,
6911                       FPMacroNaNPropagationOption nan_option);
6912 
6913   typedef void (Assembler::*SVEMulAddIndexFn)(const ZRegister& zda,
6914                                               const ZRegister& zn,
6915                                               const ZRegister& zm,
6916                                               int index);
6917 
6918   void FPMulAddIndexHelper(SVEMulAddIndexFn fn,
6919                            const ZRegister& zd,
6920                            const ZRegister& za,
6921                            const ZRegister& zn,
6922                            const ZRegister& zm,
6923                            int index);
6924 
6925   // Tell whether any of the macro instruction can be used. When false the
6926   // MacroAssembler will assert if a method which can emit a variable number
6927   // of instructions is called.
6928   bool allow_macro_instructions_;
6929 
6930   // Indicates whether we should generate simulator or native code.
6931   bool generate_simulator_code_;
6932 
6933   // The register to use as a stack pointer for stack operations.
6934   Register sp_;
6935 
6936   // Scratch registers available for use by the MacroAssembler.
6937   CPURegList tmp_list_;
6938   CPURegList v_tmp_list_;
6939   CPURegList p_tmp_list_;
6940 
6941   UseScratchRegisterScope* current_scratch_scope_;
6942 
6943   LiteralPool literal_pool_;
6944   VeneerPool veneer_pool_;
6945 
6946   ptrdiff_t checkpoint_;
6947   ptrdiff_t recommended_checkpoint_;
6948 
6949   FPMacroNaNPropagationOption fp_nan_propagation_;
6950 
6951   friend class Pool;
6952   friend class LiteralPool;
6953 };
6954 
6955 
GetOtherPoolsMaxSize()6956 inline size_t VeneerPool::GetOtherPoolsMaxSize() const {
6957   return masm_->GetLiteralPoolMaxSize();
6958 }
6959 
6960 
GetOtherPoolsMaxSize()6961 inline size_t LiteralPool::GetOtherPoolsMaxSize() const {
6962   return masm_->GetVeneerPoolMaxSize();
6963 }
6964 
6965 
SetNextRecommendedCheckpoint(ptrdiff_t offset)6966 inline void LiteralPool::SetNextRecommendedCheckpoint(ptrdiff_t offset) {
6967   masm_->recommended_checkpoint_ =
6968       std::min(masm_->recommended_checkpoint_, offset);
6969   recommended_checkpoint_ = offset;
6970 }
6971 
6972 class InstructionAccurateScope : public ExactAssemblyScope {
6973  public:
6974   VIXL_DEPRECATED("ExactAssemblyScope",
6975                   InstructionAccurateScope(MacroAssembler* masm,
6976                                            int64_t count,
6977                                            SizePolicy size_policy = kExactSize))
ExactAssemblyScope(masm,count * kInstructionSize,size_policy)6978       : ExactAssemblyScope(masm, count * kInstructionSize, size_policy) {}
6979 };
6980 
6981 class BlockLiteralPoolScope {
6982  public:
BlockLiteralPoolScope(MacroAssembler * masm)6983   explicit BlockLiteralPoolScope(MacroAssembler* masm) : masm_(masm) {
6984     masm_->BlockLiteralPool();
6985   }
6986 
~BlockLiteralPoolScope()6987   ~BlockLiteralPoolScope() { masm_->ReleaseLiteralPool(); }
6988 
6989  private:
6990   MacroAssembler* masm_;
6991 };
6992 
6993 
6994 class BlockVeneerPoolScope {
6995  public:
BlockVeneerPoolScope(MacroAssembler * masm)6996   explicit BlockVeneerPoolScope(MacroAssembler* masm) : masm_(masm) {
6997     masm_->BlockVeneerPool();
6998   }
6999 
~BlockVeneerPoolScope()7000   ~BlockVeneerPoolScope() { masm_->ReleaseVeneerPool(); }
7001 
7002  private:
7003   MacroAssembler* masm_;
7004 };
7005 
7006 
7007 class BlockPoolsScope {
7008  public:
BlockPoolsScope(MacroAssembler * masm)7009   explicit BlockPoolsScope(MacroAssembler* masm) : masm_(masm) {
7010     masm_->BlockPools();
7011   }
7012 
~BlockPoolsScope()7013   ~BlockPoolsScope() { masm_->ReleasePools(); }
7014 
7015  private:
7016   MacroAssembler* masm_;
7017 };
7018 
MovprfxHelperScope(MacroAssembler * masm,const ZRegister & dst,const ZRegister & src)7019 MovprfxHelperScope::MovprfxHelperScope(MacroAssembler* masm,
7020                                        const ZRegister& dst,
7021                                        const ZRegister& src)
7022     : ExactAssemblyScope(masm,
7023                          ShouldGenerateMovprfx(dst, src)
7024                              ? (2 * kInstructionSize)
7025                              : kInstructionSize) {
7026   if (ShouldGenerateMovprfx(dst, src)) {
7027     masm->movprfx(dst, src);
7028   }
7029 }
7030 
MovprfxHelperScope(MacroAssembler * masm,const ZRegister & dst,const PRegister & pg,const ZRegister & src)7031 MovprfxHelperScope::MovprfxHelperScope(MacroAssembler* masm,
7032                                        const ZRegister& dst,
7033                                        const PRegister& pg,
7034                                        const ZRegister& src)
7035     : ExactAssemblyScope(masm,
7036                          ShouldGenerateMovprfx(dst, pg, src)
7037                              ? (2 * kInstructionSize)
7038                              : kInstructionSize) {
7039   if (ShouldGenerateMovprfx(dst, pg, src)) {
7040     masm->movprfx(dst, pg, src);
7041   }
7042 }
7043 
7044 // This scope utility allows scratch registers to be managed safely. The
7045 // MacroAssembler's GetScratch*RegisterList() are used as a pool of scratch
7046 // registers. These registers can be allocated on demand, and will be returned
7047 // at the end of the scope.
7048 //
7049 // When the scope ends, the MacroAssembler's lists will be restored to their
7050 // original state, even if the lists were modified by some other means.
7051 class UseScratchRegisterScope {
7052  public:
7053   // This constructor implicitly calls `Open` to initialise the scope (`masm`
7054   // must not be `NULL`), so it is ready to use immediately after it has been
7055   // constructed.
UseScratchRegisterScope(MacroAssembler * masm)7056   explicit UseScratchRegisterScope(MacroAssembler* masm)
7057       : masm_(NULL),
7058         parent_(NULL),
7059         old_available_(0),
7060         old_available_v_(0),
7061         old_available_p_(0) {
7062     Open(masm);
7063   }
7064   // This constructor does not implicitly initialise the scope. Instead, the
7065   // user is required to explicitly call the `Open` function before using the
7066   // scope.
UseScratchRegisterScope()7067   UseScratchRegisterScope()
7068       : masm_(NULL),
7069         parent_(NULL),
7070         old_available_(0),
7071         old_available_v_(0),
7072         old_available_p_(0) {}
7073 
7074   // This function performs the actual initialisation work.
7075   void Open(MacroAssembler* masm);
7076 
7077   // The destructor always implicitly calls the `Close` function.
~UseScratchRegisterScope()7078   ~UseScratchRegisterScope() { Close(); }
7079 
7080   // This function performs the cleaning-up work. It must succeed even if the
7081   // scope has not been opened. It is safe to call multiple times.
7082   void Close();
7083 
7084 
7085   bool IsAvailable(const CPURegister& reg) const;
7086 
7087   // Take a register from the appropriate temps list. It will be returned
7088   // automatically when the scope ends.
AcquireW()7089   Register AcquireW() {
7090     return AcquireFrom(masm_->GetScratchRegisterList()).W();
7091   }
AcquireX()7092   Register AcquireX() {
7093     return AcquireFrom(masm_->GetScratchRegisterList()).X();
7094   }
AcquireH()7095   VRegister AcquireH() {
7096     return AcquireFrom(masm_->GetScratchVRegisterList()).H();
7097   }
AcquireS()7098   VRegister AcquireS() {
7099     return AcquireFrom(masm_->GetScratchVRegisterList()).S();
7100   }
AcquireD()7101   VRegister AcquireD() {
7102     return AcquireFrom(masm_->GetScratchVRegisterList()).D();
7103   }
AcquireZ()7104   ZRegister AcquireZ() {
7105     return AcquireFrom(masm_->GetScratchVRegisterList()).Z();
7106   }
AcquireP()7107   PRegister AcquireP() {
7108     // Prefer to allocate p8-p15 if we can, to leave p0-p7 available for use as
7109     // governing predicates.
7110     CPURegList* available = masm_->GetScratchPRegisterList();
7111     RegList preferred = ~kGoverningPRegisterMask;
7112     if ((available->GetList() & preferred) != 0) {
7113       return AcquireFrom(available, preferred).P();
7114     }
7115     return AcquireFrom(available).P();
7116   }
7117   // Acquire a P register suitable for use as a governing predicate in
7118   // instructions which only accept p0-p7 for that purpose.
AcquireGoverningP()7119   PRegister AcquireGoverningP() {
7120     CPURegList* available = masm_->GetScratchPRegisterList();
7121     return AcquireFrom(available, kGoverningPRegisterMask).P();
7122   }
7123 
7124   Register AcquireRegisterOfSize(int size_in_bits);
AcquireSameSizeAs(const Register & reg)7125   Register AcquireSameSizeAs(const Register& reg) {
7126     return AcquireRegisterOfSize(reg.GetSizeInBits());
7127   }
7128   VRegister AcquireVRegisterOfSize(int size_in_bits);
AcquireSameSizeAs(const VRegister & reg)7129   VRegister AcquireSameSizeAs(const VRegister& reg) {
7130     return AcquireVRegisterOfSize(reg.GetSizeInBits());
7131   }
AcquireCPURegisterOfSize(int size_in_bits)7132   CPURegister AcquireCPURegisterOfSize(int size_in_bits) {
7133     return masm_->GetScratchRegisterList()->IsEmpty()
7134                ? CPURegister(AcquireVRegisterOfSize(size_in_bits))
7135                : CPURegister(AcquireRegisterOfSize(size_in_bits));
7136   }
7137 
7138   // Acquire a register big enough to represent one lane of `vector`.
AcquireRegisterToHoldLane(const CPURegister & vector)7139   Register AcquireRegisterToHoldLane(const CPURegister& vector) {
7140     VIXL_ASSERT(vector.GetLaneSizeInBits() <= kXRegSize);
7141     return (vector.GetLaneSizeInBits() > kWRegSize) ? AcquireX() : AcquireW();
7142   }
7143 
7144 
7145   // Explicitly release an acquired (or excluded) register, putting it back in
7146   // the appropriate temps list.
7147   void Release(const CPURegister& reg);
7148 
7149 
7150   // Make the specified registers available as scratch registers for the
7151   // duration of this scope.
7152   void Include(const CPURegList& list);
7153   void Include(const Register& reg1,
7154                const Register& reg2 = NoReg,
7155                const Register& reg3 = NoReg,
7156                const Register& reg4 = NoReg);
7157   void Include(const VRegister& reg1,
7158                const VRegister& reg2 = NoVReg,
7159                const VRegister& reg3 = NoVReg,
7160                const VRegister& reg4 = NoVReg);
7161   void Include(const CPURegister& reg1,
7162                const CPURegister& reg2 = NoCPUReg,
7163                const CPURegister& reg3 = NoCPUReg,
7164                const CPURegister& reg4 = NoCPUReg);
7165 
7166 
7167   // Make sure that the specified registers are not available in this scope.
7168   // This can be used to prevent helper functions from using sensitive
7169   // registers, for example.
7170   void Exclude(const CPURegList& list);
7171   void Exclude(const Register& reg1,
7172                const Register& reg2 = NoReg,
7173                const Register& reg3 = NoReg,
7174                const Register& reg4 = NoReg);
7175   void Exclude(const VRegister& reg1,
7176                const VRegister& reg2 = NoVReg,
7177                const VRegister& reg3 = NoVReg,
7178                const VRegister& reg4 = NoVReg);
7179   void Exclude(const CPURegister& reg1,
7180                const CPURegister& reg2 = NoCPUReg,
7181                const CPURegister& reg3 = NoCPUReg,
7182                const CPURegister& reg4 = NoCPUReg);
7183 
7184   // Convenience for excluding registers that are part of Operands. This is
7185   // useful for sequences like this:
7186   //
7187   //    // Use 'rd' as a scratch, but only if it's not aliased by an input.
7188   //    temps.Include(rd);
7189   //    temps.Exclude(rn);
7190   //    temps.Exclude(operand);
7191   //
7192   // Otherwise, a conditional check is needed on the last 'Exclude'.
Exclude(const Operand & operand)7193   void Exclude(const Operand& operand) {
7194     if (operand.IsShiftedRegister() || operand.IsExtendedRegister()) {
7195       Exclude(operand.GetRegister());
7196     } else {
7197       VIXL_ASSERT(operand.IsImmediate());
7198     }
7199   }
7200 
7201   // Prevent any scratch registers from being used in this scope.
7202   void ExcludeAll();
7203 
7204  private:
7205   static CPURegister AcquireFrom(CPURegList* available,
7206                                  RegList mask = ~static_cast<RegList>(0));
7207 
7208   static void ReleaseByCode(CPURegList* available, int code);
7209   static void ReleaseByRegList(CPURegList* available, RegList regs);
7210   static void IncludeByRegList(CPURegList* available, RegList exclude);
7211   static void ExcludeByRegList(CPURegList* available, RegList exclude);
7212 
7213   CPURegList* GetAvailableListFor(CPURegister::RegisterBank bank);
7214 
7215   static const RegList kGoverningPRegisterMask =
7216       (static_cast<RegList>(1) << kNumberOfGoverningPRegisters) - 1;
7217 
7218   // The MacroAssembler maintains a list of available scratch registers, and
7219   // also keeps track of the most recently-opened scope so that on destruction
7220   // we can check that scopes do not outlive their parents.
7221   MacroAssembler* masm_;
7222   UseScratchRegisterScope* parent_;
7223 
7224   // The state of the available lists at the start of this scope.
7225   RegList old_available_;    // kRegister
7226   RegList old_available_v_;  // kVRegister / kZRegister
7227   RegList old_available_p_;  // kPRegister
7228 
7229   // Disallow copy constructor and operator=.
UseScratchRegisterScope(const UseScratchRegisterScope &)7230   VIXL_NO_RETURN_IN_DEBUG_MODE UseScratchRegisterScope(
7231       const UseScratchRegisterScope&) {
7232     VIXL_UNREACHABLE();
7233   }
7234   VIXL_NO_RETURN_IN_DEBUG_MODE void operator=(const UseScratchRegisterScope&) {
7235     VIXL_UNREACHABLE();
7236   }
7237 };
7238 
7239 
7240 // Like CPUFeaturesScope, but also generate Simulation pseudo-instructions to
7241 // control a Simulator's CPUFeatures dynamically.
7242 //
7243 // One major difference from CPUFeaturesScope is that this scope cannot offer
7244 // a writable "CPUFeatures* GetCPUFeatures()", because every write to the
7245 // features needs a corresponding macro instruction.
7246 class SimulationCPUFeaturesScope {
7247  public:
7248   template <typename... T>
SimulationCPUFeaturesScope(MacroAssembler * masm,T...features)7249   explicit SimulationCPUFeaturesScope(MacroAssembler* masm, T... features)
7250       : masm_(masm), cpu_features_scope_(masm, features...) {
7251     masm_->SaveSimulatorCPUFeatures();
7252     masm_->EnableSimulatorCPUFeatures(CPUFeatures(features...));
7253   }
7254 
~SimulationCPUFeaturesScope()7255   ~SimulationCPUFeaturesScope() { masm_->RestoreSimulatorCPUFeatures(); }
7256 
GetCPUFeatures()7257   const CPUFeatures* GetCPUFeatures() const {
7258     return cpu_features_scope_.GetCPUFeatures();
7259   }
7260 
SetCPUFeatures(const CPUFeatures & cpu_features)7261   void SetCPUFeatures(const CPUFeatures& cpu_features) {
7262     cpu_features_scope_.SetCPUFeatures(cpu_features);
7263     masm_->SetSimulatorCPUFeatures(cpu_features);
7264   }
7265 
7266  private:
7267   MacroAssembler* masm_;
7268   CPUFeaturesScope cpu_features_scope_;
7269 };
7270 
7271 
7272 // Variadic templating is only available from C++11.
7273 #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
7274 
7275 // `R` stands for 'return type', and `P` for 'parameter types'.
7276 template <typename R, typename... P>
CallRuntimeHelper(R (* function)(P...),RuntimeCallType call_type)7277 void MacroAssembler::CallRuntimeHelper(R (*function)(P...),
7278                                        RuntimeCallType call_type) {
7279   if (generate_simulator_code_) {
7280 #ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
7281     uintptr_t runtime_call_wrapper_address = reinterpret_cast<uintptr_t>(
7282         &(Simulator::RuntimeCallStructHelper<R, P...>::Wrapper));
7283     uintptr_t function_address = reinterpret_cast<uintptr_t>(function);
7284 
7285     EmissionCheckScope guard(this,
7286                              kRuntimeCallLength,
7287                              CodeBufferCheckScope::kExactSize);
7288     Label start;
7289     bind(&start);
7290     {
7291       ExactAssemblyScope scope(this, kInstructionSize);
7292       hlt(kRuntimeCallOpcode);
7293     }
7294     VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) ==
7295                 kRuntimeCallWrapperOffset);
7296     dc(runtime_call_wrapper_address);
7297     VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) ==
7298                 kRuntimeCallFunctionOffset);
7299     dc(function_address);
7300     VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kRuntimeCallTypeOffset);
7301     dc32(call_type);
7302     VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kRuntimeCallLength);
7303 #else
7304     VIXL_UNREACHABLE();
7305 #endif  // #ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
7306   } else {
7307     UseScratchRegisterScope temps(this);
7308     Register temp = temps.AcquireX();
7309     Mov(temp, reinterpret_cast<uint64_t>(function));
7310     if (call_type == kTailCallRuntime) {
7311       Br(temp);
7312     } else {
7313       VIXL_ASSERT(call_type == kCallRuntime);
7314       Blr(temp);
7315     }
7316   }
7317 }
7318 
7319 #endif  // #ifdef VIXL_HAS_MACROASSEMBLER_RUNTIME_CALL_SUPPORT
7320 
7321 }  // namespace aarch64
7322 
7323 // Required InvalSet template specialisations.
7324 // TODO: These template specialisations should not live in this file.  Move
7325 // VeneerPool out of the aarch64 namespace in order to share its implementation
7326 // later.
7327 template <>
7328 inline ptrdiff_t InvalSet<aarch64::VeneerPool::BranchInfo,
7329                           aarch64::VeneerPool::kNPreallocatedInfos,
7330                           ptrdiff_t,
7331                           aarch64::VeneerPool::kInvalidOffset,
7332                           aarch64::VeneerPool::kReclaimFrom,
7333                           aarch64::VeneerPool::kReclaimFactor>::
GetKey(const aarch64::VeneerPool::BranchInfo & branch_info)7334     GetKey(const aarch64::VeneerPool::BranchInfo& branch_info) {
7335   return branch_info.first_unreacheable_pc_;
7336 }
7337 template <>
7338 inline void InvalSet<aarch64::VeneerPool::BranchInfo,
7339                      aarch64::VeneerPool::kNPreallocatedInfos,
7340                      ptrdiff_t,
7341                      aarch64::VeneerPool::kInvalidOffset,
7342                      aarch64::VeneerPool::kReclaimFrom,
7343                      aarch64::VeneerPool::kReclaimFactor>::
SetKey(aarch64::VeneerPool::BranchInfo * branch_info,ptrdiff_t key)7344     SetKey(aarch64::VeneerPool::BranchInfo* branch_info, ptrdiff_t key) {
7345   branch_info->first_unreacheable_pc_ = key;
7346 }
7347 
7348 }  // namespace vixl
7349 
7350 #endif  // VIXL_AARCH64_MACRO_ASSEMBLER_AARCH64_H_
7351