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