mirror of https://github.com/python/cpython
Merged changes from libffi3-branch.
The bundled libffi copy is now in sync with the recently released libffi3.0.4 version, apart from some small changes to Modules/_ctypes/libffi/configure.ac. I gave up on using libffi3 files on os x. Instead, static configuration with files from pyobjc is used.
This commit is contained in:
parent
4a50d26ba2
commit
8bdf81d2df
|
@ -1,4 +1,5 @@
|
|||
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
libffi - Copyright (c) 1996-2008 Red Hat, Inc and others.
|
||||
See source files for details.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -11,10 +12,10 @@ 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
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
## Process this with automake to create Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
|
||||
SUBDIRS = include testsuite man
|
||||
|
||||
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \
|
||||
src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
|
||||
src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
|
||||
src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \
|
||||
src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h \
|
||||
src/ia64/unix.S \
|
||||
src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
|
||||
src/mips/ffitarget.h \
|
||||
src/m32r/ffi.c src/m32r/sysv.S src/m32r/ffitarget.h \
|
||||
src/m68k/ffi.c src/m68k/sysv.S src/m68k/ffitarget.h \
|
||||
src/powerpc/ffi.c src/powerpc/sysv.S \
|
||||
src/powerpc/linux64.S src/powerpc/linux64_closure.S \
|
||||
src/powerpc/ppc_closure.S src/powerpc/asm.h \
|
||||
src/powerpc/aix.S src/powerpc/darwin.S \
|
||||
src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
|
||||
src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
|
||||
src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
|
||||
src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h \
|
||||
src/sh64/ffi.c 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/freebsd.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/frv/eabi.S src/frv/ffitarget.h src/dlmalloc.c \
|
||||
libtool-version ChangeLog.libffi
|
||||
|
||||
info_TEXINFOS = doc/libffi.texi
|
||||
|
||||
## ################################################################
|
||||
|
||||
##
|
||||
## This section is for make and multilib madness.
|
||||
##
|
||||
|
||||
# Work around what appears to be a GNU make bug handling MAKEFLAGS
|
||||
# values defined in terms of make variables, as is the case for CC and
|
||||
# friends when we are called from the top level Makefile.
|
||||
AM_MAKEFLAGS = \
|
||||
"AR_FLAGS=$(AR_FLAGS)" \
|
||||
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
|
||||
"CFLAGS=$(CFLAGS)" \
|
||||
"CXXFLAGS=$(CXXFLAGS)" \
|
||||
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
|
||||
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
|
||||
"INSTALL=$(INSTALL)" \
|
||||
"INSTALL_DATA=$(INSTALL_DATA)" \
|
||||
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
|
||||
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
|
||||
"JC1FLAGS=$(JC1FLAGS)" \
|
||||
"LDFLAGS=$(LDFLAGS)" \
|
||||
"LIBCFLAGS=$(LIBCFLAGS)" \
|
||||
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
|
||||
"MAKE=$(MAKE)" \
|
||||
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
"PICFLAG=$(PICFLAG)" \
|
||||
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
|
||||
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
|
||||
"SHELL=$(SHELL)" \
|
||||
"exec_prefix=$(exec_prefix)" \
|
||||
"infodir=$(infodir)" \
|
||||
"libdir=$(libdir)" \
|
||||
"prefix=$(prefix)" \
|
||||
"AR=$(AR)" \
|
||||
"AS=$(AS)" \
|
||||
"CC=$(CC)" \
|
||||
"CXX=$(CXX)" \
|
||||
"LD=$(LD)" \
|
||||
"NM=$(NM)" \
|
||||
"RANLIB=$(RANLIB)" \
|
||||
"DESTDIR=$(DESTDIR)"
|
||||
|
||||
MAKEOVERRIDES=
|
||||
|
||||
lib_LTLIBRARIES = libffi.la
|
||||
noinst_LTLIBRARIES = libffi_convenience.la
|
||||
|
||||
libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \
|
||||
src/raw_api.c src/java_raw_api.c src/closures.c
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libffi.pc
|
||||
|
||||
nodist_libffi_la_SOURCES =
|
||||
|
||||
if MIPS
|
||||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
endif
|
||||
if X86
|
||||
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
|
||||
endif
|
||||
if X86_WIN32
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.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
|
||||
endif
|
||||
if SPARC
|
||||
nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
|
||||
endif
|
||||
if ALPHA
|
||||
nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
|
||||
endif
|
||||
if IA64
|
||||
nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
|
||||
endif
|
||||
if M32R
|
||||
nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
|
||||
endif
|
||||
if M68K
|
||||
nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
|
||||
endif
|
||||
if POWERPC
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
|
||||
endif
|
||||
if POWERPC_AIX
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
|
||||
endif
|
||||
if POWERPC_DARWIN
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
|
||||
endif
|
||||
if POWERPC_FREEBSD
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
|
||||
endif
|
||||
if ARM
|
||||
nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
|
||||
endif
|
||||
if LIBFFI_CRIS
|
||||
nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
|
||||
endif
|
||||
if FRV
|
||||
nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
|
||||
endif
|
||||
if S390
|
||||
nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
|
||||
endif
|
||||
if X86_64
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
|
||||
endif
|
||||
if SH
|
||||
nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
|
||||
endif
|
||||
if SH64
|
||||
nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
|
||||
endif
|
||||
if PA_LINUX
|
||||
nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
|
||||
endif
|
||||
if PA_HPUX
|
||||
nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
|
||||
endif
|
||||
|
||||
libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
|
||||
nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
|
||||
|
||||
AM_CFLAGS = -Wall -g -fexceptions
|
||||
|
||||
libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
|
||||
|
||||
AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
|
||||
AM_CCASFLAGS = $(AM_CPPFLAGS)
|
||||
|
||||
# No install-html or install-pdf support in automake yet
|
||||
.PHONY: install-html install-pdf
|
||||
install-html:
|
||||
install-pdf:
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,78 +1,67 @@
|
|||
This directory contains the libffi package, which is not part of GCC but
|
||||
shipped with GCC as convenience.
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
libffi-2.00 has not been released yet! This is a development snapshot!
|
||||
|
||||
libffi-1.20 was released on October 5, 1998. Check the libffi web
|
||||
page for updates: <URL:http://sources.redhat.com/libffi/>.
|
||||
libffi-3.0.4 was released on February 24, 2008. Check the libffi web
|
||||
page for updates: <URL:http://sourceware.org/libffi/>.
|
||||
|
||||
|
||||
What is libffi?
|
||||
===============
|
||||
|
||||
Compilers for high level languages generate code that follow certain
|
||||
conventions. These conventions are necessary, in part, for separate
|
||||
compilation to work. One such convention is the "calling
|
||||
convention". The "calling convention" is essentially a set of
|
||||
assumptions made by the compiler about where function arguments will
|
||||
be found on entry to a function. A "calling convention" also specifies
|
||||
where the return value for a function is found.
|
||||
conventions. These conventions are necessary, in part, for separate
|
||||
compilation to work. One such convention is the "calling convention".
|
||||
The "calling convention" is a set of assumptions made by the compiler
|
||||
about where function arguments will be found on entry to a function.
|
||||
A "calling convention" also specifies where the return value for a
|
||||
function is found.
|
||||
|
||||
Some programs may not know at the time of compilation what arguments
|
||||
are to be passed to a function. For instance, an interpreter may be
|
||||
are to be passed to a function. For instance, an interpreter may be
|
||||
told at run-time about the number and types of arguments used to call
|
||||
a given function. Libffi can be used in such programs to provide a
|
||||
a given function. Libffi can be used in such programs to provide a
|
||||
bridge from the interpreter program to compiled code.
|
||||
|
||||
The libffi library provides a portable, high level programming
|
||||
interface to various calling conventions. This allows a programmer to
|
||||
interface to various calling conventions. This allows a programmer to
|
||||
call any function specified by a call interface description at run
|
||||
time.
|
||||
time.
|
||||
|
||||
Ffi stands for Foreign Function Interface. A foreign function
|
||||
FFI stands for Foreign Function Interface. A foreign function
|
||||
interface is the popular name for the interface that allows code
|
||||
written in one language to call code written in another language. The
|
||||
written in one language to call code written in another language. The
|
||||
libffi library really only provides the lowest, machine dependent
|
||||
layer of a fully featured foreign function interface. A layer must
|
||||
exist above libffi that handles type conversions for values passed
|
||||
between the two languages.
|
||||
|
||||
|
||||
Supported Platforms and Prerequisites
|
||||
=====================================
|
||||
Supported Platforms
|
||||
===================
|
||||
|
||||
Libffi has been ported to:
|
||||
|
||||
SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
|
||||
|
||||
Irix 5.3 & 6.2 (System V/o32 & n32)
|
||||
|
||||
Intel x86 - Linux (System V ABI)
|
||||
|
||||
Alpha - Linux and OSF/1
|
||||
|
||||
m68k - Linux (System V ABI)
|
||||
|
||||
PowerPC - Linux (System V ABI, Darwin, AIX)
|
||||
|
||||
ARM - Linux (System V ABI)
|
||||
|
||||
Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
|
||||
that other versions will work. Libffi has also been built and tested
|
||||
with the SGI compiler tools.
|
||||
|
||||
On PowerPC, the tests failed (see the note below).
|
||||
|
||||
You must use GNU make to build libffi. SGI's make will not work.
|
||||
Sun's probably won't either.
|
||||
|
||||
If you port libffi to another platform, please let me know! I assume
|
||||
that some will be easy (x86 NetBSD), and others will be more difficult
|
||||
(HP).
|
||||
Libffi has been ported to many different platforms, although this
|
||||
release was only tested on:
|
||||
|
||||
arm oabi linux
|
||||
arm eabi linux
|
||||
hppa linux
|
||||
mips o32 linux (little endian)
|
||||
powerpc darwin
|
||||
powerpc64 linux
|
||||
sparc solaris
|
||||
sparc64 solaris
|
||||
x86 cygwin
|
||||
x86 darwin
|
||||
x86 freebsd
|
||||
x86 linux
|
||||
x86 openbsd
|
||||
x86-64 darwin
|
||||
x86-64 linux
|
||||
x86-64 OS X
|
||||
x86-64 freebsd
|
||||
|
||||
Please send additional platform test results to
|
||||
libffi-discuss@sourceware.org.
|
||||
|
||||
Installing libffi
|
||||
=================
|
||||
|
@ -101,216 +90,17 @@ Purify, as it will slow down the library.
|
|||
Configure has many other options. Use "configure --help" to see them all.
|
||||
|
||||
Once configure has finished, type "make". Note that you must be using
|
||||
GNU make. SGI's make will not work. Sun's probably won't either.
|
||||
You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
||||
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
||||
|
||||
To ensure that libffi is working as advertised, type "make test".
|
||||
To ensure that libffi is working as advertised, type "make check".
|
||||
This will require that you have DejaGNU installed.
|
||||
|
||||
To install the library and header files, type "make install".
|
||||
|
||||
|
||||
Using libffi
|
||||
============
|
||||
|
||||
The Basics
|
||||
----------
|
||||
|
||||
Libffi assumes that you have a pointer to the function you wish to
|
||||
call and that you know the number and types of arguments to pass it,
|
||||
as well as the return type of the function.
|
||||
|
||||
The first thing you must do is create an ffi_cif object that matches
|
||||
the signature of the function you wish to call. The cif in ffi_cif
|
||||
stands for Call InterFace. To prepare a call interface object, use the
|
||||
following function:
|
||||
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
ffi_type *rtype, ffi_type **atypes);
|
||||
|
||||
CIF is a pointer to the call interface object you wish
|
||||
to initialize.
|
||||
|
||||
ABI is an enum that specifies the calling convention
|
||||
to use for the call. FFI_DEFAULT_ABI defaults
|
||||
to the system's native calling convention. Other
|
||||
ABI's may be used with care. They are system
|
||||
specific.
|
||||
|
||||
NARGS is the number of arguments this function accepts.
|
||||
libffi does not yet support vararg functions.
|
||||
|
||||
RTYPE is a pointer to an ffi_type structure that represents
|
||||
the return type of the function. Ffi_type objects
|
||||
describe the types of values. libffi provides
|
||||
ffi_type objects for many of the native C types:
|
||||
signed int, unsigned int, signed char, unsigned char,
|
||||
etc. There is also a pointer ffi_type object and
|
||||
a void ffi_type. Use &ffi_type_void for functions that
|
||||
don't return values.
|
||||
|
||||
ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
|
||||
If NARGS is 0, this is ignored.
|
||||
|
||||
|
||||
ffi_prep_cif will return a status code that you are responsible
|
||||
for checking. It will be one of the following:
|
||||
|
||||
FFI_OK - All is good.
|
||||
|
||||
FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
|
||||
came across is bad.
|
||||
|
||||
|
||||
Before making the call, the VALUES vector should be initialized
|
||||
with pointers to the appropriate argument values.
|
||||
|
||||
To call the the function using the initialized ffi_cif, use the
|
||||
ffi_call function:
|
||||
|
||||
void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
|
||||
|
||||
CIF is a pointer to the ffi_cif initialized specifically
|
||||
for this function.
|
||||
|
||||
FN is a pointer to the function you want to call.
|
||||
|
||||
RVALUE is a pointer to a chunk of memory that is to hold the
|
||||
result of the function call. Currently, it must be
|
||||
at least one word in size (except for the n32 version
|
||||
under Irix 6.x, which must be a pointer to an 8 byte
|
||||
aligned value (a long long). It must also be at least
|
||||
word aligned (depending on the return type, and the
|
||||
system's alignment requirements). If RTYPE is
|
||||
&ffi_type_void, this is ignored. If RVALUE is NULL,
|
||||
the return value is discarded.
|
||||
|
||||
AVALUES is a vector of void* that point to the memory locations
|
||||
holding the argument values for a call.
|
||||
If NARGS is 0, this is ignored.
|
||||
|
||||
|
||||
If you are expecting a return value from FN it will have been stored
|
||||
at RVALUE.
|
||||
|
||||
|
||||
|
||||
An Example
|
||||
----------
|
||||
|
||||
Here is a trivial example that calls puts() a few times.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[1];
|
||||
void *values[1];
|
||||
char *s;
|
||||
int rc;
|
||||
|
||||
/* Initialize the argument info vectors */
|
||||
args[0] = &ffi_type_uint;
|
||||
values[0] = &s;
|
||||
|
||||
/* Initialize the cif */
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_uint, args) == FFI_OK)
|
||||
{
|
||||
s = "Hello World!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
/* rc now holds the result of the call to puts */
|
||||
|
||||
/* values holds a pointer to the function's arg, so to
|
||||
call puts() again all we need to do is change the
|
||||
value of s */
|
||||
s = "This is cool!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Aggregate Types
|
||||
---------------
|
||||
|
||||
Although libffi has no special support for unions or bit-fields, it is
|
||||
perfectly happy passing structures back and forth. You must first
|
||||
describe the structure to libffi by creating a new ffi_type object
|
||||
for it. Here is the definition of ffi_type:
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
unsigned size;
|
||||
short alignment;
|
||||
short type;
|
||||
struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
|
||||
All structures must have type set to FFI_TYPE_STRUCT. You may set
|
||||
size and alignment to 0. These will be calculated and reset to the
|
||||
appropriate values by ffi_prep_cif().
|
||||
|
||||
elements is a NULL terminated array of pointers to ffi_type objects
|
||||
that describe the type of the structure elements. These may, in turn,
|
||||
be structure elements.
|
||||
|
||||
The following example initializes a ffi_type object representing the
|
||||
tm struct from Linux's time.h:
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
/* Those are for future use. */
|
||||
long int __tm_gmtoff__;
|
||||
__const char *__tm_zone__;
|
||||
};
|
||||
|
||||
{
|
||||
ffi_type tm_type;
|
||||
ffi_type *tm_type_elements[12];
|
||||
int i;
|
||||
|
||||
tm_type.size = tm_type.alignment = 0;
|
||||
tm_type.elements = &tm_type_elements;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
tm_type_elements[i] = &ffi_type_sint;
|
||||
|
||||
tm_type_elements[9] = &ffi_type_slong;
|
||||
tm_type_elements[10] = &ffi_type_pointer;
|
||||
tm_type_elements[11] = NULL;
|
||||
|
||||
/* tm_type can now be used to represent tm argument types and
|
||||
return types for ffi_prep_cif() */
|
||||
}
|
||||
|
||||
|
||||
|
||||
Platform Specific Notes
|
||||
=======================
|
||||
|
||||
Intel x86
|
||||
---------
|
||||
|
||||
There are no known problems with the x86 port.
|
||||
|
||||
Sun SPARC - SunOS 4.1.3 & Solaris 2.x
|
||||
-------------------------------------
|
||||
|
||||
You must use GNU Make to build libffi on Sun platforms.
|
||||
|
||||
MIPS - Irix 5.3 & 6.x
|
||||
---------------------
|
||||
|
||||
|
@ -339,13 +129,6 @@ If you don't do this you are liable to get spurious bus errors.
|
|||
|
||||
You must use GNU Make to build libffi on SGI platforms.
|
||||
|
||||
ARM - System V ABI
|
||||
------------------
|
||||
|
||||
The ARM port was performed on a NetWinder running ARM Linux ELF
|
||||
(2.0.31) and gcc 2.8.1.
|
||||
|
||||
|
||||
|
||||
PowerPC System V ABI
|
||||
--------------------
|
||||
|
@ -372,18 +155,31 @@ single-precision anyway. This causes one test to fail (the `many
|
|||
arguments' test).
|
||||
|
||||
|
||||
What's With The Crazy Comments?
|
||||
===============================
|
||||
|
||||
You might notice a number of cryptic comments in the code, delimited
|
||||
by /*@ and @*/. These are annotations read by the program LCLint, a
|
||||
tool for statically checking C programs. You can read all about it at
|
||||
<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>.
|
||||
|
||||
|
||||
History
|
||||
=======
|
||||
|
||||
3.0.4 Feb-24-08
|
||||
Fix x86 OpenBSD configury.
|
||||
|
||||
3.0.3 Feb-22-08
|
||||
Enable x86 OpenBSD thanks to Thomas Heller, and
|
||||
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
|
||||
Clean up test instruction in README.
|
||||
|
||||
3.0.2 Feb-21-08
|
||||
Improved x86 FreeBSD support.
|
||||
Thanks to Björn König.
|
||||
|
||||
3.0.1 Feb-15-08
|
||||
Fix instruction cache flushing bug on MIPS.
|
||||
Thanks to David Daney.
|
||||
|
||||
3.0.0 Feb-15-08
|
||||
Many changes, mostly thanks to the GCC project.
|
||||
Cygnus Solutions is now Red Hat.
|
||||
|
||||
[10 years go by...]
|
||||
|
||||
1.20 Oct-5-98
|
||||
Raffaele Sena produces ARM port.
|
||||
|
||||
|
@ -467,34 +263,56 @@ History
|
|||
Authors & Credits
|
||||
=================
|
||||
|
||||
libffi was written by Anthony Green <green@cygnus.com>.
|
||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
||||
|
||||
Portions of libffi were derived from Gianni Mariani's free gencall
|
||||
library for Silicon Graphics machines.
|
||||
The developers of the GNU Compiler Collection project have made
|
||||
innumerable valuable contributions. See the ChangeLog file for
|
||||
details.
|
||||
|
||||
Some of the ideas behind libffi were inspired by Gianni Mariani's free
|
||||
gencall library for Silicon Graphics machines.
|
||||
|
||||
The closure mechanism was designed and implemented by Kresten Krab
|
||||
Thorup.
|
||||
|
||||
The Sparc port was derived from code contributed by the fine folks at
|
||||
Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
|
||||
made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
|
||||
Major processor architecture ports were contributed by the following
|
||||
developers:
|
||||
|
||||
The Alpha port was written by Richard Henderson at Cygnus Solutions.
|
||||
|
||||
Andreas Schwab ported libffi to m68k Linux and provided a number of
|
||||
bug fixes.
|
||||
|
||||
Geoffrey Keating ported libffi to the PowerPC.
|
||||
|
||||
Raffaele Sena ported libffi to the ARM.
|
||||
alpha Richard Henderson
|
||||
arm Raffaele Sena
|
||||
cris Simon Posnjak, Hans-Peter Nilsson
|
||||
frv Anthony Green
|
||||
ia64 Hans Boehm
|
||||
m32r Kazuhiro Inaoka
|
||||
m68k Andreas Schwab
|
||||
mips Anthony Green, Casey Marshall
|
||||
mips64 David Daney
|
||||
pa Randolph Chung, Dave Anglin, Andreas Tobler
|
||||
powerpc Geoffrey Keating, Andreas Tobler,
|
||||
David Edelsohn, John Hornkvist
|
||||
powerpc64 Jakub Jelinek
|
||||
s390 Gerhard Tonn, Ulrich Weigand
|
||||
sh Kaz Kojima
|
||||
sh64 Kaz Kojima
|
||||
sparc Anthony Green, Gordon Irlam
|
||||
x86 Anthony Green, Jon Beniston
|
||||
x86-64 Bo Thorsen
|
||||
|
||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
||||
stepping through the code and tracking down bugs.
|
||||
|
||||
Thanks also to Tom Tromey for bug fixes and configuration help.
|
||||
Thanks also to Tom Tromey for bug fixes, documentation and
|
||||
configuration help.
|
||||
|
||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
||||
interface.
|
||||
|
||||
Andreas Tobler has done a tremendous amount of work on the testsuite.
|
||||
|
||||
Alex Oliva solved the executable page problem for SElinux.
|
||||
|
||||
The list above is almost certainly incomplete and inaccurate. I'm
|
||||
happy to make corrections or additions upon request.
|
||||
|
||||
If you have a problem, or have found a bug, please send a note to
|
||||
green@cygnus.com.
|
||||
green@redhat.com.
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
# mmap(2) blacklisting. Some platforms provide the mmap library routine
|
||||
# but don't support all of the features we need from it.
|
||||
AC_DEFUN([AC_FUNC_MMAP_BLACKLIST],
|
||||
[
|
||||
AC_CHECK_HEADER([sys/mman.h],
|
||||
[libffi_header_sys_mman_h=yes], [libffi_header_sys_mman_h=no])
|
||||
AC_CHECK_FUNC([mmap], [libffi_func_mmap=yes], [libffi_func_mmap=no])
|
||||
if test "$libffi_header_sys_mman_h" != yes \
|
||||
|| test "$libffi_func_mmap" != yes; then
|
||||
ac_cv_func_mmap_file=no
|
||||
ac_cv_func_mmap_dev_zero=no
|
||||
ac_cv_func_mmap_anon=no
|
||||
else
|
||||
AC_CACHE_CHECK([whether read-only mmap of a plain file works],
|
||||
ac_cv_func_mmap_file,
|
||||
[# Add a system to this blacklist if
|
||||
# mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
|
||||
# memory area containing the same data that you'd get if you applied
|
||||
# read() to the same fd. The only system known to have a problem here
|
||||
# is VMS, where text files have record structure.
|
||||
case "$host_os" in
|
||||
vms* | ultrix*)
|
||||
ac_cv_func_mmap_file=no ;;
|
||||
*)
|
||||
ac_cv_func_mmap_file=yes;;
|
||||
esac])
|
||||
AC_CACHE_CHECK([whether mmap from /dev/zero works],
|
||||
ac_cv_func_mmap_dev_zero,
|
||||
[# Add a system to this blacklist if it has mmap() but /dev/zero
|
||||
# does not exist, or if mmapping /dev/zero does not give anonymous
|
||||
# zeroed pages with both the following properties:
|
||||
# 1. If you map N consecutive pages in with one call, and then
|
||||
# unmap any subset of those pages, the pages that were not
|
||||
# explicitly unmapped remain accessible.
|
||||
# 2. If you map two adjacent blocks of memory and then unmap them
|
||||
# both at once, they must both go away.
|
||||
# Systems known to be in this category are Windows (all variants),
|
||||
# VMS, and Darwin.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
|
||||
ac_cv_func_mmap_dev_zero=no ;;
|
||||
*)
|
||||
ac_cv_func_mmap_dev_zero=yes;;
|
||||
esac])
|
||||
|
||||
# Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
|
||||
AC_CACHE_CHECK([for MAP_ANON(YMOUS)], ac_cv_decl_map_anon,
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
],
|
||||
[int n = MAP_ANONYMOUS;],
|
||||
ac_cv_decl_map_anon=yes,
|
||||
ac_cv_decl_map_anon=no)])
|
||||
|
||||
if test $ac_cv_decl_map_anon = no; then
|
||||
ac_cv_func_mmap_anon=no
|
||||
else
|
||||
AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
|
||||
ac_cv_func_mmap_anon,
|
||||
[# Add a system to this blacklist if it has mmap() and MAP_ANON or
|
||||
# MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
# doesn't give anonymous zeroed pages with the same properties listed
|
||||
# above for use of /dev/zero.
|
||||
# Systems known to be in this category are Windows, VMS, and SCO Unix.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | sco* | udk* )
|
||||
ac_cv_func_mmap_anon=no ;;
|
||||
*)
|
||||
ac_cv_func_mmap_anon=yes;;
|
||||
esac])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $ac_cv_func_mmap_file = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_FILE, 1,
|
||||
[Define if read-only mmap of a plain file works.])
|
||||
fi
|
||||
if test $ac_cv_func_mmap_dev_zero = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
|
||||
[Define if mmap of /dev/zero works.])
|
||||
fi
|
||||
if test $ac_cv_func_mmap_anon = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_ANON, 1,
|
||||
[Define if mmap with MAP_ANON(YMOUS) works.])
|
||||
fi
|
||||
])
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,10 @@
|
|||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
|
||||
# Inc.
|
||||
|
||||
timestamp='2005-04-22'
|
||||
timestamp='2007-04-29'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
|
@ -21,14 +22,15 @@ timestamp='2005-04-22'
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
#
|
||||
|
@ -83,11 +85,11 @@ Try \`$me --help' for more information."
|
|||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
--time-stamp | --time* | -t )
|
||||
echo "$timestamp" ; exit 0 ;;
|
||||
echo "$timestamp" ; exit ;;
|
||||
--version | -v )
|
||||
echo "$version" ; exit 0 ;;
|
||||
echo "$version" ; exit ;;
|
||||
--help | --h* | -h )
|
||||
echo "$usage"; exit 0 ;;
|
||||
echo "$usage"; exit ;;
|
||||
-- ) # Stop option processing
|
||||
shift; break ;;
|
||||
- ) # Use stdin as input.
|
||||
|
@ -99,7 +101,7 @@ while test $# -gt 0 ; do
|
|||
*local*)
|
||||
# First pass through any local machine types.
|
||||
echo $1
|
||||
exit 0;;
|
||||
exit ;;
|
||||
|
||||
* )
|
||||
break ;;
|
||||
|
@ -118,8 +120,9 @@ esac
|
|||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
|
||||
kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
|
@ -170,6 +173,10 @@ case $os in
|
|||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
-sco6)
|
||||
os=-sco5v6
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5)
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
|
@ -186,6 +193,10 @@ case $os in
|
|||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5v6*)
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco*)
|
||||
os=-sco3.2v2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
|
@ -230,15 +241,16 @@ case $basic_machine in
|
|||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| fido | fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
|
@ -247,6 +259,7 @@ case $basic_machine in
|
|||
| mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr4300 | mips64vr4300el \
|
||||
| mips64vr5000 | mips64vr5000el \
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
|
@ -255,21 +268,24 @@ case $basic_machine in
|
|||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
| ns16k | ns32k \
|
||||
| openrisc | or32 \
|
||||
| or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| we32k \
|
||||
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| z8k)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
|
@ -280,6 +296,9 @@ case $basic_machine in
|
|||
;;
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||
;;
|
||||
ms1)
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
|
@ -299,18 +318,18 @@ case $basic_machine in
|
|||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* \
|
||||
| avr-* | avr32-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| m32r-* | m32rle-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
|
@ -321,6 +340,7 @@ case $basic_machine in
|
|||
| mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* \
|
||||
| mips64vr5000-* | mips64vr5000el-* \
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
|
@ -329,24 +349,26 @@ case $basic_machine in
|
|||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nios-* | nios2-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| xstormy16-* | xtensa-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
|
@ -661,6 +683,10 @@ case $basic_machine in
|
|||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
basic_machine=arm-unknown
|
||||
os=-mingw32ce
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
|
@ -686,6 +712,9 @@ case $basic_machine in
|
|||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
;;
|
||||
ms1-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
|
@ -761,9 +790,8 @@ case $basic_machine in
|
|||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
or32 | or32-*)
|
||||
openrisc | openrisc-*)
|
||||
basic_machine=or32-unknown
|
||||
os=-coff
|
||||
;;
|
||||
os400)
|
||||
basic_machine=powerpc-ibm
|
||||
|
@ -794,6 +822,12 @@ case $basic_machine in
|
|||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pc98)
|
||||
basic_machine=i386-pc
|
||||
;;
|
||||
pc98-*)
|
||||
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
|
@ -850,6 +884,10 @@ case $basic_machine in
|
|||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rom68k)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
|
@ -876,6 +914,10 @@ case $basic_machine in
|
|||
sb1el)
|
||||
basic_machine=mipsisa64sb1el-unknown
|
||||
;;
|
||||
sde)
|
||||
basic_machine=mipsisa32-sde
|
||||
os=-elf
|
||||
;;
|
||||
sei)
|
||||
basic_machine=mips-sei
|
||||
os=-seiux
|
||||
|
@ -887,6 +929,9 @@ case $basic_machine in
|
|||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh5el)
|
||||
basic_machine=sh5le-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
|
@ -1089,13 +1134,10 @@ case $basic_machine in
|
|||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b)
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
|
@ -1168,20 +1210,23 @@ case $os in
|
|||
| -aos* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -openbsd* | -solidbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
|
@ -1199,7 +1244,7 @@ case $os in
|
|||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
|
@ -1333,6 +1378,12 @@ else
|
|||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
score-*)
|
||||
os=-elf
|
||||
;;
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
os=-riscix1.2
|
||||
;;
|
||||
|
@ -1342,9 +1393,9 @@ case $basic_machine in
|
|||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
|
@ -1370,6 +1421,9 @@ case $basic_machine in
|
|||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
|
@ -1388,6 +1442,9 @@ case $basic_machine in
|
|||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-haiku)
|
||||
os=-haiku
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
|
@ -1559,7 +1616,7 @@ case $basic_machine in
|
|||
esac
|
||||
|
||||
echo $basic_machine$os
|
||||
exit 0
|
||||
exit
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,12 +2,21 @@ dnl Process this with autoconf to create configure
|
|||
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
AC_INIT([libffi], [2.1], [http://gcc.gnu.org/bugs.html])
|
||||
AC_INIT([libffi], [3.0.4], [http://gcc.gnu.org/bugs.html])
|
||||
AC_CONFIG_HEADERS([fficonfig.h])
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
target_alias=${target_alias-$host_alias}
|
||||
|
||||
. ${srcdir}/configure.host
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
# The same as in boehm-gc and libstdc++. Have to borrow it from there.
|
||||
# We must force CC to /not/ be precious variables; otherwise
|
||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
||||
# As a side effect, we have to subst CFLAGS ourselves.
|
||||
|
||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
||||
AC_PROG_CC
|
||||
|
@ -15,79 +24,162 @@ m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
|||
|
||||
AC_SUBST(CFLAGS)
|
||||
|
||||
AM_PROG_AS
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_CHECK_HEADERS(sys/mman.h)
|
||||
AC_CHECK_FUNCS(mmap)
|
||||
AC_FUNC_MMAP_BLACKLIST
|
||||
|
||||
dnl The -no-testsuite modules omit the test subdir.
|
||||
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
||||
|
||||
TARGETDIR="unknown"
|
||||
case "$host" in
|
||||
x86_64-*-openbsd*) TARGET=X86_64; TARGETDIR=x86;;
|
||||
mips*-*-openbsd*) TARGET=MIPS; TARGETDIR=mips;;
|
||||
sparc-*-openbsd*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc64-*-openbsd*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
alpha*-*-openbsd*) TARGET=ALPHA; TARGETDIR=alpha;;
|
||||
m68k-*-openbsd*) TARGET=M68K; TARGETDIR=m68k;;
|
||||
powerpc-*-openbsd*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
|
||||
i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-solaris2.1[[0-9]]*) TARGET=X86_64; TARGETDIR=x86;;
|
||||
i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-freebsd* | i*86-*-kfreebsd*-gnu) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-netbsdelf* | i*86-*-knetbsd*-gnu) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-openbsd*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-rtems*) TARGET=X86; TARGETDIR=x86;;
|
||||
i*86-*-win32*) TARGET=X86_WIN32; TARGETDIR=x86;;
|
||||
i*86-*-cygwin*) TARGET=X86_WIN32; TARGETDIR=x86;;
|
||||
i*86-*-mingw*) TARGET=X86_WIN32; TARGETDIR=x86;;
|
||||
frv-*-*) TARGET=FRV; TARGETDIR=frv;;
|
||||
sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc*-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc-*-linux* | sparc-*-netbsdelf* | sparc-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc*-*-rtems*) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
sparc64-*-linux* | sparc64-*-freebsd* | sparc64-*-netbsd* | sparc64-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
|
||||
alpha*-*-linux* | alpha*-*-osf* | alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu | alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu) TARGET=ALPHA; TARGETDIR=alpha;;
|
||||
ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
|
||||
m32r*-*-linux* ) TARGET=M32R; TARGETDIR=m32r;;
|
||||
m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
|
||||
mips64*-*);;
|
||||
mips-sgi-irix5.* | mips-sgi-irix6.*) TARGET=MIPS_IRIX; TARGETDIR=mips;;
|
||||
mips*-*-linux*) TARGET=MIPS_LINUX; TARGETDIR=mips;;
|
||||
powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;;
|
||||
powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
|
||||
powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;;
|
||||
powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;;
|
||||
rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
|
||||
arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
|
||||
arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) TARGET=ARM; TARGETDIR=arm;;
|
||||
arm*-*-rtems*) TARGET=ARM; TARGETDIR=arm;;
|
||||
cris-*-*) TARGET=LIBFFI_CRIS; TARGETDIR=cris;;
|
||||
s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
|
||||
s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
|
||||
amd64-*-freebsd* | x86_64-*-linux* | x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) TARGET=X86_64; TARGETDIR=x86;;
|
||||
sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
|
||||
sh-*-rtems*) TARGET=SH; TARGETDIR=sh;;
|
||||
sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
|
||||
hppa*-*-linux* | parisc*-*-linux*) TARGET=PA; TARGETDIR=pa;;
|
||||
alpha*-*-*)
|
||||
TARGET=ALPHA; TARGETDIR=alpha;
|
||||
# Support 128-bit long double, changable via command-line switch.
|
||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
||||
;;
|
||||
|
||||
arm*-*-*)
|
||||
TARGET=ARM; TARGETDIR=arm
|
||||
;;
|
||||
|
||||
amd64-*-freebsd*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
|
||||
cris-*-*)
|
||||
TARGET=LIBFFI_CRIS; TARGETDIR=cris
|
||||
;;
|
||||
|
||||
frv-*-*)
|
||||
TARGET=FRV; TARGETDIR=frv
|
||||
;;
|
||||
|
||||
hppa*-*-linux* | parisc*-*-linux*)
|
||||
TARGET=PA_LINUX; TARGETDIR=pa
|
||||
;;
|
||||
hppa*64-*-hpux*)
|
||||
TARGET=PA64_HPUX; TARGETDIR=pa
|
||||
;;
|
||||
hppa*-*-hpux*)
|
||||
TARGET=PA_HPUX; TARGETDIR=pa
|
||||
;;
|
||||
|
||||
i386-*-freebsd* | i386-*-openbsd*)
|
||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
||||
;;
|
||||
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw*)
|
||||
TARGET=X86_WIN32; TARGETDIR=x86
|
||||
;;
|
||||
i?86-*-darwin*)
|
||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
||||
;;
|
||||
i?86-*-solaris2.1[[0-9]]*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
i?86-*-*)
|
||||
TARGET=X86; TARGETDIR=x86
|
||||
;;
|
||||
|
||||
ia64*-*-*)
|
||||
TARGET=IA64; TARGETDIR=ia64
|
||||
;;
|
||||
|
||||
m32r*-*-*)
|
||||
TARGET=M32R; TARGETDIR=m32r
|
||||
;;
|
||||
|
||||
m68k-*-*)
|
||||
TARGET=M68K; TARGETDIR=m68k
|
||||
;;
|
||||
|
||||
mips-sgi-irix5.* | mips-sgi-irix6.*)
|
||||
TARGET=MIPS; TARGETDIR=mips
|
||||
;;
|
||||
mips*-*-linux*)
|
||||
TARGET=MIPS; TARGETDIR=mips
|
||||
;;
|
||||
|
||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-beos*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-darwin*)
|
||||
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-aix* | rs6000-*-aix*)
|
||||
TARGET=POWERPC_AIX; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc-*-freebsd*)
|
||||
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
|
||||
;;
|
||||
powerpc*-*-rtems*)
|
||||
TARGET=POWERPC; TARGETDIR=powerpc
|
||||
;;
|
||||
|
||||
s390-*-* | s390x-*-*)
|
||||
TARGET=S390; TARGETDIR=s390
|
||||
;;
|
||||
|
||||
sh-*-* | sh[[34]]*-*-*)
|
||||
TARGET=SH; TARGETDIR=sh
|
||||
;;
|
||||
sh64-*-* | sh5*-*-*)
|
||||
TARGET=SH64; TARGETDIR=sh64
|
||||
;;
|
||||
|
||||
sparc*-*-*)
|
||||
TARGET=SPARC; TARGETDIR=sparc
|
||||
;;
|
||||
|
||||
x86_64-*-darwin*)
|
||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
||||
;;
|
||||
x86_64-*-cygwin* | x86_64-*-mingw*)
|
||||
;;
|
||||
x86_64-*-*)
|
||||
TARGET=X86_64; TARGETDIR=x86
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(AM_RUNTESTFLAGS)
|
||||
|
||||
if test $TARGETDIR = unknown; then
|
||||
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
||||
fi
|
||||
|
||||
dnl libffi changes TARGET for MIPS to define a such macro in the header
|
||||
dnl while MIPS_IRIX or MIPS_LINUX is separatedly used to decide which
|
||||
dnl files will be compiled. So, we need to keep the original decision
|
||||
dnl of TARGET to use in fficonfig.py.in.
|
||||
MKTARGET=$TARGET
|
||||
|
||||
case x$TARGET in
|
||||
xMIPS*) TARGET=MIPS ;;
|
||||
*) ;;
|
||||
esac
|
||||
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
|
||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
||||
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
|
||||
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
|
||||
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
|
||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
||||
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
|
||||
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
|
||||
AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
|
||||
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
|
||||
AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
|
||||
AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
|
||||
AM_CONDITIONAL(S390, test x$TARGET = xS390)
|
||||
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
|
||||
AM_CONDITIONAL(SH, test x$TARGET = xSH)
|
||||
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
|
||||
AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
|
||||
AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
|
||||
AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_FUNCS(memcpy)
|
||||
|
@ -97,34 +189,30 @@ AC_CHECK_SIZEOF(double)
|
|||
AC_CHECK_SIZEOF(long double)
|
||||
|
||||
# Also AC_SUBST this variable for ffi.h.
|
||||
HAVE_LONG_DOUBLE=0
|
||||
if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
||||
if test $ac_cv_sizeof_long_double != 0; then
|
||||
HAVE_LONG_DOUBLE=1
|
||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
|
||||
if test -z "$HAVE_LONG_DOUBLE"; then
|
||||
HAVE_LONG_DOUBLE=0
|
||||
if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
||||
if test $ac_cv_sizeof_long_double != 0; then
|
||||
HAVE_LONG_DOUBLE=1
|
||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(HAVE_LONG_DOUBLE)
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
AH_VERBATIM([WORDS_BIGENDIAN],
|
||||
[
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX).
|
||||
|
||||
The block below does compile-time checking for endianness on platforms
|
||||
that use GCC and therefore allows compiling fat binaries on OSX by using
|
||||
'-arch ppc -arch i386' as the compile flags. The phrasing was choosen
|
||||
such that the configure-result is used on systems that don't use GCC.
|
||||
*/
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define WORDS_BIGENDIAN 1
|
||||
#else
|
||||
#ifndef __LITTLE_ENDIAN__
|
||||
#undef WORDS_BIGENDIAN
|
||||
#endif
|
||||
#endif])
|
||||
|
||||
AC_CACHE_CHECK([assembler .cfi pseudo-op support],
|
||||
libffi_cv_as_cfi_pseudo_op, [
|
||||
libffi_cv_as_cfi_pseudo_op=unknown
|
||||
AC_TRY_COMPILE([asm (".cfi_startproc\n\t.cfi_endproc");],,
|
||||
[libffi_cv_as_cfi_pseudo_op=yes],
|
||||
[libffi_cv_as_cfi_pseudo_op=no])
|
||||
])
|
||||
if test "x$libffi_cv_as_cfi_pseudo_op" = xyes; then
|
||||
AC_DEFINE(HAVE_AS_CFI_PSEUDO_OP, 1,
|
||||
[Define if your assembler supports .cfi_* directives.])
|
||||
fi
|
||||
|
||||
if test x$TARGET = xSPARC; then
|
||||
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
|
||||
|
@ -215,11 +303,54 @@ AH_BOTTOM([
|
|||
|
||||
AC_SUBST(TARGET)
|
||||
AC_SUBST(TARGETDIR)
|
||||
AC_SUBST(MKTARGET)
|
||||
|
||||
AC_SUBST(SHELL)
|
||||
|
||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
||||
AC_ARG_ENABLE(debug,
|
||||
[ --enable-debug debugging mode],
|
||||
if test "$enable_debug" = "yes"; then
|
||||
AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
|
||||
fi)
|
||||
|
||||
AC_ARG_ENABLE(structs,
|
||||
[ --disable-structs omit code for struct support],
|
||||
if test "$enable_structs" = "no"; then
|
||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
|
||||
fi)
|
||||
|
||||
AC_ARG_ENABLE(raw-api,
|
||||
[ --disable-raw-api make the raw api unavailable],
|
||||
if test "$enable_raw_api" = "no"; then
|
||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
||||
fi)
|
||||
|
||||
AC_ARG_ENABLE(purify-safety,
|
||||
[ --enable-purify-safety purify-safe mode],
|
||||
if test "$enable_purify_safety" = "yes"; then
|
||||
AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
|
||||
fi)
|
||||
|
||||
if test -n "$with_cross_host" &&
|
||||
test x"$with_cross_host" != x"no"; then
|
||||
toolexecdir='$(exec_prefix)/$(target_alias)'
|
||||
toolexeclibdir='$(toolexecdir)/lib'
|
||||
else
|
||||
toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
|
||||
toolexeclibdir='$(libdir)'
|
||||
fi
|
||||
multi_os_directory=`$CC -print-multi-os-directory`
|
||||
case $multi_os_directory in
|
||||
.) ;; # Avoid trailing /.
|
||||
*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
|
||||
esac
|
||||
AC_SUBST(toolexecdir)
|
||||
AC_SUBST(toolexeclibdir)
|
||||
|
||||
if test "${multilib}" = "yes"; then
|
||||
multilib_arg="--enable-multilib"
|
||||
else
|
||||
multilib_arg=
|
||||
fi
|
||||
|
||||
AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
|
||||
AC_CONFIG_COMMANDS(src, [
|
||||
|
@ -227,17 +358,12 @@ test -d src || mkdir src
|
|||
test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
||||
], [TARGETDIR="$TARGETDIR"])
|
||||
|
||||
TARGETINCDIR=$TARGETDIR
|
||||
case $host in
|
||||
*-*-darwin*)
|
||||
TARGETINCDIR="darwin"
|
||||
;;
|
||||
esac
|
||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
||||
|
||||
AC_CONFIG_FILES(include/ffi.h)
|
||||
|
||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETINCDIR/ffitarget.h)
|
||||
AC_CONFIG_LINKS(include/ffi_common.h:include/ffi_common.h)
|
||||
|
||||
AC_CONFIG_FILES(include/ffi.h fficonfig.py)
|
||||
AC_CONFIG_FILES(fficonfig.py)
|
||||
|
||||
AC_OUTPUT
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# configure.host
|
||||
#
|
||||
# This shell script handles all host based configuration for libffi.
|
||||
#
|
||||
|
||||
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
|
||||
case "${host}" in
|
||||
frv*-elf)
|
||||
LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
|
||||
;;
|
||||
esac
|
|
@ -11,9 +11,15 @@
|
|||
/* Define to the flags needed for the .section .eh_frame directive. */
|
||||
#undef EH_FRAME_FLAGS
|
||||
|
||||
/* Define this if you want extra debugging. */
|
||||
#undef FFI_DEBUG
|
||||
|
||||
/* Define this is you do not want support for the raw API. */
|
||||
#undef FFI_NO_RAW_API
|
||||
|
||||
/* Define this is you do not want support for aggregate types. */
|
||||
#undef FFI_NO_STRUCTS
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#undef HAVE_ALLOCA
|
||||
|
||||
|
@ -21,6 +27,9 @@
|
|||
*/
|
||||
#undef HAVE_ALLOCA_H
|
||||
|
||||
/* Define if your assembler supports .cfi_* directives. */
|
||||
#undef HAVE_AS_CFI_PSEUDO_OP
|
||||
|
||||
/* Define if your assembler supports .register. */
|
||||
#undef HAVE_AS_REGISTER_PSEUDO_OP
|
||||
|
||||
|
@ -28,6 +37,9 @@
|
|||
*/
|
||||
#undef HAVE_AS_SPARC_UA_PCREL
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define if __attribute__((visibility("hidden"))) is supported. */
|
||||
#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
|
||||
|
@ -82,6 +94,12 @@
|
|||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
|
@ -114,22 +132,16 @@
|
|||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define this if you are using Purify and want to suppress spurious messages.
|
||||
*/
|
||||
#undef USING_PURIFY
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX).
|
||||
|
||||
The block below does compile-time checking for endianness on platforms
|
||||
that use GCC and therefore allows compiling fat binaries on OSX by using
|
||||
'-arch ppc -arch i386' as the compile flags. The phrasing was choosen
|
||||
such that the configure-result is used on systems that don't use GCC.
|
||||
*/
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define WORDS_BIGENDIAN 1
|
||||
#else
|
||||
#ifndef __LITTLE_ENDIAN__
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#undef WORDS_BIGENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
|
|
|
@ -6,7 +6,7 @@ ffi_platforms = {
|
|||
'MIPS_IRIX': ['src/mips/ffi.c', 'src/mips/o32.S', 'src/mips/n32.S'],
|
||||
'MIPS_LINUX': ['src/mips/ffi.c', 'src/mips/o32.S'],
|
||||
'X86': ['src/x86/ffi.c', 'src/x86/sysv.S'],
|
||||
'X86_DARWIN': ['src/x86/ffi_darwin.c', 'src/x86/darwin.S'],
|
||||
'X86_FREEBSD': ['src/x86/ffi.c', 'src/x86/sysv.S'],
|
||||
'X86_WIN32': ['src/x86/ffi.c', 'src/x86/win32.S'],
|
||||
'SPARC': ['src/sparc/ffi.c', 'src/sparc/v8.S', 'src/sparc/v9.S'],
|
||||
'ALPHA': ['src/alpha/ffi.c', 'src/alpha/osf.S'],
|
||||
|
@ -14,8 +14,7 @@ ffi_platforms = {
|
|||
'M32R': ['src/m32r/sysv.S', 'src/m32r/ffi.c'],
|
||||
'M68K': ['src/m68k/ffi.c', 'src/m68k/sysv.S'],
|
||||
'POWERPC': ['src/powerpc/ffi.c', 'src/powerpc/sysv.S', 'src/powerpc/ppc_closure.S', 'src/powerpc/linux64.S', 'src/powerpc/linux64_closure.S'],
|
||||
'POWERPC_AIX': ['src/powerpc/ffi_darwin.c', 'src/powerpc/aix.S', 'src/powerpc/aix_closure.S'],
|
||||
'POWERPC_DARWIN': ['src/powerpc/ffi_darwin.c', 'src/powerpc/darwin.S', 'src/powerpc/darwin_closure.S'],
|
||||
'POWERPC_AIX': ['src/powerpc/ffi.c', 'src/powerpc/aix.S', 'src/powerpc/aix_closure.S'],
|
||||
'POWERPC_FREEBSD': ['src/powerpc/ffi.c', 'src/powerpc/sysv.S', 'src/powerpc/ppc_closure.S'],
|
||||
'ARM': ['src/arm/sysv.S', 'src/arm/ffi.c'],
|
||||
'LIBFFI_CRIS': ['src/cris/sysv.S', 'src/cris/ffi.c'],
|
||||
|
@ -27,19 +26,8 @@ ffi_platforms = {
|
|||
'PA': ['src/pa/linux.S', 'src/pa/ffi.c'],
|
||||
}
|
||||
|
||||
# Build all darwin related files on all supported darwin architectures, this
|
||||
# makes it easier to build universal binaries.
|
||||
if 1:
|
||||
all_darwin = ('X86_DARWIN', 'POWERPC_DARWIN')
|
||||
all_darwin_files = []
|
||||
for pn in all_darwin:
|
||||
all_darwin_files.extend(ffi_platforms[pn])
|
||||
for pn in all_darwin:
|
||||
ffi_platforms[pn] = all_darwin_files
|
||||
del all_darwin, all_darwin_files, pn
|
||||
|
||||
ffi_srcdir = '@srcdir@'
|
||||
ffi_sources += ffi_platforms['@MKTARGET@']
|
||||
ffi_sources += ffi_platforms['@TARGET@']
|
||||
ffi_sources = [os.path.join('@srcdir@', f) for f in ffi_sources]
|
||||
|
||||
ffi_cflags = '@CFLAGS@'
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
## Process this with automake to create Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
|
||||
DISTCLEANFILES=ffitarget.h
|
||||
EXTRA_DIST=ffi.h.in ffi_common.h
|
||||
|
||||
includesdir = $(libdir)/@PACKAGE_NAME@-@PACKAGE_VERSION@/include
|
||||
nodist_includes_HEADERS = ffi.h ffitarget.h
|
|
@ -0,0 +1,422 @@
|
|||
# Makefile.in generated by automake 1.10 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
subdir = include
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
||||
$(srcdir)/ffi.h.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/fficonfig.h
|
||||
CONFIG_CLEAN_FILES = ffi.h ffitarget.h
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||
am__installdirs = "$(DESTDIR)$(includesdir)"
|
||||
nodist_includesHEADERS_INSTALL = $(INSTALL_HEADER)
|
||||
HEADERS = $(nodist_includes_HEADERS)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ALLOCA = @ALLOCA@
|
||||
AMTAR = @AMTAR@
|
||||
AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCAS = @CCAS@
|
||||
CCASDEPMODE = @CCASDEPMODE@
|
||||
CCASFLAGS = @CCASFLAGS@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
GREP = @GREP@
|
||||
HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
TARGET = @TARGET@
|
||||
TARGETDIR = @TARGETDIR@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
toolexecdir = @toolexecdir@
|
||||
toolexeclibdir = @toolexeclibdir@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
DISTCLEANFILES = ffitarget.h
|
||||
EXTRA_DIST = ffi.h.in ffi_common.h
|
||||
includesdir = $(libdir)/@PACKAGE_NAME@-@PACKAGE_VERSION@/include
|
||||
nodist_includes_HEADERS = ffi.h ffitarget.h
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign include/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
ffi.h: $(top_builddir)/config.status $(srcdir)/ffi.h.in
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-nodist_includesHEADERS: $(nodist_includes_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(includesdir)" || $(MKDIR_P) "$(DESTDIR)$(includesdir)"
|
||||
@list='$(nodist_includes_HEADERS)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
f=$(am__strip_dir) \
|
||||
echo " $(nodist_includesHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includesdir)/$$f'"; \
|
||||
$(nodist_includesHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includesdir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-nodist_includesHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(nodist_includes_HEADERS)'; for p in $$list; do \
|
||||
f=$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(includesdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(includesdir)/$$f"; \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(includesdir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-nodist_includesHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-nodist_includesHEADERS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool ctags distclean distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-nodist_includesHEADERS \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags uninstall uninstall-am uninstall-nodist_includesHEADERS
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi @VERSION@ - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
libffi @VERSION@ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -12,13 +12,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
@ -82,6 +83,18 @@ extern "C" {
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* The closure code assumes that this works on pointers, i.e. a size_t */
|
||||
/* can hold a pointer. */
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
size_t size;
|
||||
unsigned short alignment;
|
||||
unsigned short type;
|
||||
struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
|
||||
#ifndef LIBFFI_HIDE_BASIC_TYPES
|
||||
#if SCHAR_MAX == 127
|
||||
# define ffi_type_uchar ffi_type_uint8
|
||||
# define ffi_type_schar ffi_type_sint8
|
||||
|
@ -112,26 +125,23 @@ extern "C" {
|
|||
#error "int size not supported"
|
||||
#endif
|
||||
|
||||
#define ffi_type_ulong ffi_type_uint64
|
||||
#define ffi_type_slong ffi_type_sint64
|
||||
#if LONG_MAX == 2147483647
|
||||
# if FFI_LONG_LONG_MAX != 9223372036854775807
|
||||
#error "no 64-bit data type supported"
|
||||
#error "no 64-bit data type supported"
|
||||
# endif
|
||||
#elif LONG_MAX != 9223372036854775807
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* The closure code assumes that this works on pointers, i.e. a size_t */
|
||||
/* can hold a pointer. */
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
size_t size;
|
||||
unsigned short alignment;
|
||||
unsigned short type;
|
||||
/*@null@*/ struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
#if LONG_MAX == 2147483647
|
||||
# define ffi_type_ulong ffi_type_uint32
|
||||
# define ffi_type_slong ffi_type_sint32
|
||||
#elif LONG_MAX == 9223372036854775807
|
||||
# define ffi_type_ulong ffi_type_uint64
|
||||
# define ffi_type_slong ffi_type_sint64
|
||||
#else
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* These are defined in types.c */
|
||||
extern ffi_type ffi_type_void;
|
||||
|
@ -145,14 +155,19 @@ extern ffi_type ffi_type_uint64;
|
|||
extern ffi_type ffi_type_sint64;
|
||||
extern ffi_type ffi_type_float;
|
||||
extern ffi_type ffi_type_double;
|
||||
extern ffi_type ffi_type_longdouble;
|
||||
extern ffi_type ffi_type_pointer;
|
||||
|
||||
#if @HAVE_LONG_DOUBLE@
|
||||
extern ffi_type ffi_type_longdouble;
|
||||
#else
|
||||
#define ffi_type_longdouble ffi_type_double
|
||||
#endif
|
||||
#endif /* LIBFFI_HIDE_BASIC_TYPES */
|
||||
|
||||
typedef enum {
|
||||
FFI_OK = 0,
|
||||
FFI_BAD_TYPEDEF,
|
||||
FFI_BAD_ABI
|
||||
FFI_BAD_ABI
|
||||
} ffi_status;
|
||||
|
||||
typedef unsigned FFI_TYPE;
|
||||
|
@ -160,8 +175,8 @@ typedef unsigned FFI_TYPE;
|
|||
typedef struct {
|
||||
ffi_abi abi;
|
||||
unsigned nargs;
|
||||
/*@dependent@*/ ffi_type **arg_types;
|
||||
/*@dependent@*/ ffi_type *rtype;
|
||||
ffi_type **arg_types;
|
||||
ffi_type *rtype;
|
||||
unsigned bytes;
|
||||
unsigned flags;
|
||||
#ifdef FFI_EXTRA_CIF_FIELDS
|
||||
|
@ -179,6 +194,10 @@ typedef struct {
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FFI_SIZEOF_JAVA_RAW
|
||||
# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
ffi_sarg sint;
|
||||
ffi_arg uint;
|
||||
|
@ -187,10 +206,25 @@ typedef union {
|
|||
void* ptr;
|
||||
} ffi_raw;
|
||||
|
||||
void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *avalue);
|
||||
#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
|
||||
/* This is a special case for mips64/n32 ABI (and perhaps others) where
|
||||
sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
|
||||
typedef union {
|
||||
signed int sint;
|
||||
unsigned int uint;
|
||||
float flt;
|
||||
char data[FFI_SIZEOF_JAVA_RAW];
|
||||
void* ptr;
|
||||
} ffi_java_raw;
|
||||
#else
|
||||
typedef ffi_raw ffi_java_raw;
|
||||
#endif
|
||||
|
||||
|
||||
void ffi_raw_call (ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
ffi_raw *avalue);
|
||||
|
||||
void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
|
||||
void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
|
||||
|
@ -200,13 +234,13 @@ size_t ffi_raw_size (ffi_cif *cif);
|
|||
/* packing, even on 64-bit machines. I.e. on 64-bit machines */
|
||||
/* longs and doubles are followed by an empty 64-bit word. */
|
||||
|
||||
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *avalue);
|
||||
void ffi_java_raw_call (ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
ffi_java_raw *avalue);
|
||||
|
||||
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
|
||||
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
|
||||
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
|
||||
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
|
||||
size_t ffi_java_raw_size (ffi_cif *cif);
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
@ -220,12 +254,22 @@ typedef struct {
|
|||
void *user_data;
|
||||
} ffi_closure __attribute__((aligned (8)));
|
||||
|
||||
void *ffi_closure_alloc (size_t size, void **code);
|
||||
void ffi_closure_free (void *);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure*,
|
||||
ffi_cif *,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure*,
|
||||
ffi_cif *,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void*codeloc);
|
||||
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
|
||||
|
@ -247,6 +291,27 @@ typedef struct {
|
|||
|
||||
} ffi_raw_closure;
|
||||
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
|
||||
ffi_cif *cif;
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
/* if this is enabled, then a raw closure has the same layout
|
||||
as a regular closure. We use this to install an intermediate
|
||||
handler to do the transaltion, void** -> ffi_raw*. */
|
||||
|
||||
void (*translate_args)(ffi_cif*,void*,void**,void*);
|
||||
void *this_closure;
|
||||
|
||||
#endif
|
||||
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
|
||||
void *user_data;
|
||||
|
||||
} ffi_java_raw_closure;
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
|
@ -254,28 +319,42 @@ ffi_prep_raw_closure (ffi_raw_closure*,
|
|||
void *user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_raw_closure*,
|
||||
ffi_prep_raw_closure_loc (ffi_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc);
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
/* ---- Public interface definition -------------------------------------- */
|
||||
|
||||
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
||||
/*@dependent@*/ ffi_type **atypes);
|
||||
unsigned int nargs,
|
||||
ffi_type *rtype,
|
||||
ffi_type **atypes);
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue);
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
void **avalue);
|
||||
|
||||
/* Useful for eliminating compiler warnings */
|
||||
#define FFI_FN(f) ((void (*)())f)
|
||||
#define FFI_FN(f) ((void (*)(void))f)
|
||||
|
||||
/* ---- Definitions shared with assembly code ---------------------------- */
|
||||
|
||||
|
@ -310,4 +389,3 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
|
||||
Common internal definitions and macros. Only necessary for building
|
||||
libffi.
|
||||
|
@ -18,7 +19,9 @@ extern "C" {
|
|||
this is positioned. */
|
||||
#ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
# define MAYBE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
# define MAYBE_UNUSED
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
|
@ -41,20 +44,20 @@ char *alloca ();
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(FFI_DEBUG)
|
||||
#if defined(FFI_DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef FFI_DEBUG
|
||||
/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
|
||||
void ffi_assert(char *expr, char *file, int line);
|
||||
void ffi_stop_here(void);
|
||||
void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
|
||||
void ffi_type_test(ffi_type *a, char *file, int line);
|
||||
|
||||
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
|
||||
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
|
||||
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
|
||||
#else
|
||||
#define FFI_ASSERT(x)
|
||||
#define FFI_ASSERT(x)
|
||||
#define FFI_ASSERT_AT(x, f, l)
|
||||
#define FFI_ASSERT_VALID_TYPE(x)
|
||||
#endif
|
||||
|
@ -68,9 +71,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
|
|||
/* Extended cif, used in callback from assembly routine */
|
||||
typedef struct
|
||||
{
|
||||
/*@dependent@*/ ffi_cif *cif;
|
||||
/*@dependent@*/ void *rvalue;
|
||||
/*@dependent@*/ void **avalue;
|
||||
ffi_cif *cif;
|
||||
void *rvalue;
|
||||
void **avalue;
|
||||
} extended_cif;
|
||||
|
||||
/* Terse sized type definitions. */
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
#
|
||||
|
||||
scriptversion=2004-12-17.09
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
|
@ -41,13 +42,11 @@
|
|||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
|
@ -59,236 +58,266 @@ stripprog="${STRIPPROG-strip}"
|
|||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dstarg=
|
||||
no_target_directory=
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd=$cpprog
|
||||
shift
|
||||
continue;;
|
||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
Options:
|
||||
-c (ignored)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
while test -n "$1"; do
|
||||
case $1 in
|
||||
-c) shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
--help) echo "$usage"; exit 0;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "$0: no input file specified" >&2
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ -d "$dst" ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f "$src" ] || [ -d "$src" ]
|
||||
then
|
||||
:
|
||||
else
|
||||
echo "$0: $src does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "$0: no destination specified" >&2
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d "$dst" ]
|
||||
then
|
||||
dst=$dst/`basename "$src"`
|
||||
else
|
||||
:
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS=$oIFS
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp=$pathcomp$1
|
||||
-t) dstarg=$2
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
if [ ! -d "$pathcomp" ] ;
|
||||
then
|
||||
$mkdirprog "$pathcomp"
|
||||
else
|
||||
:
|
||||
fi
|
||||
-T) no_target_directory=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
pathcomp=$pathcomp/
|
||||
--version) echo "$0 $scriptversion"; exit 0;;
|
||||
|
||||
*) # When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
test -n "$dir_arg$dstarg" && break
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dstarg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dstarg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dstarg=$arg
|
||||
done
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test -z "$1"; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd "$dst" &&
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src ;;
|
||||
esac
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
|
||||
else
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
src=
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
if test -d "$dst"; then
|
||||
mkdircmd=:
|
||||
chmodcmd=
|
||||
else
|
||||
mkdircmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
dstfile=`basename "$dst" $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
if test -z "$dstarg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
dst=$dstarg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
:
|
||||
fi
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dstarg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst/`basename "$src"`
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
# This sed command emulates the dirname command.
|
||||
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
rmtmp=$dstdir/#rm.$$#
|
||||
# Make sure that the destination directory exists.
|
||||
|
||||
# Trap to clean up temp files at exit.
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if test ! -d "$dstdir"; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
shift
|
||||
IFS=$oIFS
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
pathcomp=
|
||||
|
||||
$doit $instcmd "$src" "$dsttmp" &&
|
||||
while test $# -ne 0 ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
if test ! -d "$pathcomp"; then
|
||||
$mkdirprog "$pathcomp"
|
||||
# mkdir can fail with a `File exist' error in case several
|
||||
# install-sh are creating the directory concurrently. This
|
||||
# is OK.
|
||||
test -d "$pathcomp" || exit
|
||||
fi
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
if test -n "$dir_arg"; then
|
||||
$doit $mkdircmd "$dst" \
|
||||
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
else
|
||||
dstfile=`basename "$dst"`
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Now remove or move aside any old file at destination location. We try this
|
||||
# two ways since rm can't unlink itself on some systems and the destination
|
||||
# file might be busy for other reasons. In this case, the final cleanup
|
||||
# might fail but the new file should still install successfully.
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
{
|
||||
if [ -f "$dstdir/$dstfile" ]
|
||||
then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
|
||||
$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
|
||||
{
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
# Copy the file name to the temp name.
|
||||
$doit $cpprog "$src" "$dsttmp" &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
# Now rename the file to the real destination.
|
||||
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| {
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
|
||||
fi &&
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
if test -f "$dstdir/$dstfile"; then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
}
|
||||
}
|
||||
fi || { (exit 1); exit 1; }
|
||||
done
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
|
||||
{
|
||||
(exit 0); exit
|
||||
(exit 0); exit 0
|
||||
}
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include
|
||||
|
||||
Name: @PACKAGE_NAME@
|
||||
Description: Library supporting Foreign Function Interfaces
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -lffi
|
||||
Cflags: -I${includedir}
|
|
@ -0,0 +1,353 @@
|
|||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2004-09-07.08
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004
|
||||
# Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case "$1" in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit 0
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit 0
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program).
|
||||
case "$1" in
|
||||
lex|yacc)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
tar)
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case "$1" in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case "$f" in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison|yacc)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f y.tab.h ]; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if [ ! -f y.tab.c ]; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex|flex)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f lex.yy.c ]; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
||||
fi
|
||||
if [ -f "$file" ]; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
|
||||
fi
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar)
|
||||
shift
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case "$firstarg" in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case "$firstarg" in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998, 2001 Red Hat, Inc.
|
||||
ffi.c - Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
Alpha Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -169,10 +170,11 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
@ -33,8 +34,8 @@ typedef signed long ffi_sarg;
|
|||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
FFI_OSF,
|
||||
FFI_DEFAULT_ABI = FFI_OSF,
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
FFI_LAST_ABI,
|
||||
FFI_DEFAULT_ABI = FFI_OSF
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
|
@ -45,4 +46,3 @@ typedef enum ffi_abi {
|
|||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
osf.S - Copyright (c) 1998, 2001, 2007 Red Hat
|
||||
osf.S - Copyright (c) 1998, 2001, 2007, 2008 Red Hat
|
||||
|
||||
Alpha/OSF Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -31,7 +32,7 @@
|
|||
.text
|
||||
|
||||
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)());
|
||||
void *raddr, void (*fnaddr)(void));
|
||||
|
||||
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
|
||||
for this function. This has been allocated by ffi_call. We also
|
||||
|
@ -358,4 +359,8 @@ $LASFDE3:
|
|||
.byte 16 # uleb128 offset 16*-8
|
||||
.align 3
|
||||
$LEFDE3:
|
||||
|
||||
#ifdef __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Red Hat, Inc.
|
||||
ffi.c - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
|
||||
ARM Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -31,9 +32,7 @@
|
|||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
|
@ -42,7 +41,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
|||
|
||||
argp = stack;
|
||||
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
|
||||
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
@ -60,6 +59,9 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
|||
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
|
||||
}
|
||||
|
||||
if ((*p_arg)->type == FFI_TYPE_STRUCT)
|
||||
argp = (char *) ALIGN(argp, 4);
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
|
@ -83,7 +85,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
|
|||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -117,7 +119,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
|
@ -128,6 +129,17 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
cif->flags = (unsigned) FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size <= 4)
|
||||
/* A Composite Type not larger than 4 bytes is returned in r0. */
|
||||
cif->flags = (unsigned)FFI_TYPE_INT;
|
||||
else
|
||||
/* A Composite Type larger than 4 bytes, or whose size cannot
|
||||
be determined statically ... is stored in memory at an
|
||||
address passed [in r0]. */
|
||||
cif->flags = (unsigned)FFI_TYPE_STRUCT;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
|
@ -136,50 +148,162 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
int small_struct = (cif->flags == FFI_TYPE_INT
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT);
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
unsigned int temp;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
(cif->flags == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else if (small_struct)
|
||||
ecif.rvalue = &temp;
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
if (small_struct)
|
||||
memcpy (rvalue, &temp, cif->rtype->size);
|
||||
}
|
||||
|
||||
/** private members **/
|
||||
|
||||
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||
void** args, ffi_cif* cif);
|
||||
|
||||
void ffi_closure_SYSV (ffi_closure *);
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
unsigned int
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
{
|
||||
// our various things...
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
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 re-set RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
/*@-exportheader@*/
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||
void **avalue, ffi_cif *cif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ( cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
size_t alignment = (*p_arg)->alignment;
|
||||
if (alignment < 4)
|
||||
alignment = 4;
|
||||
/* Align if necessary */
|
||||
if ((alignment - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, alignment);
|
||||
}
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* How to make a trampoline. */
|
||||
|
||||
#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*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \
|
||||
*(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \
|
||||
*(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \
|
||||
*(unsigned int*) &__tramp[12] = __ctx; \
|
||||
*(unsigned int*) &__tramp[16] = __fun; \
|
||||
__clear_cache((&__tramp[0]), (&__tramp[19])); \
|
||||
})
|
||||
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
||||
&ffi_closure_SYSV, \
|
||||
codeloc);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
@ -40,7 +41,8 @@ typedef enum ffi_abi {
|
|||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1998 Red Hat, Inc.
|
||||
sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
|
||||
ARM Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -82,6 +83,14 @@
|
|||
# define call_reg(x) mov lr, pc ; mov pc, x
|
||||
#endif
|
||||
|
||||
/* Conditionally compile unwinder directives. */
|
||||
#ifdef __ARM_EABI__
|
||||
#define UNWIND
|
||||
#else
|
||||
#define UNWIND @
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
|
||||
.macro ARM_FUNC_START name
|
||||
.text
|
||||
|
@ -92,6 +101,7 @@
|
|||
bx pc
|
||||
nop
|
||||
.arm
|
||||
UNWIND .fnstart
|
||||
/* A hook to tell gdb that we've switched to ARM mode. Also used to call
|
||||
directly from other local arm routines. */
|
||||
_L__\name:
|
||||
|
@ -102,6 +112,7 @@ _L__\name:
|
|||
.align 0
|
||||
.arm
|
||||
ENTRY(\name)
|
||||
UNWIND .fnstart
|
||||
.endm
|
||||
#endif
|
||||
|
||||
|
@ -134,8 +145,11 @@ _L__\name:
|
|||
ARM_FUNC_START ffi_call_SYSV
|
||||
@ Save registers
|
||||
stmfd sp!, {r0-r3, fp, lr}
|
||||
UNWIND .save {r0-r3, fp, lr}
|
||||
mov fp, sp
|
||||
|
||||
UNWIND .setfp fp, sp
|
||||
|
||||
@ Make room for all of the new args.
|
||||
sub sp, fp, r2
|
||||
|
||||
|
@ -205,5 +219,81 @@ LSYM(Lepilogue):
|
|||
RETLDM "r0-r3,fp"
|
||||
|
||||
.ffi_call_SYSV_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
||||
|
||||
/*
|
||||
unsigned int FFI_HIDDEN
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
*/
|
||||
|
||||
ARM_FUNC_START ffi_closure_SYSV
|
||||
UNWIND .pad #16
|
||||
add ip, sp, #16
|
||||
stmfd sp!, {ip, lr}
|
||||
UNWIND .save {r0, lr}
|
||||
add r2, sp, #8
|
||||
.pad #16
|
||||
sub sp, sp, #16
|
||||
str sp, [sp, #8]
|
||||
add r1, sp, #8
|
||||
bl ffi_closure_SYSV_inner
|
||||
cmp r0, #FFI_TYPE_INT
|
||||
beq .Lretint
|
||||
|
||||
cmp r0, #FFI_TYPE_FLOAT
|
||||
#ifdef __SOFTFP__
|
||||
beq .Lretint
|
||||
#else
|
||||
beq .Lretfloat
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_DOUBLE
|
||||
#ifdef __SOFTFP__
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretdouble
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_LONGDOUBLE
|
||||
#ifdef __SOFTFP__
|
||||
beq .Lretlonglong
|
||||
#else
|
||||
beq .Lretlongdouble
|
||||
#endif
|
||||
|
||||
cmp r0, #FFI_TYPE_SINT64
|
||||
beq .Lretlonglong
|
||||
.Lclosure_epilogue:
|
||||
add sp, sp, #16
|
||||
ldmfd sp, {sp, pc}
|
||||
.Lretint:
|
||||
ldr r0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlonglong:
|
||||
ldr r0, [sp]
|
||||
ldr r1, [sp, #4]
|
||||
b .Lclosure_epilogue
|
||||
|
||||
#ifndef __SOFTFP__
|
||||
.Lretfloat:
|
||||
ldfs f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
.Lretlongdouble:
|
||||
ldfd f0, [sp]
|
||||
b .Lclosure_epilogue
|
||||
#endif
|
||||
|
||||
.ffi_closure_SYSV_end:
|
||||
UNWIND .fnend
|
||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
ffi.c - Copyright (c) 1998 Cygnus Solutions
|
||||
Copyright (c) 2004 Simon Posnjak
|
||||
Copyright (c) 2005 Axis Communications AB
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
CRIS Foreign Function Interface
|
||||
|
||||
|
@ -360,10 +361,11 @@ ffi_prep_closure_inner (void **params, ffi_closure* closure)
|
|||
/* API function: Prepare the trampoline. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif *, void *, void **, void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif *, void *, void **, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
void *innerfn = ffi_prep_closure_inner;
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
@ -375,7 +377,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
|
||||
&innerfn, sizeof (void *));
|
||||
memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
|
||||
&closure, sizeof (void *));
|
||||
&codeloc, sizeof (void *));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
FR-V Assembly glue.
|
||||
|
||||
$Id: eabi.S,v 1.2 2006/03/03 20:24:46 theller Exp $
|
||||
|
||||
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
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2004 Anthony Green
|
||||
ffi.c - Copyright (C) 2004 Anthony Green
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008 Red Hat, Inc.
|
||||
|
||||
FR-V Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +16,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -124,10 +127,10 @@ extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
|
|||
extended_cif *,
|
||||
unsigned, unsigned,
|
||||
unsigned *,
|
||||
void (*fn)());
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
void **avalue)
|
||||
{
|
||||
|
@ -243,14 +246,15 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
|
|||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn = (long) ffi_closure_eabi;
|
||||
unsigned long cls = (long) closure;
|
||||
unsigned long cls = (long) codeloc;
|
||||
#ifdef __FRV_FDPIC__
|
||||
register void *got __asm__("gr15");
|
||||
#endif
|
||||
|
@ -259,7 +263,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
fn = (unsigned long) ffi_closure_eabi;
|
||||
|
||||
#ifdef __FRV_FDPIC__
|
||||
tramp[0] = &tramp[2];
|
||||
tramp[0] = &((unsigned int *)codeloc)[2];
|
||||
tramp[1] = got;
|
||||
tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
|
||||
tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
|
||||
|
@ -281,7 +285,8 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
|
||||
/* Cache flushing. */
|
||||
for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
|
||||
__asm__ volatile ("dcf @(%0,%1)\n\tici @(%0,%1)" :: "r" (tramp), "r" (i));
|
||||
__asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
|
||||
"r" (codeloc));
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Red Hat, Inc.
|
||||
ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64 Foreign Function Interface
|
||||
|
@ -15,13 +15,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -69,24 +70,19 @@ endian_adjust (void *addr, size_t len)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Store VALUE to ADDR in the current cpu implementation's fp spill format. */
|
||||
/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
|
||||
This is a macro instead of a function, so that it works for all 3 floating
|
||||
point types without type conversions. Type conversion to long double breaks
|
||||
the denorm support. */
|
||||
|
||||
static inline void
|
||||
stf_spill(fpreg *addr, __float80 value)
|
||||
{
|
||||
#define stf_spill(addr, value) \
|
||||
asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
|
||||
}
|
||||
|
||||
/* Load a value from ADDR, which is in the current cpu implementation's
|
||||
fp spill format. */
|
||||
fp spill format. As above, this must also be a macro. */
|
||||
|
||||
static inline __float80
|
||||
ldf_fill(fpreg *addr)
|
||||
{
|
||||
__float80 ret;
|
||||
asm ("ldf.fill %0 = %1%P1" : "=f"(ret) : "m"(*addr));
|
||||
return ret;
|
||||
}
|
||||
#define ldf_fill(result, addr) \
|
||||
asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
|
||||
|
||||
/* Return the size of the C type associated with with TYPE. Which will
|
||||
be one of the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
@ -110,17 +106,20 @@ hfa_type_size (int type)
|
|||
/* Load from ADDR a value indicated by TYPE. Which will be one of
|
||||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static __float80
|
||||
hfa_type_load (int type, void *addr)
|
||||
static void
|
||||
hfa_type_load (fpreg *fpaddr, int type, void *addr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
return *(float *) addr;
|
||||
stf_spill (fpaddr, *(float *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
return *(double *) addr;
|
||||
stf_spill (fpaddr, *(double *) addr);
|
||||
return;
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
return *(__float80 *) addr;
|
||||
stf_spill (fpaddr, *(__float80 *) addr);
|
||||
return;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
@ -130,19 +129,31 @@ hfa_type_load (int type, void *addr)
|
|||
the FFI_IA64_TYPE_HFA_* values. */
|
||||
|
||||
static void
|
||||
hfa_type_store (int type, void *addr, __float80 value)
|
||||
hfa_type_store (int type, void *addr, fpreg *fpaddr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case FFI_IA64_TYPE_HFA_FLOAT:
|
||||
*(float *) addr = value;
|
||||
break;
|
||||
{
|
||||
float result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(float *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_DOUBLE:
|
||||
*(double *) addr = value;
|
||||
break;
|
||||
{
|
||||
double result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(double *) addr = result;
|
||||
break;
|
||||
}
|
||||
case FFI_IA64_TYPE_HFA_LDOUBLE:
|
||||
*(__float80 *) addr = value;
|
||||
break;
|
||||
{
|
||||
__float80 result;
|
||||
ldf_fill (result, fpaddr);
|
||||
*(__float80 *) addr = result;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
@ -351,8 +362,8 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
stf_spill (&stack->fp_regs[fpcount],
|
||||
hfa_type_load (hfa_type, avalue[i] + offset));
|
||||
hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
|
||||
avalue[i] + offset);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
|
@ -387,13 +398,14 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
gp pointer to the closure. This allows the function entry code to
|
||||
both retrieve the user data, and to restire the correct gp pointer. */
|
||||
|
||||
extern void ffi_closure_unix (void);
|
||||
extern void ffi_closure_unix ();
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
/* The layout of a function descriptor. A C function pointer really
|
||||
points to one of these. */
|
||||
|
@ -420,7 +432,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
|
||||
tramp->code_pointer = fd->code_pointer;
|
||||
tramp->real_gp = fd->gp;
|
||||
tramp->fake_gp = (UINT64)(PTR64)closure;
|
||||
tramp->fake_gp = (UINT64)(PTR64)codeloc;
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
@ -475,9 +487,11 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
|
|||
case FFI_TYPE_FLOAT:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
void *addr = &stack->fp_regs[fpcount++];
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
float result;
|
||||
avalue[i] = addr;
|
||||
*(float *)addr = ldf_fill (addr);
|
||||
ldf_fill (result, addr);
|
||||
*(float *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
|
||||
|
@ -487,9 +501,11 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
|
|||
case FFI_TYPE_DOUBLE:
|
||||
if (gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
void *addr = &stack->fp_regs[fpcount++];
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
double result;
|
||||
avalue[i] = addr;
|
||||
*(double *)addr = ldf_fill (addr);
|
||||
ldf_fill (result, addr);
|
||||
*(double *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
|
@ -501,9 +517,11 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
|
|||
gpcount++;
|
||||
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
|
||||
{
|
||||
void *addr = &stack->fp_regs[fpcount++];
|
||||
fpreg *addr = &stack->fp_regs[fpcount++];
|
||||
__float80 result;
|
||||
avalue[i] = addr;
|
||||
*(__float80 *)addr = ldf_fill (addr);
|
||||
ldf_fill (result, addr);
|
||||
*(__float80 *)addr = result;
|
||||
}
|
||||
else
|
||||
avalue[i] = &stack->gp_regs[gpcount];
|
||||
|
@ -533,8 +551,8 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
|
|||
&& offset < size
|
||||
&& gp_offset < 8 * 8)
|
||||
{
|
||||
hfa_type_store (hfa_type, addr + offset,
|
||||
ldf_fill (&stack->fp_regs[fpcount]));
|
||||
hfa_type_store (hfa_type, addr + offset,
|
||||
&stack->fp_regs[fpcount]);
|
||||
offset += hfa_size;
|
||||
gp_offset += hfa_size;
|
||||
fpcount += 1;
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* "Type" codes used between assembly and C. When used as a part of
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
unix.S - Copyright (c) 1998 Red Hat, Inc.
|
||||
unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2000 Hewlett Packard Company
|
||||
|
||||
IA64/unix Foreign Function Interface
|
||||
|
@ -19,13 +19,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -37,7 +38,7 @@
|
|||
.text
|
||||
|
||||
/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
|
||||
void (*fn)(), int flags);
|
||||
void (*fn)(void), int flags);
|
||||
*/
|
||||
|
||||
.align 16
|
||||
|
@ -553,3 +554,7 @@ ffi_closure_unix:
|
|||
data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
|
||||
data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
|
||||
data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2004 Renesas Technology
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
M32R Foreign Function Interface
|
||||
|
||||
|
@ -31,9 +32,7 @@
|
|||
/* ffi_prep_args is called by the assembly routine once stack
|
||||
space has been allocated for the function's arguments. */
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
unsigned int i;
|
||||
int tmp;
|
||||
|
@ -173,20 +172,10 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
|
@ -198,9 +187,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
@ -208,7 +195,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
|
@ -237,7 +223,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
}
|
||||
}
|
||||
}
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -8,11 +8,23 @@
|
|||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/cachectl.h>
|
||||
|
||||
void ffi_call_SYSV (extended_cif *,
|
||||
unsigned, unsigned,
|
||||
void *, void (*fn) ());
|
||||
void *ffi_prep_args (void *stack, extended_cif *ecif);
|
||||
void ffi_closure_SYSV (ffi_closure *);
|
||||
void ffi_closure_struct_SYSV (ffi_closure *);
|
||||
unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
|
||||
void *resp, void *args);
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space has
|
||||
been allocated for the function's arguments. */
|
||||
|
||||
static void *
|
||||
void *
|
||||
ffi_prep_args (void *stack, extended_cif *ecif)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -24,7 +36,7 @@ ffi_prep_args (void *stack, extended_cif *ecif)
|
|||
argp = stack;
|
||||
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& ecif->cif->rtype->size > 8)
|
||||
&& !ecif->cif->flags)
|
||||
struct_value_ptr = ecif->rvalue;
|
||||
else
|
||||
struct_value_ptr = NULL;
|
||||
|
@ -37,44 +49,47 @@ ffi_prep_args (void *stack, extended_cif *ecif)
|
|||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary. */
|
||||
if (((*p_arg)->alignment - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN (argp, (*p_arg)->alignment);
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof (int))
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
|
||||
break;
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
|
||||
break;
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
|
||||
break;
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp + sizeof (int) - z, *p_argv, z);
|
||||
break;
|
||||
case FFI_TYPE_STRUCT:
|
||||
memcpy (argp + sizeof (int) - z, *p_argv, z);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
z = sizeof (int);
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
else
|
||||
memcpy (argp, *p_argv, z);
|
||||
p_argv++;
|
||||
argp += z;
|
||||
z = sizeof (int);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (argp, *p_argv, z);
|
||||
|
||||
/* Align if necessary. */
|
||||
if ((sizeof(int) - 1) & z)
|
||||
z = ALIGN(z, sizeof(int));
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return struct_value_ptr;
|
||||
|
@ -86,7 +101,8 @@ ffi_prep_args (void *stack, extended_cif *ecif)
|
|||
#define CIF_FLAGS_DOUBLE 8
|
||||
#define CIF_FLAGS_LDOUBLE 16
|
||||
#define CIF_FLAGS_POINTER 32
|
||||
#define CIF_FLAGS_STRUCT 64
|
||||
#define CIF_FLAGS_STRUCT1 64
|
||||
#define CIF_FLAGS_STRUCT2 128
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
|
@ -100,12 +116,24 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size > 4 && cif->rtype->size <= 8)
|
||||
cif->flags = CIF_FLAGS_DINT;
|
||||
else if (cif->rtype->size <= 4)
|
||||
cif->flags = CIF_FLAGS_STRUCT;
|
||||
else
|
||||
cif->flags = 0;
|
||||
switch (cif->rtype->size)
|
||||
{
|
||||
case 1:
|
||||
cif->flags = CIF_FLAGS_STRUCT1;
|
||||
break;
|
||||
case 2:
|
||||
cif->flags = CIF_FLAGS_STRUCT2;
|
||||
break;
|
||||
case 4:
|
||||
cif->flags = CIF_FLAGS_INT;
|
||||
break;
|
||||
case 8:
|
||||
cif->flags = CIF_FLAGS_DINT;
|
||||
break;
|
||||
default:
|
||||
cif->flags = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
|
@ -137,11 +165,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
extern void ffi_call_SYSV (void *(*) (void *, extended_cif *),
|
||||
extended_cif *,
|
||||
unsigned, unsigned, unsigned,
|
||||
void *, void (*fn) ());
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
|
||||
{
|
||||
|
@ -149,7 +172,7 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
|
|||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
|
||||
/* If the return value is a struct and we don't have a return value
|
||||
address then we need to make one. */
|
||||
|
||||
|
@ -159,13 +182,11 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
|
|||
ecif.rvalue = alloca (cif->rtype->size);
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, cif->rtype->size * 8,
|
||||
ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
|
||||
|
@ -174,3 +195,84 @@ ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
|
||||
{
|
||||
unsigned int i;
|
||||
void **p_argv;
|
||||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z <= 4)
|
||||
{
|
||||
*p_argv = (void *) (argp + 4 - z);
|
||||
|
||||
z = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_argv = (void *) argp;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & z)
|
||||
z = ALIGN(z, sizeof(int));
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
*(unsigned short *)closure->tramp = 0x207c;
|
||||
*(void **)(closure->tramp + 2) = codeloc;
|
||||
*(unsigned short *)(closure->tramp + 6) = 0x4ef9;
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& !cif->flags)
|
||||
*(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
|
||||
else
|
||||
*(void **)(closure->tramp + 8) = ffi_closure_SYSV;
|
||||
|
||||
syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
|
||||
FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
@ -40,7 +41,8 @@ typedef enum ffi_abi {
|
|||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 0
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 16
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,47 +1,88 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S
|
||||
sysv.S - Copyright (c) 1998 Andreas Schwab
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
m68k Foreign Function Interface
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef HAVE_AS_CFI_PSEUDO_OP
|
||||
#define CFI_STARTPROC() .cfi_startproc
|
||||
#define CFI_OFFSET(reg,off) .cfi_offset reg,off
|
||||
#define CFI_DEF_CFA(reg,off) .cfi_def_cfa reg,off
|
||||
#define CFI_ENDPROC() .cfi_endproc
|
||||
#else
|
||||
#define CFI_STARTPROC()
|
||||
#define CFI_OFFSET(reg,off)
|
||||
#define CFI_DEF_CFA(reg,off)
|
||||
#define CFI_ENDPROC()
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.globl ffi_call_SYSV
|
||||
.type ffi_call_SYSV,@function
|
||||
.align 4
|
||||
|
||||
ffi_call_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#0
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %d2,-(%sp)
|
||||
CFI_OFFSET(2,-12)
|
||||
|
||||
| Make room for all of the new args.
|
||||
sub.l 16(%fp),%sp
|
||||
sub.l 12(%fp),%sp
|
||||
|
||||
| Call ffi_prep_args
|
||||
move.l 12(%fp),-(%sp)
|
||||
move.l 8(%fp),-(%sp)
|
||||
pea 4(%sp)
|
||||
move.l 8(%fp),%a0
|
||||
jsr (%a0)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_prep_args
|
||||
#else
|
||||
bsr.l ffi_prep_args@PLTPC
|
||||
#endif
|
||||
addq.l #8,%sp
|
||||
|
||||
| Pass pointer to struct value, if any
|
||||
move.l %a0,%a1
|
||||
|
||||
| Call the function
|
||||
move.l 32(%fp),%a0
|
||||
move.l 24(%fp),%a0
|
||||
jsr (%a0)
|
||||
|
||||
| Remove the space we pushed for the args
|
||||
add.l 16(%fp),%sp
|
||||
add.l 12(%fp),%sp
|
||||
|
||||
| Load the pointer to storage for the return value
|
||||
move.l 28(%fp),%a1
|
||||
move.l 20(%fp),%a1
|
||||
|
||||
| Load the return type code
|
||||
move.l 20(%fp),%d2
|
||||
move.l 16(%fp),%d2
|
||||
|
||||
| If the return value pointer is NULL, assume no return value.
|
||||
tst.l %a1
|
||||
|
@ -79,19 +120,115 @@ retlongdouble:
|
|||
|
||||
retpointer:
|
||||
btst #5,%d2
|
||||
jbeq retstruct
|
||||
jbeq retstruct1
|
||||
move.l %a0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retstruct:
|
||||
retstruct1:
|
||||
btst #6,%d2
|
||||
jbeq retstruct2
|
||||
move.b %d0,(%a1)
|
||||
jbra epilogue
|
||||
|
||||
retstruct2:
|
||||
btst #7,%d2
|
||||
jbeq noretval
|
||||
move.l 24(%fp),%d2
|
||||
bfins %d0,(%a1){#0,%d2}
|
||||
move.w %d0,(%a1)
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
move.l (%sp)+,%d2
|
||||
unlk %a6
|
||||
unlk %fp
|
||||
rts
|
||||
CFI_ENDPROC()
|
||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
||||
|
||||
.globl ffi_closure_SYSV
|
||||
.type ffi_closure_SYSV, @function
|
||||
.align 4
|
||||
|
||||
ffi_closure_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#-12
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %sp,-12(%fp)
|
||||
pea 8(%fp)
|
||||
pea -12(%fp)
|
||||
move.l %a0,-(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_closure_SYSV_inner
|
||||
#else
|
||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
||||
#endif
|
||||
|
||||
lsr.l #1,%d0
|
||||
jne 1f
|
||||
jcc .Lcls_epilogue
|
||||
move.l -12(%fp),%d0
|
||||
.Lcls_epilogue:
|
||||
unlk %fp
|
||||
rts
|
||||
1:
|
||||
lea -12(%fp),%a0
|
||||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_float
|
||||
move.l (%a0)+,%d0
|
||||
move.l (%a0),%d1
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_float:
|
||||
fmove.s (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne 1f
|
||||
jcs .Lcls_ret_ldouble
|
||||
fmove.d (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_ldouble:
|
||||
fmove.x (%a0),%fp0
|
||||
jra .Lcls_epilogue
|
||||
1:
|
||||
lsr.l #2,%d0
|
||||
jne .Lcls_ret_struct2
|
||||
jcs .Lcls_ret_struct1
|
||||
move.l (%a0),%a0
|
||||
move.l %a0,%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct1:
|
||||
move.b (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
.Lcls_ret_struct2:
|
||||
move.w (%a0),%d0
|
||||
jra .Lcls_epilogue
|
||||
CFI_ENDPROC()
|
||||
|
||||
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
||||
|
||||
.globl ffi_closure_struct_SYSV
|
||||
.type ffi_closure_struct_SYSV, @function
|
||||
.align 4
|
||||
|
||||
ffi_closure_struct_SYSV:
|
||||
CFI_STARTPROC()
|
||||
link %fp,#0
|
||||
CFI_OFFSET(14,-8)
|
||||
CFI_DEF_CFA(14,8)
|
||||
move.l %sp,-12(%fp)
|
||||
pea 8(%fp)
|
||||
move.l %a1,-(%sp)
|
||||
move.l %a0,-(%sp)
|
||||
#if !defined __PIC__
|
||||
jsr ffi_closure_SYSV_inner
|
||||
#else
|
||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
||||
#endif
|
||||
unlk %fp
|
||||
rts
|
||||
CFI_ENDPROC()
|
||||
.size ffi_closure_struct_SYSV,.-ffi_closure_struct_SYSV
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996 Red Hat, Inc.
|
||||
ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2008 David Daney
|
||||
|
||||
MIPS Foreign Function Interface
|
||||
|
||||
|
@ -14,28 +15,44 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cachectl.h>
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef __GNUC__
|
||||
# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
|
||||
# define USE__BUILTIN___CLEAR_CACHE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef USE__BUILTIN___CLEAR_CACHE
|
||||
#include <sys/cachectl.h>
|
||||
#endif
|
||||
|
||||
#ifdef FFI_DEBUG
|
||||
# define FFI_MIPS_STOP_HERE() ffi_stop_here()
|
||||
#else
|
||||
# define FFI_MIPS_STOP_HERE() do {} while(0)
|
||||
#endif
|
||||
|
||||
#ifdef FFI_MIPS_N32
|
||||
#define FIX_ARGP \
|
||||
FFI_ASSERT(argp <= &stack[bytes]); \
|
||||
if (argp == &stack[bytes]) \
|
||||
{ \
|
||||
argp = stack; \
|
||||
ffi_stop_here(); \
|
||||
FFI_MIPS_STOP_HERE(); \
|
||||
}
|
||||
#else
|
||||
#define FIX_ARGP
|
||||
|
@ -55,7 +72,7 @@ static void ffi_prep_args(char *stack,
|
|||
char *argp;
|
||||
ffi_type **p_arg;
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
/* If more than 8 double words are used, the remainder go
|
||||
on the stack. We reorder stuff on the stack here to
|
||||
support this easily. */
|
||||
|
@ -69,7 +86,7 @@ static void ffi_prep_args(char *stack,
|
|||
|
||||
memset(stack, 0, bytes);
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
if ( ecif->cif->rstruct_flag != 0 )
|
||||
#else
|
||||
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
|
||||
|
@ -92,7 +109,7 @@ static void ffi_prep_args(char *stack,
|
|||
if (a < sizeof(ffi_arg))
|
||||
a = sizeof(ffi_arg);
|
||||
|
||||
if ((a - 1) & (unsigned int) argp)
|
||||
if ((a - 1) & (unsigned long) argp)
|
||||
{
|
||||
argp = (char *) ALIGN(argp, a);
|
||||
FIX_ARGP;
|
||||
|
@ -101,9 +118,15 @@ static void ffi_prep_args(char *stack,
|
|||
z = (*p_arg)->size;
|
||||
if (z <= sizeof(ffi_arg))
|
||||
{
|
||||
int type = (*p_arg)->type;
|
||||
z = sizeof(ffi_arg);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
/* The size of a pointer depends on the ABI */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
type =
|
||||
(ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(ffi_arg *)argp = *(SINT8 *)(* p_argv);
|
||||
|
@ -126,7 +149,6 @@ static void ffi_prep_args(char *stack,
|
|||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
|
@ -135,8 +157,7 @@ static void ffi_prep_args(char *stack,
|
|||
*(float *) argp = *(float *)(* p_argv);
|
||||
break;
|
||||
|
||||
/* Handle small structures. */
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Handle structures. */
|
||||
default:
|
||||
memcpy(argp, *p_argv, (*p_arg)->size);
|
||||
break;
|
||||
|
@ -144,12 +165,12 @@ static void ffi_prep_args(char *stack,
|
|||
}
|
||||
else
|
||||
{
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#ifdef FFI_MIPS_O32
|
||||
memcpy(argp, *p_argv, z);
|
||||
#else
|
||||
{
|
||||
unsigned end = (unsigned) argp+z;
|
||||
unsigned cap = (unsigned) stack+bytes;
|
||||
unsigned long end = (unsigned long) argp + z;
|
||||
unsigned long cap = (unsigned long) stack + bytes;
|
||||
|
||||
/* Check if the data will fit within the register space.
|
||||
Handle it if it doesn't. */
|
||||
|
@ -158,12 +179,13 @@ static void ffi_prep_args(char *stack,
|
|||
memcpy(argp, *p_argv, z);
|
||||
else
|
||||
{
|
||||
unsigned portion = end - cap;
|
||||
unsigned long portion = cap - (unsigned long)argp;
|
||||
|
||||
memcpy(argp, *p_argv, portion);
|
||||
argp = stack;
|
||||
memcpy(argp,
|
||||
(void*)((unsigned)(*p_argv)+portion), z - portion);
|
||||
z -= portion;
|
||||
memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
|
||||
z);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -174,7 +196,7 @@ static void ffi_prep_args(char *stack,
|
|||
}
|
||||
}
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
|
||||
/* The n32 spec says that if "a chunk consists solely of a double
|
||||
float field (but not a double, which is part of a union), it
|
||||
|
@ -182,35 +204,41 @@ static void ffi_prep_args(char *stack,
|
|||
passed in an integer register". This code traverses structure
|
||||
definitions and generates the appropriate flags. */
|
||||
|
||||
unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
|
||||
static unsigned
|
||||
calc_n32_struct_flags(ffi_type *arg, unsigned *loc, unsigned *arg_reg)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
unsigned index = 0;
|
||||
|
||||
ffi_type *e;
|
||||
|
||||
while (e = arg->elements[index])
|
||||
while ((e = arg->elements[index]))
|
||||
{
|
||||
/* Align this object. */
|
||||
*loc = ALIGN(*loc, e->alignment);
|
||||
if (e->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
flags += (FFI_TYPE_DOUBLE << *shift);
|
||||
*shift += FFI_FLAG_BITS;
|
||||
/* Already aligned to FFI_SIZEOF_ARG. */
|
||||
*arg_reg = *loc / FFI_SIZEOF_ARG;
|
||||
if (*arg_reg > 7)
|
||||
break;
|
||||
flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
|
||||
*loc += e->size;
|
||||
}
|
||||
else if (e->type == FFI_TYPE_STRUCT)
|
||||
flags += calc_n32_struct_flags(e, shift);
|
||||
else
|
||||
*shift += FFI_FLAG_BITS;
|
||||
|
||||
*loc += e->size;
|
||||
index++;
|
||||
}
|
||||
/* Next Argument register at alignment of FFI_SIZEOF_ARG. */
|
||||
*arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
unsigned calc_n32_return_struct_flags(ffi_type *arg)
|
||||
static unsigned
|
||||
calc_n32_return_struct_flags(ffi_type *arg)
|
||||
{
|
||||
unsigned flags = 0;
|
||||
unsigned index = 0;
|
||||
unsigned small = FFI_TYPE_SMALLSTRUCT;
|
||||
ffi_type *e;
|
||||
|
||||
|
@ -229,16 +257,16 @@ unsigned calc_n32_return_struct_flags(ffi_type *arg)
|
|||
|
||||
e = arg->elements[0];
|
||||
if (e->type == FFI_TYPE_DOUBLE)
|
||||
flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
|
||||
flags = FFI_TYPE_DOUBLE;
|
||||
else if (e->type == FFI_TYPE_FLOAT)
|
||||
flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
|
||||
flags = FFI_TYPE_FLOAT;
|
||||
|
||||
if (flags && (e = arg->elements[1]))
|
||||
{
|
||||
if (e->type == FFI_TYPE_DOUBLE)
|
||||
flags += FFI_TYPE_DOUBLE;
|
||||
flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
|
||||
else if (e->type == FFI_TYPE_FLOAT)
|
||||
flags += FFI_TYPE_FLOAT;
|
||||
flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
|
||||
else
|
||||
return small;
|
||||
|
||||
|
@ -263,7 +291,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
{
|
||||
cif->flags = 0;
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#ifdef FFI_MIPS_O32
|
||||
/* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
|
||||
* does not have special handling for floating point args.
|
||||
*/
|
||||
|
@ -351,10 +379,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
/* Set the flags necessary for N32 processing */
|
||||
{
|
||||
unsigned shift = 0;
|
||||
unsigned arg_reg = 0;
|
||||
unsigned loc = 0;
|
||||
unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
|
||||
unsigned index = 0;
|
||||
|
||||
|
@ -369,7 +398,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
/* This means that the structure is being passed as
|
||||
a hidden argument */
|
||||
|
||||
shift = FFI_FLAG_BITS;
|
||||
arg_reg = 1;
|
||||
count = (cif->nargs < 7) ? cif->nargs : 7;
|
||||
|
||||
cif->rstruct_flag = !0;
|
||||
|
@ -380,23 +409,37 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
else
|
||||
cif->rstruct_flag = 0;
|
||||
|
||||
while (count-- > 0)
|
||||
while (count-- > 0 && arg_reg < 8)
|
||||
{
|
||||
switch ((cif->arg_types)[index]->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += ((cif->arg_types)[index]->type << shift);
|
||||
shift += FFI_FLAG_BITS;
|
||||
cif->flags +=
|
||||
((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
|
||||
arg_reg++;
|
||||
break;
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Align it. */
|
||||
arg_reg = ALIGN(arg_reg, 2);
|
||||
/* Treat it as two adjacent doubles. */
|
||||
cif->flags +=
|
||||
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
|
||||
arg_reg++;
|
||||
cif->flags +=
|
||||
(FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
|
||||
arg_reg++;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
loc = arg_reg * FFI_SIZEOF_ARG;
|
||||
cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
|
||||
&shift);
|
||||
&loc, &arg_reg);
|
||||
break;
|
||||
|
||||
default:
|
||||
shift += FFI_FLAG_BITS;
|
||||
arg_reg++;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
@ -431,7 +474,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
case FFI_TYPE_DOUBLE:
|
||||
cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long double is returned as if it were a struct containing
|
||||
two doubles. */
|
||||
cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
|
||||
cif->flags += (FFI_TYPE_DOUBLE + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
|
||||
<< (4 + (FFI_FLAG_BITS * 8));
|
||||
break;
|
||||
default:
|
||||
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
|
||||
break;
|
||||
|
@ -470,7 +519,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#ifdef FFI_MIPS_O32
|
||||
case FFI_O32:
|
||||
case FFI_O32_SOFT_FLOAT:
|
||||
ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
|
||||
|
@ -478,10 +527,25 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#ifdef FFI_MIPS_N32
|
||||
case FFI_N32:
|
||||
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
case FFI_N64:
|
||||
{
|
||||
int copy_rvalue = 0;
|
||||
void *rvalue_copy = ecif.rvalue;
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
|
||||
{
|
||||
/* For structures smaller than 16 bytes we clobber memory
|
||||
in 8 byte increments. Make a copy so we don't clobber
|
||||
the callers memory outside of the struct bounds. */
|
||||
rvalue_copy = alloca(16);
|
||||
copy_rvalue = 1;
|
||||
}
|
||||
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, rvalue_copy, fn);
|
||||
if (copy_rvalue)
|
||||
memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -491,42 +555,83 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
}
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* N32 not implemented yet, FFI_CLOSURES not defined */
|
||||
#if FFI_CLOSURES
|
||||
#if defined(FFI_MIPS_O32)
|
||||
extern void ffi_closure_O32(void);
|
||||
#else
|
||||
extern void ffi_closure_N32(void);
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned int fn;
|
||||
unsigned int ctx = (unsigned int) closure;
|
||||
void * fn;
|
||||
char *clear_location = (char *) codeloc;
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
|
||||
fn = (unsigned int) ffi_closure_O32;
|
||||
fn = ffi_closure_O32;
|
||||
#else /* FFI_MIPS_N32 */
|
||||
FFI_ASSERT(cif->abi == FFI_N32);
|
||||
FFI_ASSERT(!"not implemented");
|
||||
FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
|
||||
fn = ffi_closure_N32;
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
tramp[0] = 0x3c190000 | (fn >> 16); /* lui $25,high(fn) */
|
||||
tramp[1] = 0x37390000 | (fn & 0xffff); /* ori $25,low(fn) */
|
||||
tramp[2] = 0x3c080000 | (ctx >> 16); /* lui $8,high(ctx) */
|
||||
tramp[3] = 0x03200008; /* jr $25 */
|
||||
tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori $8,low(ctx) */
|
||||
#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
|
||||
/* lui $25,high(fn) */
|
||||
tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
|
||||
/* ori $25,low(fn) */
|
||||
tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
|
||||
/* lui $12,high(codeloc) */
|
||||
tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
|
||||
/* jr $25 */
|
||||
tramp[3] = 0x03200008;
|
||||
/* ori $12,low(codeloc) */
|
||||
tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
|
||||
#else
|
||||
/* N64 has a somewhat larger trampoline. */
|
||||
/* lui $25,high(fn) */
|
||||
tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
|
||||
/* lui $12,high(codeloc) */
|
||||
tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
|
||||
/* ori $25,mid-high(fn) */
|
||||
tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
|
||||
/* ori $12,mid-high(codeloc) */
|
||||
tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
|
||||
/* dsll $25,$25,16 */
|
||||
tramp[4] = 0x0019cc38;
|
||||
/* dsll $12,$12,16 */
|
||||
tramp[5] = 0x000c6438;
|
||||
/* ori $25,mid-low(fn) */
|
||||
tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
|
||||
/* ori $12,mid-low(codeloc) */
|
||||
tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
|
||||
/* dsll $25,$25,16 */
|
||||
tramp[8] = 0x0019cc38;
|
||||
/* dsll $12,$12,16 */
|
||||
tramp[9] = 0x000c6438;
|
||||
/* ori $25,low(fn) */
|
||||
tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff);
|
||||
/* jr $25 */
|
||||
tramp[11] = 0x03200008;
|
||||
/* ori $12,low(codeloc) */
|
||||
tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
|
||||
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* XXX this is available on Linux, but anything else? */
|
||||
cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE);
|
||||
|
||||
#ifdef USE__BUILTIN___CLEAR_CACHE
|
||||
__builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
|
||||
#else
|
||||
cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
|
||||
#endif
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
|
@ -567,7 +672,7 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
|||
|
||||
if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) ar[0];
|
||||
rvalue = (void *)(UINT32)ar[0];
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
|
@ -645,4 +750,177 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(FFI_MIPS_N32)
|
||||
|
||||
static void
|
||||
copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
|
||||
int argn, unsigned arg_offset, ffi_arg *ar,
|
||||
ffi_arg *fpr)
|
||||
{
|
||||
ffi_type **elt_typep = type->elements;
|
||||
while(*elt_typep)
|
||||
{
|
||||
ffi_type *elt_type = *elt_typep;
|
||||
unsigned o;
|
||||
char *tp;
|
||||
char *argp;
|
||||
char *fpp;
|
||||
|
||||
o = ALIGN(offset, elt_type->alignment);
|
||||
arg_offset += o - offset;
|
||||
offset = o;
|
||||
argn += arg_offset / sizeof(ffi_arg);
|
||||
arg_offset = arg_offset % sizeof(ffi_arg);
|
||||
|
||||
argp = (char *)(ar + argn);
|
||||
fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
|
||||
|
||||
tp = target + offset;
|
||||
|
||||
if (elt_type->type == FFI_TYPE_DOUBLE)
|
||||
*(double *)tp = *(double *)fpp;
|
||||
else
|
||||
memcpy(tp, argp + arg_offset, elt_type->size);
|
||||
|
||||
offset += elt_type->size;
|
||||
arg_offset += elt_type->size;
|
||||
elt_typep++;
|
||||
argn += arg_offset / sizeof(ffi_arg);
|
||||
arg_offset = arg_offset % sizeof(ffi_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes the arguments to a function, which will be stored on the
|
||||
* stack. AR is the pointer to the beginning of the integer
|
||||
* arguments. FPR is a pointer to the area where floating point
|
||||
* registers have been saved.
|
||||
*
|
||||
* RVALUE is the location where the function return value will be
|
||||
* stored. CLOSURE is the prepared closure to invoke.
|
||||
*
|
||||
* This function should only be called from assembly, which is in
|
||||
* turn called from a trampoline.
|
||||
*
|
||||
* Returns the function return flags.
|
||||
*
|
||||
*/
|
||||
int
|
||||
ffi_closure_mips_inner_N32 (ffi_closure *closure,
|
||||
void *rvalue, ffi_arg *ar,
|
||||
ffi_arg *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avaluep;
|
||||
ffi_arg *avalue;
|
||||
ffi_type **arg_types;
|
||||
int i, avn, argn;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
avaluep = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
|
||||
argn = 0;
|
||||
|
||||
if (cif->rstruct_flag)
|
||||
{
|
||||
#if _MIPS_SIM==_ABIN32
|
||||
rvalue = (void *)(UINT32)ar[0];
|
||||
#else /* N64 */
|
||||
rvalue = (void *)ar[0];
|
||||
#endif
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
{
|
||||
if (arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| arg_types[i]->type == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
ffi_arg *argp = argn >= 8 ? ar + argn : fpr + argn;
|
||||
#ifdef __MIPSEB__
|
||||
if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
|
||||
avaluep[i] = ((char *) argp) + sizeof (float);
|
||||
else
|
||||
#endif
|
||||
avaluep[i] = (char *) argp;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned type = arg_types[i]->type;
|
||||
|
||||
if (arg_types[i]->alignment > sizeof(ffi_arg))
|
||||
argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
|
||||
|
||||
ffi_arg *argp = ar + argn;
|
||||
|
||||
/* The size of a pointer depends on the ABI */
|
||||
if (type == FFI_TYPE_POINTER)
|
||||
type = (cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT8 *) &avalue[i] = (SINT8) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT8 *) &avalue[i] = (UINT8) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT16 *) &avalue[i] = (SINT16) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT16 *) &avalue[i] = (UINT16) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(SINT32 *) &avalue[i] = (SINT32) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
avaluep[i] = &avalue[i];
|
||||
*(UINT32 *) &avalue[i] = (UINT32) *argp;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (argn < 8)
|
||||
{
|
||||
/* Allocate space for the struct as at least part of
|
||||
it was passed in registers. */
|
||||
avaluep[i] = alloca(arg_types[i]->size);
|
||||
copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
|
||||
argn, 0, ar, fpr);
|
||||
|
||||
break;
|
||||
}
|
||||
/* Else fall through. */
|
||||
default:
|
||||
avaluep[i] = (char *) argp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avaluep, closure->user_data);
|
||||
|
||||
return cif->flags >> (FFI_FLAG_BITS * 8);
|
||||
}
|
||||
|
||||
#endif /* FFI_MIPS_N32 */
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
|
|
@ -13,19 +13,33 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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 LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifdef linux
|
||||
#include <asm/sgidefs.h>
|
||||
# ifndef _ABIN32
|
||||
# define _ABIN32 _MIPS_SIM_NABI32
|
||||
# endif
|
||||
# ifndef _ABI64
|
||||
# define _ABI64 _MIPS_SIM_ABI64
|
||||
# endif
|
||||
# ifndef _ABIO32
|
||||
# define _ABIO32 _MIPS_SIM_ABI32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(_MIPS_SIM)
|
||||
-- something is very wrong --
|
||||
#else
|
||||
|
@ -42,10 +56,13 @@
|
|||
|
||||
#ifdef FFI_MIPS_O32
|
||||
/* O32 stack frames have 32bit integer args */
|
||||
#define FFI_SIZEOF_ARG 4
|
||||
# define FFI_SIZEOF_ARG 4
|
||||
#else
|
||||
/* N32 and N64 frames have 64bit integer args */
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
# define FFI_SIZEOF_ARG 8
|
||||
# if _MIPS_SIM == _ABIN32
|
||||
# define FFI_SIZEOF_JAVA_RAW 4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define FFI_FLAG_BITS 2
|
||||
|
@ -104,19 +121,28 @@
|
|||
#define ra $31
|
||||
|
||||
#ifdef FFI_MIPS_O32
|
||||
#define REG_L lw
|
||||
#define REG_S sw
|
||||
#define SUBU subu
|
||||
#define ADDU addu
|
||||
#define SRL srl
|
||||
#define LI li
|
||||
# define REG_L lw
|
||||
# define REG_S sw
|
||||
# define SUBU subu
|
||||
# define ADDU addu
|
||||
# define SRL srl
|
||||
# define LI li
|
||||
#else /* !FFI_MIPS_O32 */
|
||||
#define REG_L ld
|
||||
#define REG_S sd
|
||||
#define SUBU dsubu
|
||||
#define ADDU daddu
|
||||
#define SRL dsrl
|
||||
#define LI dli
|
||||
# define REG_L ld
|
||||
# define REG_S sd
|
||||
# define SUBU dsubu
|
||||
# define ADDU daddu
|
||||
# define SRL dsrl
|
||||
# define LI dli
|
||||
# if (_MIPS_SIM==_ABI64)
|
||||
# define LA dla
|
||||
# define EH_FRAME_ALIGN 3
|
||||
# define FDE_ADDR_BYTES .8byte
|
||||
# else
|
||||
# define LA la
|
||||
# define EH_FRAME_ALIGN 2
|
||||
# define FDE_ADDR_BYTES .4byte
|
||||
# endif /* _MIPS_SIM==_ABI64 */
|
||||
#endif /* !FFI_MIPS_O32 */
|
||||
#else /* !LIBFFI_ASM */
|
||||
#ifdef FFI_MIPS_O32
|
||||
|
@ -143,7 +169,11 @@ typedef enum ffi_abi {
|
|||
FFI_DEFAULT_ABI = FFI_O32,
|
||||
#endif
|
||||
#else
|
||||
# if _MIPS_SIM==_ABI64
|
||||
FFI_DEFAULT_ABI = FFI_N64,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_N32,
|
||||
# endif
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
|
@ -158,8 +188,13 @@ typedef enum ffi_abi {
|
|||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#else
|
||||
/* N32/N64 not implemented yet. */
|
||||
#define FFI_CLOSURES 0
|
||||
/* N32/N64. */
|
||||
# define FFI_CLOSURES 1
|
||||
#if _MIPS_SIM==_ABI64
|
||||
#define FFI_TRAMPOLINE_SIZE 52
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#endif
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
|
@ -45,13 +46,19 @@
|
|||
.globl ffi_call_N32
|
||||
.ent ffi_call_N32
|
||||
ffi_call_N32:
|
||||
.LFB3:
|
||||
.frame $fp, SIZEOF_FRAME, ra
|
||||
.mask 0xc0000000,-FFI_SIZEOF_ARG
|
||||
.fmask 0x00000000,0
|
||||
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
.LCFI0:
|
||||
REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
|
||||
REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
|
||||
.LCFI1:
|
||||
move $fp, $sp
|
||||
|
||||
.LCFI3:
|
||||
move t9, callback # callback function pointer
|
||||
REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
|
||||
REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags
|
||||
|
@ -72,14 +79,12 @@ sixteen:
|
|||
SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
||||
# arg space
|
||||
|
||||
ADDU a0, $sp, 0 # 4 * FFI_SIZEOF_ARG
|
||||
move a0, $sp # 4 * FFI_SIZEOF_ARG
|
||||
ADDU a3, $fp, 3 * FFI_SIZEOF_ARG
|
||||
|
||||
# Call ffi_prep_args
|
||||
jal t9
|
||||
|
||||
# ADDU $sp, $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
|
||||
|
||||
# Copy the stack pointer to t9
|
||||
move t9, $sp
|
||||
|
||||
|
@ -90,18 +95,16 @@ sixteen:
|
|||
REG_L t6, 2*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# Is it bigger than 8 * FFI_SIZEOF_ARG?
|
||||
dadd t7, $0, 8 * FFI_SIZEOF_ARG
|
||||
dsub t8, t6, t7
|
||||
daddiu t8, t6, -(8 * FFI_SIZEOF_ARG)
|
||||
bltz t8, loadregs
|
||||
|
||||
add t9, t9, t8
|
||||
ADDU t9, t9, t8
|
||||
|
||||
loadregs:
|
||||
|
||||
REG_L t4, 3*FFI_SIZEOF_ARG($fp) # load the flags word
|
||||
add t6, t4, 0 # and copy it into t6
|
||||
REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6.
|
||||
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
and t4, t6, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg1_floatp
|
||||
REG_L a0, 0*FFI_SIZEOF_ARG(t9)
|
||||
b arg1_next
|
||||
|
@ -113,8 +116,7 @@ arg1_doublep:
|
|||
l.d $f12, 0*FFI_SIZEOF_ARG(t9)
|
||||
arg1_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 1*FFI_FLAG_BITS
|
||||
SRL t4, t6, 1*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg2_floatp
|
||||
REG_L a1, 1*FFI_SIZEOF_ARG(t9)
|
||||
|
@ -127,8 +129,7 @@ arg2_doublep:
|
|||
l.d $f13, 1*FFI_SIZEOF_ARG(t9)
|
||||
arg2_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 2*FFI_FLAG_BITS
|
||||
SRL t4, t6, 2*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg3_floatp
|
||||
REG_L a2, 2*FFI_SIZEOF_ARG(t9)
|
||||
|
@ -141,8 +142,7 @@ arg3_doublep:
|
|||
l.d $f14, 2*FFI_SIZEOF_ARG(t9)
|
||||
arg3_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 3*FFI_FLAG_BITS
|
||||
SRL t4, t6, 3*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg4_floatp
|
||||
REG_L a3, 3*FFI_SIZEOF_ARG(t9)
|
||||
|
@ -155,8 +155,7 @@ arg4_doublep:
|
|||
l.d $f15, 3*FFI_SIZEOF_ARG(t9)
|
||||
arg4_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 4*FFI_FLAG_BITS
|
||||
SRL t4, t6, 4*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg5_floatp
|
||||
REG_L a4, 4*FFI_SIZEOF_ARG(t9)
|
||||
|
@ -169,8 +168,7 @@ arg5_doublep:
|
|||
l.d $f16, 4*FFI_SIZEOF_ARG(t9)
|
||||
arg5_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 5*FFI_FLAG_BITS
|
||||
SRL t4, t6, 5*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg6_floatp
|
||||
REG_L a5, 5*FFI_SIZEOF_ARG(t9)
|
||||
|
@ -183,8 +181,7 @@ arg6_doublep:
|
|||
l.d $f17, 5*FFI_SIZEOF_ARG(t9)
|
||||
arg6_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 6*FFI_FLAG_BITS
|
||||
SRL t4, t6, 6*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg7_floatp
|
||||
REG_L a6, 6*FFI_SIZEOF_ARG(t9)
|
||||
|
@ -197,8 +194,7 @@ arg7_doublep:
|
|||
l.d $f18, 6*FFI_SIZEOF_ARG(t9)
|
||||
arg7_next:
|
||||
|
||||
add t4, t6, 0
|
||||
SRL t4, 7*FFI_FLAG_BITS
|
||||
SRL t4, t6, 7*FFI_FLAG_BITS
|
||||
and t4, ((1<<FFI_FLAG_BITS)-1)
|
||||
bnez t4, arg8_floatp
|
||||
REG_L a7, 7*FFI_SIZEOF_ARG(t9)
|
||||
|
@ -315,6 +311,224 @@ epilogue:
|
|||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
.LFE3:
|
||||
.end ffi_call_N32
|
||||
|
||||
/* ffi_closure_N32. Expects address of the passed-in ffi_closure in t0
|
||||
($12). Stores any arguments passed in registers onto the stack,
|
||||
then calls ffi_closure_mips_inner_N32, which then decodes
|
||||
them.
|
||||
|
||||
Stack layout:
|
||||
|
||||
20 - Start of parameters, original sp
|
||||
19 - Called function a7 save
|
||||
18 - Called function a6 save
|
||||
17 - Called function a5 save
|
||||
16 - Called function a4 save
|
||||
15 - Called function a3 save
|
||||
14 - Called function a2 save
|
||||
13 - Called function a1 save
|
||||
12 - Called function a0 save
|
||||
11 - Called function f19
|
||||
10 - Called function f18
|
||||
9 - Called function f17
|
||||
8 - Called function f16
|
||||
7 - Called function f15
|
||||
6 - Called function f14
|
||||
5 - Called function f13
|
||||
4 - Called function f12
|
||||
3 - return value high (v1 or $f2)
|
||||
2 - return value low (v0 or $f0)
|
||||
1 - ra save
|
||||
0 - gp save our sp points here
|
||||
*/
|
||||
|
||||
#define SIZEOF_FRAME2 (20 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define A7_OFF2 (19 * FFI_SIZEOF_ARG)
|
||||
#define A6_OFF2 (18 * FFI_SIZEOF_ARG)
|
||||
#define A5_OFF2 (17 * FFI_SIZEOF_ARG)
|
||||
#define A4_OFF2 (16 * FFI_SIZEOF_ARG)
|
||||
#define A3_OFF2 (15 * FFI_SIZEOF_ARG)
|
||||
#define A2_OFF2 (14 * FFI_SIZEOF_ARG)
|
||||
#define A1_OFF2 (13 * FFI_SIZEOF_ARG)
|
||||
#define A0_OFF2 (12 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define F19_OFF2 (11 * FFI_SIZEOF_ARG)
|
||||
#define F18_OFF2 (10 * FFI_SIZEOF_ARG)
|
||||
#define F17_OFF2 (9 * FFI_SIZEOF_ARG)
|
||||
#define F16_OFF2 (8 * FFI_SIZEOF_ARG)
|
||||
#define F15_OFF2 (7 * FFI_SIZEOF_ARG)
|
||||
#define F14_OFF2 (6 * FFI_SIZEOF_ARG)
|
||||
#define F13_OFF2 (5 * FFI_SIZEOF_ARG)
|
||||
#define F12_OFF2 (4 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define V1_OFF2 (3 * FFI_SIZEOF_ARG)
|
||||
#define V0_OFF2 (2 * FFI_SIZEOF_ARG)
|
||||
|
||||
#define RA_OFF2 (1 * FFI_SIZEOF_ARG)
|
||||
#define GP_OFF2 (0 * FFI_SIZEOF_ARG)
|
||||
|
||||
.align 2
|
||||
.globl ffi_closure_N32
|
||||
.ent ffi_closure_N32
|
||||
ffi_closure_N32:
|
||||
.LFB2:
|
||||
.frame $sp, SIZEOF_FRAME2, ra
|
||||
.mask 0x90000000,-(SIZEOF_FRAME2 - RA_OFF2)
|
||||
.fmask 0x00000000,0
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.LCFI5:
|
||||
.cpsetup t9, GP_OFF2, ffi_closure_N32
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
.LCFI6:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# fit in registers, then they were stored on the stack.
|
||||
REG_S a0, A0_OFF2($sp)
|
||||
REG_S a1, A1_OFF2($sp)
|
||||
REG_S a2, A2_OFF2($sp)
|
||||
REG_S a3, A3_OFF2($sp)
|
||||
REG_S a4, A4_OFF2($sp)
|
||||
REG_S a5, A5_OFF2($sp)
|
||||
REG_S a6, A6_OFF2($sp)
|
||||
REG_S a7, A7_OFF2($sp)
|
||||
|
||||
# Store all possible float/double registers.
|
||||
s.d $f12, F12_OFF2($sp)
|
||||
s.d $f13, F13_OFF2($sp)
|
||||
s.d $f14, F14_OFF2($sp)
|
||||
s.d $f15, F15_OFF2($sp)
|
||||
s.d $f16, F16_OFF2($sp)
|
||||
s.d $f17, F17_OFF2($sp)
|
||||
s.d $f18, F18_OFF2($sp)
|
||||
s.d $f19, F19_OFF2($sp)
|
||||
|
||||
# Call ffi_closure_mips_inner_N32 to do the real work.
|
||||
LA t9, ffi_closure_mips_inner_N32
|
||||
move a0, $12 # Pointer to the ffi_closure
|
||||
ADDU a1, $sp, V0_OFF2
|
||||
ADDU a2, $sp, A0_OFF2
|
||||
ADDU a3, $sp, F12_OFF2
|
||||
jalr t9
|
||||
|
||||
# Return flags are in v0
|
||||
bne v0, FFI_TYPE_INT, cls_retfloat
|
||||
REG_L v0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retfloat:
|
||||
bne v0, FFI_TYPE_FLOAT, cls_retdouble
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retdouble:
|
||||
bne v0, FFI_TYPE_DOUBLE, cls_retstruct_d
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_d:
|
||||
bne v0, FFI_TYPE_STRUCT_D, cls_retstruct_f
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_f:
|
||||
bne v0, FFI_TYPE_STRUCT_F, cls_retstruct_d_d
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_d_d:
|
||||
bne v0, FFI_TYPE_STRUCT_DD, cls_retstruct_f_f
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
l.d $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_f_f:
|
||||
bne v0, FFI_TYPE_STRUCT_FF, cls_retstruct_d_f
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
l.s $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_d_f:
|
||||
bne v0, FFI_TYPE_STRUCT_DF, cls_retstruct_f_d
|
||||
l.d $f0, V0_OFF2($sp)
|
||||
l.s $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_f_d:
|
||||
bne v0, FFI_TYPE_STRUCT_FD, cls_retstruct_small2
|
||||
l.s $f0, V0_OFF2($sp)
|
||||
l.d $f2, V1_OFF2($sp)
|
||||
b cls_epilogue
|
||||
|
||||
cls_retstruct_small2:
|
||||
REG_L v0, V0_OFF2($sp)
|
||||
REG_L v1, V1_OFF2($sp)
|
||||
|
||||
# Epilogue
|
||||
cls_epilogue:
|
||||
REG_L ra, RA_OFF2($sp) # Restore return address
|
||||
.cpreturn
|
||||
ADDU $sp, SIZEOF_FRAME2
|
||||
j ra
|
||||
.LFE2:
|
||||
.end ffi_closure_N32
|
||||
|
||||
.section .eh_frame,"aw",@progbits
|
||||
.Lframe1:
|
||||
.4byte .LECIE1-.LSCIE1 # length
|
||||
.LSCIE1:
|
||||
.4byte 0x0 # CIE
|
||||
.byte 0x1 # Version 1
|
||||
.ascii "\000" # Augmentation
|
||||
.uleb128 0x1 # Code alignment 1
|
||||
.sleb128 -4 # Data alignment -4
|
||||
.byte 0x1f # Return Address $31
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1d # in $sp
|
||||
.uleb128 0x0 # offset 0
|
||||
.align EH_FRAME_ALIGN
|
||||
.LECIE1:
|
||||
|
||||
.LSFDE1:
|
||||
.4byte .LEFDE1-.LASFDE1 # length.
|
||||
.LASFDE1:
|
||||
.4byte .LASFDE1-.Lframe1 # CIE_pointer.
|
||||
FDE_ADDR_BYTES .LFB3 # initial_location.
|
||||
FDE_ADDR_BYTES .LFE3-.LFB3 # address_range.
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB3 # to .LCFI0
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 SIZEOF_FRAME # adjust stack.by SIZEOF_FRAME
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0 # to .LCFI1
|
||||
.byte 0x9e # DW_CFA_offset of $fp
|
||||
.uleb128 2*FFI_SIZEOF_ARG/4 #
|
||||
.byte 0x9f # DW_CFA_offset of ra
|
||||
.uleb128 1*FFI_SIZEOF_ARG/4 #
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI3-.LCFI1 # to .LCFI3
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.uleb128 0x1e # in $fp
|
||||
.align EH_FRAME_ALIGN
|
||||
.LEFDE1:
|
||||
.LSFDE3:
|
||||
.4byte .LEFDE3-.LASFDE3 # length
|
||||
.LASFDE3:
|
||||
.4byte .LASFDE3-.Lframe1 # CIE_pointer.
|
||||
FDE_ADDR_BYTES .LFB2 # initial_location.
|
||||
FDE_ADDR_BYTES .LFE2-.LFB2 # address_range.
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI5-.LFB2 # to .LCFI5
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 SIZEOF_FRAME2 # adjust stack.by SIZEOF_FRAME
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte .LCFI6-.LCFI5 # to .LCFI6
|
||||
.byte 0x9c # DW_CFA_offset of $gp ($28)
|
||||
.uleb128 (SIZEOF_FRAME2 - GP_OFF2)/4
|
||||
.byte 0x9f # DW_CFA_offset of ra ($31)
|
||||
.uleb128 (SIZEOF_FRAME2 - RA_OFF2)/4
|
||||
.align EH_FRAME_ALIGN
|
||||
.LEFDE3:
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
|
@ -183,27 +184,30 @@ $LFE0:
|
|||
|
||||
|
||||
/* ffi_closure_O32. Expects address of the passed-in ffi_closure
|
||||
in t0. Stores any arguments passed in registers onto the
|
||||
in t4 ($12). Stores any arguments passed in registers onto the
|
||||
stack, then calls ffi_closure_mips_inner_O32, which
|
||||
then decodes them.
|
||||
|
||||
Stack layout:
|
||||
|
||||
14 - Start of parameters, original sp
|
||||
13 - ra save
|
||||
12 - fp save
|
||||
11 - $16 (s0) save
|
||||
10 - cprestore
|
||||
9 - return value high (v1)
|
||||
8 - return value low (v0)
|
||||
7 - f14 (le high, be low)
|
||||
6 - f14 (le low, be high)
|
||||
5 - f12 (le high, be low)
|
||||
4 - f12 (le low, be high)
|
||||
3 - Called function a3 save
|
||||
2 - Called function a2 save
|
||||
1 - Called function a1 save
|
||||
0 - Called function a0 save our sp, fp point here
|
||||
3 - a3 save
|
||||
2 - a2 save
|
||||
1 - a1 save
|
||||
0 - a0 save, original sp
|
||||
-1 - ra save
|
||||
-2 - fp save
|
||||
-3 - $16 (s0) save
|
||||
-4 - cprestore
|
||||
-5 - return value high (v1)
|
||||
-6 - return value low (v0)
|
||||
-7 - f14 (le high, be low)
|
||||
-8 - f14 (le low, be high)
|
||||
-9 - f12 (le high, be low)
|
||||
-10 - f12 (le low, be high)
|
||||
-11 - Called function a3 save
|
||||
-12 - Called function a2 save
|
||||
-13 - Called function a1 save
|
||||
-14 - Called function a0 save, our sp and fp point here
|
||||
*/
|
||||
|
||||
#define SIZEOF_FRAME2 (14 * FFI_SIZEOF_ARG)
|
||||
|
@ -251,7 +255,7 @@ $LCFI7:
|
|||
REG_S a3, A3_OFF2($fp)
|
||||
|
||||
# Load ABI enum to s0
|
||||
REG_L $16, 20($8) # cif pointer follows tramp.
|
||||
REG_L $16, 20($12) # cif pointer follows tramp.
|
||||
REG_L $16, 0($16) # abi is first member.
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
|
@ -263,7 +267,7 @@ $LCFI7:
|
|||
1:
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
la t9, ffi_closure_mips_inner_O32
|
||||
move a0, $8 # Pointer to the ffi_closure
|
||||
move a0, $12 # Pointer to the ffi_closure
|
||||
addu a1, $fp, V0_OFF2
|
||||
addu a2, $fp, A0_OFF2
|
||||
addu a3, $fp, FA_0_0_OFF2
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
(c) 2008 Red Hat, Inc.
|
||||
|
||||
HPPA Foreign Function Interface
|
||||
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -14,13 +16,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -30,15 +33,19 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
|
||||
#define ROUND_DOWN(v, a) (((size_t)(v) - (a) + 1) & ~((a) - 1))
|
||||
|
||||
#define MIN_STACK_SIZE 64
|
||||
#define FIRST_ARG_SLOT 9
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
#define fldw(addr, fpreg) asm volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
|
||||
#define fstw(fpreg, addr) asm volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
#define fldd(addr, fpreg) asm volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
|
||||
#define fstd(fpreg, addr) asm volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
#define fldw(addr, fpreg) \
|
||||
__asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
|
||||
#define fstw(fpreg, addr) \
|
||||
__asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
#define fldd(addr, fpreg) \
|
||||
__asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
|
||||
#define fstd(fpreg, addr) \
|
||||
__asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
|
||||
|
||||
#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
|
||||
|
||||
|
@ -47,16 +54,19 @@ static inline int ffi_struct_type(ffi_type *t)
|
|||
size_t sz = t->size;
|
||||
|
||||
/* Small structure results are passed in registers,
|
||||
larger ones are passed by pointer. */
|
||||
larger ones are passed by pointer. Note that
|
||||
small structures of size 2, 4 and 8 differ from
|
||||
the corresponding integer types in that they have
|
||||
different alignment requirements. */
|
||||
|
||||
if (sz <= 1)
|
||||
return FFI_TYPE_UINT8;
|
||||
else if (sz == 2)
|
||||
return FFI_TYPE_UINT16;
|
||||
return FFI_TYPE_SMALL_STRUCT2;
|
||||
else if (sz == 3)
|
||||
return FFI_TYPE_SMALL_STRUCT3;
|
||||
else if (sz == 4)
|
||||
return FFI_TYPE_UINT32;
|
||||
return FFI_TYPE_SMALL_STRUCT4;
|
||||
else if (sz == 5)
|
||||
return FFI_TYPE_SMALL_STRUCT5;
|
||||
else if (sz == 6)
|
||||
|
@ -64,61 +74,80 @@ static inline int ffi_struct_type(ffi_type *t)
|
|||
else if (sz == 7)
|
||||
return FFI_TYPE_SMALL_STRUCT7;
|
||||
else if (sz <= 8)
|
||||
return FFI_TYPE_UINT64;
|
||||
return FFI_TYPE_SMALL_STRUCT8;
|
||||
else
|
||||
return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
|
||||
}
|
||||
|
||||
/* PA has a downward growing stack, which looks like this:
|
||||
|
||||
|
||||
Offset
|
||||
[ Variable args ]
|
||||
[ Variable args ]
|
||||
SP = (4*(n+9)) arg word N
|
||||
...
|
||||
SP-52 arg word 4
|
||||
[ Fixed args ]
|
||||
[ Fixed args ]
|
||||
SP-48 arg word 3
|
||||
SP-44 arg word 2
|
||||
SP-40 arg word 1
|
||||
SP-36 arg word 0
|
||||
[ Frame marker ]
|
||||
[ Frame marker ]
|
||||
...
|
||||
SP-20 RP
|
||||
SP-4 previous SP
|
||||
|
||||
First 4 non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23
|
||||
First 2 non-FP 64-bit args are passed in register pairs, starting
|
||||
on an even numbered register (i.e. r26/r25 and r24+r23)
|
||||
First 4 FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L
|
||||
First 2 FP 64-bit arguments are passed in fr5 and fr7
|
||||
The rest are passed on the stack starting at SP-52, but 64-bit
|
||||
arguments need to be aligned to an 8-byte boundary
|
||||
|
||||
|
||||
The first four argument words on the stack are reserved for use by
|
||||
the callee. Instead, the general and floating registers replace
|
||||
the first four argument slots. Non FP arguments are passed solely
|
||||
in the general registers. FP arguments are passed in both general
|
||||
and floating registers when using libffi.
|
||||
|
||||
Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
|
||||
Non-FP 64-bit args are passed in register pairs, starting
|
||||
on an odd numbered register (i.e. r25+r26 and r23+r24).
|
||||
FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
|
||||
FP 64-bit arguments are passed in fr5 and fr7.
|
||||
|
||||
The registers are allocated in the same manner as stack slots.
|
||||
This allows the callee to save its arguments on the stack if
|
||||
necessary:
|
||||
|
||||
arg word 3 -> gr23 or fr7L
|
||||
arg word 2 -> gr24 or fr6L or fr7R
|
||||
arg word 1 -> gr25 or fr5L
|
||||
arg word 0 -> gr26 or fr4L or fr5R
|
||||
|
||||
Note that fr4R and fr6R are never used for arguments (i.e.,
|
||||
doubles are not passed in fr4 or fr6).
|
||||
|
||||
The rest of the arguments are passed on the stack starting at SP-52,
|
||||
but 64-bit arguments need to be aligned to an 8-byte boundary
|
||||
|
||||
This means we can have holes either in the register allocation,
|
||||
or in the stack. */
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments
|
||||
|
||||
|
||||
The following code will put everything into the stack frame
|
||||
(which was allocated by the asm routine), and on return
|
||||
the asm routine will load the arguments that should be
|
||||
passed by register into the appropriate registers
|
||||
|
||||
|
||||
NOTE: We load floating point args in this function... that means we
|
||||
assume gcc will not mess with fp regs in here. */
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
|
||||
/*@=exportheader@*/
|
||||
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
|
||||
{
|
||||
register unsigned int i;
|
||||
register ffi_type **p_arg;
|
||||
register void **p_argv;
|
||||
unsigned int slot = FIRST_ARG_SLOT - 1;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
char *dest_cpy;
|
||||
size_t len;
|
||||
|
||||
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, ecif, bytes);
|
||||
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
|
||||
ecif, bytes);
|
||||
|
||||
p_arg = ecif->cif->arg_types;
|
||||
p_argv = ecif->avalue;
|
||||
|
@ -130,116 +159,105 @@ void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
|
|||
switch (type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
slot++;
|
||||
*(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
slot++;
|
||||
*(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
slot++;
|
||||
*(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
slot++;
|
||||
*(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
slot++;
|
||||
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), slot);
|
||||
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
|
||||
slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
slot += 2;
|
||||
if (slot & 1)
|
||||
slot++;
|
||||
|
||||
*(UINT32 *)(stack - slot) = (*(UINT64 *)(*p_argv)) >> 32;
|
||||
*(UINT32 *)(stack - slot + 1) = (*(UINT64 *)(*p_argv)) & 0xffffffffUL;
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* First 4 args go in fr4L - fr7L */
|
||||
slot++;
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
debug(3, "Storing UINT32(float) in slot %u\n", slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 0: fldw(*p_argv, fr4); break;
|
||||
case 1: fldw(*p_argv, fr5); break;
|
||||
case 2: fldw(*p_argv, fr6); break;
|
||||
case 3: fldw(*p_argv, fr7); break;
|
||||
default:
|
||||
/* Other ones are just passed on the stack. */
|
||||
debug(3, "Storing UINT32(float) in slot %u\n", slot);
|
||||
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
slot += 2;
|
||||
if (slot & 1)
|
||||
slot++;
|
||||
switch (slot - FIRST_ARG_SLOT + 1)
|
||||
{
|
||||
/* First 2 args go in fr5, fr7 */
|
||||
case 2: fldd(*p_argv, fr5); break;
|
||||
case 4: fldd(*p_argv, fr7); break;
|
||||
default:
|
||||
debug(3, "Storing UINT64(double) at slot %u\n", slot);
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
break;
|
||||
/* First 4 args go in fr4L - fr7L. */
|
||||
case 0: fldw(stack - slot, fr4); break;
|
||||
case 1: fldw(stack - slot, fr5); break;
|
||||
case 2: fldw(stack - slot, fr6); break;
|
||||
case 3: fldw(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* Align slot for 64-bit type. */
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
debug(3, "Storing UINT64(double) at slot %u\n", slot);
|
||||
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
/* First 2 args go in fr5, fr7. */
|
||||
case 1: fldd(stack - slot, fr5); break;
|
||||
case 3: fldd(stack - slot, fr7); break;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are passed in the same manner as structures
|
||||
larger than 8 bytes. */
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
|
||||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
|
||||
if((*p_arg)->size <= 4)
|
||||
len = (*p_arg)->size;
|
||||
if (len <= 4)
|
||||
{
|
||||
slot++;
|
||||
dest_cpy = (char *)(stack - slot);
|
||||
dest_cpy += 4 - (*p_arg)->size;
|
||||
memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
|
||||
dest_cpy = (char *)(stack - slot) + 4 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else if ((*p_arg)->size <= 8)
|
||||
else if (len <= 8)
|
||||
{
|
||||
slot += 2;
|
||||
if (slot & 1)
|
||||
slot++;
|
||||
dest_cpy = (char *)(stack - slot);
|
||||
dest_cpy += 8 - (*p_arg)->size;
|
||||
memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
slot++;
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
dest_cpy = (char *)(stack - slot) + 8 - len;
|
||||
memcpy(dest_cpy, (char *)*p_argv, len);
|
||||
}
|
||||
else
|
||||
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
p_argv++;
|
||||
}
|
||||
|
||||
/* Make sure we didn't mess up and scribble on the stack. */
|
||||
{
|
||||
int n;
|
||||
unsigned int n;
|
||||
|
||||
debug(5, "Stack setup:\n");
|
||||
for (n = 0; n < (bytes + 3) / 4; n++)
|
||||
|
@ -255,7 +273,7 @@ void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
|
|||
return;
|
||||
}
|
||||
|
||||
static void ffi_size_stack_LINUX(ffi_cif *cif)
|
||||
static void ffi_size_stack_pa32(ffi_cif *cif)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
int i;
|
||||
|
@ -273,6 +291,9 @@ static void ffi_size_stack_LINUX(ffi_cif *cif)
|
|||
z += 2 + (z & 1); /* must start on even regs, so we may waste one */
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
case FFI_TYPE_STRUCT:
|
||||
z += 1; /* pass by ptr, callee will copy */
|
||||
break;
|
||||
|
@ -304,6 +325,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
#ifdef PA_HPUX
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
/* Long doubles are treated like a structure. */
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* For the return type we have to check the size of the structures.
|
||||
If the size is smaller or equal 4 bytes, the result is given back
|
||||
|
@ -327,8 +355,8 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
own stack sizing. */
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_LINUX:
|
||||
ffi_size_stack_LINUX(cif);
|
||||
case FFI_PA32:
|
||||
ffi_size_stack_pa32(cif);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -339,20 +367,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
|
||||
extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void));
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
|
@ -362,12 +381,15 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
/* If the return value is a struct and we don't have a return
|
||||
value address then we need to make one. */
|
||||
|
||||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
if (rvalue == NULL
|
||||
#ifdef PA_HPUX
|
||||
&& (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
|| cif->rtype->type == FFI_TYPE_LONGDOUBLE))
|
||||
#else
|
||||
&& cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
#endif
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
@ -375,12 +397,10 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_LINUX:
|
||||
/*@-usedef@*/
|
||||
debug(2, "Calling ffi_call_LINUX: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
|
||||
ffi_call_LINUX(ffi_prep_args_LINUX, &ecif, cif->bytes,
|
||||
case FFI_PA32:
|
||||
debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
|
||||
ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -394,7 +414,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
the stack, and we need to fill them into a cif structure and invoke
|
||||
the user function. This really ought to be in asm to make sure
|
||||
the compiler doesn't do things we don't expect. */
|
||||
UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
||||
ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
|
@ -402,7 +422,8 @@ UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
|||
UINT32 ret[2]; /* function can return up to 64-bits in registers */
|
||||
ffi_type **p_arg;
|
||||
char *tmp;
|
||||
int i, avn, slot = FIRST_ARG_SLOT - 1;
|
||||
int i, avn;
|
||||
unsigned int slot = FIRST_ARG_SLOT;
|
||||
register UINT32 r28 asm("r28");
|
||||
|
||||
cif = closure->cif;
|
||||
|
@ -430,20 +451,23 @@ UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
|||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
slot++;
|
||||
avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
slot += 2;
|
||||
if (slot & 1)
|
||||
slot++;
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
slot++;
|
||||
#ifdef PA_LINUX
|
||||
/* The closure call is indirect. In Linux, floating point
|
||||
arguments in indirect calls with a prototype are passed
|
||||
in the floating point registers instead of the general
|
||||
registers. So, we need to replace what was previously
|
||||
stored in the current slot with the value in the
|
||||
corresponding floating point register. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 0: fstw(fr4, (void *)(stack - slot)); break;
|
||||
|
@ -451,18 +475,20 @@ UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
|||
case 2: fstw(fr6, (void *)(stack - slot)); break;
|
||||
case 3: fstw(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
slot += 2;
|
||||
if (slot & 1)
|
||||
slot++;
|
||||
switch (slot - FIRST_ARG_SLOT + 1)
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
#ifdef PA_LINUX
|
||||
/* See previous comment for FFI_TYPE_FLOAT. */
|
||||
switch (slot - FIRST_ARG_SLOT)
|
||||
{
|
||||
case 2: fstd(fr5, (void *)(stack - slot)); break;
|
||||
case 4: fstd(fr7, (void *)(stack - slot)); break;
|
||||
case 1: fstd(fr5, (void *)(stack - slot)); break;
|
||||
case 3: fstd(fr7, (void *)(stack - slot)); break;
|
||||
}
|
||||
#endif
|
||||
avalue[i] = (void *)(stack - slot);
|
||||
break;
|
||||
|
||||
|
@ -470,35 +496,36 @@ UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
|||
/* Structs smaller or equal than 4 bytes are passed in one
|
||||
register. Structs smaller or equal 8 bytes are passed in two
|
||||
registers. Larger structures are passed by pointer. */
|
||||
if((*p_arg)->size <= 4) {
|
||||
slot++;
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
|
||||
(*p_arg)->size;
|
||||
} else if ((*p_arg)->size <= 8) {
|
||||
slot += 2;
|
||||
if (slot & 1)
|
||||
slot++;
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
|
||||
(*p_arg)->size;
|
||||
} else {
|
||||
slot++;
|
||||
if((*p_arg)->size <= 4)
|
||||
{
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else if ((*p_arg)->size <= 8)
|
||||
{
|
||||
slot += (slot & 1) ? 1 : 2;
|
||||
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
|
||||
(*p_arg)->size;
|
||||
}
|
||||
else
|
||||
avalue[i] = (void *) *(stack - slot);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
slot++;
|
||||
p_arg++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], ret[1]);
|
||||
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
|
||||
ret[1]);
|
||||
|
||||
/* Store the result */
|
||||
/* Store the result using the lower 2 bytes of the flags. */
|
||||
switch (cif->flags)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
|
@ -536,7 +563,9 @@ UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
|||
/* Don't need a return value, done by caller. */
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SMALL_STRUCT2:
|
||||
case FFI_TYPE_SMALL_STRUCT3:
|
||||
case FFI_TYPE_SMALL_STRUCT4:
|
||||
tmp = (void*)(stack - FIRST_ARG_SLOT);
|
||||
tmp += 4 - cif->rtype->size;
|
||||
memcpy((void*)tmp, &ret[0], cif->rtype->size);
|
||||
|
@ -545,6 +574,7 @@ UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
|||
case FFI_TYPE_SMALL_STRUCT5:
|
||||
case FFI_TYPE_SMALL_STRUCT6:
|
||||
case FFI_TYPE_SMALL_STRUCT7:
|
||||
case FFI_TYPE_SMALL_STRUCT8:
|
||||
{
|
||||
unsigned int ret2[2];
|
||||
int off;
|
||||
|
@ -582,39 +612,93 @@ UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
|
|||
cif specifies the argument and result types for fun.
|
||||
The cif must already be prep'ed. */
|
||||
|
||||
void ffi_closure_LINUX(void);
|
||||
extern void ffi_closure_pa32(void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
UINT32 *tramp = (UINT32 *)(closure->tramp);
|
||||
#ifdef PA_HPUX
|
||||
UINT32 *tmp;
|
||||
#endif
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_LINUX);
|
||||
FFI_ASSERT (cif->abi == FFI_PA32);
|
||||
|
||||
/* Make a small trampoline that will branch to our
|
||||
handler function. Use PC-relative addressing. */
|
||||
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8, %r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2, %r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10028; /* ldw 20(%r21), %r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21), %r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1), %r22 ; address of handler */
|
||||
tramp[5] = 0xeac0c000; /* bv %r0(%r22) ; branch to handler */
|
||||
tramp[6] = 0x0c281093; /* ldw 4(%r1), %r19 ; GP of handler */
|
||||
tramp[7] = ((UINT32)(ffi_closure_LINUX) & ~2);
|
||||
#ifdef PA_LINUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
|
||||
tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush up 2 two lines because of
|
||||
alignment. */
|
||||
asm volatile (
|
||||
"fdc 0(%0)\n"
|
||||
"fdc %1(%0)\n"
|
||||
"fic 0(%%sr4, %0)\n"
|
||||
"fic %1(%%sr4, %0)\n"
|
||||
"sync\n"
|
||||
: : "r"((unsigned long)tramp & ~31), "r"(32 /* stride */));
|
||||
__asm__ volatile(
|
||||
"fdc 0(%0)\n\t"
|
||||
"fdc %1(%0)\n\t"
|
||||
"fic 0(%%sr4, %0)\n\t"
|
||||
"fic %1(%%sr4, %0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
:
|
||||
: "r"((unsigned long)tramp & ~31),
|
||||
"r"(32 /* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
|
||||
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
|
||||
tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
|
||||
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
|
||||
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
|
||||
tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
|
||||
tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
|
||||
tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
|
||||
tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
|
||||
tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
|
||||
|
||||
/* Flush d/icache -- have to flush three lines because of alignment. */
|
||||
__asm__ volatile(
|
||||
"copy %1,%0\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"fdc,m %2(%0)\n\t"
|
||||
"ldsid (%1),%0\n\t"
|
||||
"mtsp %0,%%sr0\n\t"
|
||||
"copy %1,%0\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"fic,m %2(%%sr0,%0)\n\t"
|
||||
"sync\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n"
|
||||
: "=&r" ((unsigned long)tmp)
|
||||
: "r" ((unsigned long)tramp & ~31),
|
||||
"r" (32/* stride */)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
@ -35,9 +36,20 @@ typedef signed long ffi_sarg;
|
|||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef PA
|
||||
FFI_LINUX,
|
||||
FFI_DEFAULT_ABI = FFI_LINUX,
|
||||
#ifdef PA_LINUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA_HPUX
|
||||
FFI_PA32,
|
||||
FFI_DEFAULT_ABI = FFI_PA32,
|
||||
#endif
|
||||
|
||||
#ifdef PA64_HPUX
|
||||
#error "PA64_HPUX FFI is not yet implemented"
|
||||
FFI_PA64,
|
||||
FFI_DEFAULT_ABI = FFI_PA64,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
|
@ -49,11 +61,17 @@ typedef enum ffi_abi {
|
|||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#ifdef PA_LINUX
|
||||
#define FFI_TRAMPOLINE_SIZE 32
|
||||
|
||||
#define FFI_TYPE_SMALL_STRUCT3 -1
|
||||
#define FFI_TYPE_SMALL_STRUCT5 -2
|
||||
#define FFI_TYPE_SMALL_STRUCT6 -3
|
||||
#define FFI_TYPE_SMALL_STRUCT7 -4
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
#define FFI_TYPE_SMALL_STRUCT2 -1
|
||||
#define FFI_TYPE_SMALL_STRUCT3 -2
|
||||
#define FFI_TYPE_SMALL_STRUCT4 -3
|
||||
#define FFI_TYPE_SMALL_STRUCT5 -4
|
||||
#define FFI_TYPE_SMALL_STRUCT6 -5
|
||||
#define FFI_TYPE_SMALL_STRUCT7 -6
|
||||
#define FFI_TYPE_SMALL_STRUCT8 -7
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
||||
(c) 2008 Red Hat, Inc.
|
||||
|
||||
HPPA Foreign Function Interface
|
||||
|
||||
|
@ -17,7 +18,7 @@
|
|||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
IN NO EVENT SHALL RENESAS TECHNOLOGY 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.
|
||||
|
@ -31,20 +32,20 @@
|
|||
.level 1.1
|
||||
.align 4
|
||||
|
||||
/* void ffi_call_LINUX(void (*)(char *, extended_cif *),
|
||||
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
||||
extended_cif *ecif,
|
||||
unsigned bytes,
|
||||
unsigned flags,
|
||||
unsigned *rvalue,
|
||||
void (*fn)());
|
||||
void (*fn)(void));
|
||||
*/
|
||||
|
||||
.export ffi_call_LINUX,code
|
||||
.import ffi_prep_args_LINUX,code
|
||||
.export ffi_call_pa32,code
|
||||
.import ffi_prep_args_pa32,code
|
||||
|
||||
.type ffi_call_LINUX, @function
|
||||
.type ffi_call_pa32, @function
|
||||
.LFB1:
|
||||
ffi_call_LINUX:
|
||||
ffi_call_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
||||
.entry
|
||||
|
@ -63,7 +64,7 @@ ffi_call_LINUX:
|
|||
[ 64-bytes register save area ] <- %r4
|
||||
|
||||
[ Stack space for actual call, passed as ] <- %arg0
|
||||
[ arg0 to ffi_prep_args_LINUX ]
|
||||
[ arg0 to ffi_prep_args_pa32 ]
|
||||
|
||||
[ Stack for calling prep_args ] <- %sp
|
||||
*/
|
||||
|
@ -73,14 +74,14 @@ ffi_call_LINUX:
|
|||
.LCFI13:
|
||||
copy %sp, %r4
|
||||
|
||||
addl %arg2, %r4, %arg0 /* arg stack */
|
||||
stw %arg3, -48(%r3) /* save flags; we need it later */
|
||||
addl %arg2, %r4, %arg0 /* arg stack */
|
||||
stw %arg3, -48(%r3) /* save flags; we need it later */
|
||||
|
||||
/* Call prep_args:
|
||||
%arg0(stack) -- set up above
|
||||
%arg1(ecif) -- same as incoming param
|
||||
%arg2(bytes) -- same as incoming param */
|
||||
bl ffi_prep_args_LINUX,%r2
|
||||
bl ffi_prep_args_pa32,%r2
|
||||
ldo 64(%arg0), %sp
|
||||
ldo -64(%sp), %sp
|
||||
|
||||
|
@ -106,90 +107,139 @@ ffi_call_LINUX:
|
|||
|
||||
/* Store the result according to the return type. */
|
||||
|
||||
checksmst3:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, checksmst567
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. Shift
|
||||
left 8 bits to write to the result structure. */
|
||||
zdep %ret0, 23, 24, %r22
|
||||
b done
|
||||
stw %r22, 0(%r20)
|
||||
.Lcheckint:
|
||||
comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
|
||||
b .Ldone
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
checksmst567:
|
||||
/* 5-7 byte values are returned right justified:
|
||||
.Lcheckint8:
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lcheckint16:
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
|
||||
b .Ldone
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
.Lcheckdbl:
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
|
||||
b .Ldone
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
.Lcheckfloat:
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
|
||||
b .Ldone
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
.Lcheckll:
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
|
||||
stw %ret0, 0(%r20)
|
||||
b .Ldone
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
.Lchecksmst2:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
|
||||
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst3:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
|
||||
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst4:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
|
||||
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
.Lchecksmst5:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
|
||||
/* 5 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
5: ??????aa bbccddee
|
||||
6: ????aabb ccddeeff
|
||||
7: ??aabbcc ddeeffgg
|
||||
5: ??????aa bbccddee */
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
To store this in the result, write the first 4 bytes into a temp
|
||||
register using shrpw (t1 = aabbccdd), followed by a rotation of
|
||||
ret1:
|
||||
.Lchecksmst6:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
|
||||
/* 6 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
6: ????aabb ccddeeff */
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
ret0 ret1 ret1
|
||||
5: ??????aa bbccddee -> eebbccdd (rotate 8)
|
||||
6: ????aabb ccddeeff -> eeffccdd (rotate 16)
|
||||
7: ??aabbcc ddeeffgg -> eeffggdd (rotate 24)
|
||||
.Lchecksmst7:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
|
||||
/* 7 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
7: ??aabbcc ddeeffgg */
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
b .Ldone
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
then we write (t1, ret1) into the result. */
|
||||
.Lchecksmst8:
|
||||
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
|
||||
/* 8 byte values are returned right justified:
|
||||
ret0 ret1
|
||||
8: aabbccdd eeffgghh */
|
||||
extru %ret0, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret0, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stbs,ma %ret0, 1(%r20)
|
||||
extru %ret1, 7, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 15, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
extru %ret1, 23, 8, %r22
|
||||
stbs,ma %r22, 1(%r20)
|
||||
stb %ret1, 0(%r20)
|
||||
|
||||
addi,<> -FFI_TYPE_SMALL_STRUCT5,%r21,%r0
|
||||
ldi 8, %r22
|
||||
addi,<> -FFI_TYPE_SMALL_STRUCT6,%r21,%r0
|
||||
ldi 16, %r22
|
||||
addi,<> -FFI_TYPE_SMALL_STRUCT7,%r21,%r0
|
||||
ldi 24, %r22
|
||||
|
||||
/* This relies on all the FFI_TYPE_*_STRUCT* defines being <0 */
|
||||
cmpib,<=,n 0, %r21, checkint8
|
||||
mtsar %r22
|
||||
|
||||
shrpw %ret0, %ret1, %sar, %ret0 /* ret0 = aabbccdd */
|
||||
shrpw %ret1, %ret1, %sar, %ret1 /* rotate ret1 */
|
||||
|
||||
stw %ret0, 0(%r20)
|
||||
b done
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
checkint8:
|
||||
comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
|
||||
b done
|
||||
stb %ret0, 0(%r20)
|
||||
|
||||
checkint16:
|
||||
comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
|
||||
b done
|
||||
sth %ret0, 0(%r20)
|
||||
|
||||
checkint32:
|
||||
comib,<>,n FFI_TYPE_UINT32, %r21, checkint
|
||||
b done
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
checkint:
|
||||
comib,<>,n FFI_TYPE_INT, %r21, checkll
|
||||
b done
|
||||
stw %ret0, 0(%r20)
|
||||
|
||||
checkll:
|
||||
comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
|
||||
stw %ret0, 0(%r20)
|
||||
b done
|
||||
stw %ret1, 4(%r20)
|
||||
|
||||
checkdbl:
|
||||
comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
|
||||
b done
|
||||
fstd %fr4,0(%r20)
|
||||
|
||||
checkfloat:
|
||||
comib,<>,n FFI_TYPE_FLOAT, %r21, done
|
||||
fstw %fr4L,0(%r20)
|
||||
|
||||
/* structure returns are either handled by one of the
|
||||
INT/UINT64 cases above, or, if passed by pointer,
|
||||
is handled by the callee. */
|
||||
|
||||
done:
|
||||
.Ldone:
|
||||
/* all done, return */
|
||||
copy %r4, %sp /* pop arg stack */
|
||||
ldw 12(%r3), %r4
|
||||
|
@ -201,14 +251,14 @@ done:
|
|||
.procend
|
||||
.LFE1:
|
||||
|
||||
/* void ffi_closure_LINUX(void);
|
||||
/* void ffi_closure_pa32(void);
|
||||
Called with closure argument in %r21 */
|
||||
.export ffi_closure_LINUX,code
|
||||
.import ffi_closure_inner_LINUX,code
|
||||
.export ffi_closure_pa32,code
|
||||
.import ffi_closure_inner_pa32,code
|
||||
|
||||
.type ffi_closure_LINUX, @function
|
||||
.type ffi_closure_pa32, @function
|
||||
.LFB2:
|
||||
ffi_closure_LINUX:
|
||||
ffi_closure_pa32:
|
||||
.proc
|
||||
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
||||
.entry
|
||||
|
@ -228,7 +278,7 @@ ffi_closure_LINUX:
|
|||
stw %arg3, -48(%r3)
|
||||
|
||||
copy %r21, %arg0
|
||||
bl ffi_closure_inner_LINUX, %r2
|
||||
bl ffi_closure_inner_pa32, %r2
|
||||
copy %r3, %arg1
|
||||
|
||||
ldwm -64(%sp), %r3
|
||||
|
@ -299,7 +349,7 @@ ffi_closure_LINUX:
|
|||
.sleb128 -5
|
||||
|
||||
.byte 0x4 ;# DW_CFA_advance_loc4
|
||||
.word .LCFI12-.LCFI11
|
||||
.word .LCFI22-.LCFI21
|
||||
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
||||
.uleb128 0x3
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#ifdef __ppc__
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin.S - Copyright (c) 2000 John Hornkvist
|
||||
Copyright (c) 2004 Free Software Foundation, Inc.
|
||||
|
@ -244,4 +243,3 @@ LEFDE1:
|
|||
.align LOG2_GPR_BYTES
|
||||
LLFB0$non_lazy_ptr:
|
||||
.g_long LFB0
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#ifdef __ppc__
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc. based on ppc_closure.S
|
||||
|
@ -247,7 +246,7 @@ Lfinish:
|
|||
/* END(ffi_closure_ASM) */
|
||||
|
||||
.data
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
|
@ -316,4 +315,3 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
|
|||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long LFB1
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Geoffrey Keating
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
Copyright (C) 2008 Red Hat, Inc
|
||||
|
||||
PowerPC Foreign Function Interface
|
||||
|
||||
|
@ -39,7 +41,8 @@ enum {
|
|||
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
||||
FLAG_RETURNS_FP = 1 << (31-29),
|
||||
FLAG_RETURNS_64BITS = 1 << (31-28),
|
||||
FLAG_RETURNS_128BITS = 1 << (31-27),
|
||||
|
||||
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
|
||||
|
||||
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
||||
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
||||
|
@ -48,10 +51,13 @@ enum {
|
|||
};
|
||||
|
||||
/* About the SYSV ABI. */
|
||||
enum {
|
||||
NUM_GPR_ARG_REGISTERS = 8,
|
||||
NUM_FPR_ARG_REGISTERS = 8
|
||||
};
|
||||
unsigned int NUM_GPR_ARG_REGISTERS = 8;
|
||||
#ifndef __NO_FPRS__
|
||||
unsigned int NUM_FPR_ARG_REGISTERS = 8;
|
||||
#else
|
||||
unsigned int NUM_FPR_ARG_REGISTERS = 0;
|
||||
#endif
|
||||
|
||||
enum { ASM_NEEDS_REGISTERS = 4 };
|
||||
|
||||
/* ffi_prep_args_SYSV is called by the assembly routine once stack space
|
||||
|
@ -80,10 +86,8 @@ enum { ASM_NEEDS_REGISTERS = 4 };
|
|||
|
||||
*/
|
||||
|
||||
/*@-exportheader@*/
|
||||
void
|
||||
ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
|
@ -116,7 +120,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
/* 'next_arg' grows up as we put parameters in it. */
|
||||
valp next_arg;
|
||||
|
||||
int i;
|
||||
int i, ii MAYBE_UNUSED;
|
||||
ffi_type **ptr;
|
||||
double double_tmp;
|
||||
union {
|
||||
|
@ -134,6 +138,9 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
size_t struct_copy_size;
|
||||
unsigned gprvalue;
|
||||
|
||||
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
NUM_FPR_ARG_REGISTERS = 0;
|
||||
|
||||
stacktop.c = (char *) stack + bytes;
|
||||
gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
|
||||
intarg_count = 0;
|
||||
|
@ -165,6 +172,9 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
||||
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
goto soft_float_prep;
|
||||
double_tmp = **p_argv.f;
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
{
|
||||
|
@ -178,6 +188,9 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
|
||||
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
goto soft_double_prep;
|
||||
double_tmp = **p_argv.d;
|
||||
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
||||
|
@ -197,8 +210,77 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if ((ecif->cif->abi != FFI_LINUX)
|
||||
&& (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
|
||||
goto do_struct;
|
||||
/* The soft float ABI for long doubles works like this,
|
||||
a long double is passed in four consecutive gprs if available.
|
||||
A maximum of 2 long doubles can be passed in gprs.
|
||||
If we do not have 4 gprs left, the long double is passed on the
|
||||
stack, 4-byte aligned. */
|
||||
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
{
|
||||
unsigned int int_tmp = (*p_argv.ui)[0];
|
||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
|
||||
{
|
||||
if (intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
||||
*next_arg.u = int_tmp;
|
||||
next_arg.u++;
|
||||
for (ii = 1; ii < 4; ii++)
|
||||
{
|
||||
int_tmp = (*p_argv.ui)[ii];
|
||||
*next_arg.u = int_tmp;
|
||||
next_arg.u++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*gpr_base.u++ = int_tmp;
|
||||
for (ii = 1; ii < 4; ii++)
|
||||
{
|
||||
int_tmp = (*p_argv.ui)[ii];
|
||||
*gpr_base.u++ = int_tmp;
|
||||
}
|
||||
}
|
||||
intarg_count +=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
double_tmp = (*p_argv.d)[0];
|
||||
|
||||
if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
|
||||
{
|
||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS
|
||||
&& intarg_count % 2 != 0)
|
||||
{
|
||||
intarg_count++;
|
||||
next_arg.u++;
|
||||
}
|
||||
*next_arg.d = double_tmp;
|
||||
next_arg.u += 2;
|
||||
double_tmp = (*p_argv.d)[1];
|
||||
*next_arg.d = double_tmp;
|
||||
next_arg.u += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*fpr_base.d++ = double_tmp;
|
||||
double_tmp = (*p_argv.d)[1];
|
||||
*fpr_base.d++ = double_tmp;
|
||||
}
|
||||
|
||||
fparg_count += 2;
|
||||
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
soft_double_prep:
|
||||
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
|
||||
intarg_count++;
|
||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
|
||||
|
@ -232,7 +314,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
do_struct:
|
||||
#endif
|
||||
struct_copy_size = ((*ptr)->size + 15) & ~0xF;
|
||||
copy_space.c -= struct_copy_size;
|
||||
|
@ -261,6 +343,8 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
|
|||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
soft_float_prep:
|
||||
|
||||
gprvalue = **p_argv.ui;
|
||||
|
||||
putgpr:
|
||||
|
@ -322,10 +406,8 @@ enum { ASM_NEEDS_REGISTERS64 = 4 };
|
|||
|
||||
*/
|
||||
|
||||
/*@-exportheader@*/
|
||||
void FFI_HIDDEN
|
||||
ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
const unsigned long bytes = ecif->cif->bytes;
|
||||
const unsigned long flags = ecif->cif->flags;
|
||||
|
@ -433,6 +515,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
|
|||
if (fparg_count < NUM_FPR_ARG_REGISTERS64)
|
||||
*fpr_base.d++ = double_tmp;
|
||||
fparg_count++;
|
||||
FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
|
||||
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
|
||||
break;
|
||||
#endif
|
||||
|
@ -515,6 +598,9 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
unsigned type = cif->rtype->type;
|
||||
unsigned size = cif->rtype->size;
|
||||
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
NUM_FPR_ARG_REGISTERS = 0;
|
||||
|
||||
if (cif->abi != FFI_LINUX64)
|
||||
{
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
|
@ -536,11 +622,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
|
||||
/* Space for the mandatory parm save area and general registers. */
|
||||
bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
if (type == FFI_TYPE_LONGDOUBLE)
|
||||
type = FFI_TYPE_DOUBLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return value handling. The rules for SYSV are as follows:
|
||||
|
@ -549,19 +630,33 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
- 64-bit integer values and structures between 5 and 8 bytes are returned
|
||||
in gpr3 and gpr4;
|
||||
- Single/double FP values are returned in fpr1;
|
||||
- Larger structures and long double (if not equivalent to double) values
|
||||
are allocated space and a pointer is passed as the first argument.
|
||||
- Larger structures are allocated space and a pointer is passed as
|
||||
the first argument.
|
||||
- long doubles (if not equivalent to double) are returned in
|
||||
fpr1,fpr2 for Linux and as for large structs for SysV.
|
||||
For LINUX64:
|
||||
- integer values in gpr3;
|
||||
- Structures/Unions by reference;
|
||||
- Single/double FP values in fpr1, long double in fpr1,fpr2. */
|
||||
- Single/double FP values in fpr1, long double in fpr1,fpr2.
|
||||
- soft-float float/doubles are treated as UINT32/UINT64 respectivley.
|
||||
- soft-float long doubles are returned in gpr3-gpr6. */
|
||||
switch (type)
|
||||
{
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
|
||||
&& cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||
goto byref;
|
||||
flags |= FLAG_RETURNS_128BITS;
|
||||
/* Fall through. */
|
||||
#endif
|
||||
case FFI_TYPE_DOUBLE:
|
||||
flags |= FLAG_RETURNS_64BITS;
|
||||
/* Fall through. */
|
||||
case FFI_TYPE_FLOAT:
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
/* With FFI_LINUX_SOFT_FLOAT no fp registers are used. */
|
||||
if (cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
|
@ -598,15 +693,8 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
}
|
||||
}
|
||||
}
|
||||
/* else fall through. */
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (type == FFI_TYPE_LONGDOUBLE && cif->abi == FFI_LINUX64)
|
||||
{
|
||||
flags |= FLAG_RETURNS_128BITS;
|
||||
flags |= FLAG_RETURNS_FP;
|
||||
break;
|
||||
}
|
||||
byref:
|
||||
#endif
|
||||
intarg_count++;
|
||||
flags |= FLAG_RETVAL_REFERENCE;
|
||||
|
@ -631,11 +719,36 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
switch ((*ptr)->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
goto soft_float_cif;
|
||||
fparg_count++;
|
||||
/* floating singles are not 8-aligned on stack */
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||
goto do_struct;
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
{
|
||||
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
|
||||
|| intarg_count < NUM_GPR_ARG_REGISTERS)
|
||||
/* A long double in FFI_LINUX_SOFT_FLOAT can use only
|
||||
a set of four consecutive gprs. If we have not enough,
|
||||
we have to adjust the intarg_count value. */
|
||||
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
|
||||
intarg_count += 4;
|
||||
break;
|
||||
}
|
||||
else
|
||||
fparg_count++;
|
||||
/* Fall thru */
|
||||
#endif
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
goto soft_double_cif;
|
||||
fparg_count++;
|
||||
/* If this FP arg is going on the stack, it must be
|
||||
8-byte-aligned. */
|
||||
|
@ -647,6 +760,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
soft_double_cif:
|
||||
/* 'long long' arguments are passed as two words, but
|
||||
either both words must fit in registers or both go
|
||||
on the stack. If they go on the stack, they must
|
||||
|
@ -664,7 +778,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
do_struct:
|
||||
#endif
|
||||
/* We must allocate space for a copy of these to enforce
|
||||
pass-by-value. Pad the space up to a multiple of 16
|
||||
|
@ -674,6 +788,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
/* Fall through (allocate space for the pointer). */
|
||||
|
||||
default:
|
||||
soft_float_cif:
|
||||
/* Everything else is passed as a 4-byte word in a GPR, either
|
||||
the object itself or a pointer to it. */
|
||||
intarg_count++;
|
||||
|
@ -687,8 +802,13 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
{
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
fparg_count += 2;
|
||||
intarg_count += 2;
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
intarg_count += 4;
|
||||
else
|
||||
{
|
||||
fparg_count += 2;
|
||||
intarg_count += 2;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case FFI_TYPE_FLOAT:
|
||||
|
@ -751,24 +871,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void));
|
||||
extern void FFI_HIDDEN ffi_call_LINUX64(/*@out@*/ extended_cif *,
|
||||
unsigned long, unsigned long,
|
||||
/*@out@*/ unsigned long *,
|
||||
extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
|
||||
unsigned long, unsigned long *,
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
|
||||
void
|
||||
ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
|
@ -780,9 +890,7 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
|
||||
if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
@ -793,15 +901,13 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
#ifndef POWERPC64
|
||||
case FFI_SYSV:
|
||||
case FFI_GCC_SYSV:
|
||||
/*@-usedef@*/
|
||||
case FFI_LINUX:
|
||||
case FFI_LINUX_SOFT_FLOAT:
|
||||
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
#else
|
||||
case FFI_LINUX64:
|
||||
/*@-usedef@*/
|
||||
ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -815,27 +921,24 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
#define MIN_CACHE_LINE_SIZE 8
|
||||
|
||||
static void
|
||||
flush_icache (char *addr1, int size)
|
||||
flush_icache (char *wraddr, char *xaddr, int size)
|
||||
{
|
||||
int i;
|
||||
char * addr;
|
||||
for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
|
||||
{
|
||||
addr = addr1 + i;
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;"
|
||||
: : "r" (addr) : "memory");
|
||||
}
|
||||
addr = addr1 + size - 1;
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;"
|
||||
: : "r"(addr) : "memory");
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
|
||||
: : "r" (xaddr + i), "r" (wraddr + i) : "memory");
|
||||
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
|
||||
: : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
|
||||
: "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
#ifdef POWERPC64
|
||||
void **tramp = (void **) &closure->tramp[0];
|
||||
|
@ -843,7 +946,7 @@ ffi_prep_closure (ffi_closure *closure,
|
|||
FFI_ASSERT (cif->abi == FFI_LINUX64);
|
||||
/* Copy function address and TOC from ffi_closure_LINUX64. */
|
||||
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
|
||||
tramp[2] = (void *) closure;
|
||||
tramp[2] = codeloc;
|
||||
#else
|
||||
unsigned int *tramp;
|
||||
|
||||
|
@ -859,10 +962,10 @@ ffi_prep_closure (ffi_closure *closure,
|
|||
tramp[8] = 0x7c0903a6; /* mtctr r0 */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
*(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[3] = (void *) closure; /* context */
|
||||
*(void **) &tramp[3] = codeloc; /* context */
|
||||
|
||||
/* Flush the icache. */
|
||||
flush_icache (&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
||||
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
#endif
|
||||
|
||||
closure->cif = cif;
|
||||
|
@ -920,14 +1023,17 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
For FFI_SYSV the result is passed in r3/r4 if the struct size is less
|
||||
or equal 8 bytes. */
|
||||
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
if ((cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& !((cif->abi == FFI_SYSV) && (size <= 8)))
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
|| (cif->rtype->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (!((cif->abi == FFI_SYSV) && (size <= 8)))
|
||||
{
|
||||
rvalue = (void *) *pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
rvalue = (void *) *pgr;
|
||||
ng++;
|
||||
pgr++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
@ -974,6 +1080,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_POINTER:
|
||||
soft_float_closure:
|
||||
/* there are 8 gpr registers used to pass values */
|
||||
if (ng < 8)
|
||||
{
|
||||
|
@ -989,6 +1096,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
do_struct:
|
||||
#endif
|
||||
/* Structs are passed by reference. The address will appear in a
|
||||
gpr if it is one of the first 8 arguments. */
|
||||
if (ng < 8)
|
||||
|
@ -1006,6 +1116,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_UINT64:
|
||||
soft_double_closure:
|
||||
/* passing long long ints are complex, they must
|
||||
* be passed in suitable register pairs such as
|
||||
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
|
||||
|
@ -1037,6 +1148,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
break;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
goto soft_float_closure;
|
||||
/* unfortunately float values are stored as doubles
|
||||
* in the ffi_closure_SYSV code (since we don't check
|
||||
* the type in that routine).
|
||||
|
@ -1060,12 +1174,14 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
* naughty thing to do but...
|
||||
*/
|
||||
avalue[i] = pst;
|
||||
nf++;
|
||||
pst += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
/* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
goto soft_double_closure;
|
||||
/* On the outgoing stack all values are aligned to 8 */
|
||||
/* there are 8 64bit floating point registers */
|
||||
|
||||
|
@ -1080,11 +1196,47 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
if (((long) pst) & 4)
|
||||
pst++;
|
||||
avalue[i] = pst;
|
||||
nf++;
|
||||
pst += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||
goto do_struct;
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
{ /* Test if for the whole long double, 4 gprs are available.
|
||||
otherwise the stuff ends up on the stack. */
|
||||
if (ng < 5)
|
||||
{
|
||||
avalue[i] = pgr;
|
||||
pgr += 4;
|
||||
ng += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = pst;
|
||||
pst += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (nf < 7)
|
||||
{
|
||||
avalue[i] = pfr;
|
||||
pfr += 2;
|
||||
nf += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((long) pst) & 4)
|
||||
pst++;
|
||||
avalue[i] = pst;
|
||||
pst += 4;
|
||||
nf = 8;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
|
@ -1101,8 +1253,36 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& size <= 8)
|
||||
return FFI_SYSV_TYPE_SMALL_STRUCT + size;
|
||||
return cif->rtype->type;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
|
||||
return FFI_TYPE_STRUCT;
|
||||
#endif
|
||||
/* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
|
||||
respectivley UINT64. */
|
||||
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
|
||||
{
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_FLOAT:
|
||||
return FFI_TYPE_UINT32;
|
||||
break;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
return FFI_TYPE_UINT64;
|
||||
break;
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
return FFI_TYPE_UINT128;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return cif->rtype->type;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return cif->rtype->type;
|
||||
}
|
||||
}
|
||||
|
||||
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#if !(defined(__APPLE__) && !defined(__ppc__))
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1998 Geoffrey Keating
|
||||
ffi_darwin.c
|
||||
|
||||
PowerPC Foreign Function Interface
|
||||
|
||||
Darwin ABI support (c) 2001 John Hornkvist
|
||||
AIX ABI support (c) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998 Geoffrey Keating
|
||||
Copyright (C) 2001 John Hornkvist
|
||||
Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
FFI support for Darwin and AIX.
|
||||
|
||||
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
|
||||
|
@ -80,9 +80,7 @@ enum { ASM_NEEDS_REGISTERS = 4 };
|
|||
|
||||
*/
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
const unsigned bytes = ecif->cif->bytes;
|
||||
const unsigned flags = ecif->cif->flags;
|
||||
|
@ -228,6 +226,48 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
|||
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
||||
}
|
||||
|
||||
/* Adjust the size of S to be correct for Darwin.
|
||||
On Darwin, the first field of a structure has natural alignment. */
|
||||
|
||||
static void
|
||||
darwin_adjust_aggregate_sizes (ffi_type *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s->type != FFI_TYPE_STRUCT)
|
||||
return;
|
||||
|
||||
s->size = 0;
|
||||
for (i = 0; s->elements[i] != NULL; i++)
|
||||
{
|
||||
ffi_type *p;
|
||||
int align;
|
||||
|
||||
p = s->elements[i];
|
||||
darwin_adjust_aggregate_sizes (p);
|
||||
if (i == 0
|
||||
&& (p->type == FFI_TYPE_UINT64
|
||||
|| p->type == FFI_TYPE_SINT64
|
||||
|| p->type == FFI_TYPE_DOUBLE
|
||||
|| p->alignment == 8))
|
||||
align = 8;
|
||||
else if (p->alignment == 16 || p->alignment < 4)
|
||||
align = p->alignment;
|
||||
else
|
||||
align = 4;
|
||||
s->size = ALIGN(s->size, align) + p->size;
|
||||
}
|
||||
|
||||
s->size = ALIGN(s->size, s->alignment);
|
||||
|
||||
if (s->elements[0]->type == FFI_TYPE_UINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_SINT64
|
||||
|| s->elements[0]->type == FFI_TYPE_DOUBLE
|
||||
|| s->elements[0]->alignment == 8)
|
||||
s->alignment = s->alignment > 8 ? s->alignment : 8;
|
||||
/* Do not add additional tail padding. */
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
|
@ -240,8 +280,16 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
unsigned size_al = 0;
|
||||
|
||||
/* All the machine-independent calculation of cif->bytes will be wrong.
|
||||
All the calculation of structure sizes will also be wrong.
|
||||
Redo the calculation for DARWIN. */
|
||||
|
||||
if (cif->abi == FFI_DARWIN)
|
||||
{
|
||||
darwin_adjust_aggregate_sizes (cif->rtype);
|
||||
for (i = 0; i < cif->nargs; i++)
|
||||
darwin_adjust_aggregate_sizes (cif->arg_types[i]);
|
||||
}
|
||||
|
||||
/* Space for the frame pointer, callee's LR, CR, etc, and for
|
||||
the asm's temp regs. */
|
||||
|
||||
|
@ -376,25 +424,12 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_AIX(/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void),
|
||||
void (*fn2)(extended_cif *, unsigned *const));
|
||||
extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void),
|
||||
void (*fn2)(extended_cif *, unsigned *const));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void), void (*fn2)(void));
|
||||
extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
|
||||
void (*fn)(void), void (*fn2)(void));
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
|
@ -407,9 +442,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
@ -417,16 +450,12 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
switch (cif->abi)
|
||||
{
|
||||
case FFI_AIX:
|
||||
/*@-usedef@*/
|
||||
ffi_call_AIX(&ecif, -cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn, ffi_prep_args);
|
||||
/*@=usedef@*/
|
||||
ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
case FFI_DARWIN:
|
||||
/*@-usedef@*/
|
||||
ffi_call_DARWIN(&ecif, -cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn, ffi_prep_args);
|
||||
/*@=usedef@*/
|
||||
ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
|
||||
ffi_prep_args);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
|
@ -499,10 +528,11 @@ SP current --> +---------------------------------------+ 176 <- parent frame
|
|||
|
||||
*/
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
struct ffi_aix_trampoline_struct *tramp_aix;
|
||||
|
@ -524,14 +554,14 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
|
||||
tramp[3] = (unsigned long) closure; /* context */
|
||||
tramp[3] = (unsigned long) codeloc; /* context */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* Flush the icache. Only necessary on Darwin. */
|
||||
flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
||||
flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -544,7 +574,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
|
||||
tramp_aix->code_pointer = fd->code_pointer;
|
||||
tramp_aix->toc = fd->toc;
|
||||
tramp_aix->static_chain = closure;
|
||||
tramp_aix->static_chain = codeloc;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
@ -768,4 +798,3 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
|
|||
/* Tell ffi_closure_ASM to perform return type promotions. */
|
||||
return cif->rtype->type;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
Target configuration macros for PowerPC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -13,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
@ -43,10 +45,20 @@ typedef enum ffi_abi {
|
|||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
FFI_LINUX,
|
||||
FFI_LINUX_SOFT_FLOAT,
|
||||
# ifdef POWERPC64
|
||||
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||
# else
|
||||
# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
|
||||
FFI_DEFAULT_ABI = FFI_LINUX,
|
||||
# else
|
||||
# ifdef __NO_FPRS__
|
||||
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -69,7 +81,7 @@ typedef enum ffi_abi {
|
|||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
FFI_LAST_ABI
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
|
@ -78,8 +90,14 @@ typedef enum ffi_abi {
|
|||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
/* For additional types like the below, take care about the order in
|
||||
ppc_closures.S. They must follow after the FFI_TYPE_LAST. */
|
||||
|
||||
/* Needed for soft-float long-double-128 support. */
|
||||
#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
|
||||
|
||||
/* Needed for FFI_SYSV small structure returns. */
|
||||
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST)
|
||||
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
|
||||
|
||||
#if defined(POWERPC64) || defined(POWERPC_AIX)
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
PowerPC64 Assembly glue.
|
||||
|
||||
|
@ -14,13 +15,14 @@
|
|||
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 AUTHOR 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -47,8 +49,8 @@ ffi_call_LINUX64:
|
|||
std %r0, 16(%r1)
|
||||
|
||||
mr %r28, %r1 /* our AP. */
|
||||
stdux %r1, %r1, %r4
|
||||
.LCFI0:
|
||||
stdux %r1, %r1, %r4
|
||||
mr %r31, %r5 /* flags, */
|
||||
mr %r30, %r6 /* rvalue, */
|
||||
mr %r29, %r7 /* function address. */
|
||||
|
@ -100,6 +102,10 @@ ffi_call_LINUX64:
|
|||
/* Make the call. */
|
||||
bctrl
|
||||
|
||||
/* This must follow the call immediately, the unwinder
|
||||
uses this to find out if r2 has been saved or not. */
|
||||
ld %r2, 40(%r1)
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01, %r31
|
||||
bt- 30, .Ldone_return_value
|
||||
|
@ -109,7 +115,6 @@ ffi_call_LINUX64:
|
|||
|
||||
.Ldone_return_value:
|
||||
/* Restore the registers we used and return. */
|
||||
ld %r2, 40(%r1)
|
||||
mr %r1, %r28
|
||||
ld %r0, 16(%r28)
|
||||
ld %r28, -32(%r1)
|
||||
|
@ -120,12 +125,10 @@ ffi_call_LINUX64:
|
|||
blr
|
||||
|
||||
.Lfp_return_value:
|
||||
bt 27, .Lfd_return_value
|
||||
bf 28, .Lfloat_return_value
|
||||
stfd %f1, 0(%r30)
|
||||
b .Ldone_return_value
|
||||
.Lfd_return_value:
|
||||
stfd %f1, 0(%r30)
|
||||
mtcrf 0x02, %r31 /* cr6 */
|
||||
bf 27, .Ldone_return_value
|
||||
stfd %f2, 8(%r30)
|
||||
b .Ldone_return_value
|
||||
.Lfloat_return_value:
|
||||
|
@ -178,3 +181,7 @@ ffi_call_LINUX64:
|
|||
.align 3
|
||||
.LEFDE1:
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,29 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
PowerPC64 Assembly glue.
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
@ -204,3 +230,7 @@ ffi_closure_LINUX64:
|
|||
.align 3
|
||||
.LEFDE1:
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,29 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
@ -28,6 +54,7 @@ ENTRY(ffi_closure_SYSV)
|
|||
stw %r9, 40(%r1)
|
||||
stw %r10,44(%r1)
|
||||
|
||||
#ifndef __NO_FPRS__
|
||||
# next save fpr 1 to fpr 8 (aligned to 8)
|
||||
stfd %f1, 48(%r1)
|
||||
stfd %f2, 56(%r1)
|
||||
|
@ -37,6 +64,7 @@ ENTRY(ffi_closure_SYSV)
|
|||
stfd %f6, 88(%r1)
|
||||
stfd %f7, 96(%r1)
|
||||
stfd %f8, 104(%r1)
|
||||
#endif
|
||||
|
||||
# set up registers for the routine that actually does the work
|
||||
# get the context pointer from the trampoline
|
||||
|
@ -58,218 +86,190 @@ ENTRY(ffi_closure_SYSV)
|
|||
|
||||
# make the call
|
||||
bl ffi_closure_helper_SYSV@local
|
||||
|
||||
.Lret:
|
||||
# now r3 contains the return type
|
||||
# so use it to look up in a table
|
||||
# so we know how to deal with each type
|
||||
|
||||
# look up the proper starting point in table
|
||||
# by using return type as offset
|
||||
addi %r6,%r1,112 # get pointer to results area
|
||||
bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR
|
||||
mflr %r4 # move to r4
|
||||
slwi %r3,%r3,4 # now multiply return type by 16
|
||||
add %r3,%r3,%r4 # add contents of table to table address
|
||||
|
||||
mflr %r4 # move address of .Lret to r4
|
||||
slwi %r3,%r3,4 # now multiply return type by 16
|
||||
addi %r4, %r4, .Lret_type0 - .Lret
|
||||
lwz %r0,148(%r1)
|
||||
add %r3,%r3,%r4 # add contents of table to table address
|
||||
mtctr %r3
|
||||
bctr # jump to it
|
||||
bctr # jump to it
|
||||
.LFE1:
|
||||
|
||||
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||
# first.
|
||||
.align 4
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
.Lget_ret_type0_addr:
|
||||
blrl
|
||||
|
||||
# case FFI_TYPE_VOID
|
||||
.Lret_type0:
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_INT
|
||||
.Lret_type1:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
.Lfinish:
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_FLOAT
|
||||
.Lret_type2:
|
||||
lfs %f1,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_DOUBLE
|
||||
.Lret_type3:
|
||||
lfd %f1,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
.Lret_type4:
|
||||
lfd %f1,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT8
|
||||
.Lret_type5:
|
||||
lbz %r3,3(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT8
|
||||
.Lret_type6:
|
||||
lbz %r3,3(%r6)
|
||||
extsb %r3,%r3
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT16
|
||||
.Lret_type7:
|
||||
lhz %r3,2(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT16
|
||||
.Lret_type8:
|
||||
lha %r3,2(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT32
|
||||
.Lret_type9:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT32
|
||||
.Lret_type10:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_UINT64
|
||||
.Lret_type11:
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_SINT64
|
||||
.Lret_type12:
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_STRUCT
|
||||
.Lret_type13:
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_POINTER
|
||||
.Lret_type14:
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# The return types below are only used when the ABI type is FFI_SYSV.
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
|
||||
.Lret_type15:
|
||||
# fall through.
|
||||
lbz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
.Lret_type16:
|
||||
# fall through.
|
||||
lhz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
.Lret_type17:
|
||||
# fall through.
|
||||
lwz %r3,0(%r6)
|
||||
srwi %r3,%r3,8
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
|
||||
.Lret_type18:
|
||||
# this one handles the structs from above too.
|
||||
lwz %r3,0(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
.Lret_type19:
|
||||
# fall through.
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
li %r5,24
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
|
||||
.Lret_type20:
|
||||
# fall through.
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
li %r5,16
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
|
||||
.Lret_type21:
|
||||
# fall through.
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
li %r5,8
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
|
||||
.Lret_type22:
|
||||
# this one handles the above unhandled structs.
|
||||
lwz %r3,0(%r6)
|
||||
lwz %r4,4(%r6)
|
||||
b .Lfinish
|
||||
nop
|
||||
|
||||
# case done
|
||||
.Lfinish:
|
||||
|
||||
lwz %r0,148(%r1)
|
||||
lfs %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
.Lstruct567:
|
||||
subfic %r0,%r5,32
|
||||
srw %r4,%r4,%r5
|
||||
slw %r0,%r3,%r0
|
||||
srw %r3,%r3,%r5
|
||||
or %r4,%r0,%r4
|
||||
# case FFI_TYPE_DOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_LONGDOUBLE
|
||||
lfd %f1,112+0(%r1)
|
||||
lfd %f2,112+8(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT8
|
||||
lbz %r3,112+3(%r1)
|
||||
extsb %r3,%r3
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_UINT16
|
||||
lhz %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT16
|
||||
lha %r3,112+2(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_SINT32
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_SINT64
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_TYPE_STRUCT
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
nop
|
||||
|
||||
# case FFI_TYPE_POINTER
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_TYPE_UINT128
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
lwz %r5,112+8(%r1)
|
||||
bl .Luint128
|
||||
|
||||
# The return types below are only used when the ABI type is FFI_SYSV.
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
|
||||
lbz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
|
||||
lhz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
srwi %r3,%r3,8
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,24
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,16
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
li %r5,8
|
||||
b .Lstruct567
|
||||
|
||||
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
|
||||
lwz %r3,112+0(%r1)
|
||||
lwz %r4,112+4(%r1)
|
||||
mtlr %r0
|
||||
b .Lfinish
|
||||
|
||||
.Lstruct567:
|
||||
subfic %r6,%r5,32
|
||||
srw %r4,%r4,%r5
|
||||
slw %r6,%r3,%r6
|
||||
srw %r3,%r3,%r5
|
||||
or %r4,%r6,%r4
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
.Luint128:
|
||||
lwz %r6,112+12(%r1)
|
||||
mtlr %r0
|
||||
addi %r1,%r1,144
|
||||
blr
|
||||
|
||||
END(ffi_closure_SYSV)
|
||||
|
||||
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
|
||||
|
@ -321,3 +321,7 @@ END(ffi_closure_SYSV)
|
|||
.LEFDE1:
|
||||
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.h - Copyright (c) 1998 Geoffrey Keating
|
||||
sysv.S - Copyright (c) 1998 Geoffrey Keating
|
||||
Copyright (C) 2007 Free Software Foundation, Inc
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
|
@ -14,13 +15,14 @@
|
|||
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 AUTHOR 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -98,13 +100,17 @@ ENTRY(ffi_call_SYSV)
|
|||
bctrl
|
||||
|
||||
/* Now, deal with the return value. */
|
||||
mtcrf 0x01,%r31
|
||||
mtcrf 0x01,%r31 /* cr7 */
|
||||
bt- 31,L(small_struct_return_value)
|
||||
bt- 30,L(done_return_value)
|
||||
bt- 29,L(fp_return_value)
|
||||
stw %r3,0(%r30)
|
||||
bf+ 28,L(done_return_value)
|
||||
stw %r4,4(%r30)
|
||||
mtcrf 0x02,%r31 /* cr6 */
|
||||
bf 27,L(done_return_value)
|
||||
stw %r5,8(%r30)
|
||||
stw %r6,12(%r30)
|
||||
/* Fall through... */
|
||||
|
||||
L(done_return_value):
|
||||
|
@ -121,6 +127,9 @@ L(done_return_value):
|
|||
L(fp_return_value):
|
||||
bf 28,L(float_return_value)
|
||||
stfd %f1,0(%r30)
|
||||
mtcrf 0x02,%r31 /* cr6 */
|
||||
bf 27,L(done_return_value)
|
||||
stfd %f2,8(%r30)
|
||||
b L(done_return_value)
|
||||
L(float_return_value):
|
||||
stfs %f1,0(%r30)
|
||||
|
@ -215,3 +224,7 @@ END(ffi_call_SYSV)
|
|||
.align 2
|
||||
.LEFDE1:
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
prep_cif.c - Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -12,20 +12,20 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/* Round up to FFI_SIZEOF_ARG. */
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
@ -33,14 +33,12 @@
|
|||
/* Perform machine independent initialization of aggregate type
|
||||
specifications. */
|
||||
|
||||
static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
||||
static ffi_status initialize_aggregate(ffi_type *arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(arg != NULL);
|
||||
|
||||
/*@-usedef@*/
|
||||
|
||||
FFI_ASSERT(arg->elements != NULL);
|
||||
FFI_ASSERT(arg->size == 0);
|
||||
FFI_ASSERT(arg->alignment == 0);
|
||||
|
@ -51,33 +49,15 @@ static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
|||
{
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#ifdef POWERPC_DARWIN
|
||||
{
|
||||
int curalign;
|
||||
|
||||
curalign = (*ptr)->alignment;
|
||||
if (ptr != &(arg->elements[0])) {
|
||||
if (curalign > 4 && curalign != 16) {
|
||||
curalign = 4;
|
||||
}
|
||||
}
|
||||
arg->size = ALIGN(arg->size, curalign);
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > curalign) ?
|
||||
arg->alignment : curalign;
|
||||
}
|
||||
#else
|
||||
arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
#endif
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
@ -95,8 +75,6 @@ static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
|||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
|
||||
/*@=usedef@*/
|
||||
}
|
||||
|
||||
#ifndef __CRIS__
|
||||
|
@ -107,23 +85,8 @@ static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
|||
/* Perform machine independent ffi_cif preparation, then call
|
||||
machine dependent routine. */
|
||||
|
||||
#ifdef X86_DARWIN
|
||||
static inline int struct_on_stack(int size)
|
||||
{
|
||||
if (size > 8) return 1;
|
||||
/* This is not what the ABI says, but is what is really implemented */
|
||||
switch (size) {
|
||||
case 1: case 2: case 4: case 8: return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
ffi_abi abi, unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
||||
/*@dependent@*/ ffi_type **atypes)
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
|
||||
ffi_type *rtype, ffi_type **atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
|
@ -140,10 +103,8 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
|||
cif->flags = 0;
|
||||
|
||||
/* Initialize the return type if necessary */
|
||||
/*@-usedef@*/
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
/*@=usedef@*/
|
||||
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
@ -156,10 +117,9 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
|||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
#ifdef X86_DARWIN
|
||||
|
||||
&& (struct_on_stack(cif->rtype->size))
|
||||
&& (cif->rtype->size > 8)
|
||||
#endif
|
||||
)
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
|
@ -170,20 +130,11 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
|||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if defined(X86_DARWIN)
|
||||
{
|
||||
int align = (*ptr)->alignment;
|
||||
if (align > 4) align = 4;
|
||||
if ((align - 1) & bytes)
|
||||
bytes = ALIGN(bytes, align);
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
|
||||
#elif !defined __x86_64__ && !defined S390 && !defined PA
|
||||
#if !defined __x86_64__ && !defined S390 && !defined PA
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|
@ -196,7 +147,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
|||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
#endif
|
||||
|
@ -208,3 +159,16 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
|||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
#endif /* not __CRIS__ */
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2000 Software AG
|
||||
ffi.c - Copyright (c) 2000, 2007 Software AG
|
||||
Copyright (c) 2008 Red Hat, Inc
|
||||
|
||||
S390 Foreign Function Interface
|
||||
|
||||
|
@ -207,6 +208,12 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif)
|
|||
void *arg = *p_argv;
|
||||
int type = (*ptr)->type;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
/* 16-byte long double is passed like a struct. */
|
||||
if (type == FFI_TYPE_LONGDOUBLE)
|
||||
type = FFI_TYPE_STRUCT;
|
||||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
|
@ -364,6 +371,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
cif->flags = FFI390_RET_DOUBLE;
|
||||
break;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
cif->flags = FFI390_RET_STRUCT;
|
||||
n_gpr++;
|
||||
break;
|
||||
#endif
|
||||
/* Integer values are returned in gpr 2 (and gpr 3
|
||||
for 64-bit values on 31-bit machines). */
|
||||
case FFI_TYPE_UINT64:
|
||||
|
@ -400,6 +413,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
{
|
||||
int type = (*ptr)->type;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
/* 16-byte long double is passed like a struct. */
|
||||
if (type == FFI_TYPE_LONGDOUBLE)
|
||||
type = FFI_TYPE_STRUCT;
|
||||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
|
@ -562,6 +581,12 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
int deref_struct_pointer = 0;
|
||||
int type = (*ptr)->type;
|
||||
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
/* 16-byte long double is passed like a struct. */
|
||||
if (type == FFI_TYPE_LONGDOUBLE)
|
||||
type = FFI_TYPE_STRUCT;
|
||||
#endif
|
||||
|
||||
/* Check how a structure type is passed. */
|
||||
if (type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
|
@ -662,6 +687,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
/* Void is easy, and so is struct. */
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* Floating point values are returned in fpr 0. */
|
||||
|
@ -709,17 +737,18 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
|
|||
|
||||
/*====================================================================*/
|
||||
/* */
|
||||
/* Name - ffi_prep_closure. */
|
||||
/* Name - ffi_prep_closure_loc. */
|
||||
/* */
|
||||
/* Function - Prepare a FFI closure. */
|
||||
/* */
|
||||
/*====================================================================*/
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
|
@ -728,7 +757,7 @@ ffi_prep_closure (ffi_closure *closure,
|
|||
*(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
|
||||
*(short *)&closure->tramp [4] = 0x1006;
|
||||
*(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
|
||||
*(long *)&closure->tramp [8] = (long)closure;
|
||||
*(long *)&closure->tramp [8] = (long)codeloc;
|
||||
*(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
|
||||
#else
|
||||
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
|
||||
|
@ -736,7 +765,7 @@ ffi_prep_closure (ffi_closure *closure,
|
|||
*(short *)&closure->tramp [4] = 0x100e;
|
||||
*(short *)&closure->tramp [6] = 0x0004;
|
||||
*(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
|
||||
*(long *)&closure->tramp[16] = (long)closure;
|
||||
*(long *)&closure->tramp[16] = (long)codeloc;
|
||||
*(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2000 Software AG
|
||||
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
S390 Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -14,13 +15,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -427,3 +429,6 @@ ffi_closure_SYSV:
|
|||
|
||||
#endif
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2002, 2003, 2004, 2005 Kaz Kojima
|
||||
ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Kaz Kojima
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
SuperH Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +15,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -106,9 +108,7 @@ return_type (ffi_type *arg)
|
|||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register int tmp;
|
||||
|
@ -406,20 +406,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
UINT64 trvalue;
|
||||
|
@ -436,9 +426,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
else if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
@ -446,10 +434,8 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
|
@ -468,10 +454,11 @@ extern void __ic_invalidate (void *line);
|
|||
#endif
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp;
|
||||
unsigned short insn;
|
||||
|
@ -491,7 +478,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
tramp[0] = 0xd102d301;
|
||||
tramp[1] = 0x412b0000 | insn;
|
||||
#endif
|
||||
*(void **) &tramp[2] = (void *)closure; /* ctx */
|
||||
*(void **) &tramp[2] = (void *)codeloc; /* ctx */
|
||||
*(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
|
||||
|
||||
closure->cif = cif;
|
||||
|
@ -500,7 +487,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
|
||||
#if defined(__SH4__)
|
||||
/* Flush the icache. */
|
||||
__ic_invalidate(&closure->tramp[0]);
|
||||
__ic_invalidate(codeloc);
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
|
@ -535,7 +522,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
int freg = 0;
|
||||
#endif
|
||||
ffi_cif *cif;
|
||||
double temp;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
|
@ -544,7 +530,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
returns the data directly to the caller. */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
|
||||
{
|
||||
rvalue = *pgr++;
|
||||
rvalue = (void *) *pgr++;
|
||||
ireg = 1;
|
||||
}
|
||||
else
|
||||
|
@ -611,6 +597,8 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
|||
{
|
||||
if (freg + 1 >= NFREGARG)
|
||||
continue;
|
||||
if (freg & 1)
|
||||
pfr++;
|
||||
freg = (freg + 1) & ~1;
|
||||
freg += 2;
|
||||
avalue[i] = pfr;
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 2002, 2003, 2004 Kaz Kojima
|
||||
sysv.S - Copyright (c) 2002, 2003, 2004, 2006 Kaz Kojima
|
||||
|
||||
SuperH Foreign Function Interface
|
||||
|
||||
|
@ -17,7 +17,8 @@
|
|||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
|
@ -829,13 +830,13 @@ __FRAME_BEGIN__:
|
|||
.byte 0x6 /* uleb128 0x6 */
|
||||
.byte 0x8e /* DW_CFA_offset, column 0xe */
|
||||
.byte 0x5 /* uleb128 0x5 */
|
||||
.byte 0x8b /* DW_CFA_offset, column 0xb */
|
||||
.byte 0x84 /* DW_CFA_offset, column 0x4 */
|
||||
.byte 0x4 /* uleb128 0x4 */
|
||||
.byte 0x8a /* DW_CFA_offset, column 0xa */
|
||||
.byte 0x85 /* DW_CFA_offset, column 0x5 */
|
||||
.byte 0x3 /* uleb128 0x3 */
|
||||
.byte 0x89 /* DW_CFA_offset, column 0x9 */
|
||||
.byte 0x86 /* DW_CFA_offset, column 0x6 */
|
||||
.byte 0x2 /* uleb128 0x2 */
|
||||
.byte 0x88 /* DW_CFA_offset, column 0x8 */
|
||||
.byte 0x87 /* DW_CFA_offset, column 0x7 */
|
||||
.byte 0x1 /* uleb128 0x1 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.4byte .LCFIE-.LCFID
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2003, 2004 Kaz Kojima
|
||||
Copyright (c) 2008 Anthony Green
|
||||
|
||||
SuperH SHmedia Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +15,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -238,12 +240,12 @@ extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
|||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned, long long,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
{
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996, 2003, 2004 Red Hat, Inc.
|
||||
ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
SPARC Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -425,10 +426,11 @@ extern void ffi_closure_v8(void);
|
|||
#endif
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned long fn;
|
||||
|
@ -443,7 +445,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
tramp[3] = 0x01000000; /* nop */
|
||||
*((unsigned long *) &tramp[4]) = fn;
|
||||
#else
|
||||
unsigned long ctx = (unsigned long) closure;
|
||||
unsigned long ctx = (unsigned long) codeloc;
|
||||
FFI_ASSERT (cif->abi == FFI_V8);
|
||||
fn = (unsigned long) ffi_closure_v8;
|
||||
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
v8.S - Copyright (c) 1996, 1997, 2003, 2004 Red Hat, Inc.
|
||||
v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
|
||||
|
||||
SPARC Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -265,3 +266,7 @@ done2:
|
|||
.byte 0x1f ! uleb128 0x1f
|
||||
.align WS
|
||||
.LLEFDE2:
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
v9.S - Copyright (c) 2000, 2003, 2004 Red Hat, Inc.
|
||||
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
|
||||
|
||||
SPARC 64-bit Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
@ -300,3 +301,7 @@ longdouble1:
|
|||
.align 8
|
||||
.LLEFDE2:
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifdef __i386__
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc.
|
||||
|
||||
X86 Foreign Function Interface
|
||||
darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005 Red Hat, Inc.
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
X86 Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -18,16 +18,12 @@
|
|||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* This file is based on sysv.S and then hacked up by Ronald who hasn't done
|
||||
* assembly programming in 8 years.
|
||||
*/
|
||||
|
||||
#ifndef __x86_64__
|
||||
|
||||
|
@ -35,18 +31,11 @@
|
|||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef PyObjC_STRICT_DEBUGGING
|
||||
/* XXX: Debugging of stack alignment, to be removed */
|
||||
#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
|
||||
#else
|
||||
#define ASSERT_STACK_ALIGNED
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.globl _ffi_prep_args
|
||||
|
||||
.align 4
|
||||
.align 4
|
||||
.globl _ffi_call_SYSV
|
||||
|
||||
_ffi_call_SYSV:
|
||||
|
@ -54,15 +43,12 @@ _ffi_call_SYSV:
|
|||
pushl %ebp
|
||||
.LCFI0:
|
||||
movl %esp,%ebp
|
||||
subl $8,%esp
|
||||
ASSERT_STACK_ALIGNED
|
||||
.LCFI1:
|
||||
subl $8,%esp
|
||||
/* Make room for all of the new args. */
|
||||
movl 16(%ebp),%ecx
|
||||
subl %ecx,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
movl %esp,%eax
|
||||
|
||||
/* Place all of the ffi_prep_args in position */
|
||||
|
@ -71,27 +57,20 @@ _ffi_call_SYSV:
|
|||
pushl %eax
|
||||
call *8(%ebp)
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
/* Return stack to previous state and call the function */
|
||||
addl $16,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
addl $16,%esp
|
||||
|
||||
call *28(%ebp)
|
||||
|
||||
/* XXX: return returns return with 'ret $4', that upsets the stack! */
|
||||
movl 16(%ebp),%ecx
|
||||
addl %ecx,%esp
|
||||
|
||||
|
||||
/* 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 retint
|
||||
jne 0f
|
||||
|
||||
/* Even if there is no space for the return value, we are
|
||||
obliged to handle floating-point values. */
|
||||
|
@ -99,145 +78,366 @@ _ffi_call_SYSV:
|
|||
jne noretval
|
||||
fstp %st(0)
|
||||
|
||||
jmp epilogue
|
||||
|
||||
retint:
|
||||
cmpl $FFI_TYPE_INT,%ecx
|
||||
jne retfloat
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp epilogue
|
||||
0:
|
||||
.align 4
|
||||
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:
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne retdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl 24(%ebp),%ecx
|
||||
fstps (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retdouble:
|
||||
cmpl $FFI_TYPE_DOUBLE,%ecx
|
||||
jne retlongdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl 24(%ebp),%ecx
|
||||
fstpl (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retlongdouble:
|
||||
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
|
||||
jne retint64
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl 24(%ebp),%ecx
|
||||
fstpt (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retint64:
|
||||
cmpl $FFI_TYPE_SINT64,%ecx
|
||||
jne retstruct1b
|
||||
|
||||
retint64:
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
movl %edx,4(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retstruct1b:
|
||||
cmpl $FFI_TYPE_SINT8,%ecx
|
||||
jne retstruct2b
|
||||
movl 24(%ebp),%ecx
|
||||
movb %al,0(%ecx)
|
||||
jmp epilogue
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movb %al,0(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retstruct2b:
|
||||
cmpl $FFI_TYPE_SINT16,%ecx
|
||||
jne retstruct
|
||||
movl 24(%ebp),%ecx
|
||||
movw %ax,0(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
/* 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:
|
||||
cmpl $FFI_TYPE_STRUCT,%ecx
|
||||
jne noretval
|
||||
/* Nothing to do! */
|
||||
|
||||
subl $4,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
addl $8,%esp
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
ASSERT_STACK_ALIGNED
|
||||
addl $8, %esp
|
||||
popl %esi
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
#if 0
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
|
||||
.align 4
|
||||
FFI_HIDDEN (ffi_closure_SYSV)
|
||||
.globl _ffi_closure_SYSV
|
||||
|
||||
_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 */
|
||||
movl %ebx, 8(%esp)
|
||||
.LCFI7:
|
||||
call L_ffi_closure_SYSV_inner$stub
|
||||
movl 8(%esp), %ebx
|
||||
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:
|
||||
lea -8(%ebp),%esp
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret $4
|
||||
.LFE2:
|
||||
|
||||
#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
|
||||
|
||||
_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:
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
.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:
|
||||
.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
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0
|
||||
LSCIE1:
|
||||
.long 0x0
|
||||
.byte 0x1
|
||||
.ascii "zR\0"
|
||||
.byte 0x1
|
||||
.byte 0x7c
|
||||
.byte 0x8
|
||||
.byte 0x1
|
||||
.byte 0x10
|
||||
.byte 0xc
|
||||
.byte 0x5
|
||||
.byte 0x4
|
||||
.byte 0x88
|
||||
.byte 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
.globl _ffi_call_SYSV.eh
|
||||
_ffi_call_SYSV.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1
|
||||
.long .LFB1-.
|
||||
.set L$set$2,.LFE1-.LFB1
|
||||
.long L$set$2
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$3,.LCFI0-.LFB1
|
||||
.long L$set$3
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x84
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$4,.LCFI1-.LCFI0
|
||||
.long L$set$4
|
||||
.byte 0xd
|
||||
.byte 0x4
|
||||
.align 2
|
||||
LEFDE1:
|
||||
.globl _ffi_closure_SYSV.eh
|
||||
_ffi_closure_SYSV.eh:
|
||||
LSFDE2:
|
||||
.set L$set$5,LEFDE2-LASFDE2
|
||||
.long L$set$5
|
||||
LASFDE2:
|
||||
.long LASFDE2-EH_frame1
|
||||
.long .LFB2-.
|
||||
.set L$set$6,.LFE2-.LFB2
|
||||
.long L$set$6
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$7,.LCFI2-.LFB2
|
||||
.long L$set$7
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x84
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$8,.LCFI3-.LCFI2
|
||||
.long L$set$8
|
||||
.byte 0xd
|
||||
.byte 0x4
|
||||
.align 2
|
||||
LEFDE2:
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
.globl _ffi_closure_raw_SYSV.eh
|
||||
_ffi_closure_raw_SYSV.eh:
|
||||
LSFDE3:
|
||||
.set L$set$10,LEFDE3-LASFDE3
|
||||
.long L$set$10
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1
|
||||
.long .LFB3-.
|
||||
.set L$set$11,.LFE3-.LFB3
|
||||
.long L$set$11
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$12,.LCFI4-.LFB3
|
||||
.long L$set$12
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x84
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$13,.LCFI5-.LCFI4
|
||||
.long L$set$13
|
||||
.byte 0xd
|
||||
.byte 0x4
|
||||
.byte 0x4
|
||||
.set L$set$14,.LCFI6-.LCFI5
|
||||
.long L$set$14
|
||||
.byte 0x85
|
||||
.byte 0x3
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ifndef __x86_64__ */
|
||||
|
||||
#endif /* defined __i386__ */
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
|
||||
ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2002 Ranjit Mathew
|
||||
Copyright (c) 2002 Bo Thorsen
|
||||
Copyright (c) 2002 Roger Sayle
|
||||
|
||||
x86 Foreign Function Interface
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
x86 Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
@ -17,13 +18,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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__
|
||||
|
@ -36,9 +38,7 @@
|
|||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
|
@ -121,9 +121,16 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
#if !defined(X86_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
|
||||
#ifdef X86
|
||||
case FFI_TYPE_STRUCT:
|
||||
#endif
|
||||
#if defined(X86) || defined(X86_DARWIN)
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
|
@ -135,15 +142,15 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
#if defined(X86_WIN32) || defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||
#ifndef X86
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size == 1)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT8; /* same as char size */
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
|
||||
}
|
||||
else if (cif->rtype->size == 2)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT16; /* same as short size */
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
|
||||
}
|
||||
else if (cif->rtype->size == 4)
|
||||
{
|
||||
|
@ -165,35 +172,23 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef X86_DARWIN
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
#ifdef X86_WIN32
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
|
@ -206,9 +201,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
if ((rvalue == NULL) &&
|
||||
(cif->flags == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
@ -217,17 +210,13 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
|||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
#ifdef X86_WIN32
|
||||
case FFI_STDCALL:
|
||||
/*@-usedef@*/
|
||||
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#endif /* X86_WIN32 */
|
||||
default:
|
||||
|
@ -247,6 +236,10 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_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_STDCALL (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#endif
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
|
@ -256,7 +249,7 @@ ffi_closure_SYSV_inner (closure, respp, args)
|
|||
void **respp;
|
||||
void *args;
|
||||
{
|
||||
/* our various things... */
|
||||
/* our various things... */
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
|
@ -276,11 +269,9 @@ ffi_closure_SYSV_inner (closure, respp, args)
|
|||
return cif->flags;
|
||||
}
|
||||
|
||||
/*@-exportheader@*/
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||
void **avalue, ffi_cif *cif)
|
||||
/*@=exportheader@*/
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
|
||||
ffi_cif *cif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
|
@ -324,27 +315,54 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
|||
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
|
||||
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_STDCALL(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 + 10); \
|
||||
unsigned short __size = (unsigned short)(SIZE); \
|
||||
*(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[10] = 0xc2; \
|
||||
*(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
|
||||
})
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
||||
&ffi_closure_SYSV, \
|
||||
(void*)closure);
|
||||
if (cif->abi == FFI_SYSV)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
|
||||
&ffi_closure_SYSV,
|
||||
(void*)closure);
|
||||
}
|
||||
#ifdef X86_WIN32
|
||||
else if (cif->abi == FFI_STDCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
|
||||
&ffi_closure_STDCALL,
|
||||
(void*)closure, cif->bytes);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
|
@ -358,14 +376,17 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
#if !FFI_NO_RAW_API
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data)
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
if (cif->abi != FFI_SYSV) {
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
// we currently don't support certain kinds of arguments for raw
|
||||
// closures. This should be implemented by a separate assembly language
|
||||
|
@ -380,7 +401,7 @@ ffi_prep_raw_closure (ffi_raw_closure* closure,
|
|||
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
|
||||
(void*)closure);
|
||||
codeloc);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
|
@ -400,27 +421,18 @@ ffi_prep_args_raw(char *stack, extended_cif *ecif)
|
|||
* libffi-1.20, this is not the case.)
|
||||
*/
|
||||
|
||||
extern void
|
||||
ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void));
|
||||
extern void
|
||||
ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)(void));
|
||||
|
||||
#ifdef X86_WIN32
|
||||
extern void
|
||||
ffi_call_STDCALL(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void));
|
||||
ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)(void));
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
void
|
||||
ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *fake_avalue)
|
||||
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
void **avalue = (void **)fake_avalue;
|
||||
|
@ -434,9 +446,7 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
|
|||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
@ -445,17 +455,13 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
|
|||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#ifdef X86_WIN32
|
||||
case FFI_STDCALL:
|
||||
/*@-usedef@*/
|
||||
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#endif /* X86_WIN32 */
|
||||
default:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
|
||||
ffi.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
|
||||
Copyright (c) 2008 Red Hat, Inc.
|
||||
|
||||
x86-64 Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +15,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
|
@ -433,10 +435,11 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||
extern void ffi_closure_unix64(void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data)
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
volatile unsigned short *tramp;
|
||||
|
||||
|
@ -445,7 +448,7 @@ ffi_prep_closure (ffi_closure* closure,
|
|||
tramp[0] = 0xbb49; /* mov <code>, %r11 */
|
||||
*(void * volatile *) &tramp[1] = ffi_closure_unix64;
|
||||
tramp[5] = 0xba49; /* mov <data>, %r10 */
|
||||
*(void * volatile *) &tramp[6] = closure;
|
||||
*(void * volatile *) &tramp[6] = 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. */
|
||||
|
|
|
@ -1,596 +0,0 @@
|
|||
# ifdef __i386__
|
||||
/* -----------------------------------------------------------------------
|
||||
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
|
||||
|
||||
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 CYGNUS SOLUTIONS 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__
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif);
|
||||
|
||||
static inline int retval_on_stack(ffi_type* tp)
|
||||
{
|
||||
if (tp->type == FFI_TYPE_STRUCT) {
|
||||
int sz = tp->size;
|
||||
if (sz > 8) {
|
||||
return 1;
|
||||
}
|
||||
switch (sz) {
|
||||
case 1: case 2: case 4: case 8: return 0;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (retval_on_stack(ecif->cif->rtype)) {
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN(argp, sizeof(int));
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
#if !defined(X86_WIN32) && !defined(X86_DARWIN)
|
||||
case FFI_TYPE_STRUCT:
|
||||
#endif
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size == 1)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT8; /* same as char size */
|
||||
}
|
||||
else if (cif->rtype->size == 2)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT16; /* same as short size */
|
||||
}
|
||||
else if (cif->rtype->size == 4)
|
||||
{
|
||||
cif->flags = FFI_TYPE_INT; /* same as int type */
|
||||
}
|
||||
else if (cif->rtype->size == 8)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
|
||||
}
|
||||
else
|
||||
{
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
|
||||
#if 1
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
#endif
|
||||
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)(void));
|
||||
/*@=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)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
if ((rvalue == NULL) && retval_on_stack(cif->rtype))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
/* To avoid changing the assembly code make sure the size of the argument
|
||||
* block is a multiple of 16. Then add 8 to compensate for local variables
|
||||
* in ffi_call_SYSV.
|
||||
*/
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** private members **/
|
||||
|
||||
static void ffi_closure_SYSV (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#if !FFI_NO_RAW_API
|
||||
static void ffi_closure_raw_SYSV (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#endif
|
||||
|
||||
/*@-exportheader@*/
|
||||
static inline void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||
void **avalue, ffi_cif *cif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (retval_on_stack(cif->rtype)) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, sizeof(int));
|
||||
}
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
static void
|
||||
ffi_closure_SYSV (closure)
|
||||
ffi_closure *closure;
|
||||
{
|
||||
// this is our return value storage
|
||||
long double res;
|
||||
|
||||
// our various things...
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
void *resp = (void*)&res;
|
||||
void *args = __builtin_dwarf_cfa ();
|
||||
|
||||
|
||||
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 re-set RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (cif->flags == FFI_TYPE_INT)
|
||||
{
|
||||
asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
|
||||
}
|
||||
else if (cif->flags == FFI_TYPE_FLOAT)
|
||||
{
|
||||
asm ("flds (%0)" : : "r" (resp) : "st" );
|
||||
}
|
||||
else if (cif->flags == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (cif->flags == FFI_TYPE_LONGDOUBLE)
|
||||
{
|
||||
asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (cif->flags == FFI_TYPE_SINT64)
|
||||
{
|
||||
asm ("movl 0(%0),%%eax;"
|
||||
"movl 4(%0),%%edx"
|
||||
: : "r"(resp)
|
||||
: "eax", "edx");
|
||||
}
|
||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
||||
else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct */
|
||||
{
|
||||
asm ("movsbl (%0),%%eax" : : "r" (resp) : "eax");
|
||||
}
|
||||
else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
|
||||
{
|
||||
asm ("movswl (%0),%%eax" : : "r" (resp) : "eax");
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
asm ("lea -8(%ebp),%esp;"
|
||||
"pop %esi;"
|
||||
"pop %edi;"
|
||||
"pop %ebp;"
|
||||
"ret $4");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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 - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
|
||||
*(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 */ \
|
||||
})
|
||||
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
||||
&ffi_closure_SYSV, \
|
||||
(void*)closure);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* ------- Native raw API support -------------------------------- */
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
static void
|
||||
ffi_closure_raw_SYSV (closure)
|
||||
ffi_raw_closure *closure;
|
||||
{
|
||||
// this is our return value storage
|
||||
long double res;
|
||||
|
||||
// our various things...
|
||||
ffi_raw *raw_args;
|
||||
ffi_cif *cif;
|
||||
unsigned short rtype;
|
||||
void *resp = (void*)&res;
|
||||
|
||||
/* get the cif */
|
||||
cif = closure->cif;
|
||||
|
||||
/* the SYSV/X86 abi matches the RAW API exactly, well.. almost */
|
||||
raw_args = (ffi_raw*) __builtin_dwarf_cfa ();
|
||||
|
||||
(closure->fun) (cif, resp, raw_args, closure->user_data);
|
||||
|
||||
rtype = cif->flags;
|
||||
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (rtype == FFI_TYPE_INT)
|
||||
{
|
||||
asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
|
||||
}
|
||||
else if (rtype == FFI_TYPE_FLOAT)
|
||||
{
|
||||
asm ("flds (%0)" : : "r" (resp) : "st" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_LONGDOUBLE)
|
||||
{
|
||||
asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_SINT64)
|
||||
{
|
||||
asm ("movl 0(%0),%%eax; movl 4(%0),%%edx"
|
||||
: : "r"(resp)
|
||||
: "eax", "edx");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
// we currently don't support certain kinds of arguments for raw
|
||||
// closures. This should be implemented by a separate assembly language
|
||||
// routine, since it would require argument processing, something we
|
||||
// don't do now for performance.
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--)
|
||||
{
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
|
||||
(void*)closure);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_args_raw(char *stack, extended_cif *ecif)
|
||||
{
|
||||
memcpy (stack, ecif->avalue, ecif->cif->bytes);
|
||||
}
|
||||
|
||||
/* we borrow this routine from libffi (it must be changed, though, to
|
||||
* actually call the function passed in the first argument. as of
|
||||
* libffi-1.20, this is not the case.)
|
||||
*/
|
||||
|
||||
extern void
|
||||
ffi_call_SYSV(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@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)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *fake_avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
void **avalue = (void **)fake_avalue;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
if ((rvalue == NULL) && retval_on_stack(cif->rtype))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
#endif /* __i386__ */
|
|
@ -1,5 +1,7 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Target configuration macros for x86 and x86-64.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -13,13 +15,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
@ -51,7 +54,7 @@ typedef enum ffi_abi {
|
|||
#endif
|
||||
|
||||
/* ---- Intel x86 and AMD x86-64 - */
|
||||
#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
|
||||
#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
|
||||
FFI_SYSV,
|
||||
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
|
||||
#ifdef __i386__
|
||||
|
@ -68,12 +71,18 @@ typedef enum ffi_abi {
|
|||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
|
||||
#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
|
||||
|
||||
#ifdef X86_64
|
||||
#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#else
|
||||
#ifdef X86_WIN32
|
||||
#define FFI_TRAMPOLINE_SIZE 13
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 10
|
||||
#endif
|
||||
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
sysv.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005 Red Hat, Inc.
|
||||
sysv.S - Copyright (c) 1996, 1998, 2001-2003, 2005, 2008 Red Hat, Inc.
|
||||
|
||||
X86 Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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__
|
||||
|
@ -59,16 +60,15 @@ ffi_call_SYSV:
|
|||
|
||||
call *28(%ebp)
|
||||
|
||||
/* Remove the space we pushed for the args */
|
||||
movl 16(%ebp),%ecx
|
||||
addl %ecx,%esp
|
||||
|
||||
/* 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 retint
|
||||
jne 0f
|
||||
|
||||
/* Even if there is no space for the return value, we are
|
||||
obliged to handle floating-point values. */
|
||||
|
@ -78,51 +78,84 @@ ffi_call_SYSV:
|
|||
|
||||
jmp epilogue
|
||||
|
||||
retint:
|
||||
cmpl $FFI_TYPE_INT,%ecx
|
||||
jne retfloat
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
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 */
|
||||
|
||||
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:
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne retdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstps (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retdouble:
|
||||
cmpl $FFI_TYPE_DOUBLE,%ecx
|
||||
jne retlongdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstpl (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retlongdouble:
|
||||
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
|
||||
jne retint64
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstpt (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retint64:
|
||||
cmpl $FFI_TYPE_SINT64,%ecx
|
||||
jne retstruct
|
||||
/* 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
|
||||
|
||||
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
|
||||
|
@ -162,7 +195,15 @@ ffi_closure_SYSV:
|
|||
movl -12(%ebp), %ecx
|
||||
cmpl $FFI_TYPE_INT, %eax
|
||||
je .Lcls_retint
|
||||
cmpl $FFI_TYPE_FLOAT, %eax
|
||||
|
||||
/* 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
|
||||
|
@ -170,6 +211,8 @@ ffi_closure_SYSV:
|
|||
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
|
||||
|
@ -190,6 +233,10 @@ ffi_closure_SYSV:
|
|||
movl (%ecx), %eax
|
||||
movl 4(%ecx), %edx
|
||||
jmp .Lcls_epilogue
|
||||
.Lcls_retstruct:
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret $4
|
||||
.LFE2:
|
||||
.size ffi_closure_SYSV, .-ffi_closure_SYSV
|
||||
|
||||
|
@ -226,6 +273,14 @@ ffi_closure_raw_SYSV:
|
|||
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
|
||||
|
@ -377,6 +432,6 @@ ffi_closure_raw_SYSV:
|
|||
|
||||
#endif /* ifndef __x86_64__ */
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
unix64.S - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
|
||||
Copyright (c) 2008 Red Hat, Inc
|
||||
|
||||
x86-64 Foreign Function Interface
|
||||
|
||||
|
@ -14,13 +15,14 @@
|
|||
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 CYGNUS SOLUTIONS 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.
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
@ -31,7 +33,7 @@
|
|||
.text
|
||||
|
||||
/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)());
|
||||
void *raddr, void (*fnaddr)(void));
|
||||
|
||||
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
|
||||
for this function. This has been allocated by ffi_call. We also
|
||||
|
@ -410,3 +412,7 @@ ffi_closure_unix64:
|
|||
.LEFDE3:
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
#if defined __ELF__ && defined __linux__
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
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.
|
||||
|
@ -258,6 +259,22 @@ sc_epilogue:
|
|||
|
||||
.ffi_call_STDCALL_end:
|
||||
|
||||
.globl _ffi_closure_STDCALL
|
||||
_ffi_closure_STDCALL:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
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 */
|
||||
call _ffi_closure_SYSV_inner
|
||||
movl -12(%ebp), %ecx
|
||||
jmp .Lcls_return_result
|
||||
.ffi_closure_STDCALL_end:
|
||||
|
||||
.globl _ffi_closure_SYSV
|
||||
_ffi_closure_SYSV:
|
||||
pushl %ebp
|
||||
|
@ -271,6 +288,7 @@ _ffi_closure_SYSV:
|
|||
movl %edx, (%esp) /* &resp */
|
||||
call _ffi_closure_SYSV_inner
|
||||
movl -12(%ebp), %ecx
|
||||
.Lcls_return_result:
|
||||
cmpl $FFI_TYPE_INT, %eax
|
||||
je .Lcls_retint
|
||||
cmpl $FFI_TYPE_FLOAT, %eax
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
|
@ -0,0 +1,500 @@
|
|||
This directory contains the libffi package, which is not part of GCC but
|
||||
shipped with GCC as convenience.
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
libffi-2.00 has not been released yet! This is a development snapshot!
|
||||
|
||||
libffi-1.20 was released on October 5, 1998. Check the libffi web
|
||||
page for updates: <URL:http://sources.redhat.com/libffi/>.
|
||||
|
||||
|
||||
What is libffi?
|
||||
===============
|
||||
|
||||
Compilers for high level languages generate code that follow certain
|
||||
conventions. These conventions are necessary, in part, for separate
|
||||
compilation to work. One such convention is the "calling
|
||||
convention". The "calling convention" is essentially a set of
|
||||
assumptions made by the compiler about where function arguments will
|
||||
be found on entry to a function. A "calling convention" also specifies
|
||||
where the return value for a function is found.
|
||||
|
||||
Some programs may not know at the time of compilation what arguments
|
||||
are to be passed to a function. For instance, an interpreter may be
|
||||
told at run-time about the number and types of arguments used to call
|
||||
a given function. Libffi can be used in such programs to provide a
|
||||
bridge from the interpreter program to compiled code.
|
||||
|
||||
The libffi library provides a portable, high level programming
|
||||
interface to various calling conventions. This allows a programmer to
|
||||
call any function specified by a call interface description at run
|
||||
time.
|
||||
|
||||
Ffi stands for Foreign Function Interface. A foreign function
|
||||
interface is the popular name for the interface that allows code
|
||||
written in one language to call code written in another language. The
|
||||
libffi library really only provides the lowest, machine dependent
|
||||
layer of a fully featured foreign function interface. A layer must
|
||||
exist above libffi that handles type conversions for values passed
|
||||
between the two languages.
|
||||
|
||||
|
||||
Supported Platforms and Prerequisites
|
||||
=====================================
|
||||
|
||||
Libffi has been ported to:
|
||||
|
||||
SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
|
||||
|
||||
Irix 5.3 & 6.2 (System V/o32 & n32)
|
||||
|
||||
Intel x86 - Linux (System V ABI)
|
||||
|
||||
Alpha - Linux and OSF/1
|
||||
|
||||
m68k - Linux (System V ABI)
|
||||
|
||||
PowerPC - Linux (System V ABI, Darwin, AIX)
|
||||
|
||||
ARM - Linux (System V ABI)
|
||||
|
||||
Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
|
||||
that other versions will work. Libffi has also been built and tested
|
||||
with the SGI compiler tools.
|
||||
|
||||
On PowerPC, the tests failed (see the note below).
|
||||
|
||||
You must use GNU make to build libffi. SGI's make will not work.
|
||||
Sun's probably won't either.
|
||||
|
||||
If you port libffi to another platform, please let me know! I assume
|
||||
that some will be easy (x86 NetBSD), and others will be more difficult
|
||||
(HP).
|
||||
|
||||
|
||||
Installing libffi
|
||||
=================
|
||||
|
||||
[Note: before actually performing any of these installation steps,
|
||||
you may wish to read the "Platform Specific Notes" below.]
|
||||
|
||||
First you must configure the distribution for your particular
|
||||
system. Go to the directory you wish to build libffi in and run the
|
||||
"configure" program found in the root directory of the libffi source
|
||||
distribution.
|
||||
|
||||
You may want to tell configure where to install the libffi library and
|
||||
header files. To do that, use the --prefix configure switch. Libffi
|
||||
will install under /usr/local by default.
|
||||
|
||||
If you want to enable extra run-time debugging checks use the the
|
||||
--enable-debug configure switch. This is useful when your program dies
|
||||
mysteriously while using libffi.
|
||||
|
||||
Another useful configure switch is --enable-purify-safety. Using this
|
||||
will add some extra code which will suppress certain warnings when you
|
||||
are using Purify with libffi. Only use this switch when using
|
||||
Purify, as it will slow down the library.
|
||||
|
||||
Configure has many other options. Use "configure --help" to see them all.
|
||||
|
||||
Once configure has finished, type "make". Note that you must be using
|
||||
GNU make. SGI's make will not work. Sun's probably won't either.
|
||||
You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
||||
|
||||
To ensure that libffi is working as advertised, type "make test".
|
||||
|
||||
To install the library and header files, type "make install".
|
||||
|
||||
|
||||
Using libffi
|
||||
============
|
||||
|
||||
The Basics
|
||||
----------
|
||||
|
||||
Libffi assumes that you have a pointer to the function you wish to
|
||||
call and that you know the number and types of arguments to pass it,
|
||||
as well as the return type of the function.
|
||||
|
||||
The first thing you must do is create an ffi_cif object that matches
|
||||
the signature of the function you wish to call. The cif in ffi_cif
|
||||
stands for Call InterFace. To prepare a call interface object, use the
|
||||
following function:
|
||||
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
ffi_type *rtype, ffi_type **atypes);
|
||||
|
||||
CIF is a pointer to the call interface object you wish
|
||||
to initialize.
|
||||
|
||||
ABI is an enum that specifies the calling convention
|
||||
to use for the call. FFI_DEFAULT_ABI defaults
|
||||
to the system's native calling convention. Other
|
||||
ABI's may be used with care. They are system
|
||||
specific.
|
||||
|
||||
NARGS is the number of arguments this function accepts.
|
||||
libffi does not yet support vararg functions.
|
||||
|
||||
RTYPE is a pointer to an ffi_type structure that represents
|
||||
the return type of the function. Ffi_type objects
|
||||
describe the types of values. libffi provides
|
||||
ffi_type objects for many of the native C types:
|
||||
signed int, unsigned int, signed char, unsigned char,
|
||||
etc. There is also a pointer ffi_type object and
|
||||
a void ffi_type. Use &ffi_type_void for functions that
|
||||
don't return values.
|
||||
|
||||
ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
|
||||
If NARGS is 0, this is ignored.
|
||||
|
||||
|
||||
ffi_prep_cif will return a status code that you are responsible
|
||||
for checking. It will be one of the following:
|
||||
|
||||
FFI_OK - All is good.
|
||||
|
||||
FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
|
||||
came across is bad.
|
||||
|
||||
|
||||
Before making the call, the VALUES vector should be initialized
|
||||
with pointers to the appropriate argument values.
|
||||
|
||||
To call the the function using the initialized ffi_cif, use the
|
||||
ffi_call function:
|
||||
|
||||
void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
|
||||
|
||||
CIF is a pointer to the ffi_cif initialized specifically
|
||||
for this function.
|
||||
|
||||
FN is a pointer to the function you want to call.
|
||||
|
||||
RVALUE is a pointer to a chunk of memory that is to hold the
|
||||
result of the function call. Currently, it must be
|
||||
at least one word in size (except for the n32 version
|
||||
under Irix 6.x, which must be a pointer to an 8 byte
|
||||
aligned value (a long long). It must also be at least
|
||||
word aligned (depending on the return type, and the
|
||||
system's alignment requirements). If RTYPE is
|
||||
&ffi_type_void, this is ignored. If RVALUE is NULL,
|
||||
the return value is discarded.
|
||||
|
||||
AVALUES is a vector of void* that point to the memory locations
|
||||
holding the argument values for a call.
|
||||
If NARGS is 0, this is ignored.
|
||||
|
||||
|
||||
If you are expecting a return value from FN it will have been stored
|
||||
at RVALUE.
|
||||
|
||||
|
||||
|
||||
An Example
|
||||
----------
|
||||
|
||||
Here is a trivial example that calls puts() a few times.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[1];
|
||||
void *values[1];
|
||||
char *s;
|
||||
int rc;
|
||||
|
||||
/* Initialize the argument info vectors */
|
||||
args[0] = &ffi_type_uint;
|
||||
values[0] = &s;
|
||||
|
||||
/* Initialize the cif */
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_uint, args) == FFI_OK)
|
||||
{
|
||||
s = "Hello World!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
/* rc now holds the result of the call to puts */
|
||||
|
||||
/* values holds a pointer to the function's arg, so to
|
||||
call puts() again all we need to do is change the
|
||||
value of s */
|
||||
s = "This is cool!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Aggregate Types
|
||||
---------------
|
||||
|
||||
Although libffi has no special support for unions or bit-fields, it is
|
||||
perfectly happy passing structures back and forth. You must first
|
||||
describe the structure to libffi by creating a new ffi_type object
|
||||
for it. Here is the definition of ffi_type:
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
unsigned size;
|
||||
short alignment;
|
||||
short type;
|
||||
struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
|
||||
All structures must have type set to FFI_TYPE_STRUCT. You may set
|
||||
size and alignment to 0. These will be calculated and reset to the
|
||||
appropriate values by ffi_prep_cif().
|
||||
|
||||
elements is a NULL terminated array of pointers to ffi_type objects
|
||||
that describe the type of the structure elements. These may, in turn,
|
||||
be structure elements.
|
||||
|
||||
The following example initializes a ffi_type object representing the
|
||||
tm struct from Linux's time.h:
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
/* Those are for future use. */
|
||||
long int __tm_gmtoff__;
|
||||
__const char *__tm_zone__;
|
||||
};
|
||||
|
||||
{
|
||||
ffi_type tm_type;
|
||||
ffi_type *tm_type_elements[12];
|
||||
int i;
|
||||
|
||||
tm_type.size = tm_type.alignment = 0;
|
||||
tm_type.elements = &tm_type_elements;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
tm_type_elements[i] = &ffi_type_sint;
|
||||
|
||||
tm_type_elements[9] = &ffi_type_slong;
|
||||
tm_type_elements[10] = &ffi_type_pointer;
|
||||
tm_type_elements[11] = NULL;
|
||||
|
||||
/* tm_type can now be used to represent tm argument types and
|
||||
return types for ffi_prep_cif() */
|
||||
}
|
||||
|
||||
|
||||
|
||||
Platform Specific Notes
|
||||
=======================
|
||||
|
||||
Intel x86
|
||||
---------
|
||||
|
||||
There are no known problems with the x86 port.
|
||||
|
||||
Sun SPARC - SunOS 4.1.3 & Solaris 2.x
|
||||
-------------------------------------
|
||||
|
||||
You must use GNU Make to build libffi on Sun platforms.
|
||||
|
||||
MIPS - Irix 5.3 & 6.x
|
||||
---------------------
|
||||
|
||||
Irix 6.2 and better supports three different calling conventions: o32,
|
||||
n32 and n64. Currently, libffi only supports both o32 and n32 under
|
||||
Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
|
||||
configured for whichever calling convention it was built for.
|
||||
|
||||
By default, the configure script will try to build libffi with the GNU
|
||||
development tools. To build libffi with the SGI development tools, set
|
||||
the environment variable CC to either "cc -32" or "cc -n32" before
|
||||
running configure under Irix 6.x (depending on whether you want an o32
|
||||
or n32 library), or just "cc" for Irix 5.3.
|
||||
|
||||
With the n32 calling convention, when returning structures smaller
|
||||
than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
|
||||
Here's one way of forcing this:
|
||||
|
||||
double struct_storage[2];
|
||||
my_small_struct *s = (my_small_struct *) struct_storage;
|
||||
/* Use s for RVALUE */
|
||||
|
||||
If you don't do this you are liable to get spurious bus errors.
|
||||
|
||||
"long long" values are not supported yet.
|
||||
|
||||
You must use GNU Make to build libffi on SGI platforms.
|
||||
|
||||
ARM - System V ABI
|
||||
------------------
|
||||
|
||||
The ARM port was performed on a NetWinder running ARM Linux ELF
|
||||
(2.0.31) and gcc 2.8.1.
|
||||
|
||||
|
||||
|
||||
PowerPC System V ABI
|
||||
--------------------
|
||||
|
||||
There are two `System V ABI's which libffi implements for PowerPC.
|
||||
They differ only in how small structures are returned from functions.
|
||||
|
||||
In the FFI_SYSV version, structures that are 8 bytes or smaller are
|
||||
returned in registers. This is what GCC does when it is configured
|
||||
for solaris, and is what the System V ABI I have (dated September
|
||||
1995) says.
|
||||
|
||||
In the FFI_GCC_SYSV version, all structures are returned the same way:
|
||||
by passing a pointer as the first argument to the function. This is
|
||||
what GCC does when it is configured for linux or a generic sysv
|
||||
target.
|
||||
|
||||
EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
|
||||
inconsistency with the SysV ABI: When a procedure is called with many
|
||||
floating-point arguments, some of them get put on the stack. They are
|
||||
all supposed to be stored in double-precision format, even if they are
|
||||
only single-precision, but EGCS stores single-precision arguments as
|
||||
single-precision anyway. This causes one test to fail (the `many
|
||||
arguments' test).
|
||||
|
||||
|
||||
What's With The Crazy Comments?
|
||||
===============================
|
||||
|
||||
You might notice a number of cryptic comments in the code, delimited
|
||||
by /*@ and @*/. These are annotations read by the program LCLint, a
|
||||
tool for statically checking C programs. You can read all about it at
|
||||
<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>.
|
||||
|
||||
|
||||
History
|
||||
=======
|
||||
|
||||
1.20 Oct-5-98
|
||||
Raffaele Sena produces ARM port.
|
||||
|
||||
1.19 Oct-5-98
|
||||
Fixed x86 long double and long long return support.
|
||||
m68k bug fixes from Andreas Schwab.
|
||||
Patch for DU assembler compatibility for the Alpha from Richard
|
||||
Henderson.
|
||||
|
||||
1.18 Apr-17-98
|
||||
Bug fixes and MIPS configuration changes.
|
||||
|
||||
1.17 Feb-24-98
|
||||
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
|
||||
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
|
||||
|
||||
1.16 Feb-11-98
|
||||
Richard Henderson produces Alpha port.
|
||||
|
||||
1.15 Dec-4-97
|
||||
Fixed an n32 ABI bug. New libtool, auto* support.
|
||||
|
||||
1.14 May-13-97
|
||||
libtool is now used to generate shared and static libraries.
|
||||
Fixed a minor portability problem reported by Russ McManus
|
||||
<mcmanr@eq.gs.com>.
|
||||
|
||||
1.13 Dec-2-96
|
||||
Added --enable-purify-safety to keep Purify from complaining
|
||||
about certain low level code.
|
||||
Sparc fix for calling functions with < 6 args.
|
||||
Linux x86 a.out fix.
|
||||
|
||||
1.12 Nov-22-96
|
||||
Added missing ffi_type_void, needed for supporting void return
|
||||
types. Fixed test case for non MIPS machines. Cygnus Support
|
||||
is now Cygnus Solutions.
|
||||
|
||||
1.11 Oct-30-96
|
||||
Added notes about GNU make.
|
||||
|
||||
1.10 Oct-29-96
|
||||
Added configuration fix for non GNU compilers.
|
||||
|
||||
1.09 Oct-29-96
|
||||
Added --enable-debug configure switch. Clean-ups based on LCLint
|
||||
feedback. ffi_mips.h is always installed. Many configuration
|
||||
fixes. Fixed ffitest.c for sparc builds.
|
||||
|
||||
1.08 Oct-15-96
|
||||
Fixed n32 problem. Many clean-ups.
|
||||
|
||||
1.07 Oct-14-96
|
||||
Gordon Irlam rewrites v8.S again. Bug fixes.
|
||||
|
||||
1.06 Oct-14-96
|
||||
Gordon Irlam improved the sparc port.
|
||||
|
||||
1.05 Oct-14-96
|
||||
Interface changes based on feedback.
|
||||
|
||||
1.04 Oct-11-96
|
||||
Sparc port complete (modulo struct passing bug).
|
||||
|
||||
1.03 Oct-10-96
|
||||
Passing struct args, and returning struct values works for
|
||||
all architectures/calling conventions. Expanded tests.
|
||||
|
||||
1.02 Oct-9-96
|
||||
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
|
||||
Added "make test".
|
||||
|
||||
1.01 Oct-8-96
|
||||
Fixed float passing bug in mips version. Restructured some
|
||||
of the code. Builds cleanly with SGI tools.
|
||||
|
||||
1.00 Oct-7-96
|
||||
First release. No public announcement.
|
||||
|
||||
|
||||
Authors & Credits
|
||||
=================
|
||||
|
||||
libffi was written by Anthony Green <green@cygnus.com>.
|
||||
|
||||
Portions of libffi were derived from Gianni Mariani's free gencall
|
||||
library for Silicon Graphics machines.
|
||||
|
||||
The closure mechanism was designed and implemented by Kresten Krab
|
||||
Thorup.
|
||||
|
||||
The Sparc port was derived from code contributed by the fine folks at
|
||||
Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
|
||||
made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
|
||||
|
||||
The Alpha port was written by Richard Henderson at Cygnus Solutions.
|
||||
|
||||
Andreas Schwab ported libffi to m68k Linux and provided a number of
|
||||
bug fixes.
|
||||
|
||||
Geoffrey Keating ported libffi to the PowerPC.
|
||||
|
||||
Raffaele Sena ported libffi to the ARM.
|
||||
|
||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
||||
stepping through the code and tracking down bugs.
|
||||
|
||||
Thanks also to Tom Tromey for bug fixes and configuration help.
|
||||
|
||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
||||
interface.
|
||||
|
||||
If you have a problem, or have found a bug, please send a note to
|
||||
green@cygnus.com.
|
|
@ -0,0 +1,5 @@
|
|||
This directory contains a slightly modified version of libffi, extracted from
|
||||
the GCC source-tree.
|
||||
|
||||
The only modifications are those that are necessary to compile libffi using
|
||||
the Apple provided compiler and outside of the GCC source tree.
|
|
@ -0,0 +1,226 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Round up to FFI_SIZEOF_ARG. */
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
/* Perform machine independent initialization of aggregate type
|
||||
specifications. */
|
||||
|
||||
static ffi_status
|
||||
initialize_aggregate(
|
||||
/*@out@*/ ffi_type* arg)
|
||||
{
|
||||
/*@-usedef@*/
|
||||
|
||||
if (arg == NULL || arg->elements == NULL ||
|
||||
arg->size != 0 || arg->alignment != 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
ffi_type** ptr = &(arg->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#ifdef POWERPC_DARWIN
|
||||
int curalign = (*ptr)->alignment;
|
||||
|
||||
if (ptr != &(arg->elements[0]))
|
||||
{
|
||||
if (curalign > 4 && curalign != 16)
|
||||
curalign = 4;
|
||||
}
|
||||
|
||||
arg->size = ALIGN(arg->size, curalign);
|
||||
arg->size += (*ptr)->size;
|
||||
arg->alignment = (arg->alignment > curalign) ?
|
||||
arg->alignment : curalign;
|
||||
#else
|
||||
arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
||||
arg->size += (*ptr)->size;
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
#endif
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* Structure size includes tail padding. This is important for
|
||||
structures that fit in one register on ABIs like the PowerPC64
|
||||
Linux ABI that right justify small structs in a register.
|
||||
It's also needed for nested structure layout, for example
|
||||
struct A { long a; char b; }; struct B { struct A x; char y; };
|
||||
should find y at an offset of 2*sizeof(long) and result in a
|
||||
total size of 3*sizeof(long). */
|
||||
arg->size = ALIGN(arg->size, arg->alignment);
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
return FFI_OK;
|
||||
|
||||
/*@=usedef@*/
|
||||
}
|
||||
|
||||
#ifndef __CRIS__
|
||||
/* The CRIS ABI specifies structure elements to have byte
|
||||
alignment only, so it completely overrides this functions,
|
||||
which assumes "natural" alignment and padding. */
|
||||
|
||||
/* Perform machine independent ffi_cif preparation, then call
|
||||
machine dependent routine. */
|
||||
|
||||
#if defined(X86_DARWIN)
|
||||
|
||||
static inline bool
|
||||
struct_on_stack(
|
||||
int size)
|
||||
{
|
||||
if (size > 8)
|
||||
return true;
|
||||
|
||||
/* This is not what the ABI says, but is what is really implemented */
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(X86_DARWIN)
|
||||
|
||||
// Arguments' ffi_type->alignment must be nonzero.
|
||||
ffi_status
|
||||
ffi_prep_cif(
|
||||
/*@out@*/ /*@partial@*/ ffi_cif* cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
|
||||
/*@dependent@*/ ffi_type** atypes)
|
||||
{
|
||||
if (cif == NULL)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
unsigned int bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type** ptr;
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = nargs;
|
||||
cif->rtype = rtype;
|
||||
cif->flags = 0;
|
||||
|
||||
/* Initialize the return type if necessary */
|
||||
/*@-usedef@*/
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
/*@=usedef@*/
|
||||
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
||||
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
||||
#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
#ifdef X86_DARWIN
|
||||
&& (struct_on_stack(cif->rtype->size))
|
||||
#endif
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
/* Initialize any uninitialized aggregate type definitions */
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
if ((*ptr)->alignment == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if defined(X86_DARWIN)
|
||||
{
|
||||
int align = (*ptr)->alignment;
|
||||
|
||||
if (align > 4)
|
||||
align = 4;
|
||||
|
||||
if ((align - 1) & bytes)
|
||||
bytes = ALIGN(bytes, align);
|
||||
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
#elif !defined __x86_64__ && !defined S390 && !defined PA
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_V9))
|
||||
bytes += sizeof(void*);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
#endif /* not __CRIS__ */
|
|
@ -0,0 +1,352 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
The basic API is described in the README file.
|
||||
|
||||
The raw API is designed to bypass some of the argument packing
|
||||
and unpacking on architectures for which it can be avoided.
|
||||
|
||||
The closure API allows interpreted functions to be packaged up
|
||||
inside a C function pointer, so that they can be called as C functions,
|
||||
with no understanding on the client side that they are interpreted.
|
||||
It can also be used in other cases in which it is necessary to package
|
||||
up a user specified parameter and a function pointer as a single
|
||||
function pointer.
|
||||
|
||||
The closure API must be implemented in order to get its functionality,
|
||||
e.g. for use by gij. Routines are provided to emulate the raw API
|
||||
if the underlying platform doesn't allow faster implementation.
|
||||
|
||||
More details on the raw and closure API can be found in:
|
||||
|
||||
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
|
||||
|
||||
and
|
||||
|
||||
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
|
||||
-------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_H
|
||||
#define LIBFFI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Specify which architecture libffi is configured for. */
|
||||
#ifdef MACOSX
|
||||
# if defined(__i386__) || defined(__x86_64__)
|
||||
# define X86_DARWIN
|
||||
# elif defined(__ppc__) || defined(__ppc64__)
|
||||
# define POWERPC_DARWIN
|
||||
# else
|
||||
# error "Unsupported MacOS X CPU type"
|
||||
# endif
|
||||
#else
|
||||
#error "Unsupported OS type"
|
||||
#endif
|
||||
|
||||
/* ---- System configuration information --------------------------------- */
|
||||
|
||||
#include "ffitarget.h"
|
||||
#include "fficonfig.h"
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
|
||||
But we can find it either under the correct ANSI name, or under GNU
|
||||
C's internal name. */
|
||||
#ifdef LONG_LONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
|
||||
#else
|
||||
# ifdef LLONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LLONG_MAX
|
||||
# else
|
||||
# ifdef __GNUC__
|
||||
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if SCHAR_MAX == 127
|
||||
# define ffi_type_uchar ffi_type_uint8
|
||||
# define ffi_type_schar ffi_type_sint8
|
||||
#else
|
||||
#error "char size not supported"
|
||||
#endif
|
||||
|
||||
#if SHRT_MAX == 32767
|
||||
# define ffi_type_ushort ffi_type_uint16
|
||||
# define ffi_type_sshort ffi_type_sint16
|
||||
#elif SHRT_MAX == 2147483647
|
||||
# define ffi_type_ushort ffi_type_uint32
|
||||
# define ffi_type_sshort ffi_type_sint32
|
||||
#else
|
||||
#error "short size not supported"
|
||||
#endif
|
||||
|
||||
#if INT_MAX == 32767
|
||||
# define ffi_type_uint ffi_type_uint16
|
||||
# define ffi_type_sint ffi_type_sint16
|
||||
#elif INT_MAX == 2147483647
|
||||
# define ffi_type_uint ffi_type_uint32
|
||||
# define ffi_type_sint ffi_type_sint32
|
||||
#elif INT_MAX == 9223372036854775807
|
||||
# define ffi_type_uint ffi_type_uint64
|
||||
# define ffi_type_sint ffi_type_sint64
|
||||
#else
|
||||
#error "int size not supported"
|
||||
#endif
|
||||
|
||||
#define ffi_type_ulong ffi_type_uint64
|
||||
#define ffi_type_slong ffi_type_sint64
|
||||
|
||||
#if LONG_MAX == 2147483647
|
||||
# if FFI_LONG_LONG_MAX != 9223372036854775807
|
||||
# error "no 64-bit data type supported"
|
||||
# endif
|
||||
#elif LONG_MAX != 9223372036854775807
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* The closure code assumes that this works on pointers, i.e. a size_t
|
||||
can hold a pointer. */
|
||||
|
||||
typedef struct _ffi_type {
|
||||
size_t size;
|
||||
unsigned short alignment;
|
||||
unsigned short type;
|
||||
/*@null@*/ struct _ffi_type** elements;
|
||||
} ffi_type;
|
||||
|
||||
/* These are defined in types.c */
|
||||
extern ffi_type ffi_type_void;
|
||||
extern ffi_type ffi_type_uint8;
|
||||
extern ffi_type ffi_type_sint8;
|
||||
extern ffi_type ffi_type_uint16;
|
||||
extern ffi_type ffi_type_sint16;
|
||||
extern ffi_type ffi_type_uint32;
|
||||
extern ffi_type ffi_type_sint32;
|
||||
extern ffi_type ffi_type_uint64;
|
||||
extern ffi_type ffi_type_sint64;
|
||||
extern ffi_type ffi_type_float;
|
||||
extern ffi_type ffi_type_double;
|
||||
extern ffi_type ffi_type_longdouble;
|
||||
extern ffi_type ffi_type_pointer;
|
||||
|
||||
typedef enum ffi_status {
|
||||
FFI_OK = 0,
|
||||
FFI_BAD_TYPEDEF,
|
||||
FFI_BAD_ABI
|
||||
} ffi_status;
|
||||
|
||||
typedef unsigned FFI_TYPE;
|
||||
|
||||
typedef struct ffi_cif {
|
||||
ffi_abi abi;
|
||||
unsigned nargs;
|
||||
/*@dependent@*/ ffi_type** arg_types;
|
||||
/*@dependent@*/ ffi_type* rtype;
|
||||
unsigned bytes;
|
||||
unsigned flags;
|
||||
#ifdef FFI_EXTRA_CIF_FIELDS
|
||||
FFI_EXTRA_CIF_FIELDS;
|
||||
#endif
|
||||
} ffi_cif;
|
||||
|
||||
/* ---- Definitions for the raw API -------------------------------------- */
|
||||
|
||||
#ifndef FFI_SIZEOF_ARG
|
||||
# if LONG_MAX == 2147483647
|
||||
# define FFI_SIZEOF_ARG 4
|
||||
# elif LONG_MAX == 9223372036854775807
|
||||
# define FFI_SIZEOF_ARG 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
ffi_sarg sint;
|
||||
ffi_arg uint;
|
||||
float flt;
|
||||
char data[FFI_SIZEOF_ARG];
|
||||
void* ptr;
|
||||
} ffi_raw;
|
||||
|
||||
void
|
||||
ffi_raw_call(
|
||||
/*@dependent@*/ ffi_cif* cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void* rvalue,
|
||||
/*@dependent@*/ ffi_raw* avalue);
|
||||
|
||||
void
|
||||
ffi_ptrarray_to_raw(
|
||||
ffi_cif* cif,
|
||||
void** args,
|
||||
ffi_raw* raw);
|
||||
|
||||
void
|
||||
ffi_raw_to_ptrarray(
|
||||
ffi_cif* cif,
|
||||
ffi_raw* raw,
|
||||
void** args);
|
||||
|
||||
size_t
|
||||
ffi_raw_size(
|
||||
ffi_cif* cif);
|
||||
|
||||
/* This is analogous to the raw API, except it uses Java parameter
|
||||
packing, even on 64-bit machines. I.e. on 64-bit machines
|
||||
longs and doubles are followed by an empty 64-bit word. */
|
||||
void
|
||||
ffi_java_raw_call(
|
||||
/*@dependent@*/ ffi_cif* cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void* rvalue,
|
||||
/*@dependent@*/ ffi_raw* avalue);
|
||||
|
||||
void
|
||||
ffi_java_ptrarray_to_raw(
|
||||
ffi_cif* cif,
|
||||
void** args,
|
||||
ffi_raw* raw);
|
||||
|
||||
void
|
||||
ffi_java_raw_to_ptrarray(
|
||||
ffi_cif* cif,
|
||||
ffi_raw* raw,
|
||||
void** args);
|
||||
|
||||
size_t
|
||||
ffi_java_raw_size(
|
||||
ffi_cif* cif);
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
typedef struct ffi_closure {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
ffi_cif* cif;
|
||||
void (*fun)(ffi_cif*,void*,void**,void*);
|
||||
void* user_data;
|
||||
} ffi_closure;
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure(
|
||||
ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void* user_data);
|
||||
|
||||
typedef struct ffi_raw_closure {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
ffi_cif* cif;
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
/* if this is enabled, then a raw closure has the same layout
|
||||
as a regular closure. We use this to install an intermediate
|
||||
handler to do the transaltion, void** -> ffi_raw*. */
|
||||
void (*translate_args)(ffi_cif*,void*,void**,void*);
|
||||
void* this_closure;
|
||||
#endif
|
||||
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
|
||||
void* user_data;
|
||||
} ffi_raw_closure;
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure(
|
||||
ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void* user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure(
|
||||
ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void* user_data);
|
||||
|
||||
#endif // FFI_CLOSURES
|
||||
|
||||
/* ---- Public interface definition -------------------------------------- */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif(
|
||||
/*@out@*/ /*@partial@*/ ffi_cif* cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype,
|
||||
/*@dependent@*/ ffi_type** atypes);
|
||||
|
||||
void
|
||||
ffi_call(
|
||||
/*@dependent@*/ ffi_cif* cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void* rvalue,
|
||||
/*@dependent@*/ void** avalue);
|
||||
|
||||
/* Useful for eliminating compiler warnings */
|
||||
#define FFI_FN(f) ((void (*)(void))f)
|
||||
|
||||
#endif // #ifndef LIBFFI_ASM
|
||||
/* ---- Definitions shared with assembly code ---------------------------- */
|
||||
|
||||
/* If these change, update src/mips/ffitarget.h. */
|
||||
#define FFI_TYPE_VOID 0
|
||||
#define FFI_TYPE_INT 1
|
||||
#define FFI_TYPE_FLOAT 2
|
||||
#define FFI_TYPE_DOUBLE 3
|
||||
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
# define FFI_TYPE_LONGDOUBLE 4
|
||||
#else
|
||||
# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
|
||||
#endif
|
||||
|
||||
#define FFI_TYPE_UINT8 5
|
||||
#define FFI_TYPE_SINT8 6
|
||||
#define FFI_TYPE_UINT16 7
|
||||
#define FFI_TYPE_SINT16 8
|
||||
#define FFI_TYPE_UINT32 9
|
||||
#define FFI_TYPE_SINT32 10
|
||||
#define FFI_TYPE_UINT64 11
|
||||
#define FFI_TYPE_SINT64 12
|
||||
#define FFI_TYPE_STRUCT 13
|
||||
#define FFI_TYPE_POINTER 14
|
||||
|
||||
/* This should always refer to the last type code (for sanity checks) */
|
||||
#define FFI_TYPE_LAST FFI_TYPE_POINTER
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #ifndef LIBFFI_H
|
|
@ -0,0 +1,102 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
|
||||
|
||||
Common internal definitions and macros. Only necessary for building
|
||||
libffi.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef FFI_COMMON_H
|
||||
#define FFI_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "fficonfig.h"
|
||||
|
||||
/* Do not move this. Some versions of AIX are very picky about where
|
||||
this is positioned. */
|
||||
#ifdef __GNUC__
|
||||
# define alloca __builtin_alloca
|
||||
#else
|
||||
# if HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
# pragma alloca
|
||||
# else
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
char* alloca();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Check for the existence of memcpy. */
|
||||
#if STDC_HEADERS
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifndef HAVE_MEMCPY
|
||||
# define memcpy(d, s, n) bcopy((s), (d), (n))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*#if defined(FFI_DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif*/
|
||||
|
||||
#ifdef FFI_DEBUG
|
||||
#include <stdio.h>
|
||||
|
||||
/*@exits@*/ void
|
||||
ffi_assert(
|
||||
/*@temp@*/ char* expr,
|
||||
/*@temp@*/ char* file,
|
||||
int line);
|
||||
void
|
||||
ffi_stop_here(void);
|
||||
void
|
||||
ffi_type_test(
|
||||
/*@temp@*/ /*@out@*/ ffi_type* a,
|
||||
/*@temp@*/ char* file,
|
||||
int line);
|
||||
|
||||
# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
|
||||
# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
|
||||
# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__)
|
||||
#else
|
||||
# define FFI_ASSERT(x)
|
||||
# define FFI_ASSERT_AT(x, f, l)
|
||||
# define FFI_ASSERT_VALID_TYPE(x)
|
||||
#endif // #ifdef FFI_DEBUG
|
||||
|
||||
#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(
|
||||
ffi_cif* cif);
|
||||
|
||||
/* Extended cif, used in callback from assembly routine */
|
||||
typedef struct extended_cif {
|
||||
/*@dependent@*/ ffi_cif* cif;
|
||||
/*@dependent@*/ void* rvalue;
|
||||
/*@dependent@*/ void** avalue;
|
||||
} extended_cif;
|
||||
|
||||
/* Terse sized type definitions. */
|
||||
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
|
||||
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
|
||||
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
|
||||
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
|
||||
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
|
||||
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
|
||||
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
|
||||
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
|
||||
typedef float FLOAT32;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #ifndef FFI_COMMON_H
|
|
@ -0,0 +1,150 @@
|
|||
/* Manually created fficonfig.h for Darwin on PowerPC or Intel
|
||||
|
||||
This file is manually generated to do away with the need for autoconf and
|
||||
therefore make it easier to cross-compile and build fat binaries.
|
||||
|
||||
NOTE: This file was added by PyObjC.
|
||||
*/
|
||||
|
||||
#ifndef MACOSX
|
||||
#error "This file is only supported on Mac OS X"
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
# define BYTEORDER 1234
|
||||
# undef HOST_WORDS_BIG_ENDIAN
|
||||
# undef WORDS_BIGENDIAN
|
||||
# define SIZEOF_DOUBLE 8
|
||||
# define HAVE_LONG_DOUBLE 1
|
||||
# define SIZEOF_LONG_DOUBLE 16
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
# define BYTEORDER 1234
|
||||
# undef HOST_WORDS_BIG_ENDIAN
|
||||
# undef WORDS_BIGENDIAN
|
||||
# define SIZEOF_DOUBLE 8
|
||||
# define HAVE_LONG_DOUBLE 1
|
||||
# define SIZEOF_LONG_DOUBLE 16
|
||||
|
||||
#elif defined(__ppc__)
|
||||
# define BYTEORDER 4321
|
||||
# define HOST_WORDS_BIG_ENDIAN 1
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# define SIZEOF_DOUBLE 8
|
||||
# if __GNUC__ >= 4
|
||||
# define HAVE_LONG_DOUBLE 1
|
||||
# define SIZEOF_LONG_DOUBLE 16
|
||||
# else
|
||||
# undef HAVE_LONG_DOUBLE
|
||||
# define SIZEOF_LONG_DOUBLE 8
|
||||
# endif
|
||||
|
||||
#elif defined(__ppc64__)
|
||||
# define BYTEORDER 4321
|
||||
# define HOST_WORDS_BIG_ENDIAN 1
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# define SIZEOF_DOUBLE 8
|
||||
# define HAVE_LONG_DOUBLE 1
|
||||
# define SIZEOF_LONG_DOUBLE 16
|
||||
|
||||
#else
|
||||
#error "Unknown CPU type"
|
||||
#endif
|
||||
|
||||
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
||||
systems. This function is required for `alloca.c' support on those systems. */
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
/* #undef C_ALLOCA */
|
||||
|
||||
/* Define to the flags needed for the .section .eh_frame directive. */
|
||||
#define EH_FRAME_FLAGS "aw"
|
||||
|
||||
/* Define this if you want extra debugging. */
|
||||
/* #undef FFI_DEBUG */
|
||||
|
||||
/* Define this is you do not want support for the raw API. */
|
||||
#define FFI_NO_RAW_API 1
|
||||
|
||||
/* Define this if you do not want support for aggregate types. */
|
||||
/* #undef FFI_NO_STRUCTS */
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#define HAVE_ALLOCA 1
|
||||
|
||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */
|
||||
#define HAVE_ALLOCA_H 1
|
||||
|
||||
/* Define if your assembler supports .register. */
|
||||
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
|
||||
|
||||
/* Define if your assembler and linker support unaligned PC relative relocs. */
|
||||
/* #undef HAVE_AS_SPARC_UA_PCREL */
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#define HAVE_MEMCPY 1
|
||||
|
||||
/* Define if mmap with MAP_ANON(YMOUS) works. */
|
||||
#define HAVE_MMAP_ANON 1
|
||||
|
||||
/* Define if mmap of /dev/zero works. */
|
||||
/* #undef HAVE_MMAP_DEV_ZERO */
|
||||
|
||||
/* Define if read-only mmap of a plain file works. */
|
||||
#define HAVE_MMAP_FILE 1
|
||||
|
||||
/* Define if .eh_frame sections should be read-only. */
|
||||
/* #undef HAVE_RO_EH_FRAME */
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
/* #undef NO_MINUS_C_MINUS_O */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libffi"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "libffi"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "libffi 2.1"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "libffi"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "2.1"
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at run-time.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
/* #undef STACK_DIRECTION */
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define this if you are using Purify and want to suppress spurious messages. */
|
||||
/* #undef USING_PURIFY */
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.1-pyobjc"
|
||||
|
||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
# ifdef LIBFFI_ASM
|
||||
# define FFI_HIDDEN(name) .hidden name
|
||||
# else
|
||||
# define FFI_HIDDEN __attribute__((visibility ("hidden")))
|
||||
# endif
|
||||
#else
|
||||
# ifdef LIBFFI_ASM
|
||||
# define FFI_HIDDEN(name)
|
||||
# else
|
||||
# define FFI_HIDDEN
|
||||
# endif
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a
|
||||
normal build, the build environment copies the file to the right location or
|
||||
sets up the right include flags. We want to do neither because that would
|
||||
make building fat binaries harder.
|
||||
*/
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include "x86-ffitarget.h"
|
||||
#elif defined(__ppc__) || defined(__ppc64__)
|
||||
#include "ppc-ffitarget.h"
|
||||
#else
|
||||
#error "Unsupported CPU type"
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for PowerPC.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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 LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#if (defined(POWERPC) && defined(__powerpc64__)) || \
|
||||
(defined(POWERPC_DARWIN) && defined(__ppc64__))
|
||||
#define POWERPC64
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
#ifdef POWERPC
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
# ifdef POWERPC64
|
||||
FFI_DEFAULT_ABI = FFI_LINUX64,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_AIX
|
||||
FFI_AIX,
|
||||
FFI_DARWIN,
|
||||
FFI_DEFAULT_ABI = FFI_AIX,
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_DARWIN
|
||||
FFI_AIX,
|
||||
FFI_DARWIN,
|
||||
FFI_DEFAULT_ABI = FFI_DARWIN,
|
||||
#endif
|
||||
|
||||
#ifdef POWERPC_FREEBSD
|
||||
FFI_SYSV,
|
||||
FFI_GCC_SYSV,
|
||||
FFI_LINUX64,
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
|
||||
#endif // #ifndef LIBFFI_ASM
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
/* Needed for FFI_SYSV small structure returns. */
|
||||
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST)
|
||||
|
||||
#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/
|
||||
# define FFI_TRAMPOLINE_SIZE 48
|
||||
#elif defined(POWERPC_AIX)
|
||||
# define FFI_TRAMPOLINE_SIZE 24
|
||||
#else
|
||||
# define FFI_TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
|
||||
typedef struct ffi_aix_trampoline_struct {
|
||||
void* code_pointer; /* Pointer to ffi_closure_ASM */
|
||||
void* toc; /* TOC */
|
||||
void* static_chain; /* Pointer to closure */
|
||||
} ffi_aix_trampoline_struct;
|
||||
# endif
|
||||
#endif // #ifndef LIBFFI_ASM
|
||||
|
||||
#endif // #ifndef LIBFFI_TARGET_H
|
|
@ -0,0 +1,88 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
Target configuration macros for x86 and x86-64.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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 LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
#if defined(X86_64) && defined(__i386__)
|
||||
# undef X86_64
|
||||
# define X86
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# ifndef X86_64
|
||||
# define X86_64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
/* ---- Intel x86 Win32 ---------- */
|
||||
#ifdef X86_WIN32
|
||||
FFI_SYSV,
|
||||
FFI_STDCALL,
|
||||
/* TODO: Add fastcall support for the sake of completeness */
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
#endif
|
||||
|
||||
/* ---- Intel x86 and AMD x86-64 - */
|
||||
#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
|
||||
FFI_SYSV,
|
||||
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
|
||||
# ifdef __i386__
|
||||
FFI_DEFAULT_ABI = FFI_SYSV,
|
||||
# else
|
||||
FFI_DEFAULT_ABI = FFI_UNIX64,
|
||||
# endif
|
||||
#endif
|
||||
|
||||
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
|
||||
} ffi_abi;
|
||||
|
||||
#endif // #ifndef LIBFFI_ASM
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
|
||||
#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN))
|
||||
# define FFI_TRAMPOLINE_SIZE 24
|
||||
# define FFI_NATIVE_RAW_API 0
|
||||
#else
|
||||
# define FFI_TRAMPOLINE_SIZE 10
|
||||
# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
||||
#endif
|
||||
|
||||
#endif // #ifndef LIBFFI_TARGET_H
|
|
@ -0,0 +1,369 @@
|
|||
#if defined(__ppc__) || defined(__ppc64__)
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin.S - Copyright (c) 2000 John Hornkvist
|
||||
Copyright (c) 2004 Free Software Foundation, Inc.
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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 AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ppc-darwin.h>
|
||||
#include <architecture/ppc/mode_independent_asm.h>
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_prep_args
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_call_DARWIN
|
||||
|
||||
.text
|
||||
.align 2
|
||||
_ffi_call_DARWIN:
|
||||
LFB0:
|
||||
mr r12,r8 /* We only need r12 until the call,
|
||||
so it doesn't have to be saved. */
|
||||
|
||||
LFB1:
|
||||
/* Save the old stack pointer as AP. */
|
||||
mr r8,r1
|
||||
|
||||
LCFI0:
|
||||
#if defined(__ppc64__)
|
||||
/* Allocate the stack space we need.
|
||||
r4 (size of input data)
|
||||
48 bytes (linkage area)
|
||||
40 bytes (saved registers)
|
||||
8 bytes (extra FPR)
|
||||
r4 + 96 bytes total
|
||||
*/
|
||||
|
||||
addi r4,r4,-96 // Add our overhead.
|
||||
li r0,-32 // Align to 32 bytes.
|
||||
and r4,r4,r0
|
||||
#endif
|
||||
stgux r1,r1,r4 // Grow the stack.
|
||||
mflr r9
|
||||
|
||||
/* Save registers we use. */
|
||||
#if defined(__ppc64__)
|
||||
std r27,-40(r8)
|
||||
#endif
|
||||
stg r28,MODE_CHOICE(-16,-32)(r8)
|
||||
stg r29,MODE_CHOICE(-12,-24)(r8)
|
||||
stg r30,MODE_CHOICE(-8,-16)(r8)
|
||||
stg r31,MODE_CHOICE(-4,-8)(r8)
|
||||
stg r9,SF_RETURN(r8) /* return address */
|
||||
#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
|
||||
stg r2,MODE_CHOICE(20,40)(r1)
|
||||
#endif
|
||||
|
||||
LCFI1:
|
||||
#if defined(__ppc64__)
|
||||
mr r27,r3 // our extended_cif
|
||||
#endif
|
||||
/* Save arguments over call. */
|
||||
mr r31,r5 /* flags, */
|
||||
mr r30,r6 /* rvalue, */
|
||||
mr r29,r7 /* function address, */
|
||||
mr r28,r8 /* our AP. */
|
||||
|
||||
LCFI2:
|
||||
/* Call ffi_prep_args. */
|
||||
mr r4,r1
|
||||
li r9,0
|
||||
mtctr r12 /* r12 holds address of _ffi_prep_args. */
|
||||
bctrl
|
||||
#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */
|
||||
lg r2,MODE_CHOICE(20,40)(r1)
|
||||
#endif
|
||||
|
||||
/* Now do the call.
|
||||
Set up cr1 with bits 4-7 of the flags. */
|
||||
mtcrf 0x40,r31
|
||||
|
||||
/* Load all those argument registers.
|
||||
We have set up a nice stack frame, just load it into registers. */
|
||||
lg r3,SF_ARG1(r1)
|
||||
lg r4,SF_ARG2(r1)
|
||||
lg r5,SF_ARG3(r1)
|
||||
lg r6,SF_ARG4(r1)
|
||||
nop
|
||||
lg r7,SF_ARG5(r1)
|
||||
lg r8,SF_ARG6(r1)
|
||||
lg r9,SF_ARG7(r1)
|
||||
lg r10,SF_ARG8(r1)
|
||||
|
||||
/* Load all the FP registers. */
|
||||
bf 6,L2 /* No floats to load. */
|
||||
#if defined(__ppc64__)
|
||||
lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28)
|
||||
lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28)
|
||||
lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28)
|
||||
lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28)
|
||||
nop
|
||||
lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28)
|
||||
lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28)
|
||||
lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28)
|
||||
lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28)
|
||||
nop
|
||||
lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28)
|
||||
lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28)
|
||||
lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28)
|
||||
lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28)
|
||||
nop
|
||||
lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28)
|
||||
lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28)
|
||||
#elif defined(__ppc__)
|
||||
lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28)
|
||||
lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28)
|
||||
lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28)
|
||||
lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28)
|
||||
nop
|
||||
lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28)
|
||||
lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28)
|
||||
lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28)
|
||||
lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28)
|
||||
nop
|
||||
lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28)
|
||||
lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28)
|
||||
lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28)
|
||||
lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28)
|
||||
nop
|
||||
lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28)
|
||||
#else
|
||||
#error undefined architecture
|
||||
#endif
|
||||
|
||||
L2:
|
||||
mr r12,r29 // Put the target address in r12 as specified.
|
||||
mtctr r12 // Get the address to call into CTR.
|
||||
nop
|
||||
nop
|
||||
bctrl // Make the call.
|
||||
|
||||
// Deal with the return value.
|
||||
#if defined(__ppc64__)
|
||||
mtcrf 0x3,r31 // flags in cr6 and cr7
|
||||
bt 27,L(st_return_value)
|
||||
#elif defined(__ppc__)
|
||||
mtcrf 0x1,r31 // flags in cr7
|
||||
#else
|
||||
#error undefined architecture
|
||||
#endif
|
||||
|
||||
bt 30,L(done_return_value)
|
||||
bt 29,L(fp_return_value)
|
||||
stg r3,0(r30)
|
||||
#if defined(__ppc__)
|
||||
bf 28,L(done_return_value) // Store the second long if necessary.
|
||||
stg r4,4(r30)
|
||||
#endif
|
||||
// Fall through
|
||||
|
||||
L(done_return_value):
|
||||
lg r1,0(r1) // Restore stack pointer.
|
||||
// Restore the registers we used.
|
||||
lg r9,SF_RETURN(r1) // return address
|
||||
lg r31,MODE_CHOICE(-4,-8)(r1)
|
||||
mtlr r9
|
||||
lg r30,MODE_CHOICE(-8,-16)(r1)
|
||||
lg r29,MODE_CHOICE(-12,-24)(r1)
|
||||
lg r28,MODE_CHOICE(-16,-32)(r1)
|
||||
#if defined(__ppc64__)
|
||||
ld r27,-40(r1)
|
||||
#endif
|
||||
blr
|
||||
|
||||
#if defined(__ppc64__)
|
||||
L(st_return_value):
|
||||
// Grow the stack enough to fit the registers. Leave room for 8 args
|
||||
// to trample the 1st 8 slots in param area.
|
||||
stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64
|
||||
|
||||
// Store GPRs
|
||||
std r3,SF_ARG9(r1)
|
||||
std r4,SF_ARG10(r1)
|
||||
std r5,SF_ARG11(r1)
|
||||
std r6,SF_ARG12(r1)
|
||||
nop
|
||||
std r7,SF_ARG13(r1)
|
||||
std r8,SF_ARG14(r1)
|
||||
std r9,SF_ARG15(r1)
|
||||
std r10,SF_ARG16(r1)
|
||||
|
||||
// Store FPRs
|
||||
nop
|
||||
bf 26,L(call_struct_to_ram_form)
|
||||
stfd f1,SF_ARG17(r1)
|
||||
stfd f2,SF_ARG18(r1)
|
||||
stfd f3,SF_ARG19(r1)
|
||||
stfd f4,SF_ARG20(r1)
|
||||
nop
|
||||
stfd f5,SF_ARG21(r1)
|
||||
stfd f6,SF_ARG22(r1)
|
||||
stfd f7,SF_ARG23(r1)
|
||||
stfd f8,SF_ARG24(r1)
|
||||
nop
|
||||
stfd f9,SF_ARG25(r1)
|
||||
stfd f10,SF_ARG26(r1)
|
||||
stfd f11,SF_ARG27(r1)
|
||||
stfd f12,SF_ARG28(r1)
|
||||
nop
|
||||
stfd f13,SF_ARG29(r1)
|
||||
|
||||
L(call_struct_to_ram_form):
|
||||
ld r3,0(r27) // extended_cif->cif*
|
||||
ld r3,16(r3) // ffi_cif->rtype*
|
||||
addi r4,r1,SF_ARG9 // stored GPRs
|
||||
addi r6,r1,SF_ARG17 // stored FPRs
|
||||
li r5,0 // GPR size ptr (NULL)
|
||||
li r7,0 // FPR size ptr (NULL)
|
||||
li r8,0 // FPR count ptr (NULL)
|
||||
li r10,0 // struct offset (NULL)
|
||||
mr r9,r30 // return area
|
||||
bl Lffi64_struct_to_ram_form$stub
|
||||
lg r1,0(r1) // Restore stack pointer.
|
||||
b L(done_return_value)
|
||||
#endif
|
||||
|
||||
L(fp_return_value):
|
||||
/* Do we have long double to store? */
|
||||
bf 31,L(fd_return_value)
|
||||
stfd f1,0(r30)
|
||||
stfd f2,8(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(fd_return_value):
|
||||
/* Do we have double to store? */
|
||||
bf 28,L(float_return_value)
|
||||
stfd f1,0(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
L(float_return_value):
|
||||
/* We only have a float to store. */
|
||||
stfs f1,0(r30)
|
||||
b L(done_return_value)
|
||||
|
||||
LFE1:
|
||||
/* END(_ffi_call_DARWIN) */
|
||||
|
||||
/* Provide a null definition of _ffi_call_AIX. */
|
||||
.text
|
||||
.align 2
|
||||
.globl _ffi_call_AIX
|
||||
.text
|
||||
.align 2
|
||||
_ffi_call_AIX:
|
||||
blr
|
||||
/* END(_ffi_call_AIX) */
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align LOG2_GPR_BYTES
|
||||
LECIE1:
|
||||
.globl _ffi_call_DARWIN.eh
|
||||
_ffi_call_DARWIN.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 ; FDE Length
|
||||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB0$non_lazy_ptr-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB0
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI0-LFB1
|
||||
.long L$set$4
|
||||
.byte 0xd ; DW_CFA_def_cfa_register
|
||||
.byte 0x08 ; uleb128 0x08
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI1-LCFI0
|
||||
.long L$set$5
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.byte 0x9f ; DW_CFA_offset, column 0x1f
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x9e ; DW_CFA_offset, column 0x1e
|
||||
.byte 0x2 ; uleb128 0x2
|
||||
.byte 0x9d ; DW_CFA_offset, column 0x1d
|
||||
.byte 0x3 ; uleb128 0x3
|
||||
.byte 0x9c ; DW_CFA_offset, column 0x1c
|
||||
.byte 0x4 ; uleb128 0x4
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$6,LCFI2-LCFI1
|
||||
.long L$set$6
|
||||
.byte 0xd ; DW_CFA_def_cfa_register
|
||||
.byte 0x1c ; uleb128 0x1c
|
||||
.align LOG2_GPR_BYTES
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB0$non_lazy_ptr:
|
||||
.g_long LFB0
|
||||
|
||||
#if defined(__ppc64__)
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
Lffi64_struct_to_ram_form$stub:
|
||||
.indirect_symbol _ffi64_struct_to_ram_form
|
||||
mflr r0
|
||||
bcl 20,31,LO$ffi64_struct_to_ram_form
|
||||
|
||||
LO$ffi64_struct_to_ram_form:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)
|
||||
mtlr r0
|
||||
lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
|
||||
.lazy_symbol_pointer
|
||||
L_ffi64_struct_to_ram_form$lazy_ptr:
|
||||
.indirect_symbol _ffi64_struct_to_ram_form
|
||||
.g_long dyld_stub_binding_helper
|
||||
|
||||
#endif // __ppc64__
|
||||
#endif // __ppc__ || __ppc64__
|
|
@ -0,0 +1,106 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
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 AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#define L(x) x
|
||||
|
||||
#define SF_ARG9 MODE_CHOICE(56,112)
|
||||
#define SF_ARG10 MODE_CHOICE(60,120)
|
||||
#define SF_ARG11 MODE_CHOICE(64,128)
|
||||
#define SF_ARG12 MODE_CHOICE(68,136)
|
||||
#define SF_ARG13 MODE_CHOICE(72,144)
|
||||
#define SF_ARG14 MODE_CHOICE(76,152)
|
||||
#define SF_ARG15 MODE_CHOICE(80,160)
|
||||
#define SF_ARG16 MODE_CHOICE(84,168)
|
||||
#define SF_ARG17 MODE_CHOICE(88,176)
|
||||
#define SF_ARG18 MODE_CHOICE(92,184)
|
||||
#define SF_ARG19 MODE_CHOICE(96,192)
|
||||
#define SF_ARG20 MODE_CHOICE(100,200)
|
||||
#define SF_ARG21 MODE_CHOICE(104,208)
|
||||
#define SF_ARG22 MODE_CHOICE(108,216)
|
||||
#define SF_ARG23 MODE_CHOICE(112,224)
|
||||
#define SF_ARG24 MODE_CHOICE(116,232)
|
||||
#define SF_ARG25 MODE_CHOICE(120,240)
|
||||
#define SF_ARG26 MODE_CHOICE(124,248)
|
||||
#define SF_ARG27 MODE_CHOICE(128,256)
|
||||
#define SF_ARG28 MODE_CHOICE(132,264)
|
||||
#define SF_ARG29 MODE_CHOICE(136,272)
|
||||
|
||||
#define ASM_NEEDS_REGISTERS 4
|
||||
#define NUM_GPR_ARG_REGISTERS 8
|
||||
#define NUM_FPR_ARG_REGISTERS 13
|
||||
|
||||
#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8)
|
||||
#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16)
|
||||
#define FFI_TYPE_4_BYTE(x) \
|
||||
((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
|
||||
(x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
|
||||
|
||||
|
||||
#if !defined(LIBFFI_ASM)
|
||||
|
||||
enum {
|
||||
FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7
|
||||
FLAG_RETURNS_FP = 1 << (31 - 29),
|
||||
FLAG_RETURNS_64BITS = 1 << (31 - 28),
|
||||
FLAG_RETURNS_128BITS = 1 << (31 - 31),
|
||||
|
||||
FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6
|
||||
FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26),
|
||||
|
||||
FLAG_ARG_NEEDS_COPY = 1 << (31 - 7),
|
||||
FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI
|
||||
FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5),
|
||||
FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
|
||||
};
|
||||
|
||||
|
||||
void ffi_prep_args(extended_cif* inEcif, unsigned *const stack);
|
||||
|
||||
typedef union
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
} ffi_dblfl;
|
||||
|
||||
int ffi_closure_helper_DARWIN( ffi_closure* closure,
|
||||
void* rvalue, unsigned long* pgr,
|
||||
ffi_dblfl* pfr);
|
||||
|
||||
|
||||
#if defined(__ppc64__)
|
||||
void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
|
||||
const char*, unsigned int*, unsigned int*, char*, unsigned int*);
|
||||
void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
|
||||
unsigned int*, char*, unsigned int*, char*, unsigned int*);
|
||||
bool ffi64_stret_needs_ptr(const ffi_type* inType,
|
||||
unsigned short*, unsigned short*);
|
||||
bool ffi64_struct_contains_fp(const ffi_type* inType);
|
||||
unsigned int ffi64_data_size(const ffi_type* inType);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !defined(LIBFFI_ASM)
|
|
@ -0,0 +1,325 @@
|
|||
#if defined(__ppc__)
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc. based on ppc_closure.S
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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 AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ppc-ffitarget.h> // for FFI_TRAMPOLINE_SIZE
|
||||
#include <ppc-darwin.h>
|
||||
#include <architecture/ppc/mode_independent_asm.h>
|
||||
|
||||
.file "ppc-darwin_closure.S"
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
.globl _ffi_closure_ASM
|
||||
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
_ffi_closure_ASM:
|
||||
LFB1:
|
||||
mflr r0 /* extract return address */
|
||||
stg r0,MODE_CHOICE(8,16)(r1) /* save return address */
|
||||
|
||||
LCFI0:
|
||||
/* 24/48 bytes (Linkage Area)
|
||||
32/64 bytes (outgoing parameter area, always reserved)
|
||||
104 bytes (13*8 from FPR)
|
||||
16/32 bytes (result)
|
||||
176/232 total bytes */
|
||||
|
||||
/* skip over caller save area and keep stack aligned to 16/32. */
|
||||
stgu r1,-SF_ROUND(MODE_CHOICE(176,248))(r1)
|
||||
|
||||
LCFI1:
|
||||
/* We want to build up an area for the parameters passed
|
||||
in registers. (both floating point and integer) */
|
||||
|
||||
/* 176/256 bytes (callee stack frame aligned to 16/32)
|
||||
24/48 bytes (caller linkage area)
|
||||
200/304 (start of caller parameter area aligned to 4/8)
|
||||
*/
|
||||
|
||||
/* Save GPRs 3 - 10 (aligned to 4/8)
|
||||
in the parents outgoing area. */
|
||||
stg r3,MODE_CHOICE(200,304)(r1)
|
||||
stg r4,MODE_CHOICE(204,312)(r1)
|
||||
stg r5,MODE_CHOICE(208,320)(r1)
|
||||
stg r6,MODE_CHOICE(212,328)(r1)
|
||||
stg r7,MODE_CHOICE(216,336)(r1)
|
||||
stg r8,MODE_CHOICE(220,344)(r1)
|
||||
stg r9,MODE_CHOICE(224,352)(r1)
|
||||
stg r10,MODE_CHOICE(228,360)(r1)
|
||||
|
||||
/* Save FPRs 1 - 13. (aligned to 8) */
|
||||
stfd f1,MODE_CHOICE(56,112)(r1)
|
||||
stfd f2,MODE_CHOICE(64,120)(r1)
|
||||
stfd f3,MODE_CHOICE(72,128)(r1)
|
||||
stfd f4,MODE_CHOICE(80,136)(r1)
|
||||
stfd f5,MODE_CHOICE(88,144)(r1)
|
||||
stfd f6,MODE_CHOICE(96,152)(r1)
|
||||
stfd f7,MODE_CHOICE(104,160)(r1)
|
||||
stfd f8,MODE_CHOICE(112,168)(r1)
|
||||
stfd f9,MODE_CHOICE(120,176)(r1)
|
||||
stfd f10,MODE_CHOICE(128,184)(r1)
|
||||
stfd f11,MODE_CHOICE(136,192)(r1)
|
||||
stfd f12,MODE_CHOICE(144,200)(r1)
|
||||
stfd f13,MODE_CHOICE(152,208)(r1)
|
||||
|
||||
/* Set up registers for the routine that actually does the work.
|
||||
Get the context pointer from the trampoline. */
|
||||
mr r3,r11
|
||||
|
||||
/* Load the pointer to the result storage. */
|
||||
/* current stack frame size - ((4/8 * 4) + saved registers) */
|
||||
addi r4,r1,MODE_CHOICE(160,216)
|
||||
|
||||
/* Load the pointer to the saved gpr registers. */
|
||||
addi r5,r1,MODE_CHOICE(200,304)
|
||||
|
||||
/* Load the pointer to the saved fpr registers. */
|
||||
addi r6,r1,MODE_CHOICE(56,112)
|
||||
|
||||
/* Make the call. */
|
||||
bl Lffi_closure_helper_DARWIN$stub
|
||||
|
||||
/* Now r3 contains the return type
|
||||
so use it to look up in a table
|
||||
so we know how to deal with each type. */
|
||||
|
||||
/* Look the proper starting point in table
|
||||
by using return type as offset. */
|
||||
addi r5,r1,MODE_CHOICE(160,216) // Get pointer to results area.
|
||||
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
|
||||
mflr r4 // Move to r4.
|
||||
slwi r3,r3,4 // Now multiply return type by 16.
|
||||
add r3,r3,r4 // Add contents of table to table address.
|
||||
mtctr r3
|
||||
bctr
|
||||
|
||||
LFE1:
|
||||
/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
(4 instructions). For cache effectiveness we align to a 16 byte boundary
|
||||
first. */
|
||||
.align 4
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
Lget_ret_type0_addr:
|
||||
blrl
|
||||
|
||||
/* case FFI_TYPE_VOID */
|
||||
Lret_type0:
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_INT */
|
||||
Lret_type1:
|
||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_FLOAT */
|
||||
Lret_type2:
|
||||
lfs f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_DOUBLE */
|
||||
Lret_type3:
|
||||
lfd f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_LONGDOUBLE */
|
||||
Lret_type4:
|
||||
lfd f1,0(r5)
|
||||
lfd f2,8(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT8 */
|
||||
Lret_type5:
|
||||
lbz r3,MODE_CHOICE(3,7)(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT8 */
|
||||
Lret_type6:
|
||||
lbz r3,MODE_CHOICE(3,7)(r5)
|
||||
extsb r3,r3
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT16 */
|
||||
Lret_type7:
|
||||
lhz r3,MODE_CHOICE(2,6)(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT16 */
|
||||
Lret_type8:
|
||||
lha r3,MODE_CHOICE(2,6)(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT32 */
|
||||
Lret_type9: // same as Lret_type1
|
||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT32 */
|
||||
Lret_type10: // same as Lret_type1
|
||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT64 */
|
||||
Lret_type11:
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT64 */
|
||||
Lret_type12: // same as Lret_type11
|
||||
lwz r3,0(r5)
|
||||
lwz r4,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_STRUCT */
|
||||
Lret_type13:
|
||||
b MODE_CHOICE(Lfinish,Lret_struct)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* End 16-byte aligned cases */
|
||||
/* case FFI_TYPE_POINTER */
|
||||
// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
|
||||
// are added in future, the following code will need to be updated and
|
||||
// padded to 16 bytes.
|
||||
Lret_type14:
|
||||
lg r3,0(r5)
|
||||
|
||||
/* case done */
|
||||
Lfinish:
|
||||
addi r1,r1,SF_ROUND(MODE_CHOICE(176,248)) // Restore stack pointer.
|
||||
lg r0,MODE_CHOICE(8,16)(r1) /* Get return address. */
|
||||
mtlr r0 /* Reset link register. */
|
||||
blr
|
||||
|
||||
/* END(ffi_closure_ASM) */
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align LOG2_GPR_BYTES
|
||||
LECIE1:
|
||||
.globl _ffi_closure_ASM.eh
|
||||
_ffi_closure_ASM.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 ; FDE Length
|
||||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB1
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI1-LCFI0
|
||||
.long L$set$3
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 176,1 ; uleb128 176
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI0-LFB1
|
||||
.long L$set$4
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LDFCM0:
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
Lffi_closure_helper_DARWIN$stub:
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
mflr r0
|
||||
bcl 20,31,LO$ffi_closure_helper_DARWIN
|
||||
|
||||
LO$ffi_closure_helper_DARWIN:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
|
||||
mtlr r0
|
||||
lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
|
||||
.lazy_symbol_pointer
|
||||
L_ffi_closure_helper_DARWIN$lazy_ptr:
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
.g_long dyld_stub_binding_helper
|
||||
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long LFB1
|
||||
|
||||
#endif // __ppc__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,423 @@
|
|||
#if defined(__ppc64__)
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc. based on ppc_closure.S
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
||||
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 AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#define LIBFFI_ASM
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ppc-ffitarget.h> // for FFI_TRAMPOLINE_SIZE
|
||||
#include <ppc-darwin.h>
|
||||
#include <architecture/ppc/mode_independent_asm.h>
|
||||
|
||||
.file "ppc64-darwin_closure.S"
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
.globl _ffi_closure_ASM
|
||||
|
||||
.text
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
_ffi_closure_ASM:
|
||||
LFB1:
|
||||
mflr r0
|
||||
stg r0,SF_RETURN(r1) // save return address
|
||||
|
||||
// Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
|
||||
stg r3,SF_ARG1(r1)
|
||||
stg r4,SF_ARG2(r1)
|
||||
stg r5,SF_ARG3(r1)
|
||||
stg r6,SF_ARG4(r1)
|
||||
stg r7,SF_ARG5(r1)
|
||||
stg r8,SF_ARG6(r1)
|
||||
stg r9,SF_ARG7(r1)
|
||||
stg r10,SF_ARG8(r1)
|
||||
|
||||
LCFI0:
|
||||
/* 48 bytes (Linkage Area)
|
||||
64 bytes (outgoing parameter area, always reserved)
|
||||
112 bytes (14*8 for incoming FPR)
|
||||
? bytes (result)
|
||||
112 bytes (14*8 for outgoing FPR)
|
||||
16 bytes (2 saved registers)
|
||||
352 + ? total bytes
|
||||
*/
|
||||
|
||||
std r31,-8(r1) // Save registers we use.
|
||||
std r30,-16(r1)
|
||||
mr r30,r1 // Save the old SP.
|
||||
mr r31,r11 // Save the ffi_closure around ffi64_data_size.
|
||||
|
||||
// Calculate the space we need.
|
||||
stdu r1,-SF_MINSIZE(r1)
|
||||
ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
|
||||
ld r3,16(r3) // ffi_cif->rtype*
|
||||
bl Lffi64_data_size$stub
|
||||
ld r1,0(r1)
|
||||
|
||||
addi r3,r3,352 // Add our overhead.
|
||||
neg r3,r3
|
||||
li r0,-32 // Align to 32 bytes.
|
||||
and r3,r3,r0
|
||||
stdux r1,r1,r3 // Grow the stack.
|
||||
|
||||
mr r11,r31 // Copy the ffi_closure back.
|
||||
|
||||
LCFI1:
|
||||
// We want to build up an area for the parameters passed
|
||||
// in registers. (both floating point and integer)
|
||||
|
||||
/* 320 bytes (callee stack frame aligned to 32)
|
||||
48 bytes (caller linkage area)
|
||||
368 (start of caller parameter area aligned to 8)
|
||||
*/
|
||||
|
||||
// Save FPRs 1 - 14. (aligned to 8)
|
||||
stfd f1,112(r1)
|
||||
stfd f2,120(r1)
|
||||
stfd f3,128(r1)
|
||||
stfd f4,136(r1)
|
||||
stfd f5,144(r1)
|
||||
stfd f6,152(r1)
|
||||
stfd f7,160(r1)
|
||||
stfd f8,168(r1)
|
||||
stfd f9,176(r1)
|
||||
stfd f10,184(r1)
|
||||
stfd f11,192(r1)
|
||||
stfd f12,200(r1)
|
||||
stfd f13,208(r1)
|
||||
stfd f14,216(r1)
|
||||
|
||||
// Set up registers for the routine that actually does the work.
|
||||
mr r3,r11 // context pointer from the trampoline
|
||||
addi r4,r1,224 // result storage
|
||||
addi r5,r30,SF_ARG1 // saved GPRs
|
||||
addi r6,r1,112 // saved FPRs
|
||||
bl Lffi_closure_helper_DARWIN$stub
|
||||
|
||||
// Look the proper starting point in table
|
||||
// by using return type as an offset.
|
||||
addi r5,r1,224 // Get pointer to results area.
|
||||
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
|
||||
mflr r4 // Move to r4.
|
||||
slwi r3,r3,4 // Now multiply return type by 16.
|
||||
add r3,r3,r4 // Add contents of table to table address.
|
||||
mtctr r3
|
||||
bctr
|
||||
|
||||
LFE1:
|
||||
// Each of the ret_typeX code fragments has to be exactly 16 bytes long
|
||||
// (4 instructions). For cache effectiveness we align to a 16 byte
|
||||
// boundary first.
|
||||
.align 4
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
Lget_ret_type0_addr:
|
||||
blrl
|
||||
|
||||
// case FFI_TYPE_VOID
|
||||
Lret_type0:
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_INT
|
||||
Lret_type1:
|
||||
lwz r3,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_FLOAT
|
||||
Lret_type2:
|
||||
lfs f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_DOUBLE
|
||||
Lret_type3:
|
||||
lfd f1,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_LONGDOUBLE
|
||||
Lret_type4:
|
||||
lfd f1,0(r5)
|
||||
lfd f2,8(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_UINT8
|
||||
Lret_type5:
|
||||
lbz r3,7(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_SINT8
|
||||
Lret_type6:
|
||||
lbz r3,7(r5)
|
||||
extsb r3,r3
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_UINT16
|
||||
Lret_type7:
|
||||
lhz r3,6(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_SINT16
|
||||
Lret_type8:
|
||||
lha r3,6(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_UINT32
|
||||
Lret_type9: // same as Lret_type1
|
||||
lwz r3,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_SINT32
|
||||
Lret_type10: // same as Lret_type1
|
||||
lwz r3,4(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_UINT64
|
||||
Lret_type11:
|
||||
ld r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_SINT64
|
||||
Lret_type12: // same as Lret_type11
|
||||
ld r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
// case FFI_TYPE_STRUCT
|
||||
Lret_type13:
|
||||
b Lret_struct
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
// ** End 16-byte aligned cases **
|
||||
// case FFI_TYPE_POINTER
|
||||
// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
|
||||
// are added in future, the following code will need to be updated and
|
||||
// padded to 16 bytes.
|
||||
Lret_type14:
|
||||
lg r3,0(r5)
|
||||
b Lfinish
|
||||
|
||||
// copy struct into registers
|
||||
Lret_struct:
|
||||
ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
|
||||
ld r3,16(r31) // ffi_cif->rtype*
|
||||
ld r31,24(r31) // ffi_cif->flags
|
||||
mr r4,r5 // copy struct* to 2nd arg
|
||||
addi r7,r1,SF_ARG9 // GPR return area
|
||||
addi r9,r30,-16-(14*8) // FPR return area
|
||||
li r5,0 // struct offset ptr (NULL)
|
||||
li r6,0 // FPR used count ptr (NULL)
|
||||
li r8,0 // GPR return area size ptr (NULL)
|
||||
li r10,0 // FPR return area size ptr (NULL)
|
||||
bl Lffi64_struct_to_reg_form$stub
|
||||
|
||||
// Load GPRs
|
||||
ld r3,SF_ARG9(r1)
|
||||
ld r4,SF_ARG10(r1)
|
||||
ld r5,SF_ARG11(r1)
|
||||
ld r6,SF_ARG12(r1)
|
||||
nop
|
||||
ld r7,SF_ARG13(r1)
|
||||
ld r8,SF_ARG14(r1)
|
||||
ld r9,SF_ARG15(r1)
|
||||
ld r10,SF_ARG16(r1)
|
||||
nop
|
||||
|
||||
// Load FPRs
|
||||
mtcrf 0x2,r31
|
||||
bf 26,Lfinish
|
||||
lfd f1,-16-(14*8)(r30)
|
||||
lfd f2,-16-(13*8)(r30)
|
||||
lfd f3,-16-(12*8)(r30)
|
||||
lfd f4,-16-(11*8)(r30)
|
||||
nop
|
||||
lfd f5,-16-(10*8)(r30)
|
||||
lfd f6,-16-(9*8)(r30)
|
||||
lfd f7,-16-(8*8)(r30)
|
||||
lfd f8,-16-(7*8)(r30)
|
||||
nop
|
||||
lfd f9,-16-(6*8)(r30)
|
||||
lfd f10,-16-(5*8)(r30)
|
||||
lfd f11,-16-(4*8)(r30)
|
||||
lfd f12,-16-(3*8)(r30)
|
||||
nop
|
||||
lfd f13,-16-(2*8)(r30)
|
||||
lfd f14,-16-(1*8)(r30)
|
||||
// Fall through
|
||||
|
||||
// case done
|
||||
Lfinish:
|
||||
lg r1,0(r1) // Restore stack pointer.
|
||||
ld r31,-8(r1) // Restore registers we used.
|
||||
ld r30,-16(r1)
|
||||
lg r0,SF_RETURN(r1) // Get return address.
|
||||
mtlr r0 // Reset link register.
|
||||
blr
|
||||
|
||||
// END(ffi_closure_ASM)
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align LOG2_GPR_BYTES
|
||||
LECIE1:
|
||||
.globl _ffi_closure_ASM.eh
|
||||
_ffi_closure_ASM.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 ; FDE Length
|
||||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB1
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI1-LCFI0
|
||||
.long L$set$3
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 176,1 ; uleb128 176
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI0-LFB1
|
||||
.long L$set$4
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LDFCM0:
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
Lffi_closure_helper_DARWIN$stub:
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
mflr r0
|
||||
bcl 20,31,LO$ffi_closure_helper_DARWIN
|
||||
|
||||
LO$ffi_closure_helper_DARWIN:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
|
||||
mtlr r0
|
||||
lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
|
||||
.lazy_symbol_pointer
|
||||
L_ffi_closure_helper_DARWIN$lazy_ptr:
|
||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
.g_long dyld_stub_binding_helper
|
||||
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long LFB1
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
Lffi64_struct_to_reg_form$stub:
|
||||
.indirect_symbol _ffi64_struct_to_reg_form
|
||||
mflr r0
|
||||
bcl 20,31,LO$ffi64_struct_to_reg_form
|
||||
|
||||
LO$ffi64_struct_to_reg_form:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
|
||||
mtlr r0
|
||||
lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
Lffi64_data_size$stub:
|
||||
.indirect_symbol _ffi64_data_size
|
||||
mflr r0
|
||||
bcl 20,31,LO$ffi64_data_size
|
||||
|
||||
LO$ffi64_data_size:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
|
||||
mtlr r0
|
||||
lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
|
||||
.lazy_symbol_pointer
|
||||
L_ffi64_struct_to_reg_form$lazy_ptr:
|
||||
.indirect_symbol _ffi64_struct_to_reg_form
|
||||
.g_long dyld_stub_binding_helper
|
||||
|
||||
L_ffi64_data_size$lazy_ptr:
|
||||
.indirect_symbol _ffi64_data_size
|
||||
.g_long dyld_stub_binding_helper
|
||||
|
||||
#endif // __ppc64__
|
|
@ -0,0 +1,115 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
Predefined ffi_types needed by libffi.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
/* Type definitions */
|
||||
#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \
|
||||
ffi_type ffi_type_##n = { s, a, t, NULL }
|
||||
#define FFI_AGGREGATE_TYPEDEF(n, e) \
|
||||
ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
|
||||
FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
|
||||
FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
|
||||
|
||||
/* Size and alignment are fake here. They must not be 0. */
|
||||
FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
|
||||
|
||||
#if defined ALPHA || defined SPARC64 || defined X86_64 || \
|
||||
defined S390X || defined IA64 || defined POWERPC64
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
|
||||
#else
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
|
||||
#endif
|
||||
|
||||
#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN)
|
||||
|
||||
# ifdef X86_64
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
|
||||
# else
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
# endif
|
||||
|
||||
#elif defined(POWERPC_DARWIN)
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
|
||||
#elif defined SH
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
#else
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
|
||||
#endif
|
||||
|
||||
#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN)
|
||||
|
||||
# if defined X86_WIN32 || defined X86_64
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
# else
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
# endif
|
||||
|
||||
# ifdef X86_DARWIN
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
# else
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
# endif
|
||||
|
||||
#elif defined ARM || defined SH || defined POWERPC_AIX
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
|
||||
#elif defined POWERPC_DARWIN
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
|
||||
# if __GNUC__ >= 4
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
# else
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
|
||||
# endif
|
||||
|
||||
#elif defined SPARC
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
|
||||
# ifdef SPARC64
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
# else
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
|
||||
# endif
|
||||
|
||||
#elif defined X86_64 || defined POWERPC64
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
#else
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
|
||||
#endif
|
|
@ -0,0 +1,415 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc.
|
||||
derived from unix64.S
|
||||
|
||||
x86-64 Foreign Function Interface for Darwin.
|
||||
|
||||
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 AUTHOR 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.file "darwin64.S"
|
||||
.text
|
||||
|
||||
/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)());
|
||||
|
||||
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
|
||||
for this function. This has been allocated by ffi_call. We also
|
||||
deallocate some of the stack that has been alloca'd. */
|
||||
|
||||
.align 3
|
||||
.globl _ffi_call_unix64
|
||||
|
||||
_ffi_call_unix64:
|
||||
LUW0:
|
||||
movq (%rsp), %r10 /* Load return address. */
|
||||
leaq (%rdi, %rsi), %rax /* Find local stack base. */
|
||||
movq %rdx, (%rax) /* Save flags. */
|
||||
movq %rcx, 8(%rax) /* Save raddr. */
|
||||
movq %rbp, 16(%rax) /* Save old frame pointer. */
|
||||
movq %r10, 24(%rax) /* Relocate return address. */
|
||||
movq %rax, %rbp /* Finalize local stack frame. */
|
||||
LUW1:
|
||||
movq %rdi, %r10 /* Save a copy of the register area. */
|
||||
movq %r8, %r11 /* Save a copy of the target fn. */
|
||||
movl %r9d, %eax /* Set number of SSE registers. */
|
||||
|
||||
/* Load up all argument registers. */
|
||||
movq (%r10), %rdi
|
||||
movq 8(%r10), %rsi
|
||||
movq 16(%r10), %rdx
|
||||
movq 24(%r10), %rcx
|
||||
movq 32(%r10), %r8
|
||||
movq 40(%r10), %r9
|
||||
testl %eax, %eax
|
||||
jnz Lload_sse
|
||||
Lret_from_load_sse:
|
||||
|
||||
/* Deallocate the reg arg area. */
|
||||
leaq 176(%r10), %rsp
|
||||
|
||||
/* Call the user function. */
|
||||
call *%r11
|
||||
|
||||
/* Deallocate stack arg area; local stack frame in redzone. */
|
||||
leaq 24(%rbp), %rsp
|
||||
|
||||
movq 0(%rbp), %rcx /* Reload flags. */
|
||||
movq 8(%rbp), %rdi /* Reload raddr. */
|
||||
movq 16(%rbp), %rbp /* Reload old frame pointer. */
|
||||
LUW2:
|
||||
|
||||
/* The first byte of the flags contains the FFI_TYPE. */
|
||||
movzbl %cl, %r10d
|
||||
leaq Lstore_table(%rip), %r11
|
||||
movslq (%r11, %r10, 4), %r10
|
||||
addq %r11, %r10
|
||||
jmp *%r10
|
||||
|
||||
Lstore_table:
|
||||
.long Lst_void-Lstore_table /* FFI_TYPE_VOID */
|
||||
.long Lst_sint32-Lstore_table /* FFI_TYPE_INT */
|
||||
.long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */
|
||||
.long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */
|
||||
.long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */
|
||||
.long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */
|
||||
.long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */
|
||||
.long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */
|
||||
.long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */
|
||||
.long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */
|
||||
.long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */
|
||||
.long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */
|
||||
.long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */
|
||||
.long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */
|
||||
.long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */
|
||||
|
||||
.text
|
||||
.align 3
|
||||
Lst_void:
|
||||
ret
|
||||
.align 3
|
||||
Lst_uint8:
|
||||
movzbq %al, %rax
|
||||
movq %rax, (%rdi)
|
||||
ret
|
||||
.align 3
|
||||
Lst_sint8:
|
||||
movsbq %al, %rax
|
||||
movq %rax, (%rdi)
|
||||
ret
|
||||
.align 3
|
||||
Lst_uint16:
|
||||
movzwq %ax, %rax
|
||||
movq %rax, (%rdi)
|
||||
.align 3
|
||||
Lst_sint16:
|
||||
movswq %ax, %rax
|
||||
movq %rax, (%rdi)
|
||||
ret
|
||||
.align 3
|
||||
Lst_uint32:
|
||||
movl %eax, %eax
|
||||
movq %rax, (%rdi)
|
||||
.align 3
|
||||
Lst_sint32:
|
||||
cltq
|
||||
movq %rax, (%rdi)
|
||||
ret
|
||||
.align 3
|
||||
Lst_int64:
|
||||
movq %rax, (%rdi)
|
||||
ret
|
||||
.align 3
|
||||
Lst_float:
|
||||
movss %xmm0, (%rdi)
|
||||
ret
|
||||
.align 3
|
||||
Lst_double:
|
||||
movsd %xmm0, (%rdi)
|
||||
ret
|
||||
Lst_ldouble:
|
||||
fstpt (%rdi)
|
||||
ret
|
||||
.align 3
|
||||
Lst_struct:
|
||||
leaq -20(%rsp), %rsi /* Scratch area in redzone. */
|
||||
|
||||
/* We have to locate the values now, and since we don't want to
|
||||
write too much data into the user's return value, we spill the
|
||||
value to a 16 byte scratch area first. Bits 8, 9, and 10
|
||||
control where the values are located. Only one of the three
|
||||
bits will be set; see ffi_prep_cif_machdep for the pattern. */
|
||||
movd %xmm0, %r10
|
||||
movd %xmm1, %r11
|
||||
testl $0x100, %ecx
|
||||
cmovnz %rax, %rdx
|
||||
cmovnz %r10, %rax
|
||||
testl $0x200, %ecx
|
||||
cmovnz %r10, %rdx
|
||||
testl $0x400, %ecx
|
||||
cmovnz %r10, %rax
|
||||
cmovnz %r11, %rdx
|
||||
movq %rax, (%rsi)
|
||||
movq %rdx, 8(%rsi)
|
||||
|
||||
/* Bits 12-31 contain the true size of the structure. Copy from
|
||||
the scratch area to the true destination. */
|
||||
shrl $12, %ecx
|
||||
rep movsb
|
||||
ret
|
||||
|
||||
/* Many times we can avoid loading any SSE registers at all.
|
||||
It's not worth an indirect jump to load the exact set of
|
||||
SSE registers needed; zero or all is a good compromise. */
|
||||
.align 3
|
||||
LUW3:
|
||||
Lload_sse:
|
||||
movdqa 48(%r10), %xmm0
|
||||
movdqa 64(%r10), %xmm1
|
||||
movdqa 80(%r10), %xmm2
|
||||
movdqa 96(%r10), %xmm3
|
||||
movdqa 112(%r10), %xmm4
|
||||
movdqa 128(%r10), %xmm5
|
||||
movdqa 144(%r10), %xmm6
|
||||
movdqa 160(%r10), %xmm7
|
||||
jmp Lret_from_load_sse
|
||||
|
||||
LUW4:
|
||||
.align 3
|
||||
.globl _ffi_closure_unix64
|
||||
|
||||
_ffi_closure_unix64:
|
||||
LUW5:
|
||||
/* The carry flag is set by the trampoline iff SSE registers
|
||||
are used. Don't clobber it before the branch instruction. */
|
||||
leaq -200(%rsp), %rsp
|
||||
LUW6:
|
||||
movq %rdi, (%rsp)
|
||||
movq %rsi, 8(%rsp)
|
||||
movq %rdx, 16(%rsp)
|
||||
movq %rcx, 24(%rsp)
|
||||
movq %r8, 32(%rsp)
|
||||
movq %r9, 40(%rsp)
|
||||
jc Lsave_sse
|
||||
Lret_from_save_sse:
|
||||
|
||||
movq %r10, %rdi
|
||||
leaq 176(%rsp), %rsi
|
||||
movq %rsp, %rdx
|
||||
leaq 208(%rsp), %rcx
|
||||
call _ffi_closure_unix64_inner
|
||||
|
||||
/* Deallocate stack frame early; return value is now in redzone. */
|
||||
addq $200, %rsp
|
||||
LUW7:
|
||||
|
||||
/* The first byte of the return value contains the FFI_TYPE. */
|
||||
movzbl %al, %r10d
|
||||
leaq Lload_table(%rip), %r11
|
||||
movslq (%r11, %r10, 4), %r10
|
||||
addq %r11, %r10
|
||||
jmp *%r10
|
||||
|
||||
Lload_table:
|
||||
.long Lld_void-Lload_table /* FFI_TYPE_VOID */
|
||||
.long Lld_int32-Lload_table /* FFI_TYPE_INT */
|
||||
.long Lld_float-Lload_table /* FFI_TYPE_FLOAT */
|
||||
.long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */
|
||||
.long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */
|
||||
.long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */
|
||||
.long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */
|
||||
.long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */
|
||||
.long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */
|
||||
.long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */
|
||||
.long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */
|
||||
.long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */
|
||||
.long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */
|
||||
.long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */
|
||||
.long Lld_int64-Lload_table /* FFI_TYPE_POINTER */
|
||||
|
||||
.text
|
||||
.align 3
|
||||
Lld_void:
|
||||
ret
|
||||
.align 3
|
||||
Lld_int8:
|
||||
movzbl -24(%rsp), %eax
|
||||
ret
|
||||
.align 3
|
||||
Lld_int16:
|
||||
movzwl -24(%rsp), %eax
|
||||
ret
|
||||
.align 3
|
||||
Lld_int32:
|
||||
movl -24(%rsp), %eax
|
||||
ret
|
||||
.align 3
|
||||
Lld_int64:
|
||||
movq -24(%rsp), %rax
|
||||
ret
|
||||
.align 3
|
||||
Lld_float:
|
||||
movss -24(%rsp), %xmm0
|
||||
ret
|
||||
.align 3
|
||||
Lld_double:
|
||||
movsd -24(%rsp), %xmm0
|
||||
ret
|
||||
.align 3
|
||||
Lld_ldouble:
|
||||
fldt -24(%rsp)
|
||||
ret
|
||||
.align 3
|
||||
Lld_struct:
|
||||
/* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
|
||||
%rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading
|
||||
both rdx and xmm1 with the second word. For the remaining,
|
||||
bit 8 set means xmm0 gets the second word, and bit 9 means
|
||||
that rax gets the second word. */
|
||||
movq -24(%rsp), %rcx
|
||||
movq -16(%rsp), %rdx
|
||||
movq -16(%rsp), %xmm1
|
||||
testl $0x100, %eax
|
||||
cmovnz %rdx, %rcx
|
||||
movd %rcx, %xmm0
|
||||
testl $0x200, %eax
|
||||
movq -24(%rsp), %rax
|
||||
cmovnz %rdx, %rax
|
||||
ret
|
||||
|
||||
/* See the comment above Lload_sse; the same logic applies here. */
|
||||
.align 3
|
||||
LUW8:
|
||||
Lsave_sse:
|
||||
movdqa %xmm0, 48(%rsp)
|
||||
movdqa %xmm1, 64(%rsp)
|
||||
movdqa %xmm2, 80(%rsp)
|
||||
movdqa %xmm3, 96(%rsp)
|
||||
movdqa %xmm4, 112(%rsp)
|
||||
movdqa %xmm5, 128(%rsp)
|
||||
movdqa %xmm6, 144(%rsp)
|
||||
movdqa %xmm7, 160(%rsp)
|
||||
jmp Lret_from_save_sse
|
||||
|
||||
LUW9:
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1 /* CIE Length */
|
||||
.long L$set$0
|
||||
LSCIE1:
|
||||
.long 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
.byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
|
||||
.byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */
|
||||
.byte 0x10 /* CIE RA Column */
|
||||
.byte 0x1 /* uleb128 0x1; Augmentation size */
|
||||
.byte 0x10 /* FDE Encoding (pcrel sdata4) */
|
||||
.byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
|
||||
.byte 0x7 /* uleb128 0x7 */
|
||||
.byte 0x8 /* uleb128 0x8 */
|
||||
.byte 0x90 /* DW_CFA_offset, column 0x10 */
|
||||
.byte 0x1
|
||||
.align 3
|
||||
LECIE1:
|
||||
.globl _ffi_call_unix64.eh
|
||||
_ffi_call_unix64.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1 /* FDE Length */
|
||||
.long L$set$1
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 /* FDE CIE offset */
|
||||
.quad LUW0-. /* FDE initial location */
|
||||
.set L$set$2,LUW4-LUW0 /* FDE address range */
|
||||
.quad L$set$2
|
||||
.byte 0x0 /* Augmentation size */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.set L$set$3,LUW1-LUW0
|
||||
.long L$set$3
|
||||
|
||||
/* New stack frame based off rbp. This is a itty bit of unwind
|
||||
trickery in that the CFA *has* changed. There is no easy way
|
||||
to describe it correctly on entry to the function. Fortunately,
|
||||
it doesn't matter too much since at all points we can correctly
|
||||
unwind back to ffi_call. Note that the location to which we
|
||||
moved the return address is (the new) CFA-8, so from the
|
||||
perspective of the unwind info, it hasn't moved. */
|
||||
.byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */
|
||||
.byte 0x6
|
||||
.byte 0x20
|
||||
.byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */
|
||||
.byte 0x2
|
||||
.byte 0xa /* DW_CFA_remember_state */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.set L$set$4,LUW2-LUW1
|
||||
.long L$set$4
|
||||
.byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
|
||||
.byte 0x7
|
||||
.byte 0x8
|
||||
.byte 0xc0+6 /* DW_CFA_restore, %rbp */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.set L$set$5,LUW3-LUW2
|
||||
.long L$set$5
|
||||
.byte 0xb /* DW_CFA_restore_state */
|
||||
|
||||
.align 3
|
||||
LEFDE1:
|
||||
.globl _ffi_closure_unix64.eh
|
||||
_ffi_closure_unix64.eh:
|
||||
LSFDE3:
|
||||
.set L$set$6,LEFDE3-LASFDE3 /* FDE Length */
|
||||
.long L$set$6
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 /* FDE CIE offset */
|
||||
.quad LUW5-. /* FDE initial location */
|
||||
.set L$set$7,LUW9-LUW5 /* FDE address range */
|
||||
.quad L$set$7
|
||||
.byte 0x0 /* Augmentation size */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.set L$set$8,LUW6-LUW5
|
||||
.long L$set$8
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 208,1 /* uleb128 208 */
|
||||
.byte 0xa /* DW_CFA_remember_state */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.set L$set$9,LUW7-LUW6
|
||||
.long L$set$9
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x8
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.set L$set$10,LUW8-LUW7
|
||||
.long L$set$10
|
||||
.byte 0xb /* DW_CFA_restore_state */
|
||||
|
||||
.align 3
|
||||
LEFDE3:
|
||||
.subsections_via_symbols
|
||||
|
||||
#endif /* __x86_64__ */
|
|
@ -0,0 +1,243 @@
|
|||
#ifdef __i386__
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc.
|
||||
|
||||
X86 Foreign Function Interface
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* This file is based on sysv.S and then hacked up by Ronald who hasn't done
|
||||
* assembly programming in 8 years.
|
||||
*/
|
||||
|
||||
#ifndef __x86_64__
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#ifdef PyObjC_STRICT_DEBUGGING
|
||||
/* XXX: Debugging of stack alignment, to be removed */
|
||||
#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
|
||||
#else
|
||||
#define ASSERT_STACK_ALIGNED
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.globl _ffi_prep_args
|
||||
|
||||
.align 4
|
||||
.globl _ffi_call_SYSV
|
||||
|
||||
_ffi_call_SYSV:
|
||||
.LFB1:
|
||||
pushl %ebp
|
||||
.LCFI0:
|
||||
movl %esp,%ebp
|
||||
subl $8,%esp
|
||||
ASSERT_STACK_ALIGNED
|
||||
.LCFI1:
|
||||
/* Make room for all of the new args. */
|
||||
movl 16(%ebp),%ecx
|
||||
subl %ecx,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
movl %esp,%eax
|
||||
|
||||
/* Place all of the ffi_prep_args in position */
|
||||
subl $8,%esp
|
||||
pushl 12(%ebp)
|
||||
pushl %eax
|
||||
call *8(%ebp)
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
/* Return stack to previous state and call the function */
|
||||
addl $16,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
call *28(%ebp)
|
||||
|
||||
/* XXX: return returns return with 'ret $4', that upsets the stack! */
|
||||
movl 16(%ebp),%ecx
|
||||
addl %ecx,%esp
|
||||
|
||||
|
||||
/* 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 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 noretval
|
||||
fstp %st(0)
|
||||
|
||||
jmp epilogue
|
||||
|
||||
retint:
|
||||
cmpl $FFI_TYPE_INT,%ecx
|
||||
jne retfloat
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retfloat:
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne retdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstps (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retdouble:
|
||||
cmpl $FFI_TYPE_DOUBLE,%ecx
|
||||
jne retlongdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstpl (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retlongdouble:
|
||||
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
|
||||
jne retint64
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstpt (%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retint64:
|
||||
cmpl $FFI_TYPE_SINT64,%ecx
|
||||
jne retstruct1b
|
||||
/* 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:
|
||||
cmpl $FFI_TYPE_SINT8,%ecx
|
||||
jne retstruct2b
|
||||
movl 24(%ebp),%ecx
|
||||
movb %al,0(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retstruct2b:
|
||||
cmpl $FFI_TYPE_SINT16,%ecx
|
||||
jne retstruct
|
||||
movl 24(%ebp),%ecx
|
||||
movw %ax,0(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retstruct:
|
||||
cmpl $FFI_TYPE_STRUCT,%ecx
|
||||
jne noretval
|
||||
/* Nothing to do! */
|
||||
|
||||
subl $4,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
addl $8,%esp
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
ASSERT_STACK_ALIGNED
|
||||
addl $8, %esp
|
||||
|
||||
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
.LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
#if 0
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
.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:
|
||||
#endif
|
||||
|
||||
#endif /* ifndef __x86_64__ */
|
||||
|
||||
#endif /* defined __i386__ */
|
|
@ -0,0 +1,624 @@
|
|||
#ifdef __x86_64__
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
x86-ffi64.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
|
||||
|
||||
x86-64 Foreign Function Interface
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define MAX_GPR_REGS 6
|
||||
#define MAX_SSE_REGS 8
|
||||
|
||||
typedef struct RegisterArgs {
|
||||
/* Registers for argument passing. */
|
||||
UINT64 gpr[MAX_GPR_REGS];
|
||||
__int128_t sse[MAX_SSE_REGS];
|
||||
} RegisterArgs;
|
||||
|
||||
extern void
|
||||
ffi_call_unix64(
|
||||
void* args,
|
||||
unsigned long bytes,
|
||||
unsigned flags,
|
||||
void* raddr,
|
||||
void (*fnaddr)(),
|
||||
unsigned ssecount);
|
||||
|
||||
/* All reference to register classes here is identical to the code in
|
||||
gcc/config/i386/i386.c. Do *not* change one without the other. */
|
||||
|
||||
/* Register class used for passing given 64bit part of the argument.
|
||||
These represent classes as documented by the PS ABI, with the exception
|
||||
of SSESF, SSEDF classes, that are basically SSE class, just gcc will
|
||||
use SF or DFmode move instead of DImode to avoid reformating penalties.
|
||||
|
||||
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
|
||||
whenever possible (upper half does contain padding). */
|
||||
enum x86_64_reg_class
|
||||
{
|
||||
X86_64_NO_CLASS,
|
||||
X86_64_INTEGER_CLASS,
|
||||
X86_64_INTEGERSI_CLASS,
|
||||
X86_64_SSE_CLASS,
|
||||
X86_64_SSESF_CLASS,
|
||||
X86_64_SSEDF_CLASS,
|
||||
X86_64_SSEUP_CLASS,
|
||||
X86_64_X87_CLASS,
|
||||
X86_64_X87UP_CLASS,
|
||||
X86_64_COMPLEX_X87_CLASS,
|
||||
X86_64_MEMORY_CLASS
|
||||
};
|
||||
|
||||
#define MAX_CLASSES 4
|
||||
#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
|
||||
|
||||
/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
|
||||
of this code is to classify each 8bytes of incoming argument by the register
|
||||
class and assign registers accordingly. */
|
||||
|
||||
/* Return the union class of CLASS1 and CLASS2.
|
||||
See the x86-64 PS ABI for details. */
|
||||
static enum x86_64_reg_class
|
||||
merge_classes(
|
||||
enum x86_64_reg_class class1,
|
||||
enum x86_64_reg_class class2)
|
||||
{
|
||||
/* Rule #1: If both classes are equal, this is the resulting class. */
|
||||
if (class1 == class2)
|
||||
return class1;
|
||||
|
||||
/* Rule #2: If one of the classes is NO_CLASS, the resulting class is
|
||||
the other class. */
|
||||
if (class1 == X86_64_NO_CLASS)
|
||||
return class2;
|
||||
|
||||
if (class2 == X86_64_NO_CLASS)
|
||||
return class1;
|
||||
|
||||
/* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
|
||||
if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
|
||||
return X86_64_MEMORY_CLASS;
|
||||
|
||||
/* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
|
||||
if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
|
||||
|| (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
|
||||
return X86_64_INTEGERSI_CLASS;
|
||||
|
||||
if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
|
||||
|| class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
|
||||
return X86_64_INTEGER_CLASS;
|
||||
|
||||
/* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
|
||||
MEMORY is used. */
|
||||
if (class1 == X86_64_X87_CLASS
|
||||
|| class1 == X86_64_X87UP_CLASS
|
||||
|| class1 == X86_64_COMPLEX_X87_CLASS
|
||||
|| class2 == X86_64_X87_CLASS
|
||||
|| class2 == X86_64_X87UP_CLASS
|
||||
|| class2 == X86_64_COMPLEX_X87_CLASS)
|
||||
return X86_64_MEMORY_CLASS;
|
||||
|
||||
/* Rule #6: Otherwise class SSE is used. */
|
||||
return X86_64_SSE_CLASS;
|
||||
}
|
||||
|
||||
/* Classify the argument of type TYPE and mode MODE.
|
||||
CLASSES will be filled by the register class used to pass each word
|
||||
of the operand. The number of words is returned. In case the parameter
|
||||
should be passed in memory, 0 is returned. As a special case for zero
|
||||
sized containers, classes[0] will be NO_CLASS and 1 is returned.
|
||||
|
||||
See the x86-64 PS ABI for details. */
|
||||
|
||||
static int
|
||||
classify_argument(
|
||||
ffi_type* type,
|
||||
enum x86_64_reg_class classes[],
|
||||
size_t byte_offset)
|
||||
{
|
||||
switch (type->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
if (byte_offset + type->size <= 4)
|
||||
classes[0] = X86_64_INTEGERSI_CLASS;
|
||||
else
|
||||
classes[0] = X86_64_INTEGER_CLASS;
|
||||
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (byte_offset == 0)
|
||||
classes[0] = X86_64_SSESF_CLASS;
|
||||
else
|
||||
classes[0] = X86_64_SSE_CLASS;
|
||||
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_DOUBLE:
|
||||
classes[0] = X86_64_SSEDF_CLASS;
|
||||
return 1;
|
||||
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
classes[0] = X86_64_X87_CLASS;
|
||||
classes[1] = X86_64_X87UP_CLASS;
|
||||
return 2;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
ffi_type** ptr;
|
||||
int i;
|
||||
enum x86_64_reg_class subclasses[MAX_CLASSES];
|
||||
const int UNITS_PER_WORD = 8;
|
||||
int words =
|
||||
(type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
|
||||
/* If the struct is larger than 16 bytes, pass it on the stack. */
|
||||
if (type->size > 16)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < words; i++)
|
||||
classes[i] = X86_64_NO_CLASS;
|
||||
|
||||
/* Merge the fields of structure. */
|
||||
for (ptr = type->elements; *ptr != NULL; ptr++)
|
||||
{
|
||||
byte_offset = ALIGN(byte_offset, (*ptr)->alignment);
|
||||
|
||||
int num = classify_argument(*ptr, subclasses, byte_offset % 8);
|
||||
|
||||
if (num == 0)
|
||||
return 0;
|
||||
|
||||
int pos = byte_offset / 8;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
classes[i + pos] =
|
||||
merge_classes(subclasses[i], classes[i + pos]);
|
||||
}
|
||||
|
||||
byte_offset += (*ptr)->size;
|
||||
}
|
||||
|
||||
/* Final merger cleanup. */
|
||||
for (i = 0; i < words; i++)
|
||||
{
|
||||
/* If one class is MEMORY, everything should be passed in
|
||||
memory. */
|
||||
if (classes[i] == X86_64_MEMORY_CLASS)
|
||||
return 0;
|
||||
|
||||
/* The X86_64_SSEUP_CLASS should be always preceded by
|
||||
X86_64_SSE_CLASS. */
|
||||
if (classes[i] == X86_64_SSEUP_CLASS
|
||||
&& (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
|
||||
classes[i] = X86_64_SSE_CLASS;
|
||||
|
||||
/* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
|
||||
if (classes[i] == X86_64_X87UP_CLASS
|
||||
&& (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
|
||||
classes[i] = X86_64_SSE_CLASS;
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
|
||||
return 0; /* Never reached. */
|
||||
}
|
||||
|
||||
/* Examine the argument and return set number of register required in each
|
||||
class. Return zero if parameter should be passed in memory, otherwise
|
||||
the number of registers. */
|
||||
static int
|
||||
examine_argument(
|
||||
ffi_type* type,
|
||||
enum x86_64_reg_class classes[MAX_CLASSES],
|
||||
_Bool in_return,
|
||||
int* pngpr,
|
||||
int* pnsse)
|
||||
{
|
||||
int n = classify_argument(type, classes, 0);
|
||||
int ngpr = 0;
|
||||
int nsse = 0;
|
||||
int i;
|
||||
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
switch (classes[i])
|
||||
{
|
||||
case X86_64_INTEGER_CLASS:
|
||||
case X86_64_INTEGERSI_CLASS:
|
||||
ngpr++;
|
||||
break;
|
||||
|
||||
case X86_64_SSE_CLASS:
|
||||
case X86_64_SSESF_CLASS:
|
||||
case X86_64_SSEDF_CLASS:
|
||||
nsse++;
|
||||
break;
|
||||
|
||||
case X86_64_NO_CLASS:
|
||||
case X86_64_SSEUP_CLASS:
|
||||
break;
|
||||
|
||||
case X86_64_X87_CLASS:
|
||||
case X86_64_X87UP_CLASS:
|
||||
case X86_64_COMPLEX_X87_CLASS:
|
||||
return in_return != 0;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
*pngpr = ngpr;
|
||||
*pnsse = nsse;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(
|
||||
ffi_cif* cif)
|
||||
{
|
||||
int gprcount = 0;
|
||||
int ssecount = 0;
|
||||
int flags = cif->rtype->type;
|
||||
int i, avn, n, ngpr, nsse;
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
size_t bytes;
|
||||
|
||||
if (flags != FFI_TYPE_VOID)
|
||||
{
|
||||
n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
/* The return value is passed in memory. A pointer to that
|
||||
memory is the first argument. Allocate a register for it. */
|
||||
gprcount++;
|
||||
|
||||
/* We don't have to do anything in asm for the return. */
|
||||
flags = FFI_TYPE_VOID;
|
||||
}
|
||||
else if (flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* Mark which registers the result appears in. */
|
||||
_Bool sse0 = SSE_CLASS_P(classes[0]);
|
||||
_Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]);
|
||||
|
||||
if (sse0 && !sse1)
|
||||
flags |= 1 << 8;
|
||||
else if (!sse0 && sse1)
|
||||
flags |= 1 << 9;
|
||||
else if (sse0 && sse1)
|
||||
flags |= 1 << 10;
|
||||
|
||||
/* Mark the true size of the structure. */
|
||||
flags |= cif->rtype->size << 12;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go over all arguments and determine the way they should be passed.
|
||||
If it's in a register and there is space for it, let that be so. If
|
||||
not, add it's size to the stack byte count. */
|
||||
for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
|
||||
{
|
||||
if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
|
||||
|| gprcount + ngpr > MAX_GPR_REGS
|
||||
|| ssecount + nsse > MAX_SSE_REGS)
|
||||
{
|
||||
long align = cif->arg_types[i]->alignment;
|
||||
|
||||
if (align < 8)
|
||||
align = 8;
|
||||
|
||||
bytes = ALIGN(bytes, align);
|
||||
bytes += cif->arg_types[i]->size;
|
||||
}
|
||||
else
|
||||
{
|
||||
gprcount += ngpr;
|
||||
ssecount += nsse;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssecount)
|
||||
flags |= 1 << 11;
|
||||
|
||||
cif->flags = flags;
|
||||
cif->bytes = bytes;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call(
|
||||
ffi_cif* cif,
|
||||
void (*fn)(),
|
||||
void* rvalue,
|
||||
void** avalue)
|
||||
{
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
char* stack;
|
||||
char* argp;
|
||||
ffi_type** arg_types;
|
||||
int gprcount, ssecount, ngpr, nsse, i, avn;
|
||||
_Bool ret_in_memory;
|
||||
RegisterArgs* reg_args;
|
||||
|
||||
/* Can't call 32-bit mode from 64-bit mode. */
|
||||
FFI_ASSERT(cif->abi == FFI_UNIX64);
|
||||
|
||||
/* If the return value is a struct and we don't have a return value
|
||||
address then we need to make one. Note the setting of flags to
|
||||
VOID above in ffi_prep_cif_machdep. */
|
||||
ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& (cif->flags & 0xff) == FFI_TYPE_VOID);
|
||||
|
||||
if (rvalue == NULL && ret_in_memory)
|
||||
rvalue = alloca (cif->rtype->size);
|
||||
|
||||
/* Allocate the space for the arguments, plus 4 words of temp space. */
|
||||
stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8);
|
||||
reg_args = (RegisterArgs*)stack;
|
||||
argp = stack + sizeof(RegisterArgs);
|
||||
|
||||
gprcount = ssecount = 0;
|
||||
|
||||
/* 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;
|
||||
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
for (i = 0; i < avn; ++i)
|
||||
{
|
||||
size_t size = arg_types[i]->size;
|
||||
int n;
|
||||
|
||||
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
|
||||
|
||||
if (n == 0
|
||||
|| gprcount + ngpr > MAX_GPR_REGS
|
||||
|| ssecount + nsse > MAX_SSE_REGS)
|
||||
{
|
||||
long align = arg_types[i]->alignment;
|
||||
|
||||
/* Stack arguments are *always* at least 8 byte aligned. */
|
||||
if (align < 8)
|
||||
align = 8;
|
||||
|
||||
/* Pass this argument in memory. */
|
||||
argp = (void *) ALIGN (argp, align);
|
||||
memcpy (argp, avalue[i], size);
|
||||
argp += size;
|
||||
}
|
||||
else
|
||||
{ /* The argument is passed entirely in registers. */
|
||||
char *a = (char *) avalue[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < n; j++, a += 8, size -= 8)
|
||||
{
|
||||
switch (classes[j])
|
||||
{
|
||||
case X86_64_INTEGER_CLASS:
|
||||
case X86_64_INTEGERSI_CLASS:
|
||||
reg_args->gpr[gprcount] = 0;
|
||||
memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
|
||||
gprcount++;
|
||||
break;
|
||||
|
||||
case X86_64_SSE_CLASS:
|
||||
case X86_64_SSEDF_CLASS:
|
||||
reg_args->sse[ssecount++] = *(UINT64 *) a;
|
||||
break;
|
||||
|
||||
case X86_64_SSESF_CLASS:
|
||||
reg_args->sse[ssecount++] = *(UINT32 *) a;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs),
|
||||
cif->flags, rvalue, fn, ssecount);
|
||||
}
|
||||
|
||||
extern void ffi_closure_unix64(void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure(
|
||||
ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void* user_data)
|
||||
{
|
||||
if (cif->abi != FFI_UNIX64)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
volatile unsigned short* tramp =
|
||||
(volatile unsigned short*)&closure->tramp[0];
|
||||
|
||||
tramp[0] = 0xbb49; /* mov <code>, %r11 */
|
||||
*(void* volatile*)&tramp[1] = ffi_closure_unix64;
|
||||
tramp[5] = 0xba49; /* mov <data>, %r10 */
|
||||
*(void* volatile*)&tramp[6] = closure;
|
||||
|
||||
/* Set the carry bit if the function uses any sse registers.
|
||||
This is clc or stc, together with the first byte of the jmp. */
|
||||
tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
|
||||
tramp[11] = 0xe3ff; /* jmp *%r11 */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_closure_unix64_inner(
|
||||
ffi_closure* closure,
|
||||
void* rvalue,
|
||||
RegisterArgs* reg_args,
|
||||
char* argp)
|
||||
{
|
||||
ffi_cif* cif = closure->cif;
|
||||
void** avalue = alloca(cif->nargs * sizeof(void *));
|
||||
ffi_type** arg_types;
|
||||
long i, avn;
|
||||
int gprcount = 0;
|
||||
int ssecount = 0;
|
||||
int ngpr, nsse;
|
||||
int ret;
|
||||
|
||||
ret = cif->rtype->type;
|
||||
|
||||
if (ret != FFI_TYPE_VOID)
|
||||
{
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
/* 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++];
|
||||
|
||||
/* We don't have to do anything in asm for the return. */
|
||||
ret = FFI_TYPE_VOID;
|
||||
}
|
||||
else if (ret == FFI_TYPE_STRUCT && n == 2)
|
||||
{
|
||||
/* Mark which register the second word of the structure goes in. */
|
||||
_Bool sse0 = SSE_CLASS_P (classes[0]);
|
||||
_Bool sse1 = SSE_CLASS_P (classes[1]);
|
||||
|
||||
if (!sse0 && sse1)
|
||||
ret |= 1 << 8;
|
||||
else if (sse0 && !sse1)
|
||||
ret |= 1 << 9;
|
||||
}
|
||||
}
|
||||
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
for (i = 0; i < avn; ++i)
|
||||
{
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
int n;
|
||||
|
||||
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
|
||||
|
||||
if (n == 0
|
||||
|| gprcount + ngpr > MAX_GPR_REGS
|
||||
|| ssecount + nsse > MAX_SSE_REGS)
|
||||
{
|
||||
long align = arg_types[i]->alignment;
|
||||
|
||||
/* Stack arguments are *always* at least 8 byte aligned. */
|
||||
if (align < 8)
|
||||
align = 8;
|
||||
|
||||
/* Pass this argument in memory. */
|
||||
argp = (void *) ALIGN (argp, align);
|
||||
avalue[i] = argp;
|
||||
argp += arg_types[i]->size;
|
||||
}
|
||||
|
||||
#if !defined(X86_DARWIN)
|
||||
/* If the argument is in a single register, or two consecutive
|
||||
registers, then we can use that address directly. */
|
||||
else if (n == 1 || (n == 2 &&
|
||||
SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
|
||||
{
|
||||
// The argument is in a single register.
|
||||
if (SSE_CLASS_P (classes[0]))
|
||||
{
|
||||
avalue[i] = ®_args->sse[ssecount];
|
||||
ssecount += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = ®_args->gpr[gprcount];
|
||||
gprcount += n;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Otherwise, allocate space to make them consecutive. */
|
||||
else
|
||||
{
|
||||
char *a = alloca (16);
|
||||
int j;
|
||||
|
||||
avalue[i] = a;
|
||||
|
||||
for (j = 0; j < n; j++, a += 8)
|
||||
{
|
||||
if (SSE_CLASS_P (classes[j]))
|
||||
memcpy (a, ®_args->sse[ssecount++], 8);
|
||||
else
|
||||
memcpy (a, ®_args->gpr[gprcount++], 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell assembly how to perform return type promotions. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
|
@ -0,0 +1,569 @@
|
|||
#ifdef __i386__
|
||||
/* -----------------------------------------------------------------------
|
||||
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
|
||||
|
||||
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 CYGNUS SOLUTIONS 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__
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//void ffi_prep_args(char *stack, extended_cif *ecif);
|
||||
|
||||
static inline int
|
||||
retval_on_stack(
|
||||
ffi_type* tp)
|
||||
{
|
||||
if (tp->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
// int size = tp->size;
|
||||
|
||||
if (tp->size > 8)
|
||||
return 1;
|
||||
|
||||
switch (tp->size)
|
||||
{
|
||||
case 1: case 2: case 4: case 8:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_prep_args(char*, extended_cif*);
|
||||
void
|
||||
ffi_prep_args(
|
||||
char* stack,
|
||||
extended_cif* ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void** p_argv = ecif->avalue;
|
||||
register char* argp = stack;
|
||||
register ffi_type** p_arg;
|
||||
|
||||
if (retval_on_stack(ecif->cif->rtype))
|
||||
{
|
||||
*(void**)argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_arg = ecif->cif->arg_types;
|
||||
|
||||
for (i = ecif->cif->nargs; i > 0; i--, p_arg++, p_argv++)
|
||||
{
|
||||
size_t z = (*p_arg)->size;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned)argp)
|
||||
argp = (char*)ALIGN(argp, sizeof(int));
|
||||
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int*)argp = (signed int)*(SINT8*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int*)argp = (unsigned int)*(UINT8*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int*)argp = (signed int)*(SINT16*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int*)argp = (unsigned int)*(UINT16*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(signed int*)argp = (signed int)*(SINT32*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(argp, *p_argv, z);
|
||||
|
||||
argp += z;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(
|
||||
ffi_cif* cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
#if !defined(X86_WIN32) && !defined(X86_DARWIN)
|
||||
case FFI_TYPE_STRUCT:
|
||||
#endif
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
cif->flags = (unsigned)cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
||||
case FFI_TYPE_STRUCT:
|
||||
switch (cif->rtype->size)
|
||||
{
|
||||
case 1:
|
||||
cif->flags = FFI_TYPE_SINT8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
cif->flags = FFI_TYPE_SINT16;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void
|
||||
ffi_call_SYSV(
|
||||
void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif* ,
|
||||
unsigned ,
|
||||
unsigned ,
|
||||
/*@out@*/ unsigned* ,
|
||||
void (*fn)(void));
|
||||
/*@=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)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
void
|
||||
ffi_call(
|
||||
/*@dependent@*/ ffi_cif* cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void* rvalue,
|
||||
/*@dependent@*/ void** avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return
|
||||
value address then we need to make one. */
|
||||
|
||||
if ((rvalue == NULL) && retval_on_stack(cif->rtype))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
/* To avoid changing the assembly code make sure the size of the argument
|
||||
block is a multiple of 16. Then add 8 to compensate for local variables
|
||||
in ffi_call_SYSV. */
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/** private members **/
|
||||
|
||||
static void
|
||||
ffi_closure_SYSV(
|
||||
ffi_closure* closure) __attribute__((regparm(1)));
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
static void
|
||||
ffi_closure_raw_SYSV(
|
||||
ffi_raw_closure* closure) __attribute__((regparm(1)));
|
||||
#endif
|
||||
|
||||
/*@-exportheader@*/
|
||||
static inline
|
||||
void
|
||||
ffi_prep_incoming_args_SYSV(
|
||||
char* stack,
|
||||
void** rvalue,
|
||||
void** avalue,
|
||||
ffi_cif* cif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void** p_argv = avalue;
|
||||
register char* argp = stack;
|
||||
register ffi_type** p_arg;
|
||||
|
||||
if (retval_on_stack(cif->rtype))
|
||||
{
|
||||
*rvalue = *(void**)argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; i > 0; i--, p_arg++, p_argv++)
|
||||
{
|
||||
// size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned)argp)
|
||||
argp = (char*)ALIGN(argp, sizeof(int));
|
||||
|
||||
// z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
*p_argv = (void*)argp;
|
||||
|
||||
argp += (*p_arg)->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
__attribute__((regparm(1)))
|
||||
static void
|
||||
ffi_closure_SYSV(
|
||||
ffi_closure* closure)
|
||||
{
|
||||
long double res;
|
||||
ffi_cif* cif = closure->cif;
|
||||
void** arg_area = (void**)alloca(cif->nargs * sizeof(void*));
|
||||
void* resp = (void*)&res;
|
||||
void* args = __builtin_dwarf_cfa();
|
||||
|
||||
/* 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 reset RESP to point to the
|
||||
structure return address. */
|
||||
ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
|
||||
|
||||
(closure->fun)(cif, resp, arg_area, closure->user_data);
|
||||
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (cif->flags == FFI_TYPE_INT)
|
||||
asm("movl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
else if (cif->flags == FFI_TYPE_FLOAT)
|
||||
asm("flds (%0)"
|
||||
: : "r" (resp) : "st");
|
||||
else if (cif->flags == FFI_TYPE_DOUBLE)
|
||||
asm("fldl (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (cif->flags == FFI_TYPE_LONGDOUBLE)
|
||||
asm("fldt (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (cif->flags == FFI_TYPE_SINT64)
|
||||
asm("movl 0(%0),%%eax;"
|
||||
"movl 4(%0),%%edx"
|
||||
: : "r" (resp)
|
||||
: "eax", "edx");
|
||||
|
||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
||||
else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct */
|
||||
asm("movsbl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
|
||||
asm("movswl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
#endif
|
||||
|
||||
else if (cif->flags == FFI_TYPE_STRUCT)
|
||||
asm("lea -8(%ebp),%esp;"
|
||||
"pop %esi;"
|
||||
"pop %edi;"
|
||||
"pop %ebp;"
|
||||
"ret $4");
|
||||
}
|
||||
|
||||
|
||||
/* 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 - ((unsigned int)__tramp + FFI_TRAMPOLINE_SIZE); \
|
||||
*(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 */ \
|
||||
})
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
ffi_status
|
||||
ffi_prep_closure(
|
||||
ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void* user_data)
|
||||
{
|
||||
// FFI_ASSERT(cif->abi == FFI_SYSV);
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_SYSV, (void*)closure);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* ------- Native raw API support -------------------------------- */
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
__attribute__((regparm(1)))
|
||||
static void
|
||||
ffi_closure_raw_SYSV(
|
||||
ffi_raw_closure* closure)
|
||||
{
|
||||
long double res;
|
||||
ffi_raw* raw_args = (ffi_raw*)__builtin_dwarf_cfa();
|
||||
ffi_cif* cif = closure->cif;
|
||||
unsigned short rtype = cif->flags;
|
||||
void* resp = (void*)&res;
|
||||
|
||||
(closure->fun)(cif, resp, raw_args, closure->user_data);
|
||||
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (rtype == FFI_TYPE_INT)
|
||||
asm("movl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
else if (rtype == FFI_TYPE_FLOAT)
|
||||
asm("flds (%0)"
|
||||
: : "r" (resp) : "st");
|
||||
else if (rtype == FFI_TYPE_DOUBLE)
|
||||
asm("fldl (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (rtype == FFI_TYPE_LONGDOUBLE)
|
||||
asm("fldt (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (rtype == FFI_TYPE_SINT64)
|
||||
asm("movl 0(%0),%%eax;"
|
||||
"movl 4(%0),%%edx"
|
||||
: : "r" (resp) : "eax", "edx");
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure(
|
||||
ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void* user_data)
|
||||
{
|
||||
// FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
int i;
|
||||
|
||||
/* We currently don't support certain kinds of arguments for raw
|
||||
closures. This should be implemented by a separate assembly language
|
||||
routine, since it would require argument processing, something we
|
||||
don't do now for performance. */
|
||||
for (i = cif->nargs - 1; i >= 0; i--)
|
||||
{
|
||||
FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||
FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_raw_SYSV, (void*)closure);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_args_raw(
|
||||
char* stack,
|
||||
extended_cif* ecif)
|
||||
{
|
||||
memcpy(stack, ecif->avalue, ecif->cif->bytes);
|
||||
}
|
||||
|
||||
/* We borrow this routine from libffi (it must be changed, though, to
|
||||
actually call the function passed in the first argument. as of
|
||||
libffi-1.20, this is not the case.) */
|
||||
//extern void
|
||||
//ffi_call_SYSV(
|
||||
// void (*)(char *, extended_cif *),
|
||||
///*@out@*/ extended_cif* ,
|
||||
// unsigned ,
|
||||
// unsigned ,
|
||||
//*@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)(),
|
||||
/*@out@*/ void* rvalue,
|
||||
/*@dependent@*/ ffi_raw* fake_avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
void **avalue = (void **)fake_avalue;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return
|
||||
value address then we need to make one */
|
||||
if ((rvalue == NULL) && retval_on_stack(cif->rtype))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !FFI_NO_RAW_API
|
||||
//#endif // !__x86_64__
|
||||
#endif // __i386__
|
|
@ -1,5 +1,5 @@
|
|||
#! /bin/sh
|
||||
# From configure.in Revision: 60536 .
|
||||
# From configure.in Revision: 60765 .
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.61 for python 2.6.
|
||||
#
|
||||
|
@ -13223,138 +13223,6 @@ fi
|
|||
|
||||
|
||||
# Check for use of the system libffi library
|
||||
if test "${ac_cv_header_ffi_h+set}" = set; then
|
||||
{ echo "$as_me:$LINENO: checking for ffi.h" >&5
|
||||
echo $ECHO_N "checking for ffi.h... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_header_ffi_h+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_header_ffi_h" >&5
|
||||
echo "${ECHO_T}$ac_cv_header_ffi_h" >&6; }
|
||||
else
|
||||
# Is the header compilable?
|
||||
{ echo "$as_me:$LINENO: checking ffi.h usability" >&5
|
||||
echo $ECHO_N "checking ffi.h usability... $ECHO_C" >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
#include <ffi.h>
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
ac_header_compiler=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_compiler=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
|
||||
echo "${ECHO_T}$ac_header_compiler" >&6; }
|
||||
|
||||
# Is the header present?
|
||||
{ echo "$as_me:$LINENO: checking ffi.h presence" >&5
|
||||
echo $ECHO_N "checking ffi.h presence... $ECHO_C" >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <ffi.h>
|
||||
_ACEOF
|
||||
if { (ac_try="$ac_cpp conftest.$ac_ext"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } >/dev/null && {
|
||||
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
}; then
|
||||
ac_header_preproc=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_preproc=no
|
||||
fi
|
||||
|
||||
rm -f conftest.err conftest.$ac_ext
|
||||
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
|
||||
echo "${ECHO_T}$ac_header_preproc" >&6; }
|
||||
|
||||
# So? What about this header?
|
||||
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
|
||||
yes:no: )
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||
echo "$as_me: WARNING: ffi.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: proceeding with the compiler's result" >&5
|
||||
echo "$as_me: WARNING: ffi.h: proceeding with the compiler's result" >&2;}
|
||||
ac_header_preproc=yes
|
||||
;;
|
||||
no:yes:* )
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: present but cannot be compiled" >&5
|
||||
echo "$as_me: WARNING: ffi.h: present but cannot be compiled" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: check for missing prerequisite headers?" >&5
|
||||
echo "$as_me: WARNING: ffi.h: check for missing prerequisite headers?" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: see the Autoconf documentation" >&5
|
||||
echo "$as_me: WARNING: ffi.h: see the Autoconf documentation" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: section \"Present But Cannot Be Compiled\"" >&5
|
||||
echo "$as_me: WARNING: ffi.h: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: proceeding with the preprocessor's result" >&5
|
||||
echo "$as_me: WARNING: ffi.h: proceeding with the preprocessor's result" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: ffi.h: in the future, the compiler will take precedence" >&5
|
||||
echo "$as_me: WARNING: ffi.h: in the future, the compiler will take precedence" >&2;}
|
||||
( cat <<\_ASBOX
|
||||
## ------------------------------------------------ ##
|
||||
## Report this to http://www.python.org/python-bugs ##
|
||||
## ------------------------------------------------ ##
|
||||
_ASBOX
|
||||
) | sed "s/^/$as_me: WARNING: /" >&2
|
||||
;;
|
||||
esac
|
||||
{ echo "$as_me:$LINENO: checking for ffi.h" >&5
|
||||
echo $ECHO_N "checking for ffi.h... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_header_ffi_h+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_cv_header_ffi_h=$ac_header_preproc
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_header_ffi_h" >&5
|
||||
echo "${ECHO_T}$ac_cv_header_ffi_h" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for --with-system-ffi" >&5
|
||||
echo $ECHO_N "checking for --with-system-ffi... $ECHO_C" >&6; }
|
||||
|
||||
|
@ -13364,15 +13232,6 @@ if test "${with_system_ffi+set}" = set; then
|
|||
fi
|
||||
|
||||
|
||||
if test -z "$with_system_ffi" && test "$ac_cv_header_ffi_h" = yes; then
|
||||
case "$ac_sys_system/`uname -m`" in
|
||||
Linux/alpha*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
Linux/arm*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
Linux/ppc*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
Linux/s390*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
*) with_system_ffi="no"
|
||||
esac
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $with_system_ffi" >&5
|
||||
echo "${ECHO_T}$with_system_ffi" >&6; }
|
||||
|
||||
|
|
10
configure.in
10
configure.in
|
@ -1754,20 +1754,10 @@ LIBS="$withval $LIBS"
|
|||
[AC_MSG_RESULT(no)])
|
||||
|
||||
# Check for use of the system libffi library
|
||||
AC_CHECK_HEADER(ffi.h)
|
||||
AC_MSG_CHECKING(for --with-system-ffi)
|
||||
AC_ARG_WITH(system_ffi,
|
||||
AC_HELP_STRING(--with-system-ffi, build _ctypes module using an installed ffi library))
|
||||
|
||||
if test -z "$with_system_ffi" && test "$ac_cv_header_ffi_h" = yes; then
|
||||
case "$ac_sys_system/`uname -m`" in
|
||||
Linux/alpha*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
Linux/arm*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
Linux/ppc*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
Linux/s390*) with_system_ffi="yes"; CONFIG_ARGS="$CONFIG_ARGS --with-system-ffi";;
|
||||
*) with_system_ffi="no"
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($with_system_ffi)
|
||||
|
||||
# Determine if signalmodule should be used.
|
||||
|
|
35
setup.py
35
setup.py
|
@ -1455,8 +1455,37 @@ class PyBuildExt(build_ext):
|
|||
# *** Uncomment these for TOGL extension only:
|
||||
# -lGL -lGLU -lXext -lXmu \
|
||||
|
||||
def configure_ctypes_darwin(self, ext):
|
||||
# Darwin (OS X) uses preconfigured files, in
|
||||
# the Modules/_ctypes/libffi_osx directory.
|
||||
(srcdir,) = sysconfig.get_config_vars('srcdir')
|
||||
ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
|
||||
'_ctypes', 'libffi_osx'))
|
||||
sources = [os.path.join(ffi_srcdir, p)
|
||||
for p in ['ffi.c',
|
||||
'x86/x86-darwin.S',
|
||||
'x86/x86-ffi_darwin.c',
|
||||
'x86/x86-ffi64.c',
|
||||
'powerpc/ppc-darwin.S',
|
||||
'powerpc/ppc-darwin_closure.S',
|
||||
'powerpc/ppc-ffi_darwin.c',
|
||||
'powerpc/ppc64-darwin_closure.S',
|
||||
]]
|
||||
|
||||
# Add .S (preprocessed assembly) to C compiler source extensions.
|
||||
self.compiler.src_extensions.append('.S')
|
||||
|
||||
include_dirs = [os.path.join(ffi_srcdir, 'include'),
|
||||
os.path.join(ffi_srcdir, 'powerpc')]
|
||||
ext.include_dirs.extend(include_dirs)
|
||||
ext.sources.extend(sources)
|
||||
return True
|
||||
|
||||
def configure_ctypes(self, ext):
|
||||
if not self.use_system_libffi:
|
||||
if sys.platform == 'darwin':
|
||||
return self.configure_ctypes_darwin(ext)
|
||||
|
||||
(srcdir,) = sysconfig.get_config_vars('srcdir')
|
||||
ffi_builddir = os.path.join(self.build_temp, 'libffi')
|
||||
ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
|
||||
|
@ -1515,6 +1544,7 @@ class PyBuildExt(build_ext):
|
|||
|
||||
if sys.platform == 'darwin':
|
||||
sources.append('_ctypes/darwin/dlfcn_simple.c')
|
||||
extra_compile_args.append('-DMACOSX')
|
||||
include_dirs.append('_ctypes/darwin')
|
||||
# XXX Is this still needed?
|
||||
## extra_link_args.extend(['-read_only_relocs', 'warning'])
|
||||
|
@ -1544,6 +1574,11 @@ class PyBuildExt(build_ext):
|
|||
if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
|
||||
return
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
# OS X 10.5 comes with libffi.dylib; the include files are
|
||||
# in /usr/include/ffi
|
||||
inc_dirs.append('/usr/include/ffi')
|
||||
|
||||
ffi_inc = find_file('ffi.h', [], inc_dirs)
|
||||
if ffi_inc is not None:
|
||||
ffi_h = ffi_inc[0] + '/ffi.h'
|
||||
|
|
Loading…
Reference in New Issue