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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26   OTHER DEALINGS IN THE SOFTWARE.
27   ----------------------------------------------------------------------- */
28
29#define LIBFFI_ASM
30#include <fficonfig.h>
31#include <ffi.h>
32
33.text
34
35.globl ffi_prep_args
36
37        # This assumes we are using gas.
38        .balign 16
39.globl _ffi_call_SYSV
40
41_ffi_call_SYSV:
42        pushl %ebp
43        movl  %esp,%ebp
44
45        # Make room for all of the new args.
46        movl  16(%ebp),%ecx
47        subl  %ecx,%esp
48
49        movl  %esp,%eax
50
51        # Place all of the ffi_prep_args in position
52        pushl 12(%ebp)
53        pushl %eax
54        call  *8(%ebp)
55
56        # Return stack to previous state and call the function
57        addl  $8,%esp
58
59        # FIXME: Align the stack to a 128-bit boundary to avoid
60        # potential performance hits.
61
62	call  *28(%ebp)
63
64        # Remove the space we pushed for the args
65        movl  16(%ebp),%ecx
66        addl  %ecx,%esp
67
68        # Load %ecx with the return type code
69        movl  20(%ebp),%ecx
70
71        # If the return value pointer is NULL, assume no return value.
72        cmpl  $0,24(%ebp)
73        jne   retint
74
75        # Even if there is no space for the return value, we are
76        # obliged to handle floating-point values.
77        cmpl  $FFI_TYPE_FLOAT,%ecx
78        jne   noretval
79        fstp  %st(0)
80
81        jmp   epilogue
82
83retint:
84        cmpl  $FFI_TYPE_INT,%ecx
85        jne   retfloat
86        # Load %ecx with the pointer to storage for the return value
87        movl  24(%ebp),%ecx
88        movl  %eax,0(%ecx)
89        jmp   epilogue
90
91retfloat:
92        cmpl  $FFI_TYPE_FLOAT,%ecx
93        jne   retdouble
94         # Load %ecx with the pointer to storage for the return value
95        movl  24(%ebp),%ecx
96        fstps (%ecx)
97        jmp   epilogue
98
99retdouble:
100        cmpl  $FFI_TYPE_DOUBLE,%ecx
101        jne   retlongdouble
102        # Load %ecx with the pointer to storage for the return value
103        movl  24(%ebp),%ecx
104        fstpl (%ecx)
105        jmp   epilogue
106
107retlongdouble:
108        cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
109        jne   retint64
110        # Load %ecx with the pointer to storage for the return value
111        movl  24(%ebp),%ecx
112        fstpt (%ecx)
113        jmp   epilogue
114
115retint64:
116        cmpl  $FFI_TYPE_SINT64,%ecx
117        jne   retstruct
118        # Load %ecx with the pointer to storage for the return value
119        movl  24(%ebp),%ecx
120        movl  %eax,0(%ecx)
121        movl  %edx,4(%ecx)
122
123retstruct:
124        # Nothing to do!
125
126noretval:
127epilogue:
128        movl %ebp,%esp
129        popl %ebp
130        ret
131
132.ffi_call_SYSV_end:
133
134        # This assumes we are using gas.
135        .balign 16
136.globl _ffi_call_STDCALL
137
138_ffi_call_STDCALL:
139        pushl %ebp
140        movl  %esp,%ebp
141
142        # Make room for all of the new args.
143        movl  16(%ebp),%ecx
144        subl  %ecx,%esp
145
146        movl  %esp,%eax
147
148        # Place all of the ffi_prep_args in position
149        pushl 12(%ebp)
150        pushl %eax
151        call  *8(%ebp)
152
153        # Return stack to previous state and call the function
154        addl  $8,%esp
155
156        # FIXME: Align the stack to a 128-bit boundary to avoid
157        # potential performance hits.
158
159        call  *28(%ebp)
160
161        # stdcall functions pop arguments off the stack themselves
162
163        # Load %ecx with the return type code
164        movl  20(%ebp),%ecx
165
166        # If the return value pointer is NULL, assume no return value.
167        cmpl  $0,24(%ebp)
168        jne   sc_retint
169
170        # Even if there is no space for the return value, we are
171        # obliged to handle floating-point values.
172        cmpl  $FFI_TYPE_FLOAT,%ecx
173        jne   sc_noretval
174        fstp  %st(0)
175
176        jmp   sc_epilogue
177
178sc_retint:
179        cmpl  $FFI_TYPE_INT,%ecx
180        jne   sc_retfloat
181        # Load %ecx with the pointer to storage for the return value
182        movl  24(%ebp),%ecx
183        movl  %eax,0(%ecx)
184        jmp   sc_epilogue
185
186sc_retfloat:
187        cmpl  $FFI_TYPE_FLOAT,%ecx
188        jne   sc_retdouble
189         # Load %ecx with the pointer to storage for the return value
190        movl  24(%ebp),%ecx
191        fstps (%ecx)
192        jmp   sc_epilogue
193
194sc_retdouble:
195        cmpl  $FFI_TYPE_DOUBLE,%ecx
196        jne   sc_retlongdouble
197        # Load %ecx with the pointer to storage for the return value
198        movl  24(%ebp),%ecx
199        fstpl (%ecx)
200        jmp   sc_epilogue
201
202sc_retlongdouble:
203        cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
204        jne   sc_retint64
205        # Load %ecx with the pointer to storage for the return value
206        movl  24(%ebp),%ecx
207        fstpt (%ecx)
208        jmp   sc_epilogue
209
210sc_retint64:
211        cmpl  $FFI_TYPE_SINT64,%ecx
212        jne   sc_retstruct
213        # Load %ecx with the pointer to storage for the return value
214        movl  24(%ebp),%ecx
215        movl  %eax,0(%ecx)
216        movl  %edx,4(%ecx)
217
218sc_retstruct:
219        # Nothing to do!
220
221sc_noretval:
222sc_epilogue:
223        movl %ebp,%esp
224        popl %ebp
225        ret
226
227.ffi_call_STDCALL_end:
228