forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtargetarm64.h
383 lines (305 loc) · 19.3 KB
/
targetarm64.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#pragma once
#if !defined(TARGET_ARM64)
#error The file should not be included for this platform.
#endif
// clang-format off
#define CPU_LOAD_STORE_ARCH 1
#define ROUND_FLOAT 0 // Do not round intermed float expression results
#define CPU_HAS_BYTE_REGS 0
#ifdef FEATURE_SIMD
#define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned
#define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls
#endif // FEATURE_SIMD
#define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog
#define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers
#define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers
#define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp
#define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls.
#define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies
#define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register
#define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register
#define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register
#define FEATURE_STRUCT_CLASSIFIER 0 // Uses a classifier function to determine is structs are passed/returned in more than one register
#define MAX_PASS_SINGLEREG_BYTES 16 // Maximum size of a struct passed in a single register (16-byte vector).
#define MAX_PASS_MULTIREG_BYTES 64 // Maximum size of a struct that could be passed in more than one register (max is 4 16-byte vectors using an HVA)
#define MAX_RET_MULTIREG_BYTES 64 // Maximum size of a struct that could be returned in more than one register (Max is an HVA of 4 16-byte vectors)
#define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 128-bit vectors using an HVA)
#define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value.
#define MAX_MULTIREG_COUNT 4 // Maximum number of registers defined by a single instruction (including calls).
// This is also the maximum number of registers for a MultiReg node.
#define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers
#define USER_ARGS_COME_LAST 1
#define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really
// need to track stack depth, but this is currently necessary to get GC information reported at call sites.
#define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target
#define FEATURE_EH 1 // To aid platform bring-up, eliminate exceptional EH clauses (catch, filter, filter-handler, fault) and directly execute 'finally' clauses.
#define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods
#define CSE_CONSTS 1 // Enable if we want to CSE constants
#define REG_FP_FIRST REG_V0
#define REG_FP_LAST REG_V31
#define FIRST_FP_ARGREG REG_V0
#define LAST_FP_ARGREG REG_V15
#define REG_PREDICATE_FIRST REG_P0
#define REG_PREDICATE_LAST REG_P15
#define REG_PREDICATE_LOW_LAST REG_P7 // Some instructions can only use the first half of the predicate registers.
#define REG_PREDICATE_HIGH_FIRST REG_P8 // Similarly, some instructions can only use the second half of the predicate registers.
#define REG_PREDICATE_HIGH_LAST REG_P15
#define REG_MASK_FIRST REG_PREDICATE_FIRST
#define REG_MASK_LAST REG_PREDICATE_LAST
static_assert_no_msg(REG_PREDICATE_HIGH_LAST == REG_PREDICATE_LAST);
#define REGNUM_BITS 7 // number of bits in a REG_*
#define REGSIZE_BYTES 8 // number of bytes in one general purpose register
#define FP_REGSIZE_BYTES 16 // number of bytes in one FP/SIMD register
#define FPSAVE_REGSIZE_BYTES 8 // number of bytes in one FP/SIMD register that are saved/restored, for callee-saved registers
#define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call.
#define CODE_ALIGN 4 // code alignment requirement
#define STACK_ALIGN 16 // stack alignment requirement
#define RBM_INT_CALLEE_SAVED (RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28)
#define RBM_INT_CALLEE_TRASH (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_IP0|RBM_IP1|RBM_LR)
#define RBM_FLT_CALLEE_SAVED (RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15)
#define RBM_FLT_CALLEE_TRASH (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V16|RBM_V17|RBM_V18|RBM_V19|RBM_V20|RBM_V21|RBM_V22|RBM_V23|RBM_V24|RBM_V25|RBM_V26|RBM_V27|RBM_V28|RBM_V29|RBM_V30|RBM_V31)
#define RBM_LOWMASK (RBM_P0|RBM_P1|RBM_P2|RBM_P3|RBM_P4|RBM_P5|RBM_P6|RBM_P7)
#define RBM_HIGHMASK (RBM_P8|RBM_P9|RBM_P10| RBM_P11|RBM_P12|RBM_P13|RBM_P14|RBM_P15)
#define RBM_ALLMASK (RBM_LOWMASK|RBM_HIGHMASK)
#define RBM_MSK_CALLEE_SAVED (0)
#define RBM_MSK_CALLEE_TRASH RBM_ALLMASK
#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED)
#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH | RBM_MSK_CALLEE_TRASH)
#define REG_DEFAULT_HELPER_CALL_TARGET REG_R12
#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_R12
#define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH)
#define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH)
#define RBM_ALLDOUBLE RBM_ALLFLOAT
// REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED
#define REG_VAR_ORDER REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, \
REG_R6, REG_R7, REG_R8, REG_R9, REG_R10, \
REG_R11, REG_R13, REG_R14, \
REG_R12, REG_R15, REG_IP0, REG_IP1, \
REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,\
REG_LR
#define REG_VAR_ORDER_FLT REG_V16, REG_V17, REG_V18, REG_V19, \
REG_V20, REG_V21, REG_V22, REG_V23, \
REG_V24, REG_V25, REG_V26, REG_V27, \
REG_V28, REG_V29, REG_V30, REG_V31, \
REG_V7, REG_V6, REG_V5, REG_V4, \
REG_V8, REG_V9, REG_V10, REG_V11, \
REG_V12, REG_V13, REG_V14, REG_V15, \
REG_V3, REG_V2, REG_V1, REG_V0
#define CNT_CALLEE_SAVED (11)
#define CNT_CALLEE_TRASH (17)
#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1)
#define CNT_CALLEE_SAVED_FLOAT (8)
#define CNT_CALLEE_TRASH_FLOAT (24)
#define CNT_CALLEE_SAVED_MASK (4)
#define CNT_CALLEE_TRASH_MASK (8)
#define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES)
#define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES)
// On ARM64 we do not use any additional callee-saves for ENC
// since there are so many volatile registers available, and
// callee saves have to be aggressively saved by ENC codegen
// because a future version could use them.
#define RBM_ENC_CALLEE_SAVED 0
// Temporary registers used for the GS cookie check.
#define REG_GSCOOKIE_TMP_0 REG_IP0
#define REG_GSCOOKIE_TMP_1 REG_IP1
// register to hold shift amount; no special register is required on ARM64.
#define REG_SHIFT REG_NA
#define RBM_SHIFT RBM_ALLINT
// This is a general scratch register that does not conflict with the argument registers
#define REG_SCRATCH REG_R9
// This is a general register that can be optionally reserved for other purposes during codegen
#define REG_OPT_RSVD REG_IP1
#define RBM_OPT_RSVD RBM_IP1
// Where is the exception object on entry to the handler block?
#define REG_EXCEPTION_OBJECT REG_R0
#define RBM_EXCEPTION_OBJECT RBM_R0
#define REG_JUMP_THUNK_PARAM REG_R12
#define RBM_JUMP_THUNK_PARAM RBM_R12
// ARM64 write barrier ABI (see vm\arm64\asmhelpers.asm, vm\arm64\asmhelpers.S):
// CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier):
// On entry:
// x14: the destination address of the store
// x15: the object reference to be stored
// On exit:
// x12: trashed
// x14: incremented by 8
// x15: trashed
// x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
// CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier):
// On entry:
// x13: the source address (points to object reference to write)
// x14: the destination address (object reference written here)
// On exit:
// x12: trashed
// x13: incremented by 8
// x14: incremented by 8
// x15: trashed
// x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
//
// Note that while x17 (ip1) is currently only trashed under FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP,
// it is expected to be set in the future for R2R. Consider it trashed to avoid later breaking changes.
#define REG_WRITE_BARRIER_DST REG_R14
#define RBM_WRITE_BARRIER_DST RBM_R14
#define REG_WRITE_BARRIER_SRC REG_R15
#define RBM_WRITE_BARRIER_SRC RBM_R15
#define REG_WRITE_BARRIER_DST_BYREF REG_R14
#define RBM_WRITE_BARRIER_DST_BYREF RBM_R14
#define REG_WRITE_BARRIER_SRC_BYREF REG_R13
#define RBM_WRITE_BARRIER_SRC_BYREF RBM_R13
#define RBM_CALLEE_TRASH_NOGC (RBM_R12|RBM_R15|RBM_IP0|RBM_IP1|RBM_DEFAULT_HELPER_CALL_TARGET)
// Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF.
#define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_R14|RBM_CALLEE_TRASH_NOGC)
// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF.
#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC
// Registers killed by CORINFO_HELP_ASSIGN_BYREF.
#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC)
// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF.
// Note that x13 and x14 are still valid byref pointers after this helper call, despite their value being changed.
#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC
// GenericPInvokeCalliHelper VASigCookie Parameter
#define REG_PINVOKE_COOKIE_PARAM REG_R15
#define RBM_PINVOKE_COOKIE_PARAM RBM_R15
// GenericPInvokeCalliHelper unmanaged target Parameter
#define REG_PINVOKE_TARGET_PARAM REG_R12
#define RBM_PINVOKE_TARGET_PARAM RBM_R12
// IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM)
#define REG_SECRET_STUB_PARAM REG_R12
#define RBM_SECRET_STUB_PARAM RBM_R12
// R2R indirect call. Use the same registers as VSD
#define REG_R2R_INDIRECT_PARAM REG_R11
#define RBM_R2R_INDIRECT_PARAM RBM_R11
// JMP Indirect call register
#define REG_INDIRECT_CALL_TARGET_REG REG_IP0
// The following defines are useful for iterating a regNumber
#define REG_FIRST REG_R0
#define REG_INT_FIRST REG_R0
#define REG_INT_LAST REG_ZR
#define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1)
#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1))
#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1))
// The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks
#define REG_PROFILER_ENTER_ARG_FUNC_ID REG_R10
#define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_R10
#define REG_PROFILER_ENTER_ARG_CALLER_SP REG_R11
#define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_R11
#define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_R10
#define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_R10
#define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_R11
#define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_R11
// The registers trashed by profiler enter/leave/tailcall hook
#define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_ARG_RET_BUFF|RBM_FLTARG_REGS|RBM_FP))
#define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_ARG_RET_BUFF|RBM_FLTARG_REGS|RBM_FP))
#define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH
// Which register are int and long values returned in ?
#define REG_INTRET REG_R0
#define RBM_INTRET RBM_R0
#define RBM_LNGRET RBM_R0
// second return register for 16-byte structs
#define REG_INTRET_1 REG_R1
#define RBM_INTRET_1 RBM_R1
#define REG_FLOATRET REG_V0
#define RBM_FLOATRET RBM_V0
#define RBM_DOUBLERET RBM_V0
// The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper
#define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH
// The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper.
#define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH
#define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8 | RBM_R15))
#define REG_VALIDATE_INDIRECT_CALL_ADDR REG_R15
#define REG_DISPATCH_INDIRECT_CALL_ADDR REG_R9
#define REG_FPBASE REG_FP
#define RBM_FPBASE RBM_FP
#define STR_FPBASE "fp"
#define REG_SPBASE REG_SP
#define RBM_SPBASE RBM_ZR // reuse the RBM for REG_ZR
#define STR_SPBASE "sp"
#define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address
// On ARM64 the calling convention defines REG_R8 (x8) as an additional argument register.
// It isn't allocated for the normal user arguments, so it isn't counted by MAX_REG_ARG.
// Whether we use this register to pass the RetBuff is controlled by the function hasFixedRetBuffReg().
// It is considered to be the next integer argnum, which is 8.
//
#define REG_ARG_RET_BUFF REG_R8
#define RBM_ARG_RET_BUFF RBM_R8
#define RET_BUFF_ARGNUM 8
#define MAX_REG_ARG 8
#define MAX_FLOAT_REG_ARG 8
#define REG_ARG_FIRST REG_R0
#define REG_ARG_LAST REG_R7
#define REG_ARG_FP_FIRST REG_V0
#define REG_ARG_FP_LAST REG_V7
#define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots
#define REG_ARG_0 REG_R0
#define REG_ARG_1 REG_R1
#define REG_ARG_2 REG_R2
#define REG_ARG_3 REG_R3
#define REG_ARG_4 REG_R4
#define REG_ARG_5 REG_R5
#define REG_ARG_6 REG_R6
#define REG_ARG_7 REG_R7
extern const regNumber intArgRegs [MAX_REG_ARG];
extern const regMaskTP intArgMasks[MAX_REG_ARG];
#define RBM_ARG_0 RBM_R0
#define RBM_ARG_1 RBM_R1
#define RBM_ARG_2 RBM_R2
#define RBM_ARG_3 RBM_R3
#define RBM_ARG_4 RBM_R4
#define RBM_ARG_5 RBM_R5
#define RBM_ARG_6 RBM_R6
#define RBM_ARG_7 RBM_R7
#define REG_FLTARG_0 REG_V0
#define REG_FLTARG_1 REG_V1
#define REG_FLTARG_2 REG_V2
#define REG_FLTARG_3 REG_V3
#define REG_FLTARG_4 REG_V4
#define REG_FLTARG_5 REG_V5
#define REG_FLTARG_6 REG_V6
#define REG_FLTARG_7 REG_V7
#define RBM_FLTARG_0 RBM_V0
#define RBM_FLTARG_1 RBM_V1
#define RBM_FLTARG_2 RBM_V2
#define RBM_FLTARG_3 RBM_V3
#define RBM_FLTARG_4 RBM_V4
#define RBM_FLTARG_5 RBM_V5
#define RBM_FLTARG_6 RBM_V6
#define RBM_FLTARG_7 RBM_V7
#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5|RBM_ARG_6|RBM_ARG_7)
#define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7)
extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG];
extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG];
#define LBL_DIST_SMALL_MAX_NEG (-1048576)
#define LBL_DIST_SMALL_MAX_POS (+1048575)
#define LBL_SIZE_SMALL (4)
#define JCC_DIST_SMALL_MAX_NEG (-1048576)
#define JCC_DIST_SMALL_MAX_POS (+1048575)
#define TB_DIST_SMALL_MAX_NEG (-32768)
#define TB_DIST_SMALL_MAX_POS (+32767)
#define JCC_SIZE_SMALL (4)
#define JCC_SIZE_LARGE (8)
#define LDC_DIST_SMALL_MAX_NEG (-1048576)
#define LDC_DIST_SMALL_MAX_POS (+1048575)
#define LDC_SIZE_SMALL (4)
#define JMP_SIZE_SMALL (4)
// The number of bytes from the end the last probed page that must also be probed, to allow for some
// small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word
// on the stack guard page, and must be touched before any further "SUB SP".
// For arm64, this is the maximum prolog establishment pre-indexed (that is SP pre-decrement) offset.
#define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 512
// Some "Advanced SIMD / SVE scalar x indexed element" and "Advanced SIMD / SVE vector x indexed element" instructions (e.g. "MLA (by element)")
// have encoding that restricts what registers that can be used for the indexed element when the element size is H (i.e. 2 bytes).
#define RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15)
#define RBM_SVE_INDEXED_S_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7)
#define RBM_SVE_INDEXED_D_ELEMENT_ALLOWED_REGS RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS
#define REG_ZERO_INIT_FRAME_REG1 REG_R9
#define REG_ZERO_INIT_FRAME_REG2 REG_R10
#define REG_ZERO_INIT_FRAME_SIMD REG_V16
#define SWIFT_SUPPORT
#define REG_SWIFT_ERROR REG_R21
#define RBM_SWIFT_ERROR RBM_R21
#define REG_SWIFT_SELF REG_R20
#define RBM_SWIFT_SELF RBM_R20
#define REG_SWIFT_INTRET_ORDER REG_R0,REG_R1,REG_R2,REG_R3
#define REG_SWIFT_FLOATRET_ORDER REG_V0,REG_V1,REG_V2,REG_V3
// clang-format on