• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013, ARM Limited
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #ifndef VIXL_A64_MACRO_ASSEMBLER_A64_H_
28 #define VIXL_A64_MACRO_ASSEMBLER_A64_H_
29 
30 #include "globals-vixl.h"
31 #include "a64/assembler-a64.h"
32 #include "a64/debugger-a64.h"
33 
34 
35 #define LS_MACRO_LIST(V)                                      \
36   V(Ldrb, Register&, rt, LDRB_w)                              \
37   V(Strb, Register&, rt, STRB_w)                              \
38   V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w)  \
39   V(Ldrh, Register&, rt, LDRH_w)                              \
40   V(Strh, Register&, rt, STRH_w)                              \
41   V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w)  \
42   V(Ldr, CPURegister&, rt, LoadOpFor(rt))                     \
43   V(Str, CPURegister&, rt, StoreOpFor(rt))                    \
44   V(Ldrsw, Register&, rt, LDRSW_x)
45 
46 namespace vixl {
47 
48 enum BranchType {
49   // Copies of architectural conditions.
50   // The associated conditions can be used in place of those, the code will
51   // take care of reinterpreting them with the correct type.
52   integer_eq = eq,
53   integer_ne = ne,
54   integer_hs = hs,
55   integer_lo = lo,
56   integer_mi = mi,
57   integer_pl = pl,
58   integer_vs = vs,
59   integer_vc = vc,
60   integer_hi = hi,
61   integer_ls = ls,
62   integer_ge = ge,
63   integer_lt = lt,
64   integer_gt = gt,
65   integer_le = le,
66   integer_al = al,
67   integer_nv = nv,
68 
69   // These two are *different* from the architectural codes al and nv.
70   // 'always' is used to generate unconditional branches.
71   // 'never' is used to not generate a branch (generally as the inverse
72   // branch type of 'always).
73   always, never,
74   // cbz and cbnz
75   reg_zero, reg_not_zero,
76   // tbz and tbnz
77   reg_bit_clear, reg_bit_set,
78 
79   // Aliases.
80   kBranchTypeFirstCondition = eq,
81   kBranchTypeLastCondition = nv,
82   kBranchTypeFirstUsingReg = reg_zero,
83   kBranchTypeFirstUsingBit = reg_bit_clear
84 };
85 
86 
87 enum DiscardMoveMode { kDontDiscardForSameWReg, kDiscardForSameWReg };
88 
89 class MacroAssembler : public Assembler {
90  public:
MacroAssembler(byte * buffer,unsigned buffer_size)91   MacroAssembler(byte * buffer, unsigned buffer_size)
92       : Assembler(buffer, buffer_size),
93 #ifdef DEBUG
94         allow_macro_instructions_(true),
95 #endif
96         sp_(sp), tmp_list_(ip0, ip1), fptmp_list_(d31) {}
97 
98   // Logical macros.
99   void And(const Register& rd,
100            const Register& rn,
101            const Operand& operand);
102   void Ands(const Register& rd,
103             const Register& rn,
104             const Operand& operand);
105   void Bic(const Register& rd,
106            const Register& rn,
107            const Operand& operand);
108   void Bics(const Register& rd,
109             const Register& rn,
110             const Operand& operand);
111   void Orr(const Register& rd,
112            const Register& rn,
113            const Operand& operand);
114   void Orn(const Register& rd,
115            const Register& rn,
116            const Operand& operand);
117   void Eor(const Register& rd,
118            const Register& rn,
119            const Operand& operand);
120   void Eon(const Register& rd,
121            const Register& rn,
122            const Operand& operand);
123   void Tst(const Register& rn, const Operand& operand);
124   void LogicalMacro(const Register& rd,
125                     const Register& rn,
126                     const Operand& operand,
127                     LogicalOp op);
128 
129   // Add and sub macros.
130   void Add(const Register& rd,
131            const Register& rn,
132            const Operand& operand);
133   void Adds(const Register& rd,
134             const Register& rn,
135             const Operand& operand);
136   void Sub(const Register& rd,
137            const Register& rn,
138            const Operand& operand);
139   void Subs(const Register& rd,
140             const Register& rn,
141             const Operand& operand);
142   void Cmn(const Register& rn, const Operand& operand);
143   void Cmp(const Register& rn, const Operand& operand);
144   void Neg(const Register& rd,
145            const Operand& operand);
146   void Negs(const Register& rd,
147             const Operand& operand);
148 
149   void AddSubMacro(const Register& rd,
150                    const Register& rn,
151                    const Operand& operand,
152                    FlagsUpdate S,
153                    AddSubOp op);
154 
155   // Add/sub with carry macros.
156   void Adc(const Register& rd,
157            const Register& rn,
158            const Operand& operand);
159   void Adcs(const Register& rd,
160             const Register& rn,
161             const Operand& operand);
162   void Sbc(const Register& rd,
163            const Register& rn,
164            const Operand& operand);
165   void Sbcs(const Register& rd,
166             const Register& rn,
167             const Operand& operand);
168   void Ngc(const Register& rd,
169            const Operand& operand);
170   void Ngcs(const Register& rd,
171             const Operand& operand);
172   void AddSubWithCarryMacro(const Register& rd,
173                             const Register& rn,
174                             const Operand& operand,
175                             FlagsUpdate S,
176                             AddSubWithCarryOp op);
177 
178   // Move macros.
179   void Mov(const Register& rd, uint64_t imm);
180   void Mov(const Register& rd,
181            const Operand& operand,
182            DiscardMoveMode discard_mode = kDontDiscardForSameWReg);
Mvn(const Register & rd,uint64_t imm)183   void Mvn(const Register& rd, uint64_t imm) {
184     Mov(rd, (rd.size() == kXRegSize) ? ~imm : (~imm & kWRegMask));
185   };
186   void Mvn(const Register& rd, const Operand& operand);
187   bool IsImmMovz(uint64_t imm, unsigned reg_size);
188   bool IsImmMovn(uint64_t imm, unsigned reg_size);
189   unsigned CountClearHalfWords(uint64_t imm, unsigned reg_size);
190 
191   // Conditional macros.
192   void Ccmp(const Register& rn,
193             const Operand& operand,
194             StatusFlags nzcv,
195             Condition cond);
196   void Ccmn(const Register& rn,
197             const Operand& operand,
198             StatusFlags nzcv,
199             Condition cond);
200   void ConditionalCompareMacro(const Register& rn,
201                                const Operand& operand,
202                                StatusFlags nzcv,
203                                Condition cond,
204                                ConditionalCompareOp op);
205   void Csel(const Register& rd,
206             const Register& rn,
207             const Operand& operand,
208             Condition cond);
209 
210   // Load/store macros.
211 #define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \
212   void FN(const REGTYPE REG, const MemOperand& addr);
213   LS_MACRO_LIST(DECLARE_FUNCTION)
214 #undef DECLARE_FUNCTION
215 
216   void LoadStoreMacro(const CPURegister& rt,
217                       const MemOperand& addr,
218                       LoadStoreOp op);
219 
220   // Push or pop up to 4 registers of the same width to or from the stack,
221   // using the current stack pointer as set by SetStackPointer.
222   //
223   // If an argument register is 'NoReg', all further arguments are also assumed
224   // to be 'NoReg', and are thus not pushed or popped.
225   //
226   // Arguments are ordered such that "Push(a, b);" is functionally equivalent
227   // to "Push(a); Push(b);".
228   //
229   // It is valid to push the same register more than once, and there is no
230   // restriction on the order in which registers are specified.
231   //
232   // It is not valid to pop into the same register more than once in one
233   // operation, not even into the zero register.
234   //
235   // If the current stack pointer (as set by SetStackPointer) is sp, then it
236   // must be aligned to 16 bytes on entry and the total size of the specified
237   // registers must also be a multiple of 16 bytes.
238   //
239   // Even if the current stack pointer is not the system stack pointer (sp),
240   // Push (and derived methods) will still modify the system stack pointer in
241   // order to comply with ABI rules about accessing memory below the system
242   // stack pointer.
243   //
244   // Other than the registers passed into Pop, the stack pointer and (possibly)
245   // the system stack pointer, these methods do not modify any other registers.
246   void Push(const CPURegister& src0, const CPURegister& src1 = NoReg,
247             const CPURegister& src2 = NoReg, const CPURegister& src3 = NoReg);
248   void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg,
249            const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg);
250 
251   // Alternative forms of Push and Pop, taking a RegList or CPURegList that
252   // specifies the registers that are to be pushed or popped. Higher-numbered
253   // registers are associated with higher memory addresses (as in the A32 push
254   // and pop instructions).
255   //
256   // (Push|Pop)SizeRegList allow you to specify the register size as a
257   // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
258   // supported.
259   //
260   // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred.
261   void PushCPURegList(CPURegList registers);
262   void PopCPURegList(CPURegList registers);
263 
264   void PushSizeRegList(RegList registers, unsigned reg_size,
265       CPURegister::RegisterType type = CPURegister::kRegister) {
266     PushCPURegList(CPURegList(type, reg_size, registers));
267   }
268   void PopSizeRegList(RegList registers, unsigned reg_size,
269       CPURegister::RegisterType type = CPURegister::kRegister) {
270     PopCPURegList(CPURegList(type, reg_size, registers));
271   }
PushXRegList(RegList regs)272   void PushXRegList(RegList regs) {
273     PushSizeRegList(regs, kXRegSize);
274   }
PopXRegList(RegList regs)275   void PopXRegList(RegList regs) {
276     PopSizeRegList(regs, kXRegSize);
277   }
PushWRegList(RegList regs)278   void PushWRegList(RegList regs) {
279     PushSizeRegList(regs, kWRegSize);
280   }
PopWRegList(RegList regs)281   void PopWRegList(RegList regs) {
282     PopSizeRegList(regs, kWRegSize);
283   }
PushDRegList(RegList regs)284   inline void PushDRegList(RegList regs) {
285     PushSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
286   }
PopDRegList(RegList regs)287   inline void PopDRegList(RegList regs) {
288     PopSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
289   }
PushSRegList(RegList regs)290   inline void PushSRegList(RegList regs) {
291     PushSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
292   }
PopSRegList(RegList regs)293   inline void PopSRegList(RegList regs) {
294     PopSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
295   }
296 
297   // Push the specified register 'count' times.
298   void PushMultipleTimes(int count, Register src);
299 
300   // Poke 'src' onto the stack. The offset is in bytes.
301   //
302   // If the current stack pointer (as set by SetStackPointer) is sp, then sp
303   // must be aligned to 16 bytes.
304   void Poke(const Register& src, const Operand& offset);
305 
306   // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes.
307   //
308   // If the current stack pointer (as set by SetStackPointer) is sp, then sp
309   // must be aligned to 16 bytes.
310   void Peek(const Register& dst, const Operand& offset);
311 
312   // Claim or drop stack space without actually accessing memory.
313   //
314   // If the current stack pointer (as set by SetStackPointer) is sp, then it
315   // must be aligned to 16 bytes and the size claimed or dropped must be a
316   // multiple of 16 bytes.
317   void Claim(const Operand& size);
318   void Drop(const Operand& size);
319 
320   // Preserve the callee-saved registers (as defined by AAPCS64).
321   //
322   // Higher-numbered registers are pushed before lower-numbered registers, and
323   // thus get higher addresses.
324   // Floating-point registers are pushed before general-purpose registers, and
325   // thus get higher addresses.
326   //
327   // This method must not be called unless StackPointer() is sp, and it is
328   // aligned to 16 bytes.
329   void PushCalleeSavedRegisters();
330 
331   // Restore the callee-saved registers (as defined by AAPCS64).
332   //
333   // Higher-numbered registers are popped after lower-numbered registers, and
334   // thus come from higher addresses.
335   // Floating-point registers are popped after general-purpose registers, and
336   // thus come from higher addresses.
337   //
338   // This method must not be called unless StackPointer() is sp, and it is
339   // aligned to 16 bytes.
340   void PopCalleeSavedRegisters();
341 
342   // Remaining instructions are simple pass-through calls to the assembler.
Adr(const Register & rd,Label * label)343   void Adr(const Register& rd, Label* label) {
344     VIXL_ASSERT(allow_macro_instructions_);
345     VIXL_ASSERT(!rd.IsZero());
346     adr(rd, label);
347   }
Asr(const Register & rd,const Register & rn,unsigned shift)348   void Asr(const Register& rd, const Register& rn, unsigned shift) {
349     VIXL_ASSERT(allow_macro_instructions_);
350     VIXL_ASSERT(!rd.IsZero());
351     VIXL_ASSERT(!rn.IsZero());
352     asr(rd, rn, shift);
353   }
Asr(const Register & rd,const Register & rn,const Register & rm)354   void Asr(const Register& rd, const Register& rn, const Register& rm) {
355     VIXL_ASSERT(allow_macro_instructions_);
356     VIXL_ASSERT(!rd.IsZero());
357     VIXL_ASSERT(!rn.IsZero());
358     VIXL_ASSERT(!rm.IsZero());
359     asrv(rd, rn, rm);
360   }
361 
362   // Branch type inversion relies on these relations.
363   VIXL_STATIC_ASSERT((reg_zero      == (reg_not_zero ^ 1)) &&
364                      (reg_bit_clear == (reg_bit_set ^ 1)) &&
365                      (always        == (never ^ 1)));
366 
InvertBranchType(BranchType type)367   BranchType InvertBranchType(BranchType type) {
368     if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
369       return static_cast<BranchType>(
370           InvertCondition(static_cast<Condition>(type)));
371     } else {
372       return static_cast<BranchType>(type ^ 1);
373     }
374   }
375 
376   void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1);
377 
B(Label * label)378   void B(Label* label) {
379     b(label);
380   }
B(Label * label,Condition cond)381   void B(Label* label, Condition cond) {
382     VIXL_ASSERT(allow_macro_instructions_);
383     VIXL_ASSERT((cond != al) && (cond != nv));
384     b(label, cond);
385   }
B(Condition cond,Label * label)386   void B(Condition cond, Label* label) {
387     B(label, cond);
388   }
Bfi(const Register & rd,const Register & rn,unsigned lsb,unsigned width)389   void Bfi(const Register& rd,
390            const Register& rn,
391            unsigned lsb,
392            unsigned width) {
393     VIXL_ASSERT(allow_macro_instructions_);
394     VIXL_ASSERT(!rd.IsZero());
395     VIXL_ASSERT(!rn.IsZero());
396     bfi(rd, rn, lsb, width);
397   }
Bfxil(const Register & rd,const Register & rn,unsigned lsb,unsigned width)398   void Bfxil(const Register& rd,
399              const Register& rn,
400              unsigned lsb,
401              unsigned width) {
402     VIXL_ASSERT(allow_macro_instructions_);
403     VIXL_ASSERT(!rd.IsZero());
404     VIXL_ASSERT(!rn.IsZero());
405     bfxil(rd, rn, lsb, width);
406   }
Bind(Label * label)407   void Bind(Label* label) {
408     VIXL_ASSERT(allow_macro_instructions_);
409     bind(label);
410   }
Bl(Label * label)411   void Bl(Label* label) {
412     VIXL_ASSERT(allow_macro_instructions_);
413     bl(label);
414   }
Blr(const Register & xn)415   void Blr(const Register& xn) {
416     VIXL_ASSERT(allow_macro_instructions_);
417     VIXL_ASSERT(!xn.IsZero());
418     blr(xn);
419   }
Br(const Register & xn)420   void Br(const Register& xn) {
421     VIXL_ASSERT(allow_macro_instructions_);
422     VIXL_ASSERT(!xn.IsZero());
423     br(xn);
424   }
425   void Brk(int code = 0) {
426     VIXL_ASSERT(allow_macro_instructions_);
427     brk(code);
428   }
Cbnz(const Register & rt,Label * label)429   void Cbnz(const Register& rt, Label* label) {
430     VIXL_ASSERT(allow_macro_instructions_);
431     VIXL_ASSERT(!rt.IsZero());
432     cbnz(rt, label);
433   }
Cbz(const Register & rt,Label * label)434   void Cbz(const Register& rt, Label* label) {
435     VIXL_ASSERT(allow_macro_instructions_);
436     VIXL_ASSERT(!rt.IsZero());
437     cbz(rt, label);
438   }
Cinc(const Register & rd,const Register & rn,Condition cond)439   void Cinc(const Register& rd, const Register& rn, Condition cond) {
440     VIXL_ASSERT(allow_macro_instructions_);
441     VIXL_ASSERT(!rd.IsZero());
442     VIXL_ASSERT(!rn.IsZero());
443     cinc(rd, rn, cond);
444   }
Cinv(const Register & rd,const Register & rn,Condition cond)445   void Cinv(const Register& rd, const Register& rn, Condition cond) {
446     VIXL_ASSERT(allow_macro_instructions_);
447     VIXL_ASSERT(!rd.IsZero());
448     VIXL_ASSERT(!rn.IsZero());
449     cinv(rd, rn, cond);
450   }
Cls(const Register & rd,const Register & rn)451   void Cls(const Register& rd, const Register& rn) {
452     VIXL_ASSERT(allow_macro_instructions_);
453     VIXL_ASSERT(!rd.IsZero());
454     VIXL_ASSERT(!rn.IsZero());
455     cls(rd, rn);
456   }
Clz(const Register & rd,const Register & rn)457   void Clz(const Register& rd, const Register& rn) {
458     VIXL_ASSERT(allow_macro_instructions_);
459     VIXL_ASSERT(!rd.IsZero());
460     VIXL_ASSERT(!rn.IsZero());
461     clz(rd, rn);
462   }
Cneg(const Register & rd,const Register & rn,Condition cond)463   void Cneg(const Register& rd, const Register& rn, Condition cond) {
464     VIXL_ASSERT(allow_macro_instructions_);
465     VIXL_ASSERT(!rd.IsZero());
466     VIXL_ASSERT(!rn.IsZero());
467     cneg(rd, rn, cond);
468   }
Cset(const Register & rd,Condition cond)469   void Cset(const Register& rd, Condition cond) {
470     VIXL_ASSERT(allow_macro_instructions_);
471     VIXL_ASSERT(!rd.IsZero());
472     cset(rd, cond);
473   }
Csetm(const Register & rd,Condition cond)474   void Csetm(const Register& rd, Condition cond) {
475     VIXL_ASSERT(allow_macro_instructions_);
476     VIXL_ASSERT(!rd.IsZero());
477     csetm(rd, cond);
478   }
Csinc(const Register & rd,const Register & rn,const Register & rm,Condition cond)479   void Csinc(const Register& rd,
480              const Register& rn,
481              const Register& rm,
482              Condition cond) {
483     VIXL_ASSERT(allow_macro_instructions_);
484     VIXL_ASSERT(!rd.IsZero());
485     VIXL_ASSERT(!rn.IsZero());
486     VIXL_ASSERT(!rm.IsZero());
487     VIXL_ASSERT((cond != al) && (cond != nv));
488     csinc(rd, rn, rm, cond);
489   }
Csinv(const Register & rd,const Register & rn,const Register & rm,Condition cond)490   void Csinv(const Register& rd,
491              const Register& rn,
492              const Register& rm,
493              Condition cond) {
494     VIXL_ASSERT(allow_macro_instructions_);
495     VIXL_ASSERT(!rd.IsZero());
496     VIXL_ASSERT(!rn.IsZero());
497     VIXL_ASSERT(!rm.IsZero());
498     VIXL_ASSERT((cond != al) && (cond != nv));
499     csinv(rd, rn, rm, cond);
500   }
Csneg(const Register & rd,const Register & rn,const Register & rm,Condition cond)501   void Csneg(const Register& rd,
502              const Register& rn,
503              const Register& rm,
504              Condition cond) {
505     VIXL_ASSERT(allow_macro_instructions_);
506     VIXL_ASSERT(!rd.IsZero());
507     VIXL_ASSERT(!rn.IsZero());
508     VIXL_ASSERT(!rm.IsZero());
509     VIXL_ASSERT((cond != al) && (cond != nv));
510     csneg(rd, rn, rm, cond);
511   }
Dmb(BarrierDomain domain,BarrierType type)512   void Dmb(BarrierDomain domain, BarrierType type) {
513     VIXL_ASSERT(allow_macro_instructions_);
514     dmb(domain, type);
515   }
Dsb(BarrierDomain domain,BarrierType type)516   void Dsb(BarrierDomain domain, BarrierType type) {
517     VIXL_ASSERT(allow_macro_instructions_);
518     dsb(domain, type);
519   }
Extr(const Register & rd,const Register & rn,const Register & rm,unsigned lsb)520   void Extr(const Register& rd,
521             const Register& rn,
522             const Register& rm,
523             unsigned lsb) {
524     VIXL_ASSERT(allow_macro_instructions_);
525     VIXL_ASSERT(!rd.IsZero());
526     VIXL_ASSERT(!rn.IsZero());
527     VIXL_ASSERT(!rm.IsZero());
528     extr(rd, rn, rm, lsb);
529   }
Fabs(const FPRegister & fd,const FPRegister & fn)530   void Fabs(const FPRegister& fd, const FPRegister& fn) {
531     VIXL_ASSERT(allow_macro_instructions_);
532     fabs(fd, fn);
533   }
Fadd(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)534   void Fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
535     VIXL_ASSERT(allow_macro_instructions_);
536     fadd(fd, fn, fm);
537   }
Fccmp(const FPRegister & fn,const FPRegister & fm,StatusFlags nzcv,Condition cond)538   void Fccmp(const FPRegister& fn,
539              const FPRegister& fm,
540              StatusFlags nzcv,
541              Condition cond) {
542     VIXL_ASSERT(allow_macro_instructions_);
543     VIXL_ASSERT((cond != al) && (cond != nv));
544     fccmp(fn, fm, nzcv, cond);
545   }
Fcmp(const FPRegister & fn,const FPRegister & fm)546   void Fcmp(const FPRegister& fn, const FPRegister& fm) {
547     VIXL_ASSERT(allow_macro_instructions_);
548     fcmp(fn, fm);
549   }
550   void Fcmp(const FPRegister& fn, double value);
Fcsel(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,Condition cond)551   void Fcsel(const FPRegister& fd,
552              const FPRegister& fn,
553              const FPRegister& fm,
554              Condition cond) {
555     VIXL_ASSERT(allow_macro_instructions_);
556     VIXL_ASSERT((cond != al) && (cond != nv));
557     fcsel(fd, fn, fm, cond);
558   }
Fcvt(const FPRegister & fd,const FPRegister & fn)559   void Fcvt(const FPRegister& fd, const FPRegister& fn) {
560     VIXL_ASSERT(allow_macro_instructions_);
561     fcvt(fd, fn);
562   }
Fcvtas(const Register & rd,const FPRegister & fn)563   void Fcvtas(const Register& rd, const FPRegister& fn) {
564     VIXL_ASSERT(allow_macro_instructions_);
565     VIXL_ASSERT(!rd.IsZero());
566     fcvtas(rd, fn);
567   }
Fcvtau(const Register & rd,const FPRegister & fn)568   void Fcvtau(const Register& rd, const FPRegister& fn) {
569     VIXL_ASSERT(allow_macro_instructions_);
570     VIXL_ASSERT(!rd.IsZero());
571     fcvtau(rd, fn);
572   }
Fcvtms(const Register & rd,const FPRegister & fn)573   void Fcvtms(const Register& rd, const FPRegister& fn) {
574     VIXL_ASSERT(allow_macro_instructions_);
575     VIXL_ASSERT(!rd.IsZero());
576     fcvtms(rd, fn);
577   }
Fcvtmu(const Register & rd,const FPRegister & fn)578   void Fcvtmu(const Register& rd, const FPRegister& fn) {
579     VIXL_ASSERT(allow_macro_instructions_);
580     VIXL_ASSERT(!rd.IsZero());
581     fcvtmu(rd, fn);
582   }
Fcvtns(const Register & rd,const FPRegister & fn)583   void Fcvtns(const Register& rd, const FPRegister& fn) {
584     VIXL_ASSERT(allow_macro_instructions_);
585     VIXL_ASSERT(!rd.IsZero());
586     fcvtns(rd, fn);
587   }
Fcvtnu(const Register & rd,const FPRegister & fn)588   void Fcvtnu(const Register& rd, const FPRegister& fn) {
589     VIXL_ASSERT(allow_macro_instructions_);
590     VIXL_ASSERT(!rd.IsZero());
591     fcvtnu(rd, fn);
592   }
Fcvtzs(const Register & rd,const FPRegister & fn)593   void Fcvtzs(const Register& rd, const FPRegister& fn) {
594     VIXL_ASSERT(allow_macro_instructions_);
595     VIXL_ASSERT(!rd.IsZero());
596     fcvtzs(rd, fn);
597   }
Fcvtzu(const Register & rd,const FPRegister & fn)598   void Fcvtzu(const Register& rd, const FPRegister& fn) {
599     VIXL_ASSERT(allow_macro_instructions_);
600     VIXL_ASSERT(!rd.IsZero());
601     fcvtzu(rd, fn);
602   }
Fdiv(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)603   void Fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
604     VIXL_ASSERT(allow_macro_instructions_);
605     fdiv(fd, fn, fm);
606   }
Fmax(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)607   void Fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
608     VIXL_ASSERT(allow_macro_instructions_);
609     fmax(fd, fn, fm);
610   }
Fmaxnm(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)611   void Fmaxnm(const FPRegister& fd,
612               const FPRegister& fn,
613               const FPRegister& fm) {
614     VIXL_ASSERT(allow_macro_instructions_);
615     fmaxnm(fd, fn, fm);
616   }
Fmin(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)617   void Fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
618     VIXL_ASSERT(allow_macro_instructions_);
619     fmin(fd, fn, fm);
620   }
Fminnm(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)621   void Fminnm(const FPRegister& fd,
622               const FPRegister& fn,
623               const FPRegister& fm) {
624     VIXL_ASSERT(allow_macro_instructions_);
625     fminnm(fd, fn, fm);
626   }
Fmov(FPRegister fd,FPRegister fn)627   void Fmov(FPRegister fd, FPRegister fn) {
628     VIXL_ASSERT(allow_macro_instructions_);
629     // Only emit an instruction if fd and fn are different, and they are both D
630     // registers. fmov(s0, s0) is not a no-op because it clears the top word of
631     // d0. Technically, fmov(d0, d0) is not a no-op either because it clears
632     // the top of q0, but FPRegister does not currently support Q registers.
633     if (!fd.Is(fn) || !fd.Is64Bits()) {
634       fmov(fd, fn);
635     }
636   }
Fmov(FPRegister fd,Register rn)637   void Fmov(FPRegister fd, Register rn) {
638     VIXL_ASSERT(allow_macro_instructions_);
639     VIXL_ASSERT(!rn.IsZero());
640     fmov(fd, rn);
641   }
642   // Provide explicit double and float interfaces for FP immediate moves, rather
643   // than relying on implicit C++ casts. This allows signalling NaNs to be
644   // preserved when the immediate matches the format of fd. Most systems convert
645   // signalling NaNs to quiet NaNs when converting between float and double.
646   void Fmov(FPRegister fd, double imm);
647   void Fmov(FPRegister fd, float imm);
648   // Provide a template to allow other types to be converted automatically.
649   template<typename T>
Fmov(FPRegister fd,T imm)650   void Fmov(FPRegister fd, T imm) {
651     VIXL_ASSERT(allow_macro_instructions_);
652     Fmov(fd, static_cast<double>(imm));
653   }
Fmov(Register rd,FPRegister fn)654   void Fmov(Register rd, FPRegister fn) {
655     VIXL_ASSERT(allow_macro_instructions_);
656     VIXL_ASSERT(!rd.IsZero());
657     fmov(rd, fn);
658   }
Fmul(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)659   void Fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
660     VIXL_ASSERT(allow_macro_instructions_);
661     fmul(fd, fn, fm);
662   }
Fmadd(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)663   void Fmadd(const FPRegister& fd,
664              const FPRegister& fn,
665              const FPRegister& fm,
666              const FPRegister& fa) {
667     VIXL_ASSERT(allow_macro_instructions_);
668     fmadd(fd, fn, fm, fa);
669   }
Fmsub(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)670   void Fmsub(const FPRegister& fd,
671              const FPRegister& fn,
672              const FPRegister& fm,
673              const FPRegister& fa) {
674     VIXL_ASSERT(allow_macro_instructions_);
675     fmsub(fd, fn, fm, fa);
676   }
Fnmadd(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)677   void Fnmadd(const FPRegister& fd,
678               const FPRegister& fn,
679               const FPRegister& fm,
680               const FPRegister& fa) {
681     VIXL_ASSERT(allow_macro_instructions_);
682     fnmadd(fd, fn, fm, fa);
683   }
Fnmsub(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm,const FPRegister & fa)684   void Fnmsub(const FPRegister& fd,
685               const FPRegister& fn,
686               const FPRegister& fm,
687               const FPRegister& fa) {
688     VIXL_ASSERT(allow_macro_instructions_);
689     fnmsub(fd, fn, fm, fa);
690   }
Fneg(const FPRegister & fd,const FPRegister & fn)691   void Fneg(const FPRegister& fd, const FPRegister& fn) {
692     VIXL_ASSERT(allow_macro_instructions_);
693     fneg(fd, fn);
694   }
Frinta(const FPRegister & fd,const FPRegister & fn)695   void Frinta(const FPRegister& fd, const FPRegister& fn) {
696     VIXL_ASSERT(allow_macro_instructions_);
697     frinta(fd, fn);
698   }
Frintm(const FPRegister & fd,const FPRegister & fn)699   void Frintm(const FPRegister& fd, const FPRegister& fn) {
700     VIXL_ASSERT(allow_macro_instructions_);
701     frintm(fd, fn);
702   }
Frintn(const FPRegister & fd,const FPRegister & fn)703   void Frintn(const FPRegister& fd, const FPRegister& fn) {
704     VIXL_ASSERT(allow_macro_instructions_);
705     frintn(fd, fn);
706   }
Frintz(const FPRegister & fd,const FPRegister & fn)707   void Frintz(const FPRegister& fd, const FPRegister& fn) {
708     VIXL_ASSERT(allow_macro_instructions_);
709     frintz(fd, fn);
710   }
Fsqrt(const FPRegister & fd,const FPRegister & fn)711   void Fsqrt(const FPRegister& fd, const FPRegister& fn) {
712     VIXL_ASSERT(allow_macro_instructions_);
713     fsqrt(fd, fn);
714   }
Fsub(const FPRegister & fd,const FPRegister & fn,const FPRegister & fm)715   void Fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
716     VIXL_ASSERT(allow_macro_instructions_);
717     fsub(fd, fn, fm);
718   }
Hint(SystemHint code)719   void Hint(SystemHint code) {
720     VIXL_ASSERT(allow_macro_instructions_);
721     hint(code);
722   }
Hlt(int code)723   void Hlt(int code) {
724     VIXL_ASSERT(allow_macro_instructions_);
725     hlt(code);
726   }
Isb()727   void Isb() {
728     VIXL_ASSERT(allow_macro_instructions_);
729     isb();
730   }
Ldnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)731   void Ldnp(const CPURegister& rt,
732             const CPURegister& rt2,
733             const MemOperand& src) {
734     VIXL_ASSERT(allow_macro_instructions_);
735     ldnp(rt, rt2, src);
736   }
Ldp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & src)737   void Ldp(const CPURegister& rt,
738            const CPURegister& rt2,
739            const MemOperand& src) {
740     VIXL_ASSERT(allow_macro_instructions_);
741     ldp(rt, rt2, src);
742   }
Ldpsw(const Register & rt,const Register & rt2,const MemOperand & src)743   void Ldpsw(const Register& rt, const Register& rt2, const MemOperand& src) {
744     VIXL_ASSERT(allow_macro_instructions_);
745     ldpsw(rt, rt2, src);
746   }
747   // Provide both double and float interfaces for FP immediate loads, rather
748   // than relying on implicit C++ casts. This allows signalling NaNs to be
749   // preserved when the immediate matches the format of fd. Most systems convert
750   // signalling NaNs to quiet NaNs when converting between float and double.
Ldr(const FPRegister & ft,double imm)751   void Ldr(const FPRegister& ft, double imm) {
752     VIXL_ASSERT(allow_macro_instructions_);
753     if (ft.Is64Bits()) {
754       ldr(ft, imm);
755     } else {
756       ldr(ft, static_cast<float>(imm));
757     }
758   }
Ldr(const FPRegister & ft,float imm)759   void Ldr(const FPRegister& ft, float imm) {
760     VIXL_ASSERT(allow_macro_instructions_);
761     if (ft.Is32Bits()) {
762       ldr(ft, imm);
763     } else {
764       ldr(ft, static_cast<double>(imm));
765     }
766   }
Ldr(const Register & rt,uint64_t imm)767   void Ldr(const Register& rt, uint64_t imm) {
768     VIXL_ASSERT(allow_macro_instructions_);
769     VIXL_ASSERT(!rt.IsZero());
770     ldr(rt, imm);
771   }
Lsl(const Register & rd,const Register & rn,unsigned shift)772   void Lsl(const Register& rd, const Register& rn, unsigned shift) {
773     VIXL_ASSERT(allow_macro_instructions_);
774     VIXL_ASSERT(!rd.IsZero());
775     VIXL_ASSERT(!rn.IsZero());
776     lsl(rd, rn, shift);
777   }
Lsl(const Register & rd,const Register & rn,const Register & rm)778   void Lsl(const Register& rd, const Register& rn, const Register& rm) {
779     VIXL_ASSERT(allow_macro_instructions_);
780     VIXL_ASSERT(!rd.IsZero());
781     VIXL_ASSERT(!rn.IsZero());
782     VIXL_ASSERT(!rm.IsZero());
783     lslv(rd, rn, rm);
784   }
Lsr(const Register & rd,const Register & rn,unsigned shift)785   void Lsr(const Register& rd, const Register& rn, unsigned shift) {
786     VIXL_ASSERT(allow_macro_instructions_);
787     VIXL_ASSERT(!rd.IsZero());
788     VIXL_ASSERT(!rn.IsZero());
789     lsr(rd, rn, shift);
790   }
Lsr(const Register & rd,const Register & rn,const Register & rm)791   void Lsr(const Register& rd, const Register& rn, const Register& rm) {
792     VIXL_ASSERT(allow_macro_instructions_);
793     VIXL_ASSERT(!rd.IsZero());
794     VIXL_ASSERT(!rn.IsZero());
795     VIXL_ASSERT(!rm.IsZero());
796     lsrv(rd, rn, rm);
797   }
Madd(const Register & rd,const Register & rn,const Register & rm,const Register & ra)798   void Madd(const Register& rd,
799             const Register& rn,
800             const Register& rm,
801             const Register& ra) {
802     VIXL_ASSERT(allow_macro_instructions_);
803     VIXL_ASSERT(!rd.IsZero());
804     VIXL_ASSERT(!rn.IsZero());
805     VIXL_ASSERT(!rm.IsZero());
806     VIXL_ASSERT(!ra.IsZero());
807     madd(rd, rn, rm, ra);
808   }
Mneg(const Register & rd,const Register & rn,const Register & rm)809   void Mneg(const Register& rd, const Register& rn, const Register& rm) {
810     VIXL_ASSERT(allow_macro_instructions_);
811     VIXL_ASSERT(!rd.IsZero());
812     VIXL_ASSERT(!rn.IsZero());
813     VIXL_ASSERT(!rm.IsZero());
814     mneg(rd, rn, rm);
815   }
Mov(const Register & rd,const Register & rn)816   void Mov(const Register& rd, const Register& rn) {
817     VIXL_ASSERT(allow_macro_instructions_);
818     mov(rd, rn);
819   }
820   void Movk(const Register& rd, uint64_t imm, int shift = -1) {
821     VIXL_ASSERT(allow_macro_instructions_);
822     VIXL_ASSERT(!rd.IsZero());
823     movk(rd, imm, shift);
824   }
Mrs(const Register & rt,SystemRegister sysreg)825   void Mrs(const Register& rt, SystemRegister sysreg) {
826     VIXL_ASSERT(allow_macro_instructions_);
827     VIXL_ASSERT(!rt.IsZero());
828     mrs(rt, sysreg);
829   }
Msr(SystemRegister sysreg,const Register & rt)830   void Msr(SystemRegister sysreg, const Register& rt) {
831     VIXL_ASSERT(allow_macro_instructions_);
832     VIXL_ASSERT(!rt.IsZero());
833     msr(sysreg, rt);
834   }
Msub(const Register & rd,const Register & rn,const Register & rm,const Register & ra)835   void Msub(const Register& rd,
836             const Register& rn,
837             const Register& rm,
838             const Register& ra) {
839     VIXL_ASSERT(allow_macro_instructions_);
840     VIXL_ASSERT(!rd.IsZero());
841     VIXL_ASSERT(!rn.IsZero());
842     VIXL_ASSERT(!rm.IsZero());
843     VIXL_ASSERT(!ra.IsZero());
844     msub(rd, rn, rm, ra);
845   }
Mul(const Register & rd,const Register & rn,const Register & rm)846   void Mul(const Register& rd, const Register& rn, const Register& rm) {
847     VIXL_ASSERT(allow_macro_instructions_);
848     VIXL_ASSERT(!rd.IsZero());
849     VIXL_ASSERT(!rn.IsZero());
850     VIXL_ASSERT(!rm.IsZero());
851     mul(rd, rn, rm);
852   }
Nop()853   void Nop() {
854     VIXL_ASSERT(allow_macro_instructions_);
855     nop();
856   }
Rbit(const Register & rd,const Register & rn)857   void Rbit(const Register& rd, const Register& rn) {
858     VIXL_ASSERT(allow_macro_instructions_);
859     VIXL_ASSERT(!rd.IsZero());
860     VIXL_ASSERT(!rn.IsZero());
861     rbit(rd, rn);
862   }
863   void Ret(const Register& xn = lr) {
864     VIXL_ASSERT(allow_macro_instructions_);
865     VIXL_ASSERT(!xn.IsZero());
866     ret(xn);
867   }
Rev(const Register & rd,const Register & rn)868   void Rev(const Register& rd, const Register& rn) {
869     VIXL_ASSERT(allow_macro_instructions_);
870     VIXL_ASSERT(!rd.IsZero());
871     VIXL_ASSERT(!rn.IsZero());
872     rev(rd, rn);
873   }
Rev16(const Register & rd,const Register & rn)874   void Rev16(const Register& rd, const Register& rn) {
875     VIXL_ASSERT(allow_macro_instructions_);
876     VIXL_ASSERT(!rd.IsZero());
877     VIXL_ASSERT(!rn.IsZero());
878     rev16(rd, rn);
879   }
Rev32(const Register & rd,const Register & rn)880   void Rev32(const Register& rd, const Register& rn) {
881     VIXL_ASSERT(allow_macro_instructions_);
882     VIXL_ASSERT(!rd.IsZero());
883     VIXL_ASSERT(!rn.IsZero());
884     rev32(rd, rn);
885   }
Ror(const Register & rd,const Register & rs,unsigned shift)886   void Ror(const Register& rd, const Register& rs, unsigned shift) {
887     VIXL_ASSERT(allow_macro_instructions_);
888     VIXL_ASSERT(!rd.IsZero());
889     VIXL_ASSERT(!rs.IsZero());
890     ror(rd, rs, shift);
891   }
Ror(const Register & rd,const Register & rn,const Register & rm)892   void Ror(const Register& rd, const Register& rn, const Register& rm) {
893     VIXL_ASSERT(allow_macro_instructions_);
894     VIXL_ASSERT(!rd.IsZero());
895     VIXL_ASSERT(!rn.IsZero());
896     VIXL_ASSERT(!rm.IsZero());
897     rorv(rd, rn, rm);
898   }
Sbfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)899   void Sbfiz(const Register& rd,
900              const Register& rn,
901              unsigned lsb,
902              unsigned width) {
903     VIXL_ASSERT(allow_macro_instructions_);
904     VIXL_ASSERT(!rd.IsZero());
905     VIXL_ASSERT(!rn.IsZero());
906     sbfiz(rd, rn, lsb, width);
907   }
Sbfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)908   void Sbfx(const Register& rd,
909             const Register& rn,
910             unsigned lsb,
911             unsigned width) {
912     VIXL_ASSERT(allow_macro_instructions_);
913     VIXL_ASSERT(!rd.IsZero());
914     VIXL_ASSERT(!rn.IsZero());
915     sbfx(rd, rn, lsb, width);
916   }
917   void Scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
918     VIXL_ASSERT(allow_macro_instructions_);
919     VIXL_ASSERT(!rn.IsZero());
920     scvtf(fd, rn, fbits);
921   }
Sdiv(const Register & rd,const Register & rn,const Register & rm)922   void Sdiv(const Register& rd, const Register& rn, const Register& rm) {
923     VIXL_ASSERT(allow_macro_instructions_);
924     VIXL_ASSERT(!rd.IsZero());
925     VIXL_ASSERT(!rn.IsZero());
926     VIXL_ASSERT(!rm.IsZero());
927     sdiv(rd, rn, rm);
928   }
Smaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)929   void Smaddl(const Register& rd,
930               const Register& rn,
931               const Register& rm,
932               const Register& ra) {
933     VIXL_ASSERT(allow_macro_instructions_);
934     VIXL_ASSERT(!rd.IsZero());
935     VIXL_ASSERT(!rn.IsZero());
936     VIXL_ASSERT(!rm.IsZero());
937     VIXL_ASSERT(!ra.IsZero());
938     smaddl(rd, rn, rm, ra);
939   }
Smsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)940   void Smsubl(const Register& rd,
941               const Register& rn,
942               const Register& rm,
943               const Register& ra) {
944     VIXL_ASSERT(allow_macro_instructions_);
945     VIXL_ASSERT(!rd.IsZero());
946     VIXL_ASSERT(!rn.IsZero());
947     VIXL_ASSERT(!rm.IsZero());
948     VIXL_ASSERT(!ra.IsZero());
949     smsubl(rd, rn, rm, ra);
950   }
Smull(const Register & rd,const Register & rn,const Register & rm)951   void Smull(const Register& rd, const Register& rn, const Register& rm) {
952     VIXL_ASSERT(allow_macro_instructions_);
953     VIXL_ASSERT(!rd.IsZero());
954     VIXL_ASSERT(!rn.IsZero());
955     VIXL_ASSERT(!rm.IsZero());
956     smull(rd, rn, rm);
957   }
Smulh(const Register & xd,const Register & xn,const Register & xm)958   void Smulh(const Register& xd, const Register& xn, const Register& xm) {
959     VIXL_ASSERT(allow_macro_instructions_);
960     VIXL_ASSERT(!xd.IsZero());
961     VIXL_ASSERT(!xn.IsZero());
962     VIXL_ASSERT(!xm.IsZero());
963     smulh(xd, xn, xm);
964   }
Stnp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)965   void Stnp(const CPURegister& rt,
966             const CPURegister& rt2,
967             const MemOperand& dst) {
968     VIXL_ASSERT(allow_macro_instructions_);
969     stnp(rt, rt2, dst);
970   }
Stp(const CPURegister & rt,const CPURegister & rt2,const MemOperand & dst)971   void Stp(const CPURegister& rt,
972            const CPURegister& rt2,
973            const MemOperand& dst) {
974     VIXL_ASSERT(allow_macro_instructions_);
975     stp(rt, rt2, dst);
976   }
Sxtb(const Register & rd,const Register & rn)977   void Sxtb(const Register& rd, const Register& rn) {
978     VIXL_ASSERT(allow_macro_instructions_);
979     VIXL_ASSERT(!rd.IsZero());
980     VIXL_ASSERT(!rn.IsZero());
981     sxtb(rd, rn);
982   }
Sxth(const Register & rd,const Register & rn)983   void Sxth(const Register& rd, const Register& rn) {
984     VIXL_ASSERT(allow_macro_instructions_);
985     VIXL_ASSERT(!rd.IsZero());
986     VIXL_ASSERT(!rn.IsZero());
987     sxth(rd, rn);
988   }
Sxtw(const Register & rd,const Register & rn)989   void Sxtw(const Register& rd, const Register& rn) {
990     VIXL_ASSERT(allow_macro_instructions_);
991     VIXL_ASSERT(!rd.IsZero());
992     VIXL_ASSERT(!rn.IsZero());
993     sxtw(rd, rn);
994   }
Tbnz(const Register & rt,unsigned bit_pos,Label * label)995   void Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
996     VIXL_ASSERT(allow_macro_instructions_);
997     VIXL_ASSERT(!rt.IsZero());
998     tbnz(rt, bit_pos, label);
999   }
Tbz(const Register & rt,unsigned bit_pos,Label * label)1000   void Tbz(const Register& rt, unsigned bit_pos, Label* label) {
1001     VIXL_ASSERT(allow_macro_instructions_);
1002     VIXL_ASSERT(!rt.IsZero());
1003     tbz(rt, bit_pos, label);
1004   }
Ubfiz(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1005   void Ubfiz(const Register& rd,
1006              const Register& rn,
1007              unsigned lsb,
1008              unsigned width) {
1009     VIXL_ASSERT(allow_macro_instructions_);
1010     VIXL_ASSERT(!rd.IsZero());
1011     VIXL_ASSERT(!rn.IsZero());
1012     ubfiz(rd, rn, lsb, width);
1013   }
Ubfx(const Register & rd,const Register & rn,unsigned lsb,unsigned width)1014   void Ubfx(const Register& rd,
1015             const Register& rn,
1016             unsigned lsb,
1017             unsigned width) {
1018     VIXL_ASSERT(allow_macro_instructions_);
1019     VIXL_ASSERT(!rd.IsZero());
1020     VIXL_ASSERT(!rn.IsZero());
1021     ubfx(rd, rn, lsb, width);
1022   }
1023   void Ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
1024     VIXL_ASSERT(allow_macro_instructions_);
1025     VIXL_ASSERT(!rn.IsZero());
1026     ucvtf(fd, rn, fbits);
1027   }
Udiv(const Register & rd,const Register & rn,const Register & rm)1028   void Udiv(const Register& rd, const Register& rn, const Register& rm) {
1029     VIXL_ASSERT(allow_macro_instructions_);
1030     VIXL_ASSERT(!rd.IsZero());
1031     VIXL_ASSERT(!rn.IsZero());
1032     VIXL_ASSERT(!rm.IsZero());
1033     udiv(rd, rn, rm);
1034   }
Umaddl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1035   void Umaddl(const Register& rd,
1036               const Register& rn,
1037               const Register& rm,
1038               const Register& ra) {
1039     VIXL_ASSERT(allow_macro_instructions_);
1040     VIXL_ASSERT(!rd.IsZero());
1041     VIXL_ASSERT(!rn.IsZero());
1042     VIXL_ASSERT(!rm.IsZero());
1043     VIXL_ASSERT(!ra.IsZero());
1044     umaddl(rd, rn, rm, ra);
1045   }
Umsubl(const Register & rd,const Register & rn,const Register & rm,const Register & ra)1046   void Umsubl(const Register& rd,
1047               const Register& rn,
1048               const Register& rm,
1049               const Register& ra) {
1050     VIXL_ASSERT(allow_macro_instructions_);
1051     VIXL_ASSERT(!rd.IsZero());
1052     VIXL_ASSERT(!rn.IsZero());
1053     VIXL_ASSERT(!rm.IsZero());
1054     VIXL_ASSERT(!ra.IsZero());
1055     umsubl(rd, rn, rm, ra);
1056   }
Unreachable()1057   void Unreachable() {
1058     VIXL_ASSERT(allow_macro_instructions_);
1059 #ifdef USE_SIMULATOR
1060     hlt(kUnreachableOpcode);
1061 #else
1062     // Branch to 0 to generate a segfault.
1063     // lr - kInstructionSize is the address of the offending instruction.
1064     blr(xzr);
1065 #endif
1066   }
Uxtb(const Register & rd,const Register & rn)1067   void Uxtb(const Register& rd, const Register& rn) {
1068     VIXL_ASSERT(allow_macro_instructions_);
1069     VIXL_ASSERT(!rd.IsZero());
1070     VIXL_ASSERT(!rn.IsZero());
1071     uxtb(rd, rn);
1072   }
Uxth(const Register & rd,const Register & rn)1073   void Uxth(const Register& rd, const Register& rn) {
1074     VIXL_ASSERT(allow_macro_instructions_);
1075     VIXL_ASSERT(!rd.IsZero());
1076     VIXL_ASSERT(!rn.IsZero());
1077     uxth(rd, rn);
1078   }
Uxtw(const Register & rd,const Register & rn)1079   void Uxtw(const Register& rd, const Register& rn) {
1080     VIXL_ASSERT(allow_macro_instructions_);
1081     VIXL_ASSERT(!rd.IsZero());
1082     VIXL_ASSERT(!rn.IsZero());
1083     uxtw(rd, rn);
1084   }
1085 
1086   // Push the system stack pointer (sp) down to allow the same to be done to
1087   // the current stack pointer (according to StackPointer()). This must be
1088   // called _before_ accessing the memory.
1089   //
1090   // This is necessary when pushing or otherwise adding things to the stack, to
1091   // satisfy the AAPCS64 constraint that the memory below the system stack
1092   // pointer is not accessed.
1093   //
1094   // This method asserts that StackPointer() is not sp, since the call does
1095   // not make sense in that context.
1096   //
1097   // TODO: This method can only accept values of 'space' that can be encoded in
1098   // one instruction. Refer to the implementation for details.
1099   void BumpSystemStackPointer(const Operand& space);
1100 
1101 #if DEBUG
SetAllowMacroInstructions(bool value)1102   void SetAllowMacroInstructions(bool value) {
1103     allow_macro_instructions_ = value;
1104   }
1105 
AllowMacroInstructions()1106   bool AllowMacroInstructions() const {
1107     return allow_macro_instructions_;
1108   }
1109 #endif
1110 
1111   // Set the current stack pointer, but don't generate any code.
SetStackPointer(const Register & stack_pointer)1112   void SetStackPointer(const Register& stack_pointer) {
1113     VIXL_ASSERT(!TmpList()->IncludesAliasOf(stack_pointer));
1114     sp_ = stack_pointer;
1115   }
1116 
1117   // Return the current stack pointer, as set by SetStackPointer.
StackPointer()1118   const Register& StackPointer() const {
1119     return sp_;
1120   }
1121 
TmpList()1122   CPURegList* TmpList() { return &tmp_list_; }
FPTmpList()1123   CPURegList* FPTmpList() { return &fptmp_list_; }
1124 
1125   // Like printf, but print at run-time from generated code.
1126   //
1127   // The caller must ensure that arguments for floating-point placeholders
1128   // (such as %e, %f or %g) are FPRegisters, and that arguments for integer
1129   // placeholders are Registers.
1130   //
1131   // At the moment it is only possible to print the value of sp if it is the
1132   // current stack pointer. Otherwise, the MacroAssembler will automatically
1133   // update sp on every push (using BumpSystemStackPointer), so determining its
1134   // value is difficult.
1135   //
1136   // Format placeholders that refer to more than one argument, or to a specific
1137   // argument, are not supported. This includes formats like "%1$d" or "%.*d".
1138   //
1139   // This function automatically preserves caller-saved registers so that
1140   // calling code can use Printf at any point without having to worry about
1141   // corruption. The preservation mechanism generates a lot of code. If this is
1142   // a problem, preserve the important registers manually and then call
1143   // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are
1144   // implicitly preserved.
1145   void Printf(const char * format,
1146               CPURegister arg0 = NoCPUReg,
1147               CPURegister arg1 = NoCPUReg,
1148               CPURegister arg2 = NoCPUReg,
1149               CPURegister arg3 = NoCPUReg);
1150 
1151   // Like Printf, but don't preserve any caller-saved registers, not even 'lr'.
1152   //
1153   // The return code from the system printf call will be returned in x0.
1154   void PrintfNoPreserve(const char * format,
1155                         const CPURegister& arg0 = NoCPUReg,
1156                         const CPURegister& arg1 = NoCPUReg,
1157                         const CPURegister& arg2 = NoCPUReg,
1158                         const CPURegister& arg3 = NoCPUReg);
1159 
1160   // Trace control when running the debug simulator.
1161   //
1162   // For example:
1163   //
1164   // __ Trace(LOG_REGS, TRACE_ENABLE);
1165   // Will add registers to the trace if it wasn't already the case.
1166   //
1167   // __ Trace(LOG_DISASM, TRACE_DISABLE);
1168   // Will stop logging disassembly. It has no effect if the disassembly wasn't
1169   // already being logged.
1170   void Trace(TraceParameters parameters, TraceCommand command);
1171 
1172   // Log the requested data independently of what is being traced.
1173   //
1174   // For example:
1175   //
1176   // __ Log(LOG_FLAGS)
1177   // Will output the flags.
1178   void Log(TraceParameters parameters);
1179 
1180   // Enable or disable instrumentation when an Instrument visitor is attached to
1181   // the simulator.
1182   void EnableInstrumentation();
1183   void DisableInstrumentation();
1184 
1185   // Add a marker to the instrumentation data produced by an Instrument visitor.
1186   // The name is a two character string that will be attached to the marker in
1187   // the output data.
1188   void AnnotateInstrumentation(const char* marker_name);
1189 
1190  private:
1191   // The actual Push and Pop implementations. These don't generate any code
1192   // other than that required for the push or pop. This allows
1193   // (Push|Pop)CPURegList to bundle together setup code for a large block of
1194   // registers.
1195   //
1196   // Note that size is per register, and is specified in bytes.
1197   void PushHelper(int count, int size,
1198                   const CPURegister& src0, const CPURegister& src1,
1199                   const CPURegister& src2, const CPURegister& src3);
1200   void PopHelper(int count, int size,
1201                  const CPURegister& dst0, const CPURegister& dst1,
1202                  const CPURegister& dst2, const CPURegister& dst3);
1203 
1204   // Perform necessary maintenance operations before a push or pop.
1205   //
1206   // Note that size is per register, and is specified in bytes.
1207   void PrepareForPush(int count, int size);
1208   void PrepareForPop(int count, int size);
1209 
1210 #if DEBUG
1211   // Tell whether any of the macro instruction can be used. When false the
1212   // MacroAssembler will assert if a method which can emit a variable number
1213   // of instructions is called.
1214   bool allow_macro_instructions_;
1215 #endif
1216 
1217   // The register to use as a stack pointer for stack operations.
1218   Register sp_;
1219 
1220   // Scratch registers available for use by the MacroAssembler.
1221   CPURegList tmp_list_;
1222   CPURegList fptmp_list_;
1223 };
1224 
1225 
1226 // Use this scope when you need a one-to-one mapping between methods and
1227 // instructions. This scope prevents the MacroAssembler from being called and
1228 // literal pools from being emitted. It also asserts the number of instructions
1229 // emitted is what you specified when creating the scope.
1230 class InstructionAccurateScope {
1231  public:
InstructionAccurateScope(MacroAssembler * masm)1232   explicit InstructionAccurateScope(MacroAssembler* masm)
1233       : masm_(masm) {
1234     masm_->BlockLiteralPool();
1235 #ifdef DEBUG
1236     size_ = 0;
1237     old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
1238     masm_->SetAllowMacroInstructions(false);
1239 #endif
1240   }
1241 
InstructionAccurateScope(MacroAssembler * masm,int count)1242   InstructionAccurateScope(MacroAssembler* masm, int count)
1243       : masm_(masm) {
1244     USE(count);
1245     masm_->BlockLiteralPool();
1246 #ifdef DEBUG
1247     size_ = count * kInstructionSize;
1248     masm_->bind(&start_);
1249     old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
1250     masm_->SetAllowMacroInstructions(false);
1251 #endif
1252   }
1253 
~InstructionAccurateScope()1254   ~InstructionAccurateScope() {
1255     masm_->ReleaseLiteralPool();
1256 #ifdef DEBUG
1257     if (start_.IsBound()) {
1258       VIXL_ASSERT(masm_->SizeOfCodeGeneratedSince(&start_) == size_);
1259     }
1260     masm_->SetAllowMacroInstructions(old_allow_macro_instructions_);
1261 #endif
1262   }
1263 
1264  private:
1265   MacroAssembler* masm_;
1266 #ifdef DEBUG
1267   uint64_t size_;
1268   Label start_;
1269   bool old_allow_macro_instructions_;
1270 #endif
1271 };
1272 
1273 
1274 // This scope utility allows scratch registers to be managed safely. The
1275 // MacroAssembler's TmpList() (and FPTmpList()) is used as a pool of scratch
1276 // registers. These registers can be allocated on demand, and will be returned
1277 // at the end of the scope.
1278 //
1279 // When the scope ends, the MacroAssembler's lists will be restored to their
1280 // original state, even if the lists were modified by some other means.
1281 class UseScratchRegisterScope {
1282  public:
UseScratchRegisterScope(MacroAssembler * masm)1283   explicit UseScratchRegisterScope(MacroAssembler* masm)
1284       : available_(masm->TmpList()),
1285         availablefp_(masm->FPTmpList()),
1286         old_available_(available_->list()),
1287         old_availablefp_(availablefp_->list()) {
1288     VIXL_ASSERT(available_->type() == CPURegister::kRegister);
1289     VIXL_ASSERT(availablefp_->type() == CPURegister::kFPRegister);
1290   }
1291 
1292 
1293   ~UseScratchRegisterScope();
1294 
1295 
1296   bool IsAvailable(const CPURegister& reg) const;
1297 
1298 
1299   // Take a register from the appropriate temps list. It will be returned
1300   // automatically when the scope ends.
AcquireW()1301   Register AcquireW() { return AcquireNextAvailable(available_).W(); }
AcquireX()1302   Register AcquireX() { return AcquireNextAvailable(available_).X(); }
AcquireS()1303   FPRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); }
AcquireD()1304   FPRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); }
1305 
1306 
1307   Register AcquireSameSizeAs(const Register& reg);
1308   FPRegister AcquireSameSizeAs(const FPRegister& reg);
1309 
1310 
1311   // Explicitly release an acquired (or excluded) register, putting it back in
1312   // the appropriate temps list.
1313   void Release(const CPURegister& reg);
1314 
1315 
1316   // Make the specified registers available as scratch registers for the
1317   // duration of this scope.
1318   void Include(const CPURegList& list);
1319   void Include(const Register& reg1,
1320                const Register& reg2 = NoReg,
1321                const Register& reg3 = NoReg,
1322                const Register& reg4 = NoReg);
1323   void Include(const FPRegister& reg1,
1324                const FPRegister& reg2 = NoFPReg,
1325                const FPRegister& reg3 = NoFPReg,
1326                const FPRegister& reg4 = NoFPReg);
1327 
1328 
1329   // Make sure that the specified registers are not available in this scope.
1330   // This can be used to prevent helper functions from using sensitive
1331   // registers, for example.
1332   void Exclude(const CPURegList& list);
1333   void Exclude(const Register& reg1,
1334                const Register& reg2 = NoReg,
1335                const Register& reg3 = NoReg,
1336                const Register& reg4 = NoReg);
1337   void Exclude(const FPRegister& reg1,
1338                const FPRegister& reg2 = NoFPReg,
1339                const FPRegister& reg3 = NoFPReg,
1340                const FPRegister& reg4 = NoFPReg);
1341   void Exclude(const CPURegister& reg1,
1342                const CPURegister& reg2 = NoCPUReg,
1343                const CPURegister& reg3 = NoCPUReg,
1344                const CPURegister& reg4 = NoCPUReg);
1345 
1346 
1347   // Prevent any scratch registers from being used in this scope.
1348   void ExcludeAll();
1349 
1350 
1351  private:
1352   static CPURegister AcquireNextAvailable(CPURegList* available);
1353 
1354   static void ReleaseByCode(CPURegList* available, int code);
1355 
1356   static void ReleaseByRegList(CPURegList* available,
1357                                RegList regs);
1358 
1359   static void IncludeByRegList(CPURegList* available,
1360                                RegList exclude);
1361 
1362   static void ExcludeByRegList(CPURegList* available,
1363                                RegList exclude);
1364 
1365   // Available scratch registers.
1366   CPURegList* available_;     // kRegister
1367   CPURegList* availablefp_;   // kFPRegister
1368 
1369   // The state of the available lists at the start of this scope.
1370   RegList old_available_;     // kRegister
1371   RegList old_availablefp_;   // kFPRegister
1372 };
1373 
1374 
1375 }  // namespace vixl
1376 
1377 #endif  // VIXL_A64_MACRO_ASSEMBLER_A64_H_
1378