@@@ mess
[catacomb] / base / asm-common.h
CommitLineData
1a0c09c4
MW
1/// -*- mode: asm; asm-comment-char: ?/ -*-
2///
08b868da 3/// Common definitions for asesembler source files
1a0c09c4
MW
4///
5/// (c) 2015 Straylight/Edgeware
6///
7
8///----- Licensing notice ---------------------------------------------------
9///
10/// This file is part of Catacomb.
11///
12/// Catacomb is free software; you can redistribute it and/or modify
13/// it under the terms of the GNU Library General Public License as
14/// published by the Free Software Foundation; either version 2 of the
15/// License, or (at your option) any later version.
16///
17/// Catacomb is distributed in the hope that it will be useful,
18/// but WITHOUT ANY WARRANTY; without even the implied warranty of
19/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20/// GNU Library General Public License for more details.
21///
22/// You should have received a copy of the GNU Library General Public
23/// License along with Catacomb; if not, write to the Free
24/// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25/// MA 02111-1307, USA.
26
8ce88ea5
MW
27#ifndef CATACOMB_ASM_COMMON_H
28#define CATACOMB_ASM_COMMON_H
29
1a0c09c4
MW
30///--------------------------------------------------------------------------
31/// General definitions.
32
898f32b3
MW
33// Preprocessor hacks.
34#define STRINGY(x) _STRINGY(x, y)
35#define _STRINGY(x) #x
36#define GLUE(x, y) _GLUE(x, y)
37#define _GLUE(x, y) x##y
38#define _EMPTY
39
f8e509a9
MW
40// Some useful variables.
41 .L$_subsec = 0
42
43// Literal pools done the hard way.
44#define _LIT .text .L$_subsec + 1
45#define _ENDLIT .text .L$_subsec
6c54cbd3 46#define _LTORG .L$_subsec = .L$_subsec + 2; .text .L$_subsec
f8e509a9 47
1a517bb3
MW
48// Announcing an internal function.
49#define INTFUNC(name) \
1a0c09c4 50 TYPE_FUNC(name); \
8a1aa284 51 .macro ENDFUNC; _ENDFUNC(name); .endm; \
0923a413 52 .L$_prologue_p = 0; .L$_frameptr_p = 0; \
1a0c09c4 53 FUNC_PREHOOK(name); \
1a517bb3 54name: \
1a0c09c4
MW
55 FUNC_POSTHOOK(name)
56
1a517bb3
MW
57// Announcing an external function.
58#define FUNC(name) \
59 .globl F(name); \
60INTFUNC(F(name))
61
1a0c09c4
MW
62// Marking the end of a function.
63#define _ENDFUNC(name) \
0923a413
MW
64 .if ~ .L$_prologue_p; .error "Missing `endprologue'"; .endif; \
65 .if .L$_frameptr_p; .purgem dropfp; .endif; \
1a0c09c4
MW
66 .purgem ENDFUNC; \
67 SIZE_OBJ(name); \
f8e509a9 68 ENDFUNC_HOOK(name); \
6c54cbd3 69 _LTORG
1a0c09c4 70
8ae4c946
MW
71// Make a helper function, if necessary.
72#define AUXFN(name) \
73 .ifndef .L$_auxfn_def.name; \
74 .text 7128; \
75 .macro _ENDAUXFN; _ENDAUXFN_TAIL(name); .endm; \
76 FUNC_PREHOOK(name); \
77name:
78#define _ENDAUXFN_TAIL(name) \
79 .purgem _ENDAUXFN; \
80 .text .L$_subsec; \
81 .L$_auxfn_def.name = 1
82#define ENDAUXFN _ENDAUXFN; .endif
83
1a0c09c4
MW
84///--------------------------------------------------------------------------
85/// ELF-specific hacking.
86
87#if __ELF__
88
148c3643
MW
89// Section types.
90#if CPUFAM_ARMEL
91# define _SECTTY(ty) %ty
92#else
93# define _SECTTY(ty) @ty
94#endif
95
b0c2da14
MW
96// Section selection.
97#define RODATA .section .rodata, "a", _SECTTY(progbits)
98
5336ba54 99// Additional symbol metadata.
1a0c09c4 100#define TYPE_FUNC(name) .type name, STT_FUNC
6ae7b854 101#define TYPE_OBJ(name) .type name, STT_OBJECT
1a0c09c4
MW
102#define SIZE_OBJ(name) .size name, . - name
103
f2fb936a
MW
104// Special arrangements for position-independent code.
105#if __PIC__ || __PIE__
106# define WANT_PIC 1
107#endif
108
67e71236
MW
109// Don't make the stack executable by default.
110#ifndef FORCE_EXECUTABLE_STACK
111 .pushsection .note.GNU-stack, "", _SECTTY(progbits)
112 .popsection
113#endif
114
1a0c09c4
MW
115#endif
116
117///--------------------------------------------------------------------------
0f23f75f
MW
118/// Windows-specific hacking.
119
120#if ABI_WIN
1a0c09c4 121
5336ba54 122// Function names need decorating on 32-bit i386.
1a0c09c4 123#if CPUFAM_X86
0f23f75f
MW
124# define F(name) _##name
125#endif
126
b0c2da14
MW
127// Section selection.
128#define RODATA .section .rdata, "dr"
129
0f23f75f
MW
130#endif
131
132///--------------------------------------------------------------------------
133/// x86- and amd64-specific hacking.
134///
135/// It's (slightly) easier to deal with both of these in one go.
136
137#if CPUFAM_X86 || CPUFAM_AMD64
1a0c09c4 138
2cb17e02
MW
139// Word size.
140#if CPUFAM_X86
141# define WORDSZ 4
142#endif
143#if CPUFAM_AMD64
144# define WORDSZ 8
145#endif
146
1a0c09c4
MW
147// Set the function hooks.
148#define FUNC_PREHOOK(_) .balign 16
149
f71dd54d
MW
150// On Windows, arrange to install stack-unwinding data.
151#if CPUFAM_AMD64 && ABI_WIN
152# define FUNC_POSTHOOK(name) .seh_proc name
153# define ENDFUNC_HOOK(_) .seh_endproc
154// Procedures are expected to invoke `.seh_setframe' if necessary, and
155// `.seh_pushreg' and friends, and `.seh_endprologue'.
156#endif
157
0923a413
MW
158#if __ELF__
159# define FUNC_POSTHOOK(_) .cfi_startproc
160# define ENDFUNC_HOOK(_) .cfi_endproc
161#endif
162
1a0c09c4
MW
163// Don't use the wretched AT&T syntax. It's festooned with pointless
164// punctuation, and all of the data movement is backwards. Ugh!
165 .intel_syntax noprefix
166
167// Call external subroutine at ADDR, possibly via PLT.
8a1aa284 168.macro callext addr
1a0c09c4
MW
169#if WANT_PIC
170 call \addr@PLT
171#else
172 call \addr
173#endif
8a1aa284 174.endm
1a0c09c4
MW
175
176// Do I need to arrange a spare GOT register?
177#if WANT_PIC && CPUFAM_X86
178# define NEED_GOT 1
179#endif
180#define GOTREG ebx // Not needed in AMD64 so don't care.
181
182// Maybe load GOT address into GOT.
8a1aa284 183.macro ldgot got=GOTREG
0f23f75f 184#if WANT_PIC && CPUFAM_X86
8ae4c946 185 AUXFN(_ldgot.\got)
1a0c09c4
MW
186 mov \got, [esp]
187 ret
8ae4c946
MW
188 ENDAUXFN
189 call _ldgot.\got
190 add \got, offset _GLOBAL_OFFSET_TABLE_
1a0c09c4 191#endif
8a1aa284 192.endm
1a0c09c4
MW
193
194// Load address of external symbol ADDR into REG, maybe using GOT.
8a1aa284 195.macro leaext reg, addr, got=GOTREG
1a0c09c4 196#if WANT_PIC
0f23f75f 197# if CPUFAM_X86
1a0c09c4 198 mov \reg, [\got + \addr@GOT]
0f23f75f
MW
199# endif
200# if CPUFAM_AMD64
201 mov \reg, \addr@GOTPCREL[rip]
202# endif
1a0c09c4 203#else
0f23f75f 204# if CPUFAM_X86
1a0c09c4 205 mov \reg, offset \addr
0f23f75f
MW
206# endif
207# if CPUFAM_AMD64
208 lea \reg, \addr[rip]
209# endif
1a0c09c4 210#endif
8a1aa284 211.endm
1a0c09c4
MW
212
213// Address expression (possibly using a base register, and a displacement)
214// referring to ADDR, which is within our module, maybe using GOT.
215#define INTADDR(...) INTADDR__0(__VA_ARGS__, GOTREG, dummy)
216#define INTADDR__0(addr, got, ...) INTADDR__1(addr, got)
0f23f75f
MW
217#if CPUFAM_AMD64
218# define INTADDR__1(addr, got) addr + rip
219#elif WANT_PIC
1a0c09c4
MW
220# define INTADDR__1(addr, got) got + addr@GOTOFF
221#else
222# define INTADDR__1(addr, got) addr
223#endif
224
a117c06f
MW
225// Permutations for SIMD instructions. SHUF(A, B, C, D) is an immediate,
226// suitable for use in `pshufd' or `shufpd', which copies element A
227// (0 <= A < 4) of the source to element 0 of the destination, element B to
228// element 1, element C to element 2, and element D to element 3.
229#define SHUF(a, b, c, d) ((a) + 4*(b) + 16*(c) + 64*(d))
a13b5730 230
43ea7558
MW
231// Map register names to their individual pieces.
232
233// Apply decoration decor to (internal) register name reg of type ty.
234//
235// See `R_...' for internal register names. Decorations are as follows.
236//
237// b low byte (e.g., `al', `r8b')
238// h high byte (e.g., `ah')
239// w word (e.g., `ax', `r8w')
240// d doubleword (e.g., `eax', `r8d')
241// q quadword (e.g., `rax', `r8')
242// r whole register (doubleword on x86, quadword on amd64)
243//
244// And types are as follows.
245//
246// abcd the four traditional registers `a', `b', `c', `d'
247// xp the four pointer registers `si', `di', `bp', `sp'
248// ip the instruction pointer `ip'
249// rn the AMD64 numbered registers `r8'--`r15'
250#define _DECOR(ty, decor, reg) _DECOR_##ty##_##decor(reg)
251
252// Internal macros: _DECOR_ty_decor(reg) applies decoration decor to
253// (internal) register name reg of type ty.
254
255#define _DECOR_abcd_b(reg) reg##l
256#define _DECOR_abcd_h(reg) reg##h
257#define _DECOR_abcd_w(reg) reg##x
258#define _DECOR_abcd_d(reg) e##reg##x
259#if CPUFAM_AMD64
260# define _DECOR_abcd_q(reg) r##reg##x
261#endif
262
43ea7558
MW
263#define _DECOR_xp_w(reg) reg
264#define _DECOR_xp_d(reg) e##reg
265#if CPUFAM_AMD64
a105615f 266# define _DECOR_xp_b(reg) reg##l
43ea7558
MW
267# define _DECOR_xp_q(reg) r##reg
268#endif
269
270#define _DECOR_ip_w(reg) reg
271#define _DECOR_ip_d(reg) e##reg
272#if CPUFAM_AMD64
273# define _DECOR_ip_q(reg) r##reg
274#endif
275
276#if CPUFAM_AMD64
277# define _DECOR_rn_b(reg) reg##b
278# define _DECOR_rn_w(reg) reg##w
279# define _DECOR_rn_d(reg) reg##d
280# define _DECOR_rn_q(reg) reg
281# define _DECOR_rn_r(reg) reg
282#endif
283
005cd277
MW
284#define _DECOR_mem_b(addr) byte ptr addr
285#define _DECOR_mem_w(addr) word ptr addr
286#define _DECOR_mem_d(addr) dword ptr addr
287#if CPUFAM_AMD64
288# define _DECOR_mem_q(addr) qword ptr addr
289#endif
290
7e251005
MW
291#define _DECOR_imm_b(imm) byte imm
292#define _DECOR_imm_w(imm) word imm
293#define _DECOR_imm_d(imm) dword imm
294#if CPUFAM_AMD64
295# define _DECOR_imm_q(imm) qword imm
296#endif
297
43ea7558
MW
298#if CPUFAM_X86
299# define _DECOR_abcd_r(reg) e##reg##x
300# define _DECOR_xp_r(reg) e##reg
301# define _DECOR_ip_r(reg) e##reg
3c0490d1 302# define _DECOR_mem_r(addr) dword ptr addr
7e251005 303# define _DECOR_imm_r(imm) dword imm
43ea7558
MW
304#endif
305#if CPUFAM_AMD64
306# define _DECOR_abcd_r(reg) r##reg##x
307# define _DECOR_xp_r(reg) r##reg
308# define _DECOR_ip_r(reg) r##reg
3c0490d1 309# define _DECOR_mem_r(addr) qword ptr addr
7e251005 310# define _DECOR_imm_r(imm) qword imm
43ea7558
MW
311#endif
312
43ea7558
MW
313// R_r(decor) applies decoration decor to register r, which is an internal
314// register name. The internal register names are: `ip', `a', `b', `c', `d',
315// `si', `di', `bp', `sp', `r8'--`r15'.
4ff9d579 316#define R_nil(decor) nil
43ea7558
MW
317#define R_ip(decor) _DECOR(ip, decor, ip)
318#define R_a(decor) _DECOR(abcd, decor, a)
319#define R_b(decor) _DECOR(abcd, decor, b)
320#define R_c(decor) _DECOR(abcd, decor, c)
321#define R_d(decor) _DECOR(abcd, decor, d)
322#define R_si(decor) _DECOR(xp, decor, si)
323#define R_di(decor) _DECOR(xp, decor, di)
324#define R_bp(decor) _DECOR(xp, decor, bp)
325#define R_sp(decor) _DECOR(xp, decor, sp)
326#if CPUFAM_AMD64
327# define R_r8(decor) _DECOR(rn, decor, r8)
328# define R_r9(decor) _DECOR(rn, decor, r9)
329# define R_r10(decor) _DECOR(rn, decor, r10)
330# define R_r11(decor) _DECOR(rn, decor, r11)
331# define R_r12(decor) _DECOR(rn, decor, r12)
332# define R_r13(decor) _DECOR(rn, decor, r13)
333# define R_r14(decor) _DECOR(rn, decor, r14)
334# define R_r15(decor) _DECOR(rn, decor, r15)
335#endif
336
337// Refer to an in-memory datum of the type implied by decor residing at
338// address addr (which should supply its own square-brackets).
339#define MEM(decor, addr) _DECOR(mem, decor, addr)
340
7e251005
MW
341// Refer to an immediate datum of the type implied by decor.
342#define IMM(decor, imm) _DECOR(mem, decor, imm)
343
43ea7558
MW
344// Applies decoration decor to assembler-level register name reg.
345#define _REGFORM(reg, decor) _GLUE(_REGFORM_, reg)(decor)
346
347// Internal macros: _REGFORM_r(decor) applies decoration decor to an
348// assembler-level register name, in place of any decoration that register
349// name has already.
350
4ff9d579
MW
351#define _REGFORM_nil(decor) R_nil(decor)
352
43ea7558
MW
353#define _REGFORM_ip(decor) R_ip(decor)
354#define _REGFORM_eip(decor) R_ip(decor)
355
356#define _REGFORM_a(decor) R_a(decor)
357#define _REGFORM_al(decor) R_a(decor)
358#define _REGFORM_ah(decor) R_a(decor)
359#define _REGFORM_ax(decor) R_a(decor)
360#define _REGFORM_eax(decor) R_a(decor)
361
362#define _REGFORM_b(decor) R_b(decor)
363#define _REGFORM_bl(decor) R_b(decor)
364#define _REGFORM_bh(decor) R_b(decor)
365#define _REGFORM_bx(decor) R_b(decor)
366#define _REGFORM_ebx(decor) R_b(decor)
367
368#define _REGFORM_c(decor) R_c(decor)
369#define _REGFORM_cl(decor) R_c(decor)
370#define _REGFORM_ch(decor) R_c(decor)
371#define _REGFORM_cx(decor) R_c(decor)
372#define _REGFORM_ecx(decor) R_c(decor)
373
374#define _REGFORM_d(decor) R_d(decor)
375#define _REGFORM_dl(decor) R_d(decor)
376#define _REGFORM_dh(decor) R_d(decor)
377#define _REGFORM_dx(decor) R_d(decor)
378#define _REGFORM_edx(decor) R_d(decor)
379
380#define _REGFORM_si(decor) R_si(decor)
381#define _REGFORM_sil(decor) R_si(decor)
382#define _REGFORM_esi(decor) R_si(decor)
383
384#define _REGFORM_di(decor) R_di(decor)
385#define _REGFORM_dil(decor) R_di(decor)
386#define _REGFORM_edi(decor) R_di(decor)
387
388#define _REGFORM_bp(decor) R_bp(decor)
389#define _REGFORM_bpl(decor) R_bp(decor)
390#define _REGFORM_ebp(decor) R_bp(decor)
391
392#define _REGFORM_sp(decor) R_sp(decor)
393#define _REGFORM_spl(decor) R_sp(decor)
394#define _REGFORM_esp(decor) R_sp(decor)
395
396#if CPUFAM_AMD64
397
398# define _REGFORM_rip(decor) R_ip(decor)
399# define _REGFORM_rsp(decor) R_sp(decor)
400# define _REGFORM_rbp(decor) R_bp(decor)
401# define _REGFORM_rdi(decor) R_di(decor)
402# define _REGFORM_rsi(decor) R_si(decor)
403# define _REGFORM_rdx(decor) R_d(decor)
404# define _REGFORM_rcx(decor) R_c(decor)
405# define _REGFORM_rbx(decor) R_b(decor)
406# define _REGFORM_rax(decor) R_a(decor)
407
408# define _REGFORM_r8(decor) R_r8(decor)
409# define _REGFORM_r8b(decor) R_r8(decor)
410# define _REGFORM_r8w(decor) R_r8(decor)
411# define _REGFORM_r8d(decor) R_r8(decor)
412
413# define _REGFORM_r9(decor) R_r9(decor)
414# define _REGFORM_r9b(decor) R_r9(decor)
415# define _REGFORM_r9w(decor) R_r9(decor)
416# define _REGFORM_r9d(decor) R_r9(decor)
417
418# define _REGFORM_r10(decor) R_r10(decor)
419# define _REGFORM_r10b(decor) R_r10(decor)
420# define _REGFORM_r10w(decor) R_r10(decor)
421# define _REGFORM_r10d(decor) R_r10(decor)
422
423# define _REGFORM_r11(decor) R_r11(decor)
424# define _REGFORM_r11b(decor) R_r11(decor)
425# define _REGFORM_r11w(decor) R_r11(decor)
426# define _REGFORM_r11d(decor) R_r11(decor)
427
428# define _REGFORM_r12(decor) R_r12(decor)
429# define _REGFORM_r12b(decor) R_r12(decor)
430# define _REGFORM_r12w(decor) R_r12(decor)
431# define _REGFORM_r12d(decor) R_r12(decor)
432
433# define _REGFORM_r13(decor) R_r13(decor)
434# define _REGFORM_r13b(decor) R_r13(decor)
435# define _REGFORM_r13w(decor) R_r13(decor)
436# define _REGFORM_r13d(decor) R_r13(decor)
437
438# define _REGFORM_r14(decor) R_r14(decor)
439# define _REGFORM_r14b(decor) R_r14(decor)
440# define _REGFORM_r14w(decor) R_r14(decor)
441# define _REGFORM_r14d(decor) R_r14(decor)
442
443# define _REGFORM_r15(decor) R_r15(decor)
444# define _REGFORM_r15b(decor) R_r15(decor)
445# define _REGFORM_r15w(decor) R_r15(decor)
446# define _REGFORM_r15d(decor) R_r15(decor)
447
448#endif
449
450// Macros for converting register names.
451#define BYTE(reg) _REGFORM(reg, b)
452#define HIBYTE(reg) _REGFORM(reg, h)
453#define WORD(reg) _REGFORM(reg, w)
454#define DWORD(reg) _REGFORM(reg, d)
455#if CPUFAM_AMD64
456# define QWORD(reg) _REGFORM(reg, q)
457#endif
458#define WHOLE(reg) _REGFORM(reg, r)
459
a90d420c
MW
460// Macros for some common registers.
461#define AX R_a(r)
462#define BX R_b(r)
463#define CX R_c(r)
464#define DX R_d(r)
465#define SI R_si(r)
466#define DI R_di(r)
467#define BP R_bp(r)
468#define SP R_sp(r)
469
0923a413 470// Stack management and unwinding.
a90d420c 471.macro setfp fp=BP, offset=0
0923a413 472 .if \offset == 0
a90d420c 473 mov \fp, SP
0923a413
MW
474#if __ELF__
475 .cfi_def_cfa_register \fp
476#endif
477#if ABI_WIN && CPUFAM_AMD64
478 .seh_setframe \fp, 0
479#endif
480 .else
a90d420c 481 lea \fp, [SP + \offset]
0923a413
MW
482#if __ELF__
483 .cfi_def_cfa_register \fp
484 .cfi_adjust_cfa_offset -\offset
485#endif
486#if ABI_WIN && CPUFAM_AMD64
487 .seh_setframe \fp, \offset
488#endif
489 .endif
490 .L$_frameptr_p = -1
491 .macro dropfp; _dropfp \fp, \offset; .endm
492.endm
493
cdc153a5 494.macro _dropfp fp, offset=0
0923a413 495 .if \offset == 0
a90d420c 496 mov SP, \fp
0923a413 497#if __ELF__
a90d420c 498 .cfi_def_cfa_register SP
0923a413
MW
499#endif
500 .else
a90d420c 501 lea SP, [\fp - \offset]
0923a413 502#if __ELF__
a90d420c 503 .cfi_def_cfa_register SP
0923a413
MW
504 .cfi_adjust_cfa_offset +\offset
505#endif
506 .endif
507 .L$_frameptr_p = 0
508 .purgem dropfp
509.endm
510
511.macro stalloc n
a90d420c 512 sub SP, \n
0923a413
MW
513#if __ELF__
514 .cfi_adjust_cfa_offset +\n
515#endif
516#if ABI_WIN && CPUFAM_AMD64
517 .seh_stackalloc \n
518#endif
519.endm
520
521.macro stfree n
a90d420c 522 add SP, \n
0923a413
MW
523#if __ELF__
524 .cfi_adjust_cfa_offset -\n
525#endif
526.endm
527
528.macro pushreg r
529 push \r
530#if __ELF__
531 .cfi_adjust_cfa_offset +WORDSZ
532 .cfi_rel_offset \r, 0
533#endif
534#if ABI_WIN && CPUFAM_AMD64
535 .seh_pushreg \r
536#endif
537.endm
538
539.macro popreg r
540 pop \r
541#if __ELF__
542 .cfi_adjust_cfa_offset -WORDSZ
543 .cfi_restore \r
544#endif
545.endm
546
547.macro savexmm r, offset
a90d420c 548 movdqa [SP + \offset], \r
0923a413
MW
549#if ABI_WIN && CPUFAM_AMD64
550 .seh_savexmm \r, \offset
551#endif
552.endm
553
554.macro rstrxmm r, offset
a90d420c 555 movdqa \r, [SP + \offset]
0923a413
MW
556.endm
557
558.macro endprologue
559#if ABI_WIN && CPUFAM_AMD64
560 .seh_endprologue
561#endif
562 .L$_prologue_p = -1
563.endm
564
1a0c09c4
MW
565#endif
566
567///--------------------------------------------------------------------------
61bd904b
MW
568/// ARM-specific hacking.
569
59d86860 570#if CPUFAM_ARMEL
61bd904b 571
9f6eb05d
MW
572// ARM/Thumb mode things. Use ARM by default.
573#define ARM .arm; .L$_pcoff = 8
574#define THUMB .thumb; .L$_pcoff = 4
575 ARM
576
61bd904b 577// Set the function hooks.
0923a413
MW
578#define FUNC_PREHOOK(_) .balign 4; .fnstart
579#define ENDFUNC_HOOK(_) .fnend; .ltorg
61bd904b
MW
580
581// Call external subroutine at ADDR, possibly via PLT.
8a1aa284 582.macro callext addr, cond=
61bd904b
MW
583#if WANT_PIC
584 bl\cond \addr(PLT)
585#else
586 bl\cond \addr
587#endif
8a1aa284 588.endm
61bd904b
MW
589
590// Do I need to arrange a spare GOT register?
591#if WANT_PIC
592# define NEED_GOT 1
593#endif
594#define GOTREG r9
595
596// Maybe load GOT address into GOT.
8a1aa284 597.macro ldgot cond=, got=GOTREG
61bd904b 598#if WANT_PIC
adca2a18
MW
599 ldr\cond \got, .L$_ldgot$\@
600.L$_ldgot_pc$\@:
2d03a881 601 add\cond \got, pc, \got
8a1aa284 602 _LIT
adca2a18
MW
603 .balign 4
604.L$_ldgot$\@:
9f6eb05d 605 .word _GLOBAL_OFFSET_TABLE_ - .L$_ldgot_pc$\@ - .L$_pcoff
8a1aa284 606 _ENDLIT
61bd904b 607#endif
8a1aa284 608.endm
61bd904b
MW
609
610// Load address of external symbol ADDR into REG, maybe using GOT.
8a1aa284 611.macro leaext reg, addr, cond=, got=GOTREG
61bd904b 612#if WANT_PIC
adca2a18 613 ldr\cond \reg, .L$_leaext$\@
2d03a881 614 ldr\cond \reg, [\got, \reg]
8a1aa284 615 _LIT
adca2a18
MW
616 .balign 4
617.L$_leaext$\@:
618 .word \addr(GOT)
8a1aa284 619 _ENDLIT
61bd904b 620#else
2d03a881 621 ldr\cond \reg, =\addr
61bd904b 622#endif
8a1aa284 623.endm
61bd904b 624
0c53ac58 625// Load address of external symbol ADDR into REG directly.
8a1aa284 626.macro leaextq reg, addr, cond=
0c53ac58
MW
627#if WANT_PIC
628 ldr\cond \reg, .L$_leaextq$\@
629.L$_leaextq_pc$\@:
b6db2017 630 .if .L$_pcoff == 8
0c53ac58 631 ldr\cond \reg, [pc, \reg]
b6db2017 632 .else
9f6eb05d
MW
633 add\cond \reg, pc
634 ldr\cond \reg, [\reg]
b6db2017 635 .endif
8a1aa284 636 _LIT
0c53ac58
MW
637 .balign 4
638.L$_leaextq$\@:
9f6eb05d 639 .word \addr(GOT_PREL) + (. - .L$_leaextq_pc$\@ - .L$_pcoff)
8a1aa284 640 _ENDLIT
0c53ac58
MW
641#else
642 ldr\cond \reg, =\addr
643#endif
8a1aa284 644.endm
0c53ac58 645
1a031196
MW
646.macro vzero vz=q15
647 // Set VZ (default q15) to zero.
648 vmov.u32 \vz, #0
649.endm
650
651.macro vshl128 vd, vn, nbit, vz=q15
652 // Set VD to VN shifted left by NBIT. Assume VZ (default q15) is
653 // all-bits-zero. NBIT must be a multiple of 8.
654 .if \nbit&3 != 0
655 .error "shift quantity must be whole number of bytes"
656 .endif
657 vext.8 \vd, \vz, \vn, #16 - (\nbit >> 3)
658.endm
659
660.macro vshr128 vd, vn, nbit, vz=q15
661 // Set VD to VN shifted right by NBIT. Assume VZ (default q15) is
662 // all-bits-zero. NBIT must be a multiple of 8.
663 .if \nbit&3 != 0
664 .error "shift quantity must be whole number of bytes"
665 .endif
666 vext.8 \vd, \vn, \vz, #\nbit >> 3
667.endm
668
3709fba5
MW
669.macro vrol128 vd, vn, nbit
670 // Set VD to VN rotated left by NBIT. NBIT must be a multiple of 8.
671 .if \nbit&3 != 0
672 .error "shift quantity must be whole number of bytes"
673 .endif
674 vext.8 \vd, \vn, \vn, #16 - (\nbit >> 3)
675.endm
676
677.macro vror128 vd, vn, nbit
678 // Set VD to VN shifted right by NBIT. NBIT must be a multiple of 8.
679 .if \nbit&3 != 0
680 .error "shift quantity must be whole number of bytes"
681 .endif
682 vext.8 \vd, \vn, \vn, #\nbit >> 3
683.endm
684
43ea7558
MW
685// Apply decoration decor to register name reg.
686#define _REGFORM(reg, decor) _GLUE(_REGFORM_, reg)(decor)
687
688// Internal macros: `_REGFORM_r(decor)' applies decoration decor to register
689// name r.
690
4ff9d579
MW
691#define _REGFORM_nil(decor) nil
692
43ea7558
MW
693#define _REGFORM_s0(decor) _DECOR(s, decor, 0)
694#define _REGFORM_s1(decor) _DECOR(s, decor, 1)
695#define _REGFORM_s2(decor) _DECOR(s, decor, 2)
696#define _REGFORM_s3(decor) _DECOR(s, decor, 3)
697#define _REGFORM_s4(decor) _DECOR(s, decor, 4)
698#define _REGFORM_s5(decor) _DECOR(s, decor, 5)
699#define _REGFORM_s6(decor) _DECOR(s, decor, 6)
700#define _REGFORM_s7(decor) _DECOR(s, decor, 7)
701#define _REGFORM_s8(decor) _DECOR(s, decor, 8)
702#define _REGFORM_s9(decor) _DECOR(s, decor, 9)
703#define _REGFORM_s10(decor) _DECOR(s, decor, 10)
704#define _REGFORM_s11(decor) _DECOR(s, decor, 11)
705#define _REGFORM_s12(decor) _DECOR(s, decor, 12)
706#define _REGFORM_s13(decor) _DECOR(s, decor, 13)
707#define _REGFORM_s14(decor) _DECOR(s, decor, 14)
708#define _REGFORM_s15(decor) _DECOR(s, decor, 15)
709#define _REGFORM_s16(decor) _DECOR(s, decor, 16)
710#define _REGFORM_s17(decor) _DECOR(s, decor, 17)
711#define _REGFORM_s18(decor) _DECOR(s, decor, 18)
712#define _REGFORM_s19(decor) _DECOR(s, decor, 19)
713#define _REGFORM_s20(decor) _DECOR(s, decor, 20)
714#define _REGFORM_s21(decor) _DECOR(s, decor, 21)
715#define _REGFORM_s22(decor) _DECOR(s, decor, 22)
716#define _REGFORM_s23(decor) _DECOR(s, decor, 23)
717#define _REGFORM_s24(decor) _DECOR(s, decor, 24)
718#define _REGFORM_s25(decor) _DECOR(s, decor, 25)
719#define _REGFORM_s26(decor) _DECOR(s, decor, 26)
720#define _REGFORM_s27(decor) _DECOR(s, decor, 27)
721#define _REGFORM_s28(decor) _DECOR(s, decor, 28)
722#define _REGFORM_s29(decor) _DECOR(s, decor, 29)
723#define _REGFORM_s30(decor) _DECOR(s, decor, 30)
724#define _REGFORM_s31(decor) _DECOR(s, decor, 31)
725
726#define _REGFORM_d0(decor) _DECOR(d, decor, 0)
727#define _REGFORM_d1(decor) _DECOR(d, decor, 1)
728#define _REGFORM_d2(decor) _DECOR(d, decor, 2)
729#define _REGFORM_d3(decor) _DECOR(d, decor, 3)
730#define _REGFORM_d4(decor) _DECOR(d, decor, 4)
731#define _REGFORM_d5(decor) _DECOR(d, decor, 5)
732#define _REGFORM_d6(decor) _DECOR(d, decor, 6)
733#define _REGFORM_d7(decor) _DECOR(d, decor, 7)
734#define _REGFORM_d8(decor) _DECOR(d, decor, 8)
735#define _REGFORM_d9(decor) _DECOR(d, decor, 9)
736#define _REGFORM_d10(decor) _DECOR(d, decor, 10)
737#define _REGFORM_d11(decor) _DECOR(d, decor, 11)
738#define _REGFORM_d12(decor) _DECOR(d, decor, 12)
739#define _REGFORM_d13(decor) _DECOR(d, decor, 13)
740#define _REGFORM_d14(decor) _DECOR(d, decor, 14)
741#define _REGFORM_d15(decor) _DECOR(d, decor, 15)
742#define _REGFORM_d16(decor) _DECOR(d, decor, 16)
743#define _REGFORM_d17(decor) _DECOR(d, decor, 17)
744#define _REGFORM_d18(decor) _DECOR(d, decor, 18)
745#define _REGFORM_d19(decor) _DECOR(d, decor, 19)
746#define _REGFORM_d20(decor) _DECOR(d, decor, 20)
747#define _REGFORM_d21(decor) _DECOR(d, decor, 21)
748#define _REGFORM_d22(decor) _DECOR(d, decor, 22)
749#define _REGFORM_d23(decor) _DECOR(d, decor, 23)
750#define _REGFORM_d24(decor) _DECOR(d, decor, 24)
751#define _REGFORM_d25(decor) _DECOR(d, decor, 25)
752#define _REGFORM_d26(decor) _DECOR(d, decor, 26)
753#define _REGFORM_d27(decor) _DECOR(d, decor, 27)
754#define _REGFORM_d28(decor) _DECOR(d, decor, 28)
755#define _REGFORM_d29(decor) _DECOR(d, decor, 29)
756#define _REGFORM_d30(decor) _DECOR(d, decor, 30)
757#define _REGFORM_d31(decor) _DECOR(d, decor, 31)
758
759#define _REGFORM_q0(decor) _DECOR(q, decor, 0)
760#define _REGFORM_q1(decor) _DECOR(q, decor, 1)
761#define _REGFORM_q2(decor) _DECOR(q, decor, 2)
762#define _REGFORM_q3(decor) _DECOR(q, decor, 3)
763#define _REGFORM_q4(decor) _DECOR(q, decor, 4)
764#define _REGFORM_q5(decor) _DECOR(q, decor, 5)
765#define _REGFORM_q6(decor) _DECOR(q, decor, 6)
766#define _REGFORM_q7(decor) _DECOR(q, decor, 7)
767#define _REGFORM_q8(decor) _DECOR(q, decor, 8)
768#define _REGFORM_q9(decor) _DECOR(q, decor, 9)
769#define _REGFORM_q10(decor) _DECOR(q, decor, 10)
770#define _REGFORM_q11(decor) _DECOR(q, decor, 11)
771#define _REGFORM_q12(decor) _DECOR(q, decor, 12)
772#define _REGFORM_q13(decor) _DECOR(q, decor, 13)
773#define _REGFORM_q14(decor) _DECOR(q, decor, 14)
774#define _REGFORM_q15(decor) _DECOR(q, decor, 15)
775
776// `_LOPART(n)' and `_HIPART(n)' return the numbers of the register halves of
777// register n, i.e., 2*n and 2*n + 1 respectively.
778#define _LOPART(n) _GLUE(_LOPART_, n)
779#define _HIPART(n) _GLUE(_HIPART_, n)
780
781// Internal macros: `_LOPART_n' and `_HIPART_n' return the numbers of the
782// register halves of register n, i.e., 2*n and 2*n + 1 respectively.
783
784#define _LOPART_0 0
785#define _HIPART_0 1
786#define _LOPART_1 2
787#define _HIPART_1 3
788#define _LOPART_2 4
789#define _HIPART_2 5
790#define _LOPART_3 6
791#define _HIPART_3 7
792#define _LOPART_4 8
793#define _HIPART_4 9
794#define _LOPART_5 10
795#define _HIPART_5 11
796#define _LOPART_6 12
797#define _HIPART_6 13
798#define _LOPART_7 14
799#define _HIPART_7 15
800#define _LOPART_8 16
801#define _HIPART_8 17
802#define _LOPART_9 18
803#define _HIPART_9 19
804#define _LOPART_10 20
805#define _HIPART_10 21
806#define _LOPART_11 22
807#define _HIPART_11 23
808#define _LOPART_12 24
809#define _HIPART_12 25
810#define _LOPART_13 26
811#define _HIPART_13 27
812#define _LOPART_14 28
813#define _HIPART_14 29
814#define _LOPART_15 30
815#define _HIPART_15 31
816
817// Return the register number of the pair containing register n, i.e.,
818// floor(n/2).
819#define _PAIR(n) _GLUE(_PAIR_, n)
820
821// Internal macros: `_PAIR_n' returns the register number of the pair
822// containing register n, i.e., floor(n/2).
823#define _PAIR_0 0
824#define _PAIR_1 0
825#define _PAIR_2 1
826#define _PAIR_3 1
827#define _PAIR_4 2
828#define _PAIR_5 2
829#define _PAIR_6 3
830#define _PAIR_7 3
831#define _PAIR_8 4
832#define _PAIR_9 4
833#define _PAIR_10 5
834#define _PAIR_11 5
835#define _PAIR_12 6
836#define _PAIR_13 6
837#define _PAIR_14 7
838#define _PAIR_15 7
839#define _PAIR_16 8
840#define _PAIR_17 8
841#define _PAIR_18 9
842#define _PAIR_19 9
843#define _PAIR_20 10
844#define _PAIR_21 10
845#define _PAIR_22 11
846#define _PAIR_23 11
847#define _PAIR_24 12
848#define _PAIR_25 12
849#define _PAIR_26 13
850#define _PAIR_27 13
851#define _PAIR_28 14
852#define _PAIR_29 14
853#define _PAIR_30 15
854#define _PAIR_31 15
855
856// Apply decoration decor to register number n of type ty. Decorations are
857// as follows.
858//
859// decor types meaning
860// Q s, d the NEON qN register containing this one
861// D s the NEON dN register containing this one
862// D0 q the low 64-bit half of this one
863// D1 q the high 64-bit half of this one
864// S0 d, q the first 32-bit piece of this one
865// S1 d, q the second 32-bit piece of this one
866// S2 q the third 32-bit piece of this one
867// S3 q the fourth 32-bit piece of this one
868// Bn q the nth byte of this register, as a scalar
869// Hn q the nth halfword of this register, as a scalar
870// Wn q the nth word of this register, as a scalar
871#define _DECOR(ty, decor, n) _DECOR_##ty##_##decor(n)
872
873// Internal macros: `_DECOR_ty_decor(n)' applies decoration decor to register
874// number n of type ty.
875
876#define _DECOR_s_Q(n) GLUE(q, _PAIR(_PAIR(n)))
877#define _DECOR_s_D(n) GLUE(d, _PAIR(n))
878
879#define _DECOR_d_Q(n) GLUE(q, _PAIR(n))
880#define _DECOR_d_S0(n) GLUE(s, _LOPART(n))
881#define _DECOR_d_S1(n) GLUE(s, _LOPART(n))
882
883#define _DECOR_q_D0(n) GLUE(d, _LOPART(n))
884#define _DECOR_q_D1(n) GLUE(d, _HIPART(n))
885#define _DECOR_q_S0(n) GLUE(s, _LOPART(_LOPART(n)))
886#define _DECOR_q_S1(n) GLUE(s, _HIPART(_LOPART(n)))
887#define _DECOR_q_S2(n) GLUE(s, _LOPART(_HIPART(n)))
888#define _DECOR_q_S3(n) GLUE(s, _HIPART(_HIPART(n)))
889#define _DECOR_q_W0(n) GLUE(d, _LOPART(n))[0]
890#define _DECOR_q_W1(n) GLUE(d, _LOPART(n))[1]
891#define _DECOR_q_W2(n) GLUE(d, _HIPART(n))[0]
892#define _DECOR_q_W3(n) GLUE(d, _HIPART(n))[1]
893#define _DECOR_q_H0(n) GLUE(d, _LOPART(n))[0]
894#define _DECOR_q_H1(n) GLUE(d, _LOPART(n))[1]
895#define _DECOR_q_H2(n) GLUE(d, _LOPART(n))[2]
896#define _DECOR_q_H3(n) GLUE(d, _LOPART(n))[3]
897#define _DECOR_q_H4(n) GLUE(d, _HIPART(n))[0]
898#define _DECOR_q_H5(n) GLUE(d, _HIPART(n))[1]
899#define _DECOR_q_H6(n) GLUE(d, _HIPART(n))[2]
900#define _DECOR_q_H7(n) GLUE(d, _HIPART(n))[3]
901#define _DECOR_q_B0(n) GLUE(d, _LOPART(n))[0]
902#define _DECOR_q_B1(n) GLUE(d, _LOPART(n))[1]
903#define _DECOR_q_B2(n) GLUE(d, _LOPART(n))[2]
904#define _DECOR_q_B3(n) GLUE(d, _LOPART(n))[3]
905#define _DECOR_q_B4(n) GLUE(d, _LOPART(n))[4]
906#define _DECOR_q_B5(n) GLUE(d, _LOPART(n))[5]
907#define _DECOR_q_B6(n) GLUE(d, _LOPART(n))[6]
908#define _DECOR_q_B7(n) GLUE(d, _LOPART(n))[7]
909#define _DECOR_q_B8(n) GLUE(d, _HIPART(n))[0]
910#define _DECOR_q_B9(n) GLUE(d, _HIPART(n))[1]
911#define _DECOR_q_B10(n) GLUE(d, _HIPART(n))[2]
912#define _DECOR_q_B11(n) GLUE(d, _HIPART(n))[3]
913#define _DECOR_q_B12(n) GLUE(d, _HIPART(n))[4]
914#define _DECOR_q_B13(n) GLUE(d, _HIPART(n))[5]
915#define _DECOR_q_B14(n) GLUE(d, _HIPART(n))[6]
916#define _DECOR_q_B15(n) GLUE(d, _HIPART(n))[7]
917
918// Macros for navigating the NEON register hierarchy.
919#define S0(reg) _REGFORM(reg, S0)
920#define S1(reg) _REGFORM(reg, S1)
921#define S2(reg) _REGFORM(reg, S2)
922#define S3(reg) _REGFORM(reg, S3)
923#define D(reg) _REGFORM(reg, D)
924#define D0(reg) _REGFORM(reg, D0)
925#define D1(reg) _REGFORM(reg, D1)
926#define Q(reg) _REGFORM(reg, Q)
927
928// Macros for indexing quadword registers.
929#define QB(reg, i) _REGFORM(reg, B##i)
930#define QH(reg, i) _REGFORM(reg, H##i)
931#define QW(reg, i) _REGFORM(reg, W##i)
932
933// Macros for converting vldm/vstm ranges.
934#define QQ(qlo, qhi) D0(qlo)-D1(qhi)
935
0923a413 936// Stack management and unwinding.
42c44b27 937.macro setfp fp=r11, offset=0
0923a413
MW
938 .if \offset == 0
939 mov \fp, sp
940 .setfp \fp, sp
941 .else
942 add \fp, sp, #\offset
943 .setfp \fp, sp, #\offset
944 .endif
945 .macro dropfp; _dropfp \fp, \offset; .endm
946 .L$_frameptr_p = -1
947.endm
948
cdc153a5 949.macro _dropfp fp, offset=0
0923a413
MW
950 .if \offset == 0
951 mov sp, \fp
952 .else
953 sub sp, \fp, #\offset
954 .endif
955 .purgem dropfp
956 .L$_frameptr_p = 0
957.endm
958
959.macro stalloc n
960 sub sp, sp, #\n
961 .pad #\n
962.endm
963
964.macro stfree n
965 add sp, sp, #\n
966 .pad #-\n
967.endm
968
969.macro pushreg rr:vararg
1f1fd884 970 push {\rr}
0923a413
MW
971 .save {\rr}
972.endm
973
974.macro popreg rr:vararg
1f1fd884 975 pop {\rr}
0923a413
MW
976.endm
977
978.macro pushvfp rr:vararg
979 vstmdb sp!, {\rr}
980 .vsave {\rr}
981.endm
982
983.macro popvfp rr:vararg
984 vldmia sp!, {\rr}
985.endm
986
987.macro endprologue
988.endm
989
990// No need for prologue markers on ARM.
991#define FUNC_POSTHOOK(_) .L$_prologue_p = -1
992
61bd904b
MW
993#endif
994
995///--------------------------------------------------------------------------
e492db88
MW
996/// AArch64-specific hacking.
997
998#if CPUFAM_ARM64
999
1000// Set the function hooks.
1001#define FUNC_PREHOOK(_) .balign 4
1002#define FUNC_POSTHOOK(_) .cfi_startproc; .L$_prologue_p = -1
1003#define ENDFUNC_HOOK(_) .cfi_endproc
1004
1005// Call external subroutine at ADDR, possibly via PLT.
1006.macro callext addr
1007 bl \addr
1008.endm
1009
1010// Load address of external symbol ADDR into REG.
1011.macro leaext reg, addr
1012#if WANT_PIC
1013 adrp \reg, :got:\addr
1014 ldr \reg, [\reg, #:got_lo12:\addr]
1015#else
1016 adrp \reg, \addr
1017 add \reg, \reg, #:lo12:\addr
1018#endif
1019.endm
1020
1a031196
MW
1021.macro vzero vz=v31
1022 // Set VZ (default v31) to zero.
1023 dup \vz\().4s, wzr
1024.endm
1025
1026.macro vshl128 vd, vn, nbit, vz=v31
1027 // Set VD to VN shifted left by NBIT. Assume VZ (default v31) is
1028 // all-bits-zero. NBIT must be a multiple of 8.
1029 .if \nbit&3 != 0
1030 .error "shift quantity must be whole number of bytes"
1031 .endif
1032 ext \vd\().16b, \vz\().16b, \vn\().16b, #16 - (\nbit >> 3)
1033.endm
1034
1035.macro vshr128 vd, vn, nbit, vz=v31
1036 // Set VD to VN shifted right by NBIT. Assume VZ (default v31) is
1037 // all-bits-zero. NBIT must be a multiple of 8.
1038 .if \nbit&3 != 0
1039 .error "shift quantity must be whole number of bytes"
1040 .endif
1041 ext \vd\().16b, \vn\().16b, \vz\().16b, #\nbit >> 3
1042.endm
1043
e492db88 1044// Stack management and unwinding.
42c44b27 1045.macro setfp fp=x29, offset=0
e492db88
MW
1046 // If you're just going through the motions with a fixed-size stack frame,
1047 // then you want to say `add x29, sp, #OFFSET' directly, which will avoid
1048 // pointlessly restoring sp later.
1049 .if \offset == 0
1050 mov \fp, sp
1051 .cfi_def_cfa_register \fp
1052 .else
1053 add \fp, sp, #\offset
1054 .cfi_def_cfa_register \fp
1055 .cfi_adjust_cfa_offset -\offset
1056 .endif
1057 .macro dropfp; _dropfp \fp, \offset; .endm
1058 .L$_frameptr_p = -1
1059.endm
1060
cdc153a5 1061.macro _dropfp fp, offset=0
e492db88
MW
1062 .if \offset == 0
1063 mov sp, \fp
1064 .cfi_def_cfa_register sp
1065 .else
1066 sub sp, \fp, #\offset
1067 .cfi_def_cfa_register sp
1068 .cfi_adjust_cfa_offset +\offset
1069 .endif
1070 .purgem dropfp
1071 .L$_frameptr_p = 0
1072.endm
1073
1074.macro stalloc n
1075 sub sp, sp, #\n
1076 .cfi_adjust_cfa_offset +\n
1077.endm
1078
1079.macro stfree n
1080 add sp, sp, #\n
1081 .cfi_adjust_cfa_offset -\n
1082.endm
1083
4bf3072e
MW
1084.macro pushreg x, y=nil
1085 .ifeqs "\y", "nil"
e492db88
MW
1086 str \x, [sp, #-16]!
1087 .cfi_adjust_cfa_offset +16
1088 .cfi_rel_offset \x, 0
1089 .else
1090 stp \x, \y, [sp, #-16]!
1091 .cfi_adjust_cfa_offset +16
1092 .cfi_rel_offset \x, 0
1093 .cfi_rel_offset \y, 8
1094 .endif
1095.endm
1096
4bf3072e
MW
1097.macro popreg x, y=nil
1098 .ifeqs "\y", "nil"
e492db88
MW
1099 ldr \x, [sp], #16
1100 .cfi_restore \x
1101 .cfi_adjust_cfa_offset -16
1102 .else
1103 ldp \x, \y, [sp], #16
1104 .cfi_restore \x
1105 .cfi_restore \y
1106 .cfi_adjust_cfa_offset -16
1107 .endif
1108.endm
1109
4bf3072e
MW
1110.macro savereg x, y, z=nil
1111 .ifeqs "\z", "nil"
1112 str \x, [sp, \y]
e492db88
MW
1113 .cfi_rel_offset \x, \y
1114 .else
1115 stp \x, \y, [sp, #\z]
1116 .cfi_rel_offset \x, \z
1117 .cfi_rel_offset \y, \z + 8
1118 .endif
1119.endm
1120
4bf3072e
MW
1121.macro rstrreg x, y, z=nil
1122 .ifeqs "\z", "nil"
1123 ldr \x, [sp, \y]
e492db88
MW
1124 .cfi_restore \x
1125 .else
1126 ldp \x, \y, [sp, #\z]
1127 .cfi_restore \x
1128 .cfi_restore \y
1129 .endif
1130.endm
1131
1132.macro endprologue
1133.endm
1134
5f49478b
MW
1135// cmov RD, RN, CC: set RD to RN if CC is satisfied, otherwise do nothing
1136.macro cmov rd, rn, cc
1137 csel \rd, \rn, \rd, \cc
1138.endm
1139
483edf69
MW
1140// Notational improvement: write `csel.CC' etc., rather than `csel ..., CC'.
1141#define _COND(_) \
1142 _(eq) _(ne) _(cs) _(cc) _(vs) _(vc) _(mi) _(pl) \
1143 _(ge) _(lt) _(gt) _(le) _(hi) _(ls) _(al) _(nv) \
1144 _(hs) _(lo)
1145#define _INST(_) \
1146 _(ccmp) _(ccmn) \
5f49478b 1147 _(csel) _(cmov) \
483edf69
MW
1148 _(csinc) _(cinc) _(cset) \
1149 _(csneg) _(cneg) \
1150 _(csinv) _(cinv) _(csetm)
1151#define _CONDVAR(cc) _definstvar cc;
1152#define _INSTVARS(inst) \
1153 .macro _definstvar cc; \
1154 .macro inst.\cc args:vararg; inst \args, \cc; .endm; \
1155 .endm; \
1156 _COND(_CONDVAR); \
1157 .purgem _definstvar;
1158 _INST(_INSTVARS)
1159#undef _COND
1160#undef _INST
1161#undef _CONDVAR
1162#undef _INSTVARS
1163
1164// Flag bits for `ccmp' and friends.
1165#define CCMP_N 8
1166#define CCMP_Z 4
1167#define CCMP_C 2
1168#define CCMP_V 1
1169
1170// Flag settings for satisfying conditions.
1171#define CCMP_MI CCMP_N
1172#define CCMP_PL 0
1173#define CCMP_EQ CCMP_Z
1174#define CCMP_NE 0
1175#define CCMP_CS CCMP_C
1176#define CCMP_HS CCMP_C
1177#define CCMP_CC 0
1178#define CCMP_LO 0
1179#define CCMP_VS CCMP_V
1180#define CCMP_VC 0
1181#define CCMP_HI CCMP_C
1182#define CCMP_LS 0
1183#define CCMP_LT CCMP_N
1184#define CCMP_GE 0
1185#define CCMP_LE CCMP_N
1186#define CCMP_GT 0
1187
e492db88
MW
1188#endif
1189
1190///--------------------------------------------------------------------------
1a0c09c4
MW
1191/// Final stuff.
1192
1193// Default values for the various hooks.
1194#ifndef FUNC_PREHOOK
1e5664a6 1195# define FUNC_PREHOOK(_)
1a0c09c4
MW
1196#endif
1197#ifndef FUNC_POSTHOOK
1e5664a6 1198# define FUNC_POSTHOOK(_)
1a0c09c4
MW
1199#endif
1200#ifndef ENDFUNC_HOOK
1e5664a6 1201# define ENDFUNC_HOOK(_)
1a0c09c4
MW
1202#endif
1203
b0c2da14
MW
1204// Section selection.
1205#ifndef TEXT
1206# define TEXT .text .L$_subsec
1207#endif
1208#ifndef RODATA
1209# define RODATA TEXT
1210#endif
1211#ifndef DATA
1212# define DATA .data
1213#endif
1214
1215// Symbol decoration.
1a0c09c4 1216#ifndef F
772740dd
MW
1217# ifdef SYM_USCORE
1218# define F(name) _##name
1219# else
1220# define F(name) name
1221# endif
1a0c09c4
MW
1222#endif
1223
1224#ifndef TYPE_FUNC
1225# define TYPE_FUNC(name)
1226#endif
6ae7b854
MW
1227#ifndef TYPE_OBJ
1228# define TYPE_OBJ(name)
1229#endif
1a0c09c4
MW
1230#ifndef SIZE_OBJ
1231# define SIZE_OBJ(name)
1232#endif
1233
1234///----- That's all, folks --------------------------------------------------
8ce88ea5
MW
1235
1236#endif