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
84retint:
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
92retfloat:
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
100retdouble:
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
108retlongdouble:
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
116retint64:
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
124retstruct1b:
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
132retstruct2b:
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
140retstruct:
141        # Nothing to do!
142
143noretval:
144epilogue:
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
195sc_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
203sc_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
211sc_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
219sc_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
227sc_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
235sc_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
243sc_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
251sc_retstruct:
252        # Nothing to do!
253
254sc_noretval:
255sc_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
392