eba11c164722a2f34de166f139f7fabb24aab70d
[libffi.git] / libffi / src / x86 / win32.S
1 /* -----------------------------------------------------------------------
2    win32.S - Copyright (c) 1996, 1998, 2001, 2002  Red Hat, Inc.
3              Copyright (c) 2001  John Beniton
4              Copyright (c) 2002  Ranjit Mathew
5                         
6  
7    X86 Foreign Function Interface
8  
9    Permission is hereby granted, free of charge, to any person obtaining
10    a copy of this software and associated documentation files (the
11    ``Software''), to deal in the Software without restriction, including
12    without limitation the rights to use, copy, modify, merge, publish,
13    distribute, sublicense, and/or sell copies of the Software, and to
14    permit persons to whom the Software is furnished to do so, subject to
15    the following conditions:
16  
17    The above copyright notice and this permission notice shall be included
18    in all copies or substantial portions of the Software.
19  
20    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
24         ANY CLAIM, DAMAGES OR
25    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27    OTHER DEALINGS IN THE SOFTWARE.
28    ----------------------------------------------------------------------- */
29  
30 #define LIBFFI_ASM
31 #include <fficonfig.h>
32 #include <ffi.h>
33  
34 .text
35  
36 .globl ffi_prep_args
37  
38         # This assumes we are using gas.
39         .balign 16
40 .globl _ffi_call_SYSV
41  
42 _ffi_call_SYSV:
43         pushl %ebp
44         movl  %esp,%ebp
45  
46         # Make room for all of the new args.
47         movl  16(%ebp),%ecx                                                     
48         subl  %ecx,%esp
49  
50         movl  %esp,%eax
51  
52         # Place all of the ffi_prep_args in position
53         pushl 12(%ebp)
54         pushl %eax
55         call  *8(%ebp)
56  
57         # Return stack to previous state and call the function
58         addl  $8,%esp
59  
60         # FIXME: Align the stack to a 128-bit boundary to avoid
61         # potential performance hits.
62
63         call  *28(%ebp)
64  
65         # Remove the space we pushed for the args
66         movl  16(%ebp),%ecx
67         addl  %ecx,%esp
68  
69         # Load %ecx with the return type code
70         movl  20(%ebp),%ecx
71  
72         # If the return value pointer is NULL, assume no return value.
73         cmpl  $0,24(%ebp)
74         jne   retint
75  
76         # Even if there is no space for the return value, we are
77         # obliged to handle floating-point values.
78         cmpl  $FFI_TYPE_FLOAT,%ecx
79         jne   noretval
80         fstp  %st(0)
81  
82         jmp   epilogue
83  
84 retint:
85         cmpl  $FFI_TYPE_INT,%ecx
86         jne   retfloat
87         # Load %ecx with the pointer to storage for the return value
88         movl  24(%ebp),%ecx
89         movl  %eax,0(%ecx)
90         jmp   epilogue
91  
92 retfloat:
93         cmpl  $FFI_TYPE_FLOAT,%ecx
94         jne   retdouble   
95          # Load %ecx with the pointer to storage for the return value
96         movl  24(%ebp),%ecx
97         fstps (%ecx)
98         jmp   epilogue
99  
100 retdouble:
101         cmpl  $FFI_TYPE_DOUBLE,%ecx
102         jne   retlongdouble
103         # Load %ecx with the pointer to storage for the return value
104         movl  24(%ebp),%ecx
105         fstpl (%ecx)
106         jmp   epilogue
107  
108 retlongdouble:
109         cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
110         jne   retint64
111         # Load %ecx with the pointer to storage for the return value
112         movl  24(%ebp),%ecx
113         fstpt (%ecx)
114         jmp   epilogue
115  
116 retint64:
117         cmpl  $FFI_TYPE_SINT64,%ecx
118         jne   retstruct1b
119         # Load %ecx with the pointer to storage for the return value
120         movl  24(%ebp),%ecx
121         movl  %eax,0(%ecx)
122         movl  %edx,4(%ecx)
123  
124 retstruct1b:
125         cmpl  $FFI_TYPE_SINT8,%ecx
126         jne   retstruct2b
127         # Load %ecx with the pointer to storage for the return value
128         movl  24(%ebp),%ecx
129         movb  %al,0(%ecx)
130         jmp   epilogue
131  
132 retstruct2b:
133         cmpl  $FFI_TYPE_SINT16,%ecx
134         jne   retstruct
135         # Load %ecx with the pointer to storage for the return value
136         movl  24(%ebp),%ecx
137         movw  %ax,0(%ecx)
138         jmp   epilogue
139  
140 retstruct:
141         # Nothing to do!
142  
143 noretval:
144 epilogue:
145         movl %ebp,%esp
146         popl %ebp
147         ret
148  
149 .ffi_call_SYSV_end:
150
151         # This assumes we are using gas.
152         .balign 16
153 .globl _ffi_call_STDCALL
154
155 _ffi_call_STDCALL:
156         pushl %ebp
157         movl  %esp,%ebp
158
159         # Make room for all of the new args.
160         movl  16(%ebp),%ecx 
161         subl  %ecx,%esp
162
163         movl  %esp,%eax
164
165         # Place all of the ffi_prep_args in position
166         pushl 12(%ebp)
167         pushl %eax
168         call  *8(%ebp)
169
170         # Return stack to previous state and call the function
171         addl  $8,%esp
172
173         # FIXME: Align the stack to a 128-bit boundary to avoid
174         # potential performance hits.
175
176         call  *28(%ebp)
177
178         # stdcall functions pop arguments off the stack themselves
179
180         # Load %ecx with the return type code
181         movl  20(%ebp),%ecx
182
183         # If the return value pointer is NULL, assume no return value.
184         cmpl  $0,24(%ebp)
185         jne   sc_retint
186
187         # Even if there is no space for the return value, we are
188         # obliged to handle floating-point values.
189         cmpl  $FFI_TYPE_FLOAT,%ecx
190         jne   sc_noretval
191         fstp  %st(0)
192
193         jmp   sc_epilogue
194
195 sc_retint:
196         cmpl  $FFI_TYPE_INT,%ecx
197         jne   sc_retfloat
198         # Load %ecx with the pointer to storage for the return value
199         movl  24(%ebp),%ecx
200         movl  %eax,0(%ecx)
201         jmp   sc_epilogue
202
203 sc_retfloat:
204         cmpl  $FFI_TYPE_FLOAT,%ecx
205         jne   sc_retdouble
206          # Load %ecx with the pointer to storage for the return value
207         movl  24(%ebp),%ecx
208         fstps (%ecx)
209         jmp   sc_epilogue
210
211 sc_retdouble:
212         cmpl  $FFI_TYPE_DOUBLE,%ecx
213         jne   sc_retlongdouble
214         # Load %ecx with the pointer to storage for the return value
215         movl  24(%ebp),%ecx
216         fstpl (%ecx)
217         jmp   sc_epilogue
218
219 sc_retlongdouble:
220         cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
221         jne   sc_retint64
222         # Load %ecx with the pointer to storage for the return value
223         movl  24(%ebp),%ecx
224         fstpt (%ecx)
225         jmp   sc_epilogue
226
227 sc_retint64:
228         cmpl  $FFI_TYPE_SINT64,%ecx
229         jne   sc_retstruct1b
230         # Load %ecx with the pointer to storage for the return value
231         movl  24(%ebp),%ecx
232         movl  %eax,0(%ecx)
233         movl  %edx,4(%ecx)
234
235 sc_retstruct1b:
236         cmpl  $FFI_TYPE_SINT8,%ecx
237         jne   sc_retstruct2b
238         # Load %ecx with the pointer to storage for the return value
239         movl  24(%ebp),%ecx
240         movb  %al,0(%ecx)
241         jmp   sc_epilogue
242
243 sc_retstruct2b:
244         cmpl  $FFI_TYPE_SINT16,%ecx
245         jne   sc_retstruct
246         # Load %ecx with the pointer to storage for the return value
247         movl  24(%ebp),%ecx
248         movw  %ax,0(%ecx)
249         jmp   sc_epilogue
250
251 sc_retstruct:
252         # Nothing to do!
253
254 sc_noretval:
255 sc_epilogue:
256         movl %ebp,%esp
257         popl %ebp
258         ret
259
260 .ffi_call_STDCALL_end:
261
262         .globl _ffi_closure_STDCALL
263 _ffi_closure_STDCALL:
264         pushl   %ebp
265         movl    %esp, %ebp
266         subl    $40, %esp
267         leal    -24(%ebp), %edx
268         movl    %edx, -12(%ebp) /* resp */
269         leal    12(%ebp), %edx  /* account for stub return address on stack */
270         movl    %edx, 4(%esp)   /* args */
271         leal    -12(%ebp), %edx
272         movl    %edx, (%esp)    /* &resp */
273         call    _ffi_closure_SYSV_inner
274         movl    -12(%ebp), %ecx
275         jmp     .Lcls_return_result
276 .ffi_closure_STDCALL_end:
277
278         .globl _ffi_closure_SYSV
279 _ffi_closure_SYSV:
280         pushl   %ebp
281         movl    %esp, %ebp
282         subl    $40, %esp
283         leal    -24(%ebp), %edx
284         movl    %edx, -12(%ebp) /* resp */
285         leal    8(%ebp), %edx
286         movl    %edx, 4(%esp)   /* args = __builtin_dwarf_cfa () */
287         leal    -12(%ebp), %edx
288         movl    %edx, (%esp)    /* &resp */
289         call    _ffi_closure_SYSV_inner
290         movl    -12(%ebp), %ecx
291 .Lcls_return_result:
292         cmpl    $FFI_TYPE_INT, %eax
293         je      .Lcls_retint
294         cmpl    $FFI_TYPE_FLOAT, %eax
295         je      .Lcls_retfloat
296         cmpl    $FFI_TYPE_DOUBLE, %eax
297         je      .Lcls_retdouble
298         cmpl    $FFI_TYPE_LONGDOUBLE, %eax
299         je      .Lcls_retldouble
300         cmpl    $FFI_TYPE_SINT64, %eax
301         je      .Lcls_retllong
302         cmpl    $FFI_TYPE_SINT8, %eax   /* 1-byte struct */
303         je      .Lcls_retstruct1
304         cmpl    $FFI_TYPE_SINT16, %eax  /* 2-bytes struct */
305         je      .Lcls_retstruct2
306 .Lcls_epilogue:
307         movl    %ebp, %esp
308         popl    %ebp
309         ret
310 .Lcls_retint:
311         movl    (%ecx), %eax
312         jmp     .Lcls_epilogue
313 .Lcls_retfloat:
314         flds    (%ecx)
315         jmp     .Lcls_epilogue
316 .Lcls_retdouble:
317         fldl    (%ecx)
318         jmp     .Lcls_epilogue
319 .Lcls_retldouble:
320         fldt    (%ecx)
321         jmp     .Lcls_epilogue
322 .Lcls_retllong:
323         movl    (%ecx), %eax
324         movl    4(%ecx), %edx
325         jmp     .Lcls_epilogue
326 .Lcls_retstruct1:
327         movsbl  (%ecx), %eax
328         jmp     .Lcls_epilogue
329 .Lcls_retstruct2:
330         movswl  (%ecx), %eax
331         jmp     .Lcls_epilogue
332 .ffi_closure_SYSV_end:
333
334 #if !FFI_NO_RAW_API
335
336 #define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
337 #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
338 #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
339 #define CIF_FLAGS_OFFSET 20
340
341         .balign 16
342         .globl _ffi_closure_raw_SYSV
343 _ffi_closure_raw_SYSV:
344         pushl   %ebp
345         movl    %esp, %ebp
346         pushl   %esi
347         subl    $36, %esp
348         movl    RAW_CLOSURE_CIF_OFFSET(%eax), %esi       /* closure->cif */
349         movl    RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
350         movl    %edx, 12(%esp)  /* user_data */
351         leal    8(%ebp), %edx   /* __builtin_dwarf_cfa () */
352         movl    %edx, 8(%esp)   /* raw_args */
353         leal    -24(%ebp), %edx
354         movl    %edx, 4(%esp)   /* &res */
355         movl    %esi, (%esp)    /* cif */
356         call    *RAW_CLOSURE_FUN_OFFSET(%eax)            /* closure->fun */
357         movl    CIF_FLAGS_OFFSET(%esi), %eax             /* rtype */
358         cmpl    $FFI_TYPE_INT, %eax
359         je      .Lrcls_retint
360         cmpl    $FFI_TYPE_FLOAT, %eax
361         je      .Lrcls_retfloat
362         cmpl    $FFI_TYPE_DOUBLE, %eax
363         je      .Lrcls_retdouble
364         cmpl    $FFI_TYPE_LONGDOUBLE, %eax
365         je      .Lrcls_retldouble
366         cmpl    $FFI_TYPE_SINT64, %eax
367         je      .Lrcls_retllong
368 .Lrcls_epilogue:
369         addl    $36, %esp
370         popl    %esi
371         popl    %ebp
372         ret
373 .Lrcls_retint:
374         movl    -24(%ebp), %eax
375         jmp     .Lrcls_epilogue
376 .Lrcls_retfloat:
377         flds    -24(%ebp)
378         jmp     .Lrcls_epilogue
379 .Lrcls_retdouble:
380         fldl    -24(%ebp)
381         jmp     .Lrcls_epilogue
382 .Lrcls_retldouble:
383         fldt    -24(%ebp)
384         jmp     .Lrcls_epilogue
385 .Lrcls_retllong:
386         movl    -24(%ebp), %eax
387         movl    -20(%ebp), %edx
388         jmp     .Lrcls_epilogue
389 .ffi_closure_raw_SYSV_end:
390
391 #endif