OSDN Git Service

2008-02-26 Anthony Green <green@redhat.com>
[pf3gnuchains/gcc-fork.git] / libffi / src / x86 / win32.S
1 /* -----------------------------------------------------------------------
2    win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009  Red Hat, Inc.
3              Copyright (c) 2001  John Beniton
4              Copyright (c) 2002  Ranjit Mathew
5                         
6  
7    X86 Foreign Function Interface
8  
9    Permission is hereby granted, free of charge, to any person obtaining
10    a copy of this software and associated documentation files (the
11    ``Software''), to deal in the Software without restriction, including
12    without limitation the rights to use, copy, modify, merge, publish,
13    distribute, sublicense, and/or sell copies of the Software, and to
14    permit persons to whom the Software is furnished to do so, subject to
15    the following conditions:
16  
17    The above copyright notice and this permission notice shall be included
18    in all copies or substantial portions of the Software.
19  
20    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
21    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27    DEALINGS IN THE SOFTWARE.
28    -----------------------------------------------------------------------
29    */
30  
31 #define LIBFFI_ASM
32 #include <fficonfig.h>
33 #include <ffi.h>
34  
35         .text
36  
37         .extern ffi_prep_args
38  
39         # This assumes we are using gas.
40         .balign 16
41         .globl  _ffi_call_SYSV
42         .def    _ffi_call_SYSV; .scl    2;      .type   32;     .endef
43 _ffi_call_SYSV:
44 .LFB1:
45         pushl %ebp
46 .LCFI0:
47         movl  %esp,%ebp
48 .LCFI1:
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         pushl 12(%ebp)
57         pushl %eax
58         call  *8(%ebp)
59  
60         # Return stack to previous state and call the function
61         addl  $8,%esp
62  
63         # FIXME: Align the stack to a 128-bit boundary to avoid
64         # potential performance hits.
65
66         call  *28(%ebp)
67  
68         # Remove the space we pushed for the args
69         movl  16(%ebp),%ecx
70         addl  %ecx,%esp
71  
72         # Load %ecx with the return type code
73         movl  20(%ebp),%ecx
74  
75         # If the return value pointer is NULL, assume no return value.
76         cmpl  $0,24(%ebp)
77         jne   retint
78  
79         # Even if there is no space for the return value, we are
80         # obliged to handle floating-point values.
81         cmpl  $FFI_TYPE_FLOAT,%ecx
82         jne   noretval
83         fstp  %st(0)
84  
85         jmp   epilogue
86  
87 retint:
88         cmpl  $FFI_TYPE_INT,%ecx
89         jne   retfloat
90         # Load %ecx with the pointer to storage for the return value
91         movl  24(%ebp),%ecx
92         movl  %eax,0(%ecx)
93         jmp   epilogue
94  
95 retfloat:
96         cmpl  $FFI_TYPE_FLOAT,%ecx
97         jne   retdouble   
98          # Load %ecx with the pointer to storage for the return value
99         movl  24(%ebp),%ecx
100         fstps (%ecx)
101         jmp   epilogue
102  
103 retdouble:
104         cmpl  $FFI_TYPE_DOUBLE,%ecx
105         jne   retlongdouble
106         # Load %ecx with the pointer to storage for the return value
107         movl  24(%ebp),%ecx
108         fstpl (%ecx)
109         jmp   epilogue
110  
111 retlongdouble:
112         cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
113         jne   retint64
114         # Load %ecx with the pointer to storage for the return value
115         movl  24(%ebp),%ecx
116         fstpt (%ecx)
117         jmp   epilogue
118  
119 retint64:
120         cmpl  $FFI_TYPE_SINT64,%ecx
121         jne   retstruct1b
122         # Load %ecx with the pointer to storage for the return value
123         movl  24(%ebp),%ecx
124         movl  %eax,0(%ecx)
125         movl  %edx,4(%ecx)
126  
127 retstruct1b:
128         cmpl  $FFI_TYPE_SINT8,%ecx
129         jne   retstruct2b
130         # Load %ecx with the pointer to storage for the return value
131         movl  24(%ebp),%ecx
132         movb  %al,0(%ecx)
133         jmp   epilogue
134  
135 retstruct2b:
136         cmpl  $FFI_TYPE_SINT16,%ecx
137         jne   retstruct
138         # Load %ecx with the pointer to storage for the return value
139         movl  24(%ebp),%ecx
140         movw  %ax,0(%ecx)
141         jmp   epilogue
142  
143 retstruct:
144         # Nothing to do!
145  
146 noretval:
147 epilogue:
148         movl %ebp,%esp
149         popl %ebp
150         ret
151 .ffi_call_SYSV_end:
152 .LFE1:
153
154         # This assumes we are using gas.
155         .balign 16
156         .globl  _ffi_call_STDCALL
157         .def    _ffi_call_STDCALL;      .scl    2;      .type   32;     .endef
158 _ffi_call_STDCALL:
159 .LFB2:
160         pushl %ebp
161 .LCFI2:
162         movl  %esp,%ebp
163 .LCFI3:
164         # Make room for all of the new args.
165         movl  16(%ebp),%ecx 
166         subl  %ecx,%esp
167
168         movl  %esp,%eax
169
170         # Place all of the ffi_prep_args in position
171         pushl 12(%ebp)
172         pushl %eax
173         call  *8(%ebp)
174
175         # Return stack to previous state and call the function
176         addl  $8,%esp
177
178         # FIXME: Align the stack to a 128-bit boundary to avoid
179         # potential performance hits.
180
181         call  *28(%ebp)
182
183         # stdcall functions pop arguments off the stack themselves
184
185         # Load %ecx with the return type code
186         movl  20(%ebp),%ecx
187
188         # If the return value pointer is NULL, assume no return value.
189         cmpl  $0,24(%ebp)
190         jne   sc_retint
191
192         # Even if there is no space for the return value, we are
193         # obliged to handle floating-point values.
194         cmpl  $FFI_TYPE_FLOAT,%ecx
195         jne   sc_noretval
196         fstp  %st(0)
197
198         jmp   sc_epilogue
199
200 sc_retint:
201         cmpl  $FFI_TYPE_INT,%ecx
202         jne   sc_retfloat
203         # Load %ecx with the pointer to storage for the return value
204         movl  24(%ebp),%ecx
205         movl  %eax,0(%ecx)
206         jmp   sc_epilogue
207
208 sc_retfloat:
209         cmpl  $FFI_TYPE_FLOAT,%ecx
210         jne   sc_retdouble
211          # Load %ecx with the pointer to storage for the return value
212         movl  24(%ebp),%ecx
213         fstps (%ecx)
214         jmp   sc_epilogue
215
216 sc_retdouble:
217         cmpl  $FFI_TYPE_DOUBLE,%ecx
218         jne   sc_retlongdouble
219         # Load %ecx with the pointer to storage for the return value
220         movl  24(%ebp),%ecx
221         fstpl (%ecx)
222         jmp   sc_epilogue
223
224 sc_retlongdouble:
225         cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
226         jne   sc_retint64
227         # Load %ecx with the pointer to storage for the return value
228         movl  24(%ebp),%ecx
229         fstpt (%ecx)
230         jmp   sc_epilogue
231
232 sc_retint64:
233         cmpl  $FFI_TYPE_SINT64,%ecx
234         jne   sc_retstruct1b
235         # Load %ecx with the pointer to storage for the return value
236         movl  24(%ebp),%ecx
237         movl  %eax,0(%ecx)
238         movl  %edx,4(%ecx)
239
240 sc_retstruct1b:
241         cmpl  $FFI_TYPE_SINT8,%ecx
242         jne   sc_retstruct2b
243         # Load %ecx with the pointer to storage for the return value
244         movl  24(%ebp),%ecx
245         movb  %al,0(%ecx)
246         jmp   sc_epilogue
247
248 sc_retstruct2b:
249         cmpl  $FFI_TYPE_SINT16,%ecx
250         jne   sc_retstruct
251         # Load %ecx with the pointer to storage for the return value
252         movl  24(%ebp),%ecx
253         movw  %ax,0(%ecx)
254         jmp   sc_epilogue
255
256 sc_retstruct:
257         # Nothing to do!
258
259 sc_noretval:
260 sc_epilogue:
261         movl %ebp,%esp
262         popl %ebp
263         ret
264 .ffi_call_STDCALL_end:
265 .LFE2:
266
267         .globl _ffi_closure_STDCALL
268 _ffi_closure_STDCALL:
269         pushl   %ebp
270         movl    %esp, %ebp
271         subl    $40, %esp
272         leal    -24(%ebp), %edx
273         movl    %edx, -12(%ebp) /* resp */
274         leal    12(%ebp), %edx  /* account for stub return address on stack */
275         movl    %edx, 4(%esp)   /* args */
276         leal    -12(%ebp), %edx
277         movl    %edx, (%esp)    /* &resp */
278         call    _ffi_closure_SYSV_inner
279         movl    -12(%ebp), %ecx
280         jmp     .Lcls_return_result
281 .ffi_closure_STDCALL_end:
282
283         # This assumes we are using gas.
284         .balign 16
285         .globl  _ffi_closure_SYSV
286         .def    _ffi_closure_SYSV;      .scl    2;      .type   32;     .endef
287 _ffi_closure_SYSV:
288 .LFB3:
289         pushl   %ebp
290 .LCFI4:
291         movl    %esp, %ebp
292 .LCFI5:
293         subl    $40, %esp
294         leal    -24(%ebp), %edx
295         movl    %edx, -12(%ebp) /* resp */
296         leal    8(%ebp), %edx
297         movl    %edx, 4(%esp)   /* args = __builtin_dwarf_cfa () */
298         leal    -12(%ebp), %edx
299         movl    %edx, (%esp)    /* &resp */
300         call    _ffi_closure_SYSV_inner
301         movl    -12(%ebp), %ecx
302 .Lcls_return_result:
303         cmpl    $FFI_TYPE_INT, %eax
304         je      .Lcls_retint
305         cmpl    $FFI_TYPE_FLOAT, %eax
306         je      .Lcls_retfloat
307         cmpl    $FFI_TYPE_DOUBLE, %eax
308         je      .Lcls_retdouble
309         cmpl    $FFI_TYPE_LONGDOUBLE, %eax
310         je      .Lcls_retldouble
311         cmpl    $FFI_TYPE_SINT64, %eax
312         je      .Lcls_retllong
313         cmpl    $FFI_TYPE_SINT8, %eax   /* 1-byte struct */
314         je      .Lcls_retstruct1
315         cmpl    $FFI_TYPE_SINT16, %eax  /* 2-bytes struct */
316         je      .Lcls_retstruct2
317 .Lcls_epilogue:
318         movl    %ebp, %esp
319         popl    %ebp
320         ret
321 .Lcls_retint:
322         movl    (%ecx), %eax
323         jmp     .Lcls_epilogue
324 .Lcls_retfloat:
325         flds    (%ecx)
326         jmp     .Lcls_epilogue
327 .Lcls_retdouble:
328         fldl    (%ecx)
329         jmp     .Lcls_epilogue
330 .Lcls_retldouble:
331         fldt    (%ecx)
332         jmp     .Lcls_epilogue
333 .Lcls_retllong:
334         movl    (%ecx), %eax
335         movl    4(%ecx), %edx
336         jmp     .Lcls_epilogue
337 .Lcls_retstruct1:
338         movsbl  (%ecx), %eax
339         jmp     .Lcls_epilogue
340 .Lcls_retstruct2:
341         movswl  (%ecx), %eax
342         jmp     .Lcls_epilogue
343 .ffi_closure_SYSV_end:
344 .LFE3:
345
346 #if !FFI_NO_RAW_API
347
348 #define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
349 #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
350 #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
351 #define CIF_FLAGS_OFFSET 20
352
353         # This assumes we are using gas.
354         .balign 16
355         .globl  _ffi_closure_raw_SYSV
356         .def    _ffi_closure_raw_SYSV;  .scl    2;      .type   32;     .endef
357 _ffi_closure_raw_SYSV:
358 .LFB4:
359         pushl   %ebp
360 .LCFI6:
361         movl    %esp, %ebp
362 .LCFI7:
363         pushl   %esi
364 .LCFI8:
365         subl    $36, %esp
366         movl    RAW_CLOSURE_CIF_OFFSET(%eax), %esi       /* closure->cif */
367         movl    RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
368         movl    %edx, 12(%esp)  /* user_data */
369         leal    8(%ebp), %edx   /* __builtin_dwarf_cfa () */
370         movl    %edx, 8(%esp)   /* raw_args */
371         leal    -24(%ebp), %edx
372         movl    %edx, 4(%esp)   /* &res */
373         movl    %esi, (%esp)    /* cif */
374         call    *RAW_CLOSURE_FUN_OFFSET(%eax)            /* closure->fun */
375         movl    CIF_FLAGS_OFFSET(%esi), %eax             /* rtype */
376         cmpl    $FFI_TYPE_INT, %eax
377         je      .Lrcls_retint
378         cmpl    $FFI_TYPE_FLOAT, %eax
379         je      .Lrcls_retfloat
380         cmpl    $FFI_TYPE_DOUBLE, %eax
381         je      .Lrcls_retdouble
382         cmpl    $FFI_TYPE_LONGDOUBLE, %eax
383         je      .Lrcls_retldouble
384         cmpl    $FFI_TYPE_SINT64, %eax
385         je      .Lrcls_retllong
386 .Lrcls_epilogue:
387         addl    $36, %esp
388         popl    %esi
389         popl    %ebp
390         ret
391 .Lrcls_retint:
392         movl    -24(%ebp), %eax
393         jmp     .Lrcls_epilogue
394 .Lrcls_retfloat:
395         flds    -24(%ebp)
396         jmp     .Lrcls_epilogue
397 .Lrcls_retdouble:
398         fldl    -24(%ebp)
399         jmp     .Lrcls_epilogue
400 .Lrcls_retldouble:
401         fldt    -24(%ebp)
402         jmp     .Lrcls_epilogue
403 .Lrcls_retllong:
404         movl    -24(%ebp), %eax
405         movl    -20(%ebp), %edx
406         jmp     .Lrcls_epilogue
407 .ffi_closure_raw_SYSV_end:
408 .LFE4:
409
410 #endif /* !FFI_NO_RAW_API */
411
412
413         .section        .eh_frame,"w"
414 .Lframe1:
415 .LSCIE1:
416         .long   .LECIE1-.LASCIE1  /* Length of Common Information Entry */
417 .LASCIE1:
418         .long   0x0     /* CIE Identifier Tag */
419         .byte   0x1     /* CIE Version */
420 #ifdef __PIC__
421         .ascii "zR\0"   /* CIE Augmentation */
422 #else
423         .ascii "\0"     /* CIE Augmentation */
424 #endif
425         .byte   0x1     /* .uleb128 0x1; CIE Code Alignment Factor */
426         .byte   0x7c    /* .sleb128 -4; CIE Data Alignment Factor */
427         .byte   0x8     /* CIE RA Column */
428 #ifdef __PIC__
429         .byte   0x1     /* .uleb128 0x1; Augmentation size */
430         .byte   0x1b    /* FDE Encoding (pcrel sdata4) */
431 #endif
432         .byte   0xc     /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
433         .byte   0x4     /* .uleb128 0x4 */
434         .byte   0x4     /* .uleb128 0x4 */
435         .byte   0x88    /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
436         .byte   0x1     /* .uleb128 0x1 */
437         .align 4
438 .LECIE1:
439
440 .LSFDE1:
441         .long   .LEFDE1-.LASFDE1        /* FDE Length */
442 .LASFDE1:
443         .long   .LASFDE1-.Lframe1       /* FDE CIE offset */
444 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
445         .long   .LFB1-. /* FDE initial location */
446 #else
447         .long   .LFB1
448 #endif
449         .long   .LFE1-.LFB1     /* FDE address range */
450 #ifdef __PIC__
451         .byte   0x0     /* .uleb128 0x0; Augmentation size */
452 #endif
453         /* DW_CFA_xxx CFI instructions go here.  */
454
455         .byte   0x4     /* DW_CFA_advance_loc4 */
456         .long   .LCFI0-.LFB1
457         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
458         .byte   0x8     /* .uleb128 0x8 */
459         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
460         .byte   0x2     /* .uleb128 0x2 */
461
462         .byte   0x4     /* DW_CFA_advance_loc4 */
463         .long   .LCFI1-.LCFI0
464         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
465         .byte   0x5     /* .uleb128 0x5 */
466
467         /* End of DW_CFA_xxx CFI instructions.  */
468         .align 4
469 .LEFDE1:
470
471
472 .LSFDE2:
473         .long   .LEFDE2-.LASFDE2        /* FDE Length */
474 .LASFDE2:
475         .long   .LASFDE2-.Lframe1       /* FDE CIE offset */
476 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
477         .long   .LFB2-. /* FDE initial location */
478 #else
479         .long   .LFB2
480 #endif
481         .long   .LFE2-.LFB2     /* FDE address range */
482 #ifdef __PIC__
483         .byte   0x0     /* .uleb128 0x0; Augmentation size */
484 #endif
485         /* DW_CFA_xxx CFI instructions go here.  */
486
487         .byte   0x4     /* DW_CFA_advance_loc4 */
488         .long   .LCFI2-.LFB2
489         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
490         .byte   0x8     /* .uleb128 0x8 */
491         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
492         .byte   0x2     /* .uleb128 0x2 */
493
494         .byte   0x4     /* DW_CFA_advance_loc4 */
495         .long   .LCFI3-.LCFI2
496         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
497         .byte   0x5     /* .uleb128 0x5 */
498
499         /* End of DW_CFA_xxx CFI instructions.  */
500         .align 4
501 .LEFDE2:
502
503
504 .LSFDE3:
505         .long   .LEFDE3-.LASFDE3        /* FDE Length */
506 .LASFDE3:
507         .long   .LASFDE3-.Lframe1       /* FDE CIE offset */
508 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
509         .long   .LFB3-. /* FDE initial location */
510 #else
511         .long   .LFB3
512 #endif
513         .long   .LFE3-.LFB3     /* FDE address range */
514 #ifdef __PIC__
515         .byte   0x0     /* .uleb128 0x0; Augmentation size */
516 #endif
517         /* DW_CFA_xxx CFI instructions go here.  */
518
519         .byte   0x4     /* DW_CFA_advance_loc4 */
520         .long   .LCFI4-.LFB3
521         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
522         .byte   0x8     /* .uleb128 0x8 */
523         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
524         .byte   0x2     /* .uleb128 0x2 */
525
526         .byte   0x4     /* DW_CFA_advance_loc4 */
527         .long   .LCFI5-.LCFI4
528         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
529         .byte   0x5     /* .uleb128 0x5 */
530
531         /* End of DW_CFA_xxx CFI instructions.  */
532         .align 4
533 .LEFDE3:
534
535 #if !FFI_NO_RAW_API
536
537 .LSFDE4:
538         .long   .LEFDE4-.LASFDE4        /* FDE Length */
539 .LASFDE4:
540         .long   .LASFDE4-.Lframe1       /* FDE CIE offset */
541 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
542         .long   .LFB4-. /* FDE initial location */
543 #else
544         .long   .LFB4
545 #endif
546         .long   .LFE4-.LFB4     /* FDE address range */
547 #ifdef __PIC__
548         .byte   0x0     /* .uleb128 0x0; Augmentation size */
549 #endif
550         /* DW_CFA_xxx CFI instructions go here.  */
551
552         .byte   0x4     /* DW_CFA_advance_loc4 */
553         .long   .LCFI6-.LFB4
554         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
555         .byte   0x8     /* .uleb128 0x8 */
556         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
557         .byte   0x2     /* .uleb128 0x2 */
558
559         .byte   0x4     /* DW_CFA_advance_loc4 */
560         .long   .LCFI7-.LCFI6
561         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
562         .byte   0x5     /* .uleb128 0x5 */
563
564         .byte   0x4     /* DW_CFA_advance_loc4 */
565         .long   .LCFI8-.LCFI7
566         .byte   0x86    /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
567         .byte   0x3     /* .uleb128 0x3 */
568
569         /* End of DW_CFA_xxx CFI instructions.  */
570         .align 4
571 .LEFDE4:
572
573 #endif /* !FFI_NO_RAW_API */