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