diff options
Diffstat (limited to 'libffi/src/x86')
-rw-r--r-- | libffi/src/x86/ffi.c | 50 | ||||
-rw-r--r-- | libffi/src/x86/ffi64.c | 22 | ||||
-rw-r--r-- | libffi/src/x86/ffitarget.h | 38 | ||||
-rw-r--r-- | libffi/src/x86/win32.S | 30 | ||||
-rw-r--r-- | libffi/src/x86/win64.S | 22 |
5 files changed, 64 insertions, 98 deletions
diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c index 469578ea504..9343c260728 100644 --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -228,12 +228,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) switch (cif->rtype->type) { case FFI_TYPE_VOID: -#if defined(X86) || defined (X86_WIN32) || defined(X86_FREEBSD) || defined(X86_DARWIN) || defined(X86_WIN64) case FFI_TYPE_UINT8: case FFI_TYPE_UINT16: case FFI_TYPE_SINT8: case FFI_TYPE_SINT16: -#endif #ifdef X86_WIN64 case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: @@ -364,27 +362,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { #ifdef X86_WIN64 case FFI_WIN64: - { - /* Make copies of all struct arguments - NOTE: not sure if responsibility should be here or in caller */ - unsigned int i; - for (i=0; i < cif->nargs;i++) { - size_t size = cif->arg_types[i]->size; - if ((cif->arg_types[i]->type == FFI_TYPE_STRUCT - && (size != 1 && size != 2 && size != 4 && size != 8)) -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || cif->arg_types[i]->type == FFI_TYPE_LONGDOUBLE -#endif - ) - { - void *local = alloca(size); - memcpy(local, avalue[i], size); - avalue[i] = local; - } - } - ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - } + ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); break; #elif defined(X86_WIN32) case FFI_SYSV: @@ -447,8 +426,6 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *) 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))); void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *) __attribute__ ((regparm(1))); void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *) @@ -616,7 +593,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, { 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 int __dis = __fun - (__ctx + 22); \ unsigned short __size = (unsigned short)(SIZE); \ *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \ *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \ @@ -722,9 +699,6 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, int i; if (cif->abi != FFI_SYSV) { -#ifdef X86_WIN32 - if (cif->abi != FFI_THISCALL) -#endif return FFI_BAD_ABI; } @@ -739,20 +713,10 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); } -#ifdef X86_WIN32 - if (cif->abi == FFI_SYSV) - { -#endif + FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV, codeloc); -#ifdef X86_WIN32 - } - else if (cif->abi == FFI_THISCALL) - { - FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, - codeloc, cif->bytes); - } -#endif + closure->cif = cif; closure->user_data = user_data; closure->fun = fun; @@ -797,7 +761,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) #ifdef X86_WIN32 case FFI_SYSV: case FFI_STDCALL: - ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, + ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, ecif.rvalue, fn); break; case FFI_THISCALL: @@ -825,7 +789,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) 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, + ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags, ecif.rvalue, fn); } break; diff --git a/libffi/src/x86/ffi64.c b/libffi/src/x86/ffi64.c index bd907d7208c..defd7744cce 100644 --- a/libffi/src/x86/ffi64.c +++ b/libffi/src/x86/ffi64.c @@ -1,7 +1,8 @@ /* ----------------------------------------------------------------------- - ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de> + ffi64.c - Copyright (c) 20011 Anthony Green Copyright (c) 2008, 2010 Red Hat, Inc. - + Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de> + x86-64 Foreign Function Interface Permission is hereby granted, free of charge, to any person obtaining @@ -426,7 +427,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) /* If the return value is passed in memory, add the pointer as the first integer argument. */ if (ret_in_memory) - reg_args->gpr[gprcount++] = (long) rvalue; + reg_args->gpr[gprcount++] = (unsigned long) rvalue; avn = cif->nargs; arg_types = cif->arg_types; @@ -498,12 +499,21 @@ ffi_prep_closure_loc (ffi_closure* closure, { volatile unsigned short *tramp; + /* Sanity check on the cif ABI. */ + { + int abi = cif->abi; + if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))) + return FFI_BAD_ABI; + } + tramp = (volatile unsigned short *) &closure->tramp[0]; tramp[0] = 0xbb49; /* mov <code>, %r11 */ - *(void * volatile *) &tramp[1] = ffi_closure_unix64; + *((unsigned long long * volatile) &tramp[1]) + = (unsigned long) ffi_closure_unix64; tramp[5] = 0xba49; /* mov <data>, %r10 */ - *(void * volatile *) &tramp[6] = codeloc; + *((unsigned long long * volatile) &tramp[6]) + = (unsigned long) codeloc; /* Set the carry bit iff the function uses any sse registers. This is clc or stc, together with the first byte of the jmp. */ @@ -542,7 +552,7 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, { /* The return value goes in memory. Arrange for the closure return value to go directly back to the original caller. */ - rvalue = (void *) reg_args->gpr[gprcount++]; + rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++]; /* We don't have to do anything in asm for the return. */ ret = FFI_TYPE_VOID; } diff --git a/libffi/src/x86/ffitarget.h b/libffi/src/x86/ffitarget.h index dfecd1b3c6e..54a61212e4f 100644 --- a/libffi/src/x86/ffitarget.h +++ b/libffi/src/x86/ffitarget.h @@ -1,6 +1,7 @@ /* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 1996-2003, 2010 Red Hat, Inc. - Copyright (C) 2008 Free Software Foundation, Inc. + ffitarget.h - Copyright (c) 2012 Anthony Green + Copyright (c) 1996-2003, 2010 Red Hat, Inc. + Copyright (C) 2008 Free Software Foundation, Inc. Target configuration macros for x86 and x86-64. @@ -29,8 +30,15 @@ #ifndef LIBFFI_TARGET_H #define LIBFFI_TARGET_H +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + /* ---- System specific configurations ----------------------------------- */ +/* For code common to all platforms on x86 and x86_64. */ +#define X86_ANY + #if defined (X86_64) && defined (__i386__) #undef X86_64 #define X86 @@ -53,9 +61,15 @@ typedef unsigned long long ffi_arg; typedef long long ffi_sarg; #endif #else +#if defined __x86_64__ && !defined __LP64__ +#define FFI_SIZEOF_ARG 8 +typedef unsigned long long ffi_arg; +typedef long long ffi_sarg; +#else typedef unsigned long ffi_arg; typedef signed long ffi_sarg; #endif +#endif typedef enum ffi_abi { FFI_FIRST_ABI = 0, @@ -66,28 +80,26 @@ typedef enum ffi_abi { FFI_STDCALL, FFI_THISCALL, FFI_FASTCALL, + FFI_LAST_ABI, /* TODO: Add fastcall support for the sake of completeness */ - FFI_DEFAULT_ABI = FFI_SYSV, -#endif + FFI_DEFAULT_ABI = FFI_SYSV -#ifdef X86_WIN64 +#elif defined(X86_WIN64) FFI_WIN64, - FFI_DEFAULT_ABI = FFI_WIN64, -#else + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_WIN64 +#else /* ---- Intel x86 and AMD x86-64 - */ -#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__) || defined(__i386) || defined(__amd64)) FFI_SYSV, FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ + FFI_LAST_ABI, #if defined(__i386__) || defined(__i386) - FFI_DEFAULT_ABI = FFI_SYSV, + FFI_DEFAULT_ABI = FFI_SYSV #else - FFI_DEFAULT_ABI = FFI_UNIX64, + FFI_DEFAULT_ABI = FFI_UNIX64 #endif #endif -#endif /* X86_WIN64 */ - - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S index deb4a0394d8..e5c93ecf7b9 100644 --- a/libffi/src/x86/win32.S +++ b/libffi/src/x86/win32.S @@ -264,18 +264,6 @@ ffi_closure_SYSV ENDP #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) #define CIF_FLAGS_OFFSET 20 -ffi_closure_raw_THISCALL PROC NEAR - push ebp - mov ebp, esp - push esi - 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], edx - jmp stubraw -ffi_closure_raw_SYSV ENDP - ffi_closure_raw_SYSV PROC NEAR USES esi ;; the ffi_closure ctx is passed in eax by the trampoline. @@ -284,7 +272,6 @@ ffi_closure_raw_SYSV PROC NEAR USES esi mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data mov [esp + 12], edx ;; user_data lea edx, [ebp + 8] -stubraw: mov [esp + 8], edx ;; raw_args lea edx, [ebp - 24] mov [esp + 4], edx ;; &res @@ -735,21 +722,7 @@ _ffi_closure_SYSV: #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 - .balign 16 - .globl _ffi_closure_raw_THISCALL -#ifndef __OS2__ - .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef -#endif -_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 + # This assumes we are using gas. .balign 16 .globl _ffi_closure_raw_SYSV @@ -769,7 +742,6 @@ _ffi_closure_raw_SYSV: 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 */ diff --git a/libffi/src/x86/win64.S b/libffi/src/x86/win64.S index 6e9181867de..fcdb270faf5 100644 --- a/libffi/src/x86/win64.S +++ b/libffi/src/x86/win64.S @@ -232,10 +232,18 @@ ret_void$: ffi_call_win64 ENDP _TEXT ENDS END -#else + +#else + +#ifdef SYMBOL_UNDERSCORE +#define SYMBOL_NAME(name) _##name +#else +#define SYMBOL_NAME(name) name +#endif + .text -.extern _ffi_closure_win64_inner +.extern SYMBOL_NAME(ffi_closure_win64_inner) # ffi_closure_win64 will be called with these registers set: # rax points to 'closure' @@ -246,8 +254,8 @@ END # call ffi_closure_win64_inner for the actual work, then return the result. # .balign 16 - .globl _ffi_closure_win64 -_ffi_closure_win64: + .globl SYMBOL_NAME(ffi_closure_win64) +SYMBOL_NAME(ffi_closure_win64): # copy register arguments onto stack test $1,%r11 jne .Lfirst_is_float @@ -287,7 +295,7 @@ _ffi_closure_win64: mov %rax, %rcx # context is first parameter mov %rsp, %rdx # stack is second parameter add $48, %rdx # point to start of arguments - mov $_ffi_closure_win64_inner, %rax + mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax callq *%rax # call the real closure function add $40, %rsp movq %rax, %xmm0 # If the closure returned a float, @@ -296,8 +304,8 @@ _ffi_closure_win64: .ffi_closure_win64_end: .balign 16 - .globl _ffi_call_win64 -_ffi_call_win64: + .globl SYMBOL_NAME(ffi_call_win64) +SYMBOL_NAME(ffi_call_win64): # copy registers onto stack mov %r9,32(%rsp) mov %r8,24(%rsp) |