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 
  47 EXTRN ffi_closure_SYSV_inner:NEAR
  48 EXTRN ffi_closure_WIN32_inner:NEAR
  49 
  50 _TEXT SEGMENT
  51 
  52 ffi_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
  84 prepr_two_cmp:
  85         cmp  eax, 2
  86         jl   prepr_one_prep
  87         mov  ecx, esp
  88         add  esp, 8
  89 prepr_two:
  90         mov  edx, DWORD PTR [ecx+4]
  91         jmp  prepr_one
  92 prepr_one_prep:
  93         mov  ecx, esp
  94         add  esp, 4
  95 prepr_one:
  96         mov  ecx, DWORD PTR [ecx]
  97         cmp  cif_abi, 7 ;; FFI_REGISTER
  98         jne  fun
  99 
 100         xchg ecx, eax
 101 
 102 fun:
 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 
 121 ca_jumptable:
 122         jmp  [ca_jumpdata + 4 * ecx]
 123 ca_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.  */
 146 ca_retuint8:
 147         movzx eax, al
 148         jmp   ca_retint
 149 
 150 ca_retsint8:
 151         movsx eax, al
 152         jmp   ca_retint
 153 
 154 ca_retuint16:
 155         movzx eax, ax
 156         jmp   ca_retint
 157 
 158 ca_retsint16:
 159         movsx eax, ax
 160         jmp   ca_retint
 161 
 162 ca_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 
 168 ca_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 
 175 ca_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 
 181 ca_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 
 187 ca_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 
 193 ca_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 
 199 ca_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 
 205 ca_epilogue:
 206         ;; Epilogue code is autogenerated.
 207         ret
 208 ffi_call_win32 ENDP
 209 
 210 ffi_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
 216 ffi_closure_THISCALL ENDP
 217 
 218 ffi_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
 225 ffi_closure_FASTCALL ENDP
 226 
 227 ffi_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
 235 ffi_closure_REGISTER ENDP
 236 
 237 ffi_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]
 244 stub::
 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 
 252 cs_jumptable:
 253         jmp  [cs_jumpdata + 4 * eax]
 254 cs_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 
 276 cs_retuint8:
 277         movzx eax, BYTE PTR [ecx]
 278         jmp   cs_epilogue
 279 
 280 cs_retsint8:
 281         movsx eax, BYTE PTR [ecx]
 282         jmp   cs_epilogue
 283 
 284 cs_retuint16:
 285         movzx eax, WORD PTR [ecx]
 286         jmp   cs_epilogue
 287 
 288 cs_retsint16:
 289         movsx eax, WORD PTR [ecx]
 290         jmp   cs_epilogue
 291 
 292 cs_retint:
 293         mov   eax, [ecx]
 294         jmp   cs_epilogue
 295 
 296 cs_retint64:
 297         mov   eax, [ecx + 0]
 298         mov   edx, [ecx + 4]
 299         jmp   cs_epilogue
 300 
 301 cs_retfloat:
 302         fld   DWORD PTR [ecx]
 303         jmp   cs_epilogue
 304 
 305 cs_retdouble:
 306         fld   QWORD PTR [ecx]
 307         jmp   cs_epilogue
 308 
 309 cs_retlongdouble:
 310         fld   TBYTE PTR [ecx]
 311         jmp   cs_epilogue
 312 
 313 cs_retstruct:
 314         ;; Caller expects us to pop struct return value pointer hidden arg.
 315         ;; Epilogue code is autogenerated.
 316         ret	4
 317 
 318 cs_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 
 324 cs_epilogue:
 325         ;; Epilogue code is autogenerated.
 326         ret
 327 ffi_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 
 335 ffi_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
 342 ffi_closure_raw_THISCALL ENDP
 343 
 344 ffi_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]
 352 stubraw::
 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 
 361 cr_jumptable:
 362         jmp  [cr_jumpdata + 4 * eax]
 363 cr_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 
 385 cr_retuint8:
 386         movzx eax, BYTE PTR [ecx]
 387         jmp   cr_epilogue
 388 
 389 cr_retsint8:
 390         movsx eax, BYTE PTR [ecx]
 391         jmp   cr_epilogue
 392 
 393 cr_retuint16:
 394         movzx eax, WORD PTR [ecx]
 395         jmp   cr_epilogue
 396 
 397 cr_retsint16:
 398         movsx eax, WORD PTR [ecx]
 399         jmp   cr_epilogue
 400 
 401 cr_retint:
 402         mov   eax, [ecx]
 403         jmp   cr_epilogue
 404 
 405 cr_retint64:
 406         mov   eax, [ecx + 0]
 407         mov   edx, [ecx + 4]
 408         jmp   cr_epilogue
 409 
 410 cr_retfloat:
 411         fld   DWORD PTR [ecx]
 412         jmp   cr_epilogue
 413 
 414 cr_retdouble:
 415         fld   QWORD PTR [ecx]
 416         jmp   cr_epilogue
 417 
 418 cr_retlongdouble:
 419         fld   TBYTE PTR [ecx]
 420         jmp   cr_epilogue
 421 
 422 cr_epilogue:
 423         ;; Epilogue code is autogenerated.
 424         ret
 425 ffi_closure_raw_SYSV ENDP
 426 
 427 #endif /* !FFI_NO_RAW_API */
 428 
 429 ffi_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 
 447 cd_jumptable:
 448         jmp  [cd_jumpdata + 4 * eax]
 449 cd_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 
 470 cd_retuint8:
 471         movzx eax, BYTE PTR [ecx]
 472         jmp   cd_epilogue
 473 
 474 cd_retsint8:
 475         movsx eax, BYTE PTR [ecx]
 476         jmp   cd_epilogue
 477 
 478 cd_retuint16:
 479         movzx eax, WORD PTR [ecx]
 480         jmp   cd_epilogue
 481 
 482 cd_retsint16:
 483         movsx eax, WORD PTR [ecx]
 484         jmp   cd_epilogue
 485 
 486 cd_retint:
 487         mov   eax, [ecx]
 488         jmp   cd_epilogue
 489 
 490 cd_retint64:
 491         mov   eax, [ecx + 0]
 492         mov   edx, [ecx + 4]
 493         jmp   cd_epilogue
 494 
 495 cd_retfloat:
 496         fld   DWORD PTR [ecx]
 497         jmp   cd_epilogue
 498 
 499 cd_retdouble:
 500         fld   QWORD PTR [ecx]
 501         jmp   cd_epilogue
 502 
 503 cd_retlongdouble:
 504         fld   TBYTE PTR [ecx]
 505         jmp   cd_epilogue
 506 
 507 cd_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
 514 ffi_closure_STDCALL ENDP
 515 
 516 _TEXT ENDS
 517 END
 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
 532 FFI_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
 537 USCORE_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 
 608 0:
 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 */
 631 1:
 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
 715 FFI_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
 720 USCORE_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
 728 FFI_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
 733 USCORE_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
 740 FFI_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
 745 USCORE_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
 757 FFI_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
 763 USCORE_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
 784 1:      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 
 791 0:
 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 
 815 1:
 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
 901 FFI_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
 906 USCORE_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
 925 USCORE_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 */
 946 0:
 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 */
 969 1:
 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
1043 FFI_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
1048 USCORE_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
1071 1:      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
1077 0:
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 */
1103 1:
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
1177 L_ffi_closure_SYSV_inner$stub:
1178         .indirect_symbol _ffi_closure_SYSV_inner
1179         hlt ; hlt ; hlt ; hlt ; hlt
1180 L_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