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