1 /* -----------------------------------------------------------------------
2 n32.S - Copyright (c) 1996, 1998 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 )
49 SUBU $sp, SIZEOF_FRAME # Frame size
50 REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
51 REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
54 move t9, callback # callback function pointer
55 REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
56 REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags
57 REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
58 REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
60 # Allocate at least 4 words in the argstack
62 bge bytes, 4 * FFI_SIZEOF_ARG, bigger
63 LI v0, 4 * FFI_SIZEOF_ARG
67 ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned
68 and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry.
71 SUBU $sp, $sp, v0 # move the stack pointer to reflect the
74 ADDU a0, $sp, 0 # 4 * FFI_SIZEOF_ARG
75 ADDU a3, $fp, 3 * FFI_SIZEOF_ARG
80 # ADDU $sp, $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
82 # Copy the stack pointer to t9
85 # Fix the stack if there are more than 8 64bit slots worth
88 # Load the number of bytes
89 REG_L t6, 2*FFI_SIZEOF_ARG($fp)
91 # Is it bigger than 8 * FFI_SIZEOF_ARG?
92 dadd t7, $0, 8 * FFI_SIZEOF_ARG
100 REG_L t4, 3*FFI_SIZEOF_ARG($fp) # load the flags word
101 add t6, t4, 0 # and copy it into t6
103 and t4, ((1<<FFI_FLAG_BITS)-1)
105 REG_L a0, 0*FFI_SIZEOF_ARG(t9)
108 bne t4, FFI_TYPE_FLOAT, arg1_doublep
109 l.s $f12, 0*FFI_SIZEOF_ARG(t9)
112 l.d $f12, 0*FFI_SIZEOF_ARG(t9)
116 SRL t4, 1*FFI_FLAG_BITS
117 and t4, ((1<<FFI_FLAG_BITS)-1)
119 REG_L a1, 1*FFI_SIZEOF_ARG(t9)
122 bne t4, FFI_TYPE_FLOAT, arg2_doublep
123 l.s $f13, 1*FFI_SIZEOF_ARG(t9)
126 l.d $f13, 1*FFI_SIZEOF_ARG(t9)
130 SRL t4, 2*FFI_FLAG_BITS
131 and t4, ((1<<FFI_FLAG_BITS)-1)
133 REG_L a2, 2*FFI_SIZEOF_ARG(t9)
136 bne t4, FFI_TYPE_FLOAT, arg3_doublep
137 l.s $f14, 2*FFI_SIZEOF_ARG(t9)
140 l.d $f14, 2*FFI_SIZEOF_ARG(t9)
144 SRL t4, 3*FFI_FLAG_BITS
145 and t4, ((1<<FFI_FLAG_BITS)-1)
147 REG_L a3, 3*FFI_SIZEOF_ARG(t9)
150 bne t4, FFI_TYPE_FLOAT, arg4_doublep
151 l.s $f15, 3*FFI_SIZEOF_ARG(t9)
154 l.d $f15, 3*FFI_SIZEOF_ARG(t9)
158 SRL t4, 4*FFI_FLAG_BITS
159 and t4, ((1<<FFI_FLAG_BITS)-1)
161 REG_L a4, 4*FFI_SIZEOF_ARG(t9)
164 bne t4, FFI_TYPE_FLOAT, arg5_doublep
165 l.s $f16, 4*FFI_SIZEOF_ARG(t9)
168 l.d $f16, 4*FFI_SIZEOF_ARG(t9)
172 SRL t4, 5*FFI_FLAG_BITS
173 and t4, ((1<<FFI_FLAG_BITS)-1)
175 REG_L a5, 5*FFI_SIZEOF_ARG(t9)
178 bne t4, FFI_TYPE_FLOAT, arg6_doublep
179 l.s $f17, 5*FFI_SIZEOF_ARG(t9)
182 l.d $f17, 5*FFI_SIZEOF_ARG(t9)
186 SRL t4, 6*FFI_FLAG_BITS
187 and t4, ((1<<FFI_FLAG_BITS)-1)
189 REG_L a6, 6*FFI_SIZEOF_ARG(t9)
192 bne t4, FFI_TYPE_FLOAT, arg7_doublep
193 l.s $f18, 6*FFI_SIZEOF_ARG(t9)
196 l.d $f18, 6*FFI_SIZEOF_ARG(t9)
200 SRL t4, 7*FFI_FLAG_BITS
201 and t4, ((1<<FFI_FLAG_BITS)-1)
203 REG_L a7, 7*FFI_SIZEOF_ARG(t9)
206 bne t4, FFI_TYPE_FLOAT, arg8_doublep
207 l.s $f19, 7*FFI_SIZEOF_ARG(t9)
210 l.d $f19, 7*FFI_SIZEOF_ARG(t9)
214 # Load the function pointer
215 REG_L t9, 5*FFI_SIZEOF_ARG($fp)
217 # If the return value pointer is NULL, assume no return value.
218 REG_L t5, 4*FFI_SIZEOF_ARG($fp)
221 # Shift the return type flag over
222 SRL t6, 8*FFI_FLAG_BITS
224 bne t6, FFI_TYPE_INT, retfloat
226 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
231 bne t6, FFI_TYPE_FLOAT, retdouble
233 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
238 bne t6, FFI_TYPE_DOUBLE, retstruct_d
240 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
245 bne t6, FFI_TYPE_STRUCT_D, retstruct_f
247 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
252 bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
254 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
259 bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
261 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
267 bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
269 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
275 bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
277 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
283 bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
285 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
291 bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
293 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
298 bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
300 REG_L t4, 4*FFI_SIZEOF_ARG($fp)
312 REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
313 REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address
314 ADDU $sp, SIZEOF_FRAME # Fix stack pointer