diff options
author | Anthony Green <green@moxielogic.com> | 2014-09-18 19:10:54 -0400 |
---|---|---|
committer | Anthony Green <green@moxielogic.com> | 2014-09-18 19:10:54 -0400 |
commit | 4c5c4088aa3e4d8103ff9ca441937da64fdd849a (patch) | |
tree | a2a1ab5accf4a804d37a3ab918b7a5b4fd28d76c | |
parent | 862f53de04ff898a128be7eec592bae60930d6df (diff) | |
parent | 5d6340ef2cf81432da79ac8b0b1b1218ab391438 (diff) | |
download | libffi-4c5c4088aa3e4d8103ff9ca441937da64fdd849a.tar.gz |
Merge pull request #132 from nielsAD/master
Pascal and Register calling convention support on x86
-rw-r--r-- | src/x86/ffi.c | 494 | ||||
-rw-r--r-- | src/x86/ffitarget.h | 6 | ||||
-rw-r--r-- | src/x86/win32.S | 1063 |
3 files changed, 842 insertions, 721 deletions
diff --git a/src/x86/ffi.c b/src/x86/ffi.c index 64b19ec..680456b 100644 --- a/src/x86/ffi.c +++ b/src/x86/ffi.c @@ -43,19 +43,21 @@ /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ -void ffi_prep_args(char *stack, extended_cif *ecif); -void ffi_prep_args(char *stack, extended_cif *ecif) +unsigned int ffi_prep_args(char *stack, extended_cif *ecif); +unsigned int ffi_prep_args(char *stack, extended_cif *ecif) { register unsigned int i; register void **p_argv; register char *argp; register ffi_type **p_arg; #ifndef X86_WIN64 - size_t p_stack_args[2]; - void *p_stack_data[2]; + const int cabi = ecif->cif->abi; + const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1; + unsigned int stack_args_count = 0; + void *p_stack_data[3]; char *argp2 = stack; - int stack_args_count = 0; - int cabi = ecif->cif->abi; +#else + #define dir 1 #endif argp = stack; @@ -63,48 +65,56 @@ void ffi_prep_args(char *stack, extended_cif *ecif) if ((ecif->cif->flags == FFI_TYPE_STRUCT || ecif->cif->flags == FFI_TYPE_MS_STRUCT) #ifdef X86_WIN64 - && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2 - && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8) + && ((ecif->cif->rtype->size & (1 | 2 | 4 | 8)) == 0) #endif ) { - *(void **) argp = ecif->rvalue; #ifndef X86_WIN64 - /* For fastcall/thiscall this is first register-passed + /* For fastcall/thiscall/register this is first register-passed argument. */ - if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL) - { - p_stack_args[stack_args_count] = sizeof (void*); - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } + if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL || cabi == FFI_REGISTER) + { + p_stack_data[stack_args_count] = argp; + ++stack_args_count; + } #endif + + *(void **) argp = ecif->rvalue; argp += sizeof(void*); } + p_arg = ecif->cif->arg_types; p_argv = ecif->avalue; + if (dir < 0) + { + const int nargs = ecif->cif->nargs - 1; + if (nargs > 0) + { + p_arg += nargs; + p_argv += nargs; + } + } - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + for (i = ecif->cif->nargs; i != 0; - i--, p_arg++) + i--, p_arg += dir, p_argv += dir) { - size_t z; - /* Align if necessary */ if ((sizeof(void*) - 1) & (size_t) argp) argp = (char *) ALIGN(argp, sizeof(void*)); - z = (*p_arg)->size; + size_t z = (*p_arg)->size; + #ifdef X86_WIN64 - if (z > sizeof(ffi_arg) + if (z > FFI_SIZEOF_ARG || ((*p_arg)->type == FFI_TYPE_STRUCT - && (z != 1 && z != 2 && z != 4 && z != 8)) + && (z & (1 | 2 | 4 | 8)) == 0) #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE) #endif ) { - z = sizeof(ffi_arg); + z = FFI_SIZEOF_ARG; *(void **)argp = *p_argv; } else if ((*p_arg)->type == FFI_TYPE_FLOAT) @@ -113,9 +123,9 @@ void ffi_prep_args(char *stack, extended_cif *ecif) } else #endif - if (z < sizeof(ffi_arg)) + if (z < FFI_SIZEOF_ARG) { - z = sizeof(ffi_arg); + z = FFI_SIZEOF_ARG; switch ((*p_arg)->type) { case FFI_TYPE_SINT8: @@ -156,23 +166,30 @@ void ffi_prep_args(char *stack, extended_cif *ecif) } #ifndef X86_WIN64 - /* For thiscall/fastcall convention register-passed arguments + /* For thiscall/fastcall/register convention register-passed arguments are the first two none-floating-point arguments with a size smaller or equal to sizeof (void*). */ - if ((cabi == FFI_THISCALL && stack_args_count < 1) - || (cabi == FFI_FASTCALL && stack_args_count < 2)) + if ((z == FFI_SIZEOF_ARG) + && ((cabi == FFI_REGISTER) + || (cabi == FFI_THISCALL && stack_args_count < 1) + || (cabi == FFI_FASTCALL && stack_args_count < 2)) + && ((*p_arg)->type != FFI_TYPE_FLOAT && (*p_arg)->type != FFI_TYPE_STRUCT) + ) { - if (z <= 4 - && ((*p_arg)->type != FFI_TYPE_FLOAT - && (*p_arg)->type != FFI_TYPE_STRUCT)) - { - p_stack_args[stack_args_count] = z; - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } + if (dir < 0 && stack_args_count > 2) + { + /* Iterating arguments backwards, so first register-passed argument + will be passed last. Shift temporary values to make place. */ + p_stack_data[0] = p_stack_data[1]; + p_stack_data[1] = p_stack_data[2]; + stack_args_count = 2; + } + + p_stack_data[stack_args_count] = argp; + ++stack_args_count; } #endif - p_argv++; + #ifdef X86_WIN64 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); #else @@ -181,44 +198,35 @@ void ffi_prep_args(char *stack, extended_cif *ecif) } #ifndef X86_WIN64 - /* We need to move the register-passed arguments for thiscall/fastcall - on top of stack, so that those can be moved to registers ecx/edx by - call-handler. */ + /* We need to move the register-passed arguments for thiscall/fastcall/register + on top of stack, so that those can be moved to registers by call-handler. */ if (stack_args_count > 0) { - size_t zz = (p_stack_args[0] + 3) & ~3; - char *h; - - /* Move first argument to top-stack position. */ - if (p_stack_data[0] != argp2) - { - h = alloca (zz + 1); - memcpy (h, p_stack_data[0], zz); - memmove (argp2 + zz, argp2, - (size_t) ((char *) p_stack_data[0] - (char*)argp2)); - memcpy (argp2, h, zz); - } - - argp2 += zz; - --stack_args_count; - if (zz > 4) - stack_args_count = 0; - - /* If we have a second argument, then move it on top - after the first one. */ - if (stack_args_count > 0 && p_stack_data[1] != argp2) - { - zz = p_stack_args[1]; - zz = (zz + 3) & ~3; - h = alloca (zz + 1); - h = alloca (zz + 1); - memcpy (h, p_stack_data[1], zz); - memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2)); - memcpy (argp2, h, zz); - } + if (dir < 0 && stack_args_count > 1) + { + /* Reverse order if iterating arguments backwards */ + ffi_arg tmp = *(ffi_arg*) p_stack_data[0]; + *(ffi_arg*) p_stack_data[0] = *(ffi_arg*) p_stack_data[stack_args_count - 1]; + *(ffi_arg*) p_stack_data[stack_args_count - 1] = tmp; + } + + int i; + for (i = 0; i < stack_args_count; i++) + { + if (p_stack_data[i] != argp2) + { + ffi_arg tmp = *(ffi_arg*) p_stack_data[i]; + memmove (argp2 + FFI_SIZEOF_ARG, argp2, (size_t) ((char*) p_stack_data[i] - (char*)argp2)); + *(ffi_arg *) argp2 = tmp; + } + + argp2 += FFI_SIZEOF_ARG; + } } + + return stack_args_count; #endif - return; + return 0; } /* Perform machine dependent cif processing */ @@ -314,12 +322,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) #ifdef X86_WIN64 /* ensure space for storing four registers */ - cif->bytes += 4 * sizeof(ffi_arg); + cif->bytes += 4 * FFI_SIZEOF_ARG; #endif #ifndef X86_WIN32 #ifndef X86_WIN64 - if (cif->abi != FFI_STDCALL && cif->abi != FFI_THISCALL && cif->abi != FFI_FASTCALL) + if (cif->abi == FFI_SYSV || cif->abi == FFI_UNIX64) #endif cif->bytes = (cif->bytes + 15) & ~0xF; #endif @@ -329,11 +337,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) #ifdef X86_WIN64 extern int -ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, +ffi_call_win64(unsigned int (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); #else extern void -ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, +ffi_call_win32(unsigned int (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); @@ -352,8 +360,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) #ifdef X86_WIN64 if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT - && cif->rtype->size != 1 && cif->rtype->size != 2 - && cif->rtype->size != 4 && cif->rtype->size != 8) + && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0)) { ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); } @@ -387,37 +394,12 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) case FFI_MS_CDECL: #endif case FFI_STDCALL: - ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; case FFI_THISCALL: case FFI_FASTCALL: - { - unsigned int abi = cif->abi; - unsigned int i, passed_regs = 0; - - if (cif->flags == FFI_TYPE_STRUCT) - ++passed_regs; - - for (i=0; i < cif->nargs && passed_regs < 2;i++) - { - size_t sz; - - if (cif->arg_types[i]->type == FFI_TYPE_FLOAT - || cif->arg_types[i]->type == FFI_TYPE_STRUCT) - continue; - sz = (cif->arg_types[i]->size + 3) & ~3; - if (sz == 0 || sz > 4) - continue; - ++passed_regs; - } - if (passed_regs < 2 && abi == FFI_FASTCALL) - abi = FFI_THISCALL; - if (passed_regs < 1 && abi == FFI_THISCALL) - abi = FFI_STDCALL; - ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - } + case FFI_PASCAL: + case FFI_REGISTER: + ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, + ecif.rvalue, fn); break; #endif default: @@ -431,12 +413,14 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) /* The following __attribute__((regparm(1))) decorations will have no effect on MSVC or SUNPRO_C -- standard conventions apply. */ -static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, - void** args, ffi_cif* cif); +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 @@ -444,12 +428,10 @@ void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *) __attribute__ ((regparm(1))); #endif #ifndef X86_WIN64 -void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *) - __attribute__ ((regparm(1))); +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 *); #else void FFI_HIDDEN ffi_closure_win64 (ffi_closure *); #endif @@ -473,7 +455,7 @@ ffi_closure_win64_inner (ffi_closure *closure, void *args) { * a structure, it will change RESP to point to the * structure return address. */ - ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif); + ffi_prep_incoming_args(args, &resp, arg_area, cif); (closure->fun) (cif, resp, arg_area, closure->user_data); @@ -502,80 +484,165 @@ ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args) * a structure, it will change RESP to point to the * structure return address. */ - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); + 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) +{ + /* 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; +} #endif /* !X86_WIN64 */ -static void -ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, - ffi_cif *cif) +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; +#ifndef X86_WIN64 + 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 }; +#else + #define dir 1 +#endif argp = stack; +#ifndef X86_WIN64 + argp += max_stack_count * FFI_SIZEOF_ARG; +#endif + if ((cif->flags == FFI_TYPE_STRUCT + || cif->flags == FFI_TYPE_MS_STRUCT) #ifdef X86_WIN64 - if (cif->rtype->size > sizeof(ffi_arg) - || (cif->flags == FFI_TYPE_STRUCT - && (cif->rtype->size != 1 && cif->rtype->size != 2 - && cif->rtype->size != 4 && cif->rtype->size != 8))) { - *rvalue = *(void **) argp; - argp += sizeof(void *); - } -#else - if ( cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT ) { - *rvalue = *(void **) argp; - argp += sizeof(void *); - } + && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0) #endif + ) + { +#ifndef X86_WIN64 + if (passed_regs < max_stack_count) + { + *rvalue = *(void**) (stack + (passed_regs*FFI_SIZEOF_ARG)); + ++passed_regs; + } + else +#endif + { + *rvalue = *(void **) argp; + argp += sizeof(void *); + } + } - p_argv = avalue; +#ifndef X86_WIN64 + /* Do register arguments first */ + for (i = 0, p_arg = cif->arg_types; + i < cif->nargs && passed_regs < max_stack_count; + i++, p_arg++) + { + 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; + } +#endif - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + p_arg = cif->arg_types; + p_argv = avalue; + if (dir < 0) { - size_t z; + 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) { + if ((sizeof(void*) - 1) & (size_t) argp) argp = (char *) ALIGN(argp, sizeof(void*)); - } + + size_t z = (*p_arg)->size; #ifdef X86_WIN64 - if ((*p_arg)->size > sizeof(ffi_arg) + if (z > FFI_SIZEOF_ARG || ((*p_arg)->type == FFI_TYPE_STRUCT - && ((*p_arg)->size != 1 && (*p_arg)->size != 2 - && (*p_arg)->size != 4 && (*p_arg)->size != 8))) + && (z & (1 | 2 | 4 | 8)) == 0) +#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE + || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE) +#endif + ) { - z = sizeof(void *); + z = FFI_SIZEOF_ARG; *p_argv = *(void **)argp; } else +#else + 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; + } + else #endif { - z = (*p_arg)->size; - /* because we're little endian, this is what it turns into. */ - *p_argv = (void*) argp; } - - p_argv++; + #ifdef X86_WIN64 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); #else argp += z; #endif } - - return; + + return (size_t)argp - (size_t)stack; } #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \ @@ -605,7 +672,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, 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 char*) &__tramp[5] = 0xe9; \ *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ } @@ -615,36 +682,36 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, 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 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 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 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 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_STDCALL(TRAMP,FUN,CTX) \ +#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] = 0xb8; \ - *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[5] = 0xe8; \ - *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \ + *(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 */ @@ -674,21 +741,27 @@ ffi_prep_closure_loc (ffi_closure* closure, &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_STDCALL (&closure->tramp[0], - &ffi_closure_FASTCALL, - (void*)codeloc); + FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0], + &ffi_closure_FASTCALL, + (void*)codeloc); } else if (cif->abi == FFI_THISCALL) { - FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], - &ffi_closure_THISCALL, - (void*)codeloc); + FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0], + &ffi_closure_THISCALL, + (void*)codeloc); } - else if (cif->abi == FFI_STDCALL) + else if (cif->abi == FFI_STDCALL || cif->abi == FFI_PASCAL) { - FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], + FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0], &ffi_closure_STDCALL, (void*)codeloc); } @@ -764,10 +837,38 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, return FFI_OK; } -static void +static unsigned int ffi_prep_args_raw(char *stack, extended_cif *ecif) { - memcpy (stack, ecif->avalue, ecif->cif->bytes); + const ffi_cif *cif = ecif->cif; + unsigned int i, passed_regs = 0; + +#ifndef X86_WIN64 + const unsigned int abi = cif->abi; + const unsigned int max_regs = (abi == FFI_THISCALL) ? 1 + : (abi == FFI_FASTCALL) ? 2 + : (abi == FFI_REGISTER) ? 3 + : 0; + + if (cif->flags == FFI_TYPE_STRUCT) + ++passed_regs; + + for (i = 0; i < cif->nargs && passed_regs <= max_regs; i++) + { + if (cif->arg_types[i]->type == FFI_TYPE_FLOAT + || cif->arg_types[i]->type == FFI_TYPE_STRUCT) + continue; + + size_t sz = cif->arg_types[i]->size; + if (sz == 0 || sz > FFI_SIZEOF_ARG) + continue; + + ++passed_regs; + } +#endif + + memcpy (stack, ecif->avalue, cif->bytes); + return passed_regs; } /* we borrow this routine from libffi (it must be changed, though, to @@ -810,37 +911,12 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) #endif #ifndef X86_WIN64 case FFI_STDCALL: - ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; case FFI_THISCALL: case FFI_FASTCALL: - { - unsigned int abi = cif->abi; - unsigned int i, passed_regs = 0; - - if (cif->flags == FFI_TYPE_STRUCT) - ++passed_regs; - - for (i=0; i < cif->nargs && passed_regs < 2;i++) - { - size_t sz; - - if (cif->arg_types[i]->type == FFI_TYPE_FLOAT - || cif->arg_types[i]->type == FFI_TYPE_STRUCT) - continue; - sz = (cif->arg_types[i]->size + 3) & ~3; - if (sz == 0 || sz > 4) - continue; - ++passed_regs; - } - if (passed_regs < 2 && abi == FFI_FASTCALL) - cif->abi = abi = FFI_THISCALL; - if (passed_regs < 1 && abi == FFI_THISCALL) - cif->abi = abi = FFI_STDCALL; - ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - } + case FFI_PASCAL: + case FFI_REGISTER: + ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, + ecif.rvalue, fn); break; #endif default: diff --git a/src/x86/ffitarget.h b/src/x86/ffitarget.h index b2afe91..e52111e 100644 --- a/src/x86/ffitarget.h +++ b/src/x86/ffitarget.h @@ -82,6 +82,8 @@ typedef enum ffi_abi { FFI_THISCALL, FFI_FASTCALL, FFI_MS_CDECL, + FFI_PASCAL, + FFI_REGISTER, FFI_LAST_ABI, #ifdef _MSC_VER FFI_DEFAULT_ABI = FFI_MS_CDECL @@ -101,6 +103,8 @@ typedef enum ffi_abi { FFI_THISCALL, FFI_FASTCALL, FFI_STDCALL, + FFI_PASCAL, + FFI_REGISTER, FFI_LAST_ABI, #if defined(__i386__) || defined(__i386) FFI_DEFAULT_ABI = FFI_SYSV @@ -135,7 +139,7 @@ typedef enum ffi_abi { #endif #endif #ifndef X86_WIN64 -#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ +#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ #endif #endif diff --git a/src/x86/win32.S b/src/x86/win32.S index e42baf2..d523eb0 100644 --- a/src/x86/win32.S +++ b/src/x86/win32.S @@ -1,11 +1,11 @@ /* ----------------------------------------------------------------------- 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 - - + 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 @@ -34,8 +34,8 @@ #include <fficonfig.h> #include <ffi.h> -#define CIF_ABI_OFFSET 0 #define CIF_BYTES_OFFSET 16 +#define CIF_FLAGS_OFFSET 20 #ifdef _MSC_VER @@ -45,6 +45,7 @@ .MODEL FLAT, C EXTRN ffi_closure_SYSV_inner:NEAR +EXTRN ffi_closure_WIN32_inner:NEAR _TEXT SEGMENT @@ -63,33 +64,45 @@ ffi_call_win32 PROC NEAR, mov eax, esp - ;; Place all of the ffi_prep_args in position + ;; Call ffi_prep_args push ecif push eax call ffi_prep_args - - ;; Return stack to previous state and call the function add esp, 8 - ;; Handle thiscall and fastcall - cmp cif_abi, 3 ;; FFI_THISCALL - jz do_thiscall - cmp cif_abi, 4 ;; FFI_FASTCALL - jnz do_stdcall - mov ecx, DWORD PTR [esp] - mov edx, DWORD PTR [esp+4] - add esp, 8 - jmp do_stdcall -do_thiscall: - mov ecx, DWORD PTR [esp] - add esp, 4 -do_stdcall: + ;; 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 - ;; cdecl: we restore esp in the epilogue, so there's no need to - ;; remove the space we pushed for the args. - ;; stdcall: the callee has already cleaned the stack. - ;; Load ecx with the return type code mov ecx, cif_flags @@ -195,20 +208,30 @@ ca_epilogue: 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 + ;; 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 register argument 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 + ;; 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 @@ -308,15 +331,14 @@ ffi_closure_SYSV ENDP #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) -#define CIF_FLAGS_OFFSET 20 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 + 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 @@ -405,7 +427,7 @@ ffi_closure_raw_SYSV ENDP #endif /* !FFI_NO_RAW_API */ ffi_closure_STDCALL PROC NEAR FORCEFRAME - ;; the ffi_closure ctx is passed in eax by the trampoline. + mov eax, [esp] ;; the ffi_closure ctx passed by the trampoline. sub esp, 40 lea edx, [ebp - 24] @@ -415,9 +437,13 @@ ffi_closure_STDCALL PROC NEAR FORCEFRAME lea edx, [ebp - 12] mov [esp + 4], edx ;; &resp mov [esp], eax ;; closure - call ffi_closure_SYSV_inner + 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: @@ -481,21 +507,10 @@ cd_retlongdouble: cd_epilogue: mov esp, ebp pop ebp - pop ecx - pop edx - mov ecx, DWORD PTR [ecx + (CLOSURE_CIF_OFFSET-10)] - add esp, DWORD PTR [ecx + CIF_BYTES_OFFSET] - mov ecx, DWORD PTR [ecx + CIF_ABI_OFFSET] - cmp ecx, 3 - je cd_thiscall - cmp ecx, 4 - jne cd_not_fastcall - - add esp, 4 -cd_thiscall: - add esp, 4 -cd_not_fastcall: - jmp edx + mov ecx, [esp + 4] ;; Return address + add esp, [esp] ;; Parameters stack size + add esp, 8 + jmp ecx ffi_closure_STDCALL ENDP _TEXT ENDS @@ -510,14 +525,14 @@ END #else #define USCORE_SYMBOL(x) x #endif - .text + .text # This assumes we are using gas. .balign 16 FFI_HIDDEN(ffi_call_win32) - .globl USCORE_SYMBOL(ffi_call_win32) + .globl USCORE_SYMBOL(ffi_call_win32) #if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_call_win32; .scl 2; .type 32; .endef + .def _ffi_call_win32; .scl 2; .type 32; .endef #endif USCORE_SYMBOL(ffi_call_win32): .LFB1: @@ -531,32 +546,46 @@ USCORE_SYMBOL(ffi_call_win32): movl %esp,%eax - # Place all of the ffi_prep_args in position + # Call ffi_prep_args pushl 12(%ebp) pushl %eax call *8(%ebp) - - # Return stack to previous state and call the function addl $8,%esp - # Handle fastcall and thiscall - cmpl $3, 16(%ebp) # FFI_THISCALL - jz .do_thiscall - cmpl $4, 16(%ebp) # FFI_FASTCALL - jnz .do_fncall - movl (%esp), %ecx - movl 4(%esp), %edx - addl $8, %esp - jmp .do_fncall -.do_thiscall: - movl (%esp), %ecx - addl $4, %esp - -.do_fncall: - + # 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 @@ -577,52 +606,52 @@ USCORE_SYMBOL(ffi_call_win32): jmp .Lepilogue 0: - call 1f - # Do not insert anything here between the call and the jump table. + 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 */ + .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. */ + 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 + movsbl %al, %eax + jmp .Lretint .Lretsint16: - movswl %ax, %eax - jmp .Lretint + movswl %ax, %eax + jmp .Lretint .Lretuint8: - movzbl %al, %eax - jmp .Lretint + movzbl %al, %eax + jmp .Lretint .Lretuint16: - movzwl %ax, %eax - jmp .Lretint + movzwl %ax, %eax + jmp .Lretint .Lretint: # Load %ecx with the pointer to storage for the return value @@ -653,7 +682,7 @@ USCORE_SYMBOL(ffi_call_win32): movl 28(%ebp),%ecx movl %eax,0(%ecx) movl %edx,4(%ecx) - jmp .Lepilogue + jmp .Lepilogue .Lretstruct1b: # Load %ecx with the pointer to storage for the return value @@ -684,167 +713,180 @@ USCORE_SYMBOL(ffi_call_win32): .ffi_call_win32_end: .balign 16 FFI_HIDDEN(ffi_closure_THISCALL) - .globl USCORE_SYMBOL(ffi_closure_THISCALL) + .globl USCORE_SYMBOL(ffi_closure_THISCALL) #if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_THISCALL; .scl 2; .type 32; .endef + .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 + /* 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) + .globl USCORE_SYMBOL(ffi_closure_FASTCALL) #if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_FASTCALL; .scl 2; .type 32; .endef + .def _ffi_closure_FASTCALL; .scl 2; .type 32; .endef #endif USCORE_SYMBOL(ffi_closure_FASTCALL): - /* Insert the 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 -.LFE1: + /* 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) + .globl USCORE_SYMBOL(ffi_closure_SYSV) #if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_SYSV; .scl 2; .type 32; .endef + .def _ffi_closure_SYSV; .scl 2; .type 32; .endef #endif USCORE_SYMBOL(ffi_closure_SYSV): #endif .LFB3: - pushl %ebp + pushl %ebp .LCFI4: - movl %esp, %ebp + 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 */ + 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) + call USCORE_SYMBOL(ffi_closure_SYSV_inner) #elif defined(X86_DARWIN) - calll L_ffi_closure_SYSV_inner$stub + 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 + 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 + movl -12(%ebp), %ecx 0: - call 1f - # Do not insert anything here between the call and the jump table. + 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 */ + .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. */ + 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 + movsbl (%ecx), %eax + jmp .Lcls_epilogue .Lcls_retsint16: - movswl (%ecx), %eax - jmp .Lcls_epilogue + movswl (%ecx), %eax + jmp .Lcls_epilogue .Lcls_retuint8: - movzbl (%ecx), %eax - jmp .Lcls_epilogue + movzbl (%ecx), %eax + jmp .Lcls_epilogue .Lcls_retuint16: - movzwl (%ecx), %eax - jmp .Lcls_epilogue + movzwl (%ecx), %eax + jmp .Lcls_epilogue .Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue + movl (%ecx), %eax + jmp .Lcls_epilogue .Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue + flds (%ecx) + jmp .Lcls_epilogue .Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue + fldl (%ecx) + jmp .Lcls_epilogue .Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue + fldt (%ecx) + jmp .Lcls_epilogue .Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue + movl (%ecx), %eax + movl 4(%ecx), %edx + jmp .Lcls_epilogue .Lcls_retstruct1: - movsbl (%ecx), %eax - jmp .Lcls_epilogue + movsbl (%ecx), %eax + jmp .Lcls_epilogue .Lcls_retstruct2: - movswl (%ecx), %eax - jmp .Lcls_epilogue + movswl (%ecx), %eax + jmp .Lcls_epilogue .Lcls_retstruct4: - movl (%ecx), %eax - jmp .Lcls_epilogue + 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 + 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 + # 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 + movl %ebp, %esp + popl %ebp + ret .ffi_closure_SYSV_end: .LFE3: @@ -853,458 +895,457 @@ USCORE_SYMBOL(ffi_closure_SYSV): #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 #ifdef X86_WIN32 .balign 16 FFI_HIDDEN(ffi_closure_raw_THISCALL) - .globl USCORE_SYMBOL(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 + .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 + 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) + .globl USCORE_SYMBOL(ffi_closure_raw_SYSV) #if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef + .def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef #endif USCORE_SYMBOL(ffi_closure_raw_SYSV): #endif /* defined(X86_WIN32) */ .LFB4: - pushl %ebp + pushl %ebp .LCFI6: - movl %esp, %ebp + movl %esp, %ebp .LCFI7: - pushl %esi + 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 () */ + 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 */ + 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. + 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 */ + .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. */ + 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 + movsbl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retsint16: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue + movswl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retuint8: - movzbl -24(%ebp), %eax - jmp .Lrcls_epilogue + movzbl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retuint16: - movzwl -24(%ebp), %eax - jmp .Lrcls_epilogue + movzwl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue + movl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue + flds -24(%ebp) + jmp .Lrcls_epilogue .Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue + fldl -24(%ebp) + jmp .Lrcls_epilogue .Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue + fldt -24(%ebp) + jmp .Lrcls_epilogue .Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue + movl -24(%ebp), %eax + movl -20(%ebp), %edx + jmp .Lrcls_epilogue .Lrcls_retstruct1: - movsbl -24(%ebp), %eax - jmp .Lrcls_epilogue + movsbl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retstruct2: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue + movswl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retstruct4: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue + movl -24(%ebp), %eax + jmp .Lrcls_epilogue .Lrcls_retstruct: - # Nothing to do! + # Nothing to do! .Lrcls_noretval: .Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret + 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 + .balign 16 FFI_HIDDEN(ffi_closure_STDCALL) - .globl USCORE_SYMBOL(ffi_closure_STDCALL) + .globl USCORE_SYMBOL(ffi_closure_STDCALL) #if defined(X86_WIN32) && !defined(__OS2__) - .def _ffi_closure_STDCALL; .scl 2; .type 32; .endef + .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 + pushl %ebp .LCFI9: - movl %esp, %ebp + 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 */ + 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_SYSV_inner) + call USCORE_SYMBOL(ffi_closure_WIN32_inner) #elif defined(X86_DARWIN) - calll L_ffi_closure_SYSV_inner$stub + 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_SYSV_inner@PLT - movl 8(%esp), %ebx + 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 + movl -12(%ebp), %ecx 0: - call 1f - # Do not insert anything here between the call and the jump table. + 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 */ + .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. */ + 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 + movsbl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retsint16: - movswl (%ecx), %eax - jmp .Lscls_epilogue + movswl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retuint8: - movzbl (%ecx), %eax - jmp .Lscls_epilogue + movzbl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retuint16: - movzwl (%ecx), %eax - jmp .Lscls_epilogue + movzwl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retint: - movl (%ecx), %eax - jmp .Lscls_epilogue + movl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retfloat: - flds (%ecx) - jmp .Lscls_epilogue + flds (%ecx) + jmp .Lscls_epilogue .Lscls_retdouble: - fldl (%ecx) - jmp .Lscls_epilogue + fldl (%ecx) + jmp .Lscls_epilogue .Lscls_retldouble: - fldt (%ecx) - jmp .Lscls_epilogue + fldt (%ecx) + jmp .Lscls_epilogue .Lscls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lscls_epilogue + movl (%ecx), %eax + movl 4(%ecx), %edx + jmp .Lscls_epilogue .Lscls_retstruct1: - movsbl (%ecx), %eax - jmp .Lscls_epilogue + movsbl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retstruct2: - movswl (%ecx), %eax - jmp .Lscls_epilogue + movswl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retstruct4: - movl (%ecx), %eax - jmp .Lscls_epilogue + movl (%ecx), %eax + jmp .Lscls_epilogue .Lscls_retstruct: - # Nothing to do! + # Nothing to do! .Lscls_noretval: .Lscls_epilogue: - movl %ebp, %esp - popl %ebp - popl %ecx - popl %edx - movl (CLOSURE_CIF_OFFSET-10)(%ecx), %ecx - addl CIF_BYTES_OFFSET(%ecx), %esp - movl CIF_ABI_OFFSET(%ecx), %ecx - cmpl $3, %ecx /* FFI_THISCALL */ - je 1f - cmpl $4, %ecx /* FFI_FASTCALL */ - jne 2f - - addl $4, %esp -1: addl $4, %esp -2: jmp *%edx + 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 + .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" + .section .eh_frame,"w" #endif .Lframe1: .LSCIE1: - .long .LECIE1-.LASCIE1 /* Length of Common Information Entry */ + .long .LECIE1-.LASCIE1 /* Length of Common Information Entry */ .LASCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ + .long 0x0 /* CIE Identifier Tag */ + .byte 0x1 /* CIE Version */ #ifdef __PIC__ - .ascii "zR\0" /* CIE Augmentation */ + .ascii "zR\0" /* CIE Augmentation */ #else - .ascii "\0" /* CIE Augmentation */ + .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 */ + .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) */ + .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 + .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 */ + .long .LEFDE1-.LASFDE1 /* FDE Length */ .LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ + .long .LASFDE1-.Lframe1 /* FDE CIE offset */ #if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB1-. /* FDE initial location */ + .long .LFB1-. /* FDE initial location */ #else - .long .LFB1 + .long .LFB1 #endif - .long .LFE1-.LFB1 /* FDE address range */ + .long .LFE1-.LFB1 /* FDE address range */ #ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ + .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 + /* 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 */ + .long .LEFDE3-.LASFDE3 /* FDE Length */ .LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ + .long .LASFDE3-.Lframe1 /* FDE CIE offset */ #if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB3-. /* FDE initial location */ + .long .LFB3-. /* FDE initial location */ #else - .long .LFB3 + .long .LFB3 #endif - .long .LFE3-.LFB3 /* FDE address range */ + .long .LFE3-.LFB3 /* FDE address range */ #ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ + .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 + /* 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 */ + .long .LEFDE4-.LASFDE4 /* FDE Length */ .LASFDE4: - .long .LASFDE4-.Lframe1 /* FDE CIE offset */ + .long .LASFDE4-.Lframe1 /* FDE CIE offset */ #if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB4-. /* FDE initial location */ + .long .LFB4-. /* FDE initial location */ #else - .long .LFB4 + .long .LFB4 #endif - .long .LFE4-.LFB4 /* FDE address range */ + .long .LFE4-.LFB4 /* FDE address range */ #ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ + .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 + /* 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 */ + .long .LEFDE5-.LASFDE5 /* FDE Length */ .LASFDE5: - .long .LASFDE5-.Lframe1 /* FDE CIE offset */ + .long .LASFDE5-.Lframe1 /* FDE CIE offset */ #if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB5-. /* FDE initial location */ + .long .LFB5-. /* FDE initial location */ #else - .long .LFB5 + .long .LFB5 #endif - .long .LFE5-.LFB5 /* FDE address range */ + .long .LFE5-.LFB5 /* FDE address range */ #ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ + .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 + /* 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 + .section .note.GNU-stack,"",@progbits #endif |