diff --git a/configure.host b/configure.host index c6f6a02e..a4a22b78 100644 --- a/configure.host +++ b/configure.host @@ -246,7 +246,7 @@ case "${TARGET}" in SOURCES="ffi.c sysv.S" ;; X86_64) - SOURCES="ffi64.c unix64.S" + SOURCES="ffi64.c unix64.S ffiw64.c win64.S" ;; X86_WIN64) SOURCES="ffiw64.c win64.S" diff --git a/src/x86/asmnames.h b/src/x86/asmnames.h new file mode 100644 index 00000000..7551021e --- /dev/null +++ b/src/x86/asmnames.h @@ -0,0 +1,30 @@ +#ifndef ASMNAMES_H +#define ASMNAMES_H + +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) +#ifdef __USER_LABEL_PREFIX__ +# define C(X) C1(__USER_LABEL_PREFIX__, X) +#else +# define C(X) X +#endif + +#ifdef __APPLE__ +# define L(X) C1(L, X) +#else +# define L(X) C1(.L, X) +#endif + +#if defined(__ELF__) && defined(__PIC__) +# define PLT(X) X@PLT +#else +# define PLT(X) X +#endif + +#ifdef __ELF__ +# define ENDF(X) .type X,@function; .size X, . - X +#else +# define ENDF(X) +#endif + +#endif /* ASMNAMES_H */ diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c index 131b5e3d..f52749e9 100644 --- a/src/x86/ffi64.c +++ b/src/x86/ffi64.c @@ -388,6 +388,9 @@ examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], /* Perform machine dependent cif processing. */ +extern ffi_status +ffi_prep_cif_machdep_efi64(ffi_cif *cif); + ffi_status ffi_prep_cif_machdep (ffi_cif *cif) { @@ -396,6 +399,8 @@ ffi_prep_cif_machdep (ffi_cif *cif) size_t bytes, n, rtype_size; ffi_type *rtype; + if (cif->abi == FFI_EFI64) + return ffi_prep_cif_machdep_efi64(cif); if (cif->abi != FFI_UNIX64) return FFI_BAD_ABI; @@ -657,22 +662,41 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, flags, rvalue, fn); } +extern void +ffi_call_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); + void ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { + if (cif->abi == FFI_EFI64) + return ffi_call_efi64(cif, fn, rvalue, avalue); ffi_call_int (cif, fn, rvalue, avalue, NULL); } +extern void +ffi_call_go_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure); + void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure) { + if (cif->abi == FFI_EFI64) + ffi_call_go_efi64(cif, fn, rvalue, avalue, closure); ffi_call_int (cif, fn, rvalue, avalue, closure); } + extern void ffi_closure_unix64(void) FFI_HIDDEN; extern void ffi_closure_unix64_sse(void) FFI_HIDDEN; +extern ffi_status +ffi_prep_closure_loc_efi64(ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *codeloc); + ffi_status ffi_prep_closure_loc (ffi_closure* closure, ffi_cif* cif, @@ -691,6 +715,8 @@ ffi_prep_closure_loc (ffi_closure* closure, void (*dest)(void); char *tramp = closure->tramp; + if (cif->abi == FFI_EFI64) + return ffi_prep_closure_loc_efi64(closure, cif, fun, user_data, codeloc); if (cif->abi != FFI_UNIX64) return FFI_BAD_ABI; @@ -805,10 +831,16 @@ ffi_closure_unix64_inner(ffi_cif *cif, extern void ffi_go_closure_unix64(void) FFI_HIDDEN; extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN; +extern ffi_status +ffi_prep_go_closure_efi64(ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)); + ffi_status ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*)) { + if (cif->abi == FFI_EFI64) + return ffi_prep_go_closure_efi64(closure, cif, fun); if (cif->abi != FFI_UNIX64) return FFI_BAD_ABI; diff --git a/src/x86/ffitarget.h b/src/x86/ffitarget.h index 8c1dcac2..25e3f4f5 100644 --- a/src/x86/ffitarget.h +++ b/src/x86/ffitarget.h @@ -87,6 +87,8 @@ typedef enum ffi_abi { #elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) FFI_FIRST_ABI = 1, FFI_UNIX64, + FFI_WIN64, + FFI_EFI64 = FFI_WIN64, FFI_LAST_ABI, FFI_DEFAULT_ABI = FFI_UNIX64 diff --git a/src/x86/ffiw64.c b/src/x86/ffiw64.c index 8a33a6c4..0029be02 100644 --- a/src/x86/ffiw64.c +++ b/src/x86/ffiw64.c @@ -30,6 +30,10 @@ #include #ifdef X86_WIN64 +#define EFI64(name) name +#else +#define EFI64(name) name##_efi64 +#endif struct win64_call_frame { @@ -44,7 +48,7 @@ extern void ffi_call_win64 (void *stack, struct win64_call_frame *, void *closure) FFI_HIDDEN; ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) +EFI64(ffi_prep_cif_machdep)(ffi_cif *cif) { int flags, n; @@ -159,13 +163,13 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, } void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { ffi_call_int (cif, fn, rvalue, avalue, NULL); } void -ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, +EFI64(ffi_call_go)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue, void *closure) { ffi_call_int (cif, fn, rvalue, avalue, closure); @@ -176,7 +180,7 @@ extern void ffi_closure_win64(void) FFI_HIDDEN; extern void ffi_go_closure_win64(void) FFI_HIDDEN; ffi_status -ffi_prep_closure_loc (ffi_closure* closure, +EFI64(ffi_prep_closure_loc)(ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data, @@ -190,7 +194,7 @@ ffi_prep_closure_loc (ffi_closure* closure, /* nopl (%rax) */ 0x0f, 0x1f, 0x00 }; - unsigned char *tramp = closure->tramp; + char *tramp = closure->tramp; if (cif->abi != FFI_WIN64) return FFI_BAD_ABI; @@ -206,7 +210,7 @@ ffi_prep_closure_loc (ffi_closure* closure, } ffi_status -ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, +EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*)) { if (cif->abi != FFI_WIN64) @@ -277,5 +281,3 @@ ffi_closure_win64_inner(ffi_cif *cif, fun (cif, rvalue, avalue, user_data); return flags; } - -#endif /* X86_WIN64 */ diff --git a/src/x86/unix64.S b/src/x86/unix64.S index c83010c7..129aba50 100644 --- a/src/x86/unix64.S +++ b/src/x86/unix64.S @@ -31,31 +31,10 @@ #include #include #include "internal64.h" +#include "asmnames.h" .text -#define C2(X, Y) X ## Y -#define C1(X, Y) C2(X, Y) -#ifdef __USER_LABEL_PREFIX__ -# define C(X) C1(__USER_LABEL_PREFIX__, X) -#else -# define C(X) X -#endif - -#ifdef __APPLE__ -# define L(X) C1(L, X) -#else -# define L(X) C1(.L, X) -#endif - -#ifdef __ELF__ -# define PLT(X) X@PLT -# define ENDF(X) .type X,@function; .size X, . - X -#else -# define PLT(X) X -# define ENDF(X) -#endif - /* This macro allows the safe creation of jump tables without an actual table. The entry points into the table are all 8 bytes. The use of ORG asserts that we're at the correct location. */ diff --git a/src/x86/win64.S b/src/x86/win64.S index a5a20b64..9d4f8b95 100644 --- a/src/x86/win64.S +++ b/src/x86/win64.S @@ -2,20 +2,24 @@ #include #include #include +#include "asmnames.h" #if defined(HAVE_AS_CFI_PSEUDO_OP) .cfi_sections .debug_frame #endif +#ifdef X86_WIN64 +#define SEH(...) __VA_ARGS__ #define arg0 %rcx #define arg1 %rdx #define arg2 %r8 #define arg3 %r9 - -#ifdef SYMBOL_UNDERSCORE -#define SYMBOL_NAME(name) _##name #else -#define SYMBOL_NAME(name) name +#define SEH(...) +#define arg0 %rdi +#define arg1 %rsi +#define arg2 %rdx +#define arg3 %rcx #endif .macro E which @@ -34,7 +38,7 @@ .align 8 .globl ffi_call_win64 - .seh_proc ffi_call_win64 + SEH(.seh_proc ffi_call_win64) ffi_call_win64: cfi_startproc /* Set up the local stack frame and install it in rbp/rsp. */ @@ -44,9 +48,9 @@ ffi_call_win64: movq arg1, %rbp cfi_def_cfa(%rbp, 16) cfi_rel_offset(%rbp, 0) - .seh_pushreg %rbp - .seh_setframe %rbp, 0 - .seh_endprologue + SEH(.seh_pushreg %rbp) + SEH(.seh_setframe %rbp, 0) + SEH(.seh_endprologue) movq arg0, %rsp movq arg2, %r10 @@ -97,7 +101,7 @@ E FFI_TYPE_DOUBLE movsd %xmm0, (%r8) epilogue E FFI_TYPE_LONGDOUBLE - call abort + call PLT(C(abort)) E FFI_TYPE_UINT8 movzbl %al, %eax movq %rax, (%r8) @@ -132,7 +136,7 @@ E FFI_TYPE_POINTER movq %rax, (%r8) epilogue E FFI_TYPE_COMPLEX - call abort + call PLT(C(abort)) E FFI_TYPE_SMALL_STRUCT_1B movb %al, (%r8) epilogue @@ -144,12 +148,12 @@ E FFI_TYPE_SMALL_STRUCT_4B epilogue .align 8 -99: call abort +99: call PLT(C(abort)) .purgem epilogue cfi_endproc - .seh_endproc + SEH(.seh_endproc) /* 32 bytes of outgoing register stack space, 8 bytes of alignment, @@ -161,33 +165,33 @@ E FFI_TYPE_SMALL_STRUCT_4B .align 8 .globl ffi_go_closure_win64 - .seh_proc ffi_go_closure_win64 + SEH(.seh_proc ffi_go_closure_win64) ffi_go_closure_win64: cfi_startproc /* Save all integer arguments into the incoming reg stack space. */ - movq arg0, 8(%rsp) - movq arg1, 16(%rsp) - movq arg2, 24(%rsp) - movq arg3, 32(%rsp) + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) movq 8(%r10), arg0 /* load cif */ movq 16(%r10), arg1 /* load fun */ movq %r10, arg2 /* closure is user_data */ jmp 0f cfi_endproc - .seh_endproc + SEH(.seh_endproc) .align 8 .globl ffi_closure_win64 - .seh_proc ffi_closure_win64 + SEH(.seh_proc ffi_closure_win64) ffi_closure_win64: cfi_startproc /* Save all integer arguments into the incoming reg stack space. */ - movq arg0, 8(%rsp) - movq arg1, 16(%rsp) - movq arg2, 24(%rsp) - movq arg3, 32(%rsp) + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) movq FFI_TRAMPOLINE_SIZE(%r10), arg0 /* load cif */ movq FFI_TRAMPOLINE_SIZE+8(%r10), arg1 /* load fun */ @@ -195,8 +199,8 @@ ffi_closure_win64: 0: subq $ffi_clo_FS, %rsp cfi_adjust_cfa_offset(ffi_clo_FS) - .seh_stackalloc ffi_clo_FS - .seh_endprologue + SEH(.seh_stackalloc ffi_clo_FS) + SEH(.seh_endprologue) /* Save all sse arguments into the stack frame. */ movsd %xmm0, ffi_clo_OFF_X(%rsp) @@ -216,4 +220,4 @@ ffi_closure_win64: ret cfi_endproc - .seh_endproc + SEH(.seh_endproc)