1 /* -----------------------------------------------------------------------
2 n32.S - Copyright (c) 1996, 1998, 2005 Red Hat, Inc.
4 MIPS Foreign Function Interface
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:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 ----------------------------------------------------------------------- */
27 #include <fficonfig.h>
30 /* Only build this code if we are compiling for n32 */
32 #if defined(FFI_MIPS_N32)
40 #define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG )
50 SUBU $sp, SIZEOF_FRAME # Frame size
51 REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
52 REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
55 move t9, callback # callback function pointer
56 REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
57 REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags
58 REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
59 REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
61 # Allocate at least 4 words in the argstack
63 bge bytes, 4 * FFI_SIZEOF_ARG, bigger
64 LI v0, 4 * FFI_SIZEOF_ARG
68 ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned
69 and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry.
72 SUBU $sp, $sp, v0 # move the stack pointer to reflect the
75 ADDU a0, $sp, 0 # 4 * FFI_SIZEOF_ARG
76 ADDU a3, $fp, 3 * FFI_SIZEOF_ARG
81 # ADDU $sp, $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
83 # Copy the stack pointer to t9
86 # Fix the stack if there are more than 8 64bit slots worth
89 # Load the number of bytes
90 REG_L t6, 2*FFI_SIZEOF_ARG($fp)
92 # Is it bigger than 8 * FFI_SIZEOF_ARG?
93 dadd t7, $0, 8 * FFI_SIZEOF_ARG
101 REG_L t4, 3*FFI_SIZEOF_ARG($fp) # load the flags word
102 add t6, t4, 0 # and copy it into t6
104 and t4, ((1<<FFI_FLAG_BITS)-1)
106 REG_L a0, 0*FFI_SIZEOF_ARG(t9)
109 bne t4, FFI_TYPE_FLOAT, arg1_doublep
110 l.s $f12, 0*FFI_SIZEOF_ARG(t9)
113 l.d $f12, 0*FFI_SIZEOF_ARG(t9)
117 SRL t4, 1*FFI_FLAG_BITS
118 and t4, ((1<<FFI_FLAG_BITS)-1)
120 REG_L a1, 1*FFI_SIZEOF_ARG(t9)
123 bne t4, FFI_TYPE_FLOAT, arg2_doublep
124 l.s $f13, 1*FFI_SIZEOF_ARG(t9)
127 l.d $f13, 1*FFI_SIZEOF_ARG(t9)
131 SRL t4, 2*FFI_FLAG_BITS
132 and t4, ((1<<FFI_FLAG_BITS)-1)
134 REG_L a2, 2*FFI_SIZEOF_ARG(t9)
137 bne t4, FFI_TYPE_FLOAT, arg3_doublep
138 l.s $f14, 2*FFI_SIZEOF_ARG(t9)
141 l.d $f14, 2*FFI_SIZEOF_ARG(t9)
145 SRL t4, 3*FFI_FLAG_BITS
146 and t4, ((1<<FFI_FLAG_BITS)-1)
148 REG_L a3, 3*FFI_SIZEOF_ARG(t9)
151 bne t4, FFI_TYPE_FLOAT, arg4_doublep
152 l.s $f15, 3*FFI_SIZEOF_ARG(t9)
155 l.d $f15, 3*FFI_SIZEOF_ARG(t9)
159 SRL t4, 4*FFI_FLAG_BITS
160 and t4, ((1<<FFI_FLAG_BITS)-1)
162 REG_L a4, 4*FFI_SIZEOF_ARG(t9)
165 bne t4, FFI_TYPE_FLOAT, arg5_doublep
166 l.s $f16, 4*FFI_SIZEOF_ARG(t9)
169 l.d $f16, 4*FFI_SIZEOF_ARG(t9)
173 SRL t4, 5*FFI_FLAG_BITS
174 and t4, ((1<<FFI_FLAG_BITS)-1)
176 REG_L a5, 5*FFI_SIZEOF_ARG(t9)
179 bne t4, FFI_TYPE_FLOAT, arg6_doublep
180 l.s $f17, 5*FFI_SIZEOF_ARG(t9)
183 l.d $f17, 5*FFI_SIZEOF_ARG(t9)
187 SRL t4, 6*FFI_FLAG_BITS
188 and t4, ((1<<FFI_FLAG_BITS)-1)
190 REG_L a6, 6*FFI_SIZEOF_ARG(t9)
193 bne t4, FFI_TYPE_FLOAT, arg7_doublep
194 l.s $f18, 6*FFI_SIZEOF_ARG(t9)
197 l.d $f18, 6*FFI_SIZEOF_ARG(t9)
201 SRL t4, 7*FFI_FLAG_BITS
202 and t4, ((1<<FFI_FLAG_BITS)-1)
204 REG_L a7, 7*FFI_SIZEOF_ARG(t9)
207 bne t4, FFI_TYPE_FLOAT, arg8_doublep
208 l.s $f19, 7*FFI_SIZEOF_ARG(t9)
211 l.d $f19, 7*FFI_SIZEOF_ARG(t9)
215 # Load the function pointer
216 REG_L t9, 5*FFI_SIZEOF_ARG($fp)
218 # If the return value pointer is NULL, assume no return value.
219 REG_L t5, 4*FFI_SIZEOF_ARG($fp)
222 # Shift the return type flag over
223 SRL t6, 8*FFI_FLAG_BITS
225 bne t6, FFI_TYPE_INT, retfloat
227 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
232 bne t6, FFI_TYPE_FLOAT, retdouble
234 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
239 bne t6, FFI_TYPE_DOUBLE, retstruct_d
241 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
246 bne t6, FFI_TYPE_STRUCT_D, retstruct_f
248 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
253 bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
255 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
260 bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
262 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
268 bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
270 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
276 bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
278 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
284 bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
286 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
292 bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
294 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
299 bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
301 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
313 REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
314 REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address
315 ADDU $sp, SIZEOF_FRAME # Fix stack pointer