1 /* -----------------------------------------------------------------------
2 n32.S - Copyright (c) 1996, 1998 Cygnus Solutions
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 ----------------------------------------------------------------------- */
29 /* Only build this code if we are compiling for n32 */
31 #if defined(FFI_MIPS_N32)
39 #define SIZEOF_FRAME ( 8 * SIZEOF_ARG )
48 SUBU $sp, SIZEOF_FRAME # Frame size
49 REG_S $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Save frame pointer
50 REG_S ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Save return address
53 move t9, callback # callback function pointer
54 REG_S bytes, 2*SIZEOF_ARG($fp) # bytes
55 REG_S flags, 3*SIZEOF_ARG($fp) # flags
56 REG_S raddr, 4*SIZEOF_ARG($fp) # raddr
57 REG_S fn, 5*SIZEOF_ARG($fp) # fn
59 # Allocate at least 4 words in the argstack
61 bge bytes, 4 * SIZEOF_ARG, bigger
66 ADDU t4, v0, 2 * SIZEOF_ARG -1 # make sure it is aligned
67 and v0, t4, -2 * SIZEOF_ARG # to a proper boundry.
70 SUBU $sp, $sp, v0 # move the stack pointer to reflect the
73 ADDU a0, $sp, 0 # 4 * SIZEOF_ARG
74 ADDU a3, $fp, 3 * SIZEOF_ARG
79 # ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
81 # Copy the stack pointer to t9
84 # Fix the stack if there are more than 8 64bit slots worth
87 # Load the number of bytes
88 REG_L t6, 2*SIZEOF_ARG($fp)
90 # Is it bigger than 8 * SIZEOF_ARG?
91 dadd t7, $0, 8 * SIZEOF_ARG
99 REG_L t4, 3*SIZEOF_ARG($fp) # load the flags word
100 add t6, t4, 0 # and copy it into t6
102 and t4, ((1<<FFI_FLAG_BITS)-1)
104 REG_L a0, 0*SIZEOF_ARG(t9)
107 bne t4, FFI_TYPE_FLOAT, arg1_doublep
108 l.s $f12, 0*SIZEOF_ARG(t9)
111 l.d $f12, 0*SIZEOF_ARG(t9)
115 SRL t4, 1*FFI_FLAG_BITS
116 and t4, ((1<<FFI_FLAG_BITS)-1)
118 REG_L a1, 1*SIZEOF_ARG(t9)
121 bne t4, FFI_TYPE_FLOAT, arg2_doublep
122 l.s $f13, 1*SIZEOF_ARG(t9)
125 l.d $f13, 1*SIZEOF_ARG(t9)
129 SRL t4, 2*FFI_FLAG_BITS
130 and t4, ((1<<FFI_FLAG_BITS)-1)
132 REG_L a2, 2*SIZEOF_ARG(t9)
135 bne t4, FFI_TYPE_FLOAT, arg3_doublep
136 l.s $f14, 2*SIZEOF_ARG(t9)
139 l.d $f14, 2*SIZEOF_ARG(t9)
143 SRL t4, 3*FFI_FLAG_BITS
144 and t4, ((1<<FFI_FLAG_BITS)-1)
146 REG_L a3, 3*SIZEOF_ARG(t9)
149 bne t4, FFI_TYPE_FLOAT, arg4_doublep
150 l.s $f15, 3*SIZEOF_ARG(t9)
153 l.d $f15, 3*SIZEOF_ARG(t9)
157 SRL t4, 4*FFI_FLAG_BITS
158 and t4, ((1<<FFI_FLAG_BITS)-1)
160 REG_L a4, 4*SIZEOF_ARG(t9)
163 bne t4, FFI_TYPE_FLOAT, arg5_doublep
164 l.s $f16, 4*SIZEOF_ARG(t9)
167 l.d $f16, 4*SIZEOF_ARG(t9)
171 SRL t4, 5*FFI_FLAG_BITS
172 and t4, ((1<<FFI_FLAG_BITS)-1)
174 REG_L a5, 5*SIZEOF_ARG(t9)
177 bne t4, FFI_TYPE_FLOAT, arg6_doublep
178 l.s $f17, 5*SIZEOF_ARG(t9)
181 l.d $f17, 5*SIZEOF_ARG(t9)
185 SRL t4, 6*FFI_FLAG_BITS
186 and t4, ((1<<FFI_FLAG_BITS)-1)
188 REG_L a6, 6*SIZEOF_ARG(t9)
191 bne t4, FFI_TYPE_FLOAT, arg7_doublep
192 l.s $f18, 6*SIZEOF_ARG(t9)
195 l.d $f18, 6*SIZEOF_ARG(t9)
199 SRL t4, 7*FFI_FLAG_BITS
200 and t4, ((1<<FFI_FLAG_BITS)-1)
202 REG_L a7, 7*SIZEOF_ARG(t9)
205 bne t4, FFI_TYPE_FLOAT, arg8_doublep
206 l.s $f19, 7*SIZEOF_ARG(t9)
209 l.d $f19, 7*SIZEOF_ARG(t9)
213 # Load the function pointer
214 REG_L t9, 5*SIZEOF_ARG($fp)
216 # If the return value pointer is NULL, assume no return value.
217 REG_L t5, 4*SIZEOF_ARG($fp)
220 # Shift the return type flag over
221 SRL t6, 8*FFI_FLAG_BITS
223 bne t6, FFI_TYPE_INT, retfloat
225 REG_L t4, 4*SIZEOF_ARG($fp)
230 bne t6, FFI_TYPE_FLOAT, retdouble
232 REG_L t4, 4*SIZEOF_ARG($fp)
237 bne t6, FFI_TYPE_DOUBLE, retstruct_d
239 REG_L t4, 4*SIZEOF_ARG($fp)
244 bne t6, FFI_TYPE_STRUCT_D, retstruct_f
246 REG_L t4, 4*SIZEOF_ARG($fp)
251 bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
253 REG_L t4, 4*SIZEOF_ARG($fp)
258 bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
260 REG_L t4, 4*SIZEOF_ARG($fp)
266 bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
268 REG_L t4, 4*SIZEOF_ARG($fp)
274 bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
276 REG_L t4, 4*SIZEOF_ARG($fp)
282 bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
284 REG_L t4, 4*SIZEOF_ARG($fp)
290 bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
292 REG_L t4, 4*SIZEOF_ARG($fp)
297 bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
299 REG_L t4, 4*SIZEOF_ARG($fp)
311 REG_L $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
312 REG_L ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Restore return address
313 ADDU $sp, SIZEOF_FRAME # Fix stack pointer