xref: /aosp_15_r20/external/libffi/src/arm/sysv.S (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan/* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan   sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
3*1fd5a2e1SPrashanth Swaminathan	    Copyright (c) 2011 Plausible Labs Cooperative, Inc.
4*1fd5a2e1SPrashanth Swaminathan
5*1fd5a2e1SPrashanth Swaminathan   ARM Foreign Function Interface
6*1fd5a2e1SPrashanth Swaminathan
7*1fd5a2e1SPrashanth Swaminathan   Permission is hereby granted, free of charge, to any person obtaining
8*1fd5a2e1SPrashanth Swaminathan   a copy of this software and associated documentation files (the
9*1fd5a2e1SPrashanth Swaminathan   ``Software''), to deal in the Software without restriction, including
10*1fd5a2e1SPrashanth Swaminathan   without limitation the rights to use, copy, modify, merge, publish,
11*1fd5a2e1SPrashanth Swaminathan   distribute, sublicense, and/or sell copies of the Software, and to
12*1fd5a2e1SPrashanth Swaminathan   permit persons to whom the Software is furnished to do so, subject to
13*1fd5a2e1SPrashanth Swaminathan   the following conditions:
14*1fd5a2e1SPrashanth Swaminathan
15*1fd5a2e1SPrashanth Swaminathan   The above copyright notice and this permission notice shall be included
16*1fd5a2e1SPrashanth Swaminathan   in all copies or substantial portions of the Software.
17*1fd5a2e1SPrashanth Swaminathan
18*1fd5a2e1SPrashanth Swaminathan   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19*1fd5a2e1SPrashanth Swaminathan   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*1fd5a2e1SPrashanth Swaminathan   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*1fd5a2e1SPrashanth Swaminathan   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22*1fd5a2e1SPrashanth Swaminathan   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23*1fd5a2e1SPrashanth Swaminathan   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24*1fd5a2e1SPrashanth Swaminathan   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25*1fd5a2e1SPrashanth Swaminathan   DEALINGS IN THE SOFTWARE.
26*1fd5a2e1SPrashanth Swaminathan   ----------------------------------------------------------------------- */
27*1fd5a2e1SPrashanth Swaminathan
28*1fd5a2e1SPrashanth Swaminathan#ifdef __arm__
29*1fd5a2e1SPrashanth Swaminathan#define LIBFFI_ASM
30*1fd5a2e1SPrashanth Swaminathan#include <fficonfig.h>
31*1fd5a2e1SPrashanth Swaminathan#include <ffi.h>
32*1fd5a2e1SPrashanth Swaminathan#include <ffi_cfi.h>
33*1fd5a2e1SPrashanth Swaminathan#include "internal.h"
34*1fd5a2e1SPrashanth Swaminathan
35*1fd5a2e1SPrashanth Swaminathan/* GCC 4.8 provides __ARM_ARCH; construct it otherwise.  */
36*1fd5a2e1SPrashanth Swaminathan#ifndef __ARM_ARCH
37*1fd5a2e1SPrashanth Swaminathan# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
38*1fd5a2e1SPrashanth Swaminathan     || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
39*1fd5a2e1SPrashanth Swaminathan     || defined(__ARM_ARCH_7EM__)
40*1fd5a2e1SPrashanth Swaminathan#  define __ARM_ARCH 7
41*1fd5a2e1SPrashanth Swaminathan# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
42*1fd5a2e1SPrashanth Swaminathan        || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
43*1fd5a2e1SPrashanth Swaminathan        || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
44*1fd5a2e1SPrashanth Swaminathan	|| defined(__ARM_ARCH_6M__)
45*1fd5a2e1SPrashanth Swaminathan#  define __ARM_ARCH 6
46*1fd5a2e1SPrashanth Swaminathan# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
47*1fd5a2e1SPrashanth Swaminathan	|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
48*1fd5a2e1SPrashanth Swaminathan	|| defined(__ARM_ARCH_5TEJ__)
49*1fd5a2e1SPrashanth Swaminathan#  define __ARM_ARCH 5
50*1fd5a2e1SPrashanth Swaminathan# else
51*1fd5a2e1SPrashanth Swaminathan#  define __ARM_ARCH 4
52*1fd5a2e1SPrashanth Swaminathan# endif
53*1fd5a2e1SPrashanth Swaminathan#endif
54*1fd5a2e1SPrashanth Swaminathan
55*1fd5a2e1SPrashanth Swaminathan/* Conditionally compile unwinder directives.  */
56*1fd5a2e1SPrashanth Swaminathan#ifdef __ARM_EABI__
57*1fd5a2e1SPrashanth Swaminathan# define UNWIND(...)	__VA_ARGS__
58*1fd5a2e1SPrashanth Swaminathan#else
59*1fd5a2e1SPrashanth Swaminathan# define UNWIND(...)
60*1fd5a2e1SPrashanth Swaminathan#endif
61*1fd5a2e1SPrashanth Swaminathan
62*1fd5a2e1SPrashanth Swaminathan#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
63*1fd5a2e1SPrashanth Swaminathan	.cfi_sections	.debug_frame
64*1fd5a2e1SPrashanth Swaminathan#endif
65*1fd5a2e1SPrashanth Swaminathan
66*1fd5a2e1SPrashanth Swaminathan#define CONCAT(a, b)	CONCAT2(a, b)
67*1fd5a2e1SPrashanth Swaminathan#define CONCAT2(a, b)	a ## b
68*1fd5a2e1SPrashanth Swaminathan
69*1fd5a2e1SPrashanth Swaminathan#ifdef __USER_LABEL_PREFIX__
70*1fd5a2e1SPrashanth Swaminathan# define CNAME(X)	CONCAT (__USER_LABEL_PREFIX__, X)
71*1fd5a2e1SPrashanth Swaminathan#else
72*1fd5a2e1SPrashanth Swaminathan# define CNAME(X)	X
73*1fd5a2e1SPrashanth Swaminathan#endif
74*1fd5a2e1SPrashanth Swaminathan#ifdef __ELF__
75*1fd5a2e1SPrashanth Swaminathan# define SIZE(X)	.size CNAME(X), . - CNAME(X)
76*1fd5a2e1SPrashanth Swaminathan# define TYPE(X, Y)	.type CNAME(X), Y
77*1fd5a2e1SPrashanth Swaminathan#else
78*1fd5a2e1SPrashanth Swaminathan# define SIZE(X)
79*1fd5a2e1SPrashanth Swaminathan# define TYPE(X, Y)
80*1fd5a2e1SPrashanth Swaminathan#endif
81*1fd5a2e1SPrashanth Swaminathan
82*1fd5a2e1SPrashanth Swaminathan#define ARM_FUNC_START_LOCAL(name)	\
83*1fd5a2e1SPrashanth Swaminathan	.align	3;			\
84*1fd5a2e1SPrashanth Swaminathan	TYPE(CNAME(name), %function);	\
85*1fd5a2e1SPrashanth Swaminathan	CNAME(name):
86*1fd5a2e1SPrashanth Swaminathan
87*1fd5a2e1SPrashanth Swaminathan#define ARM_FUNC_START(name)		\
88*1fd5a2e1SPrashanth Swaminathan	.globl CNAME(name);		\
89*1fd5a2e1SPrashanth Swaminathan	FFI_HIDDEN(CNAME(name));	\
90*1fd5a2e1SPrashanth Swaminathan	ARM_FUNC_START_LOCAL(name)
91*1fd5a2e1SPrashanth Swaminathan
92*1fd5a2e1SPrashanth Swaminathan#define ARM_FUNC_END(name) \
93*1fd5a2e1SPrashanth Swaminathan	SIZE(name)
94*1fd5a2e1SPrashanth Swaminathan
95*1fd5a2e1SPrashanth Swaminathan/* Aid in defining a jump table with 8 bytes between entries.  */
96*1fd5a2e1SPrashanth Swaminathan/* ??? The clang assembler doesn't handle .if with symbolic expressions.  */
97*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
98*1fd5a2e1SPrashanth Swaminathan# define E(index)
99*1fd5a2e1SPrashanth Swaminathan#else
100*1fd5a2e1SPrashanth Swaminathan# define E(index)				\
101*1fd5a2e1SPrashanth Swaminathan	.if . - 0b - 8*index;			\
102*1fd5a2e1SPrashanth Swaminathan	.error "type table out of sync";	\
103*1fd5a2e1SPrashanth Swaminathan	.endif
104*1fd5a2e1SPrashanth Swaminathan#endif
105*1fd5a2e1SPrashanth Swaminathan
106*1fd5a2e1SPrashanth Swaminathan	.text
107*1fd5a2e1SPrashanth Swaminathan	.syntax unified
108*1fd5a2e1SPrashanth Swaminathan	.arm
109*1fd5a2e1SPrashanth Swaminathan
110*1fd5a2e1SPrashanth Swaminathan#ifndef __clang__
111*1fd5a2e1SPrashanth Swaminathan	/* We require interworking on LDM, which implies ARMv5T,
112*1fd5a2e1SPrashanth Swaminathan	   which implies the existance of BLX.  */
113*1fd5a2e1SPrashanth Swaminathan 	.arch	armv5t
114*1fd5a2e1SPrashanth Swaminathan#endif
115*1fd5a2e1SPrashanth Swaminathan
116*1fd5a2e1SPrashanth Swaminathan	/* Note that we use STC and LDC to encode VFP instructions,
117*1fd5a2e1SPrashanth Swaminathan	   so that we do not need ".fpu vfp", nor get that added to
118*1fd5a2e1SPrashanth Swaminathan	   the object file attributes.  These will not be executed
119*1fd5a2e1SPrashanth Swaminathan	   unless the FFI_VFP abi is used.  */
120*1fd5a2e1SPrashanth Swaminathan
121*1fd5a2e1SPrashanth Swaminathan	@ r0:   stack
122*1fd5a2e1SPrashanth Swaminathan	@ r1:   frame
123*1fd5a2e1SPrashanth Swaminathan	@ r2:   fn
124*1fd5a2e1SPrashanth Swaminathan	@ r3:	vfp_used
125*1fd5a2e1SPrashanth Swaminathan
126*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_call_VFP)
127*1fd5a2e1SPrashanth Swaminathan	UNWIND(.fnstart)
128*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
129*1fd5a2e1SPrashanth Swaminathan
130*1fd5a2e1SPrashanth Swaminathan	cmp	r3, #3			@ load only d0 if possible
131*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
132*1fd5a2e1SPrashanth Swaminathan	vldrle d0, [sp]
133*1fd5a2e1SPrashanth Swaminathan	vldmgt sp, {d0-d7}
134*1fd5a2e1SPrashanth Swaminathan#else
135*1fd5a2e1SPrashanth Swaminathan	ldcle	p11, cr0, [r0]		@ vldrle d0, [sp]
136*1fd5a2e1SPrashanth Swaminathan	ldcgt	p11, cr0, [r0], {16}	@ vldmgt sp, {d0-d7}
137*1fd5a2e1SPrashanth Swaminathan#endif
138*1fd5a2e1SPrashanth Swaminathan	add	r0, r0, #64		@ discard the vfp register args
139*1fd5a2e1SPrashanth Swaminathan	/* FALLTHRU */
140*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_call_VFP)
141*1fd5a2e1SPrashanth Swaminathan
142*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_call_SYSV)
143*1fd5a2e1SPrashanth Swaminathan	stm	r1, {fp, lr}
144*1fd5a2e1SPrashanth Swaminathan	mov	fp, r1
145*1fd5a2e1SPrashanth Swaminathan
146*1fd5a2e1SPrashanth Swaminathan	@ This is a bit of a lie wrt the origin of the unwind info, but
147*1fd5a2e1SPrashanth Swaminathan	@ now we've got the usual frame pointer and two saved registers.
148*1fd5a2e1SPrashanth Swaminathan	UNWIND(.save {fp,lr})
149*1fd5a2e1SPrashanth Swaminathan	UNWIND(.setfp fp, sp)
150*1fd5a2e1SPrashanth Swaminathan	cfi_def_cfa(fp, 8)
151*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset(fp, 0)
152*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset(lr, 4)
153*1fd5a2e1SPrashanth Swaminathan
154*1fd5a2e1SPrashanth Swaminathan	mov	sp, r0		@ install the stack pointer
155*1fd5a2e1SPrashanth Swaminathan	mov	lr, r2		@ move the fn pointer out of the way
156*1fd5a2e1SPrashanth Swaminathan	ldr	ip, [fp, #16]	@ install the static chain
157*1fd5a2e1SPrashanth Swaminathan	ldmia	sp!, {r0-r3}	@ move first 4 parameters in registers.
158*1fd5a2e1SPrashanth Swaminathan	blx	lr		@ call fn
159*1fd5a2e1SPrashanth Swaminathan
160*1fd5a2e1SPrashanth Swaminathan	@ Load r2 with the pointer to storage for the return value
161*1fd5a2e1SPrashanth Swaminathan	@ Load r3 with the return type code
162*1fd5a2e1SPrashanth Swaminathan	ldr	r2, [fp, #8]
163*1fd5a2e1SPrashanth Swaminathan	ldr	r3, [fp, #12]
164*1fd5a2e1SPrashanth Swaminathan
165*1fd5a2e1SPrashanth Swaminathan	@ Deallocate the stack with the arguments.
166*1fd5a2e1SPrashanth Swaminathan	mov	sp, fp
167*1fd5a2e1SPrashanth Swaminathan	cfi_def_cfa_register(sp)
168*1fd5a2e1SPrashanth Swaminathan
169*1fd5a2e1SPrashanth Swaminathan	@ Store values stored in registers.
170*1fd5a2e1SPrashanth Swaminathan	.align	3
171*1fd5a2e1SPrashanth Swaminathan	add	pc, pc, r3, lsl #3
172*1fd5a2e1SPrashanth Swaminathan	nop
173*1fd5a2e1SPrashanth Swaminathan0:
174*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_S)
175*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
176*1fd5a2e1SPrashanth Swaminathan	vstr s0, [r2]
177*1fd5a2e1SPrashanth Swaminathan#else
178*1fd5a2e1SPrashanth Swaminathan	stc	p10, cr0, [r2]		@ vstr s0, [r2]
179*1fd5a2e1SPrashanth Swaminathan#endif
180*1fd5a2e1SPrashanth Swaminathan	pop	{fp,pc}
181*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_D)
182*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
183*1fd5a2e1SPrashanth Swaminathan	vstr d0, [r2]
184*1fd5a2e1SPrashanth Swaminathan#else
185*1fd5a2e1SPrashanth Swaminathan	stc	p11, cr0, [r2]		@ vstr d0, [r2]
186*1fd5a2e1SPrashanth Swaminathan#endif
187*1fd5a2e1SPrashanth Swaminathan	pop	{fp,pc}
188*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_N)
189*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
190*1fd5a2e1SPrashanth Swaminathan	vstm r2, {d0-d3}
191*1fd5a2e1SPrashanth Swaminathan#else
192*1fd5a2e1SPrashanth Swaminathan	stc	p11, cr0, [r2], {8}	@ vstm r2, {d0-d3}
193*1fd5a2e1SPrashanth Swaminathan#endif
194*1fd5a2e1SPrashanth Swaminathan	pop	{fp,pc}
195*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT64)
196*1fd5a2e1SPrashanth Swaminathan	str	r1, [r2, #4]
197*1fd5a2e1SPrashanth Swaminathan	nop
198*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT)
199*1fd5a2e1SPrashanth Swaminathan	str	r0, [r2]
200*1fd5a2e1SPrashanth Swaminathan	pop	{fp,pc}
201*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VOID)
202*1fd5a2e1SPrashanth Swaminathan	pop	{fp,pc}
203*1fd5a2e1SPrashanth Swaminathan	nop
204*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_STRUCT)
205*1fd5a2e1SPrashanth Swaminathan	pop	{fp,pc}
206*1fd5a2e1SPrashanth Swaminathan
207*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
208*1fd5a2e1SPrashanth Swaminathan	UNWIND(.fnend)
209*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_call_SYSV)
210*1fd5a2e1SPrashanth Swaminathan
211*1fd5a2e1SPrashanth Swaminathan
212*1fd5a2e1SPrashanth Swaminathan/*
213*1fd5a2e1SPrashanth Swaminathan	int ffi_closure_inner_* (cif, fun, user_data, frame)
214*1fd5a2e1SPrashanth Swaminathan*/
215*1fd5a2e1SPrashanth Swaminathan
216*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_go_closure_SYSV)
217*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
218*1fd5a2e1SPrashanth Swaminathan	stmdb	sp!, {r0-r3}			@ save argument regs
219*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(16)
220*1fd5a2e1SPrashanth Swaminathan	ldr	r0, [ip, #4]			@ load cif
221*1fd5a2e1SPrashanth Swaminathan	ldr	r1, [ip, #8]			@ load fun
222*1fd5a2e1SPrashanth Swaminathan	mov	r2, ip				@ load user_data
223*1fd5a2e1SPrashanth Swaminathan	b	0f
224*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
225*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_go_closure_SYSV)
226*1fd5a2e1SPrashanth Swaminathan
227*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_closure_SYSV)
228*1fd5a2e1SPrashanth Swaminathan	UNWIND(.fnstart)
229*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
230*1fd5a2e1SPrashanth Swaminathan	stmdb	sp!, {r0-r3}			@ save argument regs
231*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(16)
232*1fd5a2e1SPrashanth Swaminathan
233*1fd5a2e1SPrashanth Swaminathan#if FFI_EXEC_TRAMPOLINE_TABLE
234*1fd5a2e1SPrashanth Swaminathan	ldr ip, [ip]				@ ip points to the config page, dereference to get the ffi_closure*
235*1fd5a2e1SPrashanth Swaminathan#endif
236*1fd5a2e1SPrashanth Swaminathan	ldr	r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET]	@ load cif
237*1fd5a2e1SPrashanth Swaminathan	ldr	r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4]  @ load fun
238*1fd5a2e1SPrashanth Swaminathan	ldr	r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8]  @ load user_data
239*1fd5a2e1SPrashanth Swaminathan0:
240*1fd5a2e1SPrashanth Swaminathan	add	ip, sp, #16			@ compute entry sp
241*1fd5a2e1SPrashanth Swaminathan	sub	sp, sp, #64+32			@ allocate frame
242*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(64+32)
243*1fd5a2e1SPrashanth Swaminathan	stmdb	sp!, {ip,lr}
244*1fd5a2e1SPrashanth Swaminathan
245*1fd5a2e1SPrashanth Swaminathan	/* Remember that EABI unwind info only applies at call sites.
246*1fd5a2e1SPrashanth Swaminathan	   We need do nothing except note the save of the stack pointer
247*1fd5a2e1SPrashanth Swaminathan	   and the link registers.  */
248*1fd5a2e1SPrashanth Swaminathan	UNWIND(.save {sp,lr})
249*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(8)
250*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset(lr, 4)
251*1fd5a2e1SPrashanth Swaminathan
252*1fd5a2e1SPrashanth Swaminathan	add	r3, sp, #8			@ load frame
253*1fd5a2e1SPrashanth Swaminathan	bl	CNAME(ffi_closure_inner_SYSV)
254*1fd5a2e1SPrashanth Swaminathan
255*1fd5a2e1SPrashanth Swaminathan	@ Load values returned in registers.
256*1fd5a2e1SPrashanth Swaminathan	add	r2, sp, #8+64			@ load result
257*1fd5a2e1SPrashanth Swaminathan	adr	r3, CNAME(ffi_closure_ret)
258*1fd5a2e1SPrashanth Swaminathan	add	pc, r3, r0, lsl #3
259*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
260*1fd5a2e1SPrashanth Swaminathan	UNWIND(.fnend)
261*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_SYSV)
262*1fd5a2e1SPrashanth Swaminathan
263*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_go_closure_VFP)
264*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
265*1fd5a2e1SPrashanth Swaminathan	stmdb	sp!, {r0-r3}			@ save argument regs
266*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(16)
267*1fd5a2e1SPrashanth Swaminathan	ldr	r0, [ip, #4]			@ load cif
268*1fd5a2e1SPrashanth Swaminathan	ldr	r1, [ip, #8]			@ load fun
269*1fd5a2e1SPrashanth Swaminathan	mov	r2, ip				@ load user_data
270*1fd5a2e1SPrashanth Swaminathan	b	0f
271*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
272*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_go_closure_VFP)
273*1fd5a2e1SPrashanth Swaminathan
274*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_closure_VFP)
275*1fd5a2e1SPrashanth Swaminathan	UNWIND(.fnstart)
276*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
277*1fd5a2e1SPrashanth Swaminathan	stmdb	sp!, {r0-r3}			@ save argument regs
278*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(16)
279*1fd5a2e1SPrashanth Swaminathan
280*1fd5a2e1SPrashanth Swaminathan#if FFI_EXEC_TRAMPOLINE_TABLE
281*1fd5a2e1SPrashanth Swaminathan	ldr ip, [ip]				@ ip points to the config page, dereference to get the ffi_closure*
282*1fd5a2e1SPrashanth Swaminathan#endif
283*1fd5a2e1SPrashanth Swaminathan	ldr	r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET]	@ load cif
284*1fd5a2e1SPrashanth Swaminathan	ldr	r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4]  @ load fun
285*1fd5a2e1SPrashanth Swaminathan	ldr	r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8]  @ load user_data
286*1fd5a2e1SPrashanth Swaminathan0:
287*1fd5a2e1SPrashanth Swaminathan	add	ip, sp, #16
288*1fd5a2e1SPrashanth Swaminathan	sub	sp, sp, #64+32			@ allocate frame
289*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(64+32)
290*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
291*1fd5a2e1SPrashanth Swaminathan	vstm sp, {d0-d7}
292*1fd5a2e1SPrashanth Swaminathan#else
293*1fd5a2e1SPrashanth Swaminathan	stc	p11, cr0, [sp], {16}		@ vstm sp, {d0-d7}
294*1fd5a2e1SPrashanth Swaminathan#endif
295*1fd5a2e1SPrashanth Swaminathan	stmdb	sp!, {ip,lr}
296*1fd5a2e1SPrashanth Swaminathan
297*1fd5a2e1SPrashanth Swaminathan	/* See above.  */
298*1fd5a2e1SPrashanth Swaminathan	UNWIND(.save {sp,lr})
299*1fd5a2e1SPrashanth Swaminathan	cfi_adjust_cfa_offset(8)
300*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset(lr, 4)
301*1fd5a2e1SPrashanth Swaminathan
302*1fd5a2e1SPrashanth Swaminathan	add	r3, sp, #8			@ load frame
303*1fd5a2e1SPrashanth Swaminathan	bl	CNAME(ffi_closure_inner_VFP)
304*1fd5a2e1SPrashanth Swaminathan
305*1fd5a2e1SPrashanth Swaminathan	@ Load values returned in registers.
306*1fd5a2e1SPrashanth Swaminathan	add	r2, sp, #8+64			@ load result
307*1fd5a2e1SPrashanth Swaminathan	adr	r3, CNAME(ffi_closure_ret)
308*1fd5a2e1SPrashanth Swaminathan	add	pc, r3, r0, lsl #3
309*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
310*1fd5a2e1SPrashanth Swaminathan	UNWIND(.fnend)
311*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_VFP)
312*1fd5a2e1SPrashanth Swaminathan
313*1fd5a2e1SPrashanth Swaminathan/* Load values returned in registers for both closure entry points.
314*1fd5a2e1SPrashanth Swaminathan   Note that we use LDM with SP in the register set.  This is deprecated
315*1fd5a2e1SPrashanth Swaminathan   by ARM, but not yet unpredictable.  */
316*1fd5a2e1SPrashanth Swaminathan
317*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START_LOCAL(ffi_closure_ret)
318*1fd5a2e1SPrashanth Swaminathan	cfi_startproc
319*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset(sp, 0)
320*1fd5a2e1SPrashanth Swaminathan	cfi_rel_offset(lr, 4)
321*1fd5a2e1SPrashanth Swaminathan0:
322*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_S)
323*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
324*1fd5a2e1SPrashanth Swaminathan	vldr s0, [r2]
325*1fd5a2e1SPrashanth Swaminathan#else
326*1fd5a2e1SPrashanth Swaminathan	ldc	p10, cr0, [r2]			@ vldr s0, [r2]
327*1fd5a2e1SPrashanth Swaminathan#endif
328*1fd5a2e1SPrashanth Swaminathan	ldm	sp, {sp,pc}
329*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_D)
330*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
331*1fd5a2e1SPrashanth Swaminathan	vldr d0, [r2]
332*1fd5a2e1SPrashanth Swaminathan#else
333*1fd5a2e1SPrashanth Swaminathan	ldc	p11, cr0, [r2]			@ vldr d0, [r2]
334*1fd5a2e1SPrashanth Swaminathan#endif
335*1fd5a2e1SPrashanth Swaminathan	ldm	sp, {sp,pc}
336*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_N)
337*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__
338*1fd5a2e1SPrashanth Swaminathan	vldm r2, {d0-d3}
339*1fd5a2e1SPrashanth Swaminathan#else
340*1fd5a2e1SPrashanth Swaminathan	ldc	p11, cr0, [r2], {8}		@ vldm r2, {d0-d3}
341*1fd5a2e1SPrashanth Swaminathan#endif
342*1fd5a2e1SPrashanth Swaminathan	ldm	sp, {sp,pc}
343*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT64)
344*1fd5a2e1SPrashanth Swaminathan	ldr	r1, [r2, #4]
345*1fd5a2e1SPrashanth Swaminathan	nop
346*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT)
347*1fd5a2e1SPrashanth Swaminathan	ldr	r0, [r2]
348*1fd5a2e1SPrashanth Swaminathan	ldm	sp, {sp,pc}
349*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VOID)
350*1fd5a2e1SPrashanth Swaminathan	ldm	sp, {sp,pc}
351*1fd5a2e1SPrashanth Swaminathan	nop
352*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_STRUCT)
353*1fd5a2e1SPrashanth Swaminathan	ldm	sp, {sp,pc}
354*1fd5a2e1SPrashanth Swaminathan	cfi_endproc
355*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_ret)
356*1fd5a2e1SPrashanth Swaminathan
357*1fd5a2e1SPrashanth Swaminathan#if FFI_EXEC_TRAMPOLINE_TABLE
358*1fd5a2e1SPrashanth Swaminathan
359*1fd5a2e1SPrashanth Swaminathan#ifdef __MACH__
360*1fd5a2e1SPrashanth Swaminathan#include <mach/machine/vm_param.h>
361*1fd5a2e1SPrashanth Swaminathan
362*1fd5a2e1SPrashanth Swaminathan.align	PAGE_MAX_SHIFT
363*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_closure_trampoline_table_page)
364*1fd5a2e1SPrashanth Swaminathan.rept	PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE
365*1fd5a2e1SPrashanth Swaminathan	adr ip, #-PAGE_MAX_SIZE   @ the config page is PAGE_MAX_SIZE behind the trampoline page
366*1fd5a2e1SPrashanth Swaminathan	sub ip, #8				  @ account for pc bias
367*1fd5a2e1SPrashanth Swaminathan	ldr	pc, [ip, #4]		  @ jump to ffi_closure_SYSV or ffi_closure_VFP
368*1fd5a2e1SPrashanth Swaminathan.endr
369*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_trampoline_table_page)
370*1fd5a2e1SPrashanth Swaminathan#endif
371*1fd5a2e1SPrashanth Swaminathan
372*1fd5a2e1SPrashanth Swaminathan#else
373*1fd5a2e1SPrashanth Swaminathan
374*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_arm_trampoline)
375*1fd5a2e1SPrashanth Swaminathan0:	adr	ip, 0b
376*1fd5a2e1SPrashanth Swaminathan	ldr	pc, 1f
377*1fd5a2e1SPrashanth Swaminathan1:	.long	0
378*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_arm_trampoline)
379*1fd5a2e1SPrashanth Swaminathan
380*1fd5a2e1SPrashanth Swaminathan#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
381*1fd5a2e1SPrashanth Swaminathan#endif /* __arm__ */
382*1fd5a2e1SPrashanth Swaminathan
383*1fd5a2e1SPrashanth Swaminathan#if defined __ELF__ && defined __linux__
384*1fd5a2e1SPrashanth Swaminathan	.section	.note.GNU-stack,"",%progbits
385*1fd5a2e1SPrashanth Swaminathan#endif
386