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