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