111
|
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
|
|
41 #define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG )
|
|
42
|
|
43 #ifdef __GNUC__
|
|
44 .abicalls
|
|
45 #endif
|
|
46 .set mips4
|
|
47 .text
|
|
48 .align 2
|
|
49 .globl ffi_call_N32
|
|
50 .ent ffi_call_N32
|
|
51 ffi_call_N32:
|
|
52 .LFB3:
|
|
53 .frame $fp, SIZEOF_FRAME, ra
|
|
54 .mask 0xc0000000,-FFI_SIZEOF_ARG
|
|
55 .fmask 0x00000000,0
|
|
56
|
|
57 # Prologue
|
|
58 SUBU $sp, SIZEOF_FRAME # Frame size
|
|
59 .LCFI0:
|
|
60 REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
|
|
61 REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
|
|
62 .LCFI1:
|
|
63 move $fp, $sp
|
|
64 .LCFI3:
|
|
65 move t9, callback # callback function pointer
|
|
66 REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
|
|
67 REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags
|
|
68 REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
|
|
69 REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
|
|
70
|
|
71 # Allocate at least 4 words in the argstack
|
|
72 move v0, bytes
|
|
73 bge bytes, 4 * FFI_SIZEOF_ARG, bigger
|
|
74 LI v0, 4 * FFI_SIZEOF_ARG
|
|
75 b sixteen
|
|
76
|
|
77 bigger:
|
|
78 ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned
|
|
79 and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry.
|
|
80
|
|
81 sixteen:
|
|
82 SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
|
83 # arg space
|
|
84
|
|
85 move a0, $sp # 4 * FFI_SIZEOF_ARG
|
|
86 ADDU a3, $fp, 3 * FFI_SIZEOF_ARG
|
|
87
|
|
88 # Call ffi_prep_args
|
|
89 jal t9
|
|
90
|
|
91 # Copy the stack pointer to t9
|
|
92 move t9, $sp
|
|
93
|
|
94 # Fix the stack if there are more than 8 64bit slots worth
|
|
95 # of arguments.
|
|
96
|
|
97 # Load the number of bytes
|
|
98 REG_L t6, 2*FFI_SIZEOF_ARG($fp)
|
|
99
|
|
100 # Is it bigger than 8 * FFI_SIZEOF_ARG?
|
|
101 daddiu t8, t6, -(8 * FFI_SIZEOF_ARG)
|
|
102 bltz t8, loadregs
|
|
103
|
|
104 ADDU t9, t9, t8
|
|
105
|
|
106 loadregs:
|
|
107
|
|
108 REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6.
|
|
109
|
|
110 and t4, t6, ((1<<FFI_FLAG_BITS)-1)
|
|
111 REG_L a0, 0*FFI_SIZEOF_ARG(t9)
|
|
112 beqz t4, arg1_next
|
|
113 bne t4, FFI_TYPE_FLOAT, arg1_doublep
|
|
114 l.s $f12, 0*FFI_SIZEOF_ARG(t9)
|
|
115 b arg1_next
|
|
116 arg1_doublep:
|
|
117 l.d $f12, 0*FFI_SIZEOF_ARG(t9)
|
|
118 arg1_next:
|
|
119
|
|
120 SRL t4, t6, 1*FFI_FLAG_BITS
|
|
121 and t4, ((1<<FFI_FLAG_BITS)-1)
|
|
122 REG_L a1, 1*FFI_SIZEOF_ARG(t9)
|
|
123 beqz t4, arg2_next
|
|
124 bne t4, FFI_TYPE_FLOAT, arg2_doublep
|
|
125 l.s $f13, 1*FFI_SIZEOF_ARG(t9)
|
|
126 b arg2_next
|
|
127 arg2_doublep:
|
|
128 l.d $f13, 1*FFI_SIZEOF_ARG(t9)
|
|
129 arg2_next:
|
|
130
|
|
131 SRL t4, t6, 2*FFI_FLAG_BITS
|
|
132 and t4, ((1<<FFI_FLAG_BITS)-1)
|
|
133 REG_L a2, 2*FFI_SIZEOF_ARG(t9)
|
|
134 beqz t4, arg3_next
|
|
135 bne t4, FFI_TYPE_FLOAT, arg3_doublep
|
|
136 l.s $f14, 2*FFI_SIZEOF_ARG(t9)
|
|
137 b arg3_next
|
|
138 arg3_doublep:
|
|
139 l.d $f14, 2*FFI_SIZEOF_ARG(t9)
|
|
140 arg3_next:
|
|
141
|
|
142 SRL t4, t6, 3*FFI_FLAG_BITS
|
|
143 and t4, ((1<<FFI_FLAG_BITS)-1)
|
|
144 REG_L a3, 3*FFI_SIZEOF_ARG(t9)
|
|
145 beqz t4, arg4_next
|
|
146 bne t4, FFI_TYPE_FLOAT, arg4_doublep
|
|
147 l.s $f15, 3*FFI_SIZEOF_ARG(t9)
|
|
148 b arg4_next
|
|
149 arg4_doublep:
|
|
150 l.d $f15, 3*FFI_SIZEOF_ARG(t9)
|
|
151 arg4_next:
|
|
152
|
|
153 SRL t4, t6, 4*FFI_FLAG_BITS
|
|
154 and t4, ((1<<FFI_FLAG_BITS)-1)
|
|
155 REG_L a4, 4*FFI_SIZEOF_ARG(t9)
|
|
156 beqz t4, arg5_next
|
|
157 bne t4, FFI_TYPE_FLOAT, arg5_doublep
|
|
158 l.s $f16, 4*FFI_SIZEOF_ARG(t9)
|
|
159 b arg5_next
|
|
160 arg5_doublep:
|
|
161 l.d $f16, 4*FFI_SIZEOF_ARG(t9)
|
|
162 arg5_next:
|
|
163
|
|
164 SRL t4, t6, 5*FFI_FLAG_BITS
|
|
165 and t4, ((1<<FFI_FLAG_BITS)-1)
|
|
166 REG_L a5, 5*FFI_SIZEOF_ARG(t9)
|
|
167 beqz t4, arg6_next
|
|
168 bne t4, FFI_TYPE_FLOAT, arg6_doublep
|
|
169 l.s $f17, 5*FFI_SIZEOF_ARG(t9)
|
|
170 b arg6_next
|
|
171 arg6_doublep:
|
|
172 l.d $f17, 5*FFI_SIZEOF_ARG(t9)
|
|
173 arg6_next:
|
|
174
|
|
175 SRL t4, t6, 6*FFI_FLAG_BITS
|
|
176 and t4, ((1<<FFI_FLAG_BITS)-1)
|
|
177 REG_L a6, 6*FFI_SIZEOF_ARG(t9)
|
|
178 beqz t4, arg7_next
|
|
179 bne t4, FFI_TYPE_FLOAT, arg7_doublep
|
|
180 l.s $f18, 6*FFI_SIZEOF_ARG(t9)
|
|
181 b arg7_next
|
|
182 arg7_doublep:
|
|
183 l.d $f18, 6*FFI_SIZEOF_ARG(t9)
|
|
184 arg7_next:
|
|
185
|
|
186 SRL t4, t6, 7*FFI_FLAG_BITS
|
|
187 and t4, ((1<<FFI_FLAG_BITS)-1)
|
|
188 REG_L a7, 7*FFI_SIZEOF_ARG(t9)
|
|
189 beqz t4, arg8_next
|
|
190 bne t4, FFI_TYPE_FLOAT, arg8_doublep
|
|
191 l.s $f19, 7*FFI_SIZEOF_ARG(t9)
|
|
192 b arg8_next
|
|
193 arg8_doublep:
|
|
194 l.d $f19, 7*FFI_SIZEOF_ARG(t9)
|
|
195 arg8_next:
|
|
196
|
|
197 callit:
|
|
198 # Load the function pointer
|
|
199 REG_L t9, 5*FFI_SIZEOF_ARG($fp)
|
|
200
|
|
201 # If the return value pointer is NULL, assume no return value.
|
|
202 REG_L t5, 4*FFI_SIZEOF_ARG($fp)
|
|
203 beqz t5, noretval
|
|
204
|
|
205 # Shift the return type flag over
|
|
206 SRL t6, 8*FFI_FLAG_BITS
|
|
207
|
|
208 beq t6, FFI_TYPE_SINT32, retint
|
|
209 bne t6, FFI_TYPE_INT, retfloat
|
|
210 retint:
|
|
211 jal t9
|
|
212 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
213 REG_S v0, 0(t4)
|
|
214 b epilogue
|
|
215
|
|
216 retfloat:
|
|
217 bne t6, FFI_TYPE_FLOAT, retdouble
|
|
218 jal t9
|
|
219 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
220 s.s $f0, 0(t4)
|
|
221 b epilogue
|
|
222
|
|
223 retdouble:
|
|
224 bne t6, FFI_TYPE_DOUBLE, retstruct_d
|
|
225 jal t9
|
|
226 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
227 s.d $f0, 0(t4)
|
|
228 b epilogue
|
|
229
|
|
230 retstruct_d:
|
|
231 bne t6, FFI_TYPE_STRUCT_D, retstruct_f
|
|
232 jal t9
|
|
233 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
234 s.d $f0, 0(t4)
|
|
235 b epilogue
|
|
236
|
|
237 retstruct_f:
|
|
238 bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
|
|
239 jal t9
|
|
240 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
241 s.s $f0, 0(t4)
|
|
242 b epilogue
|
|
243
|
|
244 retstruct_d_d:
|
|
245 bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
|
|
246 jal t9
|
|
247 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
248 s.d $f0, 0(t4)
|
|
249 s.d $f2, 8(t4)
|
|
250 b epilogue
|
|
251
|
|
252 retstruct_f_f:
|
|
253 bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
|
|
254 jal t9
|
|
255 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
256 s.s $f0, 0(t4)
|
|
257 s.s $f2, 4(t4)
|
|
258 b epilogue
|
|
259
|
|
260 retstruct_d_f:
|
|
261 bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
|
|
262 jal t9
|
|
263 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
264 s.d $f0, 0(t4)
|
|
265 s.s $f2, 8(t4)
|
|
266 b epilogue
|
|
267
|
|
268 retstruct_f_d:
|
|
269 bne t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft
|
|
270 jal t9
|
|
271 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
272 s.s $f0, 0(t4)
|
|
273 s.d $f2, 8(t4)
|
|
274 b epilogue
|
|
275
|
|
276 retstruct_d_soft:
|
|
277 bne t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft
|
|
278 jal t9
|
|
279 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
280 sd v0, 0(t4)
|
|
281 b epilogue
|
|
282
|
|
283 retstruct_f_soft:
|
|
284 bne t6, FFI_TYPE_STRUCT_F_SOFT, retstruct_d_d_soft
|
|
285 jal t9
|
|
286 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
287 sw v0, 0(t4)
|
|
288 b epilogue
|
|
289
|
|
290 retstruct_d_d_soft:
|
|
291 bne t6, FFI_TYPE_STRUCT_DD_SOFT, retstruct_f_f_soft
|
|
292 jal t9
|
|
293 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
294 sd v0, 0(t4)
|
|
295 sd v1, 8(t4)
|
|
296 b epilogue
|
|
297
|
|
298 retstruct_f_f_soft:
|
|
299 bne t6, FFI_TYPE_STRUCT_FF_SOFT, retstruct_d_f_soft
|
|
300 jal t9
|
|
301 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
302 sw v0, 0(t4)
|
|
303 sw v1, 4(t4)
|
|
304 b epilogue
|
|
305
|
|
306 retstruct_d_f_soft:
|
|
307 bne t6, FFI_TYPE_STRUCT_DF_SOFT, retstruct_f_d_soft
|
|
308 jal t9
|
|
309 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
310 sd v0, 0(t4)
|
|
311 sw v1, 8(t4)
|
|
312 b epilogue
|
|
313
|
|
314 retstruct_f_d_soft:
|
|
315 bne t6, FFI_TYPE_STRUCT_FD_SOFT, retstruct_small
|
|
316 jal t9
|
|
317 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
318 sw v0, 0(t4)
|
|
319 sd v1, 8(t4)
|
|
320 b epilogue
|
|
321
|
|
322 retstruct_small:
|
|
323 bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
|
|
324 jal t9
|
|
325 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
326 REG_S v0, 0(t4)
|
|
327 b epilogue
|
|
328
|
|
329 retstruct_small2:
|
|
330 bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
|
|
331 jal t9
|
|
332 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
|
|
333 REG_S v0, 0(t4)
|
|
334 REG_S v1, 8(t4)
|
|
335 b epilogue
|
|
336
|
|
337 retstruct:
|
|
338 noretval:
|
|
339 jal t9
|
|
340
|
|
341 # Epilogue
|
|
342 epilogue:
|
|
343 move $sp, $fp
|
|
344 REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
|
|
345 REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address
|
|
346 ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
|
347 j ra
|
|
348
|
|
349 .LFE3:
|
|
350 .end ffi_call_N32
|
|
351
|
|
352 /* ffi_closure_N32. Expects address of the passed-in ffi_closure in t0
|
|
353 ($12). Stores any arguments passed in registers onto the stack,
|
|
354 then calls ffi_closure_mips_inner_N32, which then decodes
|
|
355 them.
|
|
356
|
|
357 Stack layout:
|
|
358
|
|
359 20 - Start of parameters, original sp
|
|
360 19 - Called function a7 save
|
|
361 18 - Called function a6 save
|
|
362 17 - Called function a5 save
|
|
363 16 - Called function a4 save
|
|
364 15 - Called function a3 save
|
|
365 14 - Called function a2 save
|
|
366 13 - Called function a1 save
|
|
367 12 - Called function a0 save
|
|
368 11 - Called function f19
|
|
369 10 - Called function f18
|
|
370 9 - Called function f17
|
|
371 8 - Called function f16
|
|
372 7 - Called function f15
|
|
373 6 - Called function f14
|
|
374 5 - Called function f13
|
|
375 4 - Called function f12
|
|
376 3 - return value high (v1 or $f2)
|
|
377 2 - return value low (v0 or $f0)
|
|
378 1 - ra save
|
|
379 0 - gp save our sp points here
|
|
380 */
|
|
381
|
|
382 #define SIZEOF_FRAME2 (20 * FFI_SIZEOF_ARG)
|
|
383
|
|
384 #define A7_OFF2 (19 * FFI_SIZEOF_ARG)
|
|
385 #define A6_OFF2 (18 * FFI_SIZEOF_ARG)
|
|
386 #define A5_OFF2 (17 * FFI_SIZEOF_ARG)
|
|
387 #define A4_OFF2 (16 * FFI_SIZEOF_ARG)
|
|
388 #define A3_OFF2 (15 * FFI_SIZEOF_ARG)
|
|
389 #define A2_OFF2 (14 * FFI_SIZEOF_ARG)
|
|
390 #define A1_OFF2 (13 * FFI_SIZEOF_ARG)
|
|
391 #define A0_OFF2 (12 * FFI_SIZEOF_ARG)
|
|
392
|
|
393 #define F19_OFF2 (11 * FFI_SIZEOF_ARG)
|
|
394 #define F18_OFF2 (10 * FFI_SIZEOF_ARG)
|
|
395 #define F17_OFF2 (9 * FFI_SIZEOF_ARG)
|
|
396 #define F16_OFF2 (8 * FFI_SIZEOF_ARG)
|
|
397 #define F15_OFF2 (7 * FFI_SIZEOF_ARG)
|
|
398 #define F14_OFF2 (6 * FFI_SIZEOF_ARG)
|
|
399 #define F13_OFF2 (5 * FFI_SIZEOF_ARG)
|
|
400 #define F12_OFF2 (4 * FFI_SIZEOF_ARG)
|
|
401
|
|
402 #define V1_OFF2 (3 * FFI_SIZEOF_ARG)
|
|
403 #define V0_OFF2 (2 * FFI_SIZEOF_ARG)
|
|
404
|
|
405 #define RA_OFF2 (1 * FFI_SIZEOF_ARG)
|
|
406 #define GP_OFF2 (0 * FFI_SIZEOF_ARG)
|
|
407
|
|
408 .align 2
|
|
409 .globl ffi_closure_N32
|
|
410 .ent ffi_closure_N32
|
|
411 ffi_closure_N32:
|
|
412 .LFB2:
|
|
413 .frame $sp, SIZEOF_FRAME2, ra
|
|
414 .mask 0x90000000,-(SIZEOF_FRAME2 - RA_OFF2)
|
|
415 .fmask 0x00000000,0
|
|
416 SUBU $sp, SIZEOF_FRAME2
|
|
417 .LCFI5:
|
|
418 .cpsetup t9, GP_OFF2, ffi_closure_N32
|
|
419 REG_S ra, RA_OFF2($sp) # Save return address
|
|
420 .LCFI6:
|
|
421 # Store all possible argument registers. If there are more than
|
|
422 # fit in registers, then they were stored on the stack.
|
|
423 REG_S a0, A0_OFF2($sp)
|
|
424 REG_S a1, A1_OFF2($sp)
|
|
425 REG_S a2, A2_OFF2($sp)
|
|
426 REG_S a3, A3_OFF2($sp)
|
|
427 REG_S a4, A4_OFF2($sp)
|
|
428 REG_S a5, A5_OFF2($sp)
|
|
429 REG_S a6, A6_OFF2($sp)
|
|
430 REG_S a7, A7_OFF2($sp)
|
|
431
|
|
432 # Store all possible float/double registers.
|
|
433 s.d $f12, F12_OFF2($sp)
|
|
434 s.d $f13, F13_OFF2($sp)
|
|
435 s.d $f14, F14_OFF2($sp)
|
|
436 s.d $f15, F15_OFF2($sp)
|
|
437 s.d $f16, F16_OFF2($sp)
|
|
438 s.d $f17, F17_OFF2($sp)
|
|
439 s.d $f18, F18_OFF2($sp)
|
|
440 s.d $f19, F19_OFF2($sp)
|
|
441
|
|
442 # Call ffi_closure_mips_inner_N32 to do the real work.
|
|
443 LA t9, ffi_closure_mips_inner_N32
|
|
444 move a0, $12 # Pointer to the ffi_closure
|
|
445 ADDU a1, $sp, V0_OFF2
|
|
446 ADDU a2, $sp, A0_OFF2
|
|
447 ADDU a3, $sp, F12_OFF2
|
|
448 jalr t9
|
|
449
|
|
450 # Return flags are in v0
|
|
451 bne v0, FFI_TYPE_SINT32, cls_retint
|
|
452 lw v0, V0_OFF2($sp)
|
|
453 b cls_epilogue
|
|
454
|
|
455 cls_retint:
|
|
456 bne v0, FFI_TYPE_INT, cls_retfloat
|
|
457 REG_L v0, V0_OFF2($sp)
|
|
458 b cls_epilogue
|
|
459
|
|
460 cls_retfloat:
|
|
461 bne v0, FFI_TYPE_FLOAT, cls_retdouble
|
|
462 l.s $f0, V0_OFF2($sp)
|
|
463 b cls_epilogue
|
|
464
|
|
465 cls_retdouble:
|
|
466 bne v0, FFI_TYPE_DOUBLE, cls_retstruct_d
|
|
467 l.d $f0, V0_OFF2($sp)
|
|
468 b cls_epilogue
|
|
469
|
|
470 cls_retstruct_d:
|
|
471 bne v0, FFI_TYPE_STRUCT_D, cls_retstruct_f
|
|
472 l.d $f0, V0_OFF2($sp)
|
|
473 b cls_epilogue
|
|
474
|
|
475 cls_retstruct_f:
|
|
476 bne v0, FFI_TYPE_STRUCT_F, cls_retstruct_d_d
|
|
477 l.s $f0, V0_OFF2($sp)
|
|
478 b cls_epilogue
|
|
479
|
|
480 cls_retstruct_d_d:
|
|
481 bne v0, FFI_TYPE_STRUCT_DD, cls_retstruct_f_f
|
|
482 l.d $f0, V0_OFF2($sp)
|
|
483 l.d $f2, V1_OFF2($sp)
|
|
484 b cls_epilogue
|
|
485
|
|
486 cls_retstruct_f_f:
|
|
487 bne v0, FFI_TYPE_STRUCT_FF, cls_retstruct_d_f
|
|
488 l.s $f0, V0_OFF2($sp)
|
|
489 l.s $f2, V1_OFF2($sp)
|
|
490 b cls_epilogue
|
|
491
|
|
492 cls_retstruct_d_f:
|
|
493 bne v0, FFI_TYPE_STRUCT_DF, cls_retstruct_f_d
|
|
494 l.d $f0, V0_OFF2($sp)
|
|
495 l.s $f2, V1_OFF2($sp)
|
|
496 b cls_epilogue
|
|
497
|
|
498 cls_retstruct_f_d:
|
|
499 bne v0, FFI_TYPE_STRUCT_FD, cls_retstruct_small2
|
|
500 l.s $f0, V0_OFF2($sp)
|
|
501 l.d $f2, V1_OFF2($sp)
|
|
502 b cls_epilogue
|
|
503
|
|
504 cls_retstruct_small2:
|
|
505 REG_L v0, V0_OFF2($sp)
|
|
506 REG_L v1, V1_OFF2($sp)
|
|
507
|
|
508 # Epilogue
|
|
509 cls_epilogue:
|
|
510 REG_L ra, RA_OFF2($sp) # Restore return address
|
|
511 .cpreturn
|
|
512 ADDU $sp, SIZEOF_FRAME2
|
|
513 j ra
|
|
514 .LFE2:
|
|
515 .end ffi_closure_N32
|
|
516
|
|
517 #ifdef __GNUC__
|
|
518 .section .eh_frame,"aw",@progbits
|
|
519 .Lframe1:
|
|
520 .4byte .LECIE1-.LSCIE1 # length
|
|
521 .LSCIE1:
|
|
522 .4byte 0x0 # CIE
|
|
523 .byte 0x1 # Version 1
|
|
524 .ascii "\000" # Augmentation
|
|
525 .uleb128 0x1 # Code alignment 1
|
|
526 .sleb128 -4 # Data alignment -4
|
|
527 .byte 0x1f # Return Address $31
|
|
528 .byte 0xc # DW_CFA_def_cfa
|
|
529 .uleb128 0x1d # in $sp
|
|
530 .uleb128 0x0 # offset 0
|
|
531 .align EH_FRAME_ALIGN
|
|
532 .LECIE1:
|
|
533
|
|
534 .LSFDE1:
|
|
535 .4byte .LEFDE1-.LASFDE1 # length.
|
|
536 .LASFDE1:
|
|
537 .4byte .LASFDE1-.Lframe1 # CIE_pointer.
|
|
538 FDE_ADDR_BYTES .LFB3 # initial_location.
|
|
539 FDE_ADDR_BYTES .LFE3-.LFB3 # address_range.
|
|
540 .byte 0x4 # DW_CFA_advance_loc4
|
|
541 .4byte .LCFI0-.LFB3 # to .LCFI0
|
|
542 .byte 0xe # DW_CFA_def_cfa_offset
|
|
543 .uleb128 SIZEOF_FRAME # adjust stack.by SIZEOF_FRAME
|
|
544 .byte 0x4 # DW_CFA_advance_loc4
|
|
545 .4byte .LCFI1-.LCFI0 # to .LCFI1
|
|
546 .byte 0x9e # DW_CFA_offset of $fp
|
|
547 .uleb128 2*FFI_SIZEOF_ARG/4 #
|
|
548 .byte 0x9f # DW_CFA_offset of ra
|
|
549 .uleb128 1*FFI_SIZEOF_ARG/4 #
|
|
550 .byte 0x4 # DW_CFA_advance_loc4
|
|
551 .4byte .LCFI3-.LCFI1 # to .LCFI3
|
|
552 .byte 0xd # DW_CFA_def_cfa_register
|
|
553 .uleb128 0x1e # in $fp
|
|
554 .align EH_FRAME_ALIGN
|
|
555 .LEFDE1:
|
|
556 .LSFDE3:
|
|
557 .4byte .LEFDE3-.LASFDE3 # length
|
|
558 .LASFDE3:
|
|
559 .4byte .LASFDE3-.Lframe1 # CIE_pointer.
|
|
560 FDE_ADDR_BYTES .LFB2 # initial_location.
|
|
561 FDE_ADDR_BYTES .LFE2-.LFB2 # address_range.
|
|
562 .byte 0x4 # DW_CFA_advance_loc4
|
|
563 .4byte .LCFI5-.LFB2 # to .LCFI5
|
|
564 .byte 0xe # DW_CFA_def_cfa_offset
|
|
565 .uleb128 SIZEOF_FRAME2 # adjust stack.by SIZEOF_FRAME
|
|
566 .byte 0x4 # DW_CFA_advance_loc4
|
|
567 .4byte .LCFI6-.LCFI5 # to .LCFI6
|
|
568 .byte 0x9c # DW_CFA_offset of $gp ($28)
|
|
569 .uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4
|
|
570 .byte 0x9f # DW_CFA_offset of ra ($31)
|
|
571 .uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4
|
|
572 .align EH_FRAME_ALIGN
|
|
573 .LEFDE3:
|
|
574 #endif /* __GNUC__ */
|
|
575
|
|
576 #endif
|