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