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