e5c93ecf7b95002070aa3dafd79adac9ef0e08b4
[platform/upstream/libffi.git] / 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              Copyright (c) 2009  Daniel Witte
6                         
7  
8    X86 Foreign Function Interface
9  
10    Permission is hereby granted, free of charge, to any person obtaining
11    a copy of this software and associated documentation files (the
12    ``Software''), to deal in the Software without restriction, including
13    without limitation the rights to use, copy, modify, merge, publish,
14    distribute, sublicense, and/or sell copies of the Software, and to
15    permit persons to whom the Software is furnished to do so, subject to
16    the following conditions:
17  
18    The above copyright notice and this permission notice shall be included
19    in all copies or substantial portions of the Software.
20  
21    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28    DEALINGS IN THE SOFTWARE.
29    -----------------------------------------------------------------------
30    */
31  
32 #define LIBFFI_ASM
33 #include <fficonfig.h>
34 #include <ffi.h>
35
36 #ifdef _MSC_VER
37
38 .386
39 .MODEL FLAT, C
40
41 EXTRN ffi_closure_SYSV_inner:NEAR
42
43 _TEXT SEGMENT
44
45 ffi_call_win32 PROC NEAR,
46     ffi_prep_args : NEAR PTR DWORD,
47     ecif          : NEAR PTR DWORD,
48     cif_abi       : DWORD,
49     cif_bytes     : DWORD,
50     cif_flags     : DWORD,
51     rvalue        : NEAR PTR DWORD,
52     fn            : NEAR PTR DWORD
53
54         ;; Make room for all of the new args.
55         mov  ecx, cif_bytes
56         sub  esp, ecx
57
58         mov  eax, esp
59
60         ;; Place all of the ffi_prep_args in position
61         push ecif
62         push eax
63         call ffi_prep_args
64
65         ;; Return stack to previous state and call the function
66         add  esp, 8
67
68         ;; Handle thiscall and fastcall
69         cmp cif_abi, 3 ;; FFI_THISCALL
70         jz do_thiscall
71         cmp cif_abi, 4 ;; FFI_FASTCALL
72         jnz do_stdcall
73         mov ecx, DWORD PTR [esp]
74         mov edx, DWORD PTR [esp+4]
75         add esp, 8
76         jmp do_stdcall
77 do_thiscall:
78         mov ecx, DWORD PTR [esp]
79         add esp, 4
80 do_stdcall:
81         call fn
82
83         ;; cdecl:   we restore esp in the epilogue, so there's no need to
84         ;;          remove the space we pushed for the args.
85         ;; stdcall: the callee has already cleaned the stack.
86
87         ;; Load ecx with the return type code
88         mov  ecx, cif_flags
89
90         ;; If the return value pointer is NULL, assume no return value.
91         cmp  rvalue, 0
92         jne  ca_jumptable
93
94         ;; Even if there is no space for the return value, we are
95         ;; obliged to handle floating-point values.
96         cmp  ecx, FFI_TYPE_FLOAT
97         jne  ca_epilogue
98         fstp st(0)
99
100         jmp  ca_epilogue
101
102 ca_jumptable:
103         jmp  [ca_jumpdata + 4 * ecx]
104 ca_jumpdata:
105         ;; Do not insert anything here between label and jump table.
106         dd offset ca_epilogue       ;; FFI_TYPE_VOID
107         dd offset ca_retint         ;; FFI_TYPE_INT
108         dd offset ca_retfloat       ;; FFI_TYPE_FLOAT
109         dd offset ca_retdouble      ;; FFI_TYPE_DOUBLE
110         dd offset ca_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
111         dd offset ca_retint8        ;; FFI_TYPE_UINT8
112         dd offset ca_retint8        ;; FFI_TYPE_SINT8
113         dd offset ca_retint16       ;; FFI_TYPE_UINT16
114         dd offset ca_retint16       ;; FFI_TYPE_SINT16
115         dd offset ca_retint         ;; FFI_TYPE_UINT32
116         dd offset ca_retint         ;; FFI_TYPE_SINT32
117         dd offset ca_retint64       ;; FFI_TYPE_UINT64
118         dd offset ca_retint64       ;; FFI_TYPE_SINT64
119         dd offset ca_epilogue       ;; FFI_TYPE_STRUCT
120         dd offset ca_retint         ;; FFI_TYPE_POINTER
121         dd offset ca_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
122         dd offset ca_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
123         dd offset ca_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
124
125 ca_retint8:
126         ;; Load %ecx with the pointer to storage for the return value
127         mov   ecx, rvalue
128         mov   [ecx + 0], al
129         jmp   ca_epilogue
130
131 ca_retint16:
132         ;; Load %ecx with the pointer to storage for the return value
133         mov   ecx, rvalue
134         mov   [ecx + 0], ax
135         jmp   ca_epilogue
136
137 ca_retint:
138         ;; Load %ecx with the pointer to storage for the return value
139         mov   ecx, rvalue
140         mov   [ecx + 0], eax
141         jmp   ca_epilogue
142
143 ca_retint64:
144         ;; Load %ecx with the pointer to storage for the return value
145         mov   ecx, rvalue
146         mov   [ecx + 0], eax
147         mov   [ecx + 4], edx
148         jmp   ca_epilogue
149
150 ca_retfloat:
151         ;; Load %ecx with the pointer to storage for the return value
152         mov   ecx, rvalue
153         fstp  DWORD PTR [ecx]
154         jmp   ca_epilogue
155
156 ca_retdouble:
157         ;; Load %ecx with the pointer to storage for the return value
158         mov   ecx, rvalue
159         fstp  QWORD PTR [ecx]
160         jmp   ca_epilogue
161
162 ca_retlongdouble:
163         ;; Load %ecx with the pointer to storage for the return value
164         mov   ecx, rvalue
165         fstp  TBYTE PTR [ecx]
166         jmp   ca_epilogue
167
168 ca_epilogue:
169         ;; Epilogue code is autogenerated.
170         ret
171 ffi_call_win32 ENDP
172
173 ffi_closure_THISCALL PROC NEAR FORCEFRAME
174         push    ebp
175         mov     ebp, esp
176         sub     esp, 40
177         lea     edx, [ebp -24]
178         mov     [ebp - 12], edx /* resp */
179         lea     edx, [ebp + 12]  /* account for stub return address on stack */
180         jmp     stub
181 ffi_closure_THISCALL ENDP
182
183 ffi_closure_SYSV PROC NEAR FORCEFRAME
184     ;; the ffi_closure ctx is passed in eax by the trampoline.
185
186         sub  esp, 40
187         lea  edx, [ebp - 24]
188         mov  [ebp - 12], edx         ;; resp
189         lea  edx, [ebp + 8]
190 stub:
191         mov  [esp + 8], edx          ;; args
192         lea  edx, [ebp - 12]
193         mov  [esp + 4], edx          ;; &resp
194         mov  [esp], eax              ;; closure
195         call ffi_closure_SYSV_inner
196         mov  ecx, [ebp - 12]
197
198 cs_jumptable:
199         jmp  [cs_jumpdata + 4 * eax]
200 cs_jumpdata:
201         ;; Do not insert anything here between the label and jump table.
202         dd offset cs_epilogue       ;; FFI_TYPE_VOID
203         dd offset cs_retint         ;; FFI_TYPE_INT
204         dd offset cs_retfloat       ;; FFI_TYPE_FLOAT
205         dd offset cs_retdouble      ;; FFI_TYPE_DOUBLE
206         dd offset cs_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
207         dd offset cs_retint8        ;; FFI_TYPE_UINT8
208         dd offset cs_retint8        ;; FFI_TYPE_SINT8
209         dd offset cs_retint16       ;; FFI_TYPE_UINT16
210         dd offset cs_retint16       ;; FFI_TYPE_SINT16
211         dd offset cs_retint         ;; FFI_TYPE_UINT32
212         dd offset cs_retint         ;; FFI_TYPE_SINT32
213         dd offset cs_retint64       ;; FFI_TYPE_UINT64
214         dd offset cs_retint64       ;; FFI_TYPE_SINT64
215         dd offset cs_retstruct      ;; FFI_TYPE_STRUCT
216         dd offset cs_retint         ;; FFI_TYPE_POINTER
217         dd offset cs_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
218         dd offset cs_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
219         dd offset cs_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
220
221 cs_retint8:
222         mov   al, [ecx]
223         jmp   cs_epilogue
224
225 cs_retint16:
226         mov   ax, [ecx]
227         jmp   cs_epilogue
228
229 cs_retint:
230         mov   eax, [ecx]
231         jmp   cs_epilogue
232
233 cs_retint64:
234         mov   eax, [ecx + 0]
235         mov   edx, [ecx + 4]
236         jmp   cs_epilogue
237
238 cs_retfloat:
239         fld   DWORD PTR [ecx]
240         jmp   cs_epilogue
241
242 cs_retdouble:
243         fld   QWORD PTR [ecx]
244         jmp   cs_epilogue
245
246 cs_retlongdouble:
247         fld   TBYTE PTR [ecx]
248         jmp   cs_epilogue
249
250 cs_retstruct:
251         ;; Caller expects us to pop struct return value pointer hidden arg.
252         ;; Epilogue code is autogenerated.
253         ret     4
254
255 cs_epilogue:
256         ;; Epilogue code is autogenerated.
257         ret
258 ffi_closure_SYSV ENDP
259
260 #if !FFI_NO_RAW_API
261
262 #define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
263 #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
264 #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
265 #define CIF_FLAGS_OFFSET 20
266
267 ffi_closure_raw_SYSV PROC NEAR USES esi
268     ;; the ffi_closure ctx is passed in eax by the trampoline.
269
270         sub  esp, 40
271         mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
272         mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
273         mov  [esp + 12], edx                            ;; user_data
274         lea  edx, [ebp + 8]
275         mov  [esp + 8], edx                             ;; raw_args
276         lea  edx, [ebp - 24]
277         mov  [esp + 4], edx                             ;; &res
278         mov  [esp], esi                                 ;; cif
279         call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET]   ;; closure->fun
280         mov  eax, [esi + CIF_FLAGS_OFFSET]              ;; cif->flags
281         lea  ecx, [ebp - 24]
282
283 cr_jumptable:
284         jmp  [cr_jumpdata + 4 * eax]
285 cr_jumpdata:
286         ;; Do not insert anything here between the label and jump table.
287         dd offset cr_epilogue       ;; FFI_TYPE_VOID
288         dd offset cr_retint         ;; FFI_TYPE_INT
289         dd offset cr_retfloat       ;; FFI_TYPE_FLOAT
290         dd offset cr_retdouble      ;; FFI_TYPE_DOUBLE
291         dd offset cr_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
292         dd offset cr_retint8        ;; FFI_TYPE_UINT8
293         dd offset cr_retint8        ;; FFI_TYPE_SINT8
294         dd offset cr_retint16       ;; FFI_TYPE_UINT16
295         dd offset cr_retint16       ;; FFI_TYPE_SINT16
296         dd offset cr_retint         ;; FFI_TYPE_UINT32
297         dd offset cr_retint         ;; FFI_TYPE_SINT32
298         dd offset cr_retint64       ;; FFI_TYPE_UINT64
299         dd offset cr_retint64       ;; FFI_TYPE_SINT64
300         dd offset cr_epilogue       ;; FFI_TYPE_STRUCT
301         dd offset cr_retint         ;; FFI_TYPE_POINTER
302         dd offset cr_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
303         dd offset cr_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
304         dd offset cr_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
305
306 cr_retint8:
307         mov   al, [ecx]
308         jmp   cr_epilogue
309
310 cr_retint16:
311         mov   ax, [ecx]
312         jmp   cr_epilogue
313
314 cr_retint:
315         mov   eax, [ecx]
316         jmp   cr_epilogue
317
318 cr_retint64:
319         mov   eax, [ecx + 0]
320         mov   edx, [ecx + 4]
321         jmp   cr_epilogue
322
323 cr_retfloat:
324         fld   DWORD PTR [ecx]
325         jmp   cr_epilogue
326
327 cr_retdouble:
328         fld   QWORD PTR [ecx]
329         jmp   cr_epilogue
330
331 cr_retlongdouble:
332         fld   TBYTE PTR [ecx]
333         jmp   cr_epilogue
334
335 cr_epilogue:
336         ;; Epilogue code is autogenerated.
337         ret
338 ffi_closure_raw_SYSV ENDP
339
340 #endif /* !FFI_NO_RAW_API */
341
342 ffi_closure_STDCALL PROC NEAR FORCEFRAME
343     ;; the ffi_closure ctx is passed in eax by the trampoline.
344
345         sub  esp, 40
346         lea  edx, [ebp - 24]
347         mov  [ebp - 12], edx         ;; resp
348         lea  edx, [ebp + 12]         ;; account for stub return address on stack
349         mov  [esp + 8], edx          ;; args
350         lea  edx, [ebp - 12]
351         mov  [esp + 4], edx          ;; &resp
352         mov  [esp], eax              ;; closure
353         call ffi_closure_SYSV_inner
354         mov  ecx, [ebp - 12]
355
356 cd_jumptable:
357         jmp  [cd_jumpdata + 4 * eax]
358 cd_jumpdata:
359         ;; Do not insert anything here between the label and jump table.
360         dd offset cd_epilogue       ;; FFI_TYPE_VOID
361         dd offset cd_retint         ;; FFI_TYPE_INT
362         dd offset cd_retfloat       ;; FFI_TYPE_FLOAT
363         dd offset cd_retdouble      ;; FFI_TYPE_DOUBLE
364         dd offset cd_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
365         dd offset cd_retint8        ;; FFI_TYPE_UINT8
366         dd offset cd_retint8        ;; FFI_TYPE_SINT8
367         dd offset cd_retint16       ;; FFI_TYPE_UINT16
368         dd offset cd_retint16       ;; FFI_TYPE_SINT16
369         dd offset cd_retint         ;; FFI_TYPE_UINT32
370         dd offset cd_retint         ;; FFI_TYPE_SINT32
371         dd offset cd_retint64       ;; FFI_TYPE_UINT64
372         dd offset cd_retint64       ;; FFI_TYPE_SINT64
373         dd offset cd_epilogue       ;; FFI_TYPE_STRUCT
374         dd offset cd_retint         ;; FFI_TYPE_POINTER
375         dd offset cd_retint8        ;; FFI_TYPE_SMALL_STRUCT_1B
376         dd offset cd_retint16       ;; FFI_TYPE_SMALL_STRUCT_2B
377         dd offset cd_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
378
379 cd_retint8:
380         mov   al, [ecx]
381         jmp   cd_epilogue
382
383 cd_retint16:
384         mov   ax, [ecx]
385         jmp   cd_epilogue
386
387 cd_retint:
388         mov   eax, [ecx]
389         jmp   cd_epilogue
390
391 cd_retint64:
392         mov   eax, [ecx + 0]
393         mov   edx, [ecx + 4]
394         jmp   cd_epilogue
395
396 cd_retfloat:
397         fld   DWORD PTR [ecx]
398         jmp   cd_epilogue
399
400 cd_retdouble:
401         fld   QWORD PTR [ecx]
402         jmp   cd_epilogue
403
404 cd_retlongdouble:
405         fld   TBYTE PTR [ecx]
406         jmp   cd_epilogue
407
408 cd_epilogue:
409         ;; Epilogue code is autogenerated.
410         ret
411 ffi_closure_STDCALL ENDP
412
413 _TEXT ENDS
414 END
415
416 #else
417
418         .text
419  
420         # This assumes we are using gas.
421         .balign 16
422         .globl  _ffi_call_win32
423 #ifndef __OS2__
424         .def    _ffi_call_win32;        .scl    2;      .type   32;     .endef
425 #endif
426 _ffi_call_win32:
427 .LFB1:
428         pushl %ebp
429 .LCFI0:
430         movl  %esp,%ebp
431 .LCFI1:
432         # Make room for all of the new args.
433         movl  20(%ebp),%ecx                                                     
434         subl  %ecx,%esp
435  
436         movl  %esp,%eax
437  
438         # Place all of the ffi_prep_args in position
439         pushl 12(%ebp)
440         pushl %eax
441         call  *8(%ebp)
442  
443         # Return stack to previous state and call the function
444         addl  $8,%esp
445
446         # Handle fastcall and thiscall
447         cmpl $3, 16(%ebp)  # FFI_THISCALL
448         jz .do_thiscall
449         cmpl $4, 16(%ebp) # FFI_FASTCALL
450         jnz .do_fncall
451         movl (%esp), %ecx
452         movl 4(%esp), %edx
453         addl $8, %esp
454         jmp .do_fncall
455 .do_thiscall:
456         movl (%esp), %ecx
457         addl $4, %esp
458
459 .do_fncall:
460          
461         # FIXME: Align the stack to a 128-bit boundary to avoid
462         # potential performance hits.
463
464         call  *32(%ebp)
465  
466         # stdcall functions pop arguments off the stack themselves
467
468         # Load %ecx with the return type code
469         movl  24(%ebp),%ecx
470  
471         # If the return value pointer is NULL, assume no return value.
472         cmpl  $0,28(%ebp)
473         jne   0f
474  
475         # Even if there is no space for the return value, we are
476         # obliged to handle floating-point values.
477         cmpl  $FFI_TYPE_FLOAT,%ecx
478         jne   .Lnoretval
479         fstp  %st(0)
480  
481         jmp   .Lepilogue
482
483 0:
484         call    1f
485         # Do not insert anything here between the call and the jump table.
486 .Lstore_table:
487         .long   .Lnoretval              /* FFI_TYPE_VOID */
488         .long   .Lretint                /* FFI_TYPE_INT */
489         .long   .Lretfloat              /* FFI_TYPE_FLOAT */
490         .long   .Lretdouble             /* FFI_TYPE_DOUBLE */
491         .long   .Lretlongdouble         /* FFI_TYPE_LONGDOUBLE */
492         .long   .Lretuint8              /* FFI_TYPE_UINT8 */
493         .long   .Lretsint8              /* FFI_TYPE_SINT8 */
494         .long   .Lretuint16             /* FFI_TYPE_UINT16 */
495         .long   .Lretsint16             /* FFI_TYPE_SINT16 */
496         .long   .Lretint                /* FFI_TYPE_UINT32 */
497         .long   .Lretint                /* FFI_TYPE_SINT32 */
498         .long   .Lretint64              /* FFI_TYPE_UINT64 */
499         .long   .Lretint64              /* FFI_TYPE_SINT64 */
500         .long   .Lretstruct             /* FFI_TYPE_STRUCT */
501         .long   .Lretint                /* FFI_TYPE_POINTER */
502         .long   .Lretstruct1b           /* FFI_TYPE_SMALL_STRUCT_1B */
503         .long   .Lretstruct2b           /* FFI_TYPE_SMALL_STRUCT_2B */
504         .long   .Lretstruct4b           /* FFI_TYPE_SMALL_STRUCT_4B */
505 1:
506         add     %ecx, %ecx
507         add     %ecx, %ecx
508         add     (%esp),%ecx
509         add     $4, %esp
510         jmp     *(%ecx)
511
512         /* Sign/zero extend as appropriate.  */
513 .Lretsint8:
514         movsbl  %al, %eax
515         jmp     .Lretint
516
517 .Lretsint16:
518         movswl  %ax, %eax
519         jmp     .Lretint
520
521 .Lretuint8:
522         movzbl  %al, %eax
523         jmp     .Lretint
524
525 .Lretuint16:
526         movzwl  %ax, %eax
527         jmp     .Lretint
528
529 .Lretint:
530         # Load %ecx with the pointer to storage for the return value
531         movl  28(%ebp),%ecx
532         movl  %eax,0(%ecx)
533         jmp   .Lepilogue
534  
535 .Lretfloat:
536          # Load %ecx with the pointer to storage for the return value
537         movl  28(%ebp),%ecx
538         fstps (%ecx)
539         jmp   .Lepilogue
540  
541 .Lretdouble:
542         # Load %ecx with the pointer to storage for the return value
543         movl  28(%ebp),%ecx
544         fstpl (%ecx)
545         jmp   .Lepilogue
546  
547 .Lretlongdouble:
548         # Load %ecx with the pointer to storage for the return value
549         movl  28(%ebp),%ecx
550         fstpt (%ecx)
551         jmp   .Lepilogue
552  
553 .Lretint64:
554         # Load %ecx with the pointer to storage for the return value
555         movl  28(%ebp),%ecx
556         movl  %eax,0(%ecx)
557         movl  %edx,4(%ecx)
558         jmp   .Lepilogue
559
560 .Lretstruct1b:
561         # Load %ecx with the pointer to storage for the return value
562         movl  28(%ebp),%ecx
563         movb  %al,0(%ecx)
564         jmp   .Lepilogue
565  
566 .Lretstruct2b:
567         # Load %ecx with the pointer to storage for the return value
568         movl  28(%ebp),%ecx
569         movw  %ax,0(%ecx)
570         jmp   .Lepilogue
571
572 .Lretstruct4b:
573         # Load %ecx with the pointer to storage for the return value
574         movl  28(%ebp),%ecx
575         movl  %eax,0(%ecx)
576         jmp   .Lepilogue
577
578 .Lretstruct:
579         # Nothing to do!
580  
581 .Lnoretval:
582 .Lepilogue:
583         movl %ebp,%esp
584         popl %ebp
585         ret
586 .ffi_call_win32_end:
587         .balign 16
588         .globl  _ffi_closure_THISCALL
589 #ifndef __OS2__
590         .def    _ffi_closure_THISCALL;  .scl    2;      .type   32;     .endef
591 #endif
592 _ffi_closure_THISCALL:
593         pushl   %ebp
594         movl    %esp, %ebp
595         subl    $40, %esp
596         leal    -24(%ebp), %edx
597         movl    %edx, -12(%ebp) /* resp */
598         leal    12(%ebp), %edx  /* account for stub return address on stack */
599         jmp     .stub
600 .LFE1:
601
602         # This assumes we are using gas.
603         .balign 16
604         .globl  _ffi_closure_SYSV
605 #ifndef __OS2__
606         .def    _ffi_closure_SYSV;      .scl    2;      .type   32;     .endef
607 #endif
608 _ffi_closure_SYSV:
609 .LFB3:
610         pushl   %ebp
611 .LCFI4:
612         movl    %esp, %ebp
613 .LCFI5:
614         subl    $40, %esp
615         leal    -24(%ebp), %edx
616         movl    %edx, -12(%ebp) /* resp */
617         leal    8(%ebp), %edx
618 .stub:
619         movl    %edx, 4(%esp)   /* args = __builtin_dwarf_cfa () */
620         leal    -12(%ebp), %edx
621         movl    %edx, (%esp)    /* &resp */
622         call    _ffi_closure_SYSV_inner
623         movl    -12(%ebp), %ecx
624
625 0:
626         call    1f
627         # Do not insert anything here between the call and the jump table.
628 .Lcls_store_table:
629         .long   .Lcls_noretval          /* FFI_TYPE_VOID */
630         .long   .Lcls_retint            /* FFI_TYPE_INT */
631         .long   .Lcls_retfloat          /* FFI_TYPE_FLOAT */
632         .long   .Lcls_retdouble         /* FFI_TYPE_DOUBLE */
633         .long   .Lcls_retldouble        /* FFI_TYPE_LONGDOUBLE */
634         .long   .Lcls_retuint8          /* FFI_TYPE_UINT8 */
635         .long   .Lcls_retsint8          /* FFI_TYPE_SINT8 */
636         .long   .Lcls_retuint16         /* FFI_TYPE_UINT16 */
637         .long   .Lcls_retsint16         /* FFI_TYPE_SINT16 */
638         .long   .Lcls_retint            /* FFI_TYPE_UINT32 */
639         .long   .Lcls_retint            /* FFI_TYPE_SINT32 */
640         .long   .Lcls_retllong          /* FFI_TYPE_UINT64 */
641         .long   .Lcls_retllong          /* FFI_TYPE_SINT64 */
642         .long   .Lcls_retstruct         /* FFI_TYPE_STRUCT */
643         .long   .Lcls_retint            /* FFI_TYPE_POINTER */
644         .long   .Lcls_retstruct1        /* FFI_TYPE_SMALL_STRUCT_1B */
645         .long   .Lcls_retstruct2        /* FFI_TYPE_SMALL_STRUCT_2B */
646         .long   .Lcls_retstruct4        /* FFI_TYPE_SMALL_STRUCT_4B */
647
648 1:
649         add     %eax, %eax
650         add     %eax, %eax
651         add     (%esp),%eax
652         add     $4, %esp
653         jmp     *(%eax)
654
655         /* Sign/zero extend as appropriate.  */
656 .Lcls_retsint8:
657         movsbl  (%ecx), %eax
658         jmp     .Lcls_epilogue
659
660 .Lcls_retsint16:
661         movswl  (%ecx), %eax
662         jmp     .Lcls_epilogue
663
664 .Lcls_retuint8:
665         movzbl  (%ecx), %eax
666         jmp     .Lcls_epilogue
667
668 .Lcls_retuint16:
669         movzwl  (%ecx), %eax
670         jmp     .Lcls_epilogue
671
672 .Lcls_retint:
673         movl    (%ecx), %eax
674         jmp     .Lcls_epilogue
675
676 .Lcls_retfloat:
677         flds    (%ecx)
678         jmp     .Lcls_epilogue
679
680 .Lcls_retdouble:
681         fldl    (%ecx)
682         jmp     .Lcls_epilogue
683
684 .Lcls_retldouble:
685         fldt    (%ecx)
686         jmp     .Lcls_epilogue
687
688 .Lcls_retllong:
689         movl    (%ecx), %eax
690         movl    4(%ecx), %edx
691         jmp     .Lcls_epilogue
692
693 .Lcls_retstruct1:
694         movsbl  (%ecx), %eax
695         jmp     .Lcls_epilogue
696
697 .Lcls_retstruct2:
698         movswl  (%ecx), %eax
699         jmp     .Lcls_epilogue
700
701 .Lcls_retstruct4:
702         movl    (%ecx), %eax
703         jmp     .Lcls_epilogue
704
705 .Lcls_retstruct:
706         # Caller expects us to pop struct return value pointer hidden arg.
707         movl    %ebp, %esp
708         popl    %ebp
709         ret     $0x4
710
711 .Lcls_noretval:
712 .Lcls_epilogue:
713         movl    %ebp, %esp
714         popl    %ebp
715         ret
716 .ffi_closure_SYSV_end:
717 .LFE3:
718
719 #if !FFI_NO_RAW_API
720
721 #define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
722 #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
723 #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
724 #define CIF_FLAGS_OFFSET 20
725
726         # This assumes we are using gas.
727         .balign 16
728         .globl  _ffi_closure_raw_SYSV
729 #ifndef __OS2__
730         .def    _ffi_closure_raw_SYSV;  .scl    2;      .type   32;     .endef
731 #endif
732 _ffi_closure_raw_SYSV:
733 .LFB4:
734         pushl   %ebp
735 .LCFI6:
736         movl    %esp, %ebp
737 .LCFI7:
738         pushl   %esi
739 .LCFI8:
740         subl    $36, %esp
741         movl    RAW_CLOSURE_CIF_OFFSET(%eax), %esi       /* closure->cif */
742         movl    RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
743         movl    %edx, 12(%esp)  /* user_data */
744         leal    8(%ebp), %edx   /* __builtin_dwarf_cfa () */
745         movl    %edx, 8(%esp)   /* raw_args */
746         leal    -24(%ebp), %edx
747         movl    %edx, 4(%esp)   /* &res */
748         movl    %esi, (%esp)    /* cif */
749         call    *RAW_CLOSURE_FUN_OFFSET(%eax)            /* closure->fun */
750         movl    CIF_FLAGS_OFFSET(%esi), %eax             /* rtype */
751 0:
752         call    1f
753         # Do not insert anything here between the call and the jump table.
754 .Lrcls_store_table:
755         .long   .Lrcls_noretval         /* FFI_TYPE_VOID */
756         .long   .Lrcls_retint           /* FFI_TYPE_INT */
757         .long   .Lrcls_retfloat         /* FFI_TYPE_FLOAT */
758         .long   .Lrcls_retdouble        /* FFI_TYPE_DOUBLE */
759         .long   .Lrcls_retldouble       /* FFI_TYPE_LONGDOUBLE */
760         .long   .Lrcls_retuint8         /* FFI_TYPE_UINT8 */
761         .long   .Lrcls_retsint8         /* FFI_TYPE_SINT8 */
762         .long   .Lrcls_retuint16        /* FFI_TYPE_UINT16 */
763         .long   .Lrcls_retsint16        /* FFI_TYPE_SINT16 */
764         .long   .Lrcls_retint           /* FFI_TYPE_UINT32 */
765         .long   .Lrcls_retint           /* FFI_TYPE_SINT32 */
766         .long   .Lrcls_retllong         /* FFI_TYPE_UINT64 */
767         .long   .Lrcls_retllong         /* FFI_TYPE_SINT64 */
768         .long   .Lrcls_retstruct        /* FFI_TYPE_STRUCT */
769         .long   .Lrcls_retint           /* FFI_TYPE_POINTER */
770         .long   .Lrcls_retstruct1       /* FFI_TYPE_SMALL_STRUCT_1B */
771         .long   .Lrcls_retstruct2       /* FFI_TYPE_SMALL_STRUCT_2B */
772         .long   .Lrcls_retstruct4       /* FFI_TYPE_SMALL_STRUCT_4B */
773 1:
774         add     %eax, %eax
775         add     %eax, %eax
776         add     (%esp),%eax
777         add     $4, %esp
778         jmp     *(%eax)
779
780         /* Sign/zero extend as appropriate.  */
781 .Lrcls_retsint8:
782         movsbl  -24(%ebp), %eax
783         jmp     .Lrcls_epilogue
784
785 .Lrcls_retsint16:
786         movswl  -24(%ebp), %eax
787         jmp     .Lrcls_epilogue
788
789 .Lrcls_retuint8:
790         movzbl  -24(%ebp), %eax
791         jmp     .Lrcls_epilogue
792
793 .Lrcls_retuint16:
794         movzwl  -24(%ebp), %eax
795         jmp     .Lrcls_epilogue
796
797 .Lrcls_retint:
798         movl    -24(%ebp), %eax
799         jmp     .Lrcls_epilogue
800
801 .Lrcls_retfloat:
802         flds    -24(%ebp)
803         jmp     .Lrcls_epilogue
804
805 .Lrcls_retdouble:
806         fldl    -24(%ebp)
807         jmp     .Lrcls_epilogue
808
809 .Lrcls_retldouble:
810         fldt    -24(%ebp)
811         jmp     .Lrcls_epilogue
812
813 .Lrcls_retllong:
814         movl    -24(%ebp), %eax
815         movl    -20(%ebp), %edx
816         jmp     .Lrcls_epilogue
817
818 .Lrcls_retstruct1:
819         movsbl  -24(%ebp), %eax
820         jmp     .Lrcls_epilogue
821
822 .Lrcls_retstruct2:
823         movswl  -24(%ebp), %eax
824         jmp     .Lrcls_epilogue
825
826 .Lrcls_retstruct4:
827         movl    -24(%ebp), %eax
828         jmp     .Lrcls_epilogue
829
830 .Lrcls_retstruct:
831         # Nothing to do!
832
833 .Lrcls_noretval:
834 .Lrcls_epilogue:
835         addl    $36, %esp
836         popl    %esi
837         popl    %ebp
838         ret
839 .ffi_closure_raw_SYSV_end:
840 .LFE4:
841
842 #endif /* !FFI_NO_RAW_API */
843
844         # This assumes we are using gas.
845         .balign 16
846         .globl  _ffi_closure_STDCALL
847 #ifndef __OS2__
848         .def    _ffi_closure_STDCALL;   .scl    2;      .type   32;     .endef
849 #endif
850 _ffi_closure_STDCALL:
851 .LFB5:
852         pushl   %ebp
853 .LCFI9:
854         movl    %esp, %ebp
855 .LCFI10:
856         subl    $40, %esp
857         leal    -24(%ebp), %edx
858         movl    %edx, -12(%ebp) /* resp */
859         leal    12(%ebp), %edx  /* account for stub return address on stack */
860         movl    %edx, 4(%esp)   /* args */
861         leal    -12(%ebp), %edx
862         movl    %edx, (%esp)    /* &resp */
863         call    _ffi_closure_SYSV_inner
864         movl    -12(%ebp), %ecx
865 0:
866         call    1f
867         # Do not insert anything here between the call and the jump table.
868 .Lscls_store_table:
869         .long   .Lscls_noretval         /* FFI_TYPE_VOID */
870         .long   .Lscls_retint           /* FFI_TYPE_INT */
871         .long   .Lscls_retfloat         /* FFI_TYPE_FLOAT */
872         .long   .Lscls_retdouble        /* FFI_TYPE_DOUBLE */
873         .long   .Lscls_retldouble       /* FFI_TYPE_LONGDOUBLE */
874         .long   .Lscls_retuint8         /* FFI_TYPE_UINT8 */
875         .long   .Lscls_retsint8         /* FFI_TYPE_SINT8 */
876         .long   .Lscls_retuint16        /* FFI_TYPE_UINT16 */
877         .long   .Lscls_retsint16        /* FFI_TYPE_SINT16 */
878         .long   .Lscls_retint           /* FFI_TYPE_UINT32 */
879         .long   .Lscls_retint           /* FFI_TYPE_SINT32 */
880         .long   .Lscls_retllong         /* FFI_TYPE_UINT64 */
881         .long   .Lscls_retllong         /* FFI_TYPE_SINT64 */
882         .long   .Lscls_retstruct        /* FFI_TYPE_STRUCT */
883         .long   .Lscls_retint           /* FFI_TYPE_POINTER */
884         .long   .Lscls_retstruct1       /* FFI_TYPE_SMALL_STRUCT_1B */
885         .long   .Lscls_retstruct2       /* FFI_TYPE_SMALL_STRUCT_2B */
886         .long   .Lscls_retstruct4       /* FFI_TYPE_SMALL_STRUCT_4B */
887 1:
888         add     %eax, %eax
889         add     %eax, %eax
890         add     (%esp),%eax
891         add     $4, %esp
892         jmp     *(%eax)
893
894         /* Sign/zero extend as appropriate.  */
895 .Lscls_retsint8:
896         movsbl  (%ecx), %eax
897         jmp     .Lscls_epilogue
898
899 .Lscls_retsint16:
900         movswl  (%ecx), %eax
901         jmp     .Lscls_epilogue
902
903 .Lscls_retuint8:
904         movzbl  (%ecx), %eax
905         jmp     .Lscls_epilogue
906
907 .Lscls_retuint16:
908         movzwl  (%ecx), %eax
909         jmp     .Lscls_epilogue
910
911 .Lscls_retint:
912         movl    (%ecx), %eax
913         jmp     .Lscls_epilogue
914
915 .Lscls_retfloat:
916         flds    (%ecx)
917         jmp     .Lscls_epilogue
918
919 .Lscls_retdouble:
920         fldl    (%ecx)
921         jmp     .Lscls_epilogue
922
923 .Lscls_retldouble:
924         fldt    (%ecx)
925         jmp     .Lscls_epilogue
926
927 .Lscls_retllong:
928         movl    (%ecx), %eax
929         movl    4(%ecx), %edx
930         jmp     .Lscls_epilogue
931
932 .Lscls_retstruct1:
933         movsbl  (%ecx), %eax
934         jmp     .Lscls_epilogue
935
936 .Lscls_retstruct2:
937         movswl  (%ecx), %eax
938         jmp     .Lscls_epilogue
939
940 .Lscls_retstruct4:
941         movl    (%ecx), %eax
942         jmp     .Lscls_epilogue
943
944 .Lscls_retstruct:
945         # Nothing to do!
946
947 .Lscls_noretval:
948 .Lscls_epilogue:
949         movl    %ebp, %esp
950         popl    %ebp
951         ret
952 .ffi_closure_STDCALL_end:
953 .LFE5:
954
955 #ifndef __OS2__
956         .section        .eh_frame,"w"
957 #endif
958 .Lframe1:
959 .LSCIE1:
960         .long   .LECIE1-.LASCIE1  /* Length of Common Information Entry */
961 .LASCIE1:
962         .long   0x0     /* CIE Identifier Tag */
963         .byte   0x1     /* CIE Version */
964 #ifdef __PIC__
965         .ascii "zR\0"   /* CIE Augmentation */
966 #else
967         .ascii "\0"     /* CIE Augmentation */
968 #endif
969         .byte   0x1     /* .uleb128 0x1; CIE Code Alignment Factor */
970         .byte   0x7c    /* .sleb128 -4; CIE Data Alignment Factor */
971         .byte   0x8     /* CIE RA Column */
972 #ifdef __PIC__
973         .byte   0x1     /* .uleb128 0x1; Augmentation size */
974         .byte   0x1b    /* FDE Encoding (pcrel sdata4) */
975 #endif
976         .byte   0xc     /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
977         .byte   0x4     /* .uleb128 0x4 */
978         .byte   0x4     /* .uleb128 0x4 */
979         .byte   0x88    /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
980         .byte   0x1     /* .uleb128 0x1 */
981         .align 4
982 .LECIE1:
983
984 .LSFDE1:
985         .long   .LEFDE1-.LASFDE1        /* FDE Length */
986 .LASFDE1:
987         .long   .LASFDE1-.Lframe1       /* FDE CIE offset */
988 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
989         .long   .LFB1-. /* FDE initial location */
990 #else
991         .long   .LFB1
992 #endif
993         .long   .LFE1-.LFB1     /* FDE address range */
994 #ifdef __PIC__
995         .byte   0x0     /* .uleb128 0x0; Augmentation size */
996 #endif
997         /* DW_CFA_xxx CFI instructions go here.  */
998
999         .byte   0x4     /* DW_CFA_advance_loc4 */
1000         .long   .LCFI0-.LFB1
1001         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1002         .byte   0x8     /* .uleb128 0x8 */
1003         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1004         .byte   0x2     /* .uleb128 0x2 */
1005
1006         .byte   0x4     /* DW_CFA_advance_loc4 */
1007         .long   .LCFI1-.LCFI0
1008         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1009         .byte   0x5     /* .uleb128 0x5 */
1010
1011         /* End of DW_CFA_xxx CFI instructions.  */
1012         .align 4
1013 .LEFDE1:
1014
1015
1016 .LSFDE3:
1017         .long   .LEFDE3-.LASFDE3        /* FDE Length */
1018 .LASFDE3:
1019         .long   .LASFDE3-.Lframe1       /* FDE CIE offset */
1020 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
1021         .long   .LFB3-. /* FDE initial location */
1022 #else
1023         .long   .LFB3
1024 #endif
1025         .long   .LFE3-.LFB3     /* FDE address range */
1026 #ifdef __PIC__
1027         .byte   0x0     /* .uleb128 0x0; Augmentation size */
1028 #endif
1029         /* DW_CFA_xxx CFI instructions go here.  */
1030
1031         .byte   0x4     /* DW_CFA_advance_loc4 */
1032         .long   .LCFI4-.LFB3
1033         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1034         .byte   0x8     /* .uleb128 0x8 */
1035         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1036         .byte   0x2     /* .uleb128 0x2 */
1037
1038         .byte   0x4     /* DW_CFA_advance_loc4 */
1039         .long   .LCFI5-.LCFI4
1040         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1041         .byte   0x5     /* .uleb128 0x5 */
1042
1043         /* End of DW_CFA_xxx CFI instructions.  */
1044         .align 4
1045 .LEFDE3:
1046
1047 #if !FFI_NO_RAW_API
1048
1049 .LSFDE4:
1050         .long   .LEFDE4-.LASFDE4        /* FDE Length */
1051 .LASFDE4:
1052         .long   .LASFDE4-.Lframe1       /* FDE CIE offset */
1053 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
1054         .long   .LFB4-. /* FDE initial location */
1055 #else
1056         .long   .LFB4
1057 #endif
1058         .long   .LFE4-.LFB4     /* FDE address range */
1059 #ifdef __PIC__
1060         .byte   0x0     /* .uleb128 0x0; Augmentation size */
1061 #endif
1062         /* DW_CFA_xxx CFI instructions go here.  */
1063
1064         .byte   0x4     /* DW_CFA_advance_loc4 */
1065         .long   .LCFI6-.LFB4
1066         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1067         .byte   0x8     /* .uleb128 0x8 */
1068         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1069         .byte   0x2     /* .uleb128 0x2 */
1070
1071         .byte   0x4     /* DW_CFA_advance_loc4 */
1072         .long   .LCFI7-.LCFI6
1073         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1074         .byte   0x5     /* .uleb128 0x5 */
1075
1076         .byte   0x4     /* DW_CFA_advance_loc4 */
1077         .long   .LCFI8-.LCFI7
1078         .byte   0x86    /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
1079         .byte   0x3     /* .uleb128 0x3 */
1080
1081         /* End of DW_CFA_xxx CFI instructions.  */
1082         .align 4
1083 .LEFDE4:
1084
1085 #endif /* !FFI_NO_RAW_API */
1086
1087 .LSFDE5:
1088         .long   .LEFDE5-.LASFDE5        /* FDE Length */
1089 .LASFDE5:
1090         .long   .LASFDE5-.Lframe1       /* FDE CIE offset */
1091 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
1092         .long   .LFB5-. /* FDE initial location */
1093 #else
1094         .long   .LFB5
1095 #endif
1096         .long   .LFE5-.LFB5     /* FDE address range */
1097 #ifdef __PIC__
1098         .byte   0x0     /* .uleb128 0x0; Augmentation size */
1099 #endif
1100         /* DW_CFA_xxx CFI instructions go here.  */
1101
1102         .byte   0x4     /* DW_CFA_advance_loc4 */
1103         .long   .LCFI9-.LFB5
1104         .byte   0xe     /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1105         .byte   0x8     /* .uleb128 0x8 */
1106         .byte   0x85    /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1107         .byte   0x2     /* .uleb128 0x2 */
1108
1109         .byte   0x4     /* DW_CFA_advance_loc4 */
1110         .long   .LCFI10-.LCFI9
1111         .byte   0xd     /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1112         .byte   0x5     /* .uleb128 0x5 */
1113
1114         /* End of DW_CFA_xxx CFI instructions.  */
1115         .align 4
1116 .LEFDE5:
1117
1118 #endif /* !_MSC_VER */
1119