1/* -----------------------------------------------------------------------
2   darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
3	Copyright (C) 2008  Free Software Foundation, Inc.
4
5   X86 Foreign Function Interface
6
7   Permission is hereby granted, free of charge, to any person obtaining
8   a copy of this software and associated documentation files (the
9   ``Software''), to deal in the Software without restriction, including
10   without limitation the rights to use, copy, modify, merge, publish,
11   distribute, sublicense, and/or sell copies of the Software, and to
12   permit persons to whom the Software is furnished to do so, subject to
13   the following conditions:
14
15   The above copyright notice and this permission notice shall be included
16   in all copies or substantial portions of the Software.
17
18   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25   DEALINGS IN THE SOFTWARE.
26   -----------------------------------------------------------------------
27   */
28
29#ifndef __x86_64__
30
31#define LIBFFI_ASM
32#include <fficonfig.h>
33#include <ffi.h>
34
35.text
36
37.globl _ffi_prep_args
38
39	.align 4
40.globl _ffi_call_SYSV
41
42_ffi_call_SYSV:
43.LFB1:
44        pushl %ebp
45.LCFI0:
46        movl  %esp,%ebp
47.LCFI1:
48        subl $8,%esp
49	/* Make room for all of the new args.  */
50	movl  16(%ebp),%ecx
51	subl  %ecx,%esp
52
53	movl  %esp,%eax
54
55	/* Place all of the ffi_prep_args in position  */
56	subl  $8,%esp
57	pushl 12(%ebp)
58	pushl %eax
59	call  *8(%ebp)
60
61	/* Return stack to previous state and call the function  */
62	addl  $16,%esp
63
64	call  *28(%ebp)
65
66	/* Load %ecx with the return type code  */
67	movl  20(%ebp),%ecx
68
69	/* Protect %esi.  We're going to pop it in the epilogue.  */
70	pushl %esi
71
72	/* If the return value pointer is NULL, assume no return value.  */
73	cmpl  $0,24(%ebp)
74	jne  0f
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
830:
84	.align 4
85	call 1f
86.Lstore_table:
87	.long   noretval-.Lstore_table		/* FFI_TYPE_VOID */
88	.long   retint-.Lstore_table		/* FFI_TYPE_INT */
89	.long   retfloat-.Lstore_table		/* FFI_TYPE_FLOAT */
90	.long   retdouble-.Lstore_table		/* FFI_TYPE_DOUBLE */
91	.long   retlongdouble-.Lstore_table     /* FFI_TYPE_LONGDOUBLE */
92	.long   retuint8-.Lstore_table		/* FFI_TYPE_UINT8 */
93	.long   retsint8-.Lstore_table		/* FFI_TYPE_SINT8 */
94	.long   retuint16-.Lstore_table		/* FFI_TYPE_UINT16 */
95	.long   retsint16-.Lstore_table		/* FFI_TYPE_SINT16 */
96	.long   retint-.Lstore_table		/* FFI_TYPE_UINT32 */
97	.long   retint-.Lstore_table		/* FFI_TYPE_SINT32 */
98	.long   retint64-.Lstore_table		/* FFI_TYPE_UINT64 */
99	.long   retint64-.Lstore_table		/* FFI_TYPE_SINT64 */
100	.long   retstruct-.Lstore_table		/* FFI_TYPE_STRUCT */
101	.long   retint-.Lstore_table		/* FFI_TYPE_POINTER */
102	.long   retstruct1b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_1B */
103	.long   retstruct2b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_2B */
1041:
105	pop  %esi
106	add  (%esi, %ecx, 4), %esi
107	jmp  *%esi
108
109	/* Sign/zero extend as appropriate.  */
110retsint8:
111	movsbl  %al, %eax
112	jmp  retint
113
114retsint16:
115	movswl  %ax, %eax
116	jmp  retint
117
118retuint8:
119	movzbl  %al, %eax
120	jmp  retint
121
122retuint16:
123	movzwl  %ax, %eax
124	jmp  retint
125
126retfloat:
127	/* Load %ecx with the pointer to storage for the return value  */
128	movl  24(%ebp),%ecx
129	fstps (%ecx)
130	jmp   epilogue
131
132retdouble:
133	/* Load %ecx with the pointer to storage for the return value  */
134	movl  24(%ebp),%ecx
135	fstpl (%ecx)
136	jmp   epilogue
137
138retlongdouble:
139	/* Load %ecx with the pointer to storage for the return value  */
140	movl  24(%ebp),%ecx
141	fstpt (%ecx)
142	jmp   epilogue
143
144retint64:
145	/* Load %ecx with the pointer to storage for the return value  */
146	movl  24(%ebp),%ecx
147	movl  %eax,0(%ecx)
148	movl  %edx,4(%ecx)
149	jmp   epilogue
150
151retstruct1b:
152	/* Load %ecx with the pointer to storage for the return value  */
153	movl  24(%ebp),%ecx
154	movb  %al,0(%ecx)
155	jmp   epilogue
156
157retstruct2b:
158	/* Load %ecx with the pointer to storage for the return value  */
159	movl  24(%ebp),%ecx
160	movw  %ax,0(%ecx)
161	jmp   epilogue
162
163retint:
164	/* Load %ecx with the pointer to storage for the return value  */
165	movl  24(%ebp),%ecx
166	movl  %eax,0(%ecx)
167
168retstruct:
169	/* Nothing to do!  */
170
171noretval:
172epilogue:
173	popl %esi
174	movl %ebp,%esp
175	popl %ebp
176	ret
177
178.LFE1:
179.ffi_call_SYSV_end:
180
181	.align	4
182FFI_HIDDEN (ffi_closure_SYSV)
183.globl _ffi_closure_SYSV
184
185_ffi_closure_SYSV:
186.LFB2:
187	pushl	%ebp
188.LCFI2:
189	movl	%esp, %ebp
190.LCFI3:
191	subl	$40, %esp
192	leal	-24(%ebp), %edx
193	movl	%edx, -12(%ebp)	/* resp */
194	leal	8(%ebp), %edx
195	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
196	leal	-12(%ebp), %edx
197	movl	%edx, (%esp)	/* &resp */
198	movl	%ebx, 8(%esp)
199.LCFI7:
200	call	L_ffi_closure_SYSV_inner$stub
201	movl	8(%esp), %ebx
202	movl	-12(%ebp), %ecx
203	cmpl	$FFI_TYPE_INT, %eax
204	je	.Lcls_retint
205
206	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
207	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
208	cmpl	$FFI_TYPE_UINT64, %eax
209	jge	0f
210	cmpl	$FFI_TYPE_UINT8, %eax
211	jge	.Lcls_retint
212
2130:	cmpl	$FFI_TYPE_FLOAT, %eax
214	je	.Lcls_retfloat
215	cmpl	$FFI_TYPE_DOUBLE, %eax
216	je	.Lcls_retdouble
217	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
218	je	.Lcls_retldouble
219	cmpl	$FFI_TYPE_SINT64, %eax
220	je	.Lcls_retllong
221	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, %eax
222	je	.Lcls_retstruct1b
223	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, %eax
224	je	.Lcls_retstruct2b
225	cmpl	$FFI_TYPE_STRUCT, %eax
226	je	.Lcls_retstruct
227.Lcls_epilogue:
228	movl	%ebp, %esp
229	popl	%ebp
230	ret
231.Lcls_retint:
232	movl	(%ecx), %eax
233	jmp	.Lcls_epilogue
234.Lcls_retfloat:
235	flds	(%ecx)
236	jmp	.Lcls_epilogue
237.Lcls_retdouble:
238	fldl	(%ecx)
239	jmp	.Lcls_epilogue
240.Lcls_retldouble:
241	fldt	(%ecx)
242	jmp	.Lcls_epilogue
243.Lcls_retllong:
244	movl	(%ecx), %eax
245	movl	4(%ecx), %edx
246	jmp	.Lcls_epilogue
247.Lcls_retstruct1b:
248	movsbl	(%ecx), %eax
249	jmp	.Lcls_epilogue
250.Lcls_retstruct2b:
251	movswl	(%ecx), %eax
252	jmp	.Lcls_epilogue
253.Lcls_retstruct:
254	lea -8(%ebp),%esp
255	movl	%ebp, %esp
256	popl	%ebp
257	ret $4
258.LFE2:
259
260#if !FFI_NO_RAW_API
261
262#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
263#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
264#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
265#define CIF_FLAGS_OFFSET 20
266
267	.align	4
268FFI_HIDDEN (ffi_closure_raw_SYSV)
269.globl _ffi_closure_raw_SYSV
270
271_ffi_closure_raw_SYSV:
272.LFB3:
273	pushl	%ebp
274.LCFI4:
275	movl	%esp, %ebp
276.LCFI5:
277	pushl	%esi
278.LCFI6:
279	subl	$36, %esp
280	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
281	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
282	movl	%edx, 12(%esp)	/* user_data */
283	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
284	movl	%edx, 8(%esp)	/* raw_args */
285	leal	-24(%ebp), %edx
286	movl	%edx, 4(%esp)	/* &res */
287	movl	%esi, (%esp)	/* cif */
288	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
289	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
290	cmpl	$FFI_TYPE_INT, %eax
291	je	.Lrcls_retint
292
293	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
294	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
295	cmpl	$FFI_TYPE_UINT64, %eax
296	jge	0f
297	cmpl	$FFI_TYPE_UINT8, %eax
298	jge	.Lrcls_retint
2990:
300	cmpl	$FFI_TYPE_FLOAT, %eax
301	je	.Lrcls_retfloat
302	cmpl	$FFI_TYPE_DOUBLE, %eax
303	je	.Lrcls_retdouble
304	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
305	je	.Lrcls_retldouble
306	cmpl	$FFI_TYPE_SINT64, %eax
307	je	.Lrcls_retllong
308.Lrcls_epilogue:
309	addl	$36, %esp
310	popl	%esi
311	popl	%ebp
312	ret
313.Lrcls_retint:
314	movl	-24(%ebp), %eax
315	jmp	.Lrcls_epilogue
316.Lrcls_retfloat:
317	flds	-24(%ebp)
318	jmp	.Lrcls_epilogue
319.Lrcls_retdouble:
320	fldl	-24(%ebp)
321	jmp	.Lrcls_epilogue
322.Lrcls_retldouble:
323	fldt	-24(%ebp)
324	jmp	.Lrcls_epilogue
325.Lrcls_retllong:
326	movl	-24(%ebp), %eax
327	movl	-20(%ebp), %edx
328	jmp	.Lrcls_epilogue
329.LFE3:
330#endif
331
332.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
333L_ffi_closure_SYSV_inner$stub:
334	.indirect_symbol _ffi_closure_SYSV_inner
335	hlt ; hlt ; hlt ; hlt ; hlt
336
337
338.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
339EH_frame1:
340	.set	L$set$0,LECIE1-LSCIE1
341	.long	L$set$0
342LSCIE1:
343	.long	0x0
344	.byte	0x1
345	.ascii "zR\0"
346	.byte	0x1
347	.byte	0x7c
348	.byte	0x8
349	.byte	0x1
350	.byte	0x10
351	.byte	0xc
352	.byte	0x5
353	.byte	0x4
354	.byte	0x88
355	.byte	0x1
356	.align 2
357LECIE1:
358.globl _ffi_call_SYSV.eh
359_ffi_call_SYSV.eh:
360LSFDE1:
361	.set	L$set$1,LEFDE1-LASFDE1
362	.long	L$set$1
363LASFDE1:
364	.long	LASFDE1-EH_frame1
365	.long	.LFB1-.
366	.set L$set$2,.LFE1-.LFB1
367	.long L$set$2
368	.byte	0x0
369	.byte	0x4
370	.set L$set$3,.LCFI0-.LFB1
371	.long L$set$3
372	.byte	0xe
373	.byte	0x8
374	.byte	0x84
375	.byte	0x2
376	.byte	0x4
377	.set L$set$4,.LCFI1-.LCFI0
378	.long L$set$4
379	.byte	0xd
380	.byte	0x4
381	.align 2
382LEFDE1:
383.globl _ffi_closure_SYSV.eh
384_ffi_closure_SYSV.eh:
385LSFDE2:
386	.set	L$set$5,LEFDE2-LASFDE2
387	.long	L$set$5
388LASFDE2:
389	.long	LASFDE2-EH_frame1
390	.long	.LFB2-.
391	.set L$set$6,.LFE2-.LFB2
392	.long L$set$6
393	.byte	0x0
394	.byte	0x4
395	.set L$set$7,.LCFI2-.LFB2
396	.long L$set$7
397	.byte	0xe
398	.byte	0x8
399	.byte	0x84
400	.byte	0x2
401	.byte	0x4
402	.set L$set$8,.LCFI3-.LCFI2
403	.long L$set$8
404	.byte	0xd
405	.byte	0x4
406	.align 2
407LEFDE2:
408
409#if !FFI_NO_RAW_API
410
411.globl _ffi_closure_raw_SYSV.eh
412_ffi_closure_raw_SYSV.eh:
413LSFDE3:
414	.set	L$set$10,LEFDE3-LASFDE3
415	.long	L$set$10
416LASFDE3:
417	.long	LASFDE3-EH_frame1
418	.long	.LFB3-.
419	.set L$set$11,.LFE3-.LFB3
420	.long L$set$11
421	.byte	0x0
422	.byte	0x4
423	.set L$set$12,.LCFI4-.LFB3
424	.long L$set$12
425	.byte	0xe
426	.byte	0x8
427	.byte	0x84
428	.byte	0x2
429	.byte	0x4
430	.set L$set$13,.LCFI5-.LCFI4
431	.long L$set$13
432	.byte	0xd
433	.byte	0x4
434	.byte	0x4
435	.set L$set$14,.LCFI6-.LCFI5
436	.long L$set$14
437	.byte	0x85
438	.byte	0x3
439	.align 2
440LEFDE3:
441
442#endif
443
444#endif /* ifndef __x86_64__ */
445