1/* -----------------------------------------------------------------------
2   freebsd.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
3	       Copyright (c) 2008  Bj��rn K��nig
4
5   X86 Foreign Function Interface for FreeBSD
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#ifndef __x86_64__
29
30#define LIBFFI_ASM
31#include <fficonfig.h>
32#include <ffi.h>
33
34.text
35
36.globl ffi_prep_args
37
38	.align 4
39.globl ffi_call_SYSV
40        .type    ffi_call_SYSV,@function
41
42ffi_call_SYSV:
43.LFB1:
44        pushl %ebp
45.LCFI0:
46        movl  %esp,%ebp
47.LCFI1:
48	/* Make room for all of the new args.  */
49	movl  16(%ebp),%ecx
50	subl  %ecx,%esp
51
52	/* Align the stack pointer to 16-bytes */
53	andl  $0xfffffff0, %esp
54
55	movl  %esp,%eax
56
57	/* Place all of the ffi_prep_args in position  */
58	pushl 12(%ebp)
59	pushl %eax
60	call  *8(%ebp)
61
62	/* Return stack to previous state and call the function  */
63	addl  $8,%esp
64
65	call  *28(%ebp)
66
67	/* Load %ecx with the return type code  */
68	movl  20(%ebp),%ecx
69
70	/* Protect %esi.  We're going to pop it in the epilogue.  */
71	pushl %esi
72
73	/* If the return value pointer is NULL, assume no return value.  */
74	cmpl  $0,24(%ebp)
75	jne  0f
76
77	/* Even if there is no space for the return value, we are
78	   obliged to handle floating-point values.  */
79	cmpl  $FFI_TYPE_FLOAT,%ecx
80	jne   noretval
81	fstp  %st(0)
82
83        jmp   epilogue
84
850:
86	call  1f
87
88.Lstore_table:
89	.long	noretval-.Lstore_table	/* FFI_TYPE_VOID */
90	.long	retint-.Lstore_table	/* FFI_TYPE_INT */
91	.long	retfloat-.Lstore_table	/* FFI_TYPE_FLOAT */
92	.long	retdouble-.Lstore_table	/* FFI_TYPE_DOUBLE */
93	.long	retlongdouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
94	.long	retuint8-.Lstore_table	/* FFI_TYPE_UINT8 */
95	.long	retsint8-.Lstore_table	/* FFI_TYPE_SINT8 */
96	.long	retuint16-.Lstore_table	/* FFI_TYPE_UINT16 */
97	.long	retsint16-.Lstore_table	/* FFI_TYPE_SINT16 */
98	.long	retint-.Lstore_table	/* FFI_TYPE_UINT32 */
99	.long	retint-.Lstore_table	/* FFI_TYPE_SINT32 */
100	.long	retint64-.Lstore_table	/* FFI_TYPE_UINT64 */
101	.long	retint64-.Lstore_table	/* FFI_TYPE_SINT64 */
102	.long	retstruct-.Lstore_table	/* FFI_TYPE_STRUCT */
103	.long	retint-.Lstore_table	/* FFI_TYPE_POINTER */
104	.long   retstruct1b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_1B */
105	.long   retstruct2b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_2B */
106
1071:
108	pop  %esi
109	add  (%esi, %ecx, 4), %esi
110	jmp  *%esi
111
112	/* Sign/zero extend as appropriate.  */
113retsint8:
114	movsbl  %al, %eax
115	jmp  retint
116
117retsint16:
118	movswl  %ax, %eax
119	jmp  retint
120
121retuint8:
122	movzbl  %al, %eax
123	jmp  retint
124
125retuint16:
126	movzwl  %ax, %eax
127	jmp  retint
128
129retfloat:
130	/* Load %ecx with the pointer to storage for the return value  */
131	movl  24(%ebp),%ecx
132	fstps (%ecx)
133	jmp   epilogue
134
135retdouble:
136	/* Load %ecx with the pointer to storage for the return value  */
137	movl  24(%ebp),%ecx
138	fstpl (%ecx)
139	jmp   epilogue
140
141retlongdouble:
142	/* Load %ecx with the pointer to storage for the return value  */
143	movl  24(%ebp),%ecx
144	fstpt (%ecx)
145	jmp   epilogue
146
147retint64:
148	/* Load %ecx with the pointer to storage for the return value  */
149	movl  24(%ebp),%ecx
150	movl  %eax,0(%ecx)
151	movl  %edx,4(%ecx)
152	jmp   epilogue
153
154retstruct1b:
155	/* Load %ecx with the pointer to storage for the return value  */
156	movl  24(%ebp),%ecx
157	movb  %al,0(%ecx)
158	jmp   epilogue
159
160retstruct2b:
161	/* Load %ecx with the pointer to storage for the return value  */
162	movl  24(%ebp),%ecx
163	movw  %ax,0(%ecx)
164	jmp   epilogue
165
166retint:
167	/* Load %ecx with the pointer to storage for the return value  */
168	movl  24(%ebp),%ecx
169	movl  %eax,0(%ecx)
170
171retstruct:
172	/* Nothing to do!  */
173
174noretval:
175epilogue:
176        popl %esi
177        movl %ebp,%esp
178        popl %ebp
179        ret
180.LFE1:
181.ffi_call_SYSV_end:
182        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
183
184	.align	4
185FFI_HIDDEN (ffi_closure_SYSV)
186.globl ffi_closure_SYSV
187	.type	ffi_closure_SYSV, @function
188
189ffi_closure_SYSV:
190.LFB2:
191	pushl	%ebp
192.LCFI2:
193	movl	%esp, %ebp
194.LCFI3:
195	subl	$40, %esp
196	leal	-24(%ebp), %edx
197	movl	%edx, -12(%ebp)	/* resp */
198	leal	8(%ebp), %edx
199	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
200	leal	-12(%ebp), %edx
201	movl	%edx, (%esp)	/* &resp */
202#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
203	call	ffi_closure_SYSV_inner
204#else
205	movl	%ebx, 8(%esp)
206.LCFI7:
207	call	1f
2081:	popl	%ebx
209	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
210	call	ffi_closure_SYSV_inner@PLT
211	movl	8(%esp), %ebx
212#endif
213	movl	-12(%ebp), %ecx
214	cmpl	$FFI_TYPE_INT, %eax
215	je	.Lcls_retint
216
217	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
218	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
219	cmpl	$FFI_TYPE_UINT64, %eax
220	jge	0f
221	cmpl	$FFI_TYPE_UINT8, %eax
222	jge	.Lcls_retint
223
2240:	cmpl	$FFI_TYPE_FLOAT, %eax
225	je	.Lcls_retfloat
226	cmpl	$FFI_TYPE_DOUBLE, %eax
227	je	.Lcls_retdouble
228	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
229	je	.Lcls_retldouble
230	cmpl	$FFI_TYPE_SINT64, %eax
231	je	.Lcls_retllong
232	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, %eax
233	je	.Lcls_retstruct1b
234	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, %eax
235	je	.Lcls_retstruct2b
236	cmpl	$FFI_TYPE_STRUCT, %eax
237	je	.Lcls_retstruct
238.Lcls_epilogue:
239	movl	%ebp, %esp
240	popl	%ebp
241	ret
242.Lcls_retint:
243	movl	(%ecx), %eax
244	jmp	.Lcls_epilogue
245.Lcls_retfloat:
246	flds	(%ecx)
247	jmp	.Lcls_epilogue
248.Lcls_retdouble:
249	fldl	(%ecx)
250	jmp	.Lcls_epilogue
251.Lcls_retldouble:
252	fldt	(%ecx)
253	jmp	.Lcls_epilogue
254.Lcls_retllong:
255	movl	(%ecx), %eax
256	movl	4(%ecx), %edx
257	jmp	.Lcls_epilogue
258.Lcls_retstruct1b:
259	movsbl	(%ecx), %eax
260	jmp	.Lcls_epilogue
261.Lcls_retstruct2b:
262	movswl	(%ecx), %eax
263	jmp	.Lcls_epilogue
264.Lcls_retstruct:
265	movl	%ebp, %esp
266	popl	%ebp
267	ret	$4
268.LFE2:
269	.size	ffi_closure_SYSV, .-ffi_closure_SYSV
270
271#if !FFI_NO_RAW_API
272
273#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
274#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
275#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
276#define CIF_FLAGS_OFFSET 20
277
278	.align	4
279FFI_HIDDEN (ffi_closure_raw_SYSV)
280.globl ffi_closure_raw_SYSV
281	.type	ffi_closure_raw_SYSV, @function
282
283ffi_closure_raw_SYSV:
284.LFB3:
285	pushl	%ebp
286.LCFI4:
287	movl	%esp, %ebp
288.LCFI5:
289	pushl	%esi
290.LCFI6:
291	subl	$36, %esp
292	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
293	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
294	movl	%edx, 12(%esp)	/* user_data */
295	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
296	movl	%edx, 8(%esp)	/* raw_args */
297	leal	-24(%ebp), %edx
298	movl	%edx, 4(%esp)	/* &res */
299	movl	%esi, (%esp)	/* cif */
300	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
301	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
302	cmpl	$FFI_TYPE_INT, %eax
303	je	.Lrcls_retint
304
305	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
306	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
307	cmpl	$FFI_TYPE_UINT64, %eax
308	jge	0f
309	cmpl	$FFI_TYPE_UINT8, %eax
310	jge	.Lrcls_retint
3110:
312	cmpl	$FFI_TYPE_FLOAT, %eax
313	je	.Lrcls_retfloat
314	cmpl	$FFI_TYPE_DOUBLE, %eax
315	je	.Lrcls_retdouble
316	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
317	je	.Lrcls_retldouble
318	cmpl	$FFI_TYPE_SINT64, %eax
319	je	.Lrcls_retllong
320.Lrcls_epilogue:
321	addl	$36, %esp
322	popl	%esi
323	popl	%ebp
324	ret
325.Lrcls_retint:
326	movl	-24(%ebp), %eax
327	jmp	.Lrcls_epilogue
328.Lrcls_retfloat:
329	flds	-24(%ebp)
330	jmp	.Lrcls_epilogue
331.Lrcls_retdouble:
332	fldl	-24(%ebp)
333	jmp	.Lrcls_epilogue
334.Lrcls_retldouble:
335	fldt	-24(%ebp)
336	jmp	.Lrcls_epilogue
337.Lrcls_retllong:
338	movl	-24(%ebp), %eax
339	movl	-20(%ebp), %edx
340	jmp	.Lrcls_epilogue
341.LFE3:
342	.size	ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
343#endif
344
345	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
346.Lframe1:
347	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
348.LSCIE1:
349	.long	0x0	/* CIE Identifier Tag */
350	.byte	0x1	/* CIE Version */
351#ifdef __PIC__
352	.ascii "zR\0"	/* CIE Augmentation */
353#else
354	.ascii "\0"	/* CIE Augmentation */
355#endif
356	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
357	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
358	.byte	0x8	/* CIE RA Column */
359#ifdef __PIC__
360	.byte	0x1	/* .uleb128 0x1; Augmentation size */
361	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */
362#endif
363	.byte	0xc	/* DW_CFA_def_cfa */
364	.byte	0x4	/* .uleb128 0x4 */
365	.byte	0x4	/* .uleb128 0x4 */
366	.byte	0x88	/* DW_CFA_offset, column 0x8 */
367	.byte	0x1	/* .uleb128 0x1 */
368	.align 4
369.LECIE1:
370.LSFDE1:
371	.long	.LEFDE1-.LASFDE1	/* FDE Length */
372.LASFDE1:
373	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
374#ifdef __PIC__
375	.long	.LFB1-.	/* FDE initial location */
376#else
377	.long	.LFB1	/* FDE initial location */
378#endif
379	.long	.LFE1-.LFB1	/* FDE address range */
380#ifdef __PIC__
381	.byte	0x0	/* .uleb128 0x0; Augmentation size */
382#endif
383	.byte	0x4	/* DW_CFA_advance_loc4 */
384	.long	.LCFI0-.LFB1
385	.byte	0xe	/* DW_CFA_def_cfa_offset */
386	.byte	0x8	/* .uleb128 0x8 */
387	.byte	0x85	/* DW_CFA_offset, column 0x5 */
388	.byte	0x2	/* .uleb128 0x2 */
389	.byte	0x4	/* DW_CFA_advance_loc4 */
390	.long	.LCFI1-.LCFI0
391	.byte	0xd	/* DW_CFA_def_cfa_register */
392	.byte	0x5	/* .uleb128 0x5 */
393	.align 4
394.LEFDE1:
395.LSFDE2:
396	.long	.LEFDE2-.LASFDE2	/* FDE Length */
397.LASFDE2:
398	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
399#ifdef __PIC__
400	.long	.LFB2-.	/* FDE initial location */
401#else
402	.long	.LFB2
403#endif
404	.long	.LFE2-.LFB2	/* FDE address range */
405#ifdef __PIC__
406	.byte	0x0	/* .uleb128 0x0; Augmentation size */
407#endif
408	.byte	0x4	/* DW_CFA_advance_loc4 */
409	.long	.LCFI2-.LFB2
410	.byte	0xe	/* DW_CFA_def_cfa_offset */
411	.byte	0x8	/* .uleb128 0x8 */
412	.byte	0x85	/* DW_CFA_offset, column 0x5 */
413	.byte	0x2	/* .uleb128 0x2 */
414	.byte	0x4	/* DW_CFA_advance_loc4 */
415	.long	.LCFI3-.LCFI2
416	.byte	0xd	/* DW_CFA_def_cfa_register */
417	.byte	0x5	/* .uleb128 0x5 */
418#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__
419	.byte	0x4	/* DW_CFA_advance_loc4 */
420	.long	.LCFI7-.LCFI3
421	.byte	0x83	/* DW_CFA_offset, column 0x3 */
422	.byte	0xa	/* .uleb128 0xa */
423#endif
424	.align 4
425.LEFDE2:
426
427#if !FFI_NO_RAW_API
428
429.LSFDE3:
430	.long	.LEFDE3-.LASFDE3	/* FDE Length */
431.LASFDE3:
432	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
433#ifdef __PIC__
434	.long	.LFB3-.	/* FDE initial location */
435#else
436	.long	.LFB3
437#endif
438	.long	.LFE3-.LFB3	/* FDE address range */
439#ifdef __PIC__
440	.byte	0x0	/* .uleb128 0x0; Augmentation size */
441#endif
442	.byte	0x4	/* DW_CFA_advance_loc4 */
443	.long	.LCFI4-.LFB3
444	.byte	0xe	/* DW_CFA_def_cfa_offset */
445	.byte	0x8	/* .uleb128 0x8 */
446	.byte	0x85	/* DW_CFA_offset, column 0x5 */
447	.byte	0x2	/* .uleb128 0x2 */
448	.byte	0x4	/* DW_CFA_advance_loc4 */
449	.long	.LCFI5-.LCFI4
450	.byte	0xd	/* DW_CFA_def_cfa_register */
451	.byte	0x5	/* .uleb128 0x5 */
452	.byte	0x4	/* DW_CFA_advance_loc4 */
453	.long	.LCFI6-.LCFI5
454	.byte	0x86	/* DW_CFA_offset, column 0x6 */
455	.byte	0x3	/* .uleb128 0x3 */
456	.align 4
457.LEFDE3:
458
459#endif
460
461#endif /* ifndef __x86_64__ */
462
463	.section .note.GNU-stack,"",%progbits
464