blob: f2660637794cd2217e3806e304b40c463cd99b32 [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
30#include "globals.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
46namespace vixl {
47
48class MacroAssembler : public Assembler {
49 public:
50 MacroAssembler(byte * buffer, unsigned buffer_size)
51 : Assembler(buffer, buffer_size),
52#ifdef DEBUG
53 allow_macro_instructions_(true),
54#endif
55 sp_(sp), tmp0_(ip0), tmp1_(ip1), fptmp0_(d31) {}
56
57 // Logical macros.
58 void And(const Register& rd,
59 const Register& rn,
60 const Operand& operand,
61 FlagsUpdate S = LeaveFlags);
62 void Bic(const Register& rd,
63 const Register& rn,
64 const Operand& operand,
65 FlagsUpdate S = LeaveFlags);
66 void Orr(const Register& rd,
67 const Register& rn,
68 const Operand& operand);
69 void Orn(const Register& rd,
70 const Register& rn,
71 const Operand& operand);
72 void Eor(const Register& rd,
73 const Register& rn,
74 const Operand& operand);
75 void Eon(const Register& rd,
76 const Register& rn,
77 const Operand& operand);
78 void Tst(const Register& rn, const Operand& operand);
79 void LogicalMacro(const Register& rd,
80 const Register& rn,
81 const Operand& operand,
82 LogicalOp op);
83
84 // Add and sub macros.
85 void Add(const Register& rd,
86 const Register& rn,
87 const Operand& operand,
88 FlagsUpdate S = LeaveFlags);
89 void Sub(const Register& rd,
90 const Register& rn,
91 const Operand& operand,
92 FlagsUpdate S = LeaveFlags);
93 void Cmn(const Register& rn, const Operand& operand);
94 void Cmp(const Register& rn, const Operand& operand);
95 void Neg(const Register& rd,
96 const Operand& operand,
97 FlagsUpdate S = LeaveFlags);
98 void AddSubMacro(const Register& rd,
99 const Register& rn,
100 const Operand& operand,
101 FlagsUpdate S,
102 AddSubOp op);
103
104 // Add/sub with carry macros.
105 void Adc(const Register& rd,
106 const Register& rn,
107 const Operand& operand,
108 FlagsUpdate S = LeaveFlags);
109 void Sbc(const Register& rd,
110 const Register& rn,
111 const Operand& operand,
112 FlagsUpdate S = LeaveFlags);
113 void Ngc(const Register& rd,
114 const Operand& operand,
115 FlagsUpdate S = LeaveFlags);
116 void AddSubWithCarryMacro(const Register& rd,
117 const Register& rn,
118 const Operand& operand,
119 FlagsUpdate S,
120 AddSubWithCarryOp op);
121
122 // Move macros.
123 void Mov(const Register& rd, uint64_t imm);
124 void Mov(const Register& rd, const Operand& operand);
125 void Mvn(const Register& rd, uint64_t imm) {
126 Mov(rd, ~imm);
127 };
128 void Mvn(const Register& rd, const Operand& operand);
129 bool IsImmMovn(uint64_t imm, unsigned reg_size);
130 bool IsImmMovz(uint64_t imm, unsigned reg_size);
131
132 // Conditional compare macros.
133 void Ccmp(const Register& rn,
134 const Operand& operand,
135 StatusFlags nzcv,
136 Condition cond);
137 void Ccmn(const Register& rn,
138 const Operand& operand,
139 StatusFlags nzcv,
140 Condition cond);
141 void ConditionalCompareMacro(const Register& rn,
142 const Operand& operand,
143 StatusFlags nzcv,
144 Condition cond,
145 ConditionalCompareOp op);
146
147 // Load/store macros.
148#define DECLARE_FUNCTION(FN, REGTYPE, REG, OP) \
149 void FN(const REGTYPE REG, const MemOperand& addr);
150 LS_MACRO_LIST(DECLARE_FUNCTION)
151#undef DECLARE_FUNCTION
152
153 void LoadStoreMacro(const CPURegister& rt,
154 const MemOperand& addr,
155 LoadStoreOp op);
156
157 // Push or pop up to 4 registers of the same width to or from the stack,
158 // using the current stack pointer as set by SetStackPointer.
159 //
160 // If an argument register is 'NoReg', all further arguments are also assumed
161 // to be 'NoReg', and are thus not pushed or popped.
162 //
163 // Arguments are ordered such that "Push(a, b);" is functionally equivalent
164 // to "Push(a); Push(b);".
165 //
166 // It is valid to push the same register more than once, and there is no
167 // restriction on the order in which registers are specified.
168 //
169 // It is not valid to pop into the same register more than once in one
170 // operation, not even into the zero register.
171 //
172 // If the current stack pointer (as set by SetStackPointer) is sp, then it
173 // must be aligned to 16 bytes on entry and the total size of the specified
174 // registers must also be a multiple of 16 bytes.
175 //
176 // Even if the current stack pointer is not the system stack pointer (sp),
177 // Push (and derived methods) will still modify the system stack pointer in
178 // order to comply with ABI rules about accessing memory below the system
179 // stack pointer.
180 //
181 // Other than the registers passed into Pop, the stack pointer and (possibly)
182 // the system stack pointer, these methods do not modify any other registers.
183 // Scratch registers such as Tmp0() and Tmp1() are preserved.
184 void Push(const CPURegister& src0, const CPURegister& src1 = NoReg,
185 const CPURegister& src2 = NoReg, const CPURegister& src3 = NoReg);
186 void Pop(const CPURegister& dst0, const CPURegister& dst1 = NoReg,
187 const CPURegister& dst2 = NoReg, const CPURegister& dst3 = NoReg);
188
189 // Alternative forms of Push and Pop, taking a RegList or CPURegList that
190 // specifies the registers that are to be pushed or popped. Higher-numbered
191 // registers are associated with higher memory addresses (as in the A32 push
192 // and pop instructions).
193 //
194 // (Push|Pop)SizeRegList allow you to specify the register size as a
195 // parameter. Only kXRegSize, kWRegSize, kDRegSize and kSRegSize are
196 // supported.
197 //
198 // Otherwise, (Push|Pop)(CPU|X|W|D|S)RegList is preferred.
199 void PushCPURegList(CPURegList registers);
200 void PopCPURegList(CPURegList registers);
201
202 void PushSizeRegList(RegList registers, unsigned reg_size,
203 CPURegister::RegisterType type = CPURegister::kRegister) {
204 PushCPURegList(CPURegList(type, reg_size, registers));
205 }
206 void PopSizeRegList(RegList registers, unsigned reg_size,
207 CPURegister::RegisterType type = CPURegister::kRegister) {
208 PopCPURegList(CPURegList(type, reg_size, registers));
209 }
210 void PushXRegList(RegList regs) {
211 PushSizeRegList(regs, kXRegSize);
212 }
213 void PopXRegList(RegList regs) {
214 PopSizeRegList(regs, kXRegSize);
215 }
216 void PushWRegList(RegList regs) {
217 PushSizeRegList(regs, kWRegSize);
218 }
219 void PopWRegList(RegList regs) {
220 PopSizeRegList(regs, kWRegSize);
221 }
222 inline void PushDRegList(RegList regs) {
223 PushSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
224 }
225 inline void PopDRegList(RegList regs) {
226 PopSizeRegList(regs, kDRegSize, CPURegister::kFPRegister);
227 }
228 inline void PushSRegList(RegList regs) {
229 PushSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
230 }
231 inline void PopSRegList(RegList regs) {
232 PopSizeRegList(regs, kSRegSize, CPURegister::kFPRegister);
233 }
234
235 // Push the specified register 'count' times.
236 void PushMultipleTimes(int count, Register src);
237
238 // Poke 'src' onto the stack. The offset is in bytes.
239 //
240 // If the current stack pointer (as set by SetStackPointer) is sp, then sp
241 // must be aligned to 16 bytes.
242 void Poke(const Register& src, const Operand& offset);
243
244 // Peek at a value on the stack, and put it in 'dst'. The offset is in bytes.
245 //
246 // If the current stack pointer (as set by SetStackPointer) is sp, then sp
247 // must be aligned to 16 bytes.
248 void Peek(const Register& dst, const Operand& offset);
249
250 // Claim or drop stack space without actually accessing memory.
251 //
252 // If the current stack pointer (as set by SetStackPointer) is sp, then it
253 // must be aligned to 16 bytes and the size claimed or dropped must be a
254 // multiple of 16 bytes.
255 void Claim(const Operand& size);
256 void Drop(const Operand& size);
257
258 // Preserve the callee-saved registers (as defined by AAPCS64).
259 //
260 // Higher-numbered registers are pushed before lower-numbered registers, and
261 // thus get higher addresses.
262 // Floating-point registers are pushed before general-purpose registers, and
263 // thus get higher addresses.
264 //
265 // This method must not be called unless StackPointer() is sp, and it is
266 // aligned to 16 bytes.
267 void PushCalleeSavedRegisters();
268
269 // Restore the callee-saved registers (as defined by AAPCS64).
270 //
271 // Higher-numbered registers are popped after lower-numbered registers, and
272 // thus come from higher addresses.
273 // Floating-point registers are popped after general-purpose registers, and
274 // thus come from higher addresses.
275 //
276 // This method must not be called unless StackPointer() is sp, and it is
277 // aligned to 16 bytes.
278 void PopCalleeSavedRegisters();
279
280 // Remaining instructions are simple pass-through calls to the assembler.
281 void Adr(const Register& rd, Label* label) {
282 ASSERT(allow_macro_instructions_);
283 ASSERT(!rd.IsZero());
284 adr(rd, label);
285 }
286 void Asr(const Register& rd, const Register& rn, unsigned shift) {
287 ASSERT(allow_macro_instructions_);
288 ASSERT(!rd.IsZero());
289 ASSERT(!rn.IsZero());
290 asr(rd, rn, shift);
291 }
292 void Asr(const Register& rd, const Register& rn, const Register& rm) {
293 ASSERT(allow_macro_instructions_);
294 ASSERT(!rd.IsZero());
295 ASSERT(!rn.IsZero());
296 ASSERT(!rm.IsZero());
297 asrv(rd, rn, rm);
298 }
armvixl578645f2013-08-15 17:21:42 +0100299 void B(Label* label) {
300 b(label);
301 }
302 void B(Label* label, Condition cond) {
armvixlad96eda2013-06-14 11:42:37 +0100303 ASSERT(allow_macro_instructions_);
armvixl578645f2013-08-15 17:21:42 +0100304 ASSERT((cond != al) && (cond != nv));
armvixlad96eda2013-06-14 11:42:37 +0100305 b(label, cond);
306 }
307 void Bfi(const Register& rd,
308 const Register& rn,
309 unsigned lsb,
310 unsigned width) {
311 ASSERT(allow_macro_instructions_);
312 ASSERT(!rd.IsZero());
313 ASSERT(!rn.IsZero());
314 bfi(rd, rn, lsb, width);
315 }
316 void Bfxil(const Register& rd,
317 const Register& rn,
318 unsigned lsb,
319 unsigned width) {
320 ASSERT(allow_macro_instructions_);
321 ASSERT(!rd.IsZero());
322 ASSERT(!rn.IsZero());
323 bfxil(rd, rn, lsb, width);
324 }
325 void Bind(Label* label) {
326 ASSERT(allow_macro_instructions_);
327 bind(label);
328 }
329 void Bl(Label* label) {
330 ASSERT(allow_macro_instructions_);
331 bl(label);
332 }
333 void Blr(const Register& xn) {
334 ASSERT(allow_macro_instructions_);
335 ASSERT(!xn.IsZero());
336 blr(xn);
337 }
338 void Br(const Register& xn) {
339 ASSERT(allow_macro_instructions_);
340 ASSERT(!xn.IsZero());
341 br(xn);
342 }
343 void Brk(int code = 0) {
344 ASSERT(allow_macro_instructions_);
345 brk(code);
346 }
347 void Cbnz(const Register& rt, Label* label) {
348 ASSERT(allow_macro_instructions_);
349 ASSERT(!rt.IsZero());
350 cbnz(rt, label);
351 }
352 void Cbz(const Register& rt, Label* label) {
353 ASSERT(allow_macro_instructions_);
354 ASSERT(!rt.IsZero());
355 cbz(rt, label);
356 }
357 void Cinc(const Register& rd, const Register& rn, Condition cond) {
358 ASSERT(allow_macro_instructions_);
359 ASSERT(!rd.IsZero());
360 ASSERT(!rn.IsZero());
361 cinc(rd, rn, cond);
362 }
363 void Cinv(const Register& rd, const Register& rn, Condition cond) {
364 ASSERT(allow_macro_instructions_);
365 ASSERT(!rd.IsZero());
366 ASSERT(!rn.IsZero());
367 cinv(rd, rn, cond);
368 }
369 void Cls(const Register& rd, const Register& rn) {
370 ASSERT(allow_macro_instructions_);
371 ASSERT(!rd.IsZero());
372 ASSERT(!rn.IsZero());
373 cls(rd, rn);
374 }
375 void Clz(const Register& rd, const Register& rn) {
376 ASSERT(allow_macro_instructions_);
377 ASSERT(!rd.IsZero());
378 ASSERT(!rn.IsZero());
379 clz(rd, rn);
380 }
381 void Cneg(const Register& rd, const Register& rn, Condition cond) {
382 ASSERT(allow_macro_instructions_);
383 ASSERT(!rd.IsZero());
384 ASSERT(!rn.IsZero());
385 cneg(rd, rn, cond);
386 }
387 void Csel(const Register& rd,
388 const Register& rn,
389 const Register& rm,
390 Condition cond) {
391 ASSERT(allow_macro_instructions_);
392 ASSERT(!rd.IsZero());
393 ASSERT(!rn.IsZero());
394 ASSERT(!rm.IsZero());
armvixl578645f2013-08-15 17:21:42 +0100395 ASSERT((cond != al) && (cond != nv));
armvixlad96eda2013-06-14 11:42:37 +0100396 csel(rd, rn, rm, cond);
397 }
398 void Cset(const Register& rd, Condition cond) {
399 ASSERT(allow_macro_instructions_);
400 ASSERT(!rd.IsZero());
401 cset(rd, cond);
402 }
403 void Csetm(const Register& rd, Condition cond) {
404 ASSERT(allow_macro_instructions_);
405 ASSERT(!rd.IsZero());
406 csetm(rd, cond);
407 }
408 void Csinc(const Register& rd,
409 const Register& rn,
410 const Register& rm,
411 Condition cond) {
412 ASSERT(allow_macro_instructions_);
413 ASSERT(!rd.IsZero());
414 ASSERT(!rn.IsZero());
415 ASSERT(!rm.IsZero());
armvixl578645f2013-08-15 17:21:42 +0100416 ASSERT((cond != al) && (cond != nv));
armvixlad96eda2013-06-14 11:42:37 +0100417 csinc(rd, rn, rm, cond);
418 }
419 void Csinv(const Register& rd,
420 const Register& rn,
421 const Register& rm,
422 Condition cond) {
423 ASSERT(allow_macro_instructions_);
424 ASSERT(!rd.IsZero());
425 ASSERT(!rn.IsZero());
426 ASSERT(!rm.IsZero());
armvixl578645f2013-08-15 17:21:42 +0100427 ASSERT((cond != al) && (cond != nv));
armvixlad96eda2013-06-14 11:42:37 +0100428 csinv(rd, rn, rm, cond);
429 }
430 void Csneg(const Register& rd,
431 const Register& rn,
432 const Register& rm,
433 Condition cond) {
434 ASSERT(allow_macro_instructions_);
435 ASSERT(!rd.IsZero());
436 ASSERT(!rn.IsZero());
437 ASSERT(!rm.IsZero());
armvixl578645f2013-08-15 17:21:42 +0100438 ASSERT((cond != al) && (cond != nv));
armvixlad96eda2013-06-14 11:42:37 +0100439 csneg(rd, rn, rm, cond);
440 }
441 void Extr(const Register& rd,
442 const Register& rn,
443 const Register& rm,
444 unsigned lsb) {
445 ASSERT(allow_macro_instructions_);
446 ASSERT(!rd.IsZero());
447 ASSERT(!rn.IsZero());
448 ASSERT(!rm.IsZero());
449 extr(rd, rn, rm, lsb);
450 }
451 void Fabs(const FPRegister& fd, const FPRegister& fn) {
452 ASSERT(allow_macro_instructions_);
453 fabs(fd, fn);
454 }
455 void Fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
456 ASSERT(allow_macro_instructions_);
457 fadd(fd, fn, fm);
458 }
459 void Fccmp(const FPRegister& fn,
460 const FPRegister& fm,
461 StatusFlags nzcv,
462 Condition cond) {
463 ASSERT(allow_macro_instructions_);
armvixl578645f2013-08-15 17:21:42 +0100464 ASSERT((cond != al) && (cond != nv));
armvixlad96eda2013-06-14 11:42:37 +0100465 fccmp(fn, fm, nzcv, cond);
466 }
467 void Fcmp(const FPRegister& fn, const FPRegister& fm) {
468 ASSERT(allow_macro_instructions_);
469 fcmp(fn, fm);
470 }
471 void Fcmp(const FPRegister& fn, double value) {
472 ASSERT(allow_macro_instructions_);
473 if (value != 0.0) {
474 FPRegister tmp = AppropriateTempFor(fn);
475 Fmov(tmp, value);
476 fcmp(fn, tmp);
477 } else {
478 fcmp(fn, value);
479 }
480 }
481 void Fcsel(const FPRegister& fd,
482 const FPRegister& fn,
483 const FPRegister& fm,
484 Condition cond) {
485 ASSERT(allow_macro_instructions_);
armvixl578645f2013-08-15 17:21:42 +0100486 ASSERT((cond != al) && (cond != nv));
armvixlad96eda2013-06-14 11:42:37 +0100487 fcsel(fd, fn, fm, cond);
488 }
armvixl578645f2013-08-15 17:21:42 +0100489 void Fcvt(const FPRegister& fd, const FPRegister& fn) {
490 ASSERT(allow_macro_instructions_);
491 fcvt(fd, fn);
492 }
armvixlad96eda2013-06-14 11:42:37 +0100493 void Fcvtms(const Register& rd, const FPRegister& fn) {
494 ASSERT(allow_macro_instructions_);
495 ASSERT(!rd.IsZero());
496 fcvtms(rd, fn);
497 }
498 void Fcvtmu(const Register& rd, const FPRegister& fn) {
499 ASSERT(allow_macro_instructions_);
500 ASSERT(!rd.IsZero());
501 fcvtmu(rd, fn);
502 }
503 void Fcvtns(const Register& rd, const FPRegister& fn) {
504 ASSERT(allow_macro_instructions_);
505 ASSERT(!rd.IsZero());
506 fcvtns(rd, fn);
507 }
508 void Fcvtnu(const Register& rd, const FPRegister& fn) {
509 ASSERT(allow_macro_instructions_);
510 ASSERT(!rd.IsZero());
511 fcvtnu(rd, fn);
512 }
513 void Fcvtzs(const Register& rd, const FPRegister& fn) {
514 ASSERT(allow_macro_instructions_);
515 ASSERT(!rd.IsZero());
516 fcvtzs(rd, fn);
517 }
518 void Fcvtzu(const Register& rd, const FPRegister& fn) {
519 ASSERT(allow_macro_instructions_);
520 ASSERT(!rd.IsZero());
521 fcvtzu(rd, fn);
522 }
523 void Fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
524 ASSERT(allow_macro_instructions_);
525 fdiv(fd, fn, fm);
526 }
527 void Fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
528 ASSERT(allow_macro_instructions_);
529 fmax(fd, fn, fm);
530 }
531 void Fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
532 ASSERT(allow_macro_instructions_);
533 fmin(fd, fn, fm);
534 }
535 void Fmov(FPRegister fd, FPRegister fn) {
536 ASSERT(allow_macro_instructions_);
537 // Only emit an instruction if fd and fn are different, and they are both D
538 // registers. fmov(s0, s0) is not a no-op because it clears the top word of
539 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears
540 // the top of q0, but FPRegister does not currently support Q registers.
541 if (!fd.Is(fn) || !fd.Is64Bits()) {
542 fmov(fd, fn);
543 }
544 }
545 void Fmov(FPRegister fd, Register rn) {
546 ASSERT(allow_macro_instructions_);
547 ASSERT(!rn.IsZero());
548 fmov(fd, rn);
549 }
550 void Fmov(FPRegister fd, double imm) {
551 ASSERT(allow_macro_instructions_);
552 fmov(fd, imm);
553 }
554 void Fmov(Register rd, FPRegister fn) {
555 ASSERT(allow_macro_instructions_);
556 ASSERT(!rd.IsZero());
557 fmov(rd, fn);
558 }
559 void Fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
560 ASSERT(allow_macro_instructions_);
561 fmul(fd, fn, fm);
562 }
563 void Fmsub(const FPRegister& fd,
564 const FPRegister& fn,
565 const FPRegister& fm,
566 const FPRegister& fa) {
567 ASSERT(allow_macro_instructions_);
568 fmsub(fd, fn, fm, fa);
569 }
570 void Fneg(const FPRegister& fd, const FPRegister& fn) {
571 ASSERT(allow_macro_instructions_);
572 fneg(fd, fn);
573 }
574 void Frintn(const FPRegister& fd, const FPRegister& fn) {
575 ASSERT(allow_macro_instructions_);
576 frintn(fd, fn);
577 }
578 void Frintz(const FPRegister& fd, const FPRegister& fn) {
579 ASSERT(allow_macro_instructions_);
580 frintz(fd, fn);
581 }
582 void Fsqrt(const FPRegister& fd, const FPRegister& fn) {
583 ASSERT(allow_macro_instructions_);
584 fsqrt(fd, fn);
585 }
armvixlad96eda2013-06-14 11:42:37 +0100586 void Fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm) {
587 ASSERT(allow_macro_instructions_);
588 fsub(fd, fn, fm);
589 }
590 void Hint(SystemHint code) {
591 ASSERT(allow_macro_instructions_);
592 hint(code);
593 }
594 void Hlt(int code) {
595 ASSERT(allow_macro_instructions_);
596 hlt(code);
597 }
598 void Ldnp(const CPURegister& rt,
599 const CPURegister& rt2,
600 const MemOperand& src) {
601 ASSERT(allow_macro_instructions_);
602 ldnp(rt, rt2, src);
603 }
604 void Ldp(const CPURegister& rt,
605 const CPURegister& rt2,
606 const MemOperand& src) {
607 ASSERT(allow_macro_instructions_);
608 ldp(rt, rt2, src);
609 }
610 void Ldpsw(const Register& rt, const Register& rt2, const MemOperand& src) {
611 ASSERT(allow_macro_instructions_);
612 ldpsw(rt, rt2, src);
613 }
614 void Ldr(const FPRegister& ft, double imm) {
615 ASSERT(allow_macro_instructions_);
616 ldr(ft, imm);
617 }
618 void Ldr(const Register& rt, uint64_t imm) {
619 ASSERT(allow_macro_instructions_);
620 ASSERT(!rt.IsZero());
621 ldr(rt, imm);
622 }
623 void Lsl(const Register& rd, const Register& rn, unsigned shift) {
624 ASSERT(allow_macro_instructions_);
625 ASSERT(!rd.IsZero());
626 ASSERT(!rn.IsZero());
627 lsl(rd, rn, shift);
628 }
629 void Lsl(const Register& rd, const Register& rn, const Register& rm) {
630 ASSERT(allow_macro_instructions_);
631 ASSERT(!rd.IsZero());
632 ASSERT(!rn.IsZero());
633 ASSERT(!rm.IsZero());
634 lslv(rd, rn, rm);
635 }
636 void Lsr(const Register& rd, const Register& rn, unsigned shift) {
637 ASSERT(allow_macro_instructions_);
638 ASSERT(!rd.IsZero());
639 ASSERT(!rn.IsZero());
640 lsr(rd, rn, shift);
641 }
642 void Lsr(const Register& rd, const Register& rn, const Register& rm) {
643 ASSERT(allow_macro_instructions_);
644 ASSERT(!rd.IsZero());
645 ASSERT(!rn.IsZero());
646 ASSERT(!rm.IsZero());
647 lsrv(rd, rn, rm);
648 }
649 void Madd(const Register& rd,
650 const Register& rn,
651 const Register& rm,
652 const Register& ra) {
653 ASSERT(allow_macro_instructions_);
654 ASSERT(!rd.IsZero());
655 ASSERT(!rn.IsZero());
656 ASSERT(!rm.IsZero());
657 ASSERT(!ra.IsZero());
658 madd(rd, rn, rm, ra);
659 }
660 void Mneg(const Register& rd, const Register& rn, const Register& rm) {
661 ASSERT(allow_macro_instructions_);
662 ASSERT(!rd.IsZero());
663 ASSERT(!rn.IsZero());
664 ASSERT(!rm.IsZero());
665 mneg(rd, rn, rm);
666 }
667 void Mov(const Register& rd, const Register& rn) {
668 ASSERT(allow_macro_instructions_);
669 mov(rd, rn);
670 }
671 void Mrs(const Register& rt, SystemRegister sysreg) {
672 ASSERT(allow_macro_instructions_);
673 ASSERT(!rt.IsZero());
674 mrs(rt, sysreg);
675 }
676 void Msr(SystemRegister sysreg, const Register& rt) {
677 ASSERT(allow_macro_instructions_);
678 ASSERT(!rt.IsZero());
679 msr(sysreg, rt);
680 }
681 void Msub(const Register& rd,
682 const Register& rn,
683 const Register& rm,
684 const Register& ra) {
685 ASSERT(allow_macro_instructions_);
686 ASSERT(!rd.IsZero());
687 ASSERT(!rn.IsZero());
688 ASSERT(!rm.IsZero());
689 ASSERT(!ra.IsZero());
690 msub(rd, rn, rm, ra);
691 }
692 void Mul(const Register& rd, const Register& rn, const Register& rm) {
693 ASSERT(allow_macro_instructions_);
694 ASSERT(!rd.IsZero());
695 ASSERT(!rn.IsZero());
696 ASSERT(!rm.IsZero());
697 mul(rd, rn, rm);
698 }
699 void Nop() {
700 ASSERT(allow_macro_instructions_);
701 nop();
702 }
703 void Rbit(const Register& rd, const Register& rn) {
704 ASSERT(allow_macro_instructions_);
705 ASSERT(!rd.IsZero());
706 ASSERT(!rn.IsZero());
707 rbit(rd, rn);
708 }
709 void Ret(const Register& xn = lr) {
710 ASSERT(allow_macro_instructions_);
711 ASSERT(!xn.IsZero());
712 ret(xn);
713 }
714 void Rev(const Register& rd, const Register& rn) {
715 ASSERT(allow_macro_instructions_);
716 ASSERT(!rd.IsZero());
717 ASSERT(!rn.IsZero());
718 rev(rd, rn);
719 }
720 void Rev16(const Register& rd, const Register& rn) {
721 ASSERT(allow_macro_instructions_);
722 ASSERT(!rd.IsZero());
723 ASSERT(!rn.IsZero());
724 rev16(rd, rn);
725 }
726 void Rev32(const Register& rd, const Register& rn) {
727 ASSERT(allow_macro_instructions_);
728 ASSERT(!rd.IsZero());
729 ASSERT(!rn.IsZero());
730 rev32(rd, rn);
731 }
732 void Ror(const Register& rd, const Register& rs, unsigned shift) {
733 ASSERT(allow_macro_instructions_);
734 ASSERT(!rd.IsZero());
735 ASSERT(!rs.IsZero());
736 ror(rd, rs, shift);
737 }
738 void Ror(const Register& rd, const Register& rn, const Register& rm) {
739 ASSERT(allow_macro_instructions_);
740 ASSERT(!rd.IsZero());
741 ASSERT(!rn.IsZero());
742 ASSERT(!rm.IsZero());
743 rorv(rd, rn, rm);
744 }
745 void Sbfiz(const Register& rd,
746 const Register& rn,
747 unsigned lsb,
748 unsigned width) {
749 ASSERT(allow_macro_instructions_);
750 ASSERT(!rd.IsZero());
751 ASSERT(!rn.IsZero());
752 sbfiz(rd, rn, lsb, width);
753 }
754 void Sbfx(const Register& rd,
755 const Register& rn,
756 unsigned lsb,
757 unsigned width) {
758 ASSERT(allow_macro_instructions_);
759 ASSERT(!rd.IsZero());
760 ASSERT(!rn.IsZero());
761 sbfx(rd, rn, lsb, width);
762 }
763 void Scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
764 ASSERT(allow_macro_instructions_);
765 ASSERT(!rn.IsZero());
766 scvtf(fd, rn, fbits);
767 }
768 void Sdiv(const Register& rd, const Register& rn, const Register& rm) {
769 ASSERT(allow_macro_instructions_);
770 ASSERT(!rd.IsZero());
771 ASSERT(!rn.IsZero());
772 ASSERT(!rm.IsZero());
773 sdiv(rd, rn, rm);
774 }
775 void Smaddl(const Register& rd,
776 const Register& rn,
777 const Register& rm,
778 const Register& ra) {
779 ASSERT(allow_macro_instructions_);
780 ASSERT(!rd.IsZero());
781 ASSERT(!rn.IsZero());
782 ASSERT(!rm.IsZero());
783 ASSERT(!ra.IsZero());
784 smaddl(rd, rn, rm, ra);
785 }
786 void Smsubl(const Register& rd,
787 const Register& rn,
788 const Register& rm,
789 const Register& ra) {
790 ASSERT(allow_macro_instructions_);
791 ASSERT(!rd.IsZero());
792 ASSERT(!rn.IsZero());
793 ASSERT(!rm.IsZero());
794 ASSERT(!ra.IsZero());
795 smsubl(rd, rn, rm, ra);
796 }
797 void Smull(const Register& rd, const Register& rn, const Register& rm) {
798 ASSERT(allow_macro_instructions_);
799 ASSERT(!rd.IsZero());
800 ASSERT(!rn.IsZero());
801 ASSERT(!rm.IsZero());
802 smull(rd, rn, rm);
803 }
804 void Smulh(const Register& xd, const Register& xn, const Register& xm) {
805 ASSERT(allow_macro_instructions_);
806 ASSERT(!xd.IsZero());
807 ASSERT(!xn.IsZero());
808 ASSERT(!xm.IsZero());
809 smulh(xd, xn, xm);
810 }
811 void Stnp(const CPURegister& rt,
812 const CPURegister& rt2,
813 const MemOperand& dst) {
814 ASSERT(allow_macro_instructions_);
815 stnp(rt, rt2, dst);
816 }
817 void Stp(const CPURegister& rt,
818 const CPURegister& rt2,
819 const MemOperand& dst) {
820 ASSERT(allow_macro_instructions_);
821 stp(rt, rt2, dst);
822 }
823 void Sxtb(const Register& rd, const Register& rn) {
824 ASSERT(allow_macro_instructions_);
825 ASSERT(!rd.IsZero());
826 ASSERT(!rn.IsZero());
827 sxtb(rd, rn);
828 }
829 void Sxth(const Register& rd, const Register& rn) {
830 ASSERT(allow_macro_instructions_);
831 ASSERT(!rd.IsZero());
832 ASSERT(!rn.IsZero());
833 sxth(rd, rn);
834 }
835 void Sxtw(const Register& rd, const Register& rn) {
836 ASSERT(allow_macro_instructions_);
837 ASSERT(!rd.IsZero());
838 ASSERT(!rn.IsZero());
839 sxtw(rd, rn);
840 }
841 void Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
842 ASSERT(allow_macro_instructions_);
843 ASSERT(!rt.IsZero());
844 tbnz(rt, bit_pos, label);
845 }
846 void Tbz(const Register& rt, unsigned bit_pos, Label* label) {
847 ASSERT(allow_macro_instructions_);
848 ASSERT(!rt.IsZero());
849 tbz(rt, bit_pos, label);
850 }
851 void Ubfiz(const Register& rd,
852 const Register& rn,
853 unsigned lsb,
854 unsigned width) {
855 ASSERT(allow_macro_instructions_);
856 ASSERT(!rd.IsZero());
857 ASSERT(!rn.IsZero());
858 ubfiz(rd, rn, lsb, width);
859 }
860 void Ubfx(const Register& rd,
861 const Register& rn,
862 unsigned lsb,
863 unsigned width) {
864 ASSERT(allow_macro_instructions_);
865 ASSERT(!rd.IsZero());
866 ASSERT(!rn.IsZero());
867 ubfx(rd, rn, lsb, width);
868 }
869 void Ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0) {
870 ASSERT(allow_macro_instructions_);
871 ASSERT(!rn.IsZero());
872 ucvtf(fd, rn, fbits);
873 }
874 void Udiv(const Register& rd, const Register& rn, const Register& rm) {
875 ASSERT(allow_macro_instructions_);
876 ASSERT(!rd.IsZero());
877 ASSERT(!rn.IsZero());
878 ASSERT(!rm.IsZero());
879 udiv(rd, rn, rm);
880 }
881 void Umaddl(const Register& rd,
882 const Register& rn,
883 const Register& rm,
884 const Register& ra) {
885 ASSERT(allow_macro_instructions_);
886 ASSERT(!rd.IsZero());
887 ASSERT(!rn.IsZero());
888 ASSERT(!rm.IsZero());
889 ASSERT(!ra.IsZero());
890 umaddl(rd, rn, rm, ra);
891 }
892 void Umsubl(const Register& rd,
893 const Register& rn,
894 const Register& rm,
895 const Register& ra) {
896 ASSERT(allow_macro_instructions_);
897 ASSERT(!rd.IsZero());
898 ASSERT(!rn.IsZero());
899 ASSERT(!rm.IsZero());
900 ASSERT(!ra.IsZero());
901 umsubl(rd, rn, rm, ra);
902 }
903 void Unreachable() {
904 ASSERT(allow_macro_instructions_);
905#ifdef USE_SIMULATOR
906 hlt(kUnreachableOpcode);
907#else
908 // Branch to 0 to generate a segfault.
909 // lr - kInstructionSize is the address of the offending instruction.
910 blr(xzr);
911#endif
912 }
913 void Uxtb(const Register& rd, const Register& rn) {
914 ASSERT(allow_macro_instructions_);
915 ASSERT(!rd.IsZero());
916 ASSERT(!rn.IsZero());
917 uxtb(rd, rn);
918 }
919 void Uxth(const Register& rd, const Register& rn) {
920 ASSERT(allow_macro_instructions_);
921 ASSERT(!rd.IsZero());
922 ASSERT(!rn.IsZero());
923 uxth(rd, rn);
924 }
925 void Uxtw(const Register& rd, const Register& rn) {
926 ASSERT(allow_macro_instructions_);
927 ASSERT(!rd.IsZero());
928 ASSERT(!rn.IsZero());
929 uxtw(rd, rn);
930 }
931
932 // Push the system stack pointer (sp) down to allow the same to be done to
933 // the current stack pointer (according to StackPointer()). This must be
934 // called _before_ accessing the memory.
935 //
936 // This is necessary when pushing or otherwise adding things to the stack, to
937 // satisfy the AAPCS64 constraint that the memory below the system stack
938 // pointer is not accessed.
939 //
940 // This method asserts that StackPointer() is not sp, since the call does
941 // not make sense in that context.
942 //
943 // TODO: This method can only accept values of 'space' that can be encoded in
944 // one instruction. Refer to the implementation for details.
945 void BumpSystemStackPointer(const Operand& space);
946
947#if DEBUG
948 void SetAllowMacroInstructions(bool value) {
949 allow_macro_instructions_ = value;
950 }
951
952 bool AllowMacroInstructions() const {
953 return allow_macro_instructions_;
954 }
955#endif
956
957 // Set the current stack pointer, but don't generate any code.
958 // Note that this does not directly affect LastStackPointer().
959 void SetStackPointer(const Register& stack_pointer) {
960 ASSERT(!AreAliased(stack_pointer, Tmp0(), Tmp1()));
961 sp_ = stack_pointer;
962 }
963
964 // Return the current stack pointer, as set by SetStackPointer.
965 const Register& StackPointer() const {
966 return sp_;
967 }
968
969 // Set the registers used internally by the MacroAssembler as scratch
970 // registers. These registers are used to implement behaviours which are not
971 // directly supported by A64, and where an intermediate result is required.
972 //
973 // Both tmp0 and tmp1 may be set to any X register except for xzr, sp,
974 // and StackPointer(). Also, they must not be the same register (though they
975 // may both be NoReg).
976 //
977 // It is valid to set either or both of these registers to NoReg if you don't
978 // want the MacroAssembler to use any scratch registers. In a debug build, the
979 // Assembler will assert that any registers it uses are valid. Be aware that
980 // this check is not present in release builds. If this is a problem, use the
981 // Assembler directly.
982 void SetScratchRegisters(const Register& tmp0, const Register& tmp1) {
983 ASSERT(!AreAliased(xzr, sp, tmp0, tmp1));
984 ASSERT(!AreAliased(StackPointer(), tmp0, tmp1));
985 tmp0_ = tmp0;
986 tmp1_ = tmp1;
987 }
988
989 const Register& Tmp0() const {
990 return tmp0_;
991 }
992
993 const Register& Tmp1() const {
994 return tmp1_;
995 }
996
997 void SetFPScratchRegister(const FPRegister& fptmp0) {
998 fptmp0_ = fptmp0;
999 }
1000
1001 const FPRegister& FPTmp0() const {
1002 return fptmp0_;
1003 }
1004
1005 const Register AppropriateTempFor(
1006 const Register& target,
1007 const CPURegister& forbidden = NoCPUReg) const {
1008 Register candidate = forbidden.Is(Tmp0()) ? Tmp1() : Tmp0();
1009 ASSERT(!candidate.Is(target));
1010 return Register(candidate.code(), target.size());
1011 }
1012
1013 const FPRegister AppropriateTempFor(
1014 const FPRegister& target,
1015 const CPURegister& forbidden = NoCPUReg) const {
1016 USE(forbidden);
1017 FPRegister candidate = FPTmp0();
1018 ASSERT(!candidate.Is(forbidden));
1019 ASSERT(!candidate.Is(target));
1020 return FPRegister(candidate.code(), target.size());
1021 }
1022
1023 // Like printf, but print at run-time from generated code.
1024 //
1025 // The caller must ensure that arguments for floating-point placeholders
1026 // (such as %e, %f or %g) are FPRegisters, and that arguments for integer
1027 // placeholders are Registers.
1028 //
1029 // A maximum of four arguments may be given to any single Printf call. The
1030 // arguments must be of the same type, but they do not need to have the same
1031 // size.
1032 //
1033 // The following registers cannot be printed:
1034 // Tmp0(), Tmp1(), StackPointer(), sp.
1035 //
1036 // This function automatically preserves caller-saved registers so that
1037 // calling code can use Printf at any point without having to worry about
1038 // corruption. The preservation mechanism generates a lot of code. If this is
1039 // a problem, preserve the important registers manually and then call
1040 // PrintfNoPreserve. Callee-saved registers are not used by Printf, and are
1041 // implicitly preserved.
1042 //
1043 // This function assumes (and asserts) that the current stack pointer is
1044 // callee-saved, not caller-saved. This is most likely the case anyway, as a
1045 // caller-saved stack pointer doesn't make a lot of sense.
1046 void Printf(const char * format,
1047 const CPURegister& arg0 = NoCPUReg,
1048 const CPURegister& arg1 = NoCPUReg,
1049 const CPURegister& arg2 = NoCPUReg,
1050 const CPURegister& arg3 = NoCPUReg);
1051
1052 // Like Printf, but don't preserve any caller-saved registers, not even 'lr'.
1053 //
1054 // The return code from the system printf call will be returned in x0.
1055 void PrintfNoPreserve(const char * format,
1056 const CPURegister& arg0 = NoCPUReg,
1057 const CPURegister& arg1 = NoCPUReg,
1058 const CPURegister& arg2 = NoCPUReg,
1059 const CPURegister& arg3 = NoCPUReg);
1060
1061 // Trace control when running the debug simulator.
1062 //
1063 // For example:
1064 //
1065 // __ Trace(LOG_REGS, TRACE_ENABLE);
1066 // Will add registers to the trace if it wasn't already the case.
1067 //
1068 // __ Trace(LOG_DISASM, TRACE_DISABLE);
1069 // Will stop logging disassembly. It has no effect if the disassembly wasn't
1070 // already being logged.
1071 void Trace(TraceParameters parameters, TraceCommand command);
1072
1073 // Log the requested data independently of what is being traced.
1074 //
1075 // For example:
1076 //
1077 // __ Log(LOG_FLAGS)
1078 // Will output the flags.
armvixl578645f2013-08-15 17:21:42 +01001079 void Log(TraceParameters parameters);
1080
1081 // Enable or disable instrumentation when an Instrument visitor is attached to
1082 // the simulator.
1083 void EnableInstrumentation();
1084 void DisableInstrumentation();
1085
1086 // Add a marker to the instrumentation data produced by an Instrument visitor.
1087 // The name is a two character string that will be attached to the marker in
1088 // the output data.
1089 void AnnotateInstrumentation(const char* marker_name);
armvixlad96eda2013-06-14 11:42:37 +01001090
1091 private:
1092 // The actual Push and Pop implementations. These don't generate any code
1093 // other than that required for the push or pop. This allows
1094 // (Push|Pop)CPURegList to bundle together setup code for a large block of
1095 // registers.
1096 //
1097 // Note that size is per register, and is specified in bytes.
1098 void PushHelper(int count, int size,
1099 const CPURegister& src0, const CPURegister& src1,
1100 const CPURegister& src2, const CPURegister& src3);
1101 void PopHelper(int count, int size,
1102 const CPURegister& dst0, const CPURegister& dst1,
1103 const CPURegister& dst2, const CPURegister& dst3);
1104
1105 // Perform necessary maintenance operations before a push or pop.
1106 //
1107 // Note that size is per register, and is specified in bytes.
1108 void PrepareForPush(int count, int size);
1109 void PrepareForPop(int count, int size);
1110
1111#if DEBUG
1112 // Tell whether any of the macro instruction can be used. When false the
1113 // MacroAssembler will assert if a method which can emit a variable number
1114 // of instructions is called.
1115 bool allow_macro_instructions_;
1116#endif
1117
1118 // The register to use as a stack pointer for stack operations.
1119 Register sp_;
1120
1121 // Scratch registers used internally by the MacroAssembler.
1122 Register tmp0_;
1123 Register tmp1_;
1124 FPRegister fptmp0_;
1125};
1126
1127
1128// Use this scope when you need a one-to-one mapping between methods and
1129// instructions. This scope prevents the MacroAssembler from being called and
1130// literal pools from being emitted. It also asserts the number of instructions
1131// emitted is what you specified when creating the scope.
1132class InstructionAccurateScope {
1133 public:
1134 explicit InstructionAccurateScope(MacroAssembler* masm)
1135 : masm_(masm), size_(0) {
1136 masm_->BlockLiteralPool();
1137#ifdef DEBUG
1138 old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
1139 masm_->SetAllowMacroInstructions(false);
1140#endif
1141 }
1142
1143 InstructionAccurateScope(MacroAssembler* masm, int count)
1144 : masm_(masm), size_(count * kInstructionSize) {
1145 masm_->BlockLiteralPool();
1146#ifdef DEBUG
1147 masm_->bind(&start_);
1148 old_allow_macro_instructions_ = masm_->AllowMacroInstructions();
1149 masm_->SetAllowMacroInstructions(false);
1150#endif
1151 }
1152
1153 ~InstructionAccurateScope() {
1154 masm_->ReleaseLiteralPool();
1155#ifdef DEBUG
1156 if (start_.IsBound()) {
1157 ASSERT(masm_->SizeOfCodeGeneratedSince(&start_) == size_);
1158 }
1159 masm_->SetAllowMacroInstructions(old_allow_macro_instructions_);
1160#endif
1161 }
1162
1163 private:
1164 MacroAssembler* masm_;
1165 uint64_t size_;
1166#ifdef DEBUG
1167 Label start_;
1168 bool old_allow_macro_instructions_;
1169#endif
1170};
1171
1172
1173} // namespace vixl
1174
1175#endif // VIXL_A64_MACRO_ASSEMBLER_A64_H_