xref: /aosp_15_r20/external/libffi/src/mips/o32.S (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan/* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan   o32.S - Copyright (c) 1996, 1998, 2005  Red Hat, Inc.
3*1fd5a2e1SPrashanth Swaminathan
4*1fd5a2e1SPrashanth Swaminathan   MIPS Foreign Function Interface
5*1fd5a2e1SPrashanth Swaminathan
6*1fd5a2e1SPrashanth Swaminathan   Permission is hereby granted, free of charge, to any person obtaining
7*1fd5a2e1SPrashanth Swaminathan   a copy of this software and associated documentation files (the
8*1fd5a2e1SPrashanth Swaminathan   ``Software''), to deal in the Software without restriction, including
9*1fd5a2e1SPrashanth Swaminathan   without limitation the rights to use, copy, modify, merge, publish,
10*1fd5a2e1SPrashanth Swaminathan   distribute, sublicense, and/or sell copies of the Software, and to
11*1fd5a2e1SPrashanth Swaminathan   permit persons to whom the Software is furnished to do so, subject to
12*1fd5a2e1SPrashanth Swaminathan   the following conditions:
13*1fd5a2e1SPrashanth Swaminathan
14*1fd5a2e1SPrashanth Swaminathan   The above copyright notice and this permission notice shall be included
15*1fd5a2e1SPrashanth Swaminathan   in all copies or substantial portions of the Software.
16*1fd5a2e1SPrashanth Swaminathan
17*1fd5a2e1SPrashanth Swaminathan   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18*1fd5a2e1SPrashanth Swaminathan   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19*1fd5a2e1SPrashanth Swaminathan   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20*1fd5a2e1SPrashanth Swaminathan   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21*1fd5a2e1SPrashanth Swaminathan   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22*1fd5a2e1SPrashanth Swaminathan   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*1fd5a2e1SPrashanth Swaminathan   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24*1fd5a2e1SPrashanth Swaminathan   DEALINGS IN THE SOFTWARE.
25*1fd5a2e1SPrashanth Swaminathan   ----------------------------------------------------------------------- */
26*1fd5a2e1SPrashanth Swaminathan
27*1fd5a2e1SPrashanth Swaminathan#define LIBFFI_ASM
28*1fd5a2e1SPrashanth Swaminathan#include <fficonfig.h>
29*1fd5a2e1SPrashanth Swaminathan#include <ffi.h>
30*1fd5a2e1SPrashanth Swaminathan
31*1fd5a2e1SPrashanth Swaminathan/* Only build this code if we are compiling for o32 */
32*1fd5a2e1SPrashanth Swaminathan
33*1fd5a2e1SPrashanth Swaminathan#if defined(FFI_MIPS_O32)
34*1fd5a2e1SPrashanth Swaminathan
35*1fd5a2e1SPrashanth Swaminathan#define callback a0
36*1fd5a2e1SPrashanth Swaminathan#define bytes	 a2
37*1fd5a2e1SPrashanth Swaminathan#define flags	 a3
38*1fd5a2e1SPrashanth Swaminathan
39*1fd5a2e1SPrashanth Swaminathan#define SIZEOF_FRAME	(4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
40*1fd5a2e1SPrashanth Swaminathan#define A3_OFF		(SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
41*1fd5a2e1SPrashanth Swaminathan#define FP_OFF		(SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
42*1fd5a2e1SPrashanth Swaminathan#define RA_OFF		(SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
43*1fd5a2e1SPrashanth Swaminathan
44*1fd5a2e1SPrashanth Swaminathan	.abicalls
45*1fd5a2e1SPrashanth Swaminathan	.text
46*1fd5a2e1SPrashanth Swaminathan	.align	2
47*1fd5a2e1SPrashanth Swaminathan	.globl	ffi_call_O32
48*1fd5a2e1SPrashanth Swaminathan	.ent	ffi_call_O32
49*1fd5a2e1SPrashanth Swaminathanffi_call_O32:
50*1fd5a2e1SPrashanth Swaminathan$LFB0:
51*1fd5a2e1SPrashanth Swaminathan	# Prologue
52*1fd5a2e1SPrashanth Swaminathan	SUBU	$sp, SIZEOF_FRAME	# Frame size
53*1fd5a2e1SPrashanth Swaminathan$LCFI00:
54*1fd5a2e1SPrashanth Swaminathan	REG_S	$fp, FP_OFF($sp)	# Save frame pointer
55*1fd5a2e1SPrashanth Swaminathan$LCFI01:
56*1fd5a2e1SPrashanth Swaminathan	REG_S	ra, RA_OFF($sp)		# Save return address
57*1fd5a2e1SPrashanth Swaminathan$LCFI02:
58*1fd5a2e1SPrashanth Swaminathan	move	$fp, $sp
59*1fd5a2e1SPrashanth Swaminathan
60*1fd5a2e1SPrashanth Swaminathan$LCFI03:
61*1fd5a2e1SPrashanth Swaminathan	move	t9, callback		# callback function pointer
62*1fd5a2e1SPrashanth Swaminathan	REG_S	flags, A3_OFF($fp)	# flags
63*1fd5a2e1SPrashanth Swaminathan
64*1fd5a2e1SPrashanth Swaminathan	# Allocate at least 4 words in the argstack
65*1fd5a2e1SPrashanth Swaminathan	LI	v0, 4 * FFI_SIZEOF_ARG
66*1fd5a2e1SPrashanth Swaminathan	blt	bytes, v0, sixteen
67*1fd5a2e1SPrashanth Swaminathan
68*1fd5a2e1SPrashanth Swaminathan	ADDU	v0, bytes, 7	# make sure it is aligned
69*1fd5a2e1SPrashanth Swaminathan	and	v0, -8		# to an 8 byte boundry
70*1fd5a2e1SPrashanth Swaminathan
71*1fd5a2e1SPrashanth Swaminathansixteen:
72*1fd5a2e1SPrashanth Swaminathan	SUBU	$sp, v0		# move the stack pointer to reflect the
73*1fd5a2e1SPrashanth Swaminathan				# arg space
74*1fd5a2e1SPrashanth Swaminathan
75*1fd5a2e1SPrashanth Swaminathan	ADDU	a0, $sp, 4 * FFI_SIZEOF_ARG
76*1fd5a2e1SPrashanth Swaminathan
77*1fd5a2e1SPrashanth Swaminathan	jalr	t9
78*1fd5a2e1SPrashanth Swaminathan
79*1fd5a2e1SPrashanth Swaminathan	REG_L	t0, A3_OFF($fp)		# load the flags word
80*1fd5a2e1SPrashanth Swaminathan	SRL	t2, t0, 4		# shift our arg info
81*1fd5a2e1SPrashanth Swaminathan	and     t0, ((1<<4)-1)          # mask out the return type
82*1fd5a2e1SPrashanth Swaminathan
83*1fd5a2e1SPrashanth Swaminathan	ADDU	$sp, 4 * FFI_SIZEOF_ARG		# adjust $sp to new args
84*1fd5a2e1SPrashanth Swaminathan
85*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float
86*1fd5a2e1SPrashanth Swaminathan	bnez	t0, pass_d			# make it quick for int
87*1fd5a2e1SPrashanth Swaminathan#endif
88*1fd5a2e1SPrashanth Swaminathan	REG_L	a0, 0*FFI_SIZEOF_ARG($sp)	# just go ahead and load the
89*1fd5a2e1SPrashanth Swaminathan	REG_L	a1, 1*FFI_SIZEOF_ARG($sp)	# four regs.
90*1fd5a2e1SPrashanth Swaminathan	REG_L	a2, 2*FFI_SIZEOF_ARG($sp)
91*1fd5a2e1SPrashanth Swaminathan	REG_L	a3, 3*FFI_SIZEOF_ARG($sp)
92*1fd5a2e1SPrashanth Swaminathan	b	call_it
93*1fd5a2e1SPrashanth Swaminathan
94*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float
95*1fd5a2e1SPrashanth Swaminathanpass_d:
96*1fd5a2e1SPrashanth Swaminathan	bne	t0, FFI_ARGS_D, pass_f
97*1fd5a2e1SPrashanth Swaminathan	l.d	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
98*1fd5a2e1SPrashanth Swaminathan	REG_L	a2,   2*FFI_SIZEOF_ARG($sp)	# passing a double
99*1fd5a2e1SPrashanth Swaminathan	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
100*1fd5a2e1SPrashanth Swaminathan	b	call_it
101*1fd5a2e1SPrashanth Swaminathan
102*1fd5a2e1SPrashanth Swaminathanpass_f:
103*1fd5a2e1SPrashanth Swaminathan	bne	t0, FFI_ARGS_F, pass_d_d
104*1fd5a2e1SPrashanth Swaminathan	l.s	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
105*1fd5a2e1SPrashanth Swaminathan	REG_L	a1,   1*FFI_SIZEOF_ARG($sp)	# passing a float
106*1fd5a2e1SPrashanth Swaminathan	REG_L	a2,   2*FFI_SIZEOF_ARG($sp)
107*1fd5a2e1SPrashanth Swaminathan	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
108*1fd5a2e1SPrashanth Swaminathan	b	call_it
109*1fd5a2e1SPrashanth Swaminathan
110*1fd5a2e1SPrashanth Swaminathanpass_d_d:
111*1fd5a2e1SPrashanth Swaminathan	bne	t0, FFI_ARGS_DD, pass_f_f
112*1fd5a2e1SPrashanth Swaminathan	l.d	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
113*1fd5a2e1SPrashanth Swaminathan	l.d	$f14, 2*FFI_SIZEOF_ARG($sp)	# passing two doubles
114*1fd5a2e1SPrashanth Swaminathan	b	call_it
115*1fd5a2e1SPrashanth Swaminathan
116*1fd5a2e1SPrashanth Swaminathanpass_f_f:
117*1fd5a2e1SPrashanth Swaminathan	bne	t0, FFI_ARGS_FF, pass_d_f
118*1fd5a2e1SPrashanth Swaminathan	l.s	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
119*1fd5a2e1SPrashanth Swaminathan	l.s	$f14, 1*FFI_SIZEOF_ARG($sp)	# passing two floats
120*1fd5a2e1SPrashanth Swaminathan	REG_L	a2,   2*FFI_SIZEOF_ARG($sp)
121*1fd5a2e1SPrashanth Swaminathan	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
122*1fd5a2e1SPrashanth Swaminathan	b	call_it
123*1fd5a2e1SPrashanth Swaminathan
124*1fd5a2e1SPrashanth Swaminathanpass_d_f:
125*1fd5a2e1SPrashanth Swaminathan	bne	t0, FFI_ARGS_DF, pass_f_d
126*1fd5a2e1SPrashanth Swaminathan	l.d	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
127*1fd5a2e1SPrashanth Swaminathan	l.s	$f14, 2*FFI_SIZEOF_ARG($sp)	# passing double and float
128*1fd5a2e1SPrashanth Swaminathan	REG_L	a3,   3*FFI_SIZEOF_ARG($sp)
129*1fd5a2e1SPrashanth Swaminathan	b	call_it
130*1fd5a2e1SPrashanth Swaminathan
131*1fd5a2e1SPrashanth Swaminathanpass_f_d:
132*1fd5a2e1SPrashanth Swaminathan # assume that the only other combination must be float then double
133*1fd5a2e1SPrashanth Swaminathan #	bne	t0, FFI_ARGS_F_D, call_it
134*1fd5a2e1SPrashanth Swaminathan	l.s	$f12, 0*FFI_SIZEOF_ARG($sp)	# load $fp regs from args
135*1fd5a2e1SPrashanth Swaminathan	l.d	$f14, 2*FFI_SIZEOF_ARG($sp)	# passing double and float
136*1fd5a2e1SPrashanth Swaminathan#endif
137*1fd5a2e1SPrashanth Swaminathan
138*1fd5a2e1SPrashanth Swaminathancall_it:
139*1fd5a2e1SPrashanth Swaminathan	# Load the static chain pointer
140*1fd5a2e1SPrashanth Swaminathan	REG_L	t7, SIZEOF_FRAME + 6*FFI_SIZEOF_ARG($fp)
141*1fd5a2e1SPrashanth Swaminathan
142*1fd5a2e1SPrashanth Swaminathan	# Load the function pointer
143*1fd5a2e1SPrashanth Swaminathan	REG_L	t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
144*1fd5a2e1SPrashanth Swaminathan
145*1fd5a2e1SPrashanth Swaminathan	# If the return value pointer is NULL, assume no return value.
146*1fd5a2e1SPrashanth Swaminathan	REG_L	t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
147*1fd5a2e1SPrashanth Swaminathan	beqz	t1, noretval
148*1fd5a2e1SPrashanth Swaminathan
149*1fd5a2e1SPrashanth Swaminathan	bne     t2, FFI_TYPE_INT, retlonglong
150*1fd5a2e1SPrashanth Swaminathan	jalr	t9
151*1fd5a2e1SPrashanth Swaminathan	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
152*1fd5a2e1SPrashanth Swaminathan	REG_S	v0, 0(t0)
153*1fd5a2e1SPrashanth Swaminathan	b	epilogue
154*1fd5a2e1SPrashanth Swaminathan
155*1fd5a2e1SPrashanth Swaminathanretlonglong:
156*1fd5a2e1SPrashanth Swaminathan	# Really any 64-bit int, signed or not.
157*1fd5a2e1SPrashanth Swaminathan	bne	t2, FFI_TYPE_UINT64, retfloat
158*1fd5a2e1SPrashanth Swaminathan	jalr	t9
159*1fd5a2e1SPrashanth Swaminathan	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
160*1fd5a2e1SPrashanth Swaminathan	REG_S	v1, 4(t0)
161*1fd5a2e1SPrashanth Swaminathan	REG_S	v0, 0(t0)
162*1fd5a2e1SPrashanth Swaminathan	b	epilogue
163*1fd5a2e1SPrashanth Swaminathan
164*1fd5a2e1SPrashanth Swaminathanretfloat:
165*1fd5a2e1SPrashanth Swaminathan	bne     t2, FFI_TYPE_FLOAT, retdouble
166*1fd5a2e1SPrashanth Swaminathan	jalr	t9
167*1fd5a2e1SPrashanth Swaminathan	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
168*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float
169*1fd5a2e1SPrashanth Swaminathan	s.s	$f0, 0(t0)
170*1fd5a2e1SPrashanth Swaminathan#else
171*1fd5a2e1SPrashanth Swaminathan	REG_S	v0, 0(t0)
172*1fd5a2e1SPrashanth Swaminathan#endif
173*1fd5a2e1SPrashanth Swaminathan	b	epilogue
174*1fd5a2e1SPrashanth Swaminathan
175*1fd5a2e1SPrashanth Swaminathanretdouble:
176*1fd5a2e1SPrashanth Swaminathan	bne	t2, FFI_TYPE_DOUBLE, noretval
177*1fd5a2e1SPrashanth Swaminathan	jalr	t9
178*1fd5a2e1SPrashanth Swaminathan	REG_L	t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
179*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float
180*1fd5a2e1SPrashanth Swaminathan	s.d	$f0, 0(t0)
181*1fd5a2e1SPrashanth Swaminathan#else
182*1fd5a2e1SPrashanth Swaminathan	REG_S	v1, 4(t0)
183*1fd5a2e1SPrashanth Swaminathan	REG_S	v0, 0(t0)
184*1fd5a2e1SPrashanth Swaminathan#endif
185*1fd5a2e1SPrashanth Swaminathan	b	epilogue
186*1fd5a2e1SPrashanth Swaminathan
187*1fd5a2e1SPrashanth Swaminathannoretval:
188*1fd5a2e1SPrashanth Swaminathan	jalr	t9
189*1fd5a2e1SPrashanth Swaminathan
190*1fd5a2e1SPrashanth Swaminathan	# Epilogue
191*1fd5a2e1SPrashanth Swaminathanepilogue:
192*1fd5a2e1SPrashanth Swaminathan	move	$sp, $fp
193*1fd5a2e1SPrashanth Swaminathan	REG_L	$fp, FP_OFF($sp)	# Restore frame pointer
194*1fd5a2e1SPrashanth Swaminathan	REG_L	ra, RA_OFF($sp)		# Restore return address
195*1fd5a2e1SPrashanth Swaminathan	ADDU	$sp, SIZEOF_FRAME	# Fix stack pointer
196*1fd5a2e1SPrashanth Swaminathan	j	ra
197*1fd5a2e1SPrashanth Swaminathan
198*1fd5a2e1SPrashanth Swaminathan$LFE0:
199*1fd5a2e1SPrashanth Swaminathan	.end	ffi_call_O32
200*1fd5a2e1SPrashanth Swaminathan
201*1fd5a2e1SPrashanth Swaminathan
202*1fd5a2e1SPrashanth Swaminathan/* ffi_closure_O32. Expects address of the passed-in ffi_closure
203*1fd5a2e1SPrashanth Swaminathan	in t4 ($12). Stores any arguments passed in registers onto the
204*1fd5a2e1SPrashanth Swaminathan	stack, then calls ffi_closure_mips_inner_O32, which
205*1fd5a2e1SPrashanth Swaminathan	then decodes them.
206*1fd5a2e1SPrashanth Swaminathan
207*1fd5a2e1SPrashanth Swaminathan	Stack layout:
208*1fd5a2e1SPrashanth Swaminathan
209*1fd5a2e1SPrashanth Swaminathan	 3 - a3 save
210*1fd5a2e1SPrashanth Swaminathan	 2 - a2 save
211*1fd5a2e1SPrashanth Swaminathan	 1 - a1 save
212*1fd5a2e1SPrashanth Swaminathan	 0 - a0 save, original sp
213*1fd5a2e1SPrashanth Swaminathan	-1 - ra save
214*1fd5a2e1SPrashanth Swaminathan	-2 - fp save
215*1fd5a2e1SPrashanth Swaminathan	-3 - $16 (s0) save
216*1fd5a2e1SPrashanth Swaminathan	-4 - cprestore
217*1fd5a2e1SPrashanth Swaminathan	-5 - return value high (v1)
218*1fd5a2e1SPrashanth Swaminathan	-6 - return value low (v0)
219*1fd5a2e1SPrashanth Swaminathan	-7 - f14 (le high, be low)
220*1fd5a2e1SPrashanth Swaminathan	-8 - f14 (le low, be high)
221*1fd5a2e1SPrashanth Swaminathan	-9 - f12 (le high, be low)
222*1fd5a2e1SPrashanth Swaminathan       -10 - f12 (le low, be high)
223*1fd5a2e1SPrashanth Swaminathan       -11 - Called function a5 save
224*1fd5a2e1SPrashanth Swaminathan       -12 - Called function a4 save
225*1fd5a2e1SPrashanth Swaminathan       -13 - Called function a3 save
226*1fd5a2e1SPrashanth Swaminathan       -14 - Called function a2 save
227*1fd5a2e1SPrashanth Swaminathan       -15 - Called function a1 save
228*1fd5a2e1SPrashanth Swaminathan       -16 - Called function a0 save, our sp and fp point here
229*1fd5a2e1SPrashanth Swaminathan	 */
230*1fd5a2e1SPrashanth Swaminathan
231*1fd5a2e1SPrashanth Swaminathan#define SIZEOF_FRAME2	(16 * FFI_SIZEOF_ARG)
232*1fd5a2e1SPrashanth Swaminathan#define A3_OFF2		(SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
233*1fd5a2e1SPrashanth Swaminathan#define A2_OFF2		(SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
234*1fd5a2e1SPrashanth Swaminathan#define A1_OFF2		(SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
235*1fd5a2e1SPrashanth Swaminathan#define A0_OFF2		(SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
236*1fd5a2e1SPrashanth Swaminathan#define RA_OFF2		(SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
237*1fd5a2e1SPrashanth Swaminathan#define FP_OFF2		(SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
238*1fd5a2e1SPrashanth Swaminathan#define S0_OFF2		(SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
239*1fd5a2e1SPrashanth Swaminathan#define GP_OFF2		(SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
240*1fd5a2e1SPrashanth Swaminathan#define V1_OFF2		(SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
241*1fd5a2e1SPrashanth Swaminathan#define V0_OFF2		(SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
242*1fd5a2e1SPrashanth Swaminathan#define FA_1_1_OFF2	(SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
243*1fd5a2e1SPrashanth Swaminathan#define FA_1_0_OFF2	(SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
244*1fd5a2e1SPrashanth Swaminathan#define FA_0_1_OFF2	(SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
245*1fd5a2e1SPrashanth Swaminathan#define FA_0_0_OFF2	(SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
246*1fd5a2e1SPrashanth Swaminathan#define CALLED_A5_OFF2  (SIZEOF_FRAME2 - 11 * FFI_SIZEOF_ARG)
247*1fd5a2e1SPrashanth Swaminathan#define CALLED_A4_OFF2  (SIZEOF_FRAME2 - 12 * FFI_SIZEOF_ARG)
248*1fd5a2e1SPrashanth Swaminathan
249*1fd5a2e1SPrashanth Swaminathan	.text
250*1fd5a2e1SPrashanth Swaminathan
251*1fd5a2e1SPrashanth Swaminathan	.align	2
252*1fd5a2e1SPrashanth Swaminathan	.globl	ffi_go_closure_O32
253*1fd5a2e1SPrashanth Swaminathan	.ent	ffi_go_closure_O32
254*1fd5a2e1SPrashanth Swaminathanffi_go_closure_O32:
255*1fd5a2e1SPrashanth Swaminathan$LFB1:
256*1fd5a2e1SPrashanth Swaminathan	# Prologue
257*1fd5a2e1SPrashanth Swaminathan	.frame	$fp, SIZEOF_FRAME2, ra
258*1fd5a2e1SPrashanth Swaminathan	.set	noreorder
259*1fd5a2e1SPrashanth Swaminathan	.cpload	t9
260*1fd5a2e1SPrashanth Swaminathan	.set	reorder
261*1fd5a2e1SPrashanth Swaminathan	SUBU	$sp, SIZEOF_FRAME2
262*1fd5a2e1SPrashanth Swaminathan	.cprestore GP_OFF2
263*1fd5a2e1SPrashanth Swaminathan$LCFI10:
264*1fd5a2e1SPrashanth Swaminathan
265*1fd5a2e1SPrashanth Swaminathan	REG_S	$16, S0_OFF2($sp)	 # Save s0
266*1fd5a2e1SPrashanth Swaminathan	REG_S	$fp, FP_OFF2($sp)	 # Save frame pointer
267*1fd5a2e1SPrashanth Swaminathan	REG_S	ra, RA_OFF2($sp)	 # Save return address
268*1fd5a2e1SPrashanth Swaminathan$LCFI11:
269*1fd5a2e1SPrashanth Swaminathan
270*1fd5a2e1SPrashanth Swaminathan	move	$fp, $sp
271*1fd5a2e1SPrashanth Swaminathan$LCFI12:
272*1fd5a2e1SPrashanth Swaminathan
273*1fd5a2e1SPrashanth Swaminathan	REG_S	a0, A0_OFF2($fp)
274*1fd5a2e1SPrashanth Swaminathan	REG_S	a1, A1_OFF2($fp)
275*1fd5a2e1SPrashanth Swaminathan	REG_S	a2, A2_OFF2($fp)
276*1fd5a2e1SPrashanth Swaminathan	REG_S	a3, A3_OFF2($fp)
277*1fd5a2e1SPrashanth Swaminathan
278*1fd5a2e1SPrashanth Swaminathan	# Load ABI enum to s0
279*1fd5a2e1SPrashanth Swaminathan	REG_L	$16, 4($15)	# cif
280*1fd5a2e1SPrashanth Swaminathan	REG_L	$16, 0($16)	# abi is first member.
281*1fd5a2e1SPrashanth Swaminathan
282*1fd5a2e1SPrashanth Swaminathan	li	$13, 1		# FFI_O32
283*1fd5a2e1SPrashanth Swaminathan	bne	$16, $13, 1f	# Skip fp save if FFI_O32_SOFT_FLOAT
284*1fd5a2e1SPrashanth Swaminathan
285*1fd5a2e1SPrashanth Swaminathan	# Store all possible float/double registers.
286*1fd5a2e1SPrashanth Swaminathan	s.d	$f12, FA_0_0_OFF2($fp)
287*1fd5a2e1SPrashanth Swaminathan	s.d	$f14, FA_1_0_OFF2($fp)
288*1fd5a2e1SPrashanth Swaminathan1:
289*1fd5a2e1SPrashanth Swaminathan	# prepare arguments for ffi_closure_mips_inner_O32
290*1fd5a2e1SPrashanth Swaminathan	REG_L	a0, 4($15)	 # cif
291*1fd5a2e1SPrashanth Swaminathan	REG_L	a1, 8($15)	 # fun
292*1fd5a2e1SPrashanth Swaminathan	move	a2, $15		 # user_data = go closure
293*1fd5a2e1SPrashanth Swaminathan	addu	a3, $fp, V0_OFF2 # rvalue
294*1fd5a2e1SPrashanth Swaminathan
295*1fd5a2e1SPrashanth Swaminathan	addu	t9, $fp, A0_OFF2 # ar
296*1fd5a2e1SPrashanth Swaminathan	REG_S   t9, CALLED_A4_OFF2($fp)
297*1fd5a2e1SPrashanth Swaminathan
298*1fd5a2e1SPrashanth Swaminathan	addu	t9, $fp, FA_0_0_OFF2 #fpr
299*1fd5a2e1SPrashanth Swaminathan	REG_S   t9, CALLED_A5_OFF2($fp)
300*1fd5a2e1SPrashanth Swaminathan
301*1fd5a2e1SPrashanth Swaminathan	b $do_closure
302*1fd5a2e1SPrashanth Swaminathan
303*1fd5a2e1SPrashanth Swaminathan$LFE1:
304*1fd5a2e1SPrashanth Swaminathan	.end ffi_go_closure_O32
305*1fd5a2e1SPrashanth Swaminathan
306*1fd5a2e1SPrashanth Swaminathan	.align	2
307*1fd5a2e1SPrashanth Swaminathan	.globl	ffi_closure_O32
308*1fd5a2e1SPrashanth Swaminathan	.ent	ffi_closure_O32
309*1fd5a2e1SPrashanth Swaminathanffi_closure_O32:
310*1fd5a2e1SPrashanth Swaminathan$LFB2:
311*1fd5a2e1SPrashanth Swaminathan	# Prologue
312*1fd5a2e1SPrashanth Swaminathan	.frame	$fp, SIZEOF_FRAME2, ra
313*1fd5a2e1SPrashanth Swaminathan	.set	noreorder
314*1fd5a2e1SPrashanth Swaminathan	.cpload	t9
315*1fd5a2e1SPrashanth Swaminathan	.set	reorder
316*1fd5a2e1SPrashanth Swaminathan	SUBU	$sp, SIZEOF_FRAME2
317*1fd5a2e1SPrashanth Swaminathan	.cprestore GP_OFF2
318*1fd5a2e1SPrashanth Swaminathan$LCFI20:
319*1fd5a2e1SPrashanth Swaminathan	REG_S	$16, S0_OFF2($sp)	 # Save s0
320*1fd5a2e1SPrashanth Swaminathan	REG_S	$fp, FP_OFF2($sp)	 # Save frame pointer
321*1fd5a2e1SPrashanth Swaminathan	REG_S	ra, RA_OFF2($sp)	 # Save return address
322*1fd5a2e1SPrashanth Swaminathan$LCFI21:
323*1fd5a2e1SPrashanth Swaminathan	move	$fp, $sp
324*1fd5a2e1SPrashanth Swaminathan
325*1fd5a2e1SPrashanth Swaminathan$LCFI22:
326*1fd5a2e1SPrashanth Swaminathan	# Store all possible argument registers. If there are more than
327*1fd5a2e1SPrashanth Swaminathan	# four arguments, then they are stored above where we put a3.
328*1fd5a2e1SPrashanth Swaminathan	REG_S	a0, A0_OFF2($fp)
329*1fd5a2e1SPrashanth Swaminathan	REG_S	a1, A1_OFF2($fp)
330*1fd5a2e1SPrashanth Swaminathan	REG_S	a2, A2_OFF2($fp)
331*1fd5a2e1SPrashanth Swaminathan	REG_S	a3, A3_OFF2($fp)
332*1fd5a2e1SPrashanth Swaminathan
333*1fd5a2e1SPrashanth Swaminathan	# Load ABI enum to s0
334*1fd5a2e1SPrashanth Swaminathan	REG_L	$16, 20($12)	# cif pointer follows tramp.
335*1fd5a2e1SPrashanth Swaminathan	REG_L	$16, 0($16)	# abi is first member.
336*1fd5a2e1SPrashanth Swaminathan
337*1fd5a2e1SPrashanth Swaminathan	li	$13, 1		# FFI_O32
338*1fd5a2e1SPrashanth Swaminathan	bne	$16, $13, 1f	# Skip fp save if FFI_O32_SOFT_FLOAT
339*1fd5a2e1SPrashanth Swaminathan
340*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float
341*1fd5a2e1SPrashanth Swaminathan	# Store all possible float/double registers.
342*1fd5a2e1SPrashanth Swaminathan	s.d	$f12, FA_0_0_OFF2($fp)
343*1fd5a2e1SPrashanth Swaminathan	s.d	$f14, FA_1_0_OFF2($fp)
344*1fd5a2e1SPrashanth Swaminathan#endif
345*1fd5a2e1SPrashanth Swaminathan1:
346*1fd5a2e1SPrashanth Swaminathan	# prepare arguments for ffi_closure_mips_inner_O32
347*1fd5a2e1SPrashanth Swaminathan	REG_L	a0, 20($12)	 # cif pointer follows tramp.
348*1fd5a2e1SPrashanth Swaminathan	REG_L	a1, 24($12)	 # fun
349*1fd5a2e1SPrashanth Swaminathan	REG_L	a2, 28($12)	 # user_data
350*1fd5a2e1SPrashanth Swaminathan	addu	a3, $fp, V0_OFF2 # rvalue
351*1fd5a2e1SPrashanth Swaminathan
352*1fd5a2e1SPrashanth Swaminathan	addu	t9, $fp, A0_OFF2 # ar
353*1fd5a2e1SPrashanth Swaminathan	REG_S   t9, CALLED_A4_OFF2($fp)
354*1fd5a2e1SPrashanth Swaminathan
355*1fd5a2e1SPrashanth Swaminathan	addu	t9, $fp, FA_0_0_OFF2 #fpr
356*1fd5a2e1SPrashanth Swaminathan	REG_S   t9, CALLED_A5_OFF2($fp)
357*1fd5a2e1SPrashanth Swaminathan
358*1fd5a2e1SPrashanth Swaminathan$do_closure:
359*1fd5a2e1SPrashanth Swaminathan	la	t9, ffi_closure_mips_inner_O32
360*1fd5a2e1SPrashanth Swaminathan	# Call ffi_closure_mips_inner_O32 to do the work.
361*1fd5a2e1SPrashanth Swaminathan	jalr	t9
362*1fd5a2e1SPrashanth Swaminathan
363*1fd5a2e1SPrashanth Swaminathan	# Load the return value into the appropriate register.
364*1fd5a2e1SPrashanth Swaminathan	move	$8, $2
365*1fd5a2e1SPrashanth Swaminathan	li	$9, FFI_TYPE_VOID
366*1fd5a2e1SPrashanth Swaminathan	beq	$8, $9, closure_done
367*1fd5a2e1SPrashanth Swaminathan
368*1fd5a2e1SPrashanth Swaminathan	li	$13, 1		# FFI_O32
369*1fd5a2e1SPrashanth Swaminathan	bne	$16, $13, 1f	# Skip fp restore if FFI_O32_SOFT_FLOAT
370*1fd5a2e1SPrashanth Swaminathan
371*1fd5a2e1SPrashanth Swaminathan#ifndef __mips_soft_float
372*1fd5a2e1SPrashanth Swaminathan	li	$9, FFI_TYPE_FLOAT
373*1fd5a2e1SPrashanth Swaminathan	l.s	$f0, V0_OFF2($fp)
374*1fd5a2e1SPrashanth Swaminathan	beq	$8, $9, closure_done
375*1fd5a2e1SPrashanth Swaminathan
376*1fd5a2e1SPrashanth Swaminathan	li	$9, FFI_TYPE_DOUBLE
377*1fd5a2e1SPrashanth Swaminathan	l.d	$f0, V0_OFF2($fp)
378*1fd5a2e1SPrashanth Swaminathan	beq	$8, $9, closure_done
379*1fd5a2e1SPrashanth Swaminathan#endif
380*1fd5a2e1SPrashanth Swaminathan1:
381*1fd5a2e1SPrashanth Swaminathan	REG_L	$3, V1_OFF2($fp)
382*1fd5a2e1SPrashanth Swaminathan	REG_L	$2, V0_OFF2($fp)
383*1fd5a2e1SPrashanth Swaminathan
384*1fd5a2e1SPrashanth Swaminathanclosure_done:
385*1fd5a2e1SPrashanth Swaminathan	# Epilogue
386*1fd5a2e1SPrashanth Swaminathan	move	$sp, $fp
387*1fd5a2e1SPrashanth Swaminathan	REG_L	$16, S0_OFF2($sp)	 # Restore s0
388*1fd5a2e1SPrashanth Swaminathan	REG_L	$fp, FP_OFF2($sp)	 # Restore frame pointer
389*1fd5a2e1SPrashanth Swaminathan	REG_L	ra,  RA_OFF2($sp)	 # Restore return address
390*1fd5a2e1SPrashanth Swaminathan	ADDU	$sp, SIZEOF_FRAME2
391*1fd5a2e1SPrashanth Swaminathan	j	ra
392*1fd5a2e1SPrashanth Swaminathan$LFE2:
393*1fd5a2e1SPrashanth Swaminathan	.end	ffi_closure_O32
394*1fd5a2e1SPrashanth Swaminathan
395*1fd5a2e1SPrashanth Swaminathan/* DWARF-2 unwind info. */
396*1fd5a2e1SPrashanth Swaminathan
397*1fd5a2e1SPrashanth Swaminathan	.section	.eh_frame,"a",@progbits
398*1fd5a2e1SPrashanth Swaminathan$Lframe0:
399*1fd5a2e1SPrashanth Swaminathan	.4byte	$LECIE0-$LSCIE0	 # Length of Common Information Entry
400*1fd5a2e1SPrashanth Swaminathan$LSCIE0:
401*1fd5a2e1SPrashanth Swaminathan	.4byte	0x0	 # CIE Identifier Tag
402*1fd5a2e1SPrashanth Swaminathan	.byte	0x1	 # CIE Version
403*1fd5a2e1SPrashanth Swaminathan	.ascii "zR\0"	 # CIE Augmentation
404*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1	 # CIE Code Alignment Factor
405*1fd5a2e1SPrashanth Swaminathan	.sleb128 4	 # CIE Data Alignment Factor
406*1fd5a2e1SPrashanth Swaminathan	.byte	0x1f	 # CIE RA Column
407*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1	 # Augmentation size
408*1fd5a2e1SPrashanth Swaminathan	.byte	0x00	 # FDE Encoding (absptr)
409*1fd5a2e1SPrashanth Swaminathan	.byte	0xc	 # DW_CFA_def_cfa
410*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1d
411*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x0
412*1fd5a2e1SPrashanth Swaminathan	.align	2
413*1fd5a2e1SPrashanth Swaminathan$LECIE0:
414*1fd5a2e1SPrashanth Swaminathan
415*1fd5a2e1SPrashanth Swaminathan$LSFDE0:
416*1fd5a2e1SPrashanth Swaminathan	.4byte	$LEFDE0-$LASFDE0	 # FDE Length
417*1fd5a2e1SPrashanth Swaminathan$LASFDE0:
418*1fd5a2e1SPrashanth Swaminathan	.4byte	$LASFDE0-$Lframe0	 # FDE CIE offset
419*1fd5a2e1SPrashanth Swaminathan	.4byte	$LFB0	 # FDE initial location
420*1fd5a2e1SPrashanth Swaminathan	.4byte	$LFE0-$LFB0	 # FDE address range
421*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x0	 # Augmentation size
422*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
423*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI00-$LFB0
424*1fd5a2e1SPrashanth Swaminathan	.byte	0xe	 # DW_CFA_def_cfa_offset
425*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x18
426*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
427*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI01-$LCFI00
428*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
429*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1e	 # $fp
430*1fd5a2e1SPrashanth Swaminathan	.sleb128 -2	 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
431*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
432*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1f	 # $ra
433*1fd5a2e1SPrashanth Swaminathan	.sleb128 -1	 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
434*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
435*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI02-$LCFI01
436*1fd5a2e1SPrashanth Swaminathan	.byte	0xc	 # DW_CFA_def_cfa
437*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1e
438*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x18
439*1fd5a2e1SPrashanth Swaminathan	.align	2
440*1fd5a2e1SPrashanth Swaminathan$LEFDE0:
441*1fd5a2e1SPrashanth Swaminathan
442*1fd5a2e1SPrashanth Swaminathan$LSFDE1:
443*1fd5a2e1SPrashanth Swaminathan	.4byte	$LEFDE1-$LASFDE1	 # FDE Length
444*1fd5a2e1SPrashanth Swaminathan$LASFDE1:
445*1fd5a2e1SPrashanth Swaminathan	.4byte	$LASFDE1-$Lframe0	 # FDE CIE offset
446*1fd5a2e1SPrashanth Swaminathan	.4byte	$LFB1	 # FDE initial location
447*1fd5a2e1SPrashanth Swaminathan	.4byte	$LFE1-$LFB1	 # FDE address range
448*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x0	 # Augmentation size
449*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
450*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI10-$LFB1
451*1fd5a2e1SPrashanth Swaminathan	.byte	0xe	 # DW_CFA_def_cfa_offset
452*1fd5a2e1SPrashanth Swaminathan	.uleb128 SIZEOF_FRAME2
453*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
454*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI11-$LCFI10
455*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
456*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x10	 # $16
457*1fd5a2e1SPrashanth Swaminathan	.sleb128 -3	 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
458*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
459*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1e	 # $fp
460*1fd5a2e1SPrashanth Swaminathan	.sleb128 -2	 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
461*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
462*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1f	 # $ra
463*1fd5a2e1SPrashanth Swaminathan	.sleb128 -1	 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
464*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
465*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI12-$LCFI11
466*1fd5a2e1SPrashanth Swaminathan	.byte	0xc	 # DW_CFA_def_cfa
467*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1e
468*1fd5a2e1SPrashanth Swaminathan	.uleb128 SIZEOF_FRAME2
469*1fd5a2e1SPrashanth Swaminathan	.align	2
470*1fd5a2e1SPrashanth Swaminathan$LEFDE1:
471*1fd5a2e1SPrashanth Swaminathan
472*1fd5a2e1SPrashanth Swaminathan$LSFDE2:
473*1fd5a2e1SPrashanth Swaminathan	.4byte	$LEFDE2-$LASFDE2	 # FDE Length
474*1fd5a2e1SPrashanth Swaminathan$LASFDE2:
475*1fd5a2e1SPrashanth Swaminathan	.4byte	$LASFDE2-$Lframe0	 # FDE CIE offset
476*1fd5a2e1SPrashanth Swaminathan	.4byte	$LFB2	 # FDE initial location
477*1fd5a2e1SPrashanth Swaminathan	.4byte	$LFE2-$LFB2	 # FDE address range
478*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x0	 # Augmentation size
479*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
480*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI20-$LFB2
481*1fd5a2e1SPrashanth Swaminathan	.byte	0xe	 # DW_CFA_def_cfa_offset
482*1fd5a2e1SPrashanth Swaminathan	.uleb128 SIZEOF_FRAME2
483*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
484*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI21-$LCFI20
485*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
486*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x10	 # $16
487*1fd5a2e1SPrashanth Swaminathan	.sleb128 -3	 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
488*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
489*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1e	 # $fp
490*1fd5a2e1SPrashanth Swaminathan	.sleb128 -2	 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
491*1fd5a2e1SPrashanth Swaminathan	.byte	0x11	 # DW_CFA_offset_extended_sf
492*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1f	 # $ra
493*1fd5a2e1SPrashanth Swaminathan	.sleb128 -1	 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
494*1fd5a2e1SPrashanth Swaminathan	.byte	0x4	 # DW_CFA_advance_loc4
495*1fd5a2e1SPrashanth Swaminathan	.4byte	$LCFI22-$LCFI21
496*1fd5a2e1SPrashanth Swaminathan	.byte	0xc	 # DW_CFA_def_cfa
497*1fd5a2e1SPrashanth Swaminathan	.uleb128 0x1e
498*1fd5a2e1SPrashanth Swaminathan	.uleb128 SIZEOF_FRAME2
499*1fd5a2e1SPrashanth Swaminathan	.align	2
500*1fd5a2e1SPrashanth Swaminathan$LEFDE2:
501*1fd5a2e1SPrashanth Swaminathan
502*1fd5a2e1SPrashanth Swaminathan#endif
503