blob: d589628aae1035c7df731e1326eae37d6f285db6 [file] [log] [blame]
armvixlad96eda2013-06-14 11:42:37 +01001// 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
armvixlc68cb642014-09-25 18:49:30 +010030#include <algorithm>
31#include <limits>
32
armvixlad96eda2013-06-14 11:42:37 +010033#include "globals.h"
34#include "a64/assembler-a64.h"
35#include "a64/debugger-a64.h"
36
37
38#define LS_MACRO_LIST(V) \
39 V(Ldrb, Register&, rt, LDRB_w) \
40 V(Strb, Register&, rt, STRB_w) \
41 V(Ldrsb, Register&, rt, rt.Is64Bits() ? LDRSB_x : LDRSB_w) \
42 V(Ldrh, Register&, rt, LDRH_w) \
43 V(Strh, Register&, rt, STRH_w) \
44 V(Ldrsh, Register&, rt, rt.Is64Bits() ? LDRSH_x : LDRSH_w) \
45 V(Ldr, CPURegister&, rt, LoadOpFor(rt)) \
46 V(Str, CPURegister&, rt, StoreOpFor(rt)) \
47 V(Ldrsw, Register&, rt, LDRSW_x)
48
armvixlc68cb642014-09-25 18:49:30 +010049
50#define LSPAIR_MACRO_LIST(V) \
51 V(Ldp, CPURegister&, rt, rt2, LoadPairOpFor(rt, rt2)) \
52 V(Stp, CPURegister&, rt, rt2, StorePairOpFor(rt, rt2)) \
53 V(Ldpsw, CPURegister&, rt, rt2, LDPSW_x)
54
armvixlad96eda2013-06-14 11:42:37 +010055namespace vixl {
56
armvixlc68cb642014-09-25 18:49:30 +010057class LiteralPool {
58 public:
59 // Recommended not exact since the pool can be blocked for short periods.
60 static const ptrdiff_t kRecommendedLiteralPoolRange = 128 * KBytes;
61 enum EmitOption {
62 kBranchRequired,
63 kNoBranchRequired
64 };
65
66 explicit LiteralPool(Assembler *masm);
67 ~LiteralPool();
68 void Reset();
69
70 template <typename T>
71 RawLiteral* Add(T imm) {
72 if (IsEmpty()) {
73 first_use_ = assm_->CursorOffset();
74 } else {
75 VIXL_ASSERT(assm_->CursorOffset() > first_use_);
76 }
77
78 RawLiteral* literal = new Literal<T>(imm);
79 entries_.push_back(literal);
80
81 return literal;
82 }
83 bool IsEmpty() const { return entries_.empty(); }
84 size_t Size() const ;
85
86 void Block() { monitor_++; }
87 void Release();
88 bool IsBlocked() const { return monitor_ != 0; }
89
90 ptrdiff_t MaxCursorOffset() const {
91 if (IsEmpty()) return std::numeric_limits<ptrdiff_t>::max();
92 return first_use_ + kMaxLoadLiteralRange;
93 }
94
95 void CheckEmitFor(size_t amount, EmitOption option = kBranchRequired);
96 void Emit(EmitOption option = kNoBranchRequired);
97 ptrdiff_t NextCheckOffset();
98
99 private:
100 Assembler* assm_;
101 std::vector<RawLiteral*> entries_;
102 ptrdiff_t first_use_;
103 int monitor_;
104};
105
106
107// Forward declaration
108class MacroAssembler;
109
110// This scope has the following purposes:
111// * Acquire/Release the underlying assembler's code buffer.
112// * This is mandatory before emitting.
113// * Emit the literal pool if necessary before emitting the macro-instruction.
114// * Ensure there is enough space to emit the macro-instruction.
115class EmissionCheckScope {
116 public:
117 EmissionCheckScope(MacroAssembler* masm, size_t size);
118 ~EmissionCheckScope();
119
120 protected:
121#ifdef DEBUG
122 MacroAssembler* masm_;
123 Label start_;
124 size_t size_;
125#endif
126};
127
128
129// Helper for common Emission checks.
130// The macro-instruction maps to a single instruction.
131class SingleEmissionCheckScope : public EmissionCheckScope {
132 public:
133 explicit SingleEmissionCheckScope(MacroAssembler* masm)
134 : EmissionCheckScope(masm, kInstructionSize) {}
135};
136
137
138// The macro instruction is a "typical" macro-instruction. Typical macro-
139// instruction only emit a few instructions, a few being defined as 8 here.
140class MacroEmissionCheckScope : public EmissionCheckScope {
141 public:
142 explicit MacroEmissionCheckScope(MacroAssembler* masm)
143 : EmissionCheckScope(masm, kTypicalMacroInstructionMaxSize) {}
144
145 private:
146 static const size_t kTypicalMacroInstructionMaxSize = 8 * kInstructionSize;
147};
148
149
armvixlb0c8ae22014-03-21 14:03:59 +0000150enum BranchType {
151 // Copies of architectural conditions.
152 // The associated conditions can be used in place of those, the code will
153 // take care of reinterpreting them with the correct type.
154 integer_eq = eq,
155 integer_ne = ne,
156 integer_hs = hs,
157 integer_lo = lo,
158 integer_mi = mi,
159 integer_pl = pl,
160 integer_vs = vs,
161 integer_vc = vc,
162 integer_hi = hi,
163 integer_ls = ls,
164 integer_ge = ge,
165 integer_lt = lt,
166 integer_gt = gt,
167 integer_le = le,
168 integer_al = al,
169 integer_nv = nv,
170
171 // These two are *different* from the architectural codes al and nv.
172 // 'always' is used to generate unconditional branches.
173 // 'never' is used to not generate a branch (generally as the inverse
174 // branch type of 'always).
175 always, never,
176 // cbz and cbnz
177 reg_zero, reg_not_zero,
178 // tbz and tbnz
179 reg_bit_clear, reg_bit_set,
180
181 // Aliases.
182 kBranchTypeFirstCondition = eq,
183 kBranchTypeLastCondition = nv,
184 kBranchTypeFirstUsingReg = reg_zero,
185 kBranchTypeFirstUsingBit = reg_bit_clear
186};
187
188
armvixlf37fdc02014-02-05 13:22:16 +0000189enum DiscardMoveMode { kDontDiscardForSameWReg, kDiscardForSameWReg };
190
armvixlc68cb642014-09-25 18:49:30 +0100191
armvixlad96eda2013-06-14 11:42:37 +0100192class MacroAssembler : public Assembler {
193 public:
armvixlc68cb642014-09-25 18:49:30 +0100194 MacroAssembler(size_t capacity,
195 PositionIndependentCodeOption pic = PositionIndependentCode);
196 MacroAssembler(byte * buffer, size_t capacity,
197 PositionIndependentCodeOption pic = PositionIndependentCode);
198 ~MacroAssembler();
199
200 // Start generating code from the beginning of the buffer, discarding any code
201 // and data that has already been emitted into the buffer.
202 //
203 // In order to avoid any accidental transfer of state, Reset ASSERTs that the
204 // constant pool is not blocked.
205 void Reset();
206
207 // Finalize a code buffer of generated instructions. This function must be
208 // called before executing or copying code from the buffer.
209 void FinalizeCode();
armvixlad96eda2013-06-14 11:42:37 +0100210
211 // Logical macros.
212 void And(const Register& rd,
213 const Register& rn,
armvixlf37fdc02014-02-05 13:22:16 +0000214 const Operand& operand);
215 void Ands(const Register& rd,
216 const Register& rn,
217 const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100218 void Bic(const Register& rd,
219 const Register& rn,
armvixlf37fdc02014-02-05 13:22:16 +0000220 const Operand& operand);
221 void Bics(const Register& rd,
222 const Register& rn,
223 const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100224 void Orr(const Register& rd,
225 const Register& rn,
226 const Operand& operand);
227 void Orn(const Register& rd,
228 const Register& rn,
229 const Operand& operand);
230 void Eor(const Register& rd,
231 const Register& rn,
232 const Operand& operand);
233 void Eon(const Register& rd,
234 const Register& rn,
235 const Operand& operand);
236 void Tst(const Register& rn, const Operand& operand);
237 void LogicalMacro(const Register& rd,
238 const Register& rn,
239 const Operand& operand,
240 LogicalOp op);
241
242 // Add and sub macros.
243 void Add(const Register& rd,
244 const Register& rn,
armvixlf37fdc02014-02-05 13:22:16 +0000245 const Operand& operand);
246 void Adds(const Register& rd,
247 const Register& rn,
248 const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100249 void Sub(const Register& rd,
250 const Register& rn,
armvixlf37fdc02014-02-05 13:22:16 +0000251 const Operand& operand);
252 void Subs(const Register& rd,
253 const Register& rn,
254 const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100255 void Cmn(const Register& rn, const Operand& operand);
256 void Cmp(const Register& rn, const Operand& operand);
257 void Neg(const Register& rd,
armvixlf37fdc02014-02-05 13:22:16 +0000258 const Operand& operand);
259 void Negs(const Register& rd,
260 const Operand& operand);
261
armvixlad96eda2013-06-14 11:42:37 +0100262 void AddSubMacro(const Register& rd,
263 const Register& rn,
264 const Operand& operand,
265 FlagsUpdate S,
266 AddSubOp op);
267
268 // Add/sub with carry macros.
269 void Adc(const Register& rd,
270 const Register& rn,
armvixlf37fdc02014-02-05 13:22:16 +0000271 const Operand& operand);
272 void Adcs(const Register& rd,
273 const Register& rn,
274 const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100275 void Sbc(const Register& rd,
276 const Register& rn,
armvixlf37fdc02014-02-05 13:22:16 +0000277 const Operand& operand);
278 void Sbcs(const Register& rd,
279 const Register& rn,
280 const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100281 void Ngc(const Register& rd,
armvixlf37fdc02014-02-05 13:22:16 +0000282 const Operand& operand);
283 void Ngcs(const Register& rd,
284 const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100285 void AddSubWithCarryMacro(const Register& rd,
286 const Register& rn,
287 const Operand& operand,
288 FlagsUpdate S,
289 AddSubWithCarryOp op);
290
291 // Move macros.
292 void Mov(const Register& rd, uint64_t imm);
armvixlf37fdc02014-02-05 13:22:16 +0000293 void Mov(const Register& rd,
294 const Operand& operand,
295 DiscardMoveMode discard_mode = kDontDiscardForSameWReg);
armvixlad96eda2013-06-14 11:42:37 +0100296 void Mvn(const Register& rd, uint64_t imm) {
armvixlf37fdc02014-02-05 13:22:16 +0000297 Mov(rd, (rd.size() == kXRegSize) ? ~imm : (~imm & kWRegMask));
armvixl4a102ba2014-07-14 09:02:40 +0100298 }
armvixlad96eda2013-06-14 11:42:37 +0100299 void Mvn(const Register& rd, const Operand& operand);
armvixlad96eda2013-06-14 11:42:37 +0100300 bool IsImmMovz(uint64_t imm, unsigned reg_size);
armvixlf37fdc02014-02-05 13:22:16 +0000301 bool IsImmMovn(uint64_t imm, unsigned reg_size);
302 unsigned CountClearHalfWords(uint64_t imm, unsigned reg_size);
armvixlad96eda2013-06-14 11:42:37 +0100303
armvixl4a102ba2014-07-14 09:02:40 +0100304 // Try to move an immediate into the destination register in a single
305 // instruction. Returns true for success, and updates the contents of dst.
306 // Returns false, otherwise.
307 bool TryOneInstrMoveImmediate(const Register& dst, int64_t imm);
308
309 // Move an immediate into register dst, and return an Operand object for
310 // use with a subsequent instruction that accepts a shift. The value moved
311 // into dst is not necessarily equal to imm; it may have had a shifting
312 // operation applied to it that will be subsequently undone by the shift
313 // applied in the Operand.
314 Operand MoveImmediateForShiftedOp(const Register& dst, int64_t imm);
315
armvixlf37fdc02014-02-05 13:22:16 +0000316 // Conditional macros.
armvixlad96eda2013-06-14 11:42:37 +0100317 void Ccmp(const Register& rn,
318 const Operand& operand,
319 StatusFlags nzcv,
320 Condition cond);
321 void Ccmn(const Register& rn,
322 const Operand& operand,
323 StatusFlags nzcv,
324 Condition cond);
325 void ConditionalCompareMacro(const Register& rn,
326 const Operand& operand,
327 StatusFlags nzcv,
328 Condition cond,
329 ConditionalCompareOp op);
armvixlf37fdc02014-02-05 13:22:16 +0000330 void Csel(const Register& rd,
331 const Register& rn,
332 const Operand& operand,
333 Condition cond);
armvixlad96eda2013-06-14 11:42:37 +0100334
335 // Load/store macros.
336#define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \
337 void FN(const REGTYPE REG, const MemOperand& addr);
338 LS_MACRO_LIST(DECLARE_FUNCTION)
339#undef DECLARE_FUNCTION
340
341 void LoadStoreMacro(const CPURegister& rt,
342 const MemOperand& addr,
343 LoadStoreOp op);
344
armvixlc68cb642014-09-25 18:49:30 +0100345#define DECLARE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \
346 void FN(const REGTYPE REG, const REGTYPE REG2, const MemOperand& addr);
347 LSPAIR_MACRO_LIST(DECLARE_FUNCTION)
348#undef DECLARE_FUNCTION
349
350 void LoadStorePairMacro(const CPURegister& rt,
351 const CPURegister& rt2,
352 const MemOperand& addr,
353 LoadStorePairOp op);
354
armvixlad96eda2013-06-14 11:42:37 +0100355 // Push or pop up to 4 registers of the same width to or from the stack,
356 // using the current stack pointer as set by SetStackPointer.
357 //
358 // If an argument register is 'NoReg', all further arguments are also assumed
359 // to be 'NoReg', and are thus not pushed or popped.
360 //
361 // Arguments are ordered such that "Push(a, b);" is functionally equivalent
362 // to "Push(a); Push(b);".
363 //
364 // It is valid to push the same register more than once, and there is no
365 // restriction on the order in which registers are specified.
366 //
367 // It is not valid to pop into the same register more than once in one
368 // operation, not even into the zero register.
369 //
370 // If the current stack pointer (as set by SetStackPointer) is sp, then it
371 // must be aligned to 16 bytes on entry and the total size of the specified
372 // registers must also be a multiple of 16 bytes.
373 //
374 // Even if the current stack pointer is not the system stack pointer (sp),
375 // Push (and derived methods) will still modify the system stack pointer in
376 // order to comply with ABI rules about accessing memory below the system
377 // stack pointer.
378 //
379 // Other than the registers passed into Pop, the stack pointer and (possibly)
380 // the system stack pointer, these methods do not modify any other registers.
armvixlad96eda2013-06-14 11:42:37 +0100381 void Push(const CPURegister& src0, const CPURegister& src1 = NoReg,
382 const CPURegister& src2 = NoReg, const CPURegister& src3 = NoReg);
383 void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg,
384 const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg);
385
386 // Alternative forms of Push and Pop, taking a RegList or CPURegList that
387 // specifies the registers that are to be pushed or popped. Higher-numbered
388 // registers are associated with higher memory addresses (as in the A32 push
389 // and pop instructions).
390 //
391 // (Push|Pop)SizeRegList allow you to specify the register size as a
392 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
393 // supported.
394 //
395 // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred.
396 void PushCPURegList(CPURegList registers);
397 void PopCPURegList(CPURegList registers);
398
399 void PushSizeRegList(RegList registers, unsigned reg_size,
400 CPURegister::RegisterType type = CPURegister::kRegister) {
401 PushCPURegList(CPURegList(type, reg_size, registers));
402 }
403 void PopSizeRegList(RegList registers, unsigned reg_size,
404 CPURegister::RegisterType type = CPURegister::kRegister) {
405 PopCPURegList(CPURegList(type, reg_size, registers));
406 }
407 void PushXRegList(RegList regs) {
408 PushSizeRegList(regs, kXRegSize);
409 }
410 void PopXRegList(RegList regs) {
411 PopSizeRegList(regs, kXRegSize);
412 }
413 void PushWRegList(RegList regs) {
414 PushSizeRegList(regs, kWRegSize);
415 }
416 void PopWRegList(RegList regs) {
417 PopSizeRegList(regs, kWRegSize);
418 }
419 inline void PushDRegList(RegList regs) {
420 PushSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
421 }
422 inline void PopDRegList(RegList regs) {
423 PopSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
424 }
425 inline void PushSRegList(RegList regs) {
426 PushSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
427 }
428 inline void PopSRegList(RegList regs) {
429 PopSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
430 }
431
432 // Push the specified register 'count' times.
433 void PushMultipleTimes(int count, Register src);
434
435 // Poke 'src' onto the stack. The offset is in bytes.
436 //
437 // If the current stack pointer (as set by SetStackPointer) is sp, then sp
438 // must be aligned to 16 bytes.
439 void Poke(const Register& src, const Operand& offset);
440
441 // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes.
442 //
443 // If the current stack pointer (as set by SetStackPointer) is sp, then sp
444 // must be aligned to 16 bytes.
445 void Peek(const Register& dst, const Operand& offset);
446
armvixlc68cb642014-09-25 18:49:30 +0100447 // Alternative forms of Peek and Poke, taking a RegList or CPURegList that
448 // specifies the registers that are to be pushed or popped. Higher-numbered
449 // registers are associated with higher memory addresses.
450 //
451 // (Peek|Poke)SizeRegList allow you to specify the register size as a
452 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
453 // supported.
454 //
455 // Otherwise, (Peek|Poke)(CPU|X|W|D|S)RegList is preferred.
456 void PeekCPURegList(CPURegList registers, int offset);
457 void PokeCPURegList(CPURegList registers, int offset);
458
459 void PeekSizeRegList(RegList registers, int offset, unsigned reg_size,
460 CPURegister::RegisterType type = CPURegister::kRegister) {
461 PeekCPURegList(CPURegList(type, reg_size, registers), offset);
462 }
463 void PokeSizeRegList(RegList registers, int offset, unsigned reg_size,
464 CPURegister::RegisterType type = CPURegister::kRegister) {
465 PokeCPURegList(CPURegList(type, reg_size, registers), offset);
466 }
467 void PeekXRegList(RegList regs, int offset) {
468 PeekSizeRegList(regs, offset, kXRegSize);
469 }
470 void PokeXRegList(RegList regs, int offset) {
471 PokeSizeRegList(regs, offset, kXRegSize);
472 }
473 void PeekWRegList(RegList regs, int offset) {
474 PeekSizeRegList(regs, offset, kWRegSize);
475 }
476 void PokeWRegList(RegList regs, int offset) {
477 PokeSizeRegList(regs, offset, kWRegSize);
478 }
479 inline void PeekDRegList(RegList regs, int offset) {
480 PeekSizeRegList(regs, offset, kDRegSize, CPURegister::kFPRegister);
481 }
482 inline void PokeDRegList(RegList regs, int offset) {
483 PokeSizeRegList(regs, offset, kDRegSize, CPURegister::kFPRegister);
484 }
485 inline void PeekSRegList(RegList regs, int offset) {
486 PeekSizeRegList(regs, offset, kSRegSize, CPURegister::kFPRegister);
487 }
488 inline void PokeSRegList(RegList regs, int offset) {
489 PokeSizeRegList(regs, offset, kSRegSize, CPURegister::kFPRegister);
490 }
491
492
armvixlad96eda2013-06-14 11:42:37 +0100493 // Claim or drop stack space without actually accessing memory.
494 //
495 // If the current stack pointer (as set by SetStackPointer) is sp, then it
496 // must be aligned to 16 bytes and the size claimed or dropped must be a
497 // multiple of 16 bytes.
498 void Claim(const Operand& size);
499 void Drop(const Operand& size);
500
501 // Preserve the callee-saved registers (as defined by AAPCS64).
502 //
503 // Higher-numbered registers are pushed before lower-numbered registers, and
504 // thus get higher addresses.
505 // Floating-point registers are pushed before general-purpose registers, and
506 // thus get higher addresses.
507 //
508 // This method must not be called unless StackPointer() is sp, and it is
509 // aligned to 16 bytes.
510 void PushCalleeSavedRegisters();
511
512 // Restore the callee-saved registers (as defined by AAPCS64).
513 //
514 // Higher-numbered registers are popped after lower-numbered registers, and
515 // thus come from higher addresses.
516 // Floating-point registers are popped after general-purpose registers, and
517 // thus come from higher addresses.
518 //
519 // This method must not be called unless StackPointer() is sp, and it is
520 // aligned to 16 bytes.
521 void PopCalleeSavedRegisters();
522
523 // Remaining instructions are simple pass-through calls to the assembler.
524 void Adr(const Register& rd, Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +0000525 VIXL_ASSERT(allow_macro_instructions_);
526 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100527 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100528 adr(rd, label);
529 }
armvixl4a102ba2014-07-14 09:02:40 +0100530 void Adrp(const Register& rd, Label* label) {
531 VIXL_ASSERT(allow_macro_instructions_);
532 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100533 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +0100534 adrp(rd, label);
535 }
armvixlad96eda2013-06-14 11:42:37 +0100536 void Asr(const Register& rd, const Register& rn, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +0000537 VIXL_ASSERT(allow_macro_instructions_);
538 VIXL_ASSERT(!rd.IsZero());
539 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100540 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100541 asr(rd, rn, shift);
542 }
543 void Asr(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000544 VIXL_ASSERT(allow_macro_instructions_);
545 VIXL_ASSERT(!rd.IsZero());
546 VIXL_ASSERT(!rn.IsZero());
547 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100548 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100549 asrv(rd, rn, rm);
550 }
armvixlb0c8ae22014-03-21 14:03:59 +0000551
552 // Branch type inversion relies on these relations.
553 VIXL_STATIC_ASSERT((reg_zero == (reg_not_zero ^ 1)) &&
554 (reg_bit_clear == (reg_bit_set ^ 1)) &&
555 (always == (never ^ 1)));
556
557 BranchType InvertBranchType(BranchType type) {
558 if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
559 return static_cast<BranchType>(
560 InvertCondition(static_cast<Condition>(type)));
561 } else {
562 return static_cast<BranchType>(type ^ 1);
563 }
564 }
565
566 void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1);
567
armvixl578645f2013-08-15 17:21:42 +0100568 void B(Label* label) {
armvixlc68cb642014-09-25 18:49:30 +0100569 SingleEmissionCheckScope guard(this);
armvixl578645f2013-08-15 17:21:42 +0100570 b(label);
571 }
572 void B(Label* label, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000573 VIXL_ASSERT(allow_macro_instructions_);
574 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +0100575 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100576 b(label, cond);
577 }
armvixlb0c8ae22014-03-21 14:03:59 +0000578 void B(Condition cond, Label* label) {
579 B(label, cond);
580 }
armvixlad96eda2013-06-14 11:42:37 +0100581 void Bfi(const Register& rd,
582 const Register& rn,
583 unsigned lsb,
584 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +0000585 VIXL_ASSERT(allow_macro_instructions_);
586 VIXL_ASSERT(!rd.IsZero());
587 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100588 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100589 bfi(rd, rn, lsb, width);
590 }
591 void Bfxil(const Register& rd,
592 const Register& rn,
593 unsigned lsb,
594 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +0000595 VIXL_ASSERT(allow_macro_instructions_);
596 VIXL_ASSERT(!rd.IsZero());
597 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100598 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100599 bfxil(rd, rn, lsb, width);
600 }
601 void Bind(Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +0000602 VIXL_ASSERT(allow_macro_instructions_);
armvixlad96eda2013-06-14 11:42:37 +0100603 bind(label);
604 }
armvixlc68cb642014-09-25 18:49:30 +0100605 // Bind a label to a specified offset from the start of the buffer.
606 void BindToOffset(Label* label, ptrdiff_t offset) {
607 VIXL_ASSERT(allow_macro_instructions_);
608 Assembler::BindToOffset(label, offset);
609 }
armvixlad96eda2013-06-14 11:42:37 +0100610 void Bl(Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +0000611 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100612 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100613 bl(label);
614 }
615 void Blr(const Register& xn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000616 VIXL_ASSERT(allow_macro_instructions_);
617 VIXL_ASSERT(!xn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100618 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100619 blr(xn);
620 }
621 void Br(const Register& xn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000622 VIXL_ASSERT(allow_macro_instructions_);
623 VIXL_ASSERT(!xn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100624 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100625 br(xn);
626 }
627 void Brk(int code = 0) {
armvixlb0c8ae22014-03-21 14:03:59 +0000628 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100629 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100630 brk(code);
631 }
632 void Cbnz(const Register& rt, Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +0000633 VIXL_ASSERT(allow_macro_instructions_);
634 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100635 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100636 cbnz(rt, label);
637 }
638 void Cbz(const Register& rt, Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +0000639 VIXL_ASSERT(allow_macro_instructions_);
640 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100641 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100642 cbz(rt, label);
643 }
644 void Cinc(const Register& rd, const Register& rn, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000645 VIXL_ASSERT(allow_macro_instructions_);
646 VIXL_ASSERT(!rd.IsZero());
647 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100648 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100649 cinc(rd, rn, cond);
650 }
651 void Cinv(const Register& rd, const Register& rn, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000652 VIXL_ASSERT(allow_macro_instructions_);
653 VIXL_ASSERT(!rd.IsZero());
654 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100655 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100656 cinv(rd, rn, cond);
657 }
armvixl4a102ba2014-07-14 09:02:40 +0100658 void Clrex() {
659 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100660 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +0100661 clrex();
662 }
armvixlad96eda2013-06-14 11:42:37 +0100663 void Cls(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000664 VIXL_ASSERT(allow_macro_instructions_);
665 VIXL_ASSERT(!rd.IsZero());
666 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100667 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100668 cls(rd, rn);
669 }
670 void Clz(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000671 VIXL_ASSERT(allow_macro_instructions_);
672 VIXL_ASSERT(!rd.IsZero());
673 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100674 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100675 clz(rd, rn);
676 }
677 void Cneg(const Register& rd, const Register& rn, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000678 VIXL_ASSERT(allow_macro_instructions_);
679 VIXL_ASSERT(!rd.IsZero());
680 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100681 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100682 cneg(rd, rn, cond);
683 }
armvixlad96eda2013-06-14 11:42:37 +0100684 void Cset(const Register& rd, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000685 VIXL_ASSERT(allow_macro_instructions_);
686 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100687 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100688 cset(rd, cond);
689 }
690 void Csetm(const Register& rd, Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000691 VIXL_ASSERT(allow_macro_instructions_);
692 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100693 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100694 csetm(rd, cond);
695 }
696 void Csinc(const Register& rd,
697 const Register& rn,
698 const Register& rm,
699 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000700 VIXL_ASSERT(allow_macro_instructions_);
701 VIXL_ASSERT(!rd.IsZero());
702 VIXL_ASSERT(!rn.IsZero());
703 VIXL_ASSERT(!rm.IsZero());
704 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +0100705 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100706 csinc(rd, rn, rm, cond);
707 }
708 void Csinv(const Register& rd,
709 const Register& rn,
710 const Register& rm,
711 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000712 VIXL_ASSERT(allow_macro_instructions_);
713 VIXL_ASSERT(!rd.IsZero());
714 VIXL_ASSERT(!rn.IsZero());
715 VIXL_ASSERT(!rm.IsZero());
716 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +0100717 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100718 csinv(rd, rn, rm, cond);
719 }
720 void Csneg(const Register& rd,
721 const Register& rn,
722 const Register& rm,
723 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000724 VIXL_ASSERT(allow_macro_instructions_);
725 VIXL_ASSERT(!rd.IsZero());
726 VIXL_ASSERT(!rn.IsZero());
727 VIXL_ASSERT(!rm.IsZero());
728 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +0100729 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100730 csneg(rd, rn, rm, cond);
731 }
armvixlf37fdc02014-02-05 13:22:16 +0000732 void Dmb(BarrierDomain domain, BarrierType type) {
armvixlb0c8ae22014-03-21 14:03:59 +0000733 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100734 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000735 dmb(domain, type);
736 }
737 void Dsb(BarrierDomain domain, BarrierType type) {
armvixlb0c8ae22014-03-21 14:03:59 +0000738 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100739 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000740 dsb(domain, type);
741 }
armvixlad96eda2013-06-14 11:42:37 +0100742 void Extr(const Register& rd,
743 const Register& rn,
744 const Register& rm,
745 unsigned lsb) {
armvixlb0c8ae22014-03-21 14:03:59 +0000746 VIXL_ASSERT(allow_macro_instructions_);
747 VIXL_ASSERT(!rd.IsZero());
748 VIXL_ASSERT(!rn.IsZero());
749 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100750 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100751 extr(rd, rn, rm, lsb);
752 }
753 void Fabs(const FPRegister& fd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000754 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100755 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100756 fabs(fd, fn);
757 }
758 void Fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000759 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100760 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100761 fadd(fd, fn, fm);
762 }
763 void Fccmp(const FPRegister& fn,
764 const FPRegister& fm,
765 StatusFlags nzcv,
766 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000767 VIXL_ASSERT(allow_macro_instructions_);
768 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +0100769 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100770 fccmp(fn, fm, nzcv, cond);
771 }
772 void Fcmp(const FPRegister& fn, const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000773 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100774 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100775 fcmp(fn, fm);
776 }
armvixlb0c8ae22014-03-21 14:03:59 +0000777 void Fcmp(const FPRegister& fn, double value);
armvixlad96eda2013-06-14 11:42:37 +0100778 void Fcsel(const FPRegister& fd,
779 const FPRegister& fn,
780 const FPRegister& fm,
781 Condition cond) {
armvixlb0c8ae22014-03-21 14:03:59 +0000782 VIXL_ASSERT(allow_macro_instructions_);
783 VIXL_ASSERT((cond != al) && (cond != nv));
armvixlc68cb642014-09-25 18:49:30 +0100784 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100785 fcsel(fd, fn, fm, cond);
786 }
armvixl578645f2013-08-15 17:21:42 +0100787 void Fcvt(const FPRegister& fd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000788 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100789 SingleEmissionCheckScope guard(this);
armvixl578645f2013-08-15 17:21:42 +0100790 fcvt(fd, fn);
791 }
armvixlf37fdc02014-02-05 13:22:16 +0000792 void Fcvtas(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000793 VIXL_ASSERT(allow_macro_instructions_);
794 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100795 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000796 fcvtas(rd, fn);
797 }
798 void Fcvtau(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000799 VIXL_ASSERT(allow_macro_instructions_);
800 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100801 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000802 fcvtau(rd, fn);
803 }
armvixlad96eda2013-06-14 11:42:37 +0100804 void Fcvtms(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000805 VIXL_ASSERT(allow_macro_instructions_);
806 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100807 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100808 fcvtms(rd, fn);
809 }
810 void Fcvtmu(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000811 VIXL_ASSERT(allow_macro_instructions_);
812 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100813 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100814 fcvtmu(rd, fn);
815 }
816 void Fcvtns(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000817 VIXL_ASSERT(allow_macro_instructions_);
818 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100819 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100820 fcvtns(rd, fn);
821 }
822 void Fcvtnu(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000823 VIXL_ASSERT(allow_macro_instructions_);
824 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100825 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100826 fcvtnu(rd, fn);
827 }
828 void Fcvtzs(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000829 VIXL_ASSERT(allow_macro_instructions_);
830 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100831 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100832 fcvtzs(rd, fn);
833 }
834 void Fcvtzu(const Register& rd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000835 VIXL_ASSERT(allow_macro_instructions_);
836 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100837 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100838 fcvtzu(rd, fn);
839 }
840 void Fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000841 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100842 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100843 fdiv(fd, fn, fm);
844 }
845 void Fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000846 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100847 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100848 fmax(fd, fn, fm);
849 }
armvixlf37fdc02014-02-05 13:22:16 +0000850 void Fmaxnm(const FPRegister& fd,
851 const FPRegister& fn,
852 const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000853 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100854 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000855 fmaxnm(fd, fn, fm);
856 }
armvixlad96eda2013-06-14 11:42:37 +0100857 void Fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000858 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100859 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100860 fmin(fd, fn, fm);
861 }
armvixlf37fdc02014-02-05 13:22:16 +0000862 void Fminnm(const FPRegister& fd,
863 const FPRegister& fn,
864 const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000865 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100866 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000867 fminnm(fd, fn, fm);
868 }
armvixlad96eda2013-06-14 11:42:37 +0100869 void Fmov(FPRegister fd, FPRegister fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000870 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100871 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100872 // Only emit an instruction if fd and fn are different, and they are both D
873 // registers. fmov(s0, s0) is not a no-op because it clears the top word of
874 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears
875 // the top of q0, but FPRegister does not currently support Q registers.
876 if (!fd.Is(fn) || !fd.Is64Bits()) {
877 fmov(fd, fn);
878 }
879 }
880 void Fmov(FPRegister fd, Register rn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000881 VIXL_ASSERT(allow_macro_instructions_);
882 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100883 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100884 fmov(fd, rn);
885 }
armvixlb0c8ae22014-03-21 14:03:59 +0000886 // Provide explicit double and float interfaces for FP immediate moves, rather
887 // than relying on implicit C++ casts. This allows signalling NaNs to be
888 // preserved when the immediate matches the format of fd. Most systems convert
889 // signalling NaNs to quiet NaNs when converting between float and double.
890 void Fmov(FPRegister fd, double imm);
891 void Fmov(FPRegister fd, float imm);
892 // Provide a template to allow other types to be converted automatically.
893 template<typename T>
894 void Fmov(FPRegister fd, T imm) {
895 VIXL_ASSERT(allow_macro_instructions_);
896 Fmov(fd, static_cast<double>(imm));
armvixlad96eda2013-06-14 11:42:37 +0100897 }
898 void Fmov(Register rd, FPRegister fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000899 VIXL_ASSERT(allow_macro_instructions_);
900 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +0100901 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100902 fmov(rd, fn);
903 }
904 void Fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000905 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100906 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100907 fmul(fd, fn, fm);
908 }
armvixlf37fdc02014-02-05 13:22:16 +0000909 void Fmadd(const FPRegister& fd,
910 const FPRegister& fn,
911 const FPRegister& fm,
912 const FPRegister& fa) {
armvixlb0c8ae22014-03-21 14:03:59 +0000913 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100914 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000915 fmadd(fd, fn, fm, fa);
916 }
armvixlad96eda2013-06-14 11:42:37 +0100917 void Fmsub(const FPRegister& fd,
918 const FPRegister& fn,
919 const FPRegister& fm,
920 const FPRegister& fa) {
armvixlb0c8ae22014-03-21 14:03:59 +0000921 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100922 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100923 fmsub(fd, fn, fm, fa);
924 }
armvixlf37fdc02014-02-05 13:22:16 +0000925 void Fnmadd(const FPRegister& fd,
926 const FPRegister& fn,
927 const FPRegister& fm,
928 const FPRegister& fa) {
armvixlb0c8ae22014-03-21 14:03:59 +0000929 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100930 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000931 fnmadd(fd, fn, fm, fa);
932 }
933 void Fnmsub(const FPRegister& fd,
934 const FPRegister& fn,
935 const FPRegister& fm,
936 const FPRegister& fa) {
armvixlb0c8ae22014-03-21 14:03:59 +0000937 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100938 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000939 fnmsub(fd, fn, fm, fa);
940 }
armvixlad96eda2013-06-14 11:42:37 +0100941 void Fneg(const FPRegister& fd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000942 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100943 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100944 fneg(fd, fn);
945 }
armvixlf37fdc02014-02-05 13:22:16 +0000946 void Frinta(const FPRegister& fd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000947 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100948 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000949 frinta(fd, fn);
950 }
armvixl5799d6c2014-05-01 11:05:00 +0100951 void Frintm(const FPRegister& fd, const FPRegister& fn) {
952 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100953 SingleEmissionCheckScope guard(this);
armvixl5799d6c2014-05-01 11:05:00 +0100954 frintm(fd, fn);
955 }
armvixlad96eda2013-06-14 11:42:37 +0100956 void Frintn(const FPRegister& fd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000957 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100958 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100959 frintn(fd, fn);
960 }
961 void Frintz(const FPRegister& fd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000962 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100963 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100964 frintz(fd, fn);
965 }
966 void Fsqrt(const FPRegister& fd, const FPRegister& fn) {
armvixlb0c8ae22014-03-21 14:03:59 +0000967 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100968 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100969 fsqrt(fd, fn);
970 }
armvixlad96eda2013-06-14 11:42:37 +0100971 void Fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
armvixlb0c8ae22014-03-21 14:03:59 +0000972 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100973 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100974 fsub(fd, fn, fm);
975 }
976 void Hint(SystemHint code) {
armvixlb0c8ae22014-03-21 14:03:59 +0000977 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100978 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100979 hint(code);
980 }
981 void Hlt(int code) {
armvixlb0c8ae22014-03-21 14:03:59 +0000982 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100983 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +0100984 hlt(code);
985 }
armvixlf37fdc02014-02-05 13:22:16 +0000986 void Isb() {
armvixlb0c8ae22014-03-21 14:03:59 +0000987 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100988 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +0000989 isb();
990 }
armvixl4a102ba2014-07-14 09:02:40 +0100991 void Ldar(const Register& rt, const MemOperand& src) {
992 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100993 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +0100994 ldar(rt, src);
995 }
996 void Ldarb(const Register& rt, const MemOperand& src) {
997 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +0100998 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +0100999 ldarb(rt, src);
1000 }
1001 void Ldarh(const Register& rt, const MemOperand& src) {
1002 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001003 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001004 ldarh(rt, src);
1005 }
1006 void Ldaxp(const Register& rt, const Register& rt2, const MemOperand& src) {
1007 VIXL_ASSERT(allow_macro_instructions_);
1008 VIXL_ASSERT(!rt.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001009 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001010 ldaxp(rt, rt2, src);
1011 }
1012 void Ldaxr(const Register& rt, const MemOperand& src) {
1013 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001014 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001015 ldaxr(rt, src);
1016 }
1017 void Ldaxrb(const Register& rt, const MemOperand& src) {
1018 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001019 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001020 ldaxrb(rt, src);
1021 }
1022 void Ldaxrh(const Register& rt, const MemOperand& src) {
1023 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001024 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001025 ldaxrh(rt, src);
1026 }
armvixlad96eda2013-06-14 11:42:37 +01001027 void Ldnp(const CPURegister& rt,
1028 const CPURegister& rt2,
1029 const MemOperand& src) {
armvixlb0c8ae22014-03-21 14:03:59 +00001030 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001031 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001032 ldnp(rt, rt2, src);
1033 }
armvixlb0c8ae22014-03-21 14:03:59 +00001034 // Provide both double and float interfaces for FP immediate loads, rather
1035 // than relying on implicit C++ casts. This allows signalling NaNs to be
1036 // preserved when the immediate matches the format of fd. Most systems convert
1037 // signalling NaNs to quiet NaNs when converting between float and double.
armvixlad96eda2013-06-14 11:42:37 +01001038 void Ldr(const FPRegister& ft, double imm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001039 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001040 SingleEmissionCheckScope guard(this);
1041 RawLiteral* literal;
armvixlb0c8ae22014-03-21 14:03:59 +00001042 if (ft.Is64Bits()) {
armvixlc68cb642014-09-25 18:49:30 +01001043 literal = literal_pool_.Add(imm);
armvixlb0c8ae22014-03-21 14:03:59 +00001044 } else {
armvixlc68cb642014-09-25 18:49:30 +01001045 literal = literal_pool_.Add(static_cast<float>(imm));
armvixlb0c8ae22014-03-21 14:03:59 +00001046 }
armvixlc68cb642014-09-25 18:49:30 +01001047 ldr(ft, literal);
armvixlb0c8ae22014-03-21 14:03:59 +00001048 }
1049 void Ldr(const FPRegister& ft, float imm) {
1050 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001051 SingleEmissionCheckScope guard(this);
1052 RawLiteral* literal;
armvixlb0c8ae22014-03-21 14:03:59 +00001053 if (ft.Is32Bits()) {
armvixlc68cb642014-09-25 18:49:30 +01001054 literal = literal_pool_.Add(imm);
armvixlb0c8ae22014-03-21 14:03:59 +00001055 } else {
armvixlc68cb642014-09-25 18:49:30 +01001056 literal = literal_pool_.Add(static_cast<double>(imm));
armvixlb0c8ae22014-03-21 14:03:59 +00001057 }
armvixlc68cb642014-09-25 18:49:30 +01001058 ldr(ft, literal);
armvixlad96eda2013-06-14 11:42:37 +01001059 }
1060 void Ldr(const Register& rt, uint64_t imm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001061 VIXL_ASSERT(allow_macro_instructions_);
1062 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001063 SingleEmissionCheckScope guard(this);
1064 RawLiteral* literal;
1065 if (rt.Is64Bits()) {
1066 literal = literal_pool_.Add(imm);
1067 } else {
1068 VIXL_ASSERT(rt.Is32Bits());
1069 VIXL_ASSERT(is_uint32(imm) || is_int32(imm));
1070 literal = literal_pool_.Add(static_cast<uint32_t>(imm));
1071 }
1072 ldr(rt, literal);
1073 }
1074 void Ldrsw(const Register& rt, uint32_t imm) {
1075 VIXL_ASSERT(allow_macro_instructions_);
1076 VIXL_ASSERT(!rt.IsZero());
1077 SingleEmissionCheckScope guard(this);
1078 RawLiteral* literal = literal_pool_.Add(imm);
1079 ldrsw(rt, literal);
armvixlad96eda2013-06-14 11:42:37 +01001080 }
armvixl4a102ba2014-07-14 09:02:40 +01001081 void Ldxp(const Register& rt, const Register& rt2, const MemOperand& src) {
1082 VIXL_ASSERT(allow_macro_instructions_);
1083 VIXL_ASSERT(!rt.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001084 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001085 ldxp(rt, rt2, src);
1086 }
1087 void Ldxr(const Register& rt, const MemOperand& src) {
1088 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001089 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001090 ldxr(rt, src);
1091 }
1092 void Ldxrb(const Register& rt, const MemOperand& src) {
1093 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001094 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001095 ldxrb(rt, src);
1096 }
1097 void Ldxrh(const Register& rt, const MemOperand& src) {
1098 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001099 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001100 ldxrh(rt, src);
1101 }
armvixlad96eda2013-06-14 11:42:37 +01001102 void Lsl(const Register& rd, const Register& rn, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +00001103 VIXL_ASSERT(allow_macro_instructions_);
1104 VIXL_ASSERT(!rd.IsZero());
1105 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001106 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001107 lsl(rd, rn, shift);
1108 }
1109 void Lsl(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001110 VIXL_ASSERT(allow_macro_instructions_);
1111 VIXL_ASSERT(!rd.IsZero());
1112 VIXL_ASSERT(!rn.IsZero());
1113 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001114 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001115 lslv(rd, rn, rm);
1116 }
1117 void Lsr(const Register& rd, const Register& rn, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +00001118 VIXL_ASSERT(allow_macro_instructions_);
1119 VIXL_ASSERT(!rd.IsZero());
1120 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001121 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001122 lsr(rd, rn, shift);
1123 }
1124 void Lsr(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001125 VIXL_ASSERT(allow_macro_instructions_);
1126 VIXL_ASSERT(!rd.IsZero());
1127 VIXL_ASSERT(!rn.IsZero());
1128 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001129 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001130 lsrv(rd, rn, rm);
1131 }
1132 void Madd(const Register& rd,
1133 const Register& rn,
1134 const Register& rm,
1135 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001136 VIXL_ASSERT(allow_macro_instructions_);
1137 VIXL_ASSERT(!rd.IsZero());
1138 VIXL_ASSERT(!rn.IsZero());
1139 VIXL_ASSERT(!rm.IsZero());
1140 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001141 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001142 madd(rd, rn, rm, ra);
1143 }
1144 void Mneg(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001145 VIXL_ASSERT(allow_macro_instructions_);
1146 VIXL_ASSERT(!rd.IsZero());
1147 VIXL_ASSERT(!rn.IsZero());
1148 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001149 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001150 mneg(rd, rn, rm);
1151 }
1152 void Mov(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001153 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001154 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001155 mov(rd, rn);
1156 }
armvixlf37fdc02014-02-05 13:22:16 +00001157 void Movk(const Register& rd, uint64_t imm, int shift = -1) {
armvixlb0c8ae22014-03-21 14:03:59 +00001158 VIXL_ASSERT(allow_macro_instructions_);
1159 VIXL_ASSERT(!rd.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001160 SingleEmissionCheckScope guard(this);
armvixlf37fdc02014-02-05 13:22:16 +00001161 movk(rd, imm, shift);
1162 }
armvixlad96eda2013-06-14 11:42:37 +01001163 void Mrs(const Register& rt, SystemRegister sysreg) {
armvixlb0c8ae22014-03-21 14:03:59 +00001164 VIXL_ASSERT(allow_macro_instructions_);
1165 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001166 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001167 mrs(rt, sysreg);
1168 }
1169 void Msr(SystemRegister sysreg, const Register& rt) {
armvixlb0c8ae22014-03-21 14:03:59 +00001170 VIXL_ASSERT(allow_macro_instructions_);
1171 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001172 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001173 msr(sysreg, rt);
1174 }
1175 void Msub(const Register& rd,
1176 const Register& rn,
1177 const Register& rm,
1178 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001179 VIXL_ASSERT(allow_macro_instructions_);
1180 VIXL_ASSERT(!rd.IsZero());
1181 VIXL_ASSERT(!rn.IsZero());
1182 VIXL_ASSERT(!rm.IsZero());
1183 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001184 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001185 msub(rd, rn, rm, ra);
1186 }
1187 void Mul(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001188 VIXL_ASSERT(allow_macro_instructions_);
1189 VIXL_ASSERT(!rd.IsZero());
1190 VIXL_ASSERT(!rn.IsZero());
1191 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001192 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001193 mul(rd, rn, rm);
1194 }
1195 void Nop() {
armvixlb0c8ae22014-03-21 14:03:59 +00001196 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001197 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001198 nop();
1199 }
1200 void Rbit(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001201 VIXL_ASSERT(allow_macro_instructions_);
1202 VIXL_ASSERT(!rd.IsZero());
1203 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001204 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001205 rbit(rd, rn);
1206 }
1207 void Ret(const Register& xn = lr) {
armvixlb0c8ae22014-03-21 14:03:59 +00001208 VIXL_ASSERT(allow_macro_instructions_);
1209 VIXL_ASSERT(!xn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001210 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001211 ret(xn);
1212 }
1213 void Rev(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001214 VIXL_ASSERT(allow_macro_instructions_);
1215 VIXL_ASSERT(!rd.IsZero());
1216 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001217 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001218 rev(rd, rn);
1219 }
1220 void Rev16(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001221 VIXL_ASSERT(allow_macro_instructions_);
1222 VIXL_ASSERT(!rd.IsZero());
1223 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001224 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001225 rev16(rd, rn);
1226 }
1227 void Rev32(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001228 VIXL_ASSERT(allow_macro_instructions_);
1229 VIXL_ASSERT(!rd.IsZero());
1230 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001231 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001232 rev32(rd, rn);
1233 }
1234 void Ror(const Register& rd, const Register& rs, unsigned shift) {
armvixlb0c8ae22014-03-21 14:03:59 +00001235 VIXL_ASSERT(allow_macro_instructions_);
1236 VIXL_ASSERT(!rd.IsZero());
1237 VIXL_ASSERT(!rs.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001238 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001239 ror(rd, rs, shift);
1240 }
1241 void Ror(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001242 VIXL_ASSERT(allow_macro_instructions_);
1243 VIXL_ASSERT(!rd.IsZero());
1244 VIXL_ASSERT(!rn.IsZero());
1245 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001246 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001247 rorv(rd, rn, rm);
1248 }
1249 void Sbfiz(const Register& rd,
1250 const Register& rn,
1251 unsigned lsb,
1252 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001253 VIXL_ASSERT(allow_macro_instructions_);
1254 VIXL_ASSERT(!rd.IsZero());
1255 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001256 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001257 sbfiz(rd, rn, lsb, width);
1258 }
1259 void Sbfx(const Register& rd,
1260 const Register& rn,
1261 unsigned lsb,
1262 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001263 VIXL_ASSERT(allow_macro_instructions_);
1264 VIXL_ASSERT(!rd.IsZero());
1265 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001266 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001267 sbfx(rd, rn, lsb, width);
1268 }
1269 void Scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
armvixlb0c8ae22014-03-21 14:03:59 +00001270 VIXL_ASSERT(allow_macro_instructions_);
1271 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001272 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001273 scvtf(fd, rn, fbits);
1274 }
1275 void Sdiv(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001276 VIXL_ASSERT(allow_macro_instructions_);
1277 VIXL_ASSERT(!rd.IsZero());
1278 VIXL_ASSERT(!rn.IsZero());
1279 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001280 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001281 sdiv(rd, rn, rm);
1282 }
1283 void Smaddl(const Register& rd,
1284 const Register& rn,
1285 const Register& rm,
1286 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001287 VIXL_ASSERT(allow_macro_instructions_);
1288 VIXL_ASSERT(!rd.IsZero());
1289 VIXL_ASSERT(!rn.IsZero());
1290 VIXL_ASSERT(!rm.IsZero());
1291 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001292 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001293 smaddl(rd, rn, rm, ra);
1294 }
1295 void Smsubl(const Register& rd,
1296 const Register& rn,
1297 const Register& rm,
1298 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001299 VIXL_ASSERT(allow_macro_instructions_);
1300 VIXL_ASSERT(!rd.IsZero());
1301 VIXL_ASSERT(!rn.IsZero());
1302 VIXL_ASSERT(!rm.IsZero());
1303 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001304 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001305 smsubl(rd, rn, rm, ra);
1306 }
1307 void Smull(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001308 VIXL_ASSERT(allow_macro_instructions_);
1309 VIXL_ASSERT(!rd.IsZero());
1310 VIXL_ASSERT(!rn.IsZero());
1311 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001312 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001313 smull(rd, rn, rm);
1314 }
1315 void Smulh(const Register& xd, const Register& xn, const Register& xm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001316 VIXL_ASSERT(allow_macro_instructions_);
1317 VIXL_ASSERT(!xd.IsZero());
1318 VIXL_ASSERT(!xn.IsZero());
1319 VIXL_ASSERT(!xm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001320 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001321 smulh(xd, xn, xm);
1322 }
armvixl4a102ba2014-07-14 09:02:40 +01001323 void Stlr(const Register& rt, const MemOperand& dst) {
1324 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001325 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001326 stlr(rt, dst);
1327 }
1328 void Stlrb(const Register& rt, const MemOperand& dst) {
1329 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001330 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001331 stlrb(rt, dst);
1332 }
1333 void Stlrh(const Register& rt, const MemOperand& dst) {
1334 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001335 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001336 stlrh(rt, dst);
1337 }
1338 void Stlxp(const Register& rs,
1339 const Register& rt,
1340 const Register& rt2,
1341 const MemOperand& dst) {
1342 VIXL_ASSERT(allow_macro_instructions_);
1343 VIXL_ASSERT(!rs.Aliases(dst.base()));
1344 VIXL_ASSERT(!rs.Aliases(rt));
1345 VIXL_ASSERT(!rs.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001346 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001347 stlxp(rs, rt, rt2, dst);
1348 }
1349 void Stlxr(const Register& rs, const Register& rt, const MemOperand& dst) {
1350 VIXL_ASSERT(allow_macro_instructions_);
1351 VIXL_ASSERT(!rs.Aliases(dst.base()));
1352 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001353 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001354 stlxr(rs, rt, dst);
1355 }
1356 void Stlxrb(const Register& rs, const Register& rt, const MemOperand& dst) {
1357 VIXL_ASSERT(allow_macro_instructions_);
1358 VIXL_ASSERT(!rs.Aliases(dst.base()));
1359 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001360 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001361 stlxrb(rs, rt, dst);
1362 }
1363 void Stlxrh(const Register& rs, const Register& rt, const MemOperand& dst) {
1364 VIXL_ASSERT(allow_macro_instructions_);
1365 VIXL_ASSERT(!rs.Aliases(dst.base()));
1366 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001367 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001368 stlxrh(rs, rt, dst);
1369 }
armvixlad96eda2013-06-14 11:42:37 +01001370 void Stnp(const CPURegister& rt,
1371 const CPURegister& rt2,
1372 const MemOperand& dst) {
armvixlb0c8ae22014-03-21 14:03:59 +00001373 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001374 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001375 stnp(rt, rt2, dst);
1376 }
armvixl4a102ba2014-07-14 09:02:40 +01001377 void Stxp(const Register& rs,
1378 const Register& rt,
1379 const Register& rt2,
1380 const MemOperand& dst) {
1381 VIXL_ASSERT(allow_macro_instructions_);
1382 VIXL_ASSERT(!rs.Aliases(dst.base()));
1383 VIXL_ASSERT(!rs.Aliases(rt));
1384 VIXL_ASSERT(!rs.Aliases(rt2));
armvixlc68cb642014-09-25 18:49:30 +01001385 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001386 stxp(rs, rt, rt2, dst);
1387 }
1388 void Stxr(const Register& rs, const Register& rt, const MemOperand& dst) {
1389 VIXL_ASSERT(allow_macro_instructions_);
1390 VIXL_ASSERT(!rs.Aliases(dst.base()));
1391 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001392 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001393 stxr(rs, rt, dst);
1394 }
1395 void Stxrb(const Register& rs, const Register& rt, const MemOperand& dst) {
1396 VIXL_ASSERT(allow_macro_instructions_);
1397 VIXL_ASSERT(!rs.Aliases(dst.base()));
1398 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001399 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001400 stxrb(rs, rt, dst);
1401 }
1402 void Stxrh(const Register& rs, const Register& rt, const MemOperand& dst) {
1403 VIXL_ASSERT(allow_macro_instructions_);
1404 VIXL_ASSERT(!rs.Aliases(dst.base()));
1405 VIXL_ASSERT(!rs.Aliases(rt));
armvixlc68cb642014-09-25 18:49:30 +01001406 SingleEmissionCheckScope guard(this);
armvixl4a102ba2014-07-14 09:02:40 +01001407 stxrh(rs, rt, dst);
1408 }
armvixlad96eda2013-06-14 11:42:37 +01001409 void Sxtb(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001410 VIXL_ASSERT(allow_macro_instructions_);
1411 VIXL_ASSERT(!rd.IsZero());
1412 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001413 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001414 sxtb(rd, rn);
1415 }
1416 void Sxth(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001417 VIXL_ASSERT(allow_macro_instructions_);
1418 VIXL_ASSERT(!rd.IsZero());
1419 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001420 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001421 sxth(rd, rn);
1422 }
1423 void Sxtw(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001424 VIXL_ASSERT(allow_macro_instructions_);
1425 VIXL_ASSERT(!rd.IsZero());
1426 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001427 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001428 sxtw(rd, rn);
1429 }
1430 void Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +00001431 VIXL_ASSERT(allow_macro_instructions_);
1432 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001433 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001434 tbnz(rt, bit_pos, label);
1435 }
1436 void Tbz(const Register& rt, unsigned bit_pos, Label* label) {
armvixlb0c8ae22014-03-21 14:03:59 +00001437 VIXL_ASSERT(allow_macro_instructions_);
1438 VIXL_ASSERT(!rt.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001439 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001440 tbz(rt, bit_pos, label);
1441 }
1442 void Ubfiz(const Register& rd,
1443 const Register& rn,
1444 unsigned lsb,
1445 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001446 VIXL_ASSERT(allow_macro_instructions_);
1447 VIXL_ASSERT(!rd.IsZero());
1448 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001449 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001450 ubfiz(rd, rn, lsb, width);
1451 }
1452 void Ubfx(const Register& rd,
1453 const Register& rn,
1454 unsigned lsb,
1455 unsigned width) {
armvixlb0c8ae22014-03-21 14:03:59 +00001456 VIXL_ASSERT(allow_macro_instructions_);
1457 VIXL_ASSERT(!rd.IsZero());
1458 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001459 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001460 ubfx(rd, rn, lsb, width);
1461 }
1462 void Ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
armvixlb0c8ae22014-03-21 14:03:59 +00001463 VIXL_ASSERT(allow_macro_instructions_);
1464 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001465 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001466 ucvtf(fd, rn, fbits);
1467 }
1468 void Udiv(const Register& rd, const Register& rn, const Register& rm) {
armvixlb0c8ae22014-03-21 14:03:59 +00001469 VIXL_ASSERT(allow_macro_instructions_);
1470 VIXL_ASSERT(!rd.IsZero());
1471 VIXL_ASSERT(!rn.IsZero());
1472 VIXL_ASSERT(!rm.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001473 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001474 udiv(rd, rn, rm);
1475 }
1476 void Umaddl(const Register& rd,
1477 const Register& rn,
1478 const Register& rm,
1479 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001480 VIXL_ASSERT(allow_macro_instructions_);
1481 VIXL_ASSERT(!rd.IsZero());
1482 VIXL_ASSERT(!rn.IsZero());
1483 VIXL_ASSERT(!rm.IsZero());
1484 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001485 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001486 umaddl(rd, rn, rm, ra);
1487 }
1488 void Umsubl(const Register& rd,
1489 const Register& rn,
1490 const Register& rm,
1491 const Register& ra) {
armvixlb0c8ae22014-03-21 14:03:59 +00001492 VIXL_ASSERT(allow_macro_instructions_);
1493 VIXL_ASSERT(!rd.IsZero());
1494 VIXL_ASSERT(!rn.IsZero());
1495 VIXL_ASSERT(!rm.IsZero());
1496 VIXL_ASSERT(!ra.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001497 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001498 umsubl(rd, rn, rm, ra);
1499 }
1500 void Unreachable() {
armvixlb0c8ae22014-03-21 14:03:59 +00001501 VIXL_ASSERT(allow_macro_instructions_);
armvixlc68cb642014-09-25 18:49:30 +01001502 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001503#ifdef USE_SIMULATOR
1504 hlt(kUnreachableOpcode);
1505#else
1506 // Branch to 0 to generate a segfault.
1507 // lr - kInstructionSize is the address of the offending instruction.
1508 blr(xzr);
1509#endif
1510 }
1511 void Uxtb(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001512 VIXL_ASSERT(allow_macro_instructions_);
1513 VIXL_ASSERT(!rd.IsZero());
1514 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001515 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001516 uxtb(rd, rn);
1517 }
1518 void Uxth(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001519 VIXL_ASSERT(allow_macro_instructions_);
1520 VIXL_ASSERT(!rd.IsZero());
1521 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001522 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001523 uxth(rd, rn);
1524 }
1525 void Uxtw(const Register& rd, const Register& rn) {
armvixlb0c8ae22014-03-21 14:03:59 +00001526 VIXL_ASSERT(allow_macro_instructions_);
1527 VIXL_ASSERT(!rd.IsZero());
1528 VIXL_ASSERT(!rn.IsZero());
armvixlc68cb642014-09-25 18:49:30 +01001529 SingleEmissionCheckScope guard(this);
armvixlad96eda2013-06-14 11:42:37 +01001530 uxtw(rd, rn);
1531 }
1532
1533 // Push the system stack pointer (sp) down to allow the same to be done to
1534 // the current stack pointer (according to StackPointer()). This must be
1535 // called _before_ accessing the memory.
1536 //
1537 // This is necessary when pushing or otherwise adding things to the stack, to
1538 // satisfy the AAPCS64 constraint that the memory below the system stack
1539 // pointer is not accessed.
1540 //
1541 // This method asserts that StackPointer() is not sp, since the call does
1542 // not make sense in that context.
1543 //
1544 // TODO: This method can only accept values of 'space' that can be encoded in
1545 // one instruction. Refer to the implementation for details.
1546 void BumpSystemStackPointer(const Operand& space);
1547
1548#if DEBUG
1549 void SetAllowMacroInstructions(bool value) {
1550 allow_macro_instructions_ = value;
1551 }
1552
1553 bool AllowMacroInstructions() const {
1554 return allow_macro_instructions_;
1555 }
1556#endif
1557
armvixlc68cb642014-09-25 18:49:30 +01001558 void BlockLiteralPool() { literal_pool_.Block(); }
1559 void ReleaseLiteralPool() { literal_pool_.Release(); }
1560 bool IsLiteralPoolBlocked() const { return literal_pool_.IsBlocked(); }
1561
1562 size_t LiteralPoolSize() const {
1563 if (literal_pool_.IsEmpty()) return 0;
1564 return literal_pool_.Size() - kInstructionSize;
1565 }
1566
1567 void EmitLiteralPool(LiteralPool::EmitOption option) {
1568 if (!literal_pool_.IsEmpty()) literal_pool_.Emit(option);
1569
1570 checkpoint_ = NextCheckOffset();
1571 }
1572
1573 ptrdiff_t NextCheckOffset() {
1574 return std::min(literal_pool_.NextCheckOffset(), BufferEndOffset());
1575 }
1576
1577 void EnsureEmitFor(size_t amount) {
1578 ptrdiff_t offset = amount;
1579 if ((CursorOffset() + offset) > checkpoint_) {
1580 // Check if a pool need to be emitted.
1581 literal_pool_.CheckEmitFor(amount);
1582 // Ensure there's enough space for the emit, keep in mind the cursor will
1583 // have moved if a pool was emitted.
1584 if ((CursorOffset() + offset) > BufferEndOffset()) {
1585 EnsureSpaceFor(amount);
1586 }
1587
1588 checkpoint_ = NextCheckOffset();
1589 }
1590 }
1591
armvixlad96eda2013-06-14 11:42:37 +01001592 // Set the current stack pointer, but don't generate any code.
armvixlad96eda2013-06-14 11:42:37 +01001593 void SetStackPointer(const Register& stack_pointer) {
armvixlb0c8ae22014-03-21 14:03:59 +00001594 VIXL_ASSERT(!TmpList()->IncludesAliasOf(stack_pointer));
armvixlad96eda2013-06-14 11:42:37 +01001595 sp_ = stack_pointer;
1596 }
1597
1598 // Return the current stack pointer, as set by SetStackPointer.
1599 const Register& StackPointer() const {
1600 return sp_;
1601 }
1602
armvixlb0c8ae22014-03-21 14:03:59 +00001603 CPURegList* TmpList() { return &tmp_list_; }
1604 CPURegList* FPTmpList() { return &fptmp_list_; }
armvixlad96eda2013-06-14 11:42:37 +01001605
1606 // Like printf, but print at run-time from generated code.
1607 //
1608 // The caller must ensure that arguments for floating-point placeholders
1609 // (such as %e, %f or %g) are FPRegisters, and that arguments for integer
1610 // placeholders are Registers.
1611 //
armvixl5799d6c2014-05-01 11:05:00 +01001612 // At the moment it is only possible to print the value of sp if it is the
1613 // current stack pointer. Otherwise, the MacroAssembler will automatically
1614 // update sp on every push (using BumpSystemStackPointer), so determining its
1615 // value is difficult.
armvixlad96eda2013-06-14 11:42:37 +01001616 //
armvixl5799d6c2014-05-01 11:05:00 +01001617 // Format placeholders that refer to more than one argument, or to a specific
1618 // argument, are not supported. This includes formats like "%1$d" or "%.*d".
armvixlad96eda2013-06-14 11:42:37 +01001619 //
1620 // This function automatically preserves caller-saved registers so that
1621 // calling code can use Printf at any point without having to worry about
1622 // corruption. The preservation mechanism generates a lot of code. If this is
1623 // a problem, preserve the important registers manually and then call
1624 // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are
1625 // implicitly preserved.
armvixlad96eda2013-06-14 11:42:37 +01001626 void Printf(const char * format,
armvixl5799d6c2014-05-01 11:05:00 +01001627 CPURegister arg0 = NoCPUReg,
1628 CPURegister arg1 = NoCPUReg,
1629 CPURegister arg2 = NoCPUReg,
1630 CPURegister arg3 = NoCPUReg);
armvixlad96eda2013-06-14 11:42:37 +01001631
1632 // Like Printf, but don't preserve any caller-saved registers, not even 'lr'.
1633 //
1634 // The return code from the system printf call will be returned in x0.
1635 void PrintfNoPreserve(const char * format,
1636 const CPURegister& arg0 = NoCPUReg,
1637 const CPURegister& arg1 = NoCPUReg,
1638 const CPURegister& arg2 = NoCPUReg,
1639 const CPURegister& arg3 = NoCPUReg);
1640
1641 // Trace control when running the debug simulator.
1642 //
1643 // For example:
1644 //
1645 // __ Trace(LOG_REGS, TRACE_ENABLE);
1646 // Will add registers to the trace if it wasn't already the case.
1647 //
1648 // __ Trace(LOG_DISASM, TRACE_DISABLE);
1649 // Will stop logging disassembly. It has no effect if the disassembly wasn't
1650 // already being logged.
1651 void Trace(TraceParameters parameters, TraceCommand command);
1652
1653 // Log the requested data independently of what is being traced.
1654 //
1655 // For example:
1656 //
1657 // __ Log(LOG_FLAGS)
1658 // Will output the flags.
armvixl578645f2013-08-15 17:21:42 +01001659 void Log(TraceParameters parameters);
1660
1661 // Enable or disable instrumentation when an Instrument visitor is attached to
1662 // the simulator.
1663 void EnableInstrumentation();
1664 void DisableInstrumentation();
1665
1666 // Add a marker to the instrumentation data produced by an Instrument visitor.
1667 // The name is a two character string that will be attached to the marker in
1668 // the output data.
1669 void AnnotateInstrumentation(const char* marker_name);
armvixlad96eda2013-06-14 11:42:37 +01001670
1671 private:
1672 // The actual Push and Pop implementations. These don't generate any code
1673 // other than that required for the push or pop. This allows
1674 // (Push|Pop)CPURegList to bundle together setup code for a large block of
1675 // registers.
1676 //
1677 // Note that size is per register, and is specified in bytes.
1678 void PushHelper(int count, int size,
1679 const CPURegister& src0, const CPURegister& src1,
1680 const CPURegister& src2, const CPURegister& src3);
1681 void PopHelper(int count, int size,
1682 const CPURegister& dst0, const CPURegister& dst1,
1683 const CPURegister& dst2, const CPURegister& dst3);
1684
1685 // Perform necessary maintenance operations before a push or pop.
1686 //
1687 // Note that size is per register, and is specified in bytes.
1688 void PrepareForPush(int count, int size);
1689 void PrepareForPop(int count, int size);
1690
1691#if DEBUG
1692 // Tell whether any of the macro instruction can be used. When false the
1693 // MacroAssembler will assert if a method which can emit a variable number
1694 // of instructions is called.
1695 bool allow_macro_instructions_;
1696#endif
1697
1698 // The register to use as a stack pointer for stack operations.
1699 Register sp_;
1700
armvixlb0c8ae22014-03-21 14:03:59 +00001701 // Scratch registers available for use by the MacroAssembler.
1702 CPURegList tmp_list_;
1703 CPURegList fptmp_list_;
armvixlc68cb642014-09-25 18:49:30 +01001704
1705 LiteralPool literal_pool_;
1706 ptrdiff_t checkpoint_;
armvixlad96eda2013-06-14 11:42:37 +01001707};
1708
1709
1710// Use this scope when you need a one-to-one mapping between methods and
1711// instructions. This scope prevents the MacroAssembler from being called and
1712// literal pools from being emitted. It also asserts the number of instructions
1713// emitted is what you specified when creating the scope.
armvixlc68cb642014-09-25 18:49:30 +01001714class InstructionAccurateScope : public CodeBufferCheckScope {
armvixlad96eda2013-06-14 11:42:37 +01001715 public:
armvixlc68cb642014-09-25 18:49:30 +01001716 InstructionAccurateScope(MacroAssembler* masm,
1717 int count,
1718 AssertPolicy policy = kExactSize)
1719 : CodeBufferCheckScope(masm,
1720 (count * kInstructionSize),
1721 kCheck,
1722 policy) {
1723 VIXL_ASSERT(policy != kNoAssert);
armvixlad96eda2013-06-14 11:42:37 +01001724#ifdef DEBUG
armvixlc68cb642014-09-25 18:49:30 +01001725 old_allow_macro_instructions_ = masm->AllowMacroInstructions();
1726 masm->SetAllowMacroInstructions(false);
armvixl4a102ba2014-07-14 09:02:40 +01001727#endif
armvixlc68cb642014-09-25 18:49:30 +01001728 }
armvixlad96eda2013-06-14 11:42:37 +01001729
1730 ~InstructionAccurateScope() {
armvixlad96eda2013-06-14 11:42:37 +01001731#ifdef DEBUG
armvixlc68cb642014-09-25 18:49:30 +01001732 MacroAssembler* masm = reinterpret_cast<MacroAssembler*>(assm_);
1733 masm->SetAllowMacroInstructions(old_allow_macro_instructions_);
armvixlad96eda2013-06-14 11:42:37 +01001734#endif
1735 }
1736
1737 private:
armvixlad96eda2013-06-14 11:42:37 +01001738#ifdef DEBUG
armvixlad96eda2013-06-14 11:42:37 +01001739 bool old_allow_macro_instructions_;
1740#endif
1741};
1742
1743
armvixlc68cb642014-09-25 18:49:30 +01001744class BlockLiteralPoolScope {
1745 public:
1746 explicit BlockLiteralPoolScope(MacroAssembler* masm) : masm_(masm) {
1747 masm_->BlockLiteralPool();
1748 }
1749
1750 ~BlockLiteralPoolScope() {
1751 masm_->ReleaseLiteralPool();
1752 }
1753
1754 private:
1755 MacroAssembler* masm_;
1756};
1757
1758
armvixlb0c8ae22014-03-21 14:03:59 +00001759// This scope utility allows scratch registers to be managed safely. The
1760// MacroAssembler's TmpList() (and FPTmpList()) is used as a pool of scratch
1761// registers. These registers can be allocated on demand, and will be returned
1762// at the end of the scope.
1763//
1764// When the scope ends, the MacroAssembler's lists will be restored to their
1765// original state, even if the lists were modified by some other means.
1766class UseScratchRegisterScope {
1767 public:
1768 explicit UseScratchRegisterScope(MacroAssembler* masm)
1769 : available_(masm->TmpList()),
1770 availablefp_(masm->FPTmpList()),
1771 old_available_(available_->list()),
1772 old_availablefp_(availablefp_->list()) {
1773 VIXL_ASSERT(available_->type() == CPURegister::kRegister);
1774 VIXL_ASSERT(availablefp_->type() == CPURegister::kFPRegister);
1775 }
1776
1777
1778 ~UseScratchRegisterScope();
1779
1780
armvixl5799d6c2014-05-01 11:05:00 +01001781 bool IsAvailable(const CPURegister& reg) const;
1782
1783
armvixlb0c8ae22014-03-21 14:03:59 +00001784 // Take a register from the appropriate temps list. It will be returned
1785 // automatically when the scope ends.
1786 Register AcquireW() { return AcquireNextAvailable(available_).W(); }
1787 Register AcquireX() { return AcquireNextAvailable(available_).X(); }
1788 FPRegister AcquireS() { return AcquireNextAvailable(availablefp_).S(); }
1789 FPRegister AcquireD() { return AcquireNextAvailable(availablefp_).D(); }
1790
1791
1792 Register AcquireSameSizeAs(const Register& reg);
1793 FPRegister AcquireSameSizeAs(const FPRegister& reg);
1794
1795
1796 // Explicitly release an acquired (or excluded) register, putting it back in
1797 // the appropriate temps list.
1798 void Release(const CPURegister& reg);
1799
1800
1801 // Make the specified registers available as scratch registers for the
1802 // duration of this scope.
armvixl5799d6c2014-05-01 11:05:00 +01001803 void Include(const CPURegList& list);
armvixlb0c8ae22014-03-21 14:03:59 +00001804 void Include(const Register& reg1,
1805 const Register& reg2 = NoReg,
1806 const Register& reg3 = NoReg,
1807 const Register& reg4 = NoReg);
1808 void Include(const FPRegister& reg1,
1809 const FPRegister& reg2 = NoFPReg,
1810 const FPRegister& reg3 = NoFPReg,
1811 const FPRegister& reg4 = NoFPReg);
1812
1813
1814 // Make sure that the specified registers are not available in this scope.
1815 // This can be used to prevent helper functions from using sensitive
1816 // registers, for example.
armvixl5799d6c2014-05-01 11:05:00 +01001817 void Exclude(const CPURegList& list);
armvixlb0c8ae22014-03-21 14:03:59 +00001818 void Exclude(const Register& reg1,
1819 const Register& reg2 = NoReg,
1820 const Register& reg3 = NoReg,
1821 const Register& reg4 = NoReg);
1822 void Exclude(const FPRegister& reg1,
1823 const FPRegister& reg2 = NoFPReg,
1824 const FPRegister& reg3 = NoFPReg,
1825 const FPRegister& reg4 = NoFPReg);
1826 void Exclude(const CPURegister& reg1,
1827 const CPURegister& reg2 = NoCPUReg,
1828 const CPURegister& reg3 = NoCPUReg,
1829 const CPURegister& reg4 = NoCPUReg);
1830
1831
1832 // Prevent any scratch registers from being used in this scope.
1833 void ExcludeAll();
1834
1835
1836 private:
1837 static CPURegister AcquireNextAvailable(CPURegList* available);
1838
1839 static void ReleaseByCode(CPURegList* available, int code);
1840
1841 static void ReleaseByRegList(CPURegList* available,
1842 RegList regs);
1843
1844 static void IncludeByRegList(CPURegList* available,
1845 RegList exclude);
1846
1847 static void ExcludeByRegList(CPURegList* available,
1848 RegList exclude);
1849
1850 // Available scratch registers.
1851 CPURegList* available_; // kRegister
1852 CPURegList* availablefp_; // kFPRegister
1853
1854 // The state of the available lists at the start of this scope.
1855 RegList old_available_; // kRegister
1856 RegList old_availablefp_; // kFPRegister
1857};
1858
1859
armvixlad96eda2013-06-14 11:42:37 +01001860} // namespace vixl
1861
1862#endif // VIXL_A64_MACRO_ASSEMBLER_A64_H_