2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libffi / src / mips / n32.S
blob767fa52bd5cfe827f7cc9b4f6735af8f46532d93
1 /* -----------------------------------------------------------------------
2    n32.S - Copyright (c) 1996, 1998  Red Hat, Inc.
3    
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    ----------------------------------------------------------------------- */
26 #define LIBFFI_ASM      
27 #include <fficonfig.h>
28 #include <ffi.h>
30 /* Only build this code if we are compiling for n32 */  
32 #if defined(FFI_MIPS_N32)
34 #define callback a0
35 #define bytes    a2
36 #define flags    a3
37 #define raddr    a4
38 #define fn       a5
40 #define SIZEOF_FRAME    ( 8 * FFI_SIZEOF_ARG )
42         .text
43         .align  2
44         .globl  ffi_call_N32
45         .ent    ffi_call_N32
46 ffi_call_N32:   
48         # Prologue
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
52         move    $fp, $sp
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
61         move    v0, bytes
62         bge     bytes, 4 * FFI_SIZEOF_ARG, bigger       
63         LI      v0, 4 * FFI_SIZEOF_ARG
64         b       sixteen
66         bigger: 
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.
70 sixteen:
71         SUBU    $sp, $sp, v0    # move the stack pointer to reflect the
72                                 # arg space
74         ADDU    a0, $sp, 0      # 4 * FFI_SIZEOF_ARG
75         ADDU    a3, $fp, 3 * FFI_SIZEOF_ARG
77         # Call ffi_prep_args
78         jal     t9
79         
80         #       ADDU    $sp, $sp, 4 * FFI_SIZEOF_ARG    # adjust $sp to new args
82         # Copy the stack pointer to t9
83         move    t9, $sp
84         
85         # Fix the stack if there are more than 8 64bit slots worth
86         # of arguments.
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
93         dsub    t8, t6, t7
94         bltz    t8, loadregs
96         add     t9, t9, t8
97         
98 loadregs:       
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)
104         bnez    t4, arg1_floatp
105         REG_L   a0, 0*FFI_SIZEOF_ARG(t9)
106         b       arg1_next
107 arg1_floatp:    
108         bne     t4, FFI_TYPE_FLOAT, arg1_doublep
109         l.s     $f12, 0*FFI_SIZEOF_ARG(t9)
110         b       arg1_next
111 arg1_doublep:   
112         l.d     $f12, 0*FFI_SIZEOF_ARG(t9)
113 arg1_next:      
114         
115         add     t4, t6, 0
116         SRL     t4, 1*FFI_FLAG_BITS
117         and     t4, ((1<<FFI_FLAG_BITS)-1)
118         bnez    t4, arg2_floatp
119         REG_L   a1, 1*FFI_SIZEOF_ARG(t9)
120         b       arg2_next
121 arg2_floatp:
122         bne     t4, FFI_TYPE_FLOAT, arg2_doublep
123         l.s     $f13, 1*FFI_SIZEOF_ARG(t9)      
124         b       arg2_next
125 arg2_doublep:   
126         l.d     $f13, 1*FFI_SIZEOF_ARG(t9)      
127 arg2_next:      
128         
129         add     t4, t6, 0
130         SRL     t4, 2*FFI_FLAG_BITS
131         and     t4, ((1<<FFI_FLAG_BITS)-1)
132         bnez    t4, arg3_floatp
133         REG_L   a2, 2*FFI_SIZEOF_ARG(t9)
134         b       arg3_next
135 arg3_floatp:
136         bne     t4, FFI_TYPE_FLOAT, arg3_doublep
137         l.s     $f14, 2*FFI_SIZEOF_ARG(t9)      
138         b       arg3_next
139 arg3_doublep:   
140         l.d     $f14, 2*FFI_SIZEOF_ARG(t9)      
141 arg3_next:      
142         
143         add     t4, t6, 0
144         SRL     t4, 3*FFI_FLAG_BITS
145         and     t4, ((1<<FFI_FLAG_BITS)-1)
146         bnez    t4, arg4_floatp
147         REG_L   a3, 3*FFI_SIZEOF_ARG(t9)
148         b       arg4_next
149 arg4_floatp:
150         bne     t4, FFI_TYPE_FLOAT, arg4_doublep
151         l.s     $f15, 3*FFI_SIZEOF_ARG(t9)      
152         b       arg4_next
153 arg4_doublep:   
154         l.d     $f15, 3*FFI_SIZEOF_ARG(t9)      
155 arg4_next:      
156         
157         add     t4, t6, 0
158         SRL     t4, 4*FFI_FLAG_BITS
159         and     t4, ((1<<FFI_FLAG_BITS)-1)
160         bnez    t4, arg5_floatp
161         REG_L   a4, 4*FFI_SIZEOF_ARG(t9)
162         b       arg5_next
163 arg5_floatp:
164         bne     t4, FFI_TYPE_FLOAT, arg5_doublep
165         l.s     $f16, 4*FFI_SIZEOF_ARG(t9)      
166         b       arg5_next
167 arg5_doublep:   
168         l.d     $f16, 4*FFI_SIZEOF_ARG(t9)      
169 arg5_next:      
170         
171         add     t4, t6, 0
172         SRL     t4, 5*FFI_FLAG_BITS
173         and     t4, ((1<<FFI_FLAG_BITS)-1)
174         bnez    t4, arg6_floatp
175         REG_L   a5, 5*FFI_SIZEOF_ARG(t9)
176         b       arg6_next
177 arg6_floatp:
178         bne     t4, FFI_TYPE_FLOAT, arg6_doublep
179         l.s     $f17, 5*FFI_SIZEOF_ARG(t9)      
180         b       arg6_next
181 arg6_doublep:   
182         l.d     $f17, 5*FFI_SIZEOF_ARG(t9)      
183 arg6_next:      
184         
185         add     t4, t6, 0
186         SRL     t4, 6*FFI_FLAG_BITS
187         and     t4, ((1<<FFI_FLAG_BITS)-1)
188         bnez    t4, arg7_floatp
189         REG_L   a6, 6*FFI_SIZEOF_ARG(t9)
190         b       arg7_next
191 arg7_floatp:
192         bne     t4, FFI_TYPE_FLOAT, arg7_doublep
193         l.s     $f18, 6*FFI_SIZEOF_ARG(t9)      
194         b       arg7_next
195 arg7_doublep:   
196         l.d     $f18, 6*FFI_SIZEOF_ARG(t9)      
197 arg7_next:      
198         
199         add     t4, t6, 0
200         SRL     t4, 7*FFI_FLAG_BITS
201         and     t4, ((1<<FFI_FLAG_BITS)-1)
202         bnez    t4, arg8_floatp
203         REG_L   a7, 7*FFI_SIZEOF_ARG(t9)
204         b       arg8_next
205 arg8_floatp:
206         bne     t4, FFI_TYPE_FLOAT, arg8_doublep
207         l.s     $f19, 7*FFI_SIZEOF_ARG(t9)      
208         b       arg8_next
209 arg8_doublep:   
210         l.d     $f19, 7*FFI_SIZEOF_ARG(t9)      
211 arg8_next:      
213 callit:         
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)
219         beqz    t5, noretval
221         # Shift the return type flag over
222         SRL     t6, 8*FFI_FLAG_BITS
223         
224         bne     t6, FFI_TYPE_INT, retfloat
225         jal     t9
226         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
227         REG_S   v0, 0(t4)
228         b       epilogue
230 retfloat:
231         bne     t6, FFI_TYPE_FLOAT, retdouble
232         jal     t9
233         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
234         s.s     $f0, 0(t4)
235         b       epilogue
237 retdouble:      
238         bne     t6, FFI_TYPE_DOUBLE, retstruct_d
239         jal     t9
240         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
241         s.d     $f0, 0(t4)
242         b       epilogue
244 retstruct_d:    
245         bne     t6, FFI_TYPE_STRUCT_D, retstruct_f
246         jal     t9
247         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
248         s.d     $f0, 0(t4)
249         b       epilogue
250         
251 retstruct_f:    
252         bne     t6, FFI_TYPE_STRUCT_F, retstruct_d_d
253         jal     t9
254         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
255         s.s     $f0, 0(t4)
256         b       epilogue
257         
258 retstruct_d_d:  
259         bne     t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
260         jal     t9
261         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
262         s.d     $f0, 0(t4)
263         s.d     $f2, 8(t4)
264         b       epilogue
265         
266 retstruct_f_f:  
267         bne     t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
268         jal     t9
269         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
270         s.s     $f0, 0(t4)
271         s.s     $f2, 4(t4)
272         b       epilogue
273         
274 retstruct_d_f:  
275         bne     t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
276         jal     t9
277         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
278         s.d     $f0, 0(t4)
279         s.s     $f2, 8(t4)
280         b       epilogue
281         
282 retstruct_f_d:  
283         bne     t6, FFI_TYPE_STRUCT_FD, retstruct_small
284         jal     t9
285         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
286         s.s     $f0, 0(t4)
287         s.d     $f2, 8(t4)
288         b       epilogue
289         
290 retstruct_small:        
291         bne     t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
292         jal     t9
293         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
294         REG_S   v0, 0(t4)
295         b       epilogue
296         
297 retstruct_small2:       
298         bne     t6, FFI_TYPE_STRUCT_SMALL2, retstruct
299         jal     t9
300         REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
301         REG_S   v0, 0(t4)
302         REG_S   v1, 8(t4)
303         b       epilogue
304         
305 retstruct:      
306 noretval:       
307         jal     t9
308         
309         # Epilogue
310 epilogue:       
311         move    $sp, $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
315         j       ra
317         .end    ffi_call_N32
318         
319 #endif