xref: /aosp_15_r20/external/arm-optimized-routines/string/arm/asmdefs.h (revision 412f47f9e737e10ed5cc46ec6a8d7fa2264f8a14)
1*412f47f9SXin Li /*
2*412f47f9SXin Li  * Macros for asm code.  Arm version.
3*412f47f9SXin Li  *
4*412f47f9SXin Li  * Copyright (c) 2019-2022, Arm Limited.
5*412f47f9SXin Li  * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6*412f47f9SXin Li  */
7*412f47f9SXin Li 
8*412f47f9SXin Li #ifndef _ASMDEFS_H
9*412f47f9SXin Li #define _ASMDEFS_H
10*412f47f9SXin Li 
11*412f47f9SXin Li /* Check whether leaf function PAC signing has been requested in the
12*412f47f9SXin Li    -mbranch-protect compile-time option.  */
13*412f47f9SXin Li #define LEAF_PROTECT_BIT 2
14*412f47f9SXin Li 
15*412f47f9SXin Li #ifdef __ARM_FEATURE_PAC_DEFAULT
16*412f47f9SXin Li # define HAVE_PAC_LEAF \
17*412f47f9SXin Li 	((__ARM_FEATURE_PAC_DEFAULT & (1 << LEAF_PROTECT_BIT)) && 1)
18*412f47f9SXin Li #else
19*412f47f9SXin Li # define HAVE_PAC_LEAF 0
20*412f47f9SXin Li #endif
21*412f47f9SXin Li 
22*412f47f9SXin Li /* Provide default parameters for PAC-code handling in leaf-functions.  */
23*412f47f9SXin Li #if HAVE_PAC_LEAF
24*412f47f9SXin Li # ifndef PAC_LEAF_PUSH_IP
25*412f47f9SXin Li #  define PAC_LEAF_PUSH_IP 1
26*412f47f9SXin Li # endif
27*412f47f9SXin Li #else /* !HAVE_PAC_LEAF */
28*412f47f9SXin Li # undef PAC_LEAF_PUSH_IP
29*412f47f9SXin Li # define PAC_LEAF_PUSH_IP 0
30*412f47f9SXin Li #endif /* HAVE_PAC_LEAF */
31*412f47f9SXin Li 
32*412f47f9SXin Li #define STACK_ALIGN_ENFORCE 0
33*412f47f9SXin Li 
34*412f47f9SXin Li /******************************************************************************
35*412f47f9SXin Li * Implementation of the prologue and epilogue assembler macros and their
36*412f47f9SXin Li * associated helper functions.
37*412f47f9SXin Li *
38*412f47f9SXin Li * These functions add support for the following:
39*412f47f9SXin Li *
40*412f47f9SXin Li * - M-profile branch target identification (BTI) landing-pads when compiled
41*412f47f9SXin Li *   with `-mbranch-protection=bti'.
42*412f47f9SXin Li * - PAC-signing and verification instructions, depending on hardware support
43*412f47f9SXin Li *   and whether the PAC-signing of leaf functions has been requested via the
44*412f47f9SXin Li *   `-mbranch-protection=pac-ret+leaf' compiler argument.
45*412f47f9SXin Li * - 8-byte stack alignment preservation at function entry, defaulting to the
46*412f47f9SXin Li *   value of STACK_ALIGN_ENFORCE.
47*412f47f9SXin Li *
48*412f47f9SXin Li * Notes:
49*412f47f9SXin Li * - Prologue stack alignment is implemented by detecting a push with an odd
50*412f47f9SXin Li *   number of registers and prepending a dummy register to the list.
51*412f47f9SXin Li * - If alignment is attempted on a list containing r0, compilation will result
52*412f47f9SXin Li *   in an error.
53*412f47f9SXin Li * - If alignment is attempted in a list containing r1, r0 will be prepended to
54*412f47f9SXin Li *   the register list and r0 will be restored prior to function return.  for
55*412f47f9SXin Li *   functions with non-void return types, this will result in the corruption of
56*412f47f9SXin Li *   the result register.
57*412f47f9SXin Li * - Stack alignment is enforced via the following helper macro call-chain:
58*412f47f9SXin Li *
59*412f47f9SXin Li *	{prologue|epilogue} ->_align8 -> _preprocess_reglist ->
60*412f47f9SXin Li *		_preprocess_reglist1 -> {_prologue|_epilogue}
61*412f47f9SXin Li *
62*412f47f9SXin Li * - Debug CFI directives are automatically added to prologues and epilogues,
63*412f47f9SXin Li *   assisted by `cfisavelist' and `cfirestorelist', respectively.
64*412f47f9SXin Li *
65*412f47f9SXin Li * Arguments:
66*412f47f9SXin Li * prologue
67*412f47f9SXin Li * --------
68*412f47f9SXin Li * - first	- If `last' specified, this serves as start of general-purpose
69*412f47f9SXin Li *		  register (GPR) range to push onto stack, otherwise represents
70*412f47f9SXin Li *		  single GPR to push onto stack.  If omitted, no GPRs pushed
71*412f47f9SXin Li *		  onto stack at prologue.
72*412f47f9SXin Li * - last	- If given, specifies inclusive upper-bound of GPR range.
73*412f47f9SXin Li * - push_ip	- Determines whether IP register is to be pushed to stack at
74*412f47f9SXin Li *		  prologue.  When pac-signing is requested, this holds the
75*412f47f9SXin Li *		  the pac-key.  Either 1 or 0 to push or not push, respectively.
76*412f47f9SXin Li *		  Default behavior: Set to value of PAC_LEAF_PUSH_IP macro.
77*412f47f9SXin Li * - push_lr	- Determines whether to push lr to the stack on function entry.
78*412f47f9SXin Li *		  Either 1 or 0  to push or not push, respectively.
79*412f47f9SXin Li * - align8	- Whether to enforce alignment. Either 1 or 0, with 1 requesting
80*412f47f9SXin Li *		  alignment.
81*412f47f9SXin Li *
82*412f47f9SXin Li * epilogue
83*412f47f9SXin Li * --------
84*412f47f9SXin Li *   The epilogue should be called passing the same arguments as those passed to
85*412f47f9SXin Li *   the prologue to ensure the stack is not corrupted on function return.
86*412f47f9SXin Li *
87*412f47f9SXin Li * Usage examples:
88*412f47f9SXin Li *
89*412f47f9SXin Li *   prologue push_ip=1 -> push {ip}
90*412f47f9SXin Li *   epilogue push_ip=1, align8=1 -> pop {r2, ip}
91*412f47f9SXin Li *   prologue push_ip=1, push_lr=1 -> push {ip, lr}
92*412f47f9SXin Li *   epilogue 1 -> pop {r1}
93*412f47f9SXin Li *   prologue 1, align8=1 -> push {r0, r1}
94*412f47f9SXin Li *   epilogue 1, push_ip=1 -> pop {r1, ip}
95*412f47f9SXin Li *   prologue 1, 4 -> push {r1-r4}
96*412f47f9SXin Li *   epilogue 1, 4 push_ip=1 -> pop {r1-r4, ip}
97*412f47f9SXin Li *
98*412f47f9SXin Li ******************************************************************************/
99*412f47f9SXin Li 
100*412f47f9SXin Li /* Emit .cfi_restore directives for a consecutive sequence of registers.  */
101*412f47f9SXin Li 	.macro cfirestorelist first, last
102*412f47f9SXin Li 	.cfi_restore \last
103*412f47f9SXin Li 	.if \last-\first
104*412f47f9SXin Li 	 cfirestorelist \first, \last-1
105*412f47f9SXin Li 	.endif
106*412f47f9SXin Li 	.endm
107*412f47f9SXin Li 
108*412f47f9SXin Li /* Emit .cfi_offset directives for a consecutive sequence of registers.  */
109*412f47f9SXin Li 	.macro cfisavelist first, last, index=1
110*412f47f9SXin Li 	.cfi_offset \last, -4*(\index)
111*412f47f9SXin Li 	.if \last-\first
112*412f47f9SXin Li 	 cfisavelist \first, \last-1, \index+1
113*412f47f9SXin Li 	.endif
114*412f47f9SXin Li 	.endm
115*412f47f9SXin Li 
116*412f47f9SXin Li .macro _prologue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0
117*412f47f9SXin Li 	.if \push_ip & 1 != \push_ip
118*412f47f9SXin Li 	 .error "push_ip may be either 0 or 1"
119*412f47f9SXin Li 	.endif
120*412f47f9SXin Li 	.if \push_lr & 1 != \push_lr
121*412f47f9SXin Li 	 .error "push_lr may be either 0 or 1"
122*412f47f9SXin Li 	.endif
123*412f47f9SXin Li 	.if \first != -1
124*412f47f9SXin Li 	 .if \last == -1
125*412f47f9SXin Li 	  /* Upper-bound not provided: Set upper = lower.  */
126*412f47f9SXin Li 	  _prologue \first, \first, \push_ip, \push_lr
127*412f47f9SXin Li 	  .exitm
128*412f47f9SXin Li 	 .endif
129*412f47f9SXin Li 	.endif
130*412f47f9SXin Li #if HAVE_PAC_LEAF
131*412f47f9SXin Li # if __ARM_FEATURE_BTI_DEFAULT
132*412f47f9SXin Li 	pacbti	ip, lr, sp
133*412f47f9SXin Li # else
134*412f47f9SXin Li 	pac	ip, lr, sp
135*412f47f9SXin Li # endif /* __ARM_FEATURE_BTI_DEFAULT */
136*412f47f9SXin Li 	.cfi_register 143, 12
137*412f47f9SXin Li #else
138*412f47f9SXin Li # if __ARM_FEATURE_BTI_DEFAULT
139*412f47f9SXin Li 	bti
140*412f47f9SXin Li # endif /* __ARM_FEATURE_BTI_DEFAULT */
141*412f47f9SXin Li #endif /* HAVE_PAC_LEAF */
142*412f47f9SXin Li 	.if \first != -1
143*412f47f9SXin Li 	 .if \last != \first
144*412f47f9SXin Li 	  .if \last >= 13
145*412f47f9SXin Li 	.error "SP cannot be in the save list"
146*412f47f9SXin Li 	  .endif
147*412f47f9SXin Li 	  .if \push_ip
148*412f47f9SXin Li 	   .if \push_lr
149*412f47f9SXin Li 	/* Case 1: push register range, ip and lr registers.  */
150*412f47f9SXin Li 	push {r\first-r\last, ip, lr}
151*412f47f9SXin Li 	.cfi_adjust_cfa_offset ((\last-\first)+3)*4
152*412f47f9SXin Li 	.cfi_offset 14, -4
153*412f47f9SXin Li 	.cfi_offset 143, -8
154*412f47f9SXin Li 	cfisavelist \first, \last, 3
155*412f47f9SXin Li 	   .else // !\push_lr
156*412f47f9SXin Li 	/* Case 2: push register range and ip register.  */
157*412f47f9SXin Li 	push {r\first-r\last, ip}
158*412f47f9SXin Li 	.cfi_adjust_cfa_offset ((\last-\first)+2)*4
159*412f47f9SXin Li 	.cfi_offset 143, -4
160*412f47f9SXin Li 	cfisavelist \first, \last, 2
161*412f47f9SXin Li 	   .endif
162*412f47f9SXin Li 	  .else // !\push_ip
163*412f47f9SXin Li 	   .if \push_lr
164*412f47f9SXin Li 	/* Case 3: push register range and lr register.  */
165*412f47f9SXin Li 	push {r\first-r\last, lr}
166*412f47f9SXin Li 	.cfi_adjust_cfa_offset ((\last-\first)+2)*4
167*412f47f9SXin Li 	.cfi_offset 14, -4
168*412f47f9SXin Li 	cfisavelist \first, \last, 2
169*412f47f9SXin Li 	   .else // !\push_lr
170*412f47f9SXin Li 	/* Case 4: push register range.  */
171*412f47f9SXin Li 	push {r\first-r\last}
172*412f47f9SXin Li 	.cfi_adjust_cfa_offset ((\last-\first)+1)*4
173*412f47f9SXin Li 	cfisavelist \first, \last, 1
174*412f47f9SXin Li 	   .endif
175*412f47f9SXin Li 	  .endif
176*412f47f9SXin Li 	 .else // \last == \first
177*412f47f9SXin Li 	  .if \push_ip
178*412f47f9SXin Li 	   .if \push_lr
179*412f47f9SXin Li 	/* Case 5: push single GP register plus ip and lr registers.  */
180*412f47f9SXin Li 	push {r\first, ip, lr}
181*412f47f9SXin Li 	.cfi_adjust_cfa_offset 12
182*412f47f9SXin Li 	.cfi_offset 14, -4
183*412f47f9SXin Li 	.cfi_offset 143, -8
184*412f47f9SXin Li         cfisavelist \first, \first, 3
185*412f47f9SXin Li 	   .else // !\push_lr
186*412f47f9SXin Li 	/* Case 6: push single GP register plus ip register.  */
187*412f47f9SXin Li 	push {r\first, ip}
188*412f47f9SXin Li 	.cfi_adjust_cfa_offset 8
189*412f47f9SXin Li 	.cfi_offset 143, -4
190*412f47f9SXin Li         cfisavelist \first, \first, 2
191*412f47f9SXin Li 	   .endif
192*412f47f9SXin Li 	  .else // !\push_ip
193*412f47f9SXin Li 	   .if \push_lr
194*412f47f9SXin Li 	/* Case 7: push single GP register plus lr register.  */
195*412f47f9SXin Li 	push {r\first, lr}
196*412f47f9SXin Li 	.cfi_adjust_cfa_offset 8
197*412f47f9SXin Li 	.cfi_offset 14, -4
198*412f47f9SXin Li 	cfisavelist \first, \first, 2
199*412f47f9SXin Li 	   .else // !\push_lr
200*412f47f9SXin Li 	/* Case 8: push single GP register.  */
201*412f47f9SXin Li 	push {r\first}
202*412f47f9SXin Li 	.cfi_adjust_cfa_offset 4
203*412f47f9SXin Li 	cfisavelist \first, \first, 1
204*412f47f9SXin Li 	   .endif
205*412f47f9SXin Li 	  .endif
206*412f47f9SXin Li 	 .endif
207*412f47f9SXin Li 	.else // \first == -1
208*412f47f9SXin Li 	 .if \push_ip
209*412f47f9SXin Li 	  .if \push_lr
210*412f47f9SXin Li 	/* Case 9: push ip and lr registers.  */
211*412f47f9SXin Li 	push {ip, lr}
212*412f47f9SXin Li 	.cfi_adjust_cfa_offset 8
213*412f47f9SXin Li 	.cfi_offset 14, -4
214*412f47f9SXin Li 	.cfi_offset 143, -8
215*412f47f9SXin Li 	  .else // !\push_lr
216*412f47f9SXin Li 	/* Case 10: push ip register.  */
217*412f47f9SXin Li 	push {ip}
218*412f47f9SXin Li 	.cfi_adjust_cfa_offset 4
219*412f47f9SXin Li 	.cfi_offset 143, -4
220*412f47f9SXin Li 	  .endif
221*412f47f9SXin Li 	 .else // !\push_ip
222*412f47f9SXin Li           .if \push_lr
223*412f47f9SXin Li 	/* Case 11: push lr register.  */
224*412f47f9SXin Li 	push {lr}
225*412f47f9SXin Li 	.cfi_adjust_cfa_offset 4
226*412f47f9SXin Li 	.cfi_offset 14, -4
227*412f47f9SXin Li           .endif
228*412f47f9SXin Li 	 .endif
229*412f47f9SXin Li 	.endif
230*412f47f9SXin Li .endm
231*412f47f9SXin Li 
232*412f47f9SXin Li .macro _epilogue first=-1, last=-1, push_ip=PAC_LEAF_PUSH_IP, push_lr=0
233*412f47f9SXin Li 	.if \push_ip & 1 != \push_ip
234*412f47f9SXin Li 	 .error "push_ip may be either 0 or 1"
235*412f47f9SXin Li 	.endif
236*412f47f9SXin Li 	.if \push_lr & 1 != \push_lr
237*412f47f9SXin Li 	 .error "push_lr may be either 0 or 1"
238*412f47f9SXin Li 	.endif
239*412f47f9SXin Li 	.if \first != -1
240*412f47f9SXin Li 	 .if \last == -1
241*412f47f9SXin Li 	  /* Upper-bound not provided: Set upper = lower.  */
242*412f47f9SXin Li 	  _epilogue \first, \first, \push_ip, \push_lr
243*412f47f9SXin Li 	  .exitm
244*412f47f9SXin Li 	 .endif
245*412f47f9SXin Li 	 .if \last != \first
246*412f47f9SXin Li 	  .if \last >= 13
247*412f47f9SXin Li 	.error "SP cannot be in the save list"
248*412f47f9SXin Li 	  .endif
249*412f47f9SXin Li 	  .if \push_ip
250*412f47f9SXin Li 	   .if \push_lr
251*412f47f9SXin Li 	/* Case 1: pop register range, ip and lr registers.  */
252*412f47f9SXin Li 	pop {r\first-r\last, ip, lr}
253*412f47f9SXin Li 	.cfi_restore 14
254*412f47f9SXin Li 	.cfi_register 143, 12
255*412f47f9SXin Li 	cfirestorelist \first, \last
256*412f47f9SXin Li 	   .else // !\push_lr
257*412f47f9SXin Li 	/* Case 2: pop register range and ip register.  */
258*412f47f9SXin Li 	pop {r\first-r\last, ip}
259*412f47f9SXin Li 	.cfi_register 143, 12
260*412f47f9SXin Li 	cfirestorelist \first, \last
261*412f47f9SXin Li 	   .endif
262*412f47f9SXin Li 	  .else // !\push_ip
263*412f47f9SXin Li 	   .if \push_lr
264*412f47f9SXin Li 	/* Case 3: pop register range and lr register.  */
265*412f47f9SXin Li 	pop {r\first-r\last, lr}
266*412f47f9SXin Li 	.cfi_restore 14
267*412f47f9SXin Li 	cfirestorelist \first, \last
268*412f47f9SXin Li 	   .else // !\push_lr
269*412f47f9SXin Li 	/* Case 4: pop register range.  */
270*412f47f9SXin Li 	pop {r\first-r\last}
271*412f47f9SXin Li 	cfirestorelist \first, \last
272*412f47f9SXin Li 	   .endif
273*412f47f9SXin Li 	  .endif
274*412f47f9SXin Li 	 .else // \last == \first
275*412f47f9SXin Li 	  .if \push_ip
276*412f47f9SXin Li 	   .if \push_lr
277*412f47f9SXin Li 	/* Case 5: pop single GP register plus ip and lr registers.  */
278*412f47f9SXin Li 	pop {r\first, ip, lr}
279*412f47f9SXin Li 	.cfi_restore 14
280*412f47f9SXin Li 	.cfi_register 143, 12
281*412f47f9SXin Li 	cfirestorelist \first, \first
282*412f47f9SXin Li 	   .else // !\push_lr
283*412f47f9SXin Li 	/* Case 6: pop single GP register plus ip register.  */
284*412f47f9SXin Li 	pop {r\first, ip}
285*412f47f9SXin Li 	.cfi_register 143, 12
286*412f47f9SXin Li 	cfirestorelist \first, \first
287*412f47f9SXin Li 	   .endif
288*412f47f9SXin Li 	  .else // !\push_ip
289*412f47f9SXin Li 	   .if \push_lr
290*412f47f9SXin Li 	/* Case 7: pop single GP register plus lr register.  */
291*412f47f9SXin Li 	pop {r\first, lr}
292*412f47f9SXin Li 	.cfi_restore 14
293*412f47f9SXin Li 	cfirestorelist \first, \first
294*412f47f9SXin Li 	   .else // !\push_lr
295*412f47f9SXin Li 	/* Case 8: pop single GP register.  */
296*412f47f9SXin Li 	pop {r\first}
297*412f47f9SXin Li 	cfirestorelist \first, \first
298*412f47f9SXin Li 	   .endif
299*412f47f9SXin Li 	  .endif
300*412f47f9SXin Li 	 .endif
301*412f47f9SXin Li 	.else // \first == -1
302*412f47f9SXin Li 	 .if \push_ip
303*412f47f9SXin Li 	  .if \push_lr
304*412f47f9SXin Li 	/* Case 9: pop ip and lr registers.  */
305*412f47f9SXin Li 	pop {ip, lr}
306*412f47f9SXin Li 	.cfi_restore 14
307*412f47f9SXin Li 	.cfi_register 143, 12
308*412f47f9SXin Li 	  .else // !\push_lr
309*412f47f9SXin Li 	/* Case 10: pop ip register.  */
310*412f47f9SXin Li 	pop {ip}
311*412f47f9SXin Li 	.cfi_register 143, 12
312*412f47f9SXin Li 	  .endif
313*412f47f9SXin Li 	 .else // !\push_ip
314*412f47f9SXin Li           .if \push_lr
315*412f47f9SXin Li 	/* Case 11: pop lr register.  */
316*412f47f9SXin Li 	pop {lr}
317*412f47f9SXin Li 	.cfi_restore 14
318*412f47f9SXin Li           .endif
319*412f47f9SXin Li 	 .endif
320*412f47f9SXin Li 	.endif
321*412f47f9SXin Li #if HAVE_PAC_LEAF
322*412f47f9SXin Li 	aut	ip, lr, sp
323*412f47f9SXin Li #endif /* HAVE_PAC_LEAF */
324*412f47f9SXin Li 	bx	lr
325*412f47f9SXin Li .endm
326*412f47f9SXin Li 
327*412f47f9SXin Li /* Clean up expressions in 'last'.  */
328*412f47f9SXin Li .macro _preprocess_reglist1 first:req, last:req, push_ip:req, push_lr:req, reglist_op:req
329*412f47f9SXin Li 	.if \last == 0
330*412f47f9SXin Li 	 \reglist_op \first, 0, \push_ip, \push_lr
331*412f47f9SXin Li 	.elseif \last == 1
332*412f47f9SXin Li 	 \reglist_op \first, 1, \push_ip, \push_lr
333*412f47f9SXin Li 	.elseif \last == 2
334*412f47f9SXin Li 	 \reglist_op \first, 2, \push_ip, \push_lr
335*412f47f9SXin Li 	.elseif \last == 3
336*412f47f9SXin Li 	 \reglist_op \first, 3, \push_ip, \push_lr
337*412f47f9SXin Li 	.elseif \last == 4
338*412f47f9SXin Li 	 \reglist_op \first, 4, \push_ip, \push_lr
339*412f47f9SXin Li 	.elseif \last == 5
340*412f47f9SXin Li 	 \reglist_op \first, 5, \push_ip, \push_lr
341*412f47f9SXin Li 	.elseif \last == 6
342*412f47f9SXin Li 	 \reglist_op \first, 6, \push_ip, \push_lr
343*412f47f9SXin Li 	.elseif \last == 7
344*412f47f9SXin Li 	 \reglist_op \first, 7, \push_ip, \push_lr
345*412f47f9SXin Li 	.elseif \last == 8
346*412f47f9SXin Li 	 \reglist_op \first, 8, \push_ip, \push_lr
347*412f47f9SXin Li 	.elseif \last == 9
348*412f47f9SXin Li 	 \reglist_op \first, 9, \push_ip, \push_lr
349*412f47f9SXin Li 	.elseif \last == 10
350*412f47f9SXin Li 	 \reglist_op \first, 10, \push_ip, \push_lr
351*412f47f9SXin Li 	.elseif \last == 11
352*412f47f9SXin Li 	 \reglist_op \first, 11, \push_ip, \push_lr
353*412f47f9SXin Li 	.else
354*412f47f9SXin Li 	 .error "last (\last) out of range"
355*412f47f9SXin Li 	.endif
356*412f47f9SXin Li .endm
357*412f47f9SXin Li 
358*412f47f9SXin Li /* Clean up expressions in 'first'.  */
359*412f47f9SXin Li .macro _preprocess_reglist first:req, last, push_ip=0, push_lr=0, reglist_op:req
360*412f47f9SXin Li 	.ifb \last
361*412f47f9SXin Li 	 _preprocess_reglist \first \first \push_ip \push_lr
362*412f47f9SXin Li 	.else
363*412f47f9SXin Li 	 .if \first > \last
364*412f47f9SXin Li 	  .error "last (\last) must be at least as great as first (\first)"
365*412f47f9SXin Li 	 .endif
366*412f47f9SXin Li 	 .if \first == 0
367*412f47f9SXin Li 	  _preprocess_reglist1 0, \last, \push_ip, \push_lr, \reglist_op
368*412f47f9SXin Li 	 .elseif \first == 1
369*412f47f9SXin Li 	  _preprocess_reglist1 1, \last, \push_ip, \push_lr, \reglist_op
370*412f47f9SXin Li 	 .elseif \first == 2
371*412f47f9SXin Li 	  _preprocess_reglist1 2, \last, \push_ip, \push_lr, \reglist_op
372*412f47f9SXin Li 	 .elseif \first == 3
373*412f47f9SXin Li 	  _preprocess_reglist1 3, \last, \push_ip, \push_lr, \reglist_op
374*412f47f9SXin Li 	 .elseif \first == 4
375*412f47f9SXin Li 	  _preprocess_reglist1 4, \last, \push_ip, \push_lr, \reglist_op
376*412f47f9SXin Li 	 .elseif \first == 5
377*412f47f9SXin Li 	  _preprocess_reglist1 5, \last, \push_ip, \push_lr, \reglist_op
378*412f47f9SXin Li 	 .elseif \first == 6
379*412f47f9SXin Li 	  _preprocess_reglist1 6, \last, \push_ip, \push_lr, \reglist_op
380*412f47f9SXin Li 	 .elseif \first == 7
381*412f47f9SXin Li 	  _preprocess_reglist1 7, \last, \push_ip, \push_lr, \reglist_op
382*412f47f9SXin Li 	 .elseif \first == 8
383*412f47f9SXin Li 	  _preprocess_reglist1 8, \last, \push_ip, \push_lr, \reglist_op
384*412f47f9SXin Li 	 .elseif \first == 9
385*412f47f9SXin Li 	  _preprocess_reglist1 9, \last, \push_ip, \push_lr, \reglist_op
386*412f47f9SXin Li 	 .elseif \first == 10
387*412f47f9SXin Li 	  _preprocess_reglist1 10, \last, \push_ip, \push_lr, \reglist_op
388*412f47f9SXin Li 	 .elseif \first == 11
389*412f47f9SXin Li 	  _preprocess_reglist1 11, \last, \push_ip, \push_lr, \reglist_op
390*412f47f9SXin Li 	 .else
391*412f47f9SXin Li 	  .error "first (\first) out of range"
392*412f47f9SXin Li 	 .endif
393*412f47f9SXin Li 	.endif
394*412f47f9SXin Li .endm
395*412f47f9SXin Li 
396*412f47f9SXin Li .macro _align8 first, last, push_ip=0, push_lr=0, reglist_op=_prologue
397*412f47f9SXin Li 	.ifb \first
398*412f47f9SXin Li 	 .ifnb \last
399*412f47f9SXin Li 	  .error "can't have last (\last) without specifying first"
400*412f47f9SXin Li 	 .else // \last not blank
401*412f47f9SXin Li 	  .if ((\push_ip + \push_lr) % 2) == 0
402*412f47f9SXin Li 	   \reglist_op first=-1, last=-1, push_ip=\push_ip, push_lr=\push_lr
403*412f47f9SXin Li 	   .exitm
404*412f47f9SXin Li 	  .else // ((\push_ip + \push_lr) % 2) odd
405*412f47f9SXin Li 	   _align8 2, 2, \push_ip, \push_lr, \reglist_op
406*412f47f9SXin Li 	   .exitm
407*412f47f9SXin Li 	  .endif // ((\push_ip + \push_lr) % 2) == 0
408*412f47f9SXin Li 	 .endif // .ifnb \last
409*412f47f9SXin Li 	.endif // .ifb \first
410*412f47f9SXin Li 
411*412f47f9SXin Li 	.ifb \last
412*412f47f9SXin Li 	 _align8 \first, \first, \push_ip, \push_lr, \reglist_op
413*412f47f9SXin Li 	.else
414*412f47f9SXin Li 	 .if \push_ip & 1 <> \push_ip
415*412f47f9SXin Li 	  .error "push_ip may be 0 or 1"
416*412f47f9SXin Li 	 .endif
417*412f47f9SXin Li 	 .if \push_lr & 1 <> \push_lr
418*412f47f9SXin Li 	  .error "push_lr may be 0 or 1"
419*412f47f9SXin Li 	 .endif
420*412f47f9SXin Li 	 .ifeq (\last - \first + \push_ip + \push_lr) % 2
421*412f47f9SXin Li 	  .if \first == 0
422*412f47f9SXin Li 	   .error "Alignment required and first register is r0"
423*412f47f9SXin Li 	   .exitm
424*412f47f9SXin Li 	  .endif
425*412f47f9SXin Li 	  _preprocess_reglist \first-1, \last, \push_ip, \push_lr, \reglist_op
426*412f47f9SXin Li 	 .else
427*412f47f9SXin Li 	  _preprocess_reglist \first \last, \push_ip, \push_lr, \reglist_op
428*412f47f9SXin Li 	 .endif
429*412f47f9SXin Li 	.endif
430*412f47f9SXin Li .endm
431*412f47f9SXin Li 
432*412f47f9SXin Li .macro prologue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE
433*412f47f9SXin Li 	.if \align8
434*412f47f9SXin Li 	 _align8 \first, \last, \push_ip, \push_lr, _prologue
435*412f47f9SXin Li 	.else
436*412f47f9SXin Li 	 _prologue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr
437*412f47f9SXin Li 	.endif
438*412f47f9SXin Li .endm
439*412f47f9SXin Li 
440*412f47f9SXin Li .macro epilogue first, last, push_ip=PAC_LEAF_PUSH_IP, push_lr=0, align8=STACK_ALIGN_ENFORCE
441*412f47f9SXin Li 	.if \align8
442*412f47f9SXin Li 	 _align8 \first, \last, \push_ip, \push_lr, reglist_op=_epilogue
443*412f47f9SXin Li 	.else
444*412f47f9SXin Li 	 _epilogue first=\first, last=\last, push_ip=\push_ip, push_lr=\push_lr
445*412f47f9SXin Li 	.endif
446*412f47f9SXin Li .endm
447*412f47f9SXin Li 
448*412f47f9SXin Li #define ENTRY_ALIGN(name, alignment)	\
449*412f47f9SXin Li   .global name;		\
450*412f47f9SXin Li   .type name,%function;	\
451*412f47f9SXin Li   .align alignment;		\
452*412f47f9SXin Li   name:			\
453*412f47f9SXin Li   .fnstart;		\
454*412f47f9SXin Li   .cfi_startproc;
455*412f47f9SXin Li 
456*412f47f9SXin Li #define ENTRY(name)	ENTRY_ALIGN(name, 6)
457*412f47f9SXin Li 
458*412f47f9SXin Li #define ENTRY_ALIAS(name)	\
459*412f47f9SXin Li   .global name;		\
460*412f47f9SXin Li   .type name,%function;	\
461*412f47f9SXin Li   name:
462*412f47f9SXin Li 
463*412f47f9SXin Li #if defined (IS_LEAF)
464*412f47f9SXin Li # define END_UNWIND .cantunwind;
465*412f47f9SXin Li #else
466*412f47f9SXin Li # define END_UNWIND
467*412f47f9SXin Li #endif
468*412f47f9SXin Li 
469*412f47f9SXin Li #define END(name)	\
470*412f47f9SXin Li   .cfi_endproc;		\
471*412f47f9SXin Li   END_UNWIND		\
472*412f47f9SXin Li   .fnend;		\
473*412f47f9SXin Li   .size name, .-name;
474*412f47f9SXin Li 
475*412f47f9SXin Li #define L(l) .L ## l
476*412f47f9SXin Li 
477*412f47f9SXin Li #endif
478