]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libffi/40807 (libffi.call/return_sc.c)
authorDave Korn <dave.korn.cygwin@gmail.com>
Fri, 24 Jul 2009 10:12:16 +0000 (10:12 +0000)
committerDave Korn <davek@gcc.gnu.org>
Fri, 24 Jul 2009 10:12:16 +0000 (10:12 +0000)
PR libffi/40807
* src/x86/ffi.c (ffi_prep_cif_machdep): Also use sign/zero-extending
return types for X86_WIN32.
* src/x86/win32.S (_ffi_call_SYSV): Handle omitted return types.
(_ffi_call_STDCALL, _ffi_closure_SYSV, _ffi_closure_raw_SYSV,
_ffi_closure_STDCALL): Likewise.

* src/closures.c (is_selinux_enabled): Define to const 0 for Cygwin.
(dlmmap, dlmunmap): Also use these functions on Cygwin.

From-SVN: r150042

libffi/ChangeLog
libffi/src/closures.c
libffi/src/x86/ffi.c
libffi/src/x86/win32.S

index 7ba04c24e542e61375b364f262ca8127d0d02ef2..9af1e445e7276769131a896d18021dd341fac7d9 100644 (file)
@@ -1,3 +1,15 @@
+2009-07-24  Dave Korn  <dave.korn.cygwin@gmail.com>
+
+       PR libffi/40807
+       * src/x86/ffi.c (ffi_prep_cif_machdep): Also use sign/zero-extending
+       return types for X86_WIN32.
+       * src/x86/win32.S (_ffi_call_SYSV): Handle omitted return types.
+       (_ffi_call_STDCALL, _ffi_closure_SYSV, _ffi_closure_raw_SYSV,
+       _ffi_closure_STDCALL): Likewise.
+
+       * src/closures.c (is_selinux_enabled): Define to const 0 for Cygwin.
+       (dlmmap, dlmunmap): Also use these functions on Cygwin.
+
 2009-07-11  Richard Sandiford  <rdsandiford@googlemail.com>
 
        PR testsuite/40699
index 7692c857162630b0c4abe7e021c2ee163ad41477..f07ad06bf33b0769c77910e1a4c924bc429852f6 100644 (file)
@@ -165,7 +165,15 @@ selinux_enabled_check (void)
 
 #define is_selinux_enabled() 0
 
-#endif
+#endif /* !FFI_MMAP_EXEC_SELINUX */
+
+#elif defined (__CYGWIN__)
+
+#include <sys/mman.h>
+
+/* Cygwin is Linux-like, but not quite that Linux-like.  */
+#define is_selinux_enabled() 0
+
 #endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
 
 /* Declare all functions defined in dlmalloc.c as static.  */
@@ -185,11 +193,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED;
 static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
 static void dlmalloc_stats(void) MAYBE_UNUSED;
 
-#if !defined(X86_WIN32) && !defined(X86_WIN64)
+#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
 /* Use these for mmap and munmap within dlmalloc.c.  */
 static void *dlmmap(void *, size_t, int, int, int, off_t);
 static int dlmunmap(void *, size_t);
-#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
 
 #define mmap dlmmap
 #define munmap dlmunmap
@@ -199,7 +207,7 @@ static int dlmunmap(void *, size_t);
 #undef mmap
 #undef munmap
 
-#if !defined(X86_WIN32) && !defined(X86_WIN64)
+#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
 
 /* A mutex used to synchronize access to *exec* variables in this file.  */
 static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -514,7 +522,7 @@ segment_holding_code (mstate m, char* addr)
 }
 #endif
 
-#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
 
 /* Allocate a chunk of memory with the given size.  Returns a pointer
    to the writable address, and sets *CODE to the executable
index c89c8fc747568a6c96bd9b86831d5743bfa2856a..a5f506db19cd864f2ff0a4be8961dcb350706771 100644 (file)
@@ -155,7 +155,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 #ifdef X86
     case FFI_TYPE_STRUCT:
 #endif
-#if defined(X86) || defined(X86_DARWIN) || defined(X86_WIN64)
+#if defined(X86) || defined (X86_WIN32) || defined(X86_DARWIN) || defined(X86_WIN64)
     case FFI_TYPE_UINT8:
     case FFI_TYPE_UINT16:
     case FFI_TYPE_SINT8:
index a1de858d96ae041a80415e0147082ca13fbbae5b..7489dab19c432ba3f30e639e581727aab96c6dfb 100644 (file)
@@ -63,86 +63,121 @@ _ffi_call_SYSV:
 
        call  *28(%ebp)
  
-        # Remove the space we pushed for the args
-        movl  16(%ebp),%ecx
-        addl  %ecx,%esp
         # Load %ecx with the return type code
         movl  20(%ebp),%ecx
  
         # If the return value pointer is NULL, assume no return value.
         cmpl  $0,24(%ebp)
-        jne   retint
+        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
+        jne   .Lnoretval
         fstp  %st(0)
  
-        jmp   epilogue
-retint:
-        cmpl  $FFI_TYPE_INT,%ecx
-        jne   retfloat
+        jmp   .Lepilogue
+
+0:
+       call    1f
+       # Do not insert anything here between the call and the jump table.
+.Lstore_table:
+       .long   .Lnoretval              /* FFI_TYPE_VOID */
+       .long   .Lretint                /* FFI_TYPE_INT */
+       .long   .Lretfloat              /* FFI_TYPE_FLOAT */
+       .long   .Lretdouble             /* FFI_TYPE_DOUBLE */
+       .long   .Lretlongdouble         /* FFI_TYPE_LONGDOUBLE */
+       .long   .Lretuint8              /* FFI_TYPE_UINT8 */
+       .long   .Lretsint8              /* FFI_TYPE_SINT8 */
+       .long   .Lretuint16             /* FFI_TYPE_UINT16 */
+       .long   .Lretsint16             /* FFI_TYPE_SINT16 */
+       .long   .Lretint                /* FFI_TYPE_UINT32 */
+       .long   .Lretint                /* FFI_TYPE_SINT32 */
+       .long   .Lretint64              /* FFI_TYPE_UINT64 */
+       .long   .Lretint64              /* FFI_TYPE_SINT64 */
+       .long   .Lretstruct             /* FFI_TYPE_STRUCT */
+       .long   .Lretint                /* FFI_TYPE_POINTER */
+       .long   .Lretstruct1b           /* FFI_TYPE_SMALL_STRUCT_1B */
+       .long   .Lretstruct2b           /* FFI_TYPE_SMALL_STRUCT_2B */
+       .long   .Lretstruct4b           /* FFI_TYPE_SMALL_STRUCT_4B */
+1:
+       add     %ecx, %ecx
+       add     %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  24(%ebp),%ecx
         movl  %eax,0(%ecx)
-        jmp   epilogue
+        jmp   .Lepilogue
  
-retfloat:
-        cmpl  $FFI_TYPE_FLOAT,%ecx
-        jne   retdouble   
+.Lretfloat:
          # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         fstps (%ecx)
-        jmp   epilogue
+        jmp   .Lepilogue
  
-retdouble:
-        cmpl  $FFI_TYPE_DOUBLE,%ecx
-        jne   retlongdouble
+.Lretdouble:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         fstpl (%ecx)
-        jmp   epilogue
+        jmp   .Lepilogue
  
-retlongdouble:
-        cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
-        jne   retint64
+.Lretlongdouble:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         fstpt (%ecx)
-        jmp   epilogue
+        jmp   .Lepilogue
  
-retint64:
-        cmpl  $FFI_TYPE_SINT64,%ecx
-        jne   retstruct1b
+.Lretint64:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         movl  %eax,0(%ecx)
         movl  %edx,4(%ecx)
-retstruct1b:
-        cmpl  $FFI_TYPE_SINT8,%ecx
-        jne   retstruct2b
+       jmp   .Lepilogue
+
+.Lretstruct1b:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         movb  %al,0(%ecx)
-        jmp   epilogue
+        jmp   .Lepilogue
  
-retstruct2b:
-        cmpl  $FFI_TYPE_SINT16,%ecx
-        jne   retstruct
+.Lretstruct2b:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         movw  %ax,0(%ecx)
-        jmp   epilogue
-retstruct:
+        jmp   .Lepilogue
+
+.Lretstruct4b:
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        jmp   .Lepilogue
+
+.Lretstruct:
         # Nothing to do!
  
-noretval:
-epilogue:
+.Lnoretval:
+.Lepilogue:
         movl %ebp,%esp
         popl %ebp
         ret
@@ -185,77 +220,117 @@ _ffi_call_STDCALL:
 
         # If the return value pointer is NULL, assume no return value.
         cmpl  $0,24(%ebp)
-        jne   sc_retint
+        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   sc_noretval
+        jne   .Lsc_noretval
         fstp  %st(0)
 
-        jmp   sc_epilogue
-
-sc_retint:
-        cmpl  $FFI_TYPE_INT,%ecx
-        jne   sc_retfloat
+        jmp   .Lsc_epilogue
+
+0:
+       call    1f
+       # Do not insert anything here between the call and the jump table.
+.Lsc_store_table:
+       .long   .Lsc_noretval           /* FFI_TYPE_VOID */
+       .long   .Lsc_retint             /* FFI_TYPE_INT */
+       .long   .Lsc_retfloat           /* FFI_TYPE_FLOAT */
+       .long   .Lsc_retdouble          /* FFI_TYPE_DOUBLE */
+       .long   .Lsc_retlongdouble      /* FFI_TYPE_LONGDOUBLE */
+       .long   .Lsc_retuint8           /* FFI_TYPE_UINT8 */
+       .long   .Lsc_retsint8           /* FFI_TYPE_SINT8 */
+       .long   .Lsc_retuint16          /* FFI_TYPE_UINT16 */
+       .long   .Lsc_retsint16          /* FFI_TYPE_SINT16 */
+       .long   .Lsc_retint             /* FFI_TYPE_UINT32 */
+       .long   .Lsc_retint             /* FFI_TYPE_SINT32 */
+       .long   .Lsc_retint64           /* FFI_TYPE_UINT64 */
+       .long   .Lsc_retint64           /* FFI_TYPE_SINT64 */
+       .long   .Lsc_retstruct          /* FFI_TYPE_STRUCT */
+       .long   .Lsc_retint             /* FFI_TYPE_POINTER */
+       .long   .Lsc_retstruct1b        /* FFI_TYPE_SMALL_STRUCT_1B */
+       .long   .Lsc_retstruct2b        /* FFI_TYPE_SMALL_STRUCT_2B */
+       .long   .Lsc_retstruct4b        /* FFI_TYPE_SMALL_STRUCT_4B */
+
+1:
+       add     %ecx, %ecx
+       add     %ecx, %ecx
+       add     (%esp),%ecx
+       add     $4, %esp
+       jmp     *(%ecx)
+
+       /* Sign/zero extend as appropriate.  */
+.Lsc_retsint8:
+       movsbl  %al, %eax
+       jmp     .Lsc_retint
+
+.Lsc_retsint16:
+       movswl  %ax, %eax
+       jmp     .Lsc_retint
+
+.Lsc_retuint8:
+       movzbl  %al, %eax
+       jmp     .Lsc_retint
+
+.Lsc_retuint16:
+       movzwl  %ax, %eax
+       jmp     .Lsc_retint
+
+.Lsc_retint:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         movl  %eax,0(%ecx)
-        jmp   sc_epilogue
+        jmp   .Lsc_epilogue
 
-sc_retfloat:
-        cmpl  $FFI_TYPE_FLOAT,%ecx
-        jne   sc_retdouble
+.Lsc_retfloat:
          # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         fstps (%ecx)
-        jmp   sc_epilogue
+        jmp   .Lsc_epilogue
 
-sc_retdouble:
-        cmpl  $FFI_TYPE_DOUBLE,%ecx
-        jne   sc_retlongdouble
+.Lsc_retdouble:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         fstpl (%ecx)
-        jmp   sc_epilogue
+        jmp   .Lsc_epilogue
 
-sc_retlongdouble:
-        cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
-        jne   sc_retint64
+.Lsc_retlongdouble:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         fstpt (%ecx)
-        jmp   sc_epilogue
+        jmp   .Lsc_epilogue
 
-sc_retint64:
-        cmpl  $FFI_TYPE_SINT64,%ecx
-        jne   sc_retstruct1b
+.Lsc_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   .Lsc_epilogue
 
-sc_retstruct1b:
-        cmpl  $FFI_TYPE_SINT8,%ecx
-        jne   sc_retstruct2b
+.Lsc_retstruct1b:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         movb  %al,0(%ecx)
-        jmp   sc_epilogue
+        jmp   .Lsc_epilogue
 
-sc_retstruct2b:
-        cmpl  $FFI_TYPE_SINT16,%ecx
-        jne   sc_retstruct
+.Lsc_retstruct2b:
         # Load %ecx with the pointer to storage for the return value
         movl  24(%ebp),%ecx
         movw  %ax,0(%ecx)
-        jmp   sc_epilogue
+        jmp   .Lsc_epilogue
+
+.Lsc_retstruct4b:
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        jmp   .Lsc_epilogue
 
-sc_retstruct:
+.Lsc_retstruct:
         # Nothing to do!
 
-sc_noretval:
-sc_epilogue:
+.Lsc_noretval:
+.Lsc_epilogue:
         movl %ebp,%esp
         popl %ebp
         ret
@@ -281,46 +356,98 @@ _ffi_closure_SYSV:
        movl    %edx, (%esp)    /* &resp */
        call    _ffi_closure_SYSV_inner
        movl    -12(%ebp), %ecx
-       cmpl    $FFI_TYPE_INT, %eax
-       je      .Lcls_retint
-       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_SINT8, %eax   /* 1-byte struct */
-       je      .Lcls_retstruct1
-       cmpl    $FFI_TYPE_SINT16, %eax  /* 2-bytes struct */
-       je      .Lcls_retstruct2
-.Lcls_epilogue:
-       movl    %ebp, %esp
-       popl    %ebp
-       ret
+
+0:
+       call    1f
+       # Do not insert anything here between the call and the jump table.
+.Lcls_store_table:
+       .long   .Lcls_noretval          /* FFI_TYPE_VOID */
+       .long   .Lcls_retint            /* FFI_TYPE_INT */
+       .long   .Lcls_retfloat          /* FFI_TYPE_FLOAT */
+       .long   .Lcls_retdouble         /* FFI_TYPE_DOUBLE */
+       .long   .Lcls_retldouble        /* FFI_TYPE_LONGDOUBLE */
+       .long   .Lcls_retuint8          /* FFI_TYPE_UINT8 */
+       .long   .Lcls_retsint8          /* FFI_TYPE_SINT8 */
+       .long   .Lcls_retuint16         /* FFI_TYPE_UINT16 */
+       .long   .Lcls_retsint16         /* FFI_TYPE_SINT16 */
+       .long   .Lcls_retint            /* FFI_TYPE_UINT32 */
+       .long   .Lcls_retint            /* FFI_TYPE_SINT32 */
+       .long   .Lcls_retllong          /* FFI_TYPE_UINT64 */
+       .long   .Lcls_retllong          /* FFI_TYPE_SINT64 */
+       .long   .Lcls_retstruct         /* FFI_TYPE_STRUCT */
+       .long   .Lcls_retint            /* FFI_TYPE_POINTER */
+       .long   .Lcls_retstruct1        /* FFI_TYPE_SMALL_STRUCT_1B */
+       .long   .Lcls_retstruct2        /* FFI_TYPE_SMALL_STRUCT_2B */
+       .long   .Lcls_retstruct4        /* FFI_TYPE_SMALL_STRUCT_4B */
+
+1:
+       add     %eax, %eax
+       add     %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_noretval:
+.Lcls_epilogue:
+       movl    %ebp, %esp
+       popl    %ebp
+       ret
 .ffi_closure_SYSV_end:
 .LFE3:
 
@@ -354,37 +481,94 @@ _ffi_closure_raw_SYSV:
        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
-       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
+0:
+       call    1f
+       # Do not insert anything here between the call and the jump table.
+.Lrcls_store_table:
+       .long   .Lrcls_noretval         /* FFI_TYPE_VOID */
+       .long   .Lrcls_retint           /* FFI_TYPE_INT */
+       .long   .Lrcls_retfloat         /* FFI_TYPE_FLOAT */
+       .long   .Lrcls_retdouble        /* FFI_TYPE_DOUBLE */
+       .long   .Lrcls_retldouble       /* FFI_TYPE_LONGDOUBLE */
+       .long   .Lrcls_retuint8         /* FFI_TYPE_UINT8 */
+       .long   .Lrcls_retsint8         /* FFI_TYPE_SINT8 */
+       .long   .Lrcls_retuint16        /* FFI_TYPE_UINT16 */
+       .long   .Lrcls_retsint16        /* FFI_TYPE_SINT16 */
+       .long   .Lrcls_retint           /* FFI_TYPE_UINT32 */
+       .long   .Lrcls_retint           /* FFI_TYPE_SINT32 */
+       .long   .Lrcls_retllong         /* FFI_TYPE_UINT64 */
+       .long   .Lrcls_retllong         /* FFI_TYPE_SINT64 */
+       .long   .Lrcls_retstruct        /* FFI_TYPE_STRUCT */
+       .long   .Lrcls_retint           /* FFI_TYPE_POINTER */
+       .long   .Lrcls_retstruct1       /* FFI_TYPE_SMALL_STRUCT_1B */
+       .long   .Lrcls_retstruct2       /* FFI_TYPE_SMALL_STRUCT_2B */
+       .long   .Lrcls_retstruct4       /* FFI_TYPE_SMALL_STRUCT_4B */
+1:
+       add     %eax, %eax
+       add     %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:
 
@@ -409,49 +593,93 @@ _ffi_closure_STDCALL:
        movl    %edx, (%esp)    /* &resp */
        call    _ffi_closure_SYSV_inner
        movl    -12(%ebp), %ecx
-       /* It would be nice to just share this code with the
-          duplicate sequence in _ffi_closure_SYSV, if only
-          there were some way to represent that in the EH info.  */
-       cmpl    $FFI_TYPE_INT, %eax
-       je      .Lscls_retint
-       cmpl    $FFI_TYPE_FLOAT, %eax
-       je      .Lscls_retfloat
-       cmpl    $FFI_TYPE_DOUBLE, %eax
-       je      .Lscls_retdouble
-       cmpl    $FFI_TYPE_LONGDOUBLE, %eax
-       je      .Lscls_retldouble
-       cmpl    $FFI_TYPE_SINT64, %eax
-       je      .Lscls_retllong
-       cmpl    $FFI_TYPE_SINT8, %eax   /* 1-byte struct */
-       je      .Lscls_retstruct1
-       cmpl    $FFI_TYPE_SINT16, %eax  /* 2-bytes struct */
-       je      .Lscls_retstruct2
-.Lscls_epilogue:
-       movl    %ebp, %esp
-       popl    %ebp
-       ret
+0:
+       call    1f
+       # Do not insert anything here between the call and the jump table.
+.Lscls_store_table:
+       .long   .Lscls_noretval         /* FFI_TYPE_VOID */
+       .long   .Lscls_retint           /* FFI_TYPE_INT */
+       .long   .Lscls_retfloat         /* FFI_TYPE_FLOAT */
+       .long   .Lscls_retdouble        /* FFI_TYPE_DOUBLE */
+       .long   .Lscls_retldouble       /* FFI_TYPE_LONGDOUBLE */
+       .long   .Lscls_retuint8         /* FFI_TYPE_UINT8 */
+       .long   .Lscls_retsint8         /* FFI_TYPE_SINT8 */
+       .long   .Lscls_retuint16        /* FFI_TYPE_UINT16 */
+       .long   .Lscls_retsint16        /* FFI_TYPE_SINT16 */
+       .long   .Lscls_retint           /* FFI_TYPE_UINT32 */
+       .long   .Lscls_retint           /* FFI_TYPE_SINT32 */
+       .long   .Lscls_retllong         /* FFI_TYPE_UINT64 */
+       .long   .Lscls_retllong         /* FFI_TYPE_SINT64 */
+       .long   .Lscls_retstruct        /* FFI_TYPE_STRUCT */
+       .long   .Lscls_retint           /* FFI_TYPE_POINTER */
+       .long   .Lscls_retstruct1       /* FFI_TYPE_SMALL_STRUCT_1B */
+       .long   .Lscls_retstruct2       /* FFI_TYPE_SMALL_STRUCT_2B */
+       .long   .Lscls_retstruct4       /* FFI_TYPE_SMALL_STRUCT_4B */
+1:
+       add     %eax, %eax
+       add     %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
+       ret
 .ffi_closure_STDCALL_end:
 .LFE5: