source: trunk/gcc/libffi/src/mips/n32.S

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 7.0 KB
Line 
1/* -----------------------------------------------------------------------
2 n32.S - Copyright (c) 1996, 1998 Cygnus Solutions
3
4 MIPS Foreign Function Interface
5
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
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 ----------------------------------------------------------------------- */
25
26#define LIBFFI_ASM
27#include <ffi.h>
28
29/* Only build this code if we are compiling for n32 */
30
31#if defined(FFI_MIPS_N32)
32
33#define callback a0
34#define bytes a2
35#define flags a3
36#define raddr a4
37#define fn a5
38
39#define SIZEOF_FRAME ( 8 * SIZEOF_ARG )
40
41 .text
42 .align 2
43 .globl ffi_call_N32
44 .ent ffi_call_N32
45ffi_call_N32:
46
47 # Prologue
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
51 move $fp, $sp
52
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
58
59 # Allocate at least 4 words in the argstack
60 move v0, bytes
61 bge bytes, 4 * SIZEOF_ARG, bigger
62 LI v0, 4 * SIZEOF_ARG
63 b sixteen
64
65 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.
68
69sixteen:
70 SUBU $sp, $sp, v0 # move the stack pointer to reflect the
71 # arg space
72
73 ADDU a0, $sp, 0 # 4 * SIZEOF_ARG
74 ADDU a3, $fp, 3 * SIZEOF_ARG
75
76 # Call ffi_prep_args
77 jal t9
78
79 # ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
80
81 # Copy the stack pointer to t9
82 move t9, $sp
83
84 # Fix the stack if there are more than 8 64bit slots worth
85 # of arguments.
86
87 # Load the number of bytes
88 REG_L t6, 2*SIZEOF_ARG($fp)
89
90 # Is it bigger than 8 * SIZEOF_ARG?
91 dadd t7, $0, 8 * SIZEOF_ARG
92 dsub t8, t6, t7
93 bltz t8, loadregs
94
95 add t9, t9, t8
96
97loadregs:
98
99 REG_L t4, 3*SIZEOF_ARG($fp) # load the flags word
100 add t6, t4, 0 # and copy it into t6
101
102 and t4, ((1<<FFI_FLAG_BITS)-1)
103 bnez t4, arg1_floatp
104 REG_L a0, 0*SIZEOF_ARG(t9)
105 b arg1_next
106arg1_floatp:
107 bne t4, FFI_TYPE_FLOAT, arg1_doublep
108 l.s $f12, 0*SIZEOF_ARG(t9)
109 b arg1_next
110arg1_doublep:
111 l.d $f12, 0*SIZEOF_ARG(t9)
112arg1_next:
113
114 add t4, t6, 0
115 SRL t4, 1*FFI_FLAG_BITS
116 and t4, ((1<<FFI_FLAG_BITS)-1)
117 bnez t4, arg2_floatp
118 REG_L a1, 1*SIZEOF_ARG(t9)
119 b arg2_next
120arg2_floatp:
121 bne t4, FFI_TYPE_FLOAT, arg2_doublep
122 l.s $f13, 1*SIZEOF_ARG(t9)
123 b arg2_next
124arg2_doublep:
125 l.d $f13, 1*SIZEOF_ARG(t9)
126arg2_next:
127
128 add t4, t6, 0
129 SRL t4, 2*FFI_FLAG_BITS
130 and t4, ((1<<FFI_FLAG_BITS)-1)
131 bnez t4, arg3_floatp
132 REG_L a2, 2*SIZEOF_ARG(t9)
133 b arg3_next
134arg3_floatp:
135 bne t4, FFI_TYPE_FLOAT, arg3_doublep
136 l.s $f14, 2*SIZEOF_ARG(t9)
137 b arg3_next
138arg3_doublep:
139 l.d $f14, 2*SIZEOF_ARG(t9)
140arg3_next:
141
142 add t4, t6, 0
143 SRL t4, 3*FFI_FLAG_BITS
144 and t4, ((1<<FFI_FLAG_BITS)-1)
145 bnez t4, arg4_floatp
146 REG_L a3, 3*SIZEOF_ARG(t9)
147 b arg4_next
148arg4_floatp:
149 bne t4, FFI_TYPE_FLOAT, arg4_doublep
150 l.s $f15, 3*SIZEOF_ARG(t9)
151 b arg4_next
152arg4_doublep:
153 l.d $f15, 3*SIZEOF_ARG(t9)
154arg4_next:
155
156 add t4, t6, 0
157 SRL t4, 4*FFI_FLAG_BITS
158 and t4, ((1<<FFI_FLAG_BITS)-1)
159 bnez t4, arg5_floatp
160 REG_L a4, 4*SIZEOF_ARG(t9)
161 b arg5_next
162arg5_floatp:
163 bne t4, FFI_TYPE_FLOAT, arg5_doublep
164 l.s $f16, 4*SIZEOF_ARG(t9)
165 b arg5_next
166arg5_doublep:
167 l.d $f16, 4*SIZEOF_ARG(t9)
168arg5_next:
169
170 add t4, t6, 0
171 SRL t4, 5*FFI_FLAG_BITS
172 and t4, ((1<<FFI_FLAG_BITS)-1)
173 bnez t4, arg6_floatp
174 REG_L a5, 5*SIZEOF_ARG(t9)
175 b arg6_next
176arg6_floatp:
177 bne t4, FFI_TYPE_FLOAT, arg6_doublep
178 l.s $f17, 5*SIZEOF_ARG(t9)
179 b arg6_next
180arg6_doublep:
181 l.d $f17, 5*SIZEOF_ARG(t9)
182arg6_next:
183
184 add t4, t6, 0
185 SRL t4, 6*FFI_FLAG_BITS
186 and t4, ((1<<FFI_FLAG_BITS)-1)
187 bnez t4, arg7_floatp
188 REG_L a6, 6*SIZEOF_ARG(t9)
189 b arg7_next
190arg7_floatp:
191 bne t4, FFI_TYPE_FLOAT, arg7_doublep
192 l.s $f18, 6*SIZEOF_ARG(t9)
193 b arg7_next
194arg7_doublep:
195 l.d $f18, 6*SIZEOF_ARG(t9)
196arg7_next:
197
198 add t4, t6, 0
199 SRL t4, 7*FFI_FLAG_BITS
200 and t4, ((1<<FFI_FLAG_BITS)-1)
201 bnez t4, arg8_floatp
202 REG_L a7, 7*SIZEOF_ARG(t9)
203 b arg8_next
204arg8_floatp:
205 bne t4, FFI_TYPE_FLOAT, arg8_doublep
206 l.s $f19, 7*SIZEOF_ARG(t9)
207 b arg8_next
208arg8_doublep:
209 l.d $f19, 7*SIZEOF_ARG(t9)
210arg8_next:
211
212callit:
213 # Load the function pointer
214 REG_L t9, 5*SIZEOF_ARG($fp)
215
216 # If the return value pointer is NULL, assume no return value.
217 REG_L t5, 4*SIZEOF_ARG($fp)
218 beqz t5, noretval
219
220 # Shift the return type flag over
221 SRL t6, 8*FFI_FLAG_BITS
222
223 bne t6, FFI_TYPE_INT, retfloat
224 jal t9
225 REG_L t4, 4*SIZEOF_ARG($fp)
226 REG_S v0, 0(t4)
227 b epilogue
228
229retfloat:
230 bne t6, FFI_TYPE_FLOAT, retdouble
231 jal t9
232 REG_L t4, 4*SIZEOF_ARG($fp)
233 s.s $f0, 0(t4)
234 b epilogue
235
236retdouble:
237 bne t6, FFI_TYPE_DOUBLE, retstruct_d
238 jal t9
239 REG_L t4, 4*SIZEOF_ARG($fp)
240 s.d $f0, 0(t4)
241 b epilogue
242
243retstruct_d:
244 bne t6, FFI_TYPE_STRUCT_D, retstruct_f
245 jal t9
246 REG_L t4, 4*SIZEOF_ARG($fp)
247 s.d $f0, 0(t4)
248 b epilogue
249
250retstruct_f:
251 bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d
252 jal t9
253 REG_L t4, 4*SIZEOF_ARG($fp)
254 s.s $f0, 0(t4)
255 b epilogue
256
257retstruct_d_d:
258 bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
259 jal t9
260 REG_L t4, 4*SIZEOF_ARG($fp)
261 s.d $f0, 0(t4)
262 s.d $f2, 8(t4)
263 b epilogue
264
265retstruct_f_f:
266 bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
267 jal t9
268 REG_L t4, 4*SIZEOF_ARG($fp)
269 s.s $f0, 0(t4)
270 s.s $f2, 4(t4)
271 b epilogue
272
273retstruct_d_f:
274 bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
275 jal t9
276 REG_L t4, 4*SIZEOF_ARG($fp)
277 s.d $f0, 0(t4)
278 s.s $f2, 8(t4)
279 b epilogue
280
281retstruct_f_d:
282 bne t6, FFI_TYPE_STRUCT_FD, retstruct_small
283 jal t9
284 REG_L t4, 4*SIZEOF_ARG($fp)
285 s.s $f0, 0(t4)
286 s.d $f2, 8(t4)
287 b epilogue
288
289retstruct_small:
290 bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
291 jal t9
292 REG_L t4, 4*SIZEOF_ARG($fp)
293 REG_S v0, 0(t4)
294 b epilogue
295
296retstruct_small2:
297 bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct
298 jal t9
299 REG_L t4, 4*SIZEOF_ARG($fp)
300 REG_S v0, 0(t4)
301 REG_S v1, 8(t4)
302 b epilogue
303
304retstruct:
305noretval:
306 jal t9
307
308 # Epilogue
309epilogue:
310 move $sp, $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
314 j ra
315
316 .end ffi_call_N32
317
318#endif
Note: See TracBrowser for help on using the repository browser.