]>
Commit | Line | Data |
---|---|---|
63e5e3e0 | 1 | /* ----------------------------------------------------------------------- |
86d1b9d1 | 2 | n32.S - Copyright (c) 1996, 1998, 2005, 2007, 2009, 2010 Red Hat, Inc. |
63e5e3e0 AG |
3 | |
4 | MIPS Foreign Function Interface | |
5 | ||
63e5e3e0 AG |
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 | ||
5f933ef0 AH |
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. | |
63e5e3e0 AG |
25 | ----------------------------------------------------------------------- */ |
26 | ||
27 | #define LIBFFI_ASM | |
1450eb7a | 28 | #include <fficonfig.h> |
63e5e3e0 AG |
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 | ||
1450eb7a | 41 | #define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG ) |
63e5e3e0 | 42 | |
86d1b9d1 | 43 | #ifdef __GNUC__ |
2572f1c6 | 44 | .abicalls |
c4205f77 | 45 | #endif |
3b21983d | 46 | .set mips4 |
63e5e3e0 AG |
47 | .text |
48 | .align 2 | |
49 | .globl ffi_call_N32 | |
50 | .ent ffi_call_N32 | |
51 | ffi_call_N32: | |
89d9d98a DD |
52 | .LFB3: |
53 | .frame $fp, SIZEOF_FRAME, ra | |
54 | .mask 0xc0000000,-FFI_SIZEOF_ARG | |
55 | .fmask 0x00000000,0 | |
63e5e3e0 AG |
56 | |
57 | # Prologue | |
58 | SUBU $sp, SIZEOF_FRAME # Frame size | |
89d9d98a | 59 | .LCFI0: |
1450eb7a AT |
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 | |
89d9d98a | 62 | .LCFI1: |
63e5e3e0 | 63 | move $fp, $sp |
89d9d98a | 64 | .LCFI3: |
63e5e3e0 | 65 | move t9, callback # callback function pointer |
1450eb7a AT |
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 | |
63e5e3e0 AG |
70 | |
71 | # Allocate at least 4 words in the argstack | |
72 | move v0, bytes | |
1450eb7a AT |
73 | bge bytes, 4 * FFI_SIZEOF_ARG, bigger |
74 | LI v0, 4 * FFI_SIZEOF_ARG | |
63e5e3e0 AG |
75 | b sixteen |
76 | ||
77 | bigger: | |
1450eb7a AT |
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. | |
63e5e3e0 AG |
80 | |
81 | sixteen: | |
82 | SUBU $sp, $sp, v0 # move the stack pointer to reflect the | |
83 | # arg space | |
84 | ||
c94ae2e4 | 85 | move a0, $sp # 4 * FFI_SIZEOF_ARG |
1450eb7a | 86 | ADDU a3, $fp, 3 * FFI_SIZEOF_ARG |
63e5e3e0 AG |
87 | |
88 | # Call ffi_prep_args | |
89 | jal t9 | |
90 | ||
63e5e3e0 AG |
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 | |
1450eb7a | 98 | REG_L t6, 2*FFI_SIZEOF_ARG($fp) |
63e5e3e0 | 99 | |
1450eb7a | 100 | # Is it bigger than 8 * FFI_SIZEOF_ARG? |
c94ae2e4 | 101 | daddiu t8, t6, -(8 * FFI_SIZEOF_ARG) |
63e5e3e0 AG |
102 | bltz t8, loadregs |
103 | ||
c94ae2e4 | 104 | ADDU t9, t9, t8 |
63e5e3e0 AG |
105 | |
106 | loadregs: | |
107 | ||
c94ae2e4 | 108 | REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6. |
63e5e3e0 | 109 | |
c94ae2e4 | 110 | and t4, t6, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 111 | REG_L a0, 0*FFI_SIZEOF_ARG(t9) |
b1760f7f | 112 | beqz t4, arg1_next |
63e5e3e0 | 113 | bne t4, FFI_TYPE_FLOAT, arg1_doublep |
1450eb7a | 114 | l.s $f12, 0*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
115 | b arg1_next |
116 | arg1_doublep: | |
1450eb7a | 117 | l.d $f12, 0*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
118 | arg1_next: |
119 | ||
c94ae2e4 | 120 | SRL t4, t6, 1*FFI_FLAG_BITS |
63e5e3e0 | 121 | and t4, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 122 | REG_L a1, 1*FFI_SIZEOF_ARG(t9) |
b1760f7f | 123 | beqz t4, arg2_next |
63e5e3e0 | 124 | bne t4, FFI_TYPE_FLOAT, arg2_doublep |
1450eb7a | 125 | l.s $f13, 1*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
126 | b arg2_next |
127 | arg2_doublep: | |
1450eb7a | 128 | l.d $f13, 1*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
129 | arg2_next: |
130 | ||
c94ae2e4 | 131 | SRL t4, t6, 2*FFI_FLAG_BITS |
63e5e3e0 | 132 | and t4, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 133 | REG_L a2, 2*FFI_SIZEOF_ARG(t9) |
b1760f7f | 134 | beqz t4, arg3_next |
63e5e3e0 | 135 | bne t4, FFI_TYPE_FLOAT, arg3_doublep |
1450eb7a | 136 | l.s $f14, 2*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
137 | b arg3_next |
138 | arg3_doublep: | |
1450eb7a | 139 | l.d $f14, 2*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
140 | arg3_next: |
141 | ||
c94ae2e4 | 142 | SRL t4, t6, 3*FFI_FLAG_BITS |
63e5e3e0 | 143 | and t4, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 144 | REG_L a3, 3*FFI_SIZEOF_ARG(t9) |
b1760f7f | 145 | beqz t4, arg4_next |
63e5e3e0 | 146 | bne t4, FFI_TYPE_FLOAT, arg4_doublep |
1450eb7a | 147 | l.s $f15, 3*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
148 | b arg4_next |
149 | arg4_doublep: | |
1450eb7a | 150 | l.d $f15, 3*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
151 | arg4_next: |
152 | ||
c94ae2e4 | 153 | SRL t4, t6, 4*FFI_FLAG_BITS |
63e5e3e0 | 154 | and t4, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 155 | REG_L a4, 4*FFI_SIZEOF_ARG(t9) |
b1760f7f | 156 | beqz t4, arg5_next |
63e5e3e0 | 157 | bne t4, FFI_TYPE_FLOAT, arg5_doublep |
1450eb7a | 158 | l.s $f16, 4*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
159 | b arg5_next |
160 | arg5_doublep: | |
1450eb7a | 161 | l.d $f16, 4*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
162 | arg5_next: |
163 | ||
c94ae2e4 | 164 | SRL t4, t6, 5*FFI_FLAG_BITS |
63e5e3e0 | 165 | and t4, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 166 | REG_L a5, 5*FFI_SIZEOF_ARG(t9) |
b1760f7f | 167 | beqz t4, arg6_next |
63e5e3e0 | 168 | bne t4, FFI_TYPE_FLOAT, arg6_doublep |
1450eb7a | 169 | l.s $f17, 5*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
170 | b arg6_next |
171 | arg6_doublep: | |
1450eb7a | 172 | l.d $f17, 5*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
173 | arg6_next: |
174 | ||
c94ae2e4 | 175 | SRL t4, t6, 6*FFI_FLAG_BITS |
63e5e3e0 | 176 | and t4, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 177 | REG_L a6, 6*FFI_SIZEOF_ARG(t9) |
b1760f7f | 178 | beqz t4, arg7_next |
63e5e3e0 | 179 | bne t4, FFI_TYPE_FLOAT, arg7_doublep |
1450eb7a | 180 | l.s $f18, 6*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
181 | b arg7_next |
182 | arg7_doublep: | |
1450eb7a | 183 | l.d $f18, 6*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
184 | arg7_next: |
185 | ||
c94ae2e4 | 186 | SRL t4, t6, 7*FFI_FLAG_BITS |
63e5e3e0 | 187 | and t4, ((1<<FFI_FLAG_BITS)-1) |
1450eb7a | 188 | REG_L a7, 7*FFI_SIZEOF_ARG(t9) |
b1760f7f | 189 | beqz t4, arg8_next |
63e5e3e0 | 190 | bne t4, FFI_TYPE_FLOAT, arg8_doublep |
1450eb7a | 191 | l.s $f19, 7*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
192 | b arg8_next |
193 | arg8_doublep: | |
1450eb7a | 194 | l.d $f19, 7*FFI_SIZEOF_ARG(t9) |
63e5e3e0 AG |
195 | arg8_next: |
196 | ||
197 | callit: | |
198 | # Load the function pointer | |
1450eb7a | 199 | REG_L t9, 5*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
200 | |
201 | # If the return value pointer is NULL, assume no return value. | |
1450eb7a | 202 | REG_L t5, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
203 | beqz t5, noretval |
204 | ||
205 | # Shift the return type flag over | |
206 | SRL t6, 8*FFI_FLAG_BITS | |
5cbf8c8d DD |
207 | |
208 | beq t6, FFI_TYPE_SINT32, retint | |
63e5e3e0 | 209 | bne t6, FFI_TYPE_INT, retfloat |
5cbf8c8d | 210 | retint: |
63e5e3e0 | 211 | jal t9 |
1450eb7a | 212 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
213 | REG_S v0, 0(t4) |
214 | b epilogue | |
215 | ||
216 | retfloat: | |
217 | bne t6, FFI_TYPE_FLOAT, retdouble | |
218 | jal t9 | |
1450eb7a | 219 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
220 | s.s $f0, 0(t4) |
221 | b epilogue | |
222 | ||
223 | retdouble: | |
224 | bne t6, FFI_TYPE_DOUBLE, retstruct_d | |
225 | jal t9 | |
1450eb7a | 226 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
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 | |
1450eb7a | 233 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
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 | |
1450eb7a | 240 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
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 | |
1450eb7a | 247 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
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 | |
1450eb7a | 255 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
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 | |
1450eb7a | 263 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
264 | s.d $f0, 0(t4) |
265 | s.s $f2, 8(t4) | |
266 | b epilogue | |
267 | ||
268 | retstruct_f_d: | |
5cbf8c8d | 269 | bne t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft |
63e5e3e0 | 270 | jal t9 |
1450eb7a | 271 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
272 | s.s $f0, 0(t4) |
273 | s.d $f2, 8(t4) | |
274 | b epilogue | |
5cbf8c8d DD |
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 | |
63e5e3e0 AG |
321 | |
322 | retstruct_small: | |
323 | bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2 | |
324 | jal t9 | |
1450eb7a | 325 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
326 | REG_S v0, 0(t4) |
327 | b epilogue | |
328 | ||
329 | retstruct_small2: | |
330 | bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct | |
331 | jal t9 | |
1450eb7a | 332 | REG_L t4, 4*FFI_SIZEOF_ARG($fp) |
63e5e3e0 AG |
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 | |
1450eb7a AT |
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 | |
63e5e3e0 AG |
346 | ADDU $sp, SIZEOF_FRAME # Fix stack pointer |
347 | j ra | |
348 | ||
89d9d98a | 349 | .LFE3: |
63e5e3e0 | 350 | .end ffi_call_N32 |
89d9d98a DD |
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 | |
3ef50b62 DD |
445 | ADDU a1, $sp, V0_OFF2 |
446 | ADDU a2, $sp, A0_OFF2 | |
447 | ADDU a3, $sp, F12_OFF2 | |
89d9d98a DD |
448 | jalr t9 |
449 | ||
450 | # Return flags are in v0 | |
5cbf8c8d DD |
451 | bne v0, FFI_TYPE_SINT32, cls_retint |
452 | lw v0, V0_OFF2($sp) | |
453 | b cls_epilogue | |
454 | ||
455 | cls_retint: | |
89d9d98a DD |
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 | ||
86d1b9d1 | 517 | #ifdef __GNUC__ |
89d9d98a DD |
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: | |
86d1b9d1 | 574 | #endif /* __GNUC__ */ |
63e5e3e0 AG |
575 | |
576 | #endif |