xref: /aosp_15_r20/external/libffi/src/aarch64/sysv.S (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
2*1fd5a2e1SPrashanth Swaminathan
3*1fd5a2e1SPrashanth SwaminathanPermission is hereby granted, free of charge, to any person obtaining
4*1fd5a2e1SPrashanth Swaminathana copy of this software and associated documentation files (the
5*1fd5a2e1SPrashanth Swaminathan``Software''), to deal in the Software without restriction, including
6*1fd5a2e1SPrashanth Swaminathanwithout limitation the rights to use, copy, modify, merge, publish,
7*1fd5a2e1SPrashanth Swaminathandistribute, sublicense, and/or sell copies of the Software, and to
8*1fd5a2e1SPrashanth Swaminathanpermit persons to whom the Software is furnished to do so, subject to
9*1fd5a2e1SPrashanth Swaminathanthe following conditions:
10*1fd5a2e1SPrashanth Swaminathan
11*1fd5a2e1SPrashanth SwaminathanThe above copyright notice and this permission notice shall be
12*1fd5a2e1SPrashanth Swaminathanincluded in all copies or substantial portions of the Software.
13*1fd5a2e1SPrashanth Swaminathan
14*1fd5a2e1SPrashanth SwaminathanTHE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
15*1fd5a2e1SPrashanth SwaminathanEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16*1fd5a2e1SPrashanth SwaminathanMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17*1fd5a2e1SPrashanth SwaminathanIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18*1fd5a2e1SPrashanth SwaminathanCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19*1fd5a2e1SPrashanth SwaminathanTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20*1fd5a2e1SPrashanth SwaminathanSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
21*1fd5a2e1SPrashanth Swaminathan
22*1fd5a2e1SPrashanth Swaminathan#if defined(__aarch64__) || defined(__arm64__)
23*1fd5a2e1SPrashanth Swaminathan#define LIBFFI_ASM
24*1fd5a2e1SPrashanth Swaminathan#include <fficonfig.h>
25*1fd5a2e1SPrashanth Swaminathan#include <ffi.h>
26*1fd5a2e1SPrashanth Swaminathan#include <ffi_cfi.h>
27*1fd5a2e1SPrashanth Swaminathan#include "internal.h"
28*1fd5a2e1SPrashanth Swaminathan
29*1fd5a2e1SPrashanth Swaminathan#ifdef HAVE_MACHINE_ASM_H
30*1fd5a2e1SPrashanth Swaminathan#include <machine/asm.h>
31*1fd5a2e1SPrashanth Swaminathan#else
32*1fd5a2e1SPrashanth Swaminathan#ifdef __USER_LABEL_PREFIX__
33*1fd5a2e1SPrashanth Swaminathan#define CONCAT1(a, b) CONCAT2(a, b)
34*1fd5a2e1SPrashanth Swaminathan#define CONCAT2(a, b) a ## b
35*1fd5a2e1SPrashanth Swaminathan
36*1fd5a2e1SPrashanth Swaminathan/* Use the right prefix for global labels.  */
37*1fd5a2e1SPrashanth Swaminathan#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
38*1fd5a2e1SPrashanth Swaminathan#else
39*1fd5a2e1SPrashanth Swaminathan#define CNAME(x) x
40*1fd5a2e1SPrashanth Swaminathan#endif
41*1fd5a2e1SPrashanth Swaminathan#endif
42*1fd5a2e1SPrashanth Swaminathan
43*1fd5a2e1SPrashanth Swaminathan#ifdef __AARCH64EB__
44*1fd5a2e1SPrashanth Swaminathan# define BE(X)	X
45*1fd5a2e1SPrashanth Swaminathan#else
46*1fd5a2e1SPrashanth Swaminathan# define BE(X)	0
47*1fd5a2e1SPrashanth Swaminathan#endif
48*1fd5a2e1SPrashanth Swaminathan
49*1fd5a2e1SPrashanth Swaminathan#ifdef __ILP32__
50*1fd5a2e1SPrashanth Swaminathan#define PTR_REG(n)      w##n
51*1fd5a2e1SPrashanth Swaminathan#else
52*1fd5a2e1SPrashanth Swaminathan#define PTR_REG(n)      x##n
53*1fd5a2e1SPrashanth Swaminathan#endif
54*1fd5a2e1SPrashanth Swaminathan
55*1fd5a2e1SPrashanth Swaminathan#ifdef __ILP32__
56*1fd5a2e1SPrashanth Swaminathan#define PTR_SIZE	4
57*1fd5a2e1SPrashanth Swaminathan#else
58*1fd5a2e1SPrashanth Swaminathan#define PTR_SIZE	8
59*1fd5a2e1SPrashanth Swaminathan#endif
60*1fd5a2e1SPrashanth Swaminathan
61*1fd5a2e1SPrashanth Swaminathan	.text
62*1fd5a2e1SPrashanth Swaminathan	.align 4
63*1fd5a2e1SPrashanth Swaminathan
64*1fd5a2e1SPrashanth Swaminathan/* ffi_call_SYSV
65*1fd5a2e1SPrashanth Swaminathan   extern void ffi_call_SYSV (void *stack, void *frame,
66*1fd5a2e1SPrashanth Swaminathan			      void (*fn)(void), void *rvalue,
67*1fd5a2e1SPrashanth Swaminathan			      int flags, void *closure);
68*1fd5a2e1SPrashanth Swaminathan
69*1fd5a2e1SPrashanth Swaminathan   Therefore on entry we have:
70*1fd5a2e1SPrashanth Swaminathan
71*1fd5a2e1SPrashanth Swaminathan   x0 stack
72*1fd5a2e1SPrashanth Swaminathan   x1 frame
73*1fd5a2e1SPrashanth Swaminathan   x2 fn
74*1fd5a2e1SPrashanth Swaminathan   x3 rvalue
75*1fd5a2e1SPrashanth Swaminathan   x4 flags
76*1fd5a2e1SPrashanth Swaminathan   x5 closure
77*1fd5a2e1SPrashanth Swaminathan*/
78*1fd5a2e1SPrashanth Swaminathan
79*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
80*1fd5a2e1SPrashanth SwaminathanCNAME(ffi_call_SYSV):
81*1fd5a2e1SPrashanth Swaminathan	/* Use a stack frame allocated by our caller.  */
82*1fd5a2e1SPrashanth Swaminathan	cfi_def_cfa(x1, 32);
83*1fd5a2e1SPrashanth Swaminathan	stp	x29, x30, [x1]
84*1fd5a2e1SPrashanth Swaminathan	mov	x29, x1
85*1fd5a2e1SPrashanth Swaminathan	mov	sp, x0
86*1fd5a2e1SPrashanth Swaminathan	cfi_def_cfa_register(x29)
87*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x29, 0)
88*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x30, 8)
89*1fd5a2e1SPrashanth Swaminathan
90*1fd5a2e1SPrashanth Swaminathan	mov	x9, x2			/* save fn */
91*1fd5a2e1SPrashanth Swaminathan	mov	x8, x3			/* install structure return */
92*1fd5a2e1SPrashanth Swaminathan#ifdef FFI_GO_CLOSURES
93*1fd5a2e1SPrashanth Swaminathan	mov	x18, x5			/* install static chain */
94*1fd5a2e1SPrashanth Swaminathan#endif
95*1fd5a2e1SPrashanth Swaminathan	stp	x3, x4, [x29, #16]	/* save rvalue and flags */
96*1fd5a2e1SPrashanth Swaminathan
97*1fd5a2e1SPrashanth Swaminathan	/* Load the vector argument passing registers, if necessary.  */
98*1fd5a2e1SPrashanth Swaminathan	tbz	w4, #AARCH64_FLAG_ARG_V_BIT, 1f
99*1fd5a2e1SPrashanth Swaminathan	ldp     q0, q1, [sp, #0]
100*1fd5a2e1SPrashanth Swaminathan	ldp     q2, q3, [sp, #32]
101*1fd5a2e1SPrashanth Swaminathan	ldp     q4, q5, [sp, #64]
102*1fd5a2e1SPrashanth Swaminathan	ldp     q6, q7, [sp, #96]
103*1fd5a2e1SPrashanth Swaminathan1:
104*1fd5a2e1SPrashanth Swaminathan	/* Load the core argument passing registers, including
105*1fd5a2e1SPrashanth Swaminathan	   the structure return pointer.  */
106*1fd5a2e1SPrashanth Swaminathan	ldp     x0, x1, [sp, #16*N_V_ARG_REG + 0]
107*1fd5a2e1SPrashanth Swaminathan	ldp     x2, x3, [sp, #16*N_V_ARG_REG + 16]
108*1fd5a2e1SPrashanth Swaminathan	ldp     x4, x5, [sp, #16*N_V_ARG_REG + 32]
109*1fd5a2e1SPrashanth Swaminathan	ldp     x6, x7, [sp, #16*N_V_ARG_REG + 48]
110*1fd5a2e1SPrashanth Swaminathan
111*1fd5a2e1SPrashanth Swaminathan	/* Deallocate the context, leaving the stacked arguments.  */
112*1fd5a2e1SPrashanth Swaminathan	add	sp, sp, #CALL_CONTEXT_SIZE
113*1fd5a2e1SPrashanth Swaminathan
114*1fd5a2e1SPrashanth Swaminathan	blr     x9			/* call fn */
115*1fd5a2e1SPrashanth Swaminathan
116*1fd5a2e1SPrashanth Swaminathan	ldp	x3, x4, [x29, #16]	/* reload rvalue and flags */
117*1fd5a2e1SPrashanth Swaminathan
118*1fd5a2e1SPrashanth Swaminathan	/* Partially deconstruct the stack frame.  */
119*1fd5a2e1SPrashanth Swaminathan	mov     sp, x29
120*1fd5a2e1SPrashanth Swaminathan	cfi_def_cfa_register (sp)
121*1fd5a2e1SPrashanth Swaminathan	ldp     x29, x30, [x29]
122*1fd5a2e1SPrashanth Swaminathan
123*1fd5a2e1SPrashanth Swaminathan	/* Save the return value as directed.  */
124*1fd5a2e1SPrashanth Swaminathan	adr	x5, 0f
125*1fd5a2e1SPrashanth Swaminathan	and	w4, w4, #AARCH64_RET_MASK
126*1fd5a2e1SPrashanth Swaminathan	add	x5, x5, x4, lsl #3
127*1fd5a2e1SPrashanth Swaminathan	br	x5
128*1fd5a2e1SPrashanth Swaminathan
129*1fd5a2e1SPrashanth Swaminathan	/* Note that each table entry is 2 insns, and thus 8 bytes.
130*1fd5a2e1SPrashanth Swaminathan	   For integer data, note that we're storing into ffi_arg
131*1fd5a2e1SPrashanth Swaminathan	   and therefore we want to extend to 64 bits; these types
132*1fd5a2e1SPrashanth Swaminathan	   have two consecutive entries allocated for them.  */
133*1fd5a2e1SPrashanth Swaminathan	.align	4
134*1fd5a2e1SPrashanth Swaminathan0:	ret				/* VOID */
135*1fd5a2e1SPrashanth Swaminathan	nop
136*1fd5a2e1SPrashanth Swaminathan1:	str	x0, [x3]		/* INT64 */
137*1fd5a2e1SPrashanth Swaminathan	ret
138*1fd5a2e1SPrashanth Swaminathan2:	stp	x0, x1, [x3]		/* INT128 */
139*1fd5a2e1SPrashanth Swaminathan	ret
140*1fd5a2e1SPrashanth Swaminathan3:	brk	#1000			/* UNUSED */
141*1fd5a2e1SPrashanth Swaminathan	ret
142*1fd5a2e1SPrashanth Swaminathan4:	brk	#1000			/* UNUSED */
143*1fd5a2e1SPrashanth Swaminathan	ret
144*1fd5a2e1SPrashanth Swaminathan5:	brk	#1000			/* UNUSED */
145*1fd5a2e1SPrashanth Swaminathan	ret
146*1fd5a2e1SPrashanth Swaminathan6:	brk	#1000			/* UNUSED */
147*1fd5a2e1SPrashanth Swaminathan	ret
148*1fd5a2e1SPrashanth Swaminathan7:	brk	#1000			/* UNUSED */
149*1fd5a2e1SPrashanth Swaminathan	ret
150*1fd5a2e1SPrashanth Swaminathan8:	st4	{ v0.s, v1.s, v2.s, v3.s }[0], [x3]	/* S4 */
151*1fd5a2e1SPrashanth Swaminathan	ret
152*1fd5a2e1SPrashanth Swaminathan9:	st3	{ v0.s, v1.s, v2.s }[0], [x3]	/* S3 */
153*1fd5a2e1SPrashanth Swaminathan	ret
154*1fd5a2e1SPrashanth Swaminathan10:	stp	s0, s1, [x3]		/* S2 */
155*1fd5a2e1SPrashanth Swaminathan	ret
156*1fd5a2e1SPrashanth Swaminathan11:	str	s0, [x3]		/* S1 */
157*1fd5a2e1SPrashanth Swaminathan	ret
158*1fd5a2e1SPrashanth Swaminathan12:	st4	{ v0.d, v1.d, v2.d, v3.d }[0], [x3]	/* D4 */
159*1fd5a2e1SPrashanth Swaminathan	ret
160*1fd5a2e1SPrashanth Swaminathan13:	st3	{ v0.d, v1.d, v2.d }[0], [x3]	/* D3 */
161*1fd5a2e1SPrashanth Swaminathan	ret
162*1fd5a2e1SPrashanth Swaminathan14:	stp	d0, d1, [x3]		/* D2 */
163*1fd5a2e1SPrashanth Swaminathan	ret
164*1fd5a2e1SPrashanth Swaminathan15:	str	d0, [x3]		/* D1 */
165*1fd5a2e1SPrashanth Swaminathan	ret
166*1fd5a2e1SPrashanth Swaminathan16:	str	q3, [x3, #48]		/* Q4 */
167*1fd5a2e1SPrashanth Swaminathan	nop
168*1fd5a2e1SPrashanth Swaminathan17:	str	q2, [x3, #32]		/* Q3 */
169*1fd5a2e1SPrashanth Swaminathan	nop
170*1fd5a2e1SPrashanth Swaminathan18:	stp	q0, q1, [x3]		/* Q2 */
171*1fd5a2e1SPrashanth Swaminathan	ret
172*1fd5a2e1SPrashanth Swaminathan19:	str	q0, [x3]		/* Q1 */
173*1fd5a2e1SPrashanth Swaminathan	ret
174*1fd5a2e1SPrashanth Swaminathan20:	uxtb	w0, w0			/* UINT8 */
175*1fd5a2e1SPrashanth Swaminathan	str	x0, [x3]
176*1fd5a2e1SPrashanth Swaminathan21:	ret				/* reserved */
177*1fd5a2e1SPrashanth Swaminathan	nop
178*1fd5a2e1SPrashanth Swaminathan22:	uxth	w0, w0			/* UINT16 */
179*1fd5a2e1SPrashanth Swaminathan	str	x0, [x3]
180*1fd5a2e1SPrashanth Swaminathan23:	ret				/* reserved */
181*1fd5a2e1SPrashanth Swaminathan	nop
182*1fd5a2e1SPrashanth Swaminathan24:	mov	w0, w0			/* UINT32 */
183*1fd5a2e1SPrashanth Swaminathan	str	x0, [x3]
184*1fd5a2e1SPrashanth Swaminathan25:	ret				/* reserved */
185*1fd5a2e1SPrashanth Swaminathan	nop
186*1fd5a2e1SPrashanth Swaminathan26:	sxtb	x0, w0			/* SINT8 */
187*1fd5a2e1SPrashanth Swaminathan	str	x0, [x3]
188*1fd5a2e1SPrashanth Swaminathan27:	ret				/* reserved */
189*1fd5a2e1SPrashanth Swaminathan	nop
190*1fd5a2e1SPrashanth Swaminathan28:	sxth	x0, w0			/* SINT16 */
191*1fd5a2e1SPrashanth Swaminathan	str	x0, [x3]
192*1fd5a2e1SPrashanth Swaminathan29:	ret				/* reserved */
193*1fd5a2e1SPrashanth Swaminathan	nop
194*1fd5a2e1SPrashanth Swaminathan30:	sxtw	x0, w0			/* SINT32 */
195*1fd5a2e1SPrashanth Swaminathan	str	x0, [x3]
196*1fd5a2e1SPrashanth Swaminathan31:	ret				/* reserved */
197*1fd5a2e1SPrashanth Swaminathan	nop
198*1fd5a2e1SPrashanth Swaminathan
199*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
200*1fd5a2e1SPrashanth Swaminathan
201*1fd5a2e1SPrashanth Swaminathan	.globl	CNAME(ffi_call_SYSV)
202*1fd5a2e1SPrashanth Swaminathan	FFI_HIDDEN(CNAME(ffi_call_SYSV))
203*1fd5a2e1SPrashanth Swaminathan#ifdef __ELF__
204*1fd5a2e1SPrashanth Swaminathan	.type	CNAME(ffi_call_SYSV), #function
205*1fd5a2e1SPrashanth Swaminathan	.size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
206*1fd5a2e1SPrashanth Swaminathan#endif
207*1fd5a2e1SPrashanth Swaminathan
208*1fd5a2e1SPrashanth Swaminathan/* ffi_closure_SYSV
209*1fd5a2e1SPrashanth Swaminathan
210*1fd5a2e1SPrashanth Swaminathan   Closure invocation glue. This is the low level code invoked directly by
211*1fd5a2e1SPrashanth Swaminathan   the closure trampoline to setup and call a closure.
212*1fd5a2e1SPrashanth Swaminathan
213*1fd5a2e1SPrashanth Swaminathan   On entry x17 points to a struct ffi_closure, x16 has been clobbered
214*1fd5a2e1SPrashanth Swaminathan   all other registers are preserved.
215*1fd5a2e1SPrashanth Swaminathan
216*1fd5a2e1SPrashanth Swaminathan   We allocate a call context and save the argument passing registers,
217*1fd5a2e1SPrashanth Swaminathan   then invoked the generic C ffi_closure_SYSV_inner() function to do all
218*1fd5a2e1SPrashanth Swaminathan   the real work, on return we load the result passing registers back from
219*1fd5a2e1SPrashanth Swaminathan   the call context.
220*1fd5a2e1SPrashanth Swaminathan*/
221*1fd5a2e1SPrashanth Swaminathan
222*1fd5a2e1SPrashanth Swaminathan#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64)
223*1fd5a2e1SPrashanth Swaminathan
224*1fd5a2e1SPrashanth Swaminathan	.align 4
225*1fd5a2e1SPrashanth SwaminathanCNAME(ffi_closure_SYSV_V):
226*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
227*1fd5a2e1SPrashanth Swaminathan	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
228*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
229*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x29, 0)
230*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x30, 8)
231*1fd5a2e1SPrashanth Swaminathan
232*1fd5a2e1SPrashanth Swaminathan	/* Save the argument passing vector registers.  */
233*1fd5a2e1SPrashanth Swaminathan	stp     q0, q1, [sp, #16 + 0]
234*1fd5a2e1SPrashanth Swaminathan	stp     q2, q3, [sp, #16 + 32]
235*1fd5a2e1SPrashanth Swaminathan	stp     q4, q5, [sp, #16 + 64]
236*1fd5a2e1SPrashanth Swaminathan	stp     q6, q7, [sp, #16 + 96]
237*1fd5a2e1SPrashanth Swaminathan	b	0f
238*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
239*1fd5a2e1SPrashanth Swaminathan
240*1fd5a2e1SPrashanth Swaminathan	.globl	CNAME(ffi_closure_SYSV_V)
241*1fd5a2e1SPrashanth Swaminathan	FFI_HIDDEN(CNAME(ffi_closure_SYSV_V))
242*1fd5a2e1SPrashanth Swaminathan#ifdef __ELF__
243*1fd5a2e1SPrashanth Swaminathan	.type	CNAME(ffi_closure_SYSV_V), #function
244*1fd5a2e1SPrashanth Swaminathan	.size	CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V)
245*1fd5a2e1SPrashanth Swaminathan#endif
246*1fd5a2e1SPrashanth Swaminathan
247*1fd5a2e1SPrashanth Swaminathan	.align	4
248*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
249*1fd5a2e1SPrashanth SwaminathanCNAME(ffi_closure_SYSV):
250*1fd5a2e1SPrashanth Swaminathan	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
251*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
252*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x29, 0)
253*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x30, 8)
254*1fd5a2e1SPrashanth Swaminathan0:
255*1fd5a2e1SPrashanth Swaminathan	mov     x29, sp
256*1fd5a2e1SPrashanth Swaminathan
257*1fd5a2e1SPrashanth Swaminathan	/* Save the argument passing core registers.  */
258*1fd5a2e1SPrashanth Swaminathan	stp     x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
259*1fd5a2e1SPrashanth Swaminathan	stp     x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
260*1fd5a2e1SPrashanth Swaminathan	stp     x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
261*1fd5a2e1SPrashanth Swaminathan	stp     x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
262*1fd5a2e1SPrashanth Swaminathan
263*1fd5a2e1SPrashanth Swaminathan	/* Load ffi_closure_inner arguments.  */
264*1fd5a2e1SPrashanth Swaminathan	ldp	PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET]	/* load cif, fn */
265*1fd5a2e1SPrashanth Swaminathan	ldr	PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2]	/* load user_data */
266*1fd5a2e1SPrashanth Swaminathan.Ldo_closure:
267*1fd5a2e1SPrashanth Swaminathan	add	x3, sp, #16				/* load context */
268*1fd5a2e1SPrashanth Swaminathan	add	x4, sp, #ffi_closure_SYSV_FS		/* load stack */
269*1fd5a2e1SPrashanth Swaminathan	add	x5, sp, #16+CALL_CONTEXT_SIZE		/* load rvalue */
270*1fd5a2e1SPrashanth Swaminathan	mov	x6, x8					/* load struct_rval */
271*1fd5a2e1SPrashanth Swaminathan	bl      CNAME(ffi_closure_SYSV_inner)
272*1fd5a2e1SPrashanth Swaminathan
273*1fd5a2e1SPrashanth Swaminathan	/* Load the return value as directed.  */
274*1fd5a2e1SPrashanth Swaminathan	adr	x1, 0f
275*1fd5a2e1SPrashanth Swaminathan	and	w0, w0, #AARCH64_RET_MASK
276*1fd5a2e1SPrashanth Swaminathan	add	x1, x1, x0, lsl #3
277*1fd5a2e1SPrashanth Swaminathan	add	x3, sp, #16+CALL_CONTEXT_SIZE
278*1fd5a2e1SPrashanth Swaminathan	br	x1
279*1fd5a2e1SPrashanth Swaminathan
280*1fd5a2e1SPrashanth Swaminathan	/* Note that each table entry is 2 insns, and thus 8 bytes.  */
281*1fd5a2e1SPrashanth Swaminathan	.align	4
282*1fd5a2e1SPrashanth Swaminathan0:	b	99f			/* VOID */
283*1fd5a2e1SPrashanth Swaminathan	nop
284*1fd5a2e1SPrashanth Swaminathan1:	ldr	x0, [x3]		/* INT64 */
285*1fd5a2e1SPrashanth Swaminathan	b	99f
286*1fd5a2e1SPrashanth Swaminathan2:	ldp	x0, x1, [x3]		/* INT128 */
287*1fd5a2e1SPrashanth Swaminathan	b	99f
288*1fd5a2e1SPrashanth Swaminathan3:	brk	#1000			/* UNUSED */
289*1fd5a2e1SPrashanth Swaminathan	nop
290*1fd5a2e1SPrashanth Swaminathan4:	brk	#1000			/* UNUSED */
291*1fd5a2e1SPrashanth Swaminathan	nop
292*1fd5a2e1SPrashanth Swaminathan5:	brk	#1000			/* UNUSED */
293*1fd5a2e1SPrashanth Swaminathan	nop
294*1fd5a2e1SPrashanth Swaminathan6:	brk	#1000			/* UNUSED */
295*1fd5a2e1SPrashanth Swaminathan	nop
296*1fd5a2e1SPrashanth Swaminathan7:	brk	#1000			/* UNUSED */
297*1fd5a2e1SPrashanth Swaminathan	nop
298*1fd5a2e1SPrashanth Swaminathan8:	ldr	s3, [x3, #12]		/* S4 */
299*1fd5a2e1SPrashanth Swaminathan	nop
300*1fd5a2e1SPrashanth Swaminathan9:	ldr	s2, [x3, #8]		/* S3 */
301*1fd5a2e1SPrashanth Swaminathan	nop
302*1fd5a2e1SPrashanth Swaminathan10:	ldp	s0, s1, [x3]		/* S2 */
303*1fd5a2e1SPrashanth Swaminathan	b	99f
304*1fd5a2e1SPrashanth Swaminathan11:	ldr	s0, [x3]		/* S1 */
305*1fd5a2e1SPrashanth Swaminathan	b	99f
306*1fd5a2e1SPrashanth Swaminathan12:	ldr	d3, [x3, #24]		/* D4 */
307*1fd5a2e1SPrashanth Swaminathan	nop
308*1fd5a2e1SPrashanth Swaminathan13:	ldr	d2, [x3, #16]		/* D3 */
309*1fd5a2e1SPrashanth Swaminathan	nop
310*1fd5a2e1SPrashanth Swaminathan14:	ldp	d0, d1, [x3]		/* D2 */
311*1fd5a2e1SPrashanth Swaminathan	b	99f
312*1fd5a2e1SPrashanth Swaminathan15:	ldr	d0, [x3]		/* D1 */
313*1fd5a2e1SPrashanth Swaminathan	b	99f
314*1fd5a2e1SPrashanth Swaminathan16:	ldr	q3, [x3, #48]		/* Q4 */
315*1fd5a2e1SPrashanth Swaminathan	nop
316*1fd5a2e1SPrashanth Swaminathan17:	ldr	q2, [x3, #32]		/* Q3 */
317*1fd5a2e1SPrashanth Swaminathan	nop
318*1fd5a2e1SPrashanth Swaminathan18:	ldp	q0, q1, [x3]		/* Q2 */
319*1fd5a2e1SPrashanth Swaminathan	b	99f
320*1fd5a2e1SPrashanth Swaminathan19:	ldr	q0, [x3]		/* Q1 */
321*1fd5a2e1SPrashanth Swaminathan	b	99f
322*1fd5a2e1SPrashanth Swaminathan20:	ldrb	w0, [x3, #BE(7)]	/* UINT8 */
323*1fd5a2e1SPrashanth Swaminathan	b	99f
324*1fd5a2e1SPrashanth Swaminathan21:	brk	#1000			/* reserved */
325*1fd5a2e1SPrashanth Swaminathan	nop
326*1fd5a2e1SPrashanth Swaminathan22:	ldrh	w0, [x3, #BE(6)]	/* UINT16 */
327*1fd5a2e1SPrashanth Swaminathan	b	99f
328*1fd5a2e1SPrashanth Swaminathan23:	brk	#1000			/* reserved */
329*1fd5a2e1SPrashanth Swaminathan	nop
330*1fd5a2e1SPrashanth Swaminathan24:	ldr	w0, [x3, #BE(4)]	/* UINT32 */
331*1fd5a2e1SPrashanth Swaminathan	b	99f
332*1fd5a2e1SPrashanth Swaminathan25:	brk	#1000			/* reserved */
333*1fd5a2e1SPrashanth Swaminathan	nop
334*1fd5a2e1SPrashanth Swaminathan26:	ldrsb	x0, [x3, #BE(7)]	/* SINT8 */
335*1fd5a2e1SPrashanth Swaminathan	b	99f
336*1fd5a2e1SPrashanth Swaminathan27:	brk	#1000			/* reserved */
337*1fd5a2e1SPrashanth Swaminathan	nop
338*1fd5a2e1SPrashanth Swaminathan28:	ldrsh	x0, [x3, #BE(6)]	/* SINT16 */
339*1fd5a2e1SPrashanth Swaminathan	b	99f
340*1fd5a2e1SPrashanth Swaminathan29:	brk	#1000			/* reserved */
341*1fd5a2e1SPrashanth Swaminathan	nop
342*1fd5a2e1SPrashanth Swaminathan30:	ldrsw	x0, [x3, #BE(4)]	/* SINT32 */
343*1fd5a2e1SPrashanth Swaminathan	nop
344*1fd5a2e1SPrashanth Swaminathan31:					/* reserved */
345*1fd5a2e1SPrashanth Swaminathan99:	ldp     x29, x30, [sp], #ffi_closure_SYSV_FS
346*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
347*1fd5a2e1SPrashanth Swaminathan	cfi_restore (x29)
348*1fd5a2e1SPrashanth Swaminathan	cfi_restore (x30)
349*1fd5a2e1SPrashanth Swaminathan	ret
350*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
351*1fd5a2e1SPrashanth Swaminathan
352*1fd5a2e1SPrashanth Swaminathan	.globl	CNAME(ffi_closure_SYSV)
353*1fd5a2e1SPrashanth Swaminathan	FFI_HIDDEN(CNAME(ffi_closure_SYSV))
354*1fd5a2e1SPrashanth Swaminathan#ifdef __ELF__
355*1fd5a2e1SPrashanth Swaminathan	.type	CNAME(ffi_closure_SYSV), #function
356*1fd5a2e1SPrashanth Swaminathan	.size	CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
357*1fd5a2e1SPrashanth Swaminathan#endif
358*1fd5a2e1SPrashanth Swaminathan
359*1fd5a2e1SPrashanth Swaminathan#if FFI_EXEC_TRAMPOLINE_TABLE
360*1fd5a2e1SPrashanth Swaminathan
361*1fd5a2e1SPrashanth Swaminathan#ifdef __MACH__
362*1fd5a2e1SPrashanth Swaminathan#include <mach/machine/vm_param.h>
363*1fd5a2e1SPrashanth Swaminathan    .align PAGE_MAX_SHIFT
364*1fd5a2e1SPrashanth SwaminathanCNAME(ffi_closure_trampoline_table_page):
365*1fd5a2e1SPrashanth Swaminathan    .rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE
366*1fd5a2e1SPrashanth Swaminathan    adr x16, -PAGE_MAX_SIZE
367*1fd5a2e1SPrashanth Swaminathan    ldp x17, x16, [x16]
368*1fd5a2e1SPrashanth Swaminathan    br x16
369*1fd5a2e1SPrashanth Swaminathan	nop		/* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller that 16 bytes */
370*1fd5a2e1SPrashanth Swaminathan    .endr
371*1fd5a2e1SPrashanth Swaminathan
372*1fd5a2e1SPrashanth Swaminathan    .globl CNAME(ffi_closure_trampoline_table_page)
373*1fd5a2e1SPrashanth Swaminathan    FFI_HIDDEN(CNAME(ffi_closure_trampoline_table_page))
374*1fd5a2e1SPrashanth Swaminathan    #ifdef __ELF__
375*1fd5a2e1SPrashanth Swaminathan    	.type	CNAME(ffi_closure_trampoline_table_page), #function
376*1fd5a2e1SPrashanth Swaminathan    	.size	CNAME(ffi_closure_trampoline_table_page), . - CNAME(ffi_closure_trampoline_table_page)
377*1fd5a2e1SPrashanth Swaminathan    #endif
378*1fd5a2e1SPrashanth Swaminathan#endif
379*1fd5a2e1SPrashanth Swaminathan
380*1fd5a2e1SPrashanth Swaminathan#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
381*1fd5a2e1SPrashanth Swaminathan
382*1fd5a2e1SPrashanth Swaminathan#ifdef FFI_GO_CLOSURES
383*1fd5a2e1SPrashanth Swaminathan	.align 4
384*1fd5a2e1SPrashanth SwaminathanCNAME(ffi_go_closure_SYSV_V):
385*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
386*1fd5a2e1SPrashanth Swaminathan	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
387*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
388*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x29, 0)
389*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x30, 8)
390*1fd5a2e1SPrashanth Swaminathan
391*1fd5a2e1SPrashanth Swaminathan	/* Save the argument passing vector registers.  */
392*1fd5a2e1SPrashanth Swaminathan	stp     q0, q1, [sp, #16 + 0]
393*1fd5a2e1SPrashanth Swaminathan	stp     q2, q3, [sp, #16 + 32]
394*1fd5a2e1SPrashanth Swaminathan	stp     q4, q5, [sp, #16 + 64]
395*1fd5a2e1SPrashanth Swaminathan	stp     q6, q7, [sp, #16 + 96]
396*1fd5a2e1SPrashanth Swaminathan	b	0f
397*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
398*1fd5a2e1SPrashanth Swaminathan
399*1fd5a2e1SPrashanth Swaminathan	.globl	CNAME(ffi_go_closure_SYSV_V)
400*1fd5a2e1SPrashanth Swaminathan	FFI_HIDDEN(CNAME(ffi_go_closure_SYSV_V))
401*1fd5a2e1SPrashanth Swaminathan#ifdef __ELF__
402*1fd5a2e1SPrashanth Swaminathan	.type	CNAME(ffi_go_closure_SYSV_V), #function
403*1fd5a2e1SPrashanth Swaminathan	.size	CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V)
404*1fd5a2e1SPrashanth Swaminathan#endif
405*1fd5a2e1SPrashanth Swaminathan
406*1fd5a2e1SPrashanth Swaminathan	.align	4
407*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
408*1fd5a2e1SPrashanth SwaminathanCNAME(ffi_go_closure_SYSV):
409*1fd5a2e1SPrashanth Swaminathan	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
410*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
411*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x29, 0)
412*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset (x30, 8)
413*1fd5a2e1SPrashanth Swaminathan0:
414*1fd5a2e1SPrashanth Swaminathan	mov     x29, sp
415*1fd5a2e1SPrashanth Swaminathan
416*1fd5a2e1SPrashanth Swaminathan	/* Save the argument passing core registers.  */
417*1fd5a2e1SPrashanth Swaminathan	stp     x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
418*1fd5a2e1SPrashanth Swaminathan	stp     x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
419*1fd5a2e1SPrashanth Swaminathan	stp     x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
420*1fd5a2e1SPrashanth Swaminathan	stp     x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
421*1fd5a2e1SPrashanth Swaminathan
422*1fd5a2e1SPrashanth Swaminathan	/* Load ffi_closure_inner arguments.  */
423*1fd5a2e1SPrashanth Swaminathan	ldp	PTR_REG(0), PTR_REG(1), [x18, #PTR_SIZE]/* load cif, fn */
424*1fd5a2e1SPrashanth Swaminathan	mov	x2, x18					/* load user_data */
425*1fd5a2e1SPrashanth Swaminathan	b	.Ldo_closure
426*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
427*1fd5a2e1SPrashanth Swaminathan
428*1fd5a2e1SPrashanth Swaminathan	.globl	CNAME(ffi_go_closure_SYSV)
429*1fd5a2e1SPrashanth Swaminathan	FFI_HIDDEN(CNAME(ffi_go_closure_SYSV))
430*1fd5a2e1SPrashanth Swaminathan#ifdef __ELF__
431*1fd5a2e1SPrashanth Swaminathan	.type	CNAME(ffi_go_closure_SYSV), #function
432*1fd5a2e1SPrashanth Swaminathan	.size	CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV)
433*1fd5a2e1SPrashanth Swaminathan#endif
434*1fd5a2e1SPrashanth Swaminathan#endif /* FFI_GO_CLOSURES */
435*1fd5a2e1SPrashanth Swaminathan#endif /* __arm64__ */
436*1fd5a2e1SPrashanth Swaminathan
437*1fd5a2e1SPrashanth Swaminathan#if defined __ELF__ && defined __linux__
438*1fd5a2e1SPrashanth Swaminathan	.section .note.GNU-stack,"",%progbits
439*1fd5a2e1SPrashanth Swaminathan#endif
440*1fd5a2e1SPrashanth Swaminathan
441