This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 07/13] x86: Rewrite closures


Move everything into sysv.S, removing win32.S and freebsd.S.
Handle all abis with a single ffi_closure_inner function.
Move complexity of the raw THISCALL trampoline into assembly
instead of the trampoline itself.
Only push the context for the REGISTER abi; let the rest
receive it in a register.
---
 Makefile.am         |   13 +-
 src/x86/ffi.c       |  389 +++++----------
 src/x86/ffitarget.h |    6 +-
 src/x86/freebsd.S   |  463 ------------------
 src/x86/sysv.S      |  607 +++++++++++++++++------
 src/x86/win32.S     | 1351 ---------------------------------------------------
 6 files changed, 593 insertions(+), 2236 deletions(-)
 delete mode 100644 src/x86/freebsd.S
 delete mode 100644 src/x86/win32.S

diff --git a/Makefile.am b/Makefile.am
index 3d1ecae..97a7bd3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,8 +37,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj			\
 	 src/sh64/sysv.S src/sh64/ffitarget.h src/sparc/v8.S		\
 	 src/sparc/v9.S src/sparc/ffitarget.h src/sparc/ffi.c		\
 	 src/x86/darwin64.S src/x86/ffi.c src/x86/sysv.S		\
-	 src/x86/win32.S src/x86/darwin.S src/x86/ffiw64.c src/x86/win64.S \
-	 src/x86/freebsd.S src/x86/ffi64.c src/x86/unix64.S		\
+	 src/x86/darwin.S src/x86/ffiw64.c src/x86/win64.S 		\
+	 src/x86/ffi64.c src/x86/unix64.S				\
 	 src/x86/ffitarget.h src/pa/ffitarget.h src/pa/ffi.c		\
 	 src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c src/bfin/ffi.c	\
 	 src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S		\
@@ -126,22 +126,19 @@ if BFIN
 nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.S
 endif
 if X86
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S src/x86/win32.S
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
 endif
 if X86_FREEBSD
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/freebsd.S src/x86/win32.S
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
 endif
 if X86_WIN32
-nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
 endif
 if X86_WIN64
 nodist_libffi_la_SOURCES += src/x86/ffiw64.c src/x86/win64.S
 endif
 if X86_DARWIN
 nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
-if X86_DARWIN32
-nodist_libffi_la_SOURCES += src/x86/win32.S
-endif
 endif
 if SPARC
 nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
diff --git a/src/x86/ffi.c b/src/x86/ffi.c
index 1c77bb8..40e47d2 100644
--- a/src/x86/ffi.c
+++ b/src/x86/ffi.c
@@ -321,224 +321,105 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 
 /** private members **/
 
-/* The following __attribute__((regparm(1))) decorations will have no effect
-   on MSVC or SUNPRO_C -- standard conventions apply. */
-static unsigned int ffi_prep_incoming_args (char *stack, void **ret,
-                                            void** args, ffi_cif* cif);
-void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
-     __attribute__ ((regparm(1)));
-unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
-     __attribute__ ((regparm(1)));
-unsigned int FFI_HIDDEN ffi_closure_WIN32_inner (ffi_closure *, void **, void *)
-     __attribute__ ((regparm(1)));
-void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
-     __attribute__ ((regparm(1)));
-#ifdef X86_WIN32
-void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
-     __attribute__ ((regparm(1)));
-#endif
-void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *);
-void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *);
-void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *);
-void FFI_HIDDEN ffi_closure_REGISTER (ffi_closure *);
-
-/* This function is jumped to by the trampoline */
+void FFI_HIDDEN ffi_closure_i386(void);
+void FFI_HIDDEN ffi_closure_STDCALL(void);
+void FFI_HIDDEN ffi_closure_REGISTER(void);
 
-unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
-ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
+struct closure_frame
 {
-  /* our various things...  */
-  ffi_cif       *cif;
-  void         **arg_area;
-
-  cif         = closure->cif;
-  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
-
-  /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding 
-   * value on the stack; and if the function returns
-   * a structure, it will change RESP to point to the
-   * structure return address.  */
-
-  ffi_prep_incoming_args(args, respp, arg_area, cif);
-
-  (closure->fun) (cif, *respp, arg_area, closure->user_data);
-
-  return cif->flags;
-}
+  unsigned rettemp[4];				/* 0 */
+  unsigned regs[3];				/* 16-24 */
+  ffi_cif *cif;					/* 28 */
+  void (*fun)(ffi_cif*,void*,void**,void*);	/* 32 */
+  void *user_data;				/* 36 */
+};
 
-unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
-ffi_closure_WIN32_inner (ffi_closure *closure, void **respp, void *args)
+int FFI_HIDDEN __declspec(fastcall)
+ffi_closure_inner (struct closure_frame *frame, char *stack)
 {
-  /* our various things...  */
-  ffi_cif       *cif;
-  void         **arg_area;
-  unsigned int   ret;
-
-  cif         = closure->cif;
-  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
-
-  /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding 
-   * value on the stack; and if the function returns
-   * a structure, it will change RESP to point to the
-   * structure return address.  */
-
-  ret = ffi_prep_incoming_args(args, respp, arg_area, cif);
-
-  (closure->fun) (cif, *respp, arg_area, closure->user_data);
-
-  return ret;
-}
+  ffi_cif *cif = frame->cif;
+  int cabi, i, n, flags, dir, narg_reg;
+  const struct abi_params *pabi;
+  ffi_type **arg_types;
+  char *argp;
+  void *rvalue;
+  void **avalue;
 
-static unsigned int
-ffi_prep_incoming_args(char *stack, void **rvalue, void **avalue,
-                       ffi_cif *cif)
-{
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-  const int cabi = cif->abi;
-  const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1;
-  const unsigned int max_stack_count = (cabi == FFI_THISCALL) ? 1
-                                     : (cabi == FFI_FASTCALL) ? 2
-                                     : (cabi == FFI_REGISTER) ? 3
-                                     : 0;
-  unsigned int passed_regs = 0;
-  void *p_stack_data[3] = { stack - 1 };
-
-  argp = stack;
-  argp += max_stack_count * FFI_SIZEOF_ARG;
-
-  if ((cif->flags == FFI_TYPE_STRUCT
-       || cif->flags == FFI_TYPE_MS_STRUCT))
-    {
-      if (passed_regs < max_stack_count)
-        {
-          *rvalue = *(void**) (stack + (passed_regs*FFI_SIZEOF_ARG));
-          ++passed_regs;
-        }
-      else
-        {
-          *rvalue = *(void **) argp;
-          argp += sizeof(void *);
-        }
-    }
+  cabi = cif->abi;
+  flags = cif->flags;
+  narg_reg = 0;
+  rvalue = frame->rettemp;
+  pabi = &abi_params[cabi];
+  dir = pabi->dir;
+  argp = (dir < 0 ? stack + cif->bytes : stack);
 
-  /* Do register arguments first  */
-  for (i = 0, p_arg = cif->arg_types; 
-       i < cif->nargs && passed_regs < max_stack_count;
-       i++, p_arg++)
+  switch (flags)
     {
-      if ((*p_arg)->type == FFI_TYPE_FLOAT
-         || (*p_arg)->type == FFI_TYPE_STRUCT)
-        continue;
-
-      size_t sz = (*p_arg)->size;
-      if(sz == 0 || sz > FFI_SIZEOF_ARG)
-        continue;
-
-      p_stack_data[passed_regs] = avalue + i;
-      avalue[i] = stack + (passed_regs*FFI_SIZEOF_ARG);
-      ++passed_regs;
+    case X86_RET_STRUCTARG:
+      if (pabi->nregs > 0)
+	{
+	  rvalue = (void *)frame->regs[pabi->regs[0]];
+	  narg_reg = 1;
+	  frame->rettemp[0] = (unsigned)rvalue;
+	  break;
+	}
+      /* fallthru */
+    case X86_RET_STRUCTPOP:
+      rvalue = *(void **)argp;
+      argp += sizeof(void *);
+      break;
     }
 
-  p_arg = cif->arg_types;
-  p_argv = avalue;
-  if (dir < 0)
-    {
-      const int nargs = cif->nargs - 1;
-      if (nargs > 0)
-      {
-        p_arg  += nargs;
-        p_argv += nargs;
-      }
-    }
+  n = cif->nargs;
+  avalue = alloca(sizeof(void *) * n);
 
-  for (i = cif->nargs;
-       i != 0;
-       i--, p_arg += dir, p_argv += dir)
+  arg_types = cif->arg_types;
+  for (i = 0; i < n; ++i)
     {
-      /* Align if necessary */
-      if ((sizeof(void*) - 1) & (size_t) argp)
-        argp = (char *) ALIGN(argp, sizeof(void*));
-
-      size_t z = (*p_arg)->size;
+      size_t z = arg_types[i]->size;
+      int t = arg_types[i]->type;
+      void *valp;
 
-      if (passed_regs > 0
-          && z <= FFI_SIZEOF_ARG
-          && (p_argv == p_stack_data[0]
-            || p_argv == p_stack_data[1]
-            || p_argv == p_stack_data[2]))
-        {
-          /* Already assigned a register value */
-          continue;
-        }
+      if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
+	{
+	  if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
+	    valp = &frame->regs[pabi->regs[narg_reg++]];
+	  else if (dir < 0)
+	    {
+	      argp -= 4;
+	      valp = argp;
+	    }
+	  else
+	    {
+	      valp = argp;
+	      argp += 4;
+	    }
+	}
       else
-        {
-          /* because we're little endian, this is what it turns into.   */
-          *p_argv = (void*) argp;
-        }
+	{
+	  size_t za = ALIGN (z, FFI_SIZEOF_ARG);
+	  if (dir < 0)
+	    {
+	      argp -= za;
+	      valp = argp;
+	    }
+	  else
+	    {
+	      valp = argp;
+	      argp += za;
+	    }
+	}
 
-      argp += z;
+      avalue[i] = valp;
     }
 
-  return (size_t)argp - (size_t)stack;
-}
+  frame->fun (cif, rvalue, avalue, frame->user_data);
 
-/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
-
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   unsigned int  __fun = (unsigned int)(FUN); \
-   unsigned int  __ctx = (unsigned int)(CTX); \
-   unsigned int  __dis = __fun - (__ctx + 10);  \
-   *(unsigned char*) &__tramp[0] = 0xb8; \
-   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
-   *(unsigned char*) &__tramp[5] = 0xe9; \
-   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
- }
-
-#define FFI_INIT_TRAMPOLINE_RAW_THISCALL(TRAMP,FUN,CTX,SIZE) \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   unsigned int  __fun = (unsigned int)(FUN); \
-   unsigned int  __ctx = (unsigned int)(CTX); \
-   unsigned int  __dis = __fun - (__ctx + 49);  \
-   unsigned short __size = (unsigned short)(SIZE); \
-   *(unsigned int *) &__tramp[0] = 0x8324048b;      /* mov (%esp), %eax */ \
-   *(unsigned int *) &__tramp[4] = 0x4c890cec;      /* sub $12, %esp */ \
-   *(unsigned int *) &__tramp[8] = 0x04890424;      /* mov %ecx, 4(%esp) */ \
-   *(unsigned char*) &__tramp[12] = 0x24;           /* mov %eax, (%esp) */ \
-   *(unsigned char*) &__tramp[13] = 0xb8; \
-   *(unsigned int *) &__tramp[14] = __size;         /* mov __size, %eax */ \
-   *(unsigned int *) &__tramp[18] = 0x08244c8d;     /* lea 8(%esp), %ecx */ \
-   *(unsigned int *) &__tramp[22] = 0x4802e8c1;     /* shr $2, %eax ; dec %eax */ \
-   *(unsigned short*) &__tramp[26] = 0x0b74;        /* jz 1f */ \
-   *(unsigned int *) &__tramp[28] = 0x8908518b;     /* 2b: mov 8(%ecx), %edx */ \
-   *(unsigned int *) &__tramp[32] = 0x04c18311;     /* mov %edx, (%ecx) ; add $4, %ecx */ \
-   *(unsigned char*) &__tramp[36] = 0x48;           /* dec %eax */ \
-   *(unsigned short*) &__tramp[37] = 0xf575;        /* jnz 2b ; 1f: */ \
-   *(unsigned char*) &__tramp[39] = 0xb8; \
-   *(unsigned int*)  &__tramp[40] = __ctx;          /* movl __ctx, %eax */ \
-   *(unsigned char *)  &__tramp[44] = 0xe8; \
-   *(unsigned int*)  &__tramp[45] = __dis;          /* call __fun  */ \
-   *(unsigned char*)  &__tramp[49] = 0xc2;          /* ret  */ \
-   *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
- }
-
-#define FFI_INIT_TRAMPOLINE_WIN32(TRAMP,FUN,CTX)  \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   unsigned int  __fun = (unsigned int)(FUN); \
-   unsigned int  __ctx = (unsigned int)(CTX); \
-   unsigned int  __dis = __fun - (__ctx + 10); \
-   *(unsigned char*) &__tramp[0] = 0x68; \
-   *(unsigned int*)  &__tramp[1] = __ctx; /* push __ctx */ \
-   *(unsigned char*) &__tramp[5] = 0xe9; \
-   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
- }
-
-/* the cif must already be prep'ed */
+  if (cabi == FFI_STDCALL)
+    return flags + (cif->bytes << X86_RET_POP_SHIFT);
+  else
+    return flags;
+}
 
 ffi_status
 ffi_prep_closure_loc (ffi_closure* closure,
@@ -547,50 +428,40 @@ ffi_prep_closure_loc (ffi_closure* closure,
                       void *user_data,
                       void *codeloc)
 {
-  if (cif->abi == FFI_SYSV)
-    {
-      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
-                           &ffi_closure_SYSV,
-                           (void*)codeloc);
-    }
-  else if (cif->abi == FFI_REGISTER)
-    {
-      FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-                                   &ffi_closure_REGISTER,
-                                   (void*)codeloc);
-    }
-  else if (cif->abi == FFI_FASTCALL)
-    {
-      FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-                                   &ffi_closure_FASTCALL,
-                                   (void*)codeloc);
-    }
-  else if (cif->abi == FFI_THISCALL)
-    {
-      FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-                                   &ffi_closure_THISCALL,
-                                   (void*)codeloc);
-    }
-  else if (cif->abi == FFI_STDCALL || cif->abi == FFI_PASCAL)
-    {
-      FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-                                   &ffi_closure_STDCALL,
-                                   (void*)codeloc);
-    }
-  else if (cif->abi == FFI_MS_CDECL)
-    {
-      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
-                           &ffi_closure_SYSV,
-                           (void*)codeloc);
-    }
-  else
+  char *tramp = closure->tramp;
+  void (*dest)(void);
+  int op = 0xb8;  /* movl imm, %eax */
+
+  switch (cif->abi)
     {
+    case FFI_SYSV:
+    case FFI_THISCALL:
+    case FFI_FASTCALL:
+    case FFI_MS_CDECL:
+      dest = ffi_closure_i386;
+      break;
+    case FFI_STDCALL:
+    case FFI_PASCAL:
+      dest = ffi_closure_STDCALL;
+      break;
+    case FFI_REGISTER:
+      dest = ffi_closure_REGISTER;
+      op = 0x68;  /* pushl imm */
+    default:
       return FFI_BAD_ABI;
     }
-    
-  closure->cif  = cif;
+
+  /* movl or pushl immediate.  */
+  tramp[0] = op;
+  *(void **)(tramp + 1) = codeloc;
+
+  /* jmp dest */
+  tramp[5] = 0xe9;
+  *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
+
+  closure->cif = cif;
+  closure->fun = fun;
   closure->user_data = user_data;
-  closure->fun  = fun;
 
   return FFI_OK;
 }
@@ -599,13 +470,18 @@ ffi_prep_closure_loc (ffi_closure* closure,
 
 #if !FFI_NO_RAW_API
 
+void FFI_HIDDEN ffi_closure_raw_SYSV(void);
+void FFI_HIDDEN ffi_closure_raw_THISCALL(void);
+
 ffi_status
-ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
-                          ffi_cif* cif,
+ffi_prep_raw_closure_loc (ffi_raw_closure *closure,
+                          ffi_cif *cif,
                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
                           void *user_data,
                           void *codeloc)
 {
+  char *tramp = closure->tramp;
+  void (*dest)(void);
   int i;
 
   /* We currently don't support certain kinds of arguments for raw
@@ -613,28 +489,33 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
      language routine, since it would require argument processing,
      something we don't do now for performance.  */
   for (i = cif->nargs-1; i >= 0; i--)
-    {
-      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
-      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
-    }
+    switch (cif->arg_types[i]->type)
+      {
+      case FFI_TYPE_STRUCT:
+      case FFI_TYPE_LONGDOUBLE:
+	return FFI_BAD_TYPEDEF;
+      }
 
   switch (cif->abi)
     {
-#ifdef X86_WIN32
     case FFI_THISCALL:
-      FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0],
-					&ffi_closure_raw_THISCALL,
-					codeloc, cif->bytes);
+      dest = ffi_closure_raw_THISCALL;
       break;
-#endif
     case FFI_SYSV:
-      FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
-			   codeloc);
+      dest = ffi_closure_raw_SYSV;
       break;
     default:
       return FFI_BAD_ABI;
     }
 
+  /* movl imm, %eax.  */
+  tramp[0] = 0xb8;
+  *(void **)(tramp + 1) = codeloc;
+
+  /* jmp dest */
+  tramp[5] = 0xe9;
+  *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
+
   closure->cif = cif;
   closure->fun = fun;
   closure->user_data = user_data;
diff --git a/src/x86/ffitarget.h b/src/x86/ffitarget.h
index 91e429c..8fff29f 100644
--- a/src/x86/ffitarget.h
+++ b/src/x86/ffitarget.h
@@ -129,11 +129,7 @@ typedef enum ffi_abi {
 # define FFI_NATIVE_RAW_API 0
 # define FFI_GO_CLOSURES 1
 #else
-# ifdef X86_WIN32
-#  define FFI_TRAMPOLINE_SIZE 52
-# else
-#  define FFI_TRAMPOLINE_SIZE 10
-# endif
+# define FFI_TRAMPOLINE_SIZE 12
 # define FFI_NATIVE_RAW_API 1  /* x86 has native raw api support */
 #endif
 
diff --git a/src/x86/freebsd.S b/src/x86/freebsd.S
deleted file mode 100644
index 97e0b4e..0000000
--- a/src/x86/freebsd.S
+++ /dev/null
@@ -1,463 +0,0 @@
-/* -----------------------------------------------------------------------
-   freebsd.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
-	       Copyright (c) 2008  BjÃrn KÃnig
-	
-   X86 Foreign Function Interface for FreeBSD
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-   DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------ */
-
-#ifndef __x86_64__
-
-#define LIBFFI_ASM	
-#include <fficonfig.h>
-#include <ffi.h>
-
-.text
-
-.globl ffi_prep_args
-
-	.align 4
-.globl ffi_call_SYSV
-        .type    ffi_call_SYSV,@function
-
-ffi_call_SYSV:
-.LFB1:
-        pushl %ebp
-.LCFI0:
-        movl  %esp,%ebp
-.LCFI1:
-	/* Make room for all of the new args.  */
-	movl  16(%ebp),%ecx
-	subl  %ecx,%esp
-
-	/* Align the stack pointer to 16-bytes */
-	andl  $0xfffffff0, %esp
-
-	movl  %esp,%eax
-
-	/* Place all of the ffi_prep_args in position  */
-	pushl 12(%ebp)
-	pushl %eax
-	call  *8(%ebp)
-
-	/* Return stack to previous state and call the function  */
-	addl  $8,%esp	
-
-	call  *28(%ebp)
-
-	/* Load %ecx with the return type code  */
-	movl  20(%ebp),%ecx	
-
-	/* Protect %esi.  We're going to pop it in the epilogue.  */
-	pushl %esi
-
-	/* If the return value pointer is NULL, assume no return value.  */
-	cmpl  $0,24(%ebp)
-	jne  0f
-
-	/* Even if there is no space for the return value, we are 
-	   obliged to handle floating-point values.  */
-	cmpl  $FFI_TYPE_FLOAT,%ecx
-	jne   noretval
-	fstp  %st(0)
-
-        jmp   epilogue
-
-0:
-	call  1f
-
-.Lstore_table:
-	.long	noretval-.Lstore_table	/* FFI_TYPE_VOID */
-	.long	retint-.Lstore_table	/* FFI_TYPE_INT */
-	.long	retfloat-.Lstore_table	/* FFI_TYPE_FLOAT */
-	.long	retdouble-.Lstore_table	/* FFI_TYPE_DOUBLE */
-	.long	retlongdouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
-	.long	retuint8-.Lstore_table	/* FFI_TYPE_UINT8 */
-	.long	retsint8-.Lstore_table	/* FFI_TYPE_SINT8 */
-	.long	retuint16-.Lstore_table	/* FFI_TYPE_UINT16 */
-	.long	retsint16-.Lstore_table	/* FFI_TYPE_SINT16 */
-	.long	retint-.Lstore_table	/* FFI_TYPE_UINT32 */
-	.long	retint-.Lstore_table	/* FFI_TYPE_SINT32 */
-	.long	retint64-.Lstore_table	/* FFI_TYPE_UINT64 */
-	.long	retint64-.Lstore_table	/* FFI_TYPE_SINT64 */
-	.long	retstruct-.Lstore_table	/* FFI_TYPE_STRUCT */
-	.long	retint-.Lstore_table	/* FFI_TYPE_POINTER */
-	.long   retstruct1b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_1B */
-	.long   retstruct2b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_2B */
-
-1:
-	pop  %esi
-	add  (%esi, %ecx, 4), %esi
-	jmp  *%esi
-
-	/* Sign/zero extend as appropriate.  */
-retsint8:
-	movsbl  %al, %eax
-	jmp  retint
-
-retsint16:
-	movswl  %ax, %eax
-	jmp  retint
-
-retuint8:
-	movzbl  %al, %eax
-	jmp  retint
-
-retuint16:
-	movzwl  %ax, %eax
-	jmp  retint
-
-retfloat:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstps (%ecx)
-	jmp   epilogue
-
-retdouble:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstpl (%ecx)
-	jmp   epilogue
-
-retlongdouble:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	fstpt (%ecx)
-	jmp   epilogue
-	
-retint64:	
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	movl  %eax,0(%ecx)
-	movl  %edx,4(%ecx)
-	jmp   epilogue
-	
-retstruct1b:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx
-	movb  %al,0(%ecx)
-	jmp   epilogue
-
-retstruct2b:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx
-	movw  %ax,0(%ecx)
-	jmp   epilogue
-
-retint:
-	/* Load %ecx with the pointer to storage for the return value  */
-	movl  24(%ebp),%ecx	
-	movl  %eax,0(%ecx)
-
-retstruct:
-	/* Nothing to do!  */
-
-noretval:
-epilogue:
-        popl %esi
-        movl %ebp,%esp
-        popl %ebp
-        ret
-.LFE1:
-.ffi_call_SYSV_end:
-        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
-
-	.align	4
-FFI_HIDDEN (ffi_closure_SYSV)
-.globl ffi_closure_SYSV
-	.type	ffi_closure_SYSV, @function
-
-ffi_closure_SYSV:
-.LFB2:
-	pushl	%ebp
-.LCFI2:
-	movl	%esp, %ebp
-.LCFI3:
-	subl	$40, %esp
-	leal	-24(%ebp), %edx
-	movl	%edx, -12(%ebp)	/* resp */
-	leal	8(%ebp), %edx
-	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
-	leal	-12(%ebp), %edx
-	movl	%edx, (%esp)	/* &resp */
-#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
-	call	ffi_closure_SYSV_inner
-#else
-	movl	%ebx, 8(%esp)
-.LCFI7:
-	call	1f
-1:	popl	%ebx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-	call	ffi_closure_SYSV_inner@PLT
-	movl	8(%esp), %ebx
-#endif
-	movl	-12(%ebp), %ecx
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lcls_retint
-
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lcls_retint
-	
-0:	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lcls_retllong
-	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, %eax
-	je	.Lcls_retstruct1b
-	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, %eax
-	je	.Lcls_retstruct2b
-	cmpl	$FFI_TYPE_STRUCT, %eax
-	je	.Lcls_retstruct
-.Lcls_epilogue:
-	movl	%ebp, %esp
-	popl	%ebp
-	ret
-.Lcls_retint:
-	movl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retfloat:
-	flds	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retdouble:
-	fldl	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retldouble:
-	fldt	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retllong:
-	movl	(%ecx), %eax
-	movl	4(%ecx), %edx
-	jmp	.Lcls_epilogue
-.Lcls_retstruct1b:
-	movsbl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retstruct2b:
-	movswl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retstruct:
-	movl	%ebp, %esp
-	popl	%ebp
-	ret	$4
-.LFE2:
-	.size	ffi_closure_SYSV, .-ffi_closure_SYSV
-
-#if !FFI_NO_RAW_API
-
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-#define CIF_FLAGS_OFFSET 20
-
-	.align	4
-FFI_HIDDEN (ffi_closure_raw_SYSV)
-.globl ffi_closure_raw_SYSV
-	.type	ffi_closure_raw_SYSV, @function
-
-ffi_closure_raw_SYSV:
-.LFB3:
-	pushl	%ebp
-.LCFI4:
-	movl	%esp, %ebp
-.LCFI5:
-	pushl	%esi
-.LCFI6:
-	subl	$36, %esp
-	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-	movl	%edx, 12(%esp)	/* user_data */
-	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
-	movl	%edx, 8(%esp)	/* raw_args */
-	leal	-24(%ebp), %edx
-	movl	%edx, 4(%esp)	/* &res */
-	movl	%esi, (%esp)	/* cif */
-	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
-	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lrcls_retint
-
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lrcls_retint
-0:
-	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lrcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lrcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lrcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lrcls_retllong
-.Lrcls_epilogue:
-	addl	$36, %esp
-	popl	%esi
-	popl	%ebp
-	ret
-.Lrcls_retint:
-	movl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-.Lrcls_retfloat:
-	flds	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retdouble:
-	fldl	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retldouble:
-	fldt	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retllong:
-	movl	-24(%ebp), %eax
-	movl	-20(%ebp), %edx
-	jmp	.Lrcls_epilogue
-.LFE3:
-	.size	ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
-#endif
-
-	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
-.Lframe1:
-	.long	.LECIE1-.LSCIE1	/* Length of Common Information Entry */
-.LSCIE1:
-	.long	0x0	/* CIE Identifier Tag */
-	.byte	0x1	/* CIE Version */
-#ifdef __PIC__
-	.ascii "zR\0"	/* CIE Augmentation */
-#else
-	.ascii "\0"	/* CIE Augmentation */
-#endif
-	.byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
-	.byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
-	.byte	0x8	/* CIE RA Column */
-#ifdef __PIC__
-	.byte	0x1	/* .uleb128 0x1; Augmentation size */
-	.byte	0x1b	/* FDE Encoding (pcrel sdata4) */
-#endif
-	.byte	0xc	/* DW_CFA_def_cfa */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x4	/* .uleb128 0x4 */
-	.byte	0x88	/* DW_CFA_offset, column 0x8 */
-	.byte	0x1	/* .uleb128 0x1 */
-	.align 4
-.LECIE1:
-.LSFDE1:
-	.long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-	.long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-#ifdef __PIC__
-	.long	.LFB1-.	/* FDE initial location */
-#else
-	.long	.LFB1	/* FDE initial location */
-#endif
-	.long	.LFE1-.LFB1	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI0-.LFB1
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI1-.LCFI0
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-	.align 4
-.LEFDE1:
-.LSFDE2:
-	.long	.LEFDE2-.LASFDE2	/* FDE Length */
-.LASFDE2:
-	.long	.LASFDE2-.Lframe1	/* FDE CIE offset */
-#ifdef __PIC__
-	.long	.LFB2-.	/* FDE initial location */
-#else
-	.long	.LFB2
-#endif
-	.long	.LFE2-.LFB2	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI2-.LFB2
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI3-.LCFI2
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI7-.LCFI3
-	.byte	0x83	/* DW_CFA_offset, column 0x3 */
-	.byte	0xa	/* .uleb128 0xa */
-#endif
-	.align 4
-.LEFDE2:
-
-#if !FFI_NO_RAW_API
-
-.LSFDE3:
-	.long	.LEFDE3-.LASFDE3	/* FDE Length */
-.LASFDE3:
-	.long	.LASFDE3-.Lframe1	/* FDE CIE offset */
-#ifdef __PIC__
-	.long	.LFB3-.	/* FDE initial location */
-#else
-	.long	.LFB3
-#endif
-	.long	.LFE3-.LFB3	/* FDE address range */
-#ifdef __PIC__
-	.byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI4-.LFB3
-	.byte	0xe	/* DW_CFA_def_cfa_offset */
-	.byte	0x8	/* .uleb128 0x8 */
-	.byte	0x85	/* DW_CFA_offset, column 0x5 */
-	.byte	0x2	/* .uleb128 0x2 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI5-.LCFI4
-	.byte	0xd	/* DW_CFA_def_cfa_register */
-	.byte	0x5	/* .uleb128 0x5 */
-	.byte	0x4	/* DW_CFA_advance_loc4 */
-	.long	.LCFI6-.LCFI5
-	.byte	0x86	/* DW_CFA_offset, column 0x6 */
-	.byte	0x3	/* .uleb128 0x3 */
-	.align 4
-.LEFDE3:
-
-#endif
-
-#endif /* ifndef __x86_64__ */
-
-	.section .note.GNU-stack,"",%progbits
diff --git a/src/x86/sysv.S b/src/x86/sysv.S
index d0b8417..7b898ae 100644
--- a/src/x86/sysv.S
+++ b/src/x86/sysv.S
@@ -59,10 +59,10 @@
 
 /* This is declared as
 
-   void ffi_call_i386(struct ffi_call_frame *frame, char *argp)
+   void ffi_call_i386(struct call_frame *frame, char *argp)
         __attribute__((fastcall));
 
-   This the arguments are present in
+   Thus the arguments are present in
 
         ecx: frame
         edx: argp
@@ -170,181 +170,478 @@ E(X86_RET_UNUSED15)
 	cfi_endproc
 ENDF(C(ffi_call_i386))
 
-	.align	4
-FFI_HIDDEN (ffi_closure_SYSV)
-.globl ffi_closure_SYSV
-	.type	ffi_closure_SYSV, @function
+/* The inner helper is declared as
 
-ffi_closure_SYSV:
-	cfi_startproc
-	pushl	%ebp
-	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-	movl	%esp, %ebp
-	cfi_def_cfa_register(%ebp)
-	subl	$40, %esp
-	leal	-24(%ebp), %edx
-	movl	%edx, -12(%ebp)	/* resp */
-	leal	8(%ebp), %edx
-#ifdef __SUNPRO_C
-	/* The SUNPRO compiler doesn't support GCC's regparm function
-  	   attribute, so we have to pass all three arguments to
-	   ffi_closure_SYSV_inner on the stack.  */
-	movl	%edx, 8(%esp)	/* args = __builtin_dwarf_cfa () */
-	leal	-12(%ebp), %edx
-	movl	%edx, 4(%esp)	/* &resp */
-	movl    %eax, (%esp)    /* closure */
-#else
-	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
-	leal	-12(%ebp), %edx
-	movl	%edx, (%esp)	/* &resp */
+   void ffi_closure_inner(struct closure_frame *frame, char *argp)
+	__attribute_((fastcall))
+
+   Thus the arguments are placed in
+
+	ecx:	frame
+	edx:	argp
+*/
+
+/* Macros to help setting up the closure_data structure.  */
+
+#define closure_FS	(16 + 3*4 + 3*4 + 4)
+
+.macro	FFI_CLOSURE_SAVE_REGS
+	movl	%eax, 16+R_EAX*4(%esp)
+	movl	%edx, 16+R_EDX*4(%esp)
+	movl	%ecx, 16+R_ECX*4(%esp)
+.endm
+
+.macro	FFI_CLOSURE_COPY_TRAMP_DATA chain
+	movl	FFI_TRAMPOLINE_SIZE(%eax), %edx		/* copy cif */
+	movl	FFI_TRAMPOLINE_SIZE+4(%eax), %ecx	/* copy fun */
+	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %eax	/* copy user_data */
+	movl	%edx, 28(%esp)
+	movl	%ecx, 32(%esp)
+	movl	%eax, 36(%esp)
+.endm
+
+.macro	FFI_CLOSURE_CALL_INNER
+	movl	%esp, %ecx			/* load closure_data */
+	leal	closure_FS+4(%esp), %edx	/* load incoming stack */
+#ifdef __PIC__
+	movl	%ebx, 40(%esp)			/* save ebx */
+	cfi_rel_offset(%ebx, 40)
+	call	__x86.get_pc_thunk.bx		/* load got register */
+	addl	$C(_GLOBAL_OFFSET_TABLE_), %ebx
 #endif
 #if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
-	call	ffi_closure_SYSV_inner
+	call	C(ffi_closure_inner)
 #else
-	movl	%ebx, 8(%esp)
-	cfi_offset(%ebx, -40)
-	call	1f
-1:	popl	%ebx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-	call	ffi_closure_SYSV_inner@PLT
-	movl	8(%esp), %ebx
+	call	C(ffi_closure_inner)@PLT
+#endif
+.endm
+
+.macro	FFI_CLOSURE_MASK_AND_JUMP
+	andl	$X86_RET_TYPE_MASK, %eax
+#ifdef __PIC__
+	leal	0f@GOTOFF(%ebx, %eax, 8), %eax
+	movl	40(%esp), %ebx			/* restore ebx */
 	cfi_restore(%ebx)
+#else
+	leal	0f(, %eax, 8), %eax
 #endif
-	movl	-12(%ebp), %ecx
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lcls_retint
-
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lcls_retint
-	
-0:	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lcls_retllong
-	cmpl	$FFI_TYPE_STRUCT, %eax
-	je	.Lcls_retstruct
-.Lcls_epilogue:
-	movl	%ebp, %esp
-	popl	%ebp
+	jmp	*%eax
+.endm
+
+/* The closure entry points are reached from the ffi_closure trampoline.
+   On entry, %eax contains the address of the ffi_closure.  */
+
+	.align	16
+	.globl	C(ffi_closure_i386)
+	FFI_HIDDEN(C(ffi_closure_i386))
+
+C(ffi_closure_i386):
+	cfi_startproc
+	subl	$closure_FS, %esp
+	cfi_adjust_cfa_offset(closure_FS)
+
+	FFI_CLOSURE_SAVE_REGS
+	FFI_CLOSURE_COPY_TRAMP_DATA
+	FFI_CLOSURE_CALL_INNER
+	FFI_CLOSURE_MASK_AND_JUMP
+
+	.align	8
+0:
+E(X86_RET_FLOAT)
+	flds	(%esp)
+	jmp	9f
+E(X86_RET_DOUBLE)
+	fldl	(%esp)
+	jmp	9f
+E(X86_RET_LDOUBLE)
+	fldt	(%esp)
+	jmp	9f
+E(X86_RET_SINT8)
+	movsbl	(%esp), %eax
+	jmp	9f
+E(X86_RET_SINT16)
+	movswl	(%esp), %eax
+	jmp	9f
+E(X86_RET_UINT8)
+	movzbl	(%esp), %eax
+	jmp	9f
+E(X86_RET_UINT16)
+	movzwl	(%esp), %eax
+	jmp	9f
+E(X86_RET_INT64)
+	movl	4(%esp), %edx
+	/* fallthru */
+E(X86_RET_INT32)
+	movl	(%esp), %eax
+	/* fallthru */
+E(X86_RET_VOID)
+9:	addl	$closure_FS, %esp
+	cfi_adjust_cfa_offset(-closure_FS)
 	ret
-.Lcls_retint:
-	movl	(%ecx), %eax
-	jmp	.Lcls_epilogue
-.Lcls_retfloat:
-	flds	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retdouble:
-	fldl	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retldouble:
-	fldt	(%ecx)
-	jmp	.Lcls_epilogue
-.Lcls_retllong:
-	movl	(%ecx), %eax
-	movl	4(%ecx), %edx
-	jmp	.Lcls_epilogue
-.Lcls_retstruct:
-	movl	%ebp, %esp
-	popl	%ebp
+	cfi_adjust_cfa_offset(closure_FS)
+E(X86_RET_STRUCTPOP)
+	addl	$closure_FS, %esp
+	cfi_adjust_cfa_offset(-closure_FS)
 	ret	$4
+	cfi_adjust_cfa_offset(closure_FS)
+E(X86_RET_STRUCTARG)
+	movl	(%esp), %eax
+	jmp	9b
+E(X86_RET_STRUCT_1B)
+	movzbl	(%esp), %eax
+	jmp	9b
+E(X86_RET_STRUCT_2B)
+	movzwl	(%esp), %eax
+	jmp	9b
+
+	/* Fill out the table so that bad values are predictable.  */
+E(X86_RET_UNUSED14)
+	ud2
+E(X86_RET_UNUSED15)
+	ud2
+
+	cfi_endproc
+ENDF(C(ffi_closure_i386))
+
+/* For REGISTER, we have no available parameter registers, and so we
+   enter here having pushed the closure onto the stack.  */
+
+	.align	16
+	.globl	C(ffi_closure_REGISTER)
+	FFI_HIDDEN(C(ffi_closure_REGISTER))
+C(ffi_closure_REGISTER):
+	cfi_startproc
+	cfi_def_cfa(%esp, 8)
+	cfi_offset(%eip, -8)
+	subl	$closure_FS-4, %esp
+	cfi_adjust_cfa_offset(closure_FS-4)
+
+	FFI_CLOSURE_SAVE_REGS
+
+	movl	closure_FS-4(%esp), %ecx	/* load retaddr */
+	movl	closure_FS(%esp), %eax		/* load closure */
+	movl	%ecx, closure_FS(%esp)		/* move retaddr */
+	jmp	0f
+
+	cfi_endproc
+ENDF(C(ffi_closure_REGISTER))
+
+/* For STDCALL (and others), we need to pop N bytes of arguments off
+   the stack following the closure.  The amount needing to be popped
+   is returned to us from ffi_closure_inner.  */
+
+	.align	16
+	.globl	C(ffi_closure_STDCALL)
+	FFI_HIDDEN(C(ffi_closure_STDCALL))
+C(ffi_closure_STDCALL):
+	cfi_startproc
+	subl	$closure_FS, %esp
+	cfi_adjust_cfa_offset(closure_FS)
+
+	FFI_CLOSURE_SAVE_REGS
+0:
+	FFI_CLOSURE_COPY_TRAMP_DATA
+	FFI_CLOSURE_CALL_INNER
+
+	movl	%eax, %ecx
+	shrl	$X86_RET_POP_SHIFT, %ecx	/* isolate pop count */
+	leal	closure_FS(%esp, %ecx), %ecx	/* compute popped esp */
+	movl	closure_FS(%esp), %edx		/* move return address */
+	movl	%edx, (%ecx)
+
+	/* New pseudo-stack frame based off ecx.  This is unwind trickery
+	   in that the CFA *has* changed, to the proper popped stack address.
+	   Note that the location to which we moved the return address
+	   is the new CFA-4, so that's unchanged.  */
+	cfi_def_cfa(%ecx, 4)
+	/* Normally esp is unwound to CFA + the caller's ARGS_SIZE.
+	   We've just set the CFA to that final value.  Tell the unwinder
+	   to restore esp from CFA without the ARGS_SIZE:
+	   DW_CFA_val_expression %esp, DW_OP_call_frame_cfa.  */
+	cfi_escape(0x16, 4, 1, 0x9c)
+
+	FFI_CLOSURE_MASK_AND_JUMP
+
+	.align	8
+0:
+E(X86_RET_FLOAT)
+	flds    (%esp)
+	movl    %ecx, %esp
+	ret
+E(X86_RET_DOUBLE)
+	fldl    (%esp)
+	movl    %ecx, %esp
+	ret
+E(X86_RET_LDOUBLE)
+	fldt    (%esp)
+	movl    %ecx, %esp
+	ret
+E(X86_RET_SINT8)
+	movsbl  (%esp), %eax
+	movl    %ecx, %esp
+	ret
+E(X86_RET_SINT16)
+	movswl  (%esp), %eax
+	movl    %ecx, %esp
+	ret
+E(X86_RET_UINT8)
+	movzbl  (%esp), %eax
+	movl    %ecx, %esp
+	ret
+E(X86_RET_UINT16)
+	movzwl  (%esp), %eax
+	movl    %ecx, %esp
+	ret
+E(X86_RET_INT64)
+	popl    %eax
+	popl    %edx
+	movl    %ecx, %esp
+	ret
+E(X86_RET_INT32)
+	movl    (%esp), %eax
+	movl    %ecx, %esp
+	ret
+E(X86_RET_VOID)
+	movl    %ecx, %esp
+	ret
+E(X86_RET_STRUCTPOP)
+	movl    %ecx, %esp
+	ret
+E(X86_RET_STRUCTARG)
+	movl	(%esp), %eax
+	movl	%ecx, %esp
+	ret
+E(X86_RET_STRUCT_1B)
+	movzbl	(%esp), %eax
+	movl	%ecx, %esp
+	ret
+E(X86_RET_STRUCT_2B)
+	movzwl	(%esp), %eax
+	movl	%ecx, %esp
+	ret
+
+	/* Fill out the table so that bad values are predictable.  */
+E(X86_RET_UNUSED14)
+	ud2
+E(X86_RET_UNUSED15)
+	ud2
+
 	cfi_endproc
-	.size	ffi_closure_SYSV, .-ffi_closure_SYSV
+ENDF(C(ffi_closure_STDCALL))
 
 #if !FFI_NO_RAW_API
 
-/* Precalculate for e.g. the Solaris 10/x86 assembler.  */
-#if FFI_TRAMPOLINE_SIZE == 10
-#define RAW_CLOSURE_CIF_OFFSET 12
-#define RAW_CLOSURE_FUN_OFFSET 16
-#define RAW_CLOSURE_USER_DATA_OFFSET 20
-#elif FFI_TRAMPOLINE_SIZE == 24
-#define RAW_CLOSURE_CIF_OFFSET 24
-#define RAW_CLOSURE_FUN_OFFSET 28
-#define RAW_CLOSURE_USER_DATA_OFFSET 32
+#define raw_closure_S_FS	(16+16+12)
+
+	.align	16
+	.globl	C(ffi_closure_raw_SYSV)
+	FFI_HIDDEN(C(ffi_closure_raw_SYSV))
+C(ffi_closure_raw_SYSV):
+	cfi_startproc
+	subl	$raw_closure_S_FS, %esp
+	cfi_adjust_cfa_offset(raw_closure_S_FS)
+	movl	%ebx, raw_closure_S_FS-4(%esp)
+	cfi_rel_offset(%ebx, raw_closure_S_FS-4)
+
+	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %edx	/* load cl->user_data */
+	movl	%edx, 12(%esp)
+	leal	raw_closure_S_FS+4(%esp), %edx		/* load raw_args */
+	movl	%edx, 8(%esp)
+	leal	16(%esp), %edx				/* load &res */
+	movl	%edx, 4(%esp)
+	movl	FFI_TRAMPOLINE_SIZE(%eax), %ebx		/* load cl->cif */
+	movl	%ebx, (%esp)
+	call	*FFI_TRAMPOLINE_SIZE+4(%eax)		/* call cl->fun */
+
+	movl	20(%ebx), %eax				/* load cif->flags */
+	andl	$X86_RET_TYPE_MASK, %eax
+#ifdef __PIC__
+	call	__x86.get_pc_thunk.bx
+1:	leal	0f-1b(%ebx, %eax, 8), %eax
 #else
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+	leal	0f(,%eax, 8), %eax
 #endif
-#define CIF_FLAGS_OFFSET 20
+	movl	raw_closure_S_FS-4(%esp), %ebx
+	cfi_restore(%ebx)
+	jmp	*%eax
+
+	.align	8
+0:
+E(X86_RET_FLOAT)
+	flds	16(%esp)
+	jmp	9f
+E(X86_RET_DOUBLE)
+	fldl	16(%esp)
+	jmp	9f
+E(X86_RET_LDOUBLE)
+	fldt	16(%esp)
+	jmp	9f
+E(X86_RET_SINT8)
+	movsbl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_SINT16)
+	movswl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_UINT8)
+	movzbl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_UINT16)
+	movzwl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_INT64)
+	movl	16+4(%esp), %edx
+	/* fallthru */
+E(X86_RET_INT32)
+	movl	16(%esp), %eax
+	/* fallthru */
+E(X86_RET_VOID)
+9:	addl	$raw_closure_S_FS, %esp
+	cfi_adjust_cfa_offset(-raw_closure_S_FS)
+	ret
+	cfi_adjust_cfa_offset(raw_closure_S_FS)
+E(X86_RET_STRUCTPOP)
+	addl	$raw_closure_S_FS, %esp
+	cfi_adjust_cfa_offset(-raw_closure_S_FS)
+	ret	$4
+	cfi_adjust_cfa_offset(raw_closure_S_FS)
+E(X86_RET_STRUCTARG)
+	movl	16(%esp), %eax
+	jmp	9b
+E(X86_RET_STRUCT_1B)
+	movzbl	16(%esp), %eax
+	jmp	9b
+E(X86_RET_STRUCT_2B)
+	movzwl	16(%esp), %eax
+	jmp	9b
+
+	/* Fill out the table so that bad values are predictable.  */
+E(X86_RET_UNUSED14)
+	ud2
+E(X86_RET_UNUSED15)
+	ud2
 
-	.align	4
-FFI_HIDDEN (ffi_closure_raw_SYSV)
-.globl ffi_closure_raw_SYSV
-	.type	ffi_closure_raw_SYSV, @function
+	cfi_endproc
+ENDF(C(ffi_closure_raw_SYSV))
+
+#undef	raw_closure_S_FS
+#define raw_closure_T_FS	(16+16+8)
 
-ffi_closure_raw_SYSV:
+	.align	16
+	.globl	C(ffi_closure_raw_THISCALL)
+	FFI_HIDDEN(C(ffi_closure_raw_THISCALL))
+C(ffi_closure_raw_THISCALL):
 	cfi_startproc
-	pushl	%ebp
+	/* Rearrange the stack such that %ecx is the first argument.
+	   This means moving the return address.  */
+	popl	%edx
+	cfi_adjust_cfa_offset(-4)
+	cfi_register(%eip, %edx)
+	pushl	%ecx
 	cfi_adjust_cfa_offset(4)
-	cfi_rel_offset(%ebp, 0)
-	movl	%esp, %ebp
-	cfi_def_cfa_register(%ebp)
-	pushl	%esi
-	cfi_offset(%esi, -12)
-	subl	$36, %esp
-	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-	movl	%edx, 12(%esp)	/* user_data */
-	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
-	movl	%edx, 8(%esp)	/* raw_args */
-	leal	-24(%ebp), %edx
-	movl	%edx, 4(%esp)	/* &res */
-	movl	%esi, (%esp)	/* cif */
-	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
-	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
-	cmpl	$FFI_TYPE_INT, %eax
-	je	.Lrcls_retint
-
-	/* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-	   FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32.  */
-	cmpl	$FFI_TYPE_UINT64, %eax
-	jge	0f
-	cmpl	$FFI_TYPE_UINT8, %eax
-	jge	.Lrcls_retint
+	pushl	%edx
+	cfi_adjust_cfa_offset(4)
+	cfi_rel_offset(%eip, 0)
+	subl	$raw_closure_T_FS, %esp
+	cfi_adjust_cfa_offset(raw_closure_T_FS)
+	movl	%ebx, raw_closure_T_FS-4(%esp)
+	cfi_offset(%ebx, raw_closure_T_FS-4)
+
+	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %edx	/* load cl->user_data */
+	movl	%edx, 12(%esp)
+	leal	raw_closure_T_FS+4(%esp), %edx		/* load raw_args */
+	movl	%edx, 8(%esp)
+	leal	16(%esp), %edx				/* load &res */
+	movl	%edx, 4(%esp)
+	movl	FFI_TRAMPOLINE_SIZE(%eax), %ebx		/* load cl->cif */
+	movl	%ebx, (%esp)
+	call	*FFI_TRAMPOLINE_SIZE+4(%eax)		/* call cl->fun */
+
+	movl	20(%ebx), %eax				/* load cif->flags */
+	andl	$X86_RET_TYPE_MASK, %eax
+#ifdef __PIC__
+	call	__x86.get_pc_thunk.bx
+1:	leal	0f-1b(%ebx, %eax, 8), %eax
+#else
+	leal	0f(,%eax, 8), %eax
+#endif
+	movl	raw_closure_T_FS-4(%esp), %ebx
+	cfi_restore(%ebx)
+	jmp	*%eax
+
+	.align	8
 0:
-	cmpl	$FFI_TYPE_FLOAT, %eax
-	je	.Lrcls_retfloat
-	cmpl	$FFI_TYPE_DOUBLE, %eax
-	je	.Lrcls_retdouble
-	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
-	je	.Lrcls_retldouble
-	cmpl	$FFI_TYPE_SINT64, %eax
-	je	.Lrcls_retllong
-.Lrcls_epilogue:
-	addl	$36, %esp
-	popl	%esi
-	popl	%ebp
-	ret
-.Lrcls_retint:
-	movl	-24(%ebp), %eax
-	jmp	.Lrcls_epilogue
-.Lrcls_retfloat:
-	flds	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retdouble:
-	fldl	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retldouble:
-	fldt	-24(%ebp)
-	jmp	.Lrcls_epilogue
-.Lrcls_retllong:
-	movl	-24(%ebp), %eax
-	movl	-20(%ebp), %edx
-	jmp	.Lrcls_epilogue
+E(X86_RET_FLOAT)
+	flds	16(%esp)
+	jmp	9f
+E(X86_RET_DOUBLE)
+	fldl	16(%esp)
+	jmp	9f
+E(X86_RET_LDOUBLE)
+	fldt	16(%esp)
+	jmp	9f
+E(X86_RET_SINT8)
+	movsbl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_SINT16)
+	movswl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_UINT8)
+	movzbl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_UINT16)
+	movzwl	16(%esp), %eax
+	jmp	9f
+E(X86_RET_INT64)
+	movl	16+4(%esp), %edx
+	/* fallthru */
+E(X86_RET_INT32)
+	movl	16(%esp), %eax
+	/* fallthru */
+E(X86_RET_VOID)
+9:	addl	$raw_closure_T_FS, %esp
+	cfi_adjust_cfa_offset(-raw_closure_T_FS)
+	/* Remove the extra %ecx argument we pushed.  */
+	ret	$4
+	cfi_adjust_cfa_offset(raw_closure_T_FS)
+E(X86_RET_STRUCTPOP)
+	addl	$raw_closure_T_FS, %esp
+	cfi_adjust_cfa_offset(-raw_closure_T_FS)
+	ret	$8
+	cfi_adjust_cfa_offset(raw_closure_T_FS)
+E(X86_RET_STRUCTARG)
+	movl	16(%esp), %eax
+	jmp	9b
+E(X86_RET_STRUCT_1B)
+	movzbl	16(%esp), %eax
+	jmp	9b
+E(X86_RET_STRUCT_2B)
+	movzwl	16(%esp), %eax
+	jmp	9b
+
+	/* Fill out the table so that bad values are predictable.  */
+E(X86_RET_UNUSED14)
+	ud2
+E(X86_RET_UNUSED15)
+	ud2
+
 	cfi_endproc
-	.size	ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
+ENDF(C(ffi_closure_raw_THISCALL))
 
 #endif /* !FFI_NO_RAW_API */
+
+#if defined(__PIC__)
+	.section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+	.globl	__x86.get_pc_thunk.bx
+	.hidden	__x86.get_pc_thunk.bx
+	.type	__x86.get_pc_thunk.bx,@function
+__x86.get_pc_thunk.bx:
+	cfi_startproc
+	movl	(%esp), %ebx
+	ret
+	cfi_endproc
+	.size	__x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx
+#endif /* __PIC__ */
+
 #endif /* ifndef __x86_64__ */
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
diff --git a/src/x86/win32.S b/src/x86/win32.S
deleted file mode 100644
index d523eb0..0000000
--- a/src/x86/win32.S
+++ /dev/null
@@ -1,1351 +0,0 @@
-/* -----------------------------------------------------------------------
-   win32.S - Copyright (c) 2014  Anthony Green
-             Copyright (c) 1996, 1998, 2001, 2002, 2009  Red Hat, Inc.
-             Copyright (c) 2001  John Beniton
-             Copyright (c) 2002  Ranjit Mathew
-             Copyright (c) 2009  Daniel Witte
-
-
-   X86 Foreign Function Interface
- 
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
- 
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
- 
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-   DEALINGS IN THE SOFTWARE.
-   -----------------------------------------------------------------------
-   */
- 
-#define LIBFFI_ASM
-#include <fficonfig.h>
-#include <ffi.h>
-
-#define CIF_BYTES_OFFSET 16
-#define CIF_FLAGS_OFFSET 20
-
-#ifdef _MSC_VER
-
-#define CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
-
-.386
-.MODEL FLAT, C
-
-EXTRN ffi_closure_SYSV_inner:NEAR
-EXTRN ffi_closure_WIN32_inner:NEAR
-
-_TEXT SEGMENT
-
-ffi_call_win32 PROC NEAR,
-    ffi_prep_args : NEAR PTR DWORD,
-    ecif          : NEAR PTR DWORD,
-    cif_abi       : DWORD,
-    cif_bytes     : DWORD,
-    cif_flags     : DWORD,
-    rvalue        : NEAR PTR DWORD,
-    fn            : NEAR PTR DWORD
-
-        ;; Make room for all of the new args.
-        mov  ecx, cif_bytes
-        sub  esp, ecx
-
-        mov  eax, esp
-
-        ;; Call ffi_prep_args
-        push ecif
-        push eax
-        call ffi_prep_args
-        add  esp, 8
-
-        ;; Prepare registers
-        ;; EAX stores the number of register arguments
-        cmp  eax, 0
-        je   fun
-        cmp  eax, 3
-        jl   prepr_two_cmp
-        
-        mov  ecx, esp
-        add  esp, 12
-        mov  eax, DWORD PTR [ecx+8]
-        jmp  prepr_two
-prepr_two_cmp:
-        cmp  eax, 2
-        jl   prepr_one_prep
-        mov  ecx, esp
-        add  esp, 8
-prepr_two:
-        mov  edx, DWORD PTR [ecx+4]
-        jmp  prepr_one
-prepr_one_prep:
-        mov  ecx, esp
-        add  esp, 4
-prepr_one:
-        mov  ecx, DWORD PTR [ecx]
-        cmp  cif_abi, 7 ;; FFI_REGISTER
-        jne  fun
-
-        xchg ecx, eax
-
-fun:
-        ;; Call function
-        call fn
-
-        ;; Load ecx with the return type code
-        mov  ecx, cif_flags
-
-        ;; If the return value pointer is NULL, assume no return value.
-        cmp  rvalue, 0
-        jne  ca_jumptable
-
-        ;; Even if there is no space for the return value, we are
-        ;; obliged to handle floating-point values.
-        cmp  ecx, FFI_TYPE_FLOAT
-        jne  ca_epilogue
-        fstp st(0)
-
-        jmp  ca_epilogue
-
-ca_jumptable:
-        jmp  [ca_jumpdata + 4 * ecx]
-ca_jumpdata:
-        ;; Do not insert anything here between label and jump table.
-        dd offset ca_epilogue       ;; FFI_TYPE_VOID
-        dd offset ca_retint         ;; FFI_TYPE_INT
-        dd offset ca_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset ca_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset ca_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset ca_retuint8       ;; FFI_TYPE_UINT8
-        dd offset ca_retsint8       ;; FFI_TYPE_SINT8
-        dd offset ca_retuint16      ;; FFI_TYPE_UINT16
-        dd offset ca_retsint16      ;; FFI_TYPE_SINT16
-        dd offset ca_retint         ;; FFI_TYPE_UINT32
-        dd offset ca_retint         ;; FFI_TYPE_SINT32
-        dd offset ca_retint64       ;; FFI_TYPE_UINT64
-        dd offset ca_retint64       ;; FFI_TYPE_SINT64
-        dd offset ca_epilogue       ;; FFI_TYPE_STRUCT
-        dd offset ca_retint         ;; FFI_TYPE_POINTER
-        dd offset ca_retstruct1b    ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset ca_retstruct2b    ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset ca_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-        dd offset ca_epilogue       ;; FFI_TYPE_MS_STRUCT
-
-        /* Sign/zero extend as appropriate.  */
-ca_retuint8:
-        movzx eax, al
-        jmp   ca_retint
-
-ca_retsint8:
-        movsx eax, al
-        jmp   ca_retint
-
-ca_retuint16:
-        movzx eax, ax
-        jmp   ca_retint
-
-ca_retsint16:
-        movsx eax, ax
-        jmp   ca_retint
-
-ca_retint:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], eax
-        jmp   ca_epilogue
-
-ca_retint64:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], eax
-        mov   [ecx + 4], edx
-        jmp   ca_epilogue
-
-ca_retfloat:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        fstp  DWORD PTR [ecx]
-        jmp   ca_epilogue
-
-ca_retdouble:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        fstp  QWORD PTR [ecx]
-        jmp   ca_epilogue
-
-ca_retlongdouble:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        fstp  TBYTE PTR [ecx]
-        jmp   ca_epilogue
-
-ca_retstruct1b:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], al
-        jmp   ca_epilogue
-
-ca_retstruct2b:
-        ;; Load %ecx with the pointer to storage for the return value
-        mov   ecx, rvalue
-        mov   [ecx + 0], ax
-        jmp   ca_epilogue
-
-ca_epilogue:
-        ;; Epilogue code is autogenerated.
-        ret
-ffi_call_win32 ENDP
-
-ffi_closure_THISCALL PROC NEAR
-        ;; Insert the register argument on the stack as the first argument
-        xchg	DWORD PTR [esp+4], ecx
-        xchg	DWORD PTR [esp], ecx
-        push	ecx
-        jmp	ffi_closure_STDCALL
-ffi_closure_THISCALL ENDP
-
-ffi_closure_FASTCALL PROC NEAR
-        ;; Insert the 2 register arguments on the stack as the first argument
-        xchg	DWORD PTR [esp+4], edx
-        xchg	DWORD PTR [esp], ecx
-        push	edx
-        push	ecx
-        jmp	ffi_closure_STDCALL
-ffi_closure_FASTCALL ENDP
-
-ffi_closure_REGISTER PROC NEAR
-        ;; Insert the 3 register arguments on the stack as the first argument
-        push	eax
-        xchg	DWORD PTR [esp+8], ecx
-        xchg	DWORD PTR [esp+4], edx
-        push	ecx
-        push	edx
-        jmp	ffi_closure_STDCALL
-ffi_closure_FASTCALL ENDP
-
-ffi_closure_SYSV PROC NEAR FORCEFRAME
-    ;; the ffi_closure ctx is passed in eax by the trampoline.
-
-        sub  esp, 40
-        lea  edx, [ebp - 24]
-        mov  [ebp - 12], edx         ;; resp
-        lea  edx, [ebp + 8]
-stub::
-        mov  [esp + 8], edx          ;; args
-        lea  edx, [ebp - 12]
-        mov  [esp + 4], edx          ;; &resp
-        mov  [esp], eax              ;; closure
-        call ffi_closure_SYSV_inner
-        mov  ecx, [ebp - 12]
-
-cs_jumptable:
-        jmp  [cs_jumpdata + 4 * eax]
-cs_jumpdata:
-        ;; Do not insert anything here between the label and jump table.
-        dd offset cs_epilogue       ;; FFI_TYPE_VOID
-        dd offset cs_retint         ;; FFI_TYPE_INT
-        dd offset cs_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset cs_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset cs_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset cs_retuint8       ;; FFI_TYPE_UINT8
-        dd offset cs_retsint8       ;; FFI_TYPE_SINT8
-        dd offset cs_retuint16      ;; FFI_TYPE_UINT16
-        dd offset cs_retsint16      ;; FFI_TYPE_SINT16
-        dd offset cs_retint         ;; FFI_TYPE_UINT32
-        dd offset cs_retint         ;; FFI_TYPE_SINT32
-        dd offset cs_retint64       ;; FFI_TYPE_UINT64
-        dd offset cs_retint64       ;; FFI_TYPE_SINT64
-        dd offset cs_retstruct      ;; FFI_TYPE_STRUCT
-        dd offset cs_retint         ;; FFI_TYPE_POINTER
-        dd offset cs_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset cs_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset cs_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-        dd offset cs_retmsstruct    ;; FFI_TYPE_MS_STRUCT
-
-cs_retuint8:
-        movzx eax, BYTE PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retsint8:
-        movsx eax, BYTE PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retuint16:
-        movzx eax, WORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retsint16:
-        movsx eax, WORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retint:
-        mov   eax, [ecx]
-        jmp   cs_epilogue
-
-cs_retint64:
-        mov   eax, [ecx + 0]
-        mov   edx, [ecx + 4]
-        jmp   cs_epilogue
-
-cs_retfloat:
-        fld   DWORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retdouble:
-        fld   QWORD PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retlongdouble:
-        fld   TBYTE PTR [ecx]
-        jmp   cs_epilogue
-
-cs_retstruct:
-        ;; Caller expects us to pop struct return value pointer hidden arg.
-        ;; Epilogue code is autogenerated.
-        ret	4
-
-cs_retmsstruct:
-        ;; Caller expects us to return a pointer to the real return value.
-        mov   eax, ecx
-        ;; Caller doesn't expects us to pop struct return value pointer hidden arg.
-        jmp   cs_epilogue
-
-cs_epilogue:
-        ;; Epilogue code is autogenerated.
-        ret
-ffi_closure_SYSV ENDP
-
-#if !FFI_NO_RAW_API
-
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-
-ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME
-        sub esp, 36
-        mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
-        mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
-        mov [esp + 12], edx
-        lea edx, [ebp + 12]
-        jmp stubraw
-ffi_closure_raw_THISCALL ENDP
-
-ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME
-    ;; the ffi_closure ctx is passed in eax by the trampoline.
-
-        sub  esp, 40
-        mov  esi, [eax + RAW_CLOSURE_CIF_OFFSET]        ;; closure->cif
-        mov  edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET]  ;; closure->user_data
-        mov  [esp + 12], edx                            ;; user_data
-        lea  edx, [ebp + 8]
-stubraw::
-        mov  [esp + 8], edx                             ;; raw_args
-        lea  edx, [ebp - 24]
-        mov  [esp + 4], edx                             ;; &res
-        mov  [esp], esi                                 ;; cif
-        call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET]   ;; closure->fun
-        mov  eax, [esi + CIF_FLAGS_OFFSET]              ;; cif->flags
-        lea  ecx, [ebp - 24]
-
-cr_jumptable:
-        jmp  [cr_jumpdata + 4 * eax]
-cr_jumpdata:
-        ;; Do not insert anything here between the label and jump table.
-        dd offset cr_epilogue       ;; FFI_TYPE_VOID
-        dd offset cr_retint         ;; FFI_TYPE_INT
-        dd offset cr_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset cr_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset cr_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset cr_retuint8       ;; FFI_TYPE_UINT8
-        dd offset cr_retsint8       ;; FFI_TYPE_SINT8
-        dd offset cr_retuint16      ;; FFI_TYPE_UINT16
-        dd offset cr_retsint16      ;; FFI_TYPE_SINT16
-        dd offset cr_retint         ;; FFI_TYPE_UINT32
-        dd offset cr_retint         ;; FFI_TYPE_SINT32
-        dd offset cr_retint64       ;; FFI_TYPE_UINT64
-        dd offset cr_retint64       ;; FFI_TYPE_SINT64
-        dd offset cr_epilogue       ;; FFI_TYPE_STRUCT
-        dd offset cr_retint         ;; FFI_TYPE_POINTER
-        dd offset cr_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset cr_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset cr_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-        dd offset cr_epilogue       ;; FFI_TYPE_MS_STRUCT
-
-cr_retuint8:
-        movzx eax, BYTE PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retsint8:
-        movsx eax, BYTE PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retuint16:
-        movzx eax, WORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retsint16:
-        movsx eax, WORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retint:
-        mov   eax, [ecx]
-        jmp   cr_epilogue
-
-cr_retint64:
-        mov   eax, [ecx + 0]
-        mov   edx, [ecx + 4]
-        jmp   cr_epilogue
-
-cr_retfloat:
-        fld   DWORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retdouble:
-        fld   QWORD PTR [ecx]
-        jmp   cr_epilogue
-
-cr_retlongdouble:
-        fld   TBYTE PTR [ecx]
-        jmp   cr_epilogue
-
-cr_epilogue:
-        ;; Epilogue code is autogenerated.
-        ret
-ffi_closure_raw_SYSV ENDP
-
-#endif /* !FFI_NO_RAW_API */
-
-ffi_closure_STDCALL PROC NEAR FORCEFRAME
-        mov  eax, [esp] ;; the ffi_closure ctx passed by the trampoline.
-
-        sub  esp, 40
-        lea  edx, [ebp - 24]
-        mov  [ebp - 12], edx         ;; resp
-        lea  edx, [ebp + 12]         ;; account for stub return address on stack
-        mov  [esp + 8], edx          ;; args
-        lea  edx, [ebp - 12]
-        mov  [esp + 4], edx          ;; &resp
-        mov  [esp], eax              ;; closure
-        call ffi_closure_WIN32_inner
-        mov  ecx, [ebp - 12]
-
-        xchg [ebp + 4], eax          ;;xchg size of stack parameters and ffi_closure ctx
-        mov  eax, DWORD PTR [eax + CLOSURE_CIF_OFFSET]
-        mov  eax, DWORD PTR [eax + CIF_FLAGS_OFFSET]
-
-cd_jumptable:
-        jmp  [cd_jumpdata + 4 * eax]
-cd_jumpdata:
-        ;; Do not insert anything here between the label and jump table.
-        dd offset cd_epilogue       ;; FFI_TYPE_VOID
-        dd offset cd_retint         ;; FFI_TYPE_INT
-        dd offset cd_retfloat       ;; FFI_TYPE_FLOAT
-        dd offset cd_retdouble      ;; FFI_TYPE_DOUBLE
-        dd offset cd_retlongdouble  ;; FFI_TYPE_LONGDOUBLE
-        dd offset cd_retuint8       ;; FFI_TYPE_UINT8
-        dd offset cd_retsint8       ;; FFI_TYPE_SINT8
-        dd offset cd_retuint16      ;; FFI_TYPE_UINT16
-        dd offset cd_retsint16      ;; FFI_TYPE_SINT16
-        dd offset cd_retint         ;; FFI_TYPE_UINT32
-        dd offset cd_retint         ;; FFI_TYPE_SINT32
-        dd offset cd_retint64       ;; FFI_TYPE_UINT64
-        dd offset cd_retint64       ;; FFI_TYPE_SINT64
-        dd offset cd_epilogue       ;; FFI_TYPE_STRUCT
-        dd offset cd_retint         ;; FFI_TYPE_POINTER
-        dd offset cd_retsint8       ;; FFI_TYPE_SMALL_STRUCT_1B
-        dd offset cd_retsint16      ;; FFI_TYPE_SMALL_STRUCT_2B
-        dd offset cd_retint         ;; FFI_TYPE_SMALL_STRUCT_4B
-
-cd_retuint8:
-        movzx eax, BYTE PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retsint8:
-        movsx eax, BYTE PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retuint16:
-        movzx eax, WORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retsint16:
-        movsx eax, WORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retint:
-        mov   eax, [ecx]
-        jmp   cd_epilogue
-
-cd_retint64:
-        mov   eax, [ecx + 0]
-        mov   edx, [ecx + 4]
-        jmp   cd_epilogue
-
-cd_retfloat:
-        fld   DWORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retdouble:
-        fld   QWORD PTR [ecx]
-        jmp   cd_epilogue
-
-cd_retlongdouble:
-        fld   TBYTE PTR [ecx]
-        jmp   cd_epilogue
-
-cd_epilogue:
-        mov   esp, ebp
-        pop   ebp
-        mov   ecx, [esp + 4]  ;; Return address
-        add   esp, [esp]      ;; Parameters stack size
-        add   esp, 8
-        jmp   ecx
-ffi_closure_STDCALL ENDP
-
-_TEXT ENDS
-END
-
-#else
-
-#define CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-
-#if defined(SYMBOL_UNDERSCORE)
-#define USCORE_SYMBOL(x) _##x
-#else
-#define USCORE_SYMBOL(x) x
-#endif
-        .text
- 
-        # This assumes we are using gas.
-        .balign 16
-FFI_HIDDEN(ffi_call_win32)
-        .globl	USCORE_SYMBOL(ffi_call_win32)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_call_win32;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_call_win32):
-.LFB1:
-        pushl %ebp
-.LCFI0:
-        movl  %esp,%ebp
-.LCFI1:
-        # Make room for all of the new args.
-        movl  20(%ebp),%ecx                                                     
-        subl  %ecx,%esp
- 
-        movl  %esp,%eax
- 
-        # Call ffi_prep_args
-        pushl 12(%ebp)
-        pushl %eax
-        call  *8(%ebp)
-        addl  $8,%esp
-
-        # Prepare registers
-        # EAX stores the number of register arguments
-        cmpl  $0, %eax
-        je    .fun
-        cmpl  $3, %eax
-        jl    .prepr_two_cmp
-        
-        movl  %esp, %ecx
-        addl  $12, %esp
-        movl  8(%ecx), %eax
-        jmp   .prepr_two
-.prepr_two_cmp:
-        cmpl  $2, %eax
-        jl    .prepr_one_prep
-        movl  %esp, %ecx
-        addl  $8, %esp
-.prepr_two:
-        movl  4(%ecx), %edx
-        jmp   .prepr_one
-.prepr_one_prep:
-        movl  %esp, %ecx
-        addl  $4, %esp
-.prepr_one:
-        movl  (%ecx), %ecx
-        cmpl  $7, 16(%ebp) # FFI_REGISTER
-        jne   .fun
-
-        xchgl %eax, %ecx
-        
-.fun:
-        # FIXME: Align the stack to a 128-bit boundary to avoid
-        # potential performance hits.
-
-        # Call function
-        call  *32(%ebp)
- 
-        # stdcall functions pop arguments off the stack themselves
-
-        # Load %ecx with the return type code
-        movl  24(%ebp),%ecx
- 
-        # If the return value pointer is NULL, assume no return value.
-        cmpl  $0,28(%ebp)
-        jne   0f
- 
-        # Even if there is no space for the return value, we are
-        # obliged to handle floating-point values.
-        cmpl  $FFI_TYPE_FLOAT,%ecx
-        jne   .Lnoretval
-        fstp  %st(0)
- 
-        jmp   .Lepilogue
-
-0:
-        call 1f
-        # Do not insert anything here between the call and the jump table.
-.Lstore_table:
-        .long	.Lnoretval-.Lstore_table	/* FFI_TYPE_VOID */
-        .long	.Lretint-.Lstore_table		/* FFI_TYPE_INT */
-        .long	.Lretfloat-.Lstore_table	/* FFI_TYPE_FLOAT */
-        .long	.Lretdouble-.Lstore_table	/* FFI_TYPE_DOUBLE */
-        .long	.Lretlongdouble-.Lstore_table	/* FFI_TYPE_LONGDOUBLE */
-        .long	.Lretuint8-.Lstore_table	/* FFI_TYPE_UINT8 */
-        .long	.Lretsint8-.Lstore_table	/* FFI_TYPE_SINT8 */
-        .long	.Lretuint16-.Lstore_table	/* FFI_TYPE_UINT16 */
-        .long	.Lretsint16-.Lstore_table	/* FFI_TYPE_SINT16 */
-        .long	.Lretint-.Lstore_table		/* FFI_TYPE_UINT32 */
-        .long	.Lretint-.Lstore_table		/* FFI_TYPE_SINT32 */
-        .long	.Lretint64-.Lstore_table	/* FFI_TYPE_UINT64 */
-        .long	.Lretint64-.Lstore_table	/* FFI_TYPE_SINT64 */
-        .long	.Lretstruct-.Lstore_table	/* FFI_TYPE_STRUCT */
-        .long	.Lretint-.Lstore_table		/* FFI_TYPE_POINTER */
-        .long	.Lretstruct1b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_1B */
-        .long	.Lretstruct2b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_2B */
-        .long	.Lretstruct4b-.Lstore_table	/* FFI_TYPE_SMALL_STRUCT_4B */
-        .long	.Lretstruct-.Lstore_table	/* FFI_TYPE_MS_STRUCT */
-1:
-        shl	$2, %ecx
-        add	(%esp),%ecx
-        mov	(%ecx),%ecx
-        add	(%esp),%ecx
-        add	$4, %esp
-        jmp	*%ecx
-
-        /* Sign/zero extend as appropriate.  */
-.Lretsint8:
-        movsbl	%al, %eax
-        jmp	.Lretint
-
-.Lretsint16:
-        movswl	%ax, %eax
-        jmp	.Lretint
-
-.Lretuint8:
-        movzbl	%al, %eax
-        jmp	.Lretint
-
-.Lretuint16:
-        movzwl	%ax, %eax
-        jmp	.Lretint
-
-.Lretint:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        jmp   .Lepilogue
- 
-.Lretfloat:
-         # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        fstps (%ecx)
-        jmp   .Lepilogue
- 
-.Lretdouble:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        fstpl (%ecx)
-        jmp   .Lepilogue
- 
-.Lretlongdouble:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        fstpt (%ecx)
-        jmp   .Lepilogue
- 
-.Lretint64:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        movl  %edx,4(%ecx)
-        jmp   .Lepilogue
-
-.Lretstruct1b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movb  %al,0(%ecx)
-        jmp   .Lepilogue
- 
-.Lretstruct2b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movw  %ax,0(%ecx)
-        jmp   .Lepilogue
-
-.Lretstruct4b:
-        # Load %ecx with the pointer to storage for the return value
-        movl  28(%ebp),%ecx
-        movl  %eax,0(%ecx)
-        jmp   .Lepilogue
-
-.Lretstruct:
-        # Nothing to do!
- 
-.Lnoretval:
-.Lepilogue:
-        movl %ebp,%esp
-        popl %ebp
-        ret
-.ffi_call_win32_end:
-        .balign 16
-FFI_HIDDEN(ffi_closure_THISCALL)
-        .globl	USCORE_SYMBOL(ffi_closure_THISCALL)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_closure_THISCALL;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_closure_THISCALL):
-        /* Insert the register argument on the stack as the first argument */
-        xchg	%ecx, 4(%esp)
-        xchg	%ecx, (%esp)
-        push	%ecx
-        jmp	.ffi_closure_STDCALL_internal
-
-        .balign 16
-FFI_HIDDEN(ffi_closure_FASTCALL)
-        .globl	USCORE_SYMBOL(ffi_closure_FASTCALL)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_closure_FASTCALL;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_closure_FASTCALL):
-        /* Insert the 2 register arguments on the stack as the first two arguments */
-        xchg	%edx, 4(%esp)
-        xchg	%ecx, (%esp)
-        push	%edx
-        push	%ecx
-        jmp	.ffi_closure_STDCALL_internal
-FFI_HIDDEN(ffi_closure_REGISTER)
-        .globl	USCORE_SYMBOL(ffi_closure_REGISTER)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_closure_REGISTER;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_closure_REGISTER):
-        /* Insert the 3 register arguments on the stack as the first two arguments */
-        push	%eax
-        xchg	%ecx, 8(%esp)
-        xchg	%edx, 4(%esp)
-        push	%ecx
-        push	%edx
-        jmp	.ffi_closure_STDCALL_internal
-
-.LFE1:
-        # This assumes we are using gas.
-        .balign 16
-FFI_HIDDEN(ffi_closure_SYSV)
-#if defined(X86_WIN32)
-        .globl	USCORE_SYMBOL(ffi_closure_SYSV)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_closure_SYSV;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_closure_SYSV):
-#endif
-.LFB3:
-        pushl	%ebp
-.LCFI4:
-        movl	%esp, %ebp
-.LCFI5:
-        subl	$40, %esp
-        leal	-24(%ebp), %edx
-        movl	%edx, -12(%ebp)	/* resp */
-        leal	8(%ebp), %edx
-        movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
-        leal	-12(%ebp), %edx
-        movl	%edx, (%esp)	/* &resp */
-#if defined(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE) || !defined(__PIC__)
-        call	USCORE_SYMBOL(ffi_closure_SYSV_inner)
-#elif defined(X86_DARWIN)
-        calll	L_ffi_closure_SYSV_inner$stub
-#else
-        movl	%ebx, 8(%esp)
-        call	1f
-1:      popl	%ebx
-        addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-        call	ffi_closure_SYSV_inner@PLT
-        movl	8(%esp), %ebx
-#endif
-        movl	-12(%ebp), %ecx
-
-0:
-        call	1f
-        # Do not insert anything here between the call and the jump table.
-.Lcls_store_table:
-        .long	.Lcls_noretval-.Lcls_store_table	/* FFI_TYPE_VOID */
-        .long	.Lcls_retint-.Lcls_store_table		/* FFI_TYPE_INT */
-        .long	.Lcls_retfloat-.Lcls_store_table	/* FFI_TYPE_FLOAT */
-        .long	.Lcls_retdouble-.Lcls_store_table	/* FFI_TYPE_DOUBLE */
-        .long	.Lcls_retldouble-.Lcls_store_table	/* FFI_TYPE_LONGDOUBLE */
-        .long	.Lcls_retuint8-.Lcls_store_table	/* FFI_TYPE_UINT8 */
-        .long	.Lcls_retsint8-.Lcls_store_table	/* FFI_TYPE_SINT8 */
-        .long	.Lcls_retuint16-.Lcls_store_table	/* FFI_TYPE_UINT16 */
-        .long	.Lcls_retsint16-.Lcls_store_table	/* FFI_TYPE_SINT16 */
-        .long	.Lcls_retint-.Lcls_store_table		/* FFI_TYPE_UINT32 */
-        .long	.Lcls_retint-.Lcls_store_table		/* FFI_TYPE_SINT32 */
-        .long	.Lcls_retllong-.Lcls_store_table	/* FFI_TYPE_UINT64 */
-        .long	.Lcls_retllong-.Lcls_store_table	/* FFI_TYPE_SINT64 */
-        .long	.Lcls_retstruct-.Lcls_store_table	/* FFI_TYPE_STRUCT */
-        .long	.Lcls_retint-.Lcls_store_table		/* FFI_TYPE_POINTER */
-        .long	.Lcls_retstruct1-.Lcls_store_table	/* FFI_TYPE_SMALL_STRUCT_1B */
-        .long	.Lcls_retstruct2-.Lcls_store_table	/* FFI_TYPE_SMALL_STRUCT_2B */
-        .long	.Lcls_retstruct4-.Lcls_store_table	/* FFI_TYPE_SMALL_STRUCT_4B */
-        .long	.Lcls_retmsstruct-.Lcls_store_table	/* FFI_TYPE_MS_STRUCT */
-
-1:
-        shl	$2, %eax
-        add	(%esp),%eax
-        mov	(%eax),%eax
-        add	(%esp),%eax
-        add	$4, %esp
-        jmp	*%eax
-
-        /* Sign/zero extend as appropriate.  */
-.Lcls_retsint8:
-        movsbl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retsint16:
-        movswl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retuint8:
-        movzbl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retuint16:
-        movzwl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retint:
-        movl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retfloat:
-        flds	(%ecx)
-        jmp	.Lcls_epilogue
-
-.Lcls_retdouble:
-        fldl	(%ecx)
-        jmp	.Lcls_epilogue
-
-.Lcls_retldouble:
-        fldt	(%ecx)
-        jmp	.Lcls_epilogue
-
-.Lcls_retllong:
-        movl	(%ecx), %eax
-        movl	4(%ecx), %edx
-        jmp	.Lcls_epilogue
-
-.Lcls_retstruct1:
-        movsbl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retstruct2:
-        movswl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retstruct4:
-        movl	(%ecx), %eax
-        jmp	.Lcls_epilogue
-
-.Lcls_retstruct:
-        # Caller expects us to pop struct return value pointer hidden arg.
-        movl	%ebp, %esp
-        popl	%ebp
-        ret	$0x4
-
-.Lcls_retmsstruct:
-        # Caller expects us to return a pointer to the real return value.
-        mov	%ecx, %eax
-        # Caller doesn't expects us to pop struct return value pointer hidden arg.
-        jmp	.Lcls_epilogue
-
-.Lcls_noretval:
-.Lcls_epilogue:
-        movl	%ebp, %esp
-        popl	%ebp
-        ret
-.ffi_closure_SYSV_end:
-.LFE3:
-
-#if !FFI_NO_RAW_API
-
-#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-
-#ifdef X86_WIN32
-        .balign 16
-FFI_HIDDEN(ffi_closure_raw_THISCALL)
-        .globl	USCORE_SYMBOL(ffi_closure_raw_THISCALL)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_closure_raw_THISCALL;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_closure_raw_THISCALL):
-        pushl	%ebp
-        movl	%esp, %ebp
-        pushl	%esi
-        subl	$36, %esp
-        movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-        movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-        movl	%edx, 12(%esp)	/* user_data */
-        leal	12(%ebp), %edx	/* __builtin_dwarf_cfa () */
-        jmp	.stubraw
-#endif /* X86_WIN32 */
-
-        # This assumes we are using gas.
-        .balign 16
-#if defined(X86_WIN32)
-        .globl	USCORE_SYMBOL(ffi_closure_raw_SYSV)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_closure_raw_SYSV;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_closure_raw_SYSV):
-#endif /* defined(X86_WIN32) */
-.LFB4:
-        pushl	%ebp
-.LCFI6:
-        movl	%esp, %ebp
-.LCFI7:
-        pushl	%esi
-.LCFI8:
-        subl	$36, %esp
-        movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
-        movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-        movl	%edx, 12(%esp)	/* user_data */
-        leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
-.stubraw:
-        movl	%edx, 8(%esp)	/* raw_args */
-        leal	-24(%ebp), %edx
-        movl	%edx, 4(%esp)	/* &res */
-        movl	%esi, (%esp)	/* cif */
-        call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
-        movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
-0:
-        call	1f
-        # Do not insert anything here between the call and the jump table.
-.Lrcls_store_table:
-        .long	.Lrcls_noretval-.Lrcls_store_table	/* FFI_TYPE_VOID */
-        .long	.Lrcls_retint-.Lrcls_store_table	/* FFI_TYPE_INT */
-        .long	.Lrcls_retfloat-.Lrcls_store_table	/* FFI_TYPE_FLOAT */
-        .long	.Lrcls_retdouble-.Lrcls_store_table	/* FFI_TYPE_DOUBLE */
-        .long	.Lrcls_retldouble-.Lrcls_store_table	/* FFI_TYPE_LONGDOUBLE */
-        .long	.Lrcls_retuint8-.Lrcls_store_table	/* FFI_TYPE_UINT8 */
-        .long	.Lrcls_retsint8-.Lrcls_store_table	/* FFI_TYPE_SINT8 */
-        .long	.Lrcls_retuint16-.Lrcls_store_table	/* FFI_TYPE_UINT16 */
-        .long	.Lrcls_retsint16-.Lrcls_store_table	/* FFI_TYPE_SINT16 */
-        .long	.Lrcls_retint-.Lrcls_store_table	/* FFI_TYPE_UINT32 */
-        .long	.Lrcls_retint-.Lrcls_store_table	/* FFI_TYPE_SINT32 */
-        .long	.Lrcls_retllong-.Lrcls_store_table	/* FFI_TYPE_UINT64 */
-        .long	.Lrcls_retllong-.Lrcls_store_table	/* FFI_TYPE_SINT64 */
-        .long	.Lrcls_retstruct-.Lrcls_store_table	/* FFI_TYPE_STRUCT */
-        .long	.Lrcls_retint-.Lrcls_store_table	/* FFI_TYPE_POINTER */
-        .long	.Lrcls_retstruct1-.Lrcls_store_table	/* FFI_TYPE_SMALL_STRUCT_1B */
-        .long	.Lrcls_retstruct2-.Lrcls_store_table	/* FFI_TYPE_SMALL_STRUCT_2B */
-        .long	.Lrcls_retstruct4-.Lrcls_store_table	/* FFI_TYPE_SMALL_STRUCT_4B */
-        .long	.Lrcls_retstruct-.Lrcls_store_table	/* FFI_TYPE_MS_STRUCT */
-1:
-        shl	$2, %eax
-        add	(%esp),%eax
-        mov	(%eax),%eax
-        add	(%esp),%eax
-        add	$4, %esp
-        jmp	*%eax
-
-        /* Sign/zero extend as appropriate.  */
-.Lrcls_retsint8:
-        movsbl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retsint16:
-        movswl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retuint8:
-        movzbl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retuint16:
-        movzwl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retint:
-        movl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retfloat:
-        flds	-24(%ebp)
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retdouble:
-        fldl	-24(%ebp)
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retldouble:
-        fldt	-24(%ebp)
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retllong:
-        movl	-24(%ebp), %eax
-        movl	-20(%ebp), %edx
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct1:
-        movsbl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct2:
-        movswl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct4:
-        movl	-24(%ebp), %eax
-        jmp	.Lrcls_epilogue
-
-.Lrcls_retstruct:
-        # Nothing to do!
-
-.Lrcls_noretval:
-.Lrcls_epilogue:
-        addl	$36, %esp
-        popl	%esi
-        popl	%ebp
-        ret
-.ffi_closure_raw_SYSV_end:
-.LFE4:
-
-#endif /* !FFI_NO_RAW_API */
-
-        # This assumes we are using gas.
-        .balign	16
-FFI_HIDDEN(ffi_closure_STDCALL)
-        .globl	USCORE_SYMBOL(ffi_closure_STDCALL)
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .def	_ffi_closure_STDCALL;	.scl	2;	.type	32;	.endef
-#endif
-USCORE_SYMBOL(ffi_closure_STDCALL):
-.ffi_closure_STDCALL_internal:
-        /* ffi_closure ctx is at top of the stack */
-        movl	(%esp), %eax
-.LFB5:
-        pushl	%ebp
-.LCFI9:
-        movl	%esp, %ebp
-.LCFI10:
-        subl	$40, %esp
-        leal	-24(%ebp), %edx
-        movl	%edx, -12(%ebp)	/* resp */
-        leal	12(%ebp), %edx  /* account for stub return address on stack */
-        movl	%edx, 4(%esp)	/* args */
-        leal	-12(%ebp), %edx
-        movl	%edx, (%esp)	/* &resp */
-#if defined(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE) || !defined(__PIC__)
-        call	USCORE_SYMBOL(ffi_closure_WIN32_inner)
-#elif defined(X86_DARWIN)
-        calll	L_ffi_closure_WIN32_inner$stub
-#else
-        movl	%ebx, 8(%esp)
-        call	1f
-1:      popl	%ebx
-        addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-        call	ffi_closure_WIN32_inner@PLT
-        movl	8(%esp), %ebx
-#endif
-        movl	-12(%ebp), %ecx
-0:
-        xchgl	4(%ebp), %eax /* xchg size of stack parameters and ffi_closure ctx */
-        movl	CLOSURE_CIF_OFFSET(%eax), %eax
-        movl	CIF_FLAGS_OFFSET(%eax), %eax
-
-        call	1f
-        # Do not insert anything here between the call and the jump table.
-.Lscls_store_table:
-        .long	.Lscls_noretval-.Lscls_store_table	/* FFI_TYPE_VOID */
-        .long	.Lscls_retint-.Lscls_store_table	/* FFI_TYPE_INT */
-        .long	.Lscls_retfloat-.Lscls_store_table	/* FFI_TYPE_FLOAT */
-        .long	.Lscls_retdouble-.Lscls_store_table	/* FFI_TYPE_DOUBLE */
-        .long	.Lscls_retldouble-.Lscls_store_table	/* FFI_TYPE_LONGDOUBLE */
-        .long	.Lscls_retuint8-.Lscls_store_table	/* FFI_TYPE_UINT8 */
-        .long	.Lscls_retsint8-.Lscls_store_table	/* FFI_TYPE_SINT8 */
-        .long	.Lscls_retuint16-.Lscls_store_table	/* FFI_TYPE_UINT16 */
-        .long	.Lscls_retsint16-.Lscls_store_table	/* FFI_TYPE_SINT16 */
-        .long	.Lscls_retint-.Lscls_store_table	/* FFI_TYPE_UINT32 */
-        .long	.Lscls_retint-.Lscls_store_table	/* FFI_TYPE_SINT32 */
-        .long	.Lscls_retllong-.Lscls_store_table	/* FFI_TYPE_UINT64 */
-        .long	.Lscls_retllong-.Lscls_store_table	/* FFI_TYPE_SINT64 */
-        .long	.Lscls_retstruct-.Lscls_store_table	/* FFI_TYPE_STRUCT */
-        .long	.Lscls_retint-.Lscls_store_table	/* FFI_TYPE_POINTER */
-        .long	.Lscls_retstruct1-.Lscls_store_table	/* FFI_TYPE_SMALL_STRUCT_1B */
-        .long	.Lscls_retstruct2-.Lscls_store_table	/* FFI_TYPE_SMALL_STRUCT_2B */
-        .long	.Lscls_retstruct4-.Lscls_store_table	/* FFI_TYPE_SMALL_STRUCT_4B */
-1:
-        shl	$2, %eax
-        add	(%esp),%eax
-        mov	(%eax),%eax
-        add	(%esp),%eax
-        add	$4, %esp
-        jmp	*%eax
-
-        /* Sign/zero extend as appropriate.  */
-.Lscls_retsint8:
-        movsbl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retsint16:
-        movswl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retuint8:
-        movzbl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retuint16:
-        movzwl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retint:
-        movl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retfloat:
-        flds	(%ecx)
-        jmp	.Lscls_epilogue
-
-.Lscls_retdouble:
-        fldl	(%ecx)
-        jmp	.Lscls_epilogue
-
-.Lscls_retldouble:
-        fldt	(%ecx)
-        jmp	.Lscls_epilogue
-
-.Lscls_retllong:
-        movl	(%ecx), %eax
-        movl	4(%ecx), %edx
-        jmp	.Lscls_epilogue
-
-.Lscls_retstruct1:
-        movsbl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retstruct2:
-        movswl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retstruct4:
-        movl	(%ecx), %eax
-        jmp	.Lscls_epilogue
-
-.Lscls_retstruct:
-        # Nothing to do!
-
-.Lscls_noretval:
-.Lscls_epilogue:
-        movl	%ebp, %esp
-        popl	%ebp
-        movl	4(%esp), %ecx /* Return address */
-        addl	(%esp), %esp  /* Parameters stack size */
-        addl	$8, %esp
-        jmp	*%ecx
-.ffi_closure_STDCALL_end:
-.LFE5:
-
-#if defined(X86_DARWIN)
-.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
-L_ffi_closure_SYSV_inner$stub:
-        .indirect_symbol _ffi_closure_SYSV_inner
-        hlt ; hlt ; hlt ; hlt ; hlt
-L_ffi_closure_WIN32_inner$stub:
-        .indirect_symbol _ffi_closure_WIN32_inner
-        hlt ; hlt ; hlt ; hlt ; hlt
-#endif
-
-#if defined(X86_WIN32) && !defined(__OS2__)
-        .section	.eh_frame,"w"
-#endif
-.Lframe1:
-.LSCIE1:
-        .long	.LECIE1-.LASCIE1  /* Length of Common Information Entry */
-.LASCIE1:
-        .long	0x0	/* CIE Identifier Tag */
-        .byte	0x1	/* CIE Version */
-#ifdef __PIC__
-        .ascii "zR\0"	/* CIE Augmentation */
-#else
-        .ascii "\0"	/* CIE Augmentation */
-#endif
-        .byte	0x1	/* .uleb128 0x1; CIE Code Alignment Factor */
-        .byte	0x7c	/* .sleb128 -4; CIE Data Alignment Factor */
-        .byte	0x8	/* CIE RA Column */
-#ifdef __PIC__
-        .byte	0x1	/* .uleb128 0x1; Augmentation size */
-        .byte	0x1b	/* FDE Encoding (pcrel sdata4) */
-#endif
-        .byte	0xc	/* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
-        .byte	0x4	/* .uleb128 0x4 */
-        .byte	0x4	/* .uleb128 0x4 */
-        .byte	0x88	/* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
-        .byte	0x1	/* .uleb128 0x1 */
-        .align 4
-.LECIE1:
-
-.LSFDE1:
-        .long	.LEFDE1-.LASFDE1	/* FDE Length */
-.LASFDE1:
-        .long	.LASFDE1-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-        .long	.LFB1-.	/* FDE initial location */
-#else
-        .long	.LFB1
-#endif
-        .long	.LFE1-.LFB1	/* FDE address range */
-#ifdef __PIC__
-        .byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-        /* DW_CFA_xxx CFI instructions go here.  */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI0-.LFB1
-        .byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-        .byte	0x8	/* .uleb128 0x8 */
-        .byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-        .byte	0x2	/* .uleb128 0x2 */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI1-.LCFI0
-        .byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-        .byte	0x5	/* .uleb128 0x5 */
-
-        /* End of DW_CFA_xxx CFI instructions.  */
-        .align 4
-.LEFDE1:
-
-.LSFDE3:
-        .long	.LEFDE3-.LASFDE3	/* FDE Length */
-.LASFDE3:
-        .long	.LASFDE3-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-        .long	.LFB3-.	/* FDE initial location */
-#else
-        .long	.LFB3
-#endif
-        .long	.LFE3-.LFB3	/* FDE address range */
-#ifdef __PIC__
-        .byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-        /* DW_CFA_xxx CFI instructions go here.  */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI4-.LFB3
-        .byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-        .byte	0x8	/* .uleb128 0x8 */
-        .byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-        .byte	0x2	/* .uleb128 0x2 */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI5-.LCFI4
-        .byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-        .byte	0x5	/* .uleb128 0x5 */
-
-        /* End of DW_CFA_xxx CFI instructions.  */
-        .align 4
-.LEFDE3:
-
-#if !FFI_NO_RAW_API
-
-.LSFDE4:
-        .long	.LEFDE4-.LASFDE4	/* FDE Length */
-.LASFDE4:
-        .long	.LASFDE4-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-        .long	.LFB4-.	/* FDE initial location */
-#else
-        .long	.LFB4
-#endif
-        .long	.LFE4-.LFB4	/* FDE address range */
-#ifdef __PIC__
-        .byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-        /* DW_CFA_xxx CFI instructions go here.  */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI6-.LFB4
-        .byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-        .byte	0x8	/* .uleb128 0x8 */
-        .byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-        .byte	0x2	/* .uleb128 0x2 */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI7-.LCFI6
-        .byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-        .byte	0x5	/* .uleb128 0x5 */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI8-.LCFI7
-        .byte	0x86	/* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
-        .byte	0x3	/* .uleb128 0x3 */
-
-        /* End of DW_CFA_xxx CFI instructions.  */
-        .align 4
-.LEFDE4:
-
-#endif /* !FFI_NO_RAW_API */
-
-.LSFDE5:
-        .long	.LEFDE5-.LASFDE5	/* FDE Length */
-.LASFDE5:
-        .long	.LASFDE5-.Lframe1	/* FDE CIE offset */
-#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-        .long	.LFB5-.	/* FDE initial location */
-#else
-        .long	.LFB5
-#endif
-        .long	.LFE5-.LFB5	/* FDE address range */
-#ifdef __PIC__
-        .byte	0x0	/* .uleb128 0x0; Augmentation size */
-#endif
-        /* DW_CFA_xxx CFI instructions go here.  */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI9-.LFB5
-        .byte	0xe	/* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-        .byte	0x8	/* .uleb128 0x8 */
-        .byte	0x85	/* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-        .byte	0x2	/* .uleb128 0x2 */
-
-        .byte	0x4	/* DW_CFA_advance_loc4 */
-        .long	.LCFI10-.LCFI9
-        .byte	0xd	/* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-        .byte	0x5	/* .uleb128 0x5 */
-
-        /* End of DW_CFA_xxx CFI instructions.  */
-        .align 4
-.LEFDE5:
-
-#endif /* !_MSC_VER */
-
-#if defined __ELF__ && defined __linux__
-        .section	.note.GNU-stack,"",@progbits
-#endif
-- 
1.9.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]