diff options
author | green <green@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-12-06 01:16:45 +0000 |
---|---|---|
committer | green <green@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-12-06 01:16:45 +0000 |
commit | acdc3fc389635aa1cd0b457ed0e3fefb229dab6a (patch) | |
tree | 42b4b6f3ce932aab0dbf81a4fb15247efd28b464 /libffi/src/x86 | |
parent | 40e6305ae1d5a9082adcafd92b54abcf9dc558da (diff) | |
download | gcc-acdc3fc389635aa1cd0b457ed0e3fefb229dab6a.tar.gz |
2002-11-10 Ranjit Mathew <rmathew@hotmail.com>
* include/ffi.h.in: Added FFI_STDCALL ffi_type
enumeration for X86_WIN32.
* src/x86/win32.S: Added ffi_call_STDCALL function
definition.
* src/x86/ffi.c (ffi_call/ffi_raw_call): Added
switch cases for recognising FFI_STDCALL and
calling ffi_call_STDCALL if target is X86_WIN32.
* src/ffitest.c (my_stdcall_strlen/stdcall_many):
stdcall versions of the "my_strlen" and "many"
test functions (for X86_WIN32).
Added test cases to test stdcall invocation using
these functions.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@59878 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi/src/x86')
-rw-r--r-- | libffi/src/x86/ffi.c | 42 | ||||
-rw-r--r-- | libffi/src/x86/win32.S | 105 |
2 files changed, 144 insertions, 3 deletions
diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c index 77193250311..68135f97c35 100644 --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -1,5 +1,8 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996, 1998, 1999 Cygnus Solutions + ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. + Copyright (c) 2002 Ranjit Mathew + Copyright (c) 2002 Bo Thorsen + Copyright (c) 2002 Roger Sayle x86 Foreign Function Interface @@ -148,6 +151,18 @@ extern void ffi_call_SYSV(void (*)(char *, extended_cif *), /*@=declundef@*/ /*@=exportheader@*/ +#ifdef X86_WIN32 +/*@-declundef@*/ +/*@-exportheader@*/ +extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); +/*@=declundef@*/ +/*@=exportheader@*/ +#endif /* X86_WIN32 */ + void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, @@ -180,6 +195,14 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif, cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; +#ifdef X86_WIN32 + case FFI_STDCALL: + /*@-usedef@*/ + ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#endif /* X86_WIN32 */ default: FFI_ASSERT(0); break; @@ -448,6 +471,15 @@ ffi_call_SYSV(void (*)(char *, extended_cif *), /*@out@*/ unsigned *, void (*fn)()); +#ifdef X86_WIN32 +extern void +ffi_call_STDCALL(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); +#endif /* X86_WIN32 */ + void ffi_raw_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), @@ -482,6 +514,14 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif, cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; +#ifdef X86_WIN32 + case FFI_STDCALL: + /*@-usedef@*/ + ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#endif /* X86_WIN32 */ default: FFI_ASSERT(0); break; diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S index 520d1fc0898..796af18754b 100644 --- a/libffi/src/x86/win32.S +++ b/libffi/src/x86/win32.S @@ -1,5 +1,8 @@ /* ----------------------------------------------------------------------- - win32.S - Copyright (c) 1996, 1998, 2001 Cygnus Solutions + win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc. + Copyright (c) 2001 John Beniton + Copyright (c) 2002 Ranjit Mathew + X86 Foreign Function Interface @@ -52,7 +55,10 @@ _ffi_call_SYSV: # Return stack to previous state and call the function addl $8,%esp - call *28(%ebp) + # FIXME: Align the stack to a 128-bit boundary to avoid + # potential performance hits. + + call *28(%ebp) # Remove the space we pushed for the args movl 16(%ebp),%ecx @@ -123,3 +129,98 @@ epilogue: ret .ffi_call_SYSV_end: + + # This assumes we are using gas. + .balign 16 +.globl _ffi_call_STDCALL + +_ffi_call_STDCALL: + pushl %ebp + movl %esp,%ebp + + # Make room for all of the new args. + movl 16(%ebp),%ecx + subl %ecx,%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 + + # FIXME: Align the stack to a 128-bit boundary to avoid + # potential performance hits. + + call *28(%ebp) + + # stdcall functions pop arguments off the stack themselves + + # Load %ecx with the return type code + movl 20(%ebp),%ecx + + # If the return value pointer is NULL, assume no return value. + cmpl $0,24(%ebp) + jne sc_retint + + # Even if there is no space for the return value, we are + # obliged to handle floating-point values. + cmpl $FFI_TYPE_FLOAT,%ecx + jne sc_noretval + fstp %st(0) + + jmp sc_epilogue + +sc_retint: + cmpl $FFI_TYPE_INT,%ecx + jne sc_retfloat + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + jmp sc_epilogue + +sc_retfloat: + cmpl $FFI_TYPE_FLOAT,%ecx + jne sc_retdouble + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstps (%ecx) + jmp sc_epilogue + +sc_retdouble: + cmpl $FFI_TYPE_DOUBLE,%ecx + jne sc_retlongdouble + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstpl (%ecx) + jmp sc_epilogue + +sc_retlongdouble: + cmpl $FFI_TYPE_LONGDOUBLE,%ecx + jne sc_retint64 + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + fstpt (%ecx) + jmp sc_epilogue + +sc_retint64: + cmpl $FFI_TYPE_SINT64,%ecx + jne sc_retstruct + # Load %ecx with the pointer to storage for the return value + movl 24(%ebp),%ecx + movl %eax,0(%ecx) + movl %edx,4(%ecx) + +sc_retstruct: + # Nothing to do! + +sc_noretval: +sc_epilogue: + movl %ebp,%esp + popl %ebp + ret + +.ffi_call_STDCALL_end: |