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