OSDN Git Service

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