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