• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* -----------------------------------------------------------------------
2   n32.S - Copyright (c) 1996, 1998, 2005, 2007, 2009, 2010  Red Hat, Inc.
3
4   MIPS Foreign Function Interface
5
6   Permission is hereby granted, free of charge, to any person obtaining
7   a copy of this software and associated documentation files (the
8   ``Software''), to deal in the Software without restriction, including
9   without limitation the rights to use, copy, modify, merge, publish,
10   distribute, sublicense, and/or sell copies of the Software, and to
11   permit persons to whom the Software is furnished to do so, subject to
12   the following conditions:
13
14   The above copyright notice and this permission notice shall be included
15   in all copies or substantial portions of the Software.
16
17   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24   DEALINGS IN THE SOFTWARE.
25   ----------------------------------------------------------------------- */
26
27#define LIBFFI_ASM
28#include <fficonfig.h>
29#include <ffi.h>
30
31/* Only build this code if we are compiling for n32 */
32
33#if defined(FFI_MIPS_N32)
34
35#define callback a0
36#define bytes	 a2
37#define flags	 a3
38#define raddr    a4
39#define fn       a5
40#define closure  a6
41
42/* Note: to keep stack 16 byte aligned we need even number slots
43   used 9 slots here
44*/
45#define SIZEOF_FRAME	( 10 * FFI_SIZEOF_ARG )
46
47#ifdef __GNUC__
48	.abicalls
49#endif
50#if !defined(__mips_isa_rev) || (__mips_isa_rev<6)
51	.set mips4
52#endif
53	.text
54	.align	2
55	.globl	ffi_call_N32
56	.ent	ffi_call_N32
57ffi_call_N32:
58.LFB0:
59	.frame	$fp, SIZEOF_FRAME, ra
60	.mask	0xc0000000,-FFI_SIZEOF_ARG
61	.fmask	0x00000000,0
62
63	# Prologue
64	SUBU	$sp, SIZEOF_FRAME			# Frame size
65.LCFI00:
66	REG_S	$fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp)	# Save frame pointer
67	REG_S	ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)	# Save return address
68.LCFI01:
69	move	$fp, $sp
70.LCFI02:
71	move	t9, callback	# callback function pointer
72	REG_S	bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
73	REG_S	flags, 3*FFI_SIZEOF_ARG($fp) # flags
74	REG_S	raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
75	REG_S	fn,    5*FFI_SIZEOF_ARG($fp) # fn
76	REG_S	closure, 6*FFI_SIZEOF_ARG($fp) # closure
77
78	# Allocate at least 4 words in the argstack
79	move	v0, bytes
80	bge	bytes, 4 * FFI_SIZEOF_ARG, bigger
81	LI	v0, 4 * FFI_SIZEOF_ARG
82	b	sixteen
83
84	bigger:
85	ADDU	t4, v0, 2 * FFI_SIZEOF_ARG -1	# make sure it is aligned
86	and	v0, t4, -2 * FFI_SIZEOF_ARG		# to a proper boundry.
87
88sixteen:
89	SUBU	$sp, $sp, v0	# move the stack pointer to reflect the
90				# arg space
91
92	move	a0, $sp         # 4 * FFI_SIZEOF_ARG
93	ADDU	a3, $fp, 3 * FFI_SIZEOF_ARG
94
95	# Call ffi_prep_args
96	jal	t9
97
98	# Copy the stack pointer to t9
99	move	t9, $sp
100
101	# Fix the stack if there are more than 8 64bit slots worth
102	# of arguments.
103
104	# Load the number of bytes
105	REG_L	t6, 2*FFI_SIZEOF_ARG($fp)
106
107	# Is it bigger than 8 * FFI_SIZEOF_ARG?
108	daddiu	t8, t6, -(8 * FFI_SIZEOF_ARG)
109	bltz	t8, loadregs
110
111	ADDU	t9, t9, t8
112
113loadregs:
114
115	REG_L	t6, 3*FFI_SIZEOF_ARG($fp)  # load the flags word into t6.
116
117#ifdef __mips_soft_float
118	REG_L	a0, 0*FFI_SIZEOF_ARG(t9)
119	REG_L	a1, 1*FFI_SIZEOF_ARG(t9)
120	REG_L	a2, 2*FFI_SIZEOF_ARG(t9)
121	REG_L	a3, 3*FFI_SIZEOF_ARG(t9)
122	REG_L	a4, 4*FFI_SIZEOF_ARG(t9)
123	REG_L	a5, 5*FFI_SIZEOF_ARG(t9)
124	REG_L	a6, 6*FFI_SIZEOF_ARG(t9)
125	REG_L	a7, 7*FFI_SIZEOF_ARG(t9)
126#else
127	and	t4, t6, ((1<<FFI_FLAG_BITS)-1)
128	REG_L	a0, 0*FFI_SIZEOF_ARG(t9)
129	beqz	t4, arg1_next
130	bne	t4, FFI_TYPE_FLOAT, arg1_doublep
131	l.s	$f12, 0*FFI_SIZEOF_ARG(t9)
132	b	arg1_next
133arg1_doublep:
134	l.d	$f12, 0*FFI_SIZEOF_ARG(t9)
135arg1_next:
136
137	SRL	t4, t6, 1*FFI_FLAG_BITS
138	and	t4, ((1<<FFI_FLAG_BITS)-1)
139	REG_L	a1, 1*FFI_SIZEOF_ARG(t9)
140	beqz	t4, arg2_next
141	bne	t4, FFI_TYPE_FLOAT, arg2_doublep
142	l.s	$f13, 1*FFI_SIZEOF_ARG(t9)
143	b	arg2_next
144arg2_doublep:
145	l.d	$f13, 1*FFI_SIZEOF_ARG(t9)
146arg2_next:
147
148	SRL	t4, t6, 2*FFI_FLAG_BITS
149	and	t4, ((1<<FFI_FLAG_BITS)-1)
150	REG_L	a2, 2*FFI_SIZEOF_ARG(t9)
151	beqz	t4, arg3_next
152	bne	t4, FFI_TYPE_FLOAT, arg3_doublep
153	l.s	$f14, 2*FFI_SIZEOF_ARG(t9)
154	b	arg3_next
155arg3_doublep:
156	l.d	$f14, 2*FFI_SIZEOF_ARG(t9)
157arg3_next:
158
159	SRL	t4, t6, 3*FFI_FLAG_BITS
160	and	t4, ((1<<FFI_FLAG_BITS)-1)
161	REG_L	a3, 3*FFI_SIZEOF_ARG(t9)
162	beqz	t4, arg4_next
163	bne	t4, FFI_TYPE_FLOAT, arg4_doublep
164	l.s	$f15, 3*FFI_SIZEOF_ARG(t9)
165	b	arg4_next
166arg4_doublep:
167	l.d	$f15, 3*FFI_SIZEOF_ARG(t9)
168arg4_next:
169
170	SRL	t4, t6, 4*FFI_FLAG_BITS
171	and	t4, ((1<<FFI_FLAG_BITS)-1)
172	REG_L	a4, 4*FFI_SIZEOF_ARG(t9)
173	beqz	t4, arg5_next
174	bne	t4, FFI_TYPE_FLOAT, arg5_doublep
175	l.s	$f16, 4*FFI_SIZEOF_ARG(t9)
176	b	arg5_next
177arg5_doublep:
178	l.d	$f16, 4*FFI_SIZEOF_ARG(t9)
179arg5_next:
180
181	SRL	t4, t6, 5*FFI_FLAG_BITS
182	and	t4, ((1<<FFI_FLAG_BITS)-1)
183	REG_L	a5, 5*FFI_SIZEOF_ARG(t9)
184	beqz	t4, arg6_next
185	bne	t4, FFI_TYPE_FLOAT, arg6_doublep
186	l.s	$f17, 5*FFI_SIZEOF_ARG(t9)
187	b	arg6_next
188arg6_doublep:
189	l.d	$f17, 5*FFI_SIZEOF_ARG(t9)
190arg6_next:
191
192	SRL	t4, t6, 6*FFI_FLAG_BITS
193	and	t4, ((1<<FFI_FLAG_BITS)-1)
194	REG_L	a6, 6*FFI_SIZEOF_ARG(t9)
195	beqz	t4, arg7_next
196	bne	t4, FFI_TYPE_FLOAT, arg7_doublep
197	l.s	$f18, 6*FFI_SIZEOF_ARG(t9)
198	b	arg7_next
199arg7_doublep:
200	l.d	$f18, 6*FFI_SIZEOF_ARG(t9)
201arg7_next:
202
203	SRL	t4, t6, 7*FFI_FLAG_BITS
204	and	t4, ((1<<FFI_FLAG_BITS)-1)
205	REG_L	a7, 7*FFI_SIZEOF_ARG(t9)
206	beqz	t4, arg8_next
207	bne	t4, FFI_TYPE_FLOAT, arg8_doublep
208 	l.s	$f19, 7*FFI_SIZEOF_ARG(t9)
209	b	arg8_next
210arg8_doublep:
211 	l.d	$f19, 7*FFI_SIZEOF_ARG(t9)
212arg8_next:
213#endif
214
215callit:
216	# Load the function pointer
217	REG_L	t9, 5*FFI_SIZEOF_ARG($fp)
218
219	# install the static chain(t7=$15)
220	REG_L	t7, 6*FFI_SIZEOF_ARG($fp)
221
222	# If the return value pointer is NULL, assume no return value.
223	REG_L	t5, 4*FFI_SIZEOF_ARG($fp)
224	beqz	t5, noretval
225
226	# Shift the return type flag over
227	SRL	t6, 8*FFI_FLAG_BITS
228
229	beq	t6, FFI_TYPE_SINT32, retint
230	bne     t6, FFI_TYPE_INT, retfloat
231retint:
232	jal	t9
233	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
234	REG_S	v0, 0(t4)
235	b	epilogue
236
237retfloat:
238#ifndef __mips_soft_float
239	bne     t6, FFI_TYPE_FLOAT, retdouble
240	jal	t9
241	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
242	s.s	$f0, 0(t4)
243	b	epilogue
244
245retdouble:
246	bne	t6, FFI_TYPE_DOUBLE, retstruct_d
247	jal	t9
248	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
249	s.d	$f0, 0(t4)
250	b	epilogue
251
252retstruct_d:
253	bne	t6, FFI_TYPE_STRUCT_D, retstruct_f
254	jal	t9
255	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
256	s.d	$f0, 0(t4)
257	b	epilogue
258
259retstruct_f:
260	bne	t6, FFI_TYPE_STRUCT_F, retstruct_d_d
261	jal	t9
262	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
263	s.s	$f0, 0(t4)
264	b	epilogue
265
266retstruct_d_d:
267	bne	t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
268	jal	t9
269	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
270	s.d	$f0, 0(t4)
271	s.d	$f2, 8(t4)
272	b	epilogue
273
274retstruct_f_f:
275	bne	t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
276	jal	t9
277	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
278	s.s	$f0, 0(t4)
279	s.s	$f2, 4(t4)
280	b	epilogue
281
282retstruct_d_f:
283	bne	t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
284	jal	t9
285	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
286	s.d	$f0, 0(t4)
287	s.s	$f2, 8(t4)
288	b	epilogue
289
290retstruct_f_d:
291	bne	t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft
292	jal	t9
293	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
294	s.s	$f0, 0(t4)
295	s.d	$f2, 8(t4)
296	b	epilogue
297#endif
298
299retstruct_d_soft:
300	bne	t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft
301	jal	t9
302	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
303	sd	v0, 0(t4)
304	b	epilogue
305
306retstruct_f_soft:
307	bne	t6, FFI_TYPE_STRUCT_F_SOFT, retstruct_d_d_soft
308	jal	t9
309	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
310	sw	v0, 0(t4)
311	b	epilogue
312
313retstruct_d_d_soft:
314	bne	t6, FFI_TYPE_STRUCT_DD_SOFT, retstruct_f_f_soft
315	jal	t9
316	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
317	sd	v0, 0(t4)
318	sd	v1, 8(t4)
319	b	epilogue
320
321retstruct_f_f_soft:
322	bne	t6, FFI_TYPE_STRUCT_FF_SOFT, retstruct_d_f_soft
323	jal	t9
324	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
325	sw	v0, 0(t4)
326	sw	v1, 4(t4)
327	b	epilogue
328
329retstruct_d_f_soft:
330	bne	t6, FFI_TYPE_STRUCT_DF_SOFT, retstruct_f_d_soft
331	jal	t9
332	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
333	sd	v0, 0(t4)
334	sw	v1, 8(t4)
335	b	epilogue
336
337retstruct_f_d_soft:
338	bne	t6, FFI_TYPE_STRUCT_FD_SOFT, retstruct_small
339	jal	t9
340	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
341	sw	v0, 0(t4)
342	sd	v1, 8(t4)
343	b	epilogue
344
345retstruct_small:
346	bne	t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
347	jal	t9
348	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
349	REG_S	v0, 0(t4)
350	b	epilogue
351
352retstruct_small2:
353	bne	t6, FFI_TYPE_STRUCT_SMALL2, retstruct
354	jal	t9
355	REG_L	t4, 4*FFI_SIZEOF_ARG($fp)
356	REG_S	v0, 0(t4)
357	REG_S	v1, 8(t4)
358	b	epilogue
359
360retstruct:
361noretval:
362	jal	t9
363
364	# Epilogue
365epilogue:
366	move	$sp, $fp
367	REG_L	$fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
368	REG_L	ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)  # Restore return address
369	ADDU	$sp, SIZEOF_FRAME		      # Fix stack pointer
370	j	ra
371
372.LFE0:
373	.end	ffi_call_N32
374
375/* ffi_closure_N32. Expects address of the passed-in ffi_closure in t0
376   ($12). Stores any arguments passed in registers onto the stack,
377   then calls ffi_closure_mips_inner_N32, which then decodes
378   them.
379
380	Stack layout:
381
382	20 - Start of parameters, original sp
383	19 - Called function a7 save
384	18 - Called function a6 save
385	17 - Called function a5 save
386	16 - Called function a4 save
387	15 - Called function a3 save
388	14 - Called function a2 save
389	13 - Called function a1 save
390	12 - Called function a0 save
391	11 - Called function f19
392	10 - Called function f18
393	 9 - Called function f17
394	 8 - Called function f16
395	 7 - Called function f15
396         6 - Called function f14
397         5 - Called function f13
398         4 - Called function f12
399	 3 - return value high (v1 or $f2)
400	 2 - return value low (v0 or $f0)
401	 1 - ra save
402	 0 - gp save our sp  points here
403	 */
404
405#define SIZEOF_FRAME2	(20 * FFI_SIZEOF_ARG)
406
407#define A7_OFF2		(19 * FFI_SIZEOF_ARG)
408#define A6_OFF2		(18 * FFI_SIZEOF_ARG)
409#define A5_OFF2		(17 * FFI_SIZEOF_ARG)
410#define A4_OFF2		(16 * FFI_SIZEOF_ARG)
411#define A3_OFF2		(15 * FFI_SIZEOF_ARG)
412#define A2_OFF2		(14 * FFI_SIZEOF_ARG)
413#define A1_OFF2		(13 * FFI_SIZEOF_ARG)
414#define A0_OFF2		(12 * FFI_SIZEOF_ARG)
415
416#define F19_OFF2	(11 * FFI_SIZEOF_ARG)
417#define F18_OFF2	(10 * FFI_SIZEOF_ARG)
418#define F17_OFF2	(9  * FFI_SIZEOF_ARG)
419#define F16_OFF2	(8  * FFI_SIZEOF_ARG)
420#define F15_OFF2	(7  * FFI_SIZEOF_ARG)
421#define F14_OFF2	(6  * FFI_SIZEOF_ARG)
422#define F13_OFF2	(5  * FFI_SIZEOF_ARG)
423#define F12_OFF2	(4  * FFI_SIZEOF_ARG)
424
425#define V1_OFF2		(3  * FFI_SIZEOF_ARG)
426#define V0_OFF2		(2  * FFI_SIZEOF_ARG)
427
428#define RA_OFF2		(1  * FFI_SIZEOF_ARG)
429#define GP_OFF2		(0  * FFI_SIZEOF_ARG)
430
431	.align	2
432	.globl	ffi_go_closure_N32
433	.ent	ffi_go_closure_N32
434ffi_go_closure_N32:
435.LFB1:
436	.frame	$sp, SIZEOF_FRAME2, ra
437	.mask	0x90000000,-(SIZEOF_FRAME2 - RA_OFF2)
438	.fmask	0x00000000,0
439	SUBU	$sp, SIZEOF_FRAME2
440.LCFI10:
441	.cpsetup t9, GP_OFF2, ffi_go_closure_N32
442	REG_S	ra, RA_OFF2($sp)	# Save return address
443.LCFI11:
444
445	REG_S	a0, A0_OFF2($sp)
446	REG_S	a1, A1_OFF2($sp)
447	REG_S	a2, A2_OFF2($sp)
448	REG_S	a3, A3_OFF2($sp)
449	REG_S	a4, A4_OFF2($sp)
450	REG_S	a5, A5_OFF2($sp)
451
452	# Call ffi_closure_mips_inner_N32 to do the real work.
453	LA	t9, ffi_closure_mips_inner_N32
454	REG_L	a0, 8($15)   # cif
455	REG_L	a1, 16($15) # fun
456	move	a2, t7                     # userdata=closure
457	ADDU	a3, $sp, V0_OFF2           # rvalue
458	ADDU	a4, $sp, A0_OFF2           # ar
459	ADDU	a5, $sp, F12_OFF2          # fpr
460
461	b	$do_closure
462
463.LFE1:
464	.end	ffi_go_closure_N32
465
466	.align	2
467	.globl	ffi_closure_N32
468	.ent	ffi_closure_N32
469ffi_closure_N32:
470.LFB2:
471	.frame	$sp, SIZEOF_FRAME2, ra
472	.mask	0x90000000,-(SIZEOF_FRAME2 - RA_OFF2)
473	.fmask	0x00000000,0
474	SUBU	$sp, SIZEOF_FRAME2
475.LCFI20:
476	.cpsetup t9, GP_OFF2, ffi_closure_N32
477	REG_S	ra, RA_OFF2($sp)	# Save return address
478.LCFI21:
479	REG_S	a0, A0_OFF2($sp)
480	REG_S	a1, A1_OFF2($sp)
481	REG_S	a2, A2_OFF2($sp)
482	REG_S	a3, A3_OFF2($sp)
483	REG_S	a4, A4_OFF2($sp)
484	REG_S	a5, A5_OFF2($sp)
485
486	# Call ffi_closure_mips_inner_N32 to do the real work.
487	LA	t9, ffi_closure_mips_inner_N32
488	REG_L	a0, 56($12)   # cif
489	REG_L	a1, 64($12)   # fun
490	REG_L	a2, 72($12) # user_data
491	ADDU	a3, $sp, V0_OFF2
492	ADDU	a4, $sp, A0_OFF2
493	ADDU	a5, $sp, F12_OFF2
494
495$do_closure:
496	# Store all possible argument registers. If there are more than
497	# fit in registers, then they were stored on the stack.
498	REG_S	a6, A6_OFF2($sp)
499	REG_S	a7, A7_OFF2($sp)
500
501#ifndef __mips_soft_float
502	# Store all possible float/double registers.
503	s.d	$f12, F12_OFF2($sp)
504	s.d	$f13, F13_OFF2($sp)
505	s.d	$f14, F14_OFF2($sp)
506	s.d	$f15, F15_OFF2($sp)
507	s.d	$f16, F16_OFF2($sp)
508	s.d	$f17, F17_OFF2($sp)
509	s.d	$f18, F18_OFF2($sp)
510	s.d	$f19, F19_OFF2($sp)
511#endif
512
513	jalr	t9
514
515	# Return flags are in v0
516	bne     v0, FFI_TYPE_SINT32, cls_retint
517	lw	v0, V0_OFF2($sp)
518	b	cls_epilogue
519
520cls_retint:
521	bne     v0, FFI_TYPE_INT, cls_retfloat
522	REG_L	v0, V0_OFF2($sp)
523	b	cls_epilogue
524
525cls_retfloat:
526#ifndef __mips_soft_float
527	bne     v0, FFI_TYPE_FLOAT, cls_retdouble
528	l.s	$f0, V0_OFF2($sp)
529	b	cls_epilogue
530
531cls_retdouble:
532	bne	v0, FFI_TYPE_DOUBLE, cls_retstruct_d
533	l.d	$f0, V0_OFF2($sp)
534	b	cls_epilogue
535
536cls_retstruct_d:
537	bne	v0, FFI_TYPE_STRUCT_D, cls_retstruct_f
538	l.d	$f0, V0_OFF2($sp)
539	b	cls_epilogue
540
541cls_retstruct_f:
542	bne	v0, FFI_TYPE_STRUCT_F, cls_retstruct_d_d
543	l.s	$f0, V0_OFF2($sp)
544	b	cls_epilogue
545
546cls_retstruct_d_d:
547	bne	v0, FFI_TYPE_STRUCT_DD, cls_retstruct_f_f
548	l.d	$f0, V0_OFF2($sp)
549	l.d	$f2, V1_OFF2($sp)
550	b	cls_epilogue
551
552cls_retstruct_f_f:
553	bne	v0, FFI_TYPE_STRUCT_FF, cls_retstruct_d_f
554	l.s	$f0, V0_OFF2($sp)
555	l.s	$f2, V1_OFF2($sp)
556	b	cls_epilogue
557
558cls_retstruct_d_f:
559	bne	v0, FFI_TYPE_STRUCT_DF, cls_retstruct_f_d
560	l.d	$f0, V0_OFF2($sp)
561	l.s	$f2, V1_OFF2($sp)
562	b	cls_epilogue
563
564cls_retstruct_f_d:
565	bne	v0, FFI_TYPE_STRUCT_FD, cls_retstruct_small2
566	l.s	$f0, V0_OFF2($sp)
567	l.d	$f2, V1_OFF2($sp)
568	b	cls_epilogue
569#endif
570
571cls_retstruct_small2:
572	REG_L	v0, V0_OFF2($sp)
573	REG_L	v1, V1_OFF2($sp)
574
575	# Epilogue
576cls_epilogue:
577	REG_L	ra,  RA_OFF2($sp)	 # Restore return address
578	.cpreturn
579	ADDU	$sp, SIZEOF_FRAME2
580	j	ra
581.LFE2:
582	.end	ffi_closure_N32
583
584#ifdef __GNUC__
585        .section        .eh_frame,"aw",@progbits
586.Lframe1:
587        .4byte  .LECIE1-.LSCIE1		# length
588.LSCIE1:
589        .4byte  0x0			# CIE
590        .byte   0x1			# Version 1
591        .ascii  "\000"			# Augmentation
592        .uleb128 0x1			# Code alignment 1
593        .sleb128 -4			# Data alignment -4
594        .byte   0x1f			# Return Address $31
595        .byte   0xc			# DW_CFA_def_cfa
596        .uleb128 0x1d			# in $sp
597        .uleb128 0x0			# offset 0
598        .align  EH_FRAME_ALIGN
599.LECIE1:
600
601.LSFDE0:
602        .4byte  .LEFDE0-.LASFDE0	# length.
603.LASFDE0:
604        .4byte  .LASFDE0-.Lframe1	# CIE_pointer.
605        FDE_ADDR_BYTES  .LFB0		# initial_location.
606        FDE_ADDR_BYTES  .LFE0-.LFB0	# address_range.
607        .byte   0x4			# DW_CFA_advance_loc4
608        .4byte  .LCFI00-.LFB0		# to .LCFI00
609        .byte   0xe			# DW_CFA_def_cfa_offset
610        .uleb128 SIZEOF_FRAME		# adjust stack.by SIZEOF_FRAME
611        .byte   0x4			# DW_CFA_advance_loc4
612        .4byte  .LCFI01-.LCFI00		# to .LCFI01
613        .byte   0x9e			# DW_CFA_offset of $fp
614        .uleb128 2*FFI_SIZEOF_ARG/4	#
615        .byte   0x9f			# DW_CFA_offset of ra
616        .uleb128 1*FFI_SIZEOF_ARG/4	#
617        .byte   0x4			# DW_CFA_advance_loc4
618        .4byte  .LCFI02-.LCFI01		# to .LCFI02
619        .byte   0xd			# DW_CFA_def_cfa_register
620        .uleb128 0x1e			# in $fp
621        .align  EH_FRAME_ALIGN
622.LEFDE0:
623
624.LSFDE1:
625	.4byte	.LEFDE1-.LASFDE1	# length
626.LASFDE1:
627	.4byte	.LASFDE1-.Lframe1	# CIE_pointer.
628	FDE_ADDR_BYTES	.LFB1		# initial_location.
629	FDE_ADDR_BYTES	.LFE1-.LFB1	# address_range.
630	.byte	0x4			# DW_CFA_advance_loc4
631	.4byte	.LCFI10-.LFB1		# to .LCFI10
632	.byte	0xe			# DW_CFA_def_cfa_offset
633	.uleb128 SIZEOF_FRAME2		# adjust stack.by SIZEOF_FRAME
634	.byte	0x4			# DW_CFA_advance_loc4
635	.4byte	.LCFI11-.LCFI10		# to .LCFI11
636	.byte	0x9c			# DW_CFA_offset of $gp ($28)
637	.uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4
638	.byte	0x9f			# DW_CFA_offset of ra ($31)
639	.uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4
640	.align	EH_FRAME_ALIGN
641.LEFDE1:
642
643.LSFDE2:
644	.4byte	.LEFDE2-.LASFDE2	# length
645.LASFDE2:
646	.4byte	.LASFDE2-.Lframe1	# CIE_pointer.
647	FDE_ADDR_BYTES	.LFB2		# initial_location.
648	FDE_ADDR_BYTES	.LFE2-.LFB2	# address_range.
649	.byte	0x4			# DW_CFA_advance_loc4
650	.4byte	.LCFI20-.LFB2		# to .LCFI20
651	.byte	0xe			# DW_CFA_def_cfa_offset
652	.uleb128 SIZEOF_FRAME2		# adjust stack.by SIZEOF_FRAME
653	.byte	0x4			# DW_CFA_advance_loc4
654	.4byte	.LCFI21-.LCFI20		# to .LCFI21
655	.byte	0x9c			# DW_CFA_offset of $gp ($28)
656	.uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4
657	.byte	0x9f			# DW_CFA_offset of ra ($31)
658	.uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4
659	.align	EH_FRAME_ALIGN
660.LEFDE2:
661#endif /* __GNUC__ */
662
663#endif
664