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.
This commit is contained in:
Richard Henderson
2014-11-05 10:15:25 +01:00
parent b9ac94f3af
commit b21ec1ce78
6 changed files with 600 additions and 2243 deletions

View File

@@ -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

View File

@@ -321,225 +321,106 @@ 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 *);
void FFI_HIDDEN ffi_closure_i386(void);
void FFI_HIDDEN ffi_closure_STDCALL(void);
void FFI_HIDDEN ffi_closure_REGISTER(void);
/* This function is jumped to by the trampoline */
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;
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 */
};
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 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;
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;
cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * 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);
/* 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;
}
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))
switch (flags)
{
if (passed_regs < max_stack_count)
case X86_RET_STRUCTARG:
if (pabi->nregs > 0)
{
*rvalue = *(void**) (stack + (passed_regs*FFI_SIZEOF_ARG));
++passed_regs;
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;
}
n = cif->nargs;
avalue = alloca(sizeof(void *) * n);
arg_types = cif->arg_types;
for (i = 0; i < n; ++i)
{
size_t z = arg_types[i]->size;
int t = arg_types[i]->type;
void *valp;
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
{
*rvalue = *(void **) argp;
argp += sizeof(void *);
valp = argp;
argp += 4;
}
}
/* Do register arguments first */
for (i = 0, p_arg = cif->arg_types;
i < cif->nargs && passed_regs < max_stack_count;
i++, p_arg++)
else
{
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;
}
p_arg = cif->arg_types;
p_argv = avalue;
size_t za = ALIGN (z, FFI_SIZEOF_ARG);
if (dir < 0)
{
const int nargs = cif->nargs - 1;
if (nargs > 0)
{
p_arg += nargs;
p_argv += nargs;
}
}
for (i = cif->nargs;
i != 0;
i--, p_arg += dir, p_argv += dir)
{
/* Align if necessary */
if ((sizeof(void*) - 1) & (size_t) argp)
argp = (char *) ALIGN(argp, sizeof(void*));
size_t z = (*p_arg)->size;
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;
argp -= za;
valp = argp;
}
else
{
/* because we're little endian, this is what it turns into. */
*p_argv = (void*) argp;
valp = argp;
argp += za;
}
}
argp += z;
avalue[i] = valp;
}
return (size_t)argp - (size_t)stack;
frame->fun (cif, rvalue, avalue, frame->user_data);
if (cabi == FFI_STDCALL)
return flags + (cif->bytes << X86_RET_POP_SHIFT);
else
return flags;
}
/* 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 */
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
@@ -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;
}
/* 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->user_data = user_data;
closure->fun = fun;
closure->user_data = user_data;
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--)
switch (cif->arg_types[i]->type)
{
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
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;

View File

@@ -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

View File

@@ -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

View File

@@ -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
cfi_restore(%ebx)
call C(ffi_closure_inner)@PLT
#endif
movl -12(%ebp), %ecx
cmpl $FFI_TYPE_INT, %eax
je .Lcls_retint
.endm
/* 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
.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
jmp *%eax
.endm
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
/* 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
.size ffi_closure_SYSV, .-ffi_closure_SYSV
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
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
#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)
#endif
#define CIF_FLAGS_OFFSET 20
#define raw_closure_S_FS (16+16+12)
.align 4
FFI_HIDDEN (ffi_closure_raw_SYSV)
.globl ffi_closure_raw_SYSV
.type ffi_closure_raw_SYSV, @function
ffi_closure_raw_SYSV:
.align 16
.globl C(ffi_closure_raw_SYSV)
FFI_HIDDEN(C(ffi_closure_raw_SYSV))
C(ffi_closure_raw_SYSV):
cfi_startproc
pushl %ebp
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
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)
/* 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
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
leal 0f(,%eax, 8), %eax
#endif
movl raw_closure_S_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
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
.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
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
cfi_endproc
.size ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
ENDF(C(ffi_closure_raw_SYSV))
#undef raw_closure_S_FS
#define raw_closure_T_FS (16+16+8)
.align 16
.globl C(ffi_closure_raw_THISCALL)
FFI_HIDDEN(C(ffi_closure_raw_THISCALL))
C(ffi_closure_raw_THISCALL):
cfi_startproc
/* 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)
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:
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
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

File diff suppressed because it is too large Load Diff