OSDN Git Service

2002-07-18 H.J. Lu (hjl@gnu.org)
[pf3gnuchains/gcc-fork.git] / libffi / src / mips / n32.S
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
45 ffi_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
69 sixteen:
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         
97 loadregs:       
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
106 arg1_floatp:    
107         bne     t4, FFI_TYPE_FLOAT, arg1_doublep
108         l.s     $f12, 0*SIZEOF_ARG(t9)
109         b       arg1_next
110 arg1_doublep:   
111         l.d     $f12, 0*SIZEOF_ARG(t9)
112 arg1_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
120 arg2_floatp:
121         bne     t4, FFI_TYPE_FLOAT, arg2_doublep
122         l.s     $f13, 1*SIZEOF_ARG(t9)  
123         b       arg2_next
124 arg2_doublep:   
125         l.d     $f13, 1*SIZEOF_ARG(t9)  
126 arg2_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
134 arg3_floatp:
135         bne     t4, FFI_TYPE_FLOAT, arg3_doublep
136         l.s     $f14, 2*SIZEOF_ARG(t9)  
137         b       arg3_next
138 arg3_doublep:   
139         l.d     $f14, 2*SIZEOF_ARG(t9)  
140 arg3_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
148 arg4_floatp:
149         bne     t4, FFI_TYPE_FLOAT, arg4_doublep
150         l.s     $f15, 3*SIZEOF_ARG(t9)  
151         b       arg4_next
152 arg4_doublep:   
153         l.d     $f15, 3*SIZEOF_ARG(t9)  
154 arg4_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
162 arg5_floatp:
163         bne     t4, FFI_TYPE_FLOAT, arg5_doublep
164         l.s     $f16, 4*SIZEOF_ARG(t9)  
165         b       arg5_next
166 arg5_doublep:   
167         l.d     $f16, 4*SIZEOF_ARG(t9)  
168 arg5_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
176 arg6_floatp:
177         bne     t4, FFI_TYPE_FLOAT, arg6_doublep
178         l.s     $f17, 5*SIZEOF_ARG(t9)  
179         b       arg6_next
180 arg6_doublep:   
181         l.d     $f17, 5*SIZEOF_ARG(t9)  
182 arg6_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
190 arg7_floatp:
191         bne     t4, FFI_TYPE_FLOAT, arg7_doublep
192         l.s     $f18, 6*SIZEOF_ARG(t9)  
193         b       arg7_next
194 arg7_doublep:   
195         l.d     $f18, 6*SIZEOF_ARG(t9)  
196 arg7_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
204 arg8_floatp:
205         bne     t4, FFI_TYPE_FLOAT, arg8_doublep
206         l.s     $f19, 7*SIZEOF_ARG(t9)  
207         b       arg8_next
208 arg8_doublep:   
209         l.d     $f19, 7*SIZEOF_ARG(t9)  
210 arg8_next:      
211
212 callit:         
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
229 retfloat:
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
236 retdouble:      
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
243 retstruct_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         
250 retstruct_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         
257 retstruct_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         
265 retstruct_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         
273 retstruct_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         
281 retstruct_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         
289 retstruct_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         
296 retstruct_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         
304 retstruct:      
305 noretval:       
306         jal     t9
307         
308         # Epilogue
309 epilogue:       
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