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