ctypes-commit Mailing List for ctypes (Page 104)
Brought to you by:
theller
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
(8) |
May
(90) |
Jun
(143) |
Jul
(106) |
Aug
(94) |
Sep
(84) |
Oct
(163) |
Nov
(60) |
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(128) |
Feb
(79) |
Mar
(227) |
Apr
(192) |
May
(179) |
Jun
(41) |
Jul
(53) |
Aug
(103) |
Sep
(28) |
Oct
(38) |
Nov
(81) |
Dec
(17) |
2006 |
Jan
(184) |
Feb
(111) |
Mar
(188) |
Apr
(67) |
May
(58) |
Jun
(123) |
Jul
(73) |
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
From: Thomas H. <th...@us...> - 2004-06-23 16:19:53
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6415 Modified Files: _ctypes_test.c Log Message: No need to include ffi.h in _ctypes_test.c. Index: _ctypes_test.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes_test.c,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** _ctypes_test.c 22 Jun 2004 12:31:49 -0000 1.19 --- _ctypes_test.c 23 Jun 2004 16:19:43 -0000 1.20 *************** *** 1,5 **** #include <Python.h> - #include <ffi.h> - #include "ctypes.h" #ifdef MS_WIN32 --- 1,3 ---- *************** *** 7,51 **** #endif - /* Although this is compiled as a Python extension module, it's not really - one. But this is the easiest way to create a shared library. - - This library exports functions for testing _ctypes. - */ - - PyObject *my_debug(PyObject *self, CDataObject *arg) - { - #ifdef MS_WIN32 - DISPPARAMS *dp; - VARIANT *va; - OLECHAR FAR * FAR *p; - FUNCDESC *f = (FUNCDESC *)(arg->b_ptr); - - ELEMDESC *pelemdesc = *(ELEMDESC **)arg->b_ptr; - int *pi; - char *cp; - char **cpp; - IUnknown *pIunk = *(IUnknown **)(arg->b_ptr); - IDispatch *pIDisp = (IDispatch *)(arg->b_ptr); - dp = (DISPPARAMS *)arg->b_ptr; - va = (VARIANT *)arg->b_ptr; - p = (OLECHAR FAR * FAR *)arg->b_ptr; - pi = (int *)arg->b_ptr; - cp = arg->b_ptr; - cpp = (char **)arg->b_ptr; - #ifdef _DEBUG - _asm int 3; - /* - Py_BEGIN_ALLOW_THREADS - x = pIunk->lpVtbl->AddRef(pIunk); - x = pIunk->lpVtbl->Release(pIunk); - Py_END_ALLOW_THREADS - */ - #endif - #endif - Py_INCREF(Py_None); - return Py_None; - } - - #ifdef MS_WIN32 #define EXPORT(x) __declspec(dllexport) x --- 5,8 ---- *************** *** 306,312 **** {"func_si", py_func_si, METH_VARARGS}, {"func", py_func, METH_NOARGS}, - #ifdef _DEBUG - {"my_debug", my_debug, METH_O}, - #endif { NULL, NULL, 0, NULL}, }; --- 263,266 ---- |
From: Thomas H. <th...@us...> - 2004-06-23 15:22:24
|
Update of /cvsroot/ctypes/ctypes/source/gcc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26087 Added Files: config.if move-if-change Log Message: Add missing files. --- NEW FILE: move-if-change --- #!/bin/sh # Copyright (C) 1996 Free Software Foundation, Inc. # # 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 of the License, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. if test -r $2 then if cmp $1 $2 > /dev/null then echo $2 is unchanged rm -f $1 else mv -f $1 $2 fi else mv -f $1 $2 fi --- NEW FILE: config.if --- #! /dev/null # Don't call it directly. This shell script fragment is called to # determine: # # 1. libstcxx_incdir: the interface name for libstdc++. # # Get the top level src dir. if [ -z "${topsrcdir}" -a -z "${top_srcdir}" ] then echo "Undefined top level src dir: topsrcdir and top_srcdir are empty" >&2 exit 1 fi if [ -n "${topsrcdir}" ] then if_topsrcdir=${topsrcdir} else if_topsrcdir=${top_srcdir} fi # Set libstdcxx_incdir. # This is the same as gcc/configure.in and libstdc++-v3/acinclude.m4. if test -z "$gcc_version"; then if test -z "${gcc_version_trigger}" \ && test -f ${if_topsrcdir}/gcc/version.c; then gcc_version_trigger=${if_topsrcdir}/gcc/version.c fi if test -f "${gcc_version_trigger}"; then gcc_version_full=`grep version_string "${gcc_version_trigger}" | sed -e 's/.*"\([^"]*\)".*/\1/'` else gcc_version_full=`$CC -v 2>&1 | sed -n 's/^gcc version //p'` fi gcc_version=`echo ${gcc_version_full} | sed -e 's/\([^ ]*\) .*/\1/'` fi libstdcxx_incdir=c++/${gcc_version} |
From: Thomas H. <th...@us...> - 2004-06-22 12:32:32
|
Update of /cvsroot/ctypes/ctypes/unittests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26261 Modified Files: test_cfuncs.py Log Message: Tests for functions with void result. Index: test_cfuncs.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/unittests/test_cfuncs.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** test_cfuncs.py 11 Jun 2004 09:08:55 -0000 1.9 --- test_cfuncs.py 22 Jun 2004 12:32:22 -0000 1.10 *************** *** 102,105 **** --- 102,111 ---- self.failUnlessEqual(self.dll.tf_i(-42), -84) + def test_void(self): + self.dll.tv_i.restype = None + self.dll.tv_i.argtypes = (c_int,) + self.failUnlessEqual(self.dll.tv_i(42), None) + self.failUnlessEqual(self.dll.tv_i(-42), None) + # The following repeates the above tests with stdcall functions (where # they are available) |
From: Thomas H. <th...@us...> - 2004-06-22 12:31:58
|
Update of /cvsroot/ctypes/ctypes/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25848 Modified Files: _ctypes_test.c Log Message: New test functions with void result. Index: _ctypes_test.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes_test.c,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** _ctypes_test.c 25 May 2004 09:33:21 -0000 1.18 --- _ctypes_test.c 22 Jun 2004 12:31:49 -0000 1.19 *************** *** 353,356 **** --- 353,357 ---- EXPORT(float) tf_bf(char x, float c) { return c; } EXPORT(double) tf_bd(char x, double c) { return c; } + EXPORT(void) tv_i(int i) { return; } #ifdef MS_WIN32 *************** *** 367,370 **** --- 368,372 ---- EXPORT(float) __stdcall s_tf_bf(char x, float c) { return c; } EXPORT(double) __stdcall s_tf_bd(char x, double c) { return c; } + EXPORT(void) __stdcall s_tv_i(int i) { return; } #endif |
From: Thomas H. <th...@us...> - 2004-06-22 10:14:25
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/testsuite In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24084/gcc/libffi/testsuite Added Files: Makefile.am Makefile.in Log Message: Added from gcc cvs. --- NEW FILE: Makefile.in --- # Makefile.in generated by automake 1.8.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004 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@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ 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 = testsuite DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../config/accross.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 = SOURCES = DIST_SOURCES = DEJATOOL = $(PACKAGE) RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ ALPHA_FALSE = @ALPHA_FALSE@ ALPHA_TRUE = @ALPHA_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AM_RUNTESTFLAGS = ARM_FALSE = @ARM_FALSE@ ARM_TRUE = @ARM_TRUE@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@ IA64_FALSE = @IA64_FALSE@ IA64_TRUE = @IA64_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ M68K_FALSE = @M68K_FALSE@ M68K_TRUE = @M68K_TRUE@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MIPS_IRIX_FALSE = @MIPS_IRIX_FALSE@ MIPS_IRIX_TRUE = @MIPS_IRIX_TRUE@ MIPS_LINUX_FALSE = @MIPS_LINUX_FALSE@ MIPS_LINUX_TRUE = @MIPS_LINUX_TRUE@ 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@ PA_FALSE = @PA_FALSE@ PA_TRUE = @PA_TRUE@ POWERPC_AIX_FALSE = @POWERPC_AIX_FALSE@ POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@ POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@ POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@ POWERPC_FALSE = @POWERPC_FALSE@ POWERPC_TRUE = @POWERPC_TRUE@ RANLIB = @RANLIB@ S390_FALSE = @S390_FALSE@ S390_TRUE = @S390_TRUE@ SET_MAKE = @SET_MAKE@ SH64_FALSE = @SH64_FALSE@ SH64_TRUE = @SH64_TRUE@ SHELL = @SHELL@ SH_FALSE = @SH_FALSE@ SH_TRUE = @SH_TRUE@ SPARC_FALSE = @SPARC_FALSE@ SPARC_TRUE = @SPARC_TRUE@ STRIP = @STRIP@ TARGET = @TARGET@ TARGETDIR = @TARGETDIR@ TESTSUBDIR_FALSE = @TESTSUBDIR_FALSE@ TESTSUBDIR_TRUE = @TESTSUBDIR_TRUE@ VERSION = @VERSION@ X86_64_FALSE = @X86_64_FALSE@ X86_64_TRUE = @X86_64_TRUE@ X86_FALSE = @X86_FALSE@ X86_TRUE = @X86_TRUE@ X86_WIN32_FALSE = @X86_WIN32_FALSE@ X86_WIN32_TRUE = @X86_WIN32_TRUE@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ gcc_version = @gcc_version@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ multi_basedir = @multi_basedir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ tool_include_dir = @tool_include_dir@ toolexecdir = @toolexecdir@ toolexeclibdir = @toolexeclibdir@ AUTOMAKE_OPTIONS = foreign dejagnu # Setup the testing framework, if you have one EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \ echo $(top_builddir)/../expect/expect ; \ else echo expect ; fi` RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \ echo $(top_srcdir)/../dejagnu/runtest ; \ else echo runtest; fi` CLEANFILES = *.exe core* *.log *.sum 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 testsuite/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign testsuite/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 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: check-DEJAGNU: site.exp srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \ EXPECT=$(EXPECT); export EXPECT; \ runtest=$(RUNTEST); \ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \ l='$(DEJATOOL)'; for tool in $$l; do \ $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \ done; \ else echo "WARNING: could not find \`runtest'" 1>&2; :;\ fi site.exp: Makefile @echo 'Making a new site.exp file...' @echo '## these variables are automatically generated by make ##' >site.tmp @echo '# Do not edit here. If you wish to override these values' >>site.tmp @echo '# edit the last section' >>site.tmp @echo 'set srcdir $(srcdir)' >>site.tmp @echo "set objdir `pwd`" >>site.tmp @echo 'set build_alias "$(build_alias)"' >>site.tmp @echo 'set build_triplet $(build_triplet)' >>site.tmp @echo 'set host_alias "$(host_alias)"' >>site.tmp @echo 'set host_triplet $(host_triplet)' >>site.tmp @echo 'set target_alias "$(target_alias)"' >>site.tmp @echo 'set target_triplet $(target_triplet)' >>site.tmp @echo '## All variables above are generated by configure. Do Not Edit ##' >>site.tmp @test ! -f site.exp || \ sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp @-rm -f site.bak @test ! -f site.exp || mv site.exp site.bak @mv site.tmp site.exp distclean-DEJAGNU: -rm -f site.exp site.bak -l='$(DEJATOOL)'; for tool in $$l; do \ rm -f $$tool.sum $$tool.log; \ done distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ 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 $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU check: check-am all-am: Makefile installdirs: 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: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -rm -f $(CONFIG_CLEAN_FILES) 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-DEJAGNU distclean-generic \ distclean-libtool dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: 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-info-am .PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \ clean-libtool distclean distclean-DEJAGNU distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ uninstall uninstall-am uninstall-info-am # 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: --- NEW FILE: Makefile.am --- ## Process this file with automake to produce Makefile.in. AUTOMAKE_OPTIONS = foreign dejagnu # Setup the testing framework, if you have one EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \ echo $(top_builddir)/../expect/expect ; \ else echo expect ; fi` RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \ echo $(top_srcdir)/../dejagnu/runtest ; \ else echo runtest; fi` AM_RUNTESTFLAGS = CLEANFILES = *.exe core* *.log *.sum |
From: Thomas H. <th...@us...> - 2004-06-22 09:54:40
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10673 Modified Files: setup.py Log Message: libffi source directory. Index: setup.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/setup.py,v retrieving revision 1.67 retrieving revision 1.68 diff -C2 -d -r1.67 -r1.68 *** setup.py 22 Jun 2004 09:08:16 -0000 1.67 --- setup.py 22 Jun 2004 09:54:27 -0000 1.68 *************** *** 12,16 **** # XXX explain LIBFFI_SOURCES ##LIBFFI_SOURCES='libffi-src' ! LIBFFI_SOURCES='../libffi' ################################################################ --- 12,16 ---- # XXX explain LIBFFI_SOURCES ##LIBFFI_SOURCES='libffi-src' ! LIBFFI_SOURCES='source/gcc/libffi' ################################################################ *************** *** 193,196 **** --- 193,198 ---- elif case.endswith("ERROR"): sys.stderr.write("E") + else: + sys.stderr.write("?") stop_time = time.time() *************** *** 237,240 **** --- 239,244 ---- elif line.endswith("ERROR"): self.errors += 1 + else: #? + self.errors += 1 elif line == "=" * 70: # failure or error |
From: Thomas H. <th...@us...> - 2004-06-22 09:08:26
|
Update of /cvsroot/ctypes/ctypes In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9227 Modified Files: setup.py Log Message: Run tests in separate processes. Index: setup.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/setup.py,v retrieving revision 1.66 retrieving revision 1.67 diff -C2 -d -r1.66 -r1.67 *** setup.py 18 Jun 2004 13:12:00 -0000 1.66 --- setup.py 22 Jun 2004 09:08:16 -0000 1.67 *************** *** 107,110 **** --- 107,113 ---- LIBFFI_SOURCES=None + if sys.platform == 'win32': + LIBFFI_SOURCES=None + ################################################################ *************** *** 164,173 **** # finalize_options() - def run(self): ! ! import glob, unittest ! # Invoke the 'build' command to "build" pure Python modules ! # (ie. copy 'em into the build tree) self.run_command('build') --- 167,172 ---- # finalize_options() def run(self): ! import glob, unittest, time self.run_command('build') *************** *** 175,217 **** test_files = [os.path.basename(f) for f in glob.glob(mask)] - # remember old sys.path to restore it afterwards - old_path = sys.path[:] - - # extend sys.path - sys.path.insert(0, self.build_purelib) - sys.path.insert(0, self.build_platlib) - sys.path.insert(0, self.test_dir) - self.announce("testing") ! # Import all test modules, collect unittest.TestCase classes, ! # and build a TestSuite from them. ! test_suites = [] ! for f in test_files: ! modname = os.path.splitext(f)[0] ! try: ! mod = __import__(modname) ! except Exception, detail: ! self.warn("Could not import %s (%s)" % (modname, detail)) ! continue ! for name in dir(mod): ! if name.startswith("_"): ! continue ! o = getattr(mod, name) ! if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase): ! test_suites.append(unittest.makeSuite(o)) ! if test_suites: ! self.announce("running unittests") ! runner = unittest.TextTestRunner(verbosity=self.verbosity) ! suite = unittest.TestSuite(test_suites) ! runner.run(suite) ! # restore sys.path ! sys.path = old_path[:] # run() # class test --- 174,260 ---- test_files = [os.path.basename(f) for f in glob.glob(mask)] self.announce("testing") ! self.testcases = [] ! self.ok = self.fail = self.errors = 0 ! self.tracebacks = [] ! start_time = time.time() ! for t in test_files: ! testcases = self.run_test(os.path.join(self.test_dir, t)) ! for case in testcases: ! if self.verbosity > 1: ! print >> sys.stderr, case ! elif self.verbosity == 1: ! if case.endswith("ok"): ! sys.stderr.write(".") ! elif case.endswith("FAIL"): ! sys.stderr.write("F") ! elif case.endswith("ERROR"): ! sys.stderr.write("E") ! stop_time = time.time() ! print >> sys.stderr ! for f in self.tracebacks: ! print >> sys.stderr, "=" * 42 ! print >> sys.stderr, f[0] ! print >> sys.stderr, "-" * 42 ! print >> sys.stderr, "\n".join(f[1:]) ! print >> sys.stderr ! print >> sys.stderr, "-" * 70 ! print >> sys.stderr, "Ran %d tests in %.3fs" % (len(self.testcases), stop_time - start_time) ! print >> sys.stderr ! if self.fail + self.errors == 0: ! print >> sys.stderr, "OK" ! else: ! if self.errors: ! print >> sys.stderr, "FAILED (failures=%d, errors=%d)" % (self.fail, self.errors) ! else: ! print >> sys.stderr, "FAILED (failures=%d)" % self.fail # run() + def run_test(self, path): + # Run a test file in a separate process, and parse the output. + # Collect the results in the ok, fail, error, testcases and + # tracebacks instance vars. + # A sequence of testcase names together with their outcome is returned. + i, o = os.popen4("%s %s -v" % (sys.executable, path)) + i.close() + cases = [] + while 1: + line = o.readline() + if not line: + break + line = line.rstrip() + if line.startswith('test'): + cases.append(line) + if line.endswith("ok"): + self.ok += 1 + elif line.endswith("FAIL"): + self.fail += 1 + elif line.endswith("ERROR"): + self.errors += 1 + elif line == "=" * 70: + # failure or error + name = o.readline().rstrip() + assert o.readline().rstrip() == "-" * 70 + tb = [name] + while 1: + data = o.readline() + if not data.rstrip(): + break + tb.append(data.rstrip()) + self.tracebacks.append(tb) + elif line.rstrip() == '-' * 70: + pass + elif line.startswith("Ran "): + pass + ## else: + ## print line + self.testcases.extend(cases) + return cases + # class test |
From: Thomas H. <th...@us...> - 2004-06-22 08:59:59
|
Update of /cvsroot/ctypes/ctypes/unittests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4287 Modified Files: test_win32.py Log Message: Index: test_win32.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/unittests/test_win32.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** test_win32.py 18 May 2004 12:03:56 -0000 1.6 --- test_win32.py 22 Jun 2004 08:59:50 -0000 1.7 *************** *** 30,35 **** def test_SEH(self): ! """Call functions with invalid arguments, and make sure that access violations ! are trapped and raise an exception""" # Normally, in a debug build of the _ctypes extension # module, exceptions are not trapped, so we can only run --- 30,36 ---- def test_SEH(self): ! # Call functions with invalid arguments, and make sure that access violations ! # are trapped and raise an exception. ! # # Normally, in a debug build of the _ctypes extension # module, exceptions are not trapped, so we can only run |
From: Thomas H. <th...@us...> - 2004-06-21 11:31:12
|
Update of /cvsroot/ctypes/ctypes/unittests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18849 Modified Files: test_callbacks.py Log Message: Refactored. Index: test_callbacks.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/unittests/test_callbacks.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** test_callbacks.py 27 May 2004 16:42:11 -0000 1.17 --- test_callbacks.py 21 Jun 2004 11:31:00 -0000 1.18 *************** *** 11,19 **** def check_type(self, typ, arg): PROTO = self.functype.im_func(typ, typ) ! return PROTO(self.callback)(arg) - def check_type_1(self, typ, arg): PROTO = self.functype.im_func(typ, c_byte, typ) ! return PROTO(self.callback)(-3, arg) if not hasattr(unittest.TestCase, "failUnlessAlmostEqual"): --- 11,28 ---- def check_type(self, typ, arg): PROTO = self.functype.im_func(typ, typ) ! result = PROTO(self.callback)(arg) ! if typ == c_float: ! self.failUnlessAlmostEqual(result, arg, places=5) ! else: ! self.failUnlessEqual(self.got_args, (arg,)) ! self.failUnlessEqual(result, arg) PROTO = self.functype.im_func(typ, c_byte, typ) ! result = PROTO(self.callback)(-3, arg) ! if typ == c_float: ! self.failUnlessAlmostEqual(result, arg, places=5) ! else: ! self.failUnlessEqual(self.got_args, (-3, arg)) ! self.failUnlessEqual(result, arg) if not hasattr(unittest.TestCase, "failUnlessAlmostEqual"): *************** *** 35,124 **** def test_byte(self): ! self.failUnlessEqual(self.check_type(c_byte, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_byte, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_ubyte(self): ! self.failUnlessEqual(self.check_type(c_ubyte, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_ubyte, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_short(self): ! self.failUnlessEqual(self.check_type(c_short, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_short, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_ushort(self): ! self.failUnlessEqual(self.check_type(c_ushort, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_ushort, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_int(self): ! self.failUnlessEqual(self.check_type(c_int, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_int, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_uint(self): ! self.failUnlessEqual(self.check_type(c_uint, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_uint, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_long(self): ! self.failUnlessEqual(self.check_type(c_long, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_long, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_ulong(self): ! self.failUnlessEqual(self.check_type(c_ulong, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_ulong, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_longlong(self): ! self.failUnlessEqual(self.check_type(c_longlong, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_longlong, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_ulonglong(self): ! self.failUnlessEqual(self.check_type(c_ulonglong, 42), 42) ! self.failUnlessEqual(self.got_args, (42,)) ! self.failUnlessEqual(self.check_type_1(c_ulonglong, 42), 42) ! self.failUnlessEqual(self.got_args, (-3, 42)) def test_float(self): # only almost equal: double -> float -> double import math ! self.failUnlessAlmostEqual(self.check_type(c_float, math.e), math.e, ! places=6) ! self.failUnlessAlmostEqual(self.got_args[0], math.e, places=6) ! self.failUnlessAlmostEqual(self.check_type_1(c_float, math.e), math.e, ! places=6) ! self.failUnlessAlmostEqual(self.got_args[1], math.e, places=6) def test_double(self): ! self.failUnlessEqual(self.check_type(c_double, 3.14), 3.14) ! self.failUnlessEqual(self.got_args, (3.14,)) ! self.failUnlessEqual(self.check_type_1(c_double, 3.14), 3.14) ! self.failUnlessEqual(self.got_args, (-3, 3.14)) def test_char(self): ! self.failUnlessEqual(self.check_type(c_char, "x"), "x") ! self.failUnlessEqual(self.got_args, ("x",)) ! self.failUnlessEqual(self.check_type_1(c_char, "x"), "x") ! self.failUnlessEqual(self.got_args, (-3, "x")) def test_char_p(self): ! self.failUnlessEqual(self.check_type(c_char_p, "abc"), "abc") ! self.failUnlessEqual(self.got_args, ("abc",)) ! self.failUnlessEqual(self.check_type_1(c_char_p, "abc"), "abc") ! self.failUnlessEqual(self.got_args, (-3, "abc")) try: --- 44,98 ---- def test_byte(self): ! self.check_type(c_byte, 42) ! self.check_type(c_byte, -42) def test_ubyte(self): ! self.check_type(c_ubyte, 42) def test_short(self): ! self.check_type(c_short, 42) ! self.check_type(c_short, -42) def test_ushort(self): ! self.check_type(c_ushort, 42) def test_int(self): ! self.check_type(c_int, 42) ! self.check_type(c_int, -42) def test_uint(self): ! self.check_type(c_uint, 42) def test_long(self): ! self.check_type(c_long, 42) ! self.check_type(c_long, -42) def test_ulong(self): ! self.check_type(c_ulong, 42) def test_longlong(self): ! self.check_type(c_longlong, 42) ! self.check_type(c_longlong, -42) def test_ulonglong(self): ! self.check_type(c_ulonglong, 42) def test_float(self): # only almost equal: double -> float -> double import math ! self.check_type(c_float, math.e) ! self.check_type(c_float, -math.e) def test_double(self): ! self.check_type(c_double, 3.14) ! self.check_type(c_double, -3.14) def test_char(self): ! self.check_type(c_char, "x") ! self.check_type(c_char, "a") def test_char_p(self): ! self.check_type(c_char_p, "abc") ! self.check_type(c_char_p, "def") try: |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:26
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/sparc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/sparc Added Files: ffi.c ffitarget.h v8.S v9.S Log Message: Importing libffi sources and build tools. --- NEW FILE: v9.S --- /* ----------------------------------------------------------------------- v9.S - Copyright (c) 2000, 2003, 2004 Red Hat, Inc. SPARC 64-bit 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #ifdef SPARC64 /* Only compile this in for 64bit builds, because otherwise the object file will have inproper architecture due to used instructions. */ #define STACKFRAME 128 /* Minimum stack framesize for SPARC */ #define STACK_BIAS 2047 #define ARGS (128) /* Offset of register area in frame */ .text .align 8 .globl ffi_call_v9 .globl _ffi_call_v9 ffi_call_v9: _ffi_call_v9: .LLFB1: save %sp, -STACKFRAME, %sp .LLCFI0: sub %sp, %i2, %sp ! alloca() space in stack for frame to set up add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of ! frame to set up mov %l0, %o0 ! call routine to set up frame call %i0 mov %i1, %o1 ! (delay) brz,pt %o0, 1f ldx [%l0+ARGS], %o0 ! call foreign function ldd [%l0+ARGS], %f0 ldd [%l0+ARGS+8], %f2 ldd [%l0+ARGS+16], %f4 ldd [%l0+ARGS+24], %f6 ldd [%l0+ARGS+32], %f8 ldd [%l0+ARGS+40], %f10 ldd [%l0+ARGS+48], %f12 ldd [%l0+ARGS+56], %f14 ldd [%l0+ARGS+64], %f16 ldd [%l0+ARGS+72], %f18 ldd [%l0+ARGS+80], %f20 ldd [%l0+ARGS+88], %f22 ldd [%l0+ARGS+96], %f24 ldd [%l0+ARGS+104], %f26 ldd [%l0+ARGS+112], %f28 ldd [%l0+ARGS+120], %f30 1: ldx [%l0+ARGS+8], %o1 ldx [%l0+ARGS+16], %o2 ldx [%l0+ARGS+24], %o3 ldx [%l0+ARGS+32], %o4 ldx [%l0+ARGS+40], %o5 call %i5 sub %l0, STACK_BIAS, %sp ! (delay) switch to frame ! If the return value pointer is NULL, assume no return value. brz,pn %i4, done nop cmp %i3, FFI_TYPE_INT be,a,pt %icc, done stx %o0, [%i4+0] ! (delay) cmp %i3, FFI_TYPE_FLOAT be,a,pn %icc, done st %f0, [%i4+0] ! (delay) cmp %i3, FFI_TYPE_DOUBLE be,a,pn %icc, done std %f0, [%i4+0] ! (delay) cmp %i3, FFI_TYPE_STRUCT be,pn %icc, dostruct cmp %i3, FFI_TYPE_LONGDOUBLE bne,pt %icc, done nop std %f0, [%i4+0] std %f2, [%i4+8] done: ret restore dostruct: /* This will not work correctly for unions. */ stx %o0, [%i4+0] stx %o1, [%i4+8] stx %o2, [%i4+16] stx %o3, [%i4+24] std %f0, [%i4+32] std %f2, [%i4+40] std %f4, [%i4+48] std %f6, [%i4+56] ret restore .LLFE1: .ffi_call_v9_end: .size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9 #undef STACKFRAME #define STACKFRAME 336 /* 16*8 register window + 6*8 args backing store + 20*8 locals */ #define FP %fp+STACK_BIAS /* ffi_closure_v9(...) Receives the closure argument in %g1. */ .text .align 8 .globl ffi_closure_v9 ffi_closure_v9: .LLFB2: save %sp, -STACKFRAME, %sp .LLCFI1: ! Store all of the potential argument registers in va_list format. stx %i0, [FP+128+0] stx %i1, [FP+128+8] stx %i2, [FP+128+16] stx %i3, [FP+128+24] stx %i4, [FP+128+32] stx %i5, [FP+128+40] ! Store possible floating point argument registers too. std %f0, [FP-128] std %f2, [FP-120] std %f4, [FP-112] std %f6, [FP-104] std %f8, [FP-96] std %f10, [FP-88] std %f12, [FP-80] std %f14, [FP-72] std %f16, [FP-64] std %f18, [FP-56] std %f20, [FP-48] std %f22, [FP-40] std %f24, [FP-32] std %f26, [FP-24] std %f28, [FP-16] std %f30, [FP-8] ! Call ffi_closure_sparc_inner to do the bulk of the work. mov %g1, %o0 add %fp, STACK_BIAS-160, %o1 add %fp, STACK_BIAS+128, %o2 call ffi_closure_sparc_inner_v9 add %fp, STACK_BIAS-128, %o3 ! Load up the return value in the proper type. ! See ffi_prep_cif_machdep for the list of cases. cmp %o0, FFI_TYPE_VOID be,pn %icc, done1 cmp %o0, FFI_TYPE_INT be,pn %icc, integer cmp %o0, FFI_TYPE_FLOAT be,a,pn %icc, done1 ld [FP-160], %f0 cmp %o0, FFI_TYPE_DOUBLE be,a,pn %icc, done1 ldd [FP-160], %f0 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE cmp %o0, FFI_TYPE_LONGDOUBLE be,a,pn %icc, longdouble1 ldd [FP-160], %f0 #endif ! FFI_TYPE_STRUCT ldx [FP-152], %i1 ldx [FP-144], %i2 ldx [FP-136], %i3 ldd [FP-160], %f0 ldd [FP-152], %f2 ldd [FP-144], %f4 ldd [FP-136], %f6 integer: ldx [FP-160], %i0 done1: ret restore #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE longdouble1: ldd [FP-152], %f2 ret restore #endif .LLFE2: .ffi_closure_v9_end: .size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9 #ifdef HAVE_RO_EH_FRAME .section ".eh_frame",#alloc #else .section ".eh_frame",#alloc,#write #endif .LLframe1: .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry .LLSCIE1: .uaword 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 0xf ! CIE RA Column .byte 0x1 ! uleb128 0x1; Augmentation size #ifdef HAVE_AS_SPARC_UA_PCREL .byte 0x1b ! FDE Encoding (pcrel sdata4) #else .byte 0x50 ! FDE Encoding (aligned absolute) #endif .byte 0xc ! DW_CFA_def_cfa .byte 0xe ! uleb128 0xe .byte 0xff,0xf ! uleb128 0x7ff .align 8 .LLECIE1: .LLSFDE1: .uaword .LLEFDE1-.LLASFDE1 ! FDE Length .LLASFDE1: .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset #ifdef HAVE_AS_SPARC_UA_PCREL .uaword %r_disp32(.LLFB1) .uaword .LLFE1-.LLFB1 ! FDE address range #else .align 8 .xword .LLFB1 .uaxword .LLFE1-.LLFB1 ! FDE address range #endif .byte 0x0 ! uleb128 0x0; Augmentation size .byte 0x4 ! DW_CFA_advance_loc4 .uaword .LLCFI0-.LLFB1 .byte 0xd ! DW_CFA_def_cfa_register .byte 0x1e ! uleb128 0x1e .byte 0x2d ! DW_CFA_GNU_window_save .byte 0x9 ! DW_CFA_register .byte 0xf ! uleb128 0xf .byte 0x1f ! uleb128 0x1f .align 8 .LLEFDE1: .LLSFDE2: .uaword .LLEFDE2-.LLASFDE2 ! FDE Length .LLASFDE2: .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset #ifdef HAVE_AS_SPARC_UA_PCREL .uaword %r_disp32(.LLFB2) .uaword .LLFE2-.LLFB2 ! FDE address range #else .align 8 .xword .LLFB2 .uaxword .LLFE2-.LLFB2 ! FDE address range #endif .byte 0x0 ! uleb128 0x0; Augmentation size .byte 0x4 ! DW_CFA_advance_loc4 .uaword .LLCFI1-.LLFB2 .byte 0xd ! DW_CFA_def_cfa_register .byte 0x1e ! uleb128 0x1e .byte 0x2d ! DW_CFA_GNU_window_save .byte 0x9 ! DW_CFA_register .byte 0xf ! uleb128 0xf .byte 0x1f ! uleb128 0x1f .align 8 .LLEFDE2: #endif --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for SPARC. 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(__arch64__) || defined(__sparcv9) #define SPARC64 #endif #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_V8, FFI_V8PLUS, FFI_V9, #ifdef SPARC64 FFI_DEFAULT_ABI = FFI_V9, #else FFI_DEFAULT_ABI = FFI_V8, #endif FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 #ifdef SPARC64 #define FFI_TRAMPOLINE_SIZE 24 #else #define FFI_TRAMPOLINE_SIZE 16 #endif #endif --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1996, 2003, 2004 Red Hat, Inc. SPARC 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> /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ void ffi_prep_args_v8(char *stack, extended_cif *ecif) { int i; void **p_argv; char *argp; ffi_type **p_arg; /* Skip 16 words for the window save area */ argp = stack + 16*sizeof(int); /* This should only really be done when we are returning a structure, however, it's faster just to do it all the time... if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */ *(int *) argp = (long)ecif->rvalue; /* And 1 word for the structure return value. */ argp += sizeof(int); #ifdef USING_PURIFY /* Purify will probably complain in our assembly routine, unless we zero out this memory. */ ((int*)argp)[0] = 0; ((int*)argp)[1] = 0; ((int*)argp)[2] = 0; ((int*)argp)[3] = 0; ((int*)argp)[4] = 0; ((int*)argp)[5] = 0; #endif p_argv = ecif->avalue; for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++) { size_t z; if ((*p_arg)->type == FFI_TYPE_STRUCT #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE || (*p_arg)->type == FFI_TYPE_LONGDOUBLE #endif ) { *(unsigned int *) argp = (unsigned long)(* p_argv); z = sizeof(int); } else { z = (*p_arg)->size; if (z < sizeof(int)) { z = sizeof(int); switch ((*p_arg)->type) { case FFI_TYPE_SINT8: *(signed int *) argp = *(SINT8 *)(* p_argv); break; case FFI_TYPE_UINT8: *(unsigned int *) argp = *(UINT8 *)(* p_argv); break; case FFI_TYPE_SINT16: *(signed int *) argp = *(SINT16 *)(* p_argv); break; case FFI_TYPE_UINT16: *(unsigned int *) argp = *(UINT16 *)(* p_argv); break; default: FFI_ASSERT(0); } } else { memcpy(argp, *p_argv, z); } } p_argv++; argp += z; } return; } int ffi_prep_args_v9(char *stack, extended_cif *ecif) { int i, ret = 0; int tmp; void **p_argv; char *argp; ffi_type **p_arg; tmp = 0; /* Skip 16 words for the window save area */ argp = stack + 16*sizeof(long long); #ifdef USING_PURIFY /* Purify will probably complain in our assembly routine, unless we zero out this memory. */ ((long long*)argp)[0] = 0; ((long long*)argp)[1] = 0; ((long long*)argp)[2] = 0; ((long long*)argp)[3] = 0; ((long long*)argp)[4] = 0; ((long long*)argp)[5] = 0; #endif p_argv = ecif->avalue; if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 32) { *(unsigned long long *) argp = (unsigned long)ecif->rvalue; argp += sizeof(long long); tmp = 1; } for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++) { size_t z; z = (*p_arg)->size; switch ((*p_arg)->type) { case FFI_TYPE_STRUCT: if (z > 16) { /* For structures larger than 16 bytes we pass reference. */ *(unsigned long long *) argp = (unsigned long)* p_argv; argp += sizeof(long long); tmp++; p_argv++; continue; } /* FALLTHROUGH */ case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: #endif ret = 1; /* We should promote into FP regs as well as integer. */ break; } if (z < sizeof(long long)) { switch ((*p_arg)->type) { case FFI_TYPE_SINT8: *(signed long long *) argp = *(SINT8 *)(* p_argv); break; case FFI_TYPE_UINT8: *(unsigned long long *) argp = *(UINT8 *)(* p_argv); break; case FFI_TYPE_SINT16: *(signed long long *) argp = *(SINT16 *)(* p_argv); break; case FFI_TYPE_UINT16: *(unsigned long long *) argp = *(UINT16 *)(* p_argv); break; case FFI_TYPE_SINT32: *(signed long long *) argp = *(SINT32 *)(* p_argv); break; case FFI_TYPE_UINT32: *(unsigned long long *) argp = *(UINT32 *)(* p_argv); break; case FFI_TYPE_FLOAT: *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */ break; case FFI_TYPE_STRUCT: memcpy(argp, *p_argv, z); break; default: FFI_ASSERT(0); } z = sizeof(long long); tmp++; } else if (z == sizeof(long long)) { memcpy(argp, *p_argv, z); z = sizeof(long long); tmp++; } else { if ((tmp & 1) && (*p_arg)->alignment > 8) { tmp++; argp += sizeof(long long); } memcpy(argp, *p_argv, z); z = 2 * sizeof(long long); tmp += 2; } p_argv++; argp += z; } return ret; } /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { int wordsize; if (cif->abi != FFI_V9) { wordsize = 4; /* If we are returning a struct, this will already have been added. Otherwise we need to add it because it's always got to be there! */ if (cif->rtype->type != FFI_TYPE_STRUCT) cif->bytes += wordsize; /* sparc call frames require that space is allocated for 6 args, even if they aren't used. Make that space if necessary. */ if (cif->bytes < 4*6+4) cif->bytes = 4*6+4; } else { wordsize = 8; /* sparc call frames require that space is allocated for 6 args, even if they aren't used. Make that space if necessary. */ if (cif->bytes < 8*6) cif->bytes = 8*6; } /* Adjust cif->bytes. to include 16 words for the window save area, and maybe the struct/union return pointer area, */ cif->bytes += 16 * wordsize; /* The stack must be 2 word aligned, so round bytes up appropriately. */ cif->bytes = ALIGN(cif->bytes, 2 * wordsize); /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: #endif cif->flags = cif->rtype->type; break; case FFI_TYPE_STRUCT: if (cif->abi == FFI_V9 && cif->rtype->size > 32) cif->flags = FFI_TYPE_VOID; else cif->flags = FFI_TYPE_STRUCT; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: if (cif->abi != FFI_V9) { cif->flags = FFI_TYPE_SINT64; break; } /* FALLTHROUGH */ default: cif->flags = FFI_TYPE_INT; break; } return FFI_OK; } int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt) { ffi_type **ptr = &arg->elements[0]; while (*ptr != NULL) { if (off & ((*ptr)->alignment - 1)) off = ALIGN(off, (*ptr)->alignment); switch ((*ptr)->type) { case FFI_TYPE_STRUCT: off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt); off = ALIGN(off, FFI_SIZEOF_ARG); break; case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: #endif memmove(ret + off, flt + off, (*ptr)->size); off += (*ptr)->size; break; default: memmove(ret + off, intg + off, (*ptr)->size); off += (*ptr)->size; break; } ptr++; } return off; } #ifdef SPARC64 extern int ffi_call_v9(void *, extended_cif *, unsigned, unsigned, unsigned *, void (*fn)()); #else extern int ffi_call_v8(void *, extended_cif *, unsigned, unsigned, unsigned *, void (*fn)()); #endif void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) { extended_cif ecif; void *rval = rvalue; 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 */ ecif.rvalue = rvalue; if (cif->rtype->type == FFI_TYPE_STRUCT) { if (cif->rtype->size <= 32) rval = alloca(64); else { rval = NULL; if (rvalue == NULL) ecif.rvalue = alloca(cif->rtype->size); } } switch (cif->abi) { case FFI_V8: #ifdef SPARC64 /* We don't yet support calling 32bit code from 64bit */ FFI_ASSERT(0); #else ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, cif->flags, rvalue, fn); #endif break; case FFI_V9: #ifdef SPARC64 ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, cif->flags, rval, fn); if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT) ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32); #else /* And vice versa */ FFI_ASSERT(0); #endif break; default: FFI_ASSERT(0); break; } } #ifdef SPARC64 extern void ffi_closure_v9(void); #else 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) { unsigned int *tramp = (unsigned int *) &closure->tramp[0]; unsigned long fn; #ifdef SPARC64 /* Trampoline address is equal to the closure address. We take advantage of that to reduce the trampoline size by 8 bytes. */ FFI_ASSERT (cif->abi == FFI_V9); fn = (unsigned long) ffi_closure_v9; tramp[0] = 0x83414000; /* rd %pc, %g1 */ tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */ tramp[2] = 0x81c14000; /* jmp %g5 */ tramp[3] = 0x01000000; /* nop */ *((unsigned long *) &tramp[4]) = fn; #else unsigned long ctx = (unsigned long) closure; FFI_ASSERT (cif->abi == FFI_V8); fn = (unsigned long) ffi_closure_v8; tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */ tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */ tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp %g1+%lo(fn) */ tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or %g2, %lo(ctx) */ #endif closure->cif = cif; closure->fun = fun; closure->user_data = user_data; /* Flush the Icache. FIXME: alignment isn't certain, assume 8 bytes */ #ifdef SPARC64 asm volatile ("flush %0" : : "r" (closure) : "memory"); asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory"); #else asm volatile ("iflush %0" : : "r" (closure) : "memory"); asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory"); #endif return FFI_OK; } int ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue, unsigned long *gpr) { ffi_cif *cif; ffi_type **arg_types; void **avalue; int i, argn; cif = closure->cif; arg_types = cif->arg_types; avalue = alloca(cif->nargs * sizeof(void *)); /* Copy the caller's structure return address so that the closure returns the data directly to the caller. */ if (cif->flags == FFI_TYPE_STRUCT #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE || cif->flags == FFI_TYPE_LONGDOUBLE #endif ) rvalue = (void *) gpr[0]; /* Always skip the structure return address. */ argn = 1; /* Grab the addresses of the arguments from the stack frame. */ for (i = 0; i < cif->nargs; i++) { if (arg_types[i]->type == FFI_TYPE_STRUCT #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE || arg_types[i]->type == FFI_TYPE_LONGDOUBLE #endif ) { /* Straight copy of invisible reference. */ avalue[i] = (void *)gpr[argn++]; } else { /* Always right-justify. */ argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size; } } /* Invoke the closure. */ (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_sparc how to perform return type promotions. */ return cif->rtype->type; } int ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue, unsigned long *gpr, double *fpr) { ffi_cif *cif; ffi_type **arg_types; void **avalue; int i, argn, fp_slot_max; cif = closure->cif; arg_types = cif->arg_types; avalue = alloca(cif->nargs * sizeof(void *)); /* Copy the caller's structure return address so that the closure returns the data directly to the caller. */ if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT) { rvalue = (void *) gpr[0]; /* Skip the structure return address. */ argn = 1; } else argn = 0; fp_slot_max = 16 - argn; /* Grab the addresses of the arguments from the stack frame. */ for (i = 0; i < cif->nargs; i++) { if (arg_types[i]->type == FFI_TYPE_STRUCT) { if (arg_types[i]->size > 16) { /* Straight copy of invisible reference. */ avalue[i] = (void *)gpr[argn++]; } else { /* Left-justify. */ ffi_v9_layout_struct(arg_types[i], 0, (char *) &gpr[argn], (char *) &gpr[argn], (char *) &fpr[argn]); avalue[i] = &gpr[argn]; argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } else { /* Right-justify. */ argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; if (i < fp_slot_max && (arg_types[i]->type == FFI_TYPE_FLOAT || arg_types[i]->type == FFI_TYPE_DOUBLE #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE || arg_types[i]->type == FFI_TYPE_LONGDOUBLE #endif )) avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size; else avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size; } } /* Invoke the closure. */ (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_sparc how to perform return type promotions. */ return cif->rtype->type; } --- NEW FILE: v8.S --- /* ----------------------------------------------------------------------- v8.S - Copyright (c) 1996, 1997, 2003, 2004 Red Hat, Inc. SPARC 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #define STACKFRAME 96 /* Minimum stack framesize for SPARC */ #define ARGS (64+4) /* Offset of register area in frame */ .text .align 8 .globl ffi_call_v8 .globl _ffi_call_v8 ffi_call_v8: _ffi_call_v8: .LLFB1: save %sp, -STACKFRAME, %sp .LLCFI0: sub %sp, %i2, %sp ! alloca() space in stack for frame to set up add %sp, STACKFRAME, %l0 ! %l0 has start of ! frame to set up mov %l0, %o0 ! call routine to set up frame call %i0 mov %i1, %o1 ! (delay) ld [%l0+ARGS], %o0 ! call foreign function ld [%l0+ARGS+4], %o1 ld [%l0+ARGS+8], %o2 ld [%l0+ARGS+12], %o3 ld [%l0+ARGS+16], %o4 ld [%l0+ARGS+20], %o5 call %i5 mov %l0, %sp ! (delay) switch to frame nop ! STRUCT returning functions skip 12 instead of 8 bytes ! If the return value pointer is NULL, assume no return value. tst %i4 bz done nop cmp %i3, FFI_TYPE_INT be,a done st %o0, [%i4] ! (delay) cmp %i3, FFI_TYPE_FLOAT be,a done st %f0, [%i4+0] ! (delay) cmp %i3, FFI_TYPE_SINT64 be longlong cmp %i3, FFI_TYPE_DOUBLE bne done nop st %f0, [%i4+0] st %f1, [%i4+4] done: ret restore longlong: st %o0, [%i4+0] st %o1, [%i4+4] ret restore .LLFE1: .ffi_call_v8_end: .size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8 #undef STACKFRAME #define STACKFRAME 104 /* 16*4 register window + 1*4 struct return + 6*4 args backing store + 3*4 locals */ /* ffi_closure_v8(...) Receives the closure argument in %g2. */ .text .align 8 .globl ffi_closure_v8 ffi_closure_v8: #ifdef HAVE_AS_REGISTER_PSEUDO_OP .register %g2, #scratch #endif .LLFB2: save %sp, -STACKFRAME, %sp .LLCFI1: ! Store all of the potential argument registers in va_list format. st %i0, [%fp+68+0] st %i1, [%fp+68+4] st %i2, [%fp+68+8] st %i3, [%fp+68+12] st %i4, [%fp+68+16] st %i5, [%fp+68+20] ! Call ffi_closure_sparc_inner to do the bulk of the work. mov %g2, %o0 add %fp, -8, %o1 call ffi_closure_sparc_inner_v8 add %fp, 64, %o2 ! Load up the return value in the proper type. ! See ffi_prep_cif_machdep for the list of cases. cmp %o0, FFI_TYPE_VOID be done1 cmp %o0, FFI_TYPE_INT be integer cmp %o0, FFI_TYPE_FLOAT be,a done1 ld [%fp-8], %f0 cmp %o0, FFI_TYPE_DOUBLE be,a done1 ldd [%fp-8], %f0 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE cmp %o0, FFI_TYPE_LONGDOUBLE be done2 #endif cmp %o0, FFI_TYPE_STRUCT be done2 ! FFI_TYPE_SINT64 ld [%fp-4], %i1 integer: ld [%fp-8], %i0 done1: jmp %i7+8 restore done2: ! Skip 'unimp'. jmp %i7+12 restore .LLFE2: .ffi_closure_v8_end: .size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8 #ifdef SPARC64 #define WS 8 #define nword xword #define uanword uaxword #else #define WS 4 #define nword long #define uanword uaword #endif #ifdef HAVE_RO_EH_FRAME .section ".eh_frame",#alloc #else .section ".eh_frame",#alloc,#write #endif .LLframe1: .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry .LLSCIE1: .uaword 0x0 ! CIE Identifier Tag .byte 0x1 ! CIE Version .ascii "zR\0" ! CIE Augmentation .byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor .byte 0x80-WS ! sleb128 -WS; CIE Data Alignment Factor .byte 0xf ! CIE RA Column .byte 0x1 ! uleb128 0x1; Augmentation size #ifdef HAVE_AS_SPARC_UA_PCREL .byte 0x1b ! FDE Encoding (pcrel sdata4) #else .byte 0x50 ! FDE Encoding (aligned absolute) #endif .byte 0xc ! DW_CFA_def_cfa .byte 0xe ! uleb128 0xe .byte 0x0 ! uleb128 0x0 .align WS .LLECIE1: .LLSFDE1: .uaword .LLEFDE1-.LLASFDE1 ! FDE Length .LLASFDE1: .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset #ifdef HAVE_AS_SPARC_UA_PCREL .uaword %r_disp32(.LLFB1) .uaword .LLFE1-.LLFB1 ! FDE address range #else .align WS .nword .LLFB1 .uanword .LLFE1-.LLFB1 ! FDE address range #endif .byte 0x0 ! uleb128 0x0; Augmentation size .byte 0x4 ! DW_CFA_advance_loc4 .uaword .LLCFI0-.LLFB1 .byte 0xd ! DW_CFA_def_cfa_register .byte 0x1e ! uleb128 0x1e .byte 0x2d ! DW_CFA_GNU_window_save .byte 0x9 ! DW_CFA_register .byte 0xf ! uleb128 0xf .byte 0x1f ! uleb128 0x1f .align WS .LLEFDE1: .LLSFDE2: .uaword .LLEFDE2-.LLASFDE2 ! FDE Length .LLASFDE2: .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset #ifdef HAVE_AS_SPARC_UA_PCREL .uaword %r_disp32(.LLFB2) .uaword .LLFE2-.LLFB2 ! FDE address range #else .align WS .nword .LLFB2 .uanword .LLFE2-.LLFB2 ! FDE address range #endif .byte 0x0 ! uleb128 0x0; Augmentation size .byte 0x4 ! DW_CFA_advance_loc4 .uaword .LLCFI1-.LLFB2 .byte 0xd ! DW_CFA_def_cfa_register .byte 0x1e ! uleb128 0x1e .byte 0x2d ! DW_CFA_GNU_window_save .byte 0x9 ! DW_CFA_register .byte 0xf ! uleb128 0xf .byte 0x1f ! uleb128 0x1f .align WS .LLEFDE2: |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:25
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/sh64 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/sh64 Added Files: ffi.c ffitarget.h sysv.S Log Message: Importing libffi sources and build tools. --- NEW FILE: sysv.S --- /* ----------------------------------------------------------------------- sysv.S - Copyright (c) 2003 Kaz Kojima SuperH SHmedia 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #ifdef HAVE_MACHINE_ASM_H #include <machine/asm.h> #else /* XXX these lose for some platforms, I'm sure. */ #define CNAME(x) x #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): #endif #ifdef __LITTLE_ENDIAN__ #define OFS_FLT 0 #else #define OFS_FLT 4 #endif .section .text..SHmedia32,"ax" # r2: ffi_prep_args # r3: &ecif # r4: bytes # r5: flags # r6: flags2 # r7: rvalue # r8: fn # This assumes we are using gas. .align 5 ENTRY(ffi_call_SYSV) # Save registers .LFB1: addi.l r15, -48, r15 .LCFI0: st.q r15, 40, r32 st.q r15, 32, r31 st.q r15, 24, r30 st.q r15, 16, r29 st.q r15, 8, r28 st.l r15, 4, r18 st.l r15, 0, r14 add.l r15, r63, r14 .LCFI1: # add r4, r63, r28 add r5, r63, r29 add r6, r63, r30 add r7, r63, r31 add r8, r63, r32 addi r4, (64 + 7), r4 andi r4, ~7, r4 sub.l r15, r4, r15 ptabs/l r2, tr0 add r15, r63, r2 blink tr0, r18 addi r15, 64, r22 movi 0, r0 movi 0, r1 pt/l 1f, tr1 bnei/l r29, FFI_TYPE_STRUCT, tr1 ld.l r15, 0, r19 addi r15, 8, r15 addi r0, 1, r0 1: .L_pass: andi r30, 3, r20 shlri r30, 2, r30 pt/l .L_call_it, tr0 pt/l .L_pass_i, tr1 pt/l .L_pass_f, tr2 beqi/l r20, FFI_TYPE_VOID, tr0 beqi/l r20, FFI_TYPE_INT, tr1 beqi/l r20, FFI_TYPE_FLOAT, tr2 .L_pass_d: addi r0, 1, r0 addi r1, 1, r1 andi r1, ~1, r1 pt/l 3f, tr0 movi 12, r20 bge/l r1, r20, tr0 pt/l .L_pop_d, tr1 pt/l 2f, tr0 blink tr1, r63 2: addi.l r15, 8, r15 3: pt/l .L_pass, tr0 addi r1, 2, r1 blink tr0, r63 .L_pop_d: pt/l .L_pop_d_tbl, tr1 gettr tr1, r20 shlli r1, 2, r21 add r20, r21, r20 ptabs/l r20, tr1 blink tr1, r63 .L_pop_d_tbl: fld.d r15, 0, dr0 blink tr0, r63 fld.d r15, 0, dr2 blink tr0, r63 fld.d r15, 0, dr4 blink tr0, r63 fld.d r15, 0, dr6 blink tr0, r63 fld.d r15, 0, dr8 blink tr0, r63 fld.d r15, 0, dr10 blink tr0, r63 .L_pass_f: addi r0, 1, r0 pt/l 3f, tr0 movi 12, r20 bge/l r1, r20, tr0 pt/l .L_pop_f, tr1 pt/l 2f, tr0 blink tr1, r63 2: addi.l r15, 8, r15 3: pt/l .L_pass, tr0 addi r1, 1, r1 blink tr0, r63 .L_pop_f: pt/l .L_pop_f_tbl, tr1 gettr tr1, r20 shlli r1, 3, r21 add r20, r21, r20 ptabs/l r20, tr1 blink tr1, r63 .L_pop_f_tbl: fld.s r15, OFS_FLT, fr0 blink tr0, r63 fld.s r15, OFS_FLT, fr1 blink tr0, r63 fld.s r15, OFS_FLT, fr2 blink tr0, r63 fld.s r15, OFS_FLT, fr3 blink tr0, r63 fld.s r15, OFS_FLT, fr4 blink tr0, r63 fld.s r15, OFS_FLT, fr5 blink tr0, r63 fld.s r15, OFS_FLT, fr6 blink tr0, r63 fld.s r15, OFS_FLT, fr7 blink tr0, r63 fld.s r15, OFS_FLT, fr8 blink tr0, r63 fld.s r15, OFS_FLT, fr9 blink tr0, r63 fld.s r15, OFS_FLT, fr10 blink tr0, r63 fld.s r15, OFS_FLT, fr11 blink tr0, r63 .L_pass_i: pt/l 3f, tr0 movi 8, r20 bge/l r0, r20, tr0 pt/l .L_pop_i, tr1 pt/l 2f, tr0 blink tr1, r63 2: addi.l r15, 8, r15 3: pt/l .L_pass, tr0 addi r0, 1, r0 blink tr0, r63 .L_pop_i: pt/l .L_pop_i_tbl, tr1 gettr tr1, r20 shlli r0, 3, r21 add r20, r21, r20 ptabs/l r20, tr1 blink tr1, r63 .L_pop_i_tbl: ld.q r15, 0, r2 blink tr0, r63 ld.q r15, 0, r3 blink tr0, r63 ld.q r15, 0, r4 blink tr0, r63 ld.q r15, 0, r5 blink tr0, r63 ld.q r15, 0, r6 blink tr0, r63 ld.q r15, 0, r7 blink tr0, r63 ld.q r15, 0, r8 blink tr0, r63 ld.q r15, 0, r9 blink tr0, r63 .L_call_it: # call function pt/l 1f, tr1 bnei/l r29, FFI_TYPE_STRUCT, tr1 add r19, r63, r2 1: add r22, r63, r15 ptabs/l r32, tr0 blink tr0, r18 pt/l .L_ret_i, tr0 pt/l .L_ret_ll, tr1 pt/l .L_ret_d, tr2 pt/l .L_ret_f, tr3 pt/l .L_epilogue, tr4 beqi/l r29, FFI_TYPE_INT, tr0 beqi/l r29, FFI_TYPE_SINT64, tr1 beqi/l r29, FFI_TYPE_UINT64, tr1 beqi/l r29, FFI_TYPE_DOUBLE, tr2 beqi/l r29, FFI_TYPE_FLOAT, tr3 blink tr4, r63 .L_ret_d: fst.d r31, 0, dr0 blink tr4, r63 .L_ret_ll: st.q r31, 0, r2 blink tr4, r63 .L_ret_f: fst.s r31, OFS_FLT, fr0 blink tr4, r63 .L_ret_i: st.l r31, 0, r2 # Fall .L_epilogue: # Remove the space we pushed for the args add r14, r63, r15 ld.l r15, 0, r14 ld.l r15, 4, r18 ld.q r15, 8, r28 ld.q r15, 16, r29 ld.q r15, 24, r30 ld.q r15, 32, r31 ld.q r15, 40, r32 addi.l r15, 48, r15 ptabs r18, tr0 blink tr0, r63 .LFE1: .ffi_call_SYSV_end: .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) .align 5 ENTRY(ffi_closure_SYSV) .LFB2: addi.l r15, -136, r15 .LCFI2: st.l r15, 12, r18 st.l r15, 8, r14 st.l r15, 4, r12 add r15, r63, r14 .LCFI3: /* Stack layout: ... 64 bytes (register parameters) 48 bytes (floating register parameters) 8 bytes (result) 4 bytes (r18) 4 bytes (r14) 4 bytes (r12) 4 bytes (for align) <- new stack pointer */ fst.d r14, 24, dr0 fst.d r14, 32, dr2 fst.d r14, 40, dr4 fst.d r14, 48, dr6 fst.d r14, 56, dr8 fst.d r14, 64, dr10 st.q r14, 72, r2 st.q r14, 80, r3 st.q r14, 88, r4 st.q r14, 96, r5 st.q r14, 104, r6 st.q r14, 112, r7 st.q r14, 120, r8 st.q r14, 128, r9 add r1, r63, r2 addi r14, 16, r3 addi r14, 72, r4 addi r14, 24, r5 addi r14, 136, r6 #ifdef PIC movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12 shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12 .LPCS0: ptrel/u r12, tr0 movi ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1 gettr tr0, r12 ldx.l r1, r12, r1 ptabs r1, tr0 #else pt/l ffi_closure_helper_SYSV, tr0 #endif blink tr0, r18 shlli r2, 1, r1 movi (((datalabel .L_table) >> 16) & 65535), r2 shori ((datalabel .L_table) & 65535), r2 ldx.w r2, r1, r1 add r1, r2, r1 pt/l .L_case_v, tr1 ptabs r1, tr0 blink tr0, r63 .align 2 .L_table: .word .L_case_v - datalabel .L_table /* FFI_TYPE_VOID */ .word .L_case_i - datalabel .L_table /* FFI_TYPE_INT */ .word .L_case_f - datalabel .L_table /* FFI_TYPE_FLOAT */ .word .L_case_d - datalabel .L_table /* FFI_TYPE_DOUBLE */ .word .L_case_d - datalabel .L_table /* FFI_TYPE_LONGDOUBLE */ .word .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */ .word .L_case_q - datalabel .L_table /* FFI_TYPE_SINT8 */ .word .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */ .word .L_case_h - datalabel .L_table /* FFI_TYPE_SINT16 */ .word .L_case_i - datalabel .L_table /* FFI_TYPE_UINT32 */ .word .L_case_i - datalabel .L_table /* FFI_TYPE_SINT32 */ .word .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */ .word .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */ .word .L_case_v - datalabel .L_table /* FFI_TYPE_STRUCT */ .word .L_case_i - datalabel .L_table /* FFI_TYPE_POINTER */ .align 2 .L_case_d: fld.d r14, 16, dr0 blink tr1, r63 .L_case_f: fld.s r14, 16, fr0 blink tr1, r63 .L_case_ll: ld.q r14, 16, r2 blink tr1, r63 .L_case_i: ld.l r14, 16, r2 blink tr1, r63 .L_case_q: ld.b r14, 16, r2 blink tr1, r63 .L_case_uq: ld.ub r14, 16, r2 blink tr1, r63 .L_case_h: ld.w r14, 16, r2 blink tr1, r63 .L_case_uh: ld.uw r14, 16, r2 blink tr1, r63 .L_case_v: add.l r14, r63, r15 ld.l r15, 4, r12 ld.l r15, 8, r14 ld.l r15, 12, r18 addi.l r15, 136, r15 ptabs r18, tr0 blink tr0, r63 .LFE2: .ffi_closure_SYSV_end: .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) .section ".eh_frame","aw",@progbits __FRAME_BEGIN__: .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ .LSCIE1: .4byte 0x0 /* CIE Identifier Tag */ .byte 0x1 /* CIE Version */ .ascii "zR\0" /* CIE Augmentation */ .uleb128 0x1 /* CIE Code Alignment Factor */ .sleb128 -4 /* CIE Data Alignment Factor */ .byte 0x12 /* CIE RA Column */ .uleb128 0x1 /* Augmentation size */ .byte 0x1b /* FDE Encoding (pcrel sdata4) */ .byte 0xc /* DW_CFA_def_cfa */ .uleb128 0xf .uleb128 0x0 .align 2 .LECIE1: .LSFDE1: .4byte datalabel .LEFDE1-datalabel .LASFDE1 /* FDE Length */ .LASFDE1: .4byte datalabel .LASFDE1-datalabel __FRAME_BEGIN__ .4byte datalabel .LFB1-. /* FDE initial location */ .4byte datalabel .LFE1-datalabel .LFB1 /* FDE address range */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte datalabel .LCFI0-datalabel .LFB1 .byte 0xe /* DW_CFA_def_cfa_offset */ .uleb128 0x30 .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte datalabel .LCFI1-datalabel .LCFI0 .byte 0x8e /* DW_CFA_offset, column 0xe */ .uleb128 0xc .byte 0x92 /* DW_CFA_offset, column 0x12 */ .uleb128 0xb .byte 0x9c /* DW_CFA_offset, column 0x1c */ .uleb128 0xa .byte 0x9d /* DW_CFA_offset, column 0x1d */ .uleb128 0x8 .byte 0x9e /* DW_CFA_offset, column 0x1e */ .uleb128 0x6 .byte 0x9f /* DW_CFA_offset, column 0x1f */ .uleb128 0x4 .byte 0xa0 /* DW_CFA_offset, column 0x20 */ .uleb128 0x2 .byte 0xd /* DW_CFA_def_cfa_register */ .uleb128 0xe .align 2 .LEFDE1: .LSFDE3: .4byte datalabel .LEFDE3-datalabel .LASFDE3 /* FDE Length */ .LASFDE3: .4byte datalabel .LASFDE3-datalabel __FRAME_BEGIN__ .4byte datalabel .LFB2-. /* FDE initial location */ .4byte datalabel .LFE2-datalabel .LFB2 /* FDE address range */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte datalabel .LCFI2-datalabel .LFB2 .byte 0xe /* DW_CFA_def_cfa_offset */ .uleb128 0x88 .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte datalabel .LCFI3-datalabel .LCFI2 .byte 0x8c /* DW_CFA_offset, column 0xc */ .uleb128 0x21 .byte 0x8e /* DW_CFA_offset, column 0xe */ .uleb128 0x20 .byte 0x92 /* DW_CFA_offset, column 0x12 */ .uleb128 0x1f .byte 0xd /* DW_CFA_def_cfa_register */ .uleb128 0xe .align 2 .LEFDE3: --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 2003 Kaz Kojima SuperH SHmedia 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> #define NGREGARG 8 #define NFREGARG 12 /* If the structure has essentialy an unique element, return its type. */ static int simple_type (ffi_type *arg) { if (arg->type != FFI_TYPE_STRUCT) return arg->type; else if (arg->elements[1]) return FFI_TYPE_STRUCT; return simple_type (arg->elements[0]); } static int return_type (ffi_type *arg) { unsigned short type; if (arg->type != FFI_TYPE_STRUCT) return arg->type; type = simple_type (arg->elements[0]); if (! arg->elements[1]) { switch (type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: return FFI_TYPE_UINT64; default: return type; } } /* gcc uses r2 if the result can be packed in on register. */ if (arg->size <= sizeof (UINT64)) return FFI_TYPE_UINT64; return FFI_TYPE_STRUCT; } /* 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 unsigned int avn; register void **p_argv; register char *argp; register ffi_type **p_arg; argp = stack; if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) { *(void **) argp = ecif->rvalue; argp += sizeof (UINT64); } avn = ecif->cif->nargs; p_argv = ecif->avalue; for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) { size_t z; z = (*p_arg)->size; if (z < sizeof (UINT32)) { switch ((*p_arg)->type) { case FFI_TYPE_SINT8: *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv); break; case FFI_TYPE_UINT8: *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv); break; case FFI_TYPE_SINT16: *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv); break; case FFI_TYPE_UINT16: *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv); break; case FFI_TYPE_STRUCT: *(UINT64 *) argp = (UINT64) *(UINT32 *)(*p_argv); break; default: FFI_ASSERT(0); } argp += sizeof (UINT64); } else if (z == sizeof (UINT32)) { *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv); argp += sizeof (UINT64); } else if (z == sizeof (UINT64)) { *(UINT64 *) argp = *(UINT64 *) (*p_argv); argp += sizeof (UINT64); } else { int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64); memcpy (argp, *p_argv, z); argp += n * sizeof (UINT64); } } return; } /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { int i, j; int size, type; int n, m; int greg; int freg; greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0); freg = 0; cif->flags2 = 0; for (i = j = 0; i < cif->nargs; i++) { type = (cif->arg_types)[i]->type; switch (type) { case FFI_TYPE_FLOAT: greg++; cif->bytes += sizeof (UINT64) - sizeof (float); if (freg >= NFREGARG - 1) continue; freg++; cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); break; case FFI_TYPE_DOUBLE: if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG) continue; if ((freg + 1) < NFREGARG) { freg = (freg + 1) & ~1; freg += 2; cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++); } else cif->flags2 += FFI_TYPE_INT << (2 * j++); break; default: size = (cif->arg_types)[i]->size; if (size < sizeof (UINT64)) cif->bytes += sizeof (UINT64) - size; n = (size + sizeof (UINT64) - 1) / sizeof (UINT64); if (greg >= NGREGARG) continue; else if (greg + n - 1 >= NGREGARG) greg = NGREGARG; else greg += n; for (m = 0; m < n; m++) cif->flags2 += FFI_TYPE_INT << (2 * j++); break; } } /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_STRUCT: cif->flags = return_type (cif->rtype); break; case FFI_TYPE_VOID: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: cif->flags = cif->rtype->type; break; default: cif->flags = FFI_TYPE_INT; break; } return FFI_OK; } /*@-declundef@*/ /*@-exportheader@*/ extern void ffi_call_SYSV(void (*)(char *, extended_cif *), /*@out@*/ extended_cif *, unsigned, unsigned, long long, /*@out@*/ unsigned *, void (*fn)()); /*@=declundef@*/ /*@=exportheader@*/ void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@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) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-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, &ecif, cif->bytes, cif->flags, cif->flags2, ecif.rvalue, fn); /*@=usedef@*/ break; default: FFI_ASSERT(0); break; } } extern void ffi_closure_SYSV (void); extern void __ic_invalidate (void *line); ffi_status ffi_prep_closure (ffi_closure *closure, ffi_cif *cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data) { unsigned int *tramp; FFI_ASSERT (cif->abi == FFI_GCC_SYSV); tramp = (unsigned int *) &closure->tramp[0]; /* Since ffi_closure is an aligned object, the ffi trampoline is called as an SHcompact code. Sigh. SHcompact part: mova @(1,pc),r0; add #1,r0; jmp @r0; nop; SHmedia part: movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0 movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63 */ #ifdef __LITTLE_ENDIAN__ tramp[0] = 0x7001c701; tramp[1] = 0x0009402b; #else tramp[0] = 0xc7017001; tramp[1] = 0x402b0009; #endif tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10; tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10; tramp[4] = 0x6bf10600; tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10; tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10; tramp[7] = 0x4401fff0; closure->cif = cif; closure->fun = fun; closure->user_data = user_data; /* Flush the icache. */ asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp)); return FFI_OK; } /* Basically the trampoline invokes ffi_closure_SYSV, and on * entry, r3 holds the address of the closure. * After storing the registers that could possibly contain * parameters to be passed into the stack frame and setting * up space for a return value, ffi_closure_SYSV invokes the * following helper function to do most of the work. */ int ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, UINT64 *pgr, UINT64 *pfr, UINT64 *pst) { void **avalue; ffi_type **p_arg; int i, avn; int greg, freg; ffi_cif *cif; cif = closure->cif; avalue = alloca (cif->nargs * sizeof (void *)); /* Copy the caller's structure return value address so that the closure returns the data directly to the caller. */ if (cif->rtype->type == FFI_TYPE_STRUCT) { rvalue = *pgr; greg = 1; } else greg = 0; freg = 0; cif = closure->cif; avn = cif->nargs; /* Grab the addresses of the arguments from the stack frame. */ for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) { size_t z; void *p; z = (*p_arg)->size; if (z < sizeof (UINT32)) { p = pgr + greg++; switch ((*p_arg)->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: case FFI_TYPE_STRUCT: #ifdef __LITTLE_ENDIAN__ avalue[i] = p; #else avalue[i] = ((char *) p) + sizeof (UINT32) - z; #endif break; default: FFI_ASSERT(0); } } else if (z == sizeof (UINT32)) { if ((*p_arg)->type == FFI_TYPE_FLOAT) { if (freg < NFREGARG - 1) #ifdef __LITTLE_ENDIAN__ avalue[i] = (UINT32 *) pfr + (1 ^ freg++); #else avalue[i] = (UINT32 *) pfr + freg++; #endif else #ifdef __LITTLE_ENDIAN__ avalue[i] = pgr + greg; #else avalue[i] = (UINT32 *) (pgr + greg) + 1; #endif } else #ifdef __LITTLE_ENDIAN__ avalue[i] = pgr + greg; #else avalue[i] = (UINT32 *) (pgr + greg) + 1; #endif greg++; } else if ((*p_arg)->type == FFI_TYPE_DOUBLE) { if (freg + 1 >= NFREGARG) avalue[i] = pgr + greg; else { freg = (freg + 1) & ~1; avalue[i] = pfr + (freg >> 1); freg += 2; } greg++; } else { int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64); avalue[i] = pgr + greg; greg += n; } } (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_SYSV how to perform return type promotions. */ return cif->rtype->type; } --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for SuperH - SHmedia. 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 /* ---- Generic type definitions ----------------------------------------- */ #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #define FFI_EXTRA_CIF_FIELDS long long flags2 #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #define FFI_TRAMPOLINE_SIZE 32 #define FFI_NATIVE_RAW_API 0 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:25
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/sh In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/sh Added Files: ffi.c ffitarget.h sysv.S Log Message: Importing libffi sources and build tools. --- NEW FILE: sysv.S --- /* ----------------------------------------------------------------------- sysv.S - Copyright (c) 2002, 2003 Kaz Kojima SuperH 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #ifdef HAVE_MACHINE_ASM_H #include <machine/asm.h> #else /* XXX these lose for some platforms, I'm sure. */ #define CNAME(x) x #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): #endif #if defined(__HITACHI__) #define STRUCT_VALUE_ADDRESS_WITH_ARG 1 #else #define STRUCT_VALUE_ADDRESS_WITH_ARG 0 #endif .text # r4: ffi_prep_args # r5: &ecif # r6: bytes # r7: flags # sp+0: rvalue # sp+4: fn # This assumes we are using gas. ENTRY(ffi_call_SYSV) # Save registers .LFB1: mov.l r8,@-r15 .LCFI0: mov.l r9,@-r15 .LCFI1: mov.l r10,@-r15 .LCFI2: mov.l r12,@-r15 .LCFI3: mov.l r14,@-r15 .LCFI4: sts.l pr,@-r15 .LCFI5: mov r15,r14 .LCFI6: #if defined(__SH4__) mov r6,r8 mov r7,r9 sub r6,r15 add #-16,r15 mov #~7,r0 and r0,r15 mov r4,r0 jsr @r0 mov r15,r4 mov r9,r1 shlr8 r9 shlr8 r9 shlr8 r9 mov #FFI_TYPE_STRUCT,r2 cmp/eq r2,r9 bf 1f #if STRUCT_VALUE_ADDRESS_WITH_ARG mov.l @r15+,r4 bra 2f mov #5,r2 #else mov.l @r15+,r10 #endif 1: mov #4,r2 2: mov #4,r3 L_pass: cmp/pl r8 bf L_call_it mov r1,r0 and #3,r0 L_pass_d: cmp/eq #FFI_TYPE_DOUBLE,r0 bf L_pass_f mov r3,r0 and #1,r0 tst r0,r0 bt 1f add #1,r3 1: mov r15,r0 and #7,r0 tst r0,r0 bt 2f add #4,r15 2: mov #12,r0 cmp/hs r0,r3 bt/s 3f shlr2 r1 bsr L_pop_d nop 3: add #2,r3 bra L_pass add #-8,r8 L_pop_d: mov r3,r0 add r0,r0 add r3,r0 add #-12,r0 braf r0 nop #ifdef __LITTLE_ENDIAN__ fmov.s @r15+,fr5 rts fmov.s @r15+,fr4 fmov.s @r15+,fr7 rts fmov.s @r15+,fr6 fmov.s @r15+,fr9 rts fmov.s @r15+,fr8 fmov.s @r15+,fr11 rts fmov.s @r15+,fr10 #else fmov.s @r15+,fr4 rts fmov.s @r15+,fr5 fmov.s @r15+,fr6 rts fmov.s @r15+,fr7 fmov.s @r15+,fr8 rts fmov.s @r15+,fr9 fmov.s @r15+,fr10 rts fmov.s @r15+,fr11 #endif L_pass_f: cmp/eq #FFI_TYPE_FLOAT,r0 bf L_pass_i mov #12,r0 cmp/hs r0,r3 bt/s 2f shlr2 r1 bsr L_pop_f nop 2: add #1,r3 bra L_pass add #-4,r8 L_pop_f: mov r3,r0 shll2 r0 add #-16,r0 braf r0 nop #ifdef __LITTLE_ENDIAN__ rts fmov.s @r15+,fr5 rts fmov.s @r15+,fr4 rts fmov.s @r15+,fr7 rts fmov.s @r15+,fr6 rts fmov.s @r15+,fr9 rts fmov.s @r15+,fr8 rts fmov.s @r15+,fr11 rts fmov.s @r15+,fr10 #else rts fmov.s @r15+,fr4 rts fmov.s @r15+,fr5 rts fmov.s @r15+,fr6 rts fmov.s @r15+,fr7 rts fmov.s @r15+,fr8 rts fmov.s @r15+,fr9 rts fmov.s @r15+,fr10 rts fmov.s @r15+,fr11 #endif L_pass_i: cmp/eq #FFI_TYPE_INT,r0 bf L_call_it mov #8,r0 cmp/hs r0,r2 bt/s 2f shlr2 r1 bsr L_pop_i nop 2: add #1,r2 bra L_pass add #-4,r8 L_pop_i: mov r2,r0 shll2 r0 add #-16,r0 braf r0 nop rts mov.l @r15+,r4 rts mov.l @r15+,r5 rts mov.l @r15+,r6 rts mov.l @r15+,r7 L_call_it: # call function #if (! STRUCT_VALUE_ADDRESS_WITH_ARG) mov r10, r2 #endif mov.l @(28,r14),r1 jsr @r1 nop L_ret_d: mov #FFI_TYPE_DOUBLE,r2 cmp/eq r2,r9 bf L_ret_ll mov.l @(24,r14),r1 #ifdef __LITTLE_ENDIAN__ fmov.s fr1,@r1 add #4,r1 bra L_epilogue fmov.s fr0,@r1 #else fmov.s fr0,@r1 add #4,r1 bra L_epilogue fmov.s fr1,@r1 #endif L_ret_ll: mov #FFI_TYPE_SINT64,r2 cmp/eq r2,r9 bt/s 1f mov #FFI_TYPE_UINT64,r2 cmp/eq r2,r9 bf L_ret_f 1: mov.l @(24,r14),r2 mov.l r0,@r2 bra L_epilogue mov.l r1,@(4,r2) L_ret_f: mov #FFI_TYPE_FLOAT,r2 cmp/eq r2,r9 bf L_ret_i mov.l @(24,r14),r1 bra L_epilogue fmov.s fr0,@r1 L_ret_i: mov #FFI_TYPE_INT,r2 cmp/eq r2,r9 bf L_epilogue mov.l @(24,r14),r1 bra L_epilogue mov.l r0,@r1 L_epilogue: # Remove the space we pushed for the args mov r14,r15 lds.l @r15+,pr mov.l @r15+,r14 mov.l @r15+,r12 mov.l @r15+,r10 mov.l @r15+,r9 rts mov.l @r15+,r8 #else mov r6,r8 mov r7,r9 sub r6,r15 add #-16,r15 mov #~7,r0 and r0,r15 mov r4,r0 jsr @r0 mov r15,r4 mov r9,r3 shlr8 r9 shlr8 r9 shlr8 r9 mov #FFI_TYPE_STRUCT,r2 cmp/eq r2,r9 bf 1f #if STRUCT_VALUE_ADDRESS_WITH_ARG mov.l @r15+,r4 bra 2f mov #5,r2 #else mov.l @r15+,r10 #endif 1: mov #4,r2 2: L_pass: cmp/pl r8 bf L_call_it mov r3,r0 and #3,r0 L_pass_d: cmp/eq #FFI_TYPE_DOUBLE,r0 bf L_pass_i mov r15,r0 and #7,r0 tst r0,r0 bt 1f add #4,r15 1: mov #8,r0 cmp/hs r0,r2 bt/s 2f shlr2 r3 bsr L_pop_d nop 2: add #2,r2 bra L_pass add #-8,r8 L_pop_d: mov r2,r0 add r0,r0 add r2,r0 add #-12,r0 add r0,r0 braf r0 nop mov.l @r15+,r4 rts mov.l @r15+,r5 mov.l @r15+,r5 rts mov.l @r15+,r6 mov.l @r15+,r6 rts mov.l @r15+,r7 rts mov.l @r15+,r7 L_pass_i: mov #8,r0 cmp/hs r0,r2 bt/s 2f shlr2 r3 bsr L_pop_i nop 2: add #1,r2 bra L_pass add #-4,r8 L_pop_i: mov r2,r0 shll2 r0 add #-16,r0 braf r0 nop rts mov.l @r15+,r4 rts mov.l @r15+,r5 rts mov.l @r15+,r6 rts mov.l @r15+,r7 L_call_it: # call function #if (! STRUCT_VALUE_ADDRESS_WITH_ARG) mov r10, r2 #endif mov.l @(28,r14),r1 jsr @r1 nop L_ret_d: mov #FFI_TYPE_DOUBLE,r2 cmp/eq r2,r9 bf L_ret_ll mov.l @(24,r14),r2 mov.l r0,@r2 bra L_epilogue mov.l r1,@(4,r2) L_ret_ll: mov #FFI_TYPE_SINT64,r2 cmp/eq r2,r9 bt/s 1f mov #FFI_TYPE_UINT64,r2 cmp/eq r2,r9 bf L_ret_i 1: mov.l @(24,r14),r2 mov.l r0,@r2 bra L_epilogue mov.l r1,@(4,r2) L_ret_i: mov #FFI_TYPE_FLOAT,r2 cmp/eq r2,r9 bt 1f mov #FFI_TYPE_INT,r2 cmp/eq r2,r9 bf L_epilogue 1: mov.l @(24,r14),r1 bra L_epilogue mov.l r0,@r1 L_epilogue: # Remove the space we pushed for the args mov r14,r15 lds.l @r15+,pr mov.l @r15+,r14 mov.l @r15+,r12 mov.l @r15+,r10 mov.l @r15+,r9 rts mov.l @r15+,r8 #endif .LFE1: .ffi_call_SYSV_end: .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) .globl ffi_closure_helper_SYSV ENTRY(ffi_closure_SYSV) .LFB2: mov.l r14,@-r15 .LCFI7: sts.l pr,@-r15 /* Stack layout: ... 32 bytes (floating register parameters, SH-4 only) 16 bytes (register parameters) 8 bytes (result) 4 bytes (pad) 4 bytes (5th arg) <- new stack pointer */ .LCFI8: #if defined(__SH4__) add #-64,r15 #else add #-32,r15 #endif .LCFI9: mov r15,r14 .LCFIA: mov r14,r1 add #32,r1 mov.l r7,@-r1 mov.l r6,@-r1 mov.l r5,@-r1 mov.l r4,@-r1 mov r1,r6 #if defined(__SH4__) mov r14,r1 add #64,r1 #ifdef __LITTLE_ENDIAN__ fmov.s fr10,@-r1 fmov.s fr11,@-r1 fmov.s fr8,@-r1 fmov.s fr9,@-r1 fmov.s fr6,@-r1 fmov.s fr7,@-r1 fmov.s fr4,@-r1 fmov.s fr5,@-r1 #else fmov.s fr11,@-r1 fmov.s fr10,@-r1 fmov.s fr9,@-r1 fmov.s fr8,@-r1 fmov.s fr7,@-r1 fmov.s fr6,@-r1 fmov.s fr5,@-r1 fmov.s fr4,@-r1 #endif mov r1,r7 #endif mov r14,r1 add #8,r1 mov r1,r5 mov r14,r1 #if defined(__SH4__) add #72,r1 #else add #40,r1 #endif mov.l r1,@r14 mov.l L_helper,r0 jsr @r0 mov r3,r4 shll r0 mov r0,r1 mova L_table,r0 add r1,r0 mov.w @r0,r0 mov r14,r2 braf r0 add #8,r2 0: .align 2 L_helper: .long ffi_closure_helper_SYSV L_table: .short L_case_v - 0b /* FFI_TYPE_VOID */ .short L_case_i - 0b /* FFI_TYPE_INT */ #if defined(__SH4__) .short L_case_f - 0b /* FFI_TYPE_FLOAT */ .short L_case_d - 0b /* FFI_TYPE_DOUBLE */ .short L_case_d - 0b /* FFI_TYPE_LONGDOUBLE */ #else .short L_case_i - 0b /* FFI_TYPE_FLOAT */ .short L_case_ll - 0b /* FFI_TYPE_DOUBLE */ .short L_case_ll - 0b /* FFI_TYPE_LONGDOUBLE */ #endif .short L_case_uq - 0b /* FFI_TYPE_UINT8 */ .short L_case_q - 0b /* FFI_TYPE_SINT8 */ .short L_case_uh - 0b /* FFI_TYPE_UINT16 */ .short L_case_h - 0b /* FFI_TYPE_SINT16 */ .short L_case_i - 0b /* FFI_TYPE_UINT32 */ .short L_case_i - 0b /* FFI_TYPE_SINT32 */ .short L_case_ll - 0b /* FFI_TYPE_UINT64 */ .short L_case_ll - 0b /* FFI_TYPE_SINT64 */ .short L_case_v - 0b /* FFI_TYPE_STRUCT */ .short L_case_i - 0b /* FFI_TYPE_POINTER */ #if defined(__SH4__) L_case_d: #ifdef __LITTLE_ENDIAN__ fmov.s @r2+,fr1 bra L_case_v fmov.s @r2,fr0 #else fmov.s @r2+,fr0 bra L_case_v fmov.s @r2,fr1 #endif L_case_f: bra L_case_v fmov.s @r2,fr0 #endif L_case_ll: mov.l @r2+,r0 bra L_case_v mov.l @r2,r1 L_case_i: bra L_case_v mov.l @r2,r0 L_case_q: #ifdef __LITTLE_ENDIAN__ #else add #3,r2 #endif bra L_case_v mov.b @r2,r0 L_case_uq: #ifdef __LITTLE_ENDIAN__ #else add #3,r2 #endif mov.b @r2,r0 bra L_case_v extu.b r0,r0 L_case_h: #ifdef __LITTLE_ENDIAN__ #else add #2,r2 #endif bra L_case_v mov.w @r2,r0 L_case_uh: #ifdef __LITTLE_ENDIAN__ #else add #2,r2 #endif mov.w @r2,r0 extu.w r0,r0 /* fall through */ L_case_v: #if defined(__SH4__) add #64,r15 #else add #32,r15 #endif lds.l @r15+,pr rts mov.l @r15+,r14 .LFE2: .ffi_closure_SYSV_end: .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) .section ".eh_frame","aw",@progbits __FRAME_BEGIN__: .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ .LSCIE1: .4byte 0x0 /* CIE Identifier Tag */ .byte 0x1 /* CIE Version */ .byte 0x0 /* CIE Augmentation */ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ .byte 0x7c /* sleb128 -4; CIE Data Alignment Factor */ .byte 0x11 /* CIE RA Column */ .byte 0xc /* DW_CFA_def_cfa */ .byte 0xf /* uleb128 0xf */ .byte 0x0 /* uleb128 0x0 */ .align 2 .LECIE1: .LSFDE1: .4byte .LEFDE1-.LASFDE1 /* FDE Length */ .LASFDE1: .4byte .LASFDE1-__FRAME_BEGIN__ /* FDE CIE offset */ .4byte .LFB1 /* FDE initial location */ .4byte .LFE1-.LFB1 /* FDE address range */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI0-.LFB1 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0x4 /* uleb128 0x4 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI1-.LCFI0 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0x8 /* uleb128 0x4 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI2-.LCFI1 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0xc /* uleb128 0x4 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI3-.LCFI2 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0x10 /* uleb128 0x4 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI4-.LCFI3 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0x14 /* uleb128 0x4 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI5-.LCFI4 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0x18 /* uleb128 0x4 */ .byte 0x91 /* DW_CFA_offset, column 0x11 */ .byte 0x6 /* uleb128 0x6 */ .byte 0x8e /* DW_CFA_offset, column 0xe */ .byte 0x5 /* uleb128 0x5 */ .byte 0x8c /* DW_CFA_offset, column 0xc */ .byte 0x4 /* uleb128 0x4 */ .byte 0x8a /* DW_CFA_offset, column 0xa */ .byte 0x3 /* uleb128 0x3 */ .byte 0x89 /* DW_CFA_offset, column 0x9 */ .byte 0x2 /* uleb128 0x2 */ .byte 0x88 /* DW_CFA_offset, column 0x8 */ .byte 0x1 /* uleb128 0x1 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI6-.LCFI5 .byte 0xd /* DW_CFA_def_cfa_register */ .byte 0xe /* uleb128 0xe */ .align 2 .LEFDE1: .LSFDE3: .4byte .LEFDE3-.LASFDE3 /* FDE Length */ .LASFDE3: .4byte .LASFDE3-__FRAME_BEGIN__ /* FDE CIE offset */ .4byte .LFB2 /* FDE initial location */ .4byte .LFE2-.LFB2 /* FDE address range */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI7-.LFB2 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0x4 /* uleb128 0x4 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI8-.LCFI7 .byte 0xe /* DW_CFA_def_cfa_offset */ .byte 0x8 /* uleb128 0x8 */ .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFI9-.LCFI8 .byte 0xe /* DW_CFA_def_cfa_offset */ #if defined(__SH4__) .byte 8+64 /* uleb128 8+64 */ #else .byte 8+32 /* uleb128 8+32 */ #endif .byte 0x91 /* DW_CFA_offset, column 0x11 */ .byte 0x2 .byte 0x8e /* DW_CFA_offset, column 0xe */ .byte 0x1 .byte 0x4 /* DW_CFA_advance_loc4 */ .4byte .LCFIA-.LCFI9 .byte 0xd /* DW_CFA_def_cfa_register */ .byte 0xe /* uleb128 0xe */ .align 2 .LEFDE3: --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 2002, 2003 Kaz Kojima SuperH 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> #define NGREGARG 4 #if defined(__SH4__) #define NFREGARG 8 #endif #if defined(__HITACHI__) #define STRUCT_VALUE_ADDRESS_WITH_ARG 1 #else #define STRUCT_VALUE_ADDRESS_WITH_ARG 0 #endif /* If the structure has essentialy an unique element, return its type. */ static int simple_type (ffi_type *arg) { if (arg->type != FFI_TYPE_STRUCT) return arg->type; else if (arg->elements[1]) return FFI_TYPE_STRUCT; return simple_type (arg->elements[0]); } static int return_type (ffi_type *arg) { unsigned short type; if (arg->type != FFI_TYPE_STRUCT) return arg->type; type = simple_type (arg->elements[0]); if (! arg->elements[1]) { switch (type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: return FFI_TYPE_INT; default: return type; } } /* gcc uses r0/r1 pair for some kind of structures. */ if (arg->size <= 2 * sizeof (int)) { int i = 0; ffi_type *e; while ((e = arg->elements[i++])) { type = simple_type (e); switch (type) { case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_INT: case FFI_TYPE_FLOAT: return FFI_TYPE_UINT64; default: break; } } } return FFI_TYPE_STRUCT; } /* 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; register unsigned int avn; register void **p_argv; register char *argp; register ffi_type **p_arg; int greg, ireg; #if defined(__SH4__) int freg = 0; #endif tmp = 0; argp = stack; if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) { *(void **) argp = ecif->rvalue; argp += 4; ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0; } else ireg = 0; /* Set arguments for registers. */ greg = ireg; avn = ecif->cif->nargs; p_argv = ecif->avalue; for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) { size_t z; z = (*p_arg)->size; if (z < sizeof(int)) { if (greg++ >= NGREGARG) continue; 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_STRUCT: *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); break; default: FFI_ASSERT(0); } argp += z; } else if (z == sizeof(int)) { #if defined(__SH4__) if ((*p_arg)->type == FFI_TYPE_FLOAT) { if (freg++ >= NFREGARG) continue; } else #endif { if (greg++ >= NGREGARG) continue; } *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); argp += z; } #if defined(__SH4__) else if ((*p_arg)->type == FFI_TYPE_DOUBLE) { if (freg + 1 >= NFREGARG) continue; freg = (freg + 1) & ~1; freg += 2; memcpy (argp, *p_argv, z); argp += z; } #endif else { int n = (z + sizeof (int) - 1) / sizeof (int); #if defined(__SH4__) if (greg + n - 1 >= NGREGARG) continue; greg += n; #else if (greg >= NGREGARG) continue; else if (greg + n - 1 >= NGREGARG) greg = NGREGARG; else greg += n; #endif memcpy (argp, *p_argv, z); argp += n * sizeof (int); } } /* Set arguments on stack. */ greg = ireg; #if defined(__SH4__) freg = 0; #endif p_argv = ecif->avalue; for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) { size_t z; z = (*p_arg)->size; if (z < sizeof(int)) { if (greg++ < NGREGARG) continue; 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_STRUCT: *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); break; default: FFI_ASSERT(0); } argp += z; } else if (z == sizeof(int)) { #if defined(__SH4__) if ((*p_arg)->type == FFI_TYPE_FLOAT) { if (freg++ < NFREGARG) continue; } else #endif { if (greg++ < NGREGARG) continue; } *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); argp += z; } #if defined(__SH4__) else if ((*p_arg)->type == FFI_TYPE_DOUBLE) { if (freg + 1 < NFREGARG) { freg = (freg + 1) & ~1; freg += 2; continue; } memcpy (argp, *p_argv, z); argp += z; } #endif else { int n = (z + sizeof (int) - 1) / sizeof (int); if (greg + n - 1 < NGREGARG) { greg += n; continue; } #if (! defined(__SH4__)) else if (greg < NGREGARG) { greg = NGREGARG; continue; } #endif memcpy (argp, *p_argv, z); argp += n * sizeof (int); } } return; } /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { int i, j; int size, type; int n, m; int greg; #if defined(__SH4__) int freg = 0; #endif cif->flags = 0; greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) && STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0; #if defined(__SH4__) for (i = j = 0; i < cif->nargs && j < 12; i++) { type = (cif->arg_types)[i]->type; switch (type) { case FFI_TYPE_FLOAT: if (freg >= NFREGARG) continue; freg++; cif->flags += ((cif->arg_types)[i]->type) << (2 * j); j++; break; case FFI_TYPE_DOUBLE: if ((freg + 1) >= NFREGARG) continue; freg = (freg + 1) & ~1; freg += 2; cif->flags += ((cif->arg_types)[i]->type) << (2 * j); j++; break; default: size = (cif->arg_types)[i]->size; n = (size + sizeof (int) - 1) / sizeof (int); if (greg + n - 1 >= NGREGARG) continue; greg += n; for (m = 0; m < n; m++) cif->flags += FFI_TYPE_INT << (2 * j++); break; } } #else for (i = j = 0; i < cif->nargs && j < 4; i++) { size = (cif->arg_types)[i]->size; n = (size + sizeof (int) - 1) / sizeof (int); if (greg >= NGREGARG) continue; else if (greg + n - 1 >= NGREGARG) greg = NGREGARG; else greg += n; for (m = 0; m < n; m++) cif->flags += FFI_TYPE_INT << (2 * j++); } #endif /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_STRUCT: cif->flags += (unsigned) (return_type (cif->rtype)) << 24; break; case FFI_TYPE_VOID: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: cif->flags += (unsigned) cif->rtype->type << 24; break; default: cif->flags += FFI_TYPE_INT << 24; break; } 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@*/ void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@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) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-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, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; default: FFI_ASSERT(0); break; } } extern void ffi_closure_SYSV (void); #if defined(__SH4__) 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) { unsigned int *tramp; FFI_ASSERT (cif->abi == FFI_GCC_SYSV); tramp = (unsigned int *) &closure->tramp[0]; #ifdef __LITTLE_ENDIAN__ tramp[0] = 0xd301d202; tramp[1] = 0x0009422b; #else tramp[0] = 0xd202d301; tramp[1] = 0x422b0009; #endif *(void **) &tramp[2] = (void *)closure; /* ctx */ *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */ closure->cif = cif; closure->fun = fun; closure->user_data = user_data; #if defined(__SH4__) /* Flush the icache. */ __ic_invalidate(&closure->tramp[0]); #endif return FFI_OK; } /* Basically the trampoline invokes ffi_closure_SYSV, and on * entry, r3 holds the address of the closure. * After storing the registers that could possibly contain * parameters to be passed into the stack frame and setting * up space for a return value, ffi_closure_SYSV invokes the * following helper function to do most of the work. */ #ifdef __LITTLE_ENDIAN__ #define OFS_INT8 0 #define OFS_INT16 0 #else #define OFS_INT8 3 #define OFS_INT16 2 #endif int ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, unsigned long *pgr, unsigned long *pfr, unsigned long *pst) { void **avalue; ffi_type **p_arg; int i, avn; int ireg, greg = 0; #if defined(__SH4__) int freg = 0; #endif ffi_cif *cif; double temp; cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); /* Copy the caller's structure return value address so that the closure returns the data directly to the caller. */ if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG) { rvalue = *pgr++; ireg = 1; } else ireg = 0; cif = closure->cif; greg = ireg; avn = cif->nargs; /* Grab the addresses of the arguments from the stack frame. */ for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) { size_t z; z = (*p_arg)->size; if (z < sizeof(int)) { if (greg++ >= NGREGARG) continue; z = sizeof(int); switch ((*p_arg)->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: avalue[i] = (((char *)pgr) + OFS_INT8); break; case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: avalue[i] = (((char *)pgr) + OFS_INT16); break; case FFI_TYPE_STRUCT: avalue[i] = pgr; break; default: FFI_ASSERT(0); } pgr++; } else if (z == sizeof(int)) { #if defined(__SH4__) if ((*p_arg)->type == FFI_TYPE_FLOAT) { if (freg++ >= NFREGARG) continue; avalue[i] = pfr; pfr++; } else #endif { if (greg++ >= NGREGARG) continue; avalue[i] = pgr; pgr++; } } #if defined(__SH4__) else if ((*p_arg)->type == FFI_TYPE_DOUBLE) { if (freg + 1 >= NFREGARG) continue; freg = (freg + 1) & ~1; freg += 2; avalue[i] = pfr; pfr += 2; } #endif else { int n = (z + sizeof (int) - 1) / sizeof (int); #if defined(__SH4__) if (greg + n - 1 >= NGREGARG) continue; greg += n; #else if (greg >= NGREGARG) continue; else if (greg + n - 1 >= NGREGARG) greg = NGREGARG; else greg += n; #endif avalue[i] = pgr; pgr += n; } } greg = ireg; #if defined(__SH4__) freg = 0; #endif for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) { size_t z; z = (*p_arg)->size; if (z < sizeof(int)) { if (greg++ < NGREGARG) continue; z = sizeof(int); switch ((*p_arg)->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: avalue[i] = (((char *)pst) + OFS_INT8); break; case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: avalue[i] = (((char *)pst) + OFS_INT16); break; case FFI_TYPE_STRUCT: avalue[i] = pst; break; default: FFI_ASSERT(0); } pst++; } else if (z == sizeof(int)) { #if defined(__SH4__) if ((*p_arg)->type == FFI_TYPE_FLOAT) { if (freg++ < NFREGARG) continue; } else #endif { if (greg++ < NGREGARG) continue; } avalue[i] = pst; pst++; } #if defined(__SH4__) else if ((*p_arg)->type == FFI_TYPE_DOUBLE) { if (freg + 1 < NFREGARG) { freg = (freg + 1) & ~1; freg += 2; continue; } avalue[i] = pst; pst += 2; } #endif else { int n = (z + sizeof (int) - 1) / sizeof (int); if (greg + n - 1 < NGREGARG) { greg += n; continue; } #if (! defined(__SH4__)) else if (greg < NGREGARG) { greg = NGREGARG; continue; } #endif avalue[i] = pst; pst += n; } } (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_SYSV how to perform return type promotions. */ return return_type (cif->rtype); } --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for SuperH. 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 /* ---- Generic type definitions ----------------------------------------- */ #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif #define FFI_CLOSURES 1 #define FFI_TRAMPOLINE_SIZE 16 #define FFI_NATIVE_RAW_API 0 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:24
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/mips In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/mips Added Files: ffi.c ffitarget.h n32.S o32.S Log Message: Importing libffi sources and build tools. --- NEW FILE: n32.S --- /* ----------------------------------------------------------------------- n32.S - Copyright (c) 1996, 1998 Red Hat, Inc. MIPS 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> /* Only build this code if we are compiling for n32 */ #if defined(FFI_MIPS_N32) #define callback a0 #define bytes a2 #define flags a3 #define raddr a4 #define fn a5 #define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG ) .text .align 2 .globl ffi_call_N32 .ent ffi_call_N32 ffi_call_N32: # Prologue SUBU $sp, SIZEOF_FRAME # Frame size 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 move $fp, $sp move t9, callback # callback function pointer REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn # Allocate at least 4 words in the argstack move v0, bytes bge bytes, 4 * FFI_SIZEOF_ARG, bigger LI v0, 4 * FFI_SIZEOF_ARG b sixteen bigger: ADDU t4, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned and v0, t4, -2 * FFI_SIZEOF_ARG # to a proper boundry. sixteen: SUBU $sp, $sp, v0 # move the stack pointer to reflect the # arg space ADDU a0, $sp, 0 # 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 # Fix the stack if there are more than 8 64bit slots worth # of arguments. # Load the number of bytes 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 bltz t8, loadregs add 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 and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg1_floatp REG_L a0, 0*FFI_SIZEOF_ARG(t9) b arg1_next arg1_floatp: bne t4, FFI_TYPE_FLOAT, arg1_doublep l.s $f12, 0*FFI_SIZEOF_ARG(t9) b arg1_next arg1_doublep: l.d $f12, 0*FFI_SIZEOF_ARG(t9) arg1_next: add t4, t6, 0 SRL t4, 1*FFI_FLAG_BITS and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg2_floatp REG_L a1, 1*FFI_SIZEOF_ARG(t9) b arg2_next arg2_floatp: bne t4, FFI_TYPE_FLOAT, arg2_doublep l.s $f13, 1*FFI_SIZEOF_ARG(t9) b arg2_next arg2_doublep: l.d $f13, 1*FFI_SIZEOF_ARG(t9) arg2_next: add t4, t6, 0 SRL t4, 2*FFI_FLAG_BITS and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg3_floatp REG_L a2, 2*FFI_SIZEOF_ARG(t9) b arg3_next arg3_floatp: bne t4, FFI_TYPE_FLOAT, arg3_doublep l.s $f14, 2*FFI_SIZEOF_ARG(t9) b arg3_next arg3_doublep: l.d $f14, 2*FFI_SIZEOF_ARG(t9) arg3_next: add t4, t6, 0 SRL t4, 3*FFI_FLAG_BITS and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg4_floatp REG_L a3, 3*FFI_SIZEOF_ARG(t9) b arg4_next arg4_floatp: bne t4, FFI_TYPE_FLOAT, arg4_doublep l.s $f15, 3*FFI_SIZEOF_ARG(t9) b arg4_next arg4_doublep: l.d $f15, 3*FFI_SIZEOF_ARG(t9) arg4_next: add t4, t6, 0 SRL t4, 4*FFI_FLAG_BITS and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg5_floatp REG_L a4, 4*FFI_SIZEOF_ARG(t9) b arg5_next arg5_floatp: bne t4, FFI_TYPE_FLOAT, arg5_doublep l.s $f16, 4*FFI_SIZEOF_ARG(t9) b arg5_next arg5_doublep: l.d $f16, 4*FFI_SIZEOF_ARG(t9) arg5_next: add t4, t6, 0 SRL t4, 5*FFI_FLAG_BITS and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg6_floatp REG_L a5, 5*FFI_SIZEOF_ARG(t9) b arg6_next arg6_floatp: bne t4, FFI_TYPE_FLOAT, arg6_doublep l.s $f17, 5*FFI_SIZEOF_ARG(t9) b arg6_next arg6_doublep: l.d $f17, 5*FFI_SIZEOF_ARG(t9) arg6_next: add t4, t6, 0 SRL t4, 6*FFI_FLAG_BITS and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg7_floatp REG_L a6, 6*FFI_SIZEOF_ARG(t9) b arg7_next arg7_floatp: bne t4, FFI_TYPE_FLOAT, arg7_doublep l.s $f18, 6*FFI_SIZEOF_ARG(t9) b arg7_next arg7_doublep: l.d $f18, 6*FFI_SIZEOF_ARG(t9) arg7_next: add t4, t6, 0 SRL t4, 7*FFI_FLAG_BITS and t4, ((1<<FFI_FLAG_BITS)-1) bnez t4, arg8_floatp REG_L a7, 7*FFI_SIZEOF_ARG(t9) b arg8_next arg8_floatp: bne t4, FFI_TYPE_FLOAT, arg8_doublep l.s $f19, 7*FFI_SIZEOF_ARG(t9) b arg8_next arg8_doublep: l.d $f19, 7*FFI_SIZEOF_ARG(t9) arg8_next: callit: # Load the function pointer REG_L t9, 5*FFI_SIZEOF_ARG($fp) # If the return value pointer is NULL, assume no return value. REG_L t5, 4*FFI_SIZEOF_ARG($fp) beqz t5, noretval # Shift the return type flag over SRL t6, 8*FFI_FLAG_BITS bne t6, FFI_TYPE_INT, retfloat jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) REG_S v0, 0(t4) b epilogue retfloat: bne t6, FFI_TYPE_FLOAT, retdouble jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.s $f0, 0(t4) b epilogue retdouble: bne t6, FFI_TYPE_DOUBLE, retstruct_d jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.d $f0, 0(t4) b epilogue retstruct_d: bne t6, FFI_TYPE_STRUCT_D, retstruct_f jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.d $f0, 0(t4) b epilogue retstruct_f: bne t6, FFI_TYPE_STRUCT_F, retstruct_d_d jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.s $f0, 0(t4) b epilogue retstruct_d_d: bne t6, FFI_TYPE_STRUCT_DD, retstruct_f_f jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.d $f0, 0(t4) s.d $f2, 8(t4) b epilogue retstruct_f_f: bne t6, FFI_TYPE_STRUCT_FF, retstruct_d_f jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.s $f0, 0(t4) s.s $f2, 4(t4) b epilogue retstruct_d_f: bne t6, FFI_TYPE_STRUCT_DF, retstruct_f_d jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.d $f0, 0(t4) s.s $f2, 8(t4) b epilogue retstruct_f_d: bne t6, FFI_TYPE_STRUCT_FD, retstruct_small jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.s $f0, 0(t4) s.d $f2, 8(t4) b epilogue retstruct_small: bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2 jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) REG_S v0, 0(t4) b epilogue retstruct_small2: bne t6, FFI_TYPE_STRUCT_SMALL2, retstruct jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) REG_S v0, 0(t4) REG_S v1, 8(t4) b epilogue retstruct: noretval: jal t9 # Epilogue epilogue: move $sp, $fp REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address ADDU $sp, SIZEOF_FRAME # Fix stack pointer j ra .end ffi_call_N32 #endif --- NEW FILE: o32.S --- /* ----------------------------------------------------------------------- o32.S - Copyright (c) 1996, 1998 Red Hat, Inc. MIPS 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> /* Only build this code if we are compiling for o32 */ #if defined(FFI_MIPS_O32) #define callback a0 #define bytes a2 #define flags a3 #define SIZEOF_FRAME ( 4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG ) .text .align 2 .globl ffi_call_O32 .ent ffi_call_O32 ffi_call_O32: # Prologue SUBU $sp, SIZEOF_FRAME # Frame size 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 move $fp, $sp move t9, callback # callback function pointer REG_S flags, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp) # flags # Allocate at least 4 words in the argstack move v0, bytes bge bytes, 4 * FFI_SIZEOF_ARG, bigger LI v0, 4 * FFI_SIZEOF_ARG b sixteen bigger: ADDU t0, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned and v0, t0, -2 * FFI_SIZEOF_ARG # to an 8 byte boundry sixteen: SUBU $sp, $sp, v0 # move the stack pointer to reflect the # arg space ADDU a0, $sp, 4 * FFI_SIZEOF_ARG ADDU a3, $fp, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG jal t9 REG_L t0, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp) # load the flags word add t2, t0, 0 # and copy it into t2 and t0, ((1<<4)-1) # mask out the return type SRL t2, 4 # shift our arg info ADDU $sp, $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args bnez t0, pass_d # make it quick for int REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs. REG_L a2, 2*FFI_SIZEOF_ARG($sp) REG_L a3, 3*FFI_SIZEOF_ARG($sp) b call_it pass_d: bne t0, FFI_ARGS_D, pass_f l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args REG_L a2, 2*FFI_SIZEOF_ARG($sp) # passing a double REG_L a3, 3*FFI_SIZEOF_ARG($sp) b call_it pass_f: bne t0, FFI_ARGS_F, pass_d_d l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args REG_L a1, 1*FFI_SIZEOF_ARG($sp) # passing a float REG_L a2, 2*FFI_SIZEOF_ARG($sp) REG_L a3, 3*FFI_SIZEOF_ARG($sp) b call_it pass_d_d: bne t0, FFI_ARGS_DD, pass_f_f l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing two doubles b call_it pass_f_f: bne t0, FFI_ARGS_FF, pass_d_f l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args l.s $f14, 1*FFI_SIZEOF_ARG($sp) # passing two floats REG_L a2, 2*FFI_SIZEOF_ARG($sp) REG_L a3, 3*FFI_SIZEOF_ARG($sp) b call_it pass_d_f: bne t0, FFI_ARGS_DF, pass_f_d l.d $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args l.s $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float REG_L a3, 3*FFI_SIZEOF_ARG($sp) b call_it pass_f_d: # assume that the only other combination must be float then double # bne t0, FFI_ARGS_F_D, call_it l.s $f12, 0*FFI_SIZEOF_ARG($sp) # load $fp regs from args l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float call_it: # Load the function pointer REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp) # If the return value pointer is NULL, assume no return value. REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) beqz t1, noretval bne t2, FFI_TYPE_INT, retfloat jal t9 REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) REG_S v0, 0(t0) b epilogue retfloat: bne t2, FFI_TYPE_FLOAT, retdouble jal t9 REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) s.s $f0, 0(t0) b epilogue retdouble: bne t2, FFI_TYPE_DOUBLE, noretval jal t9 REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp) s.d $f0, 0(t0) b epilogue noretval: jal t9 # Epilogue epilogue: move $sp, $fp REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address ADDU $sp, SIZEOF_FRAME # Fix stack pointer j ra .end ffi_call_O32 #endif --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1996 Red Hat, Inc. MIPS 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> #if _MIPS_SIM == _ABIN32 #define FIX_ARGP \ FFI_ASSERT(argp <= &stack[bytes]); \ if (argp == &stack[bytes]) \ { \ argp = stack; \ ffi_stop_here(); \ } #else #define FIX_ARGP #endif /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ static void ffi_prep_args(char *stack, extended_cif *ecif, int bytes, int flags) { register int i; register void **p_argv; register char *argp; register ffi_type **p_arg; #if _MIPS_SIM == _ABIN32 /* 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. */ if (bytes > 8 * FFI_SIZEOF_ARG) argp = &stack[bytes - (8 * FFI_SIZEOF_ARG)]; else argp = stack; #else argp = stack; #endif memset(stack, 0, bytes); #if _MIPS_SIM == _ABIN32 if ( ecif->cif->rstruct_flag != 0 ) #else if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) #endif { *(ffi_arg *) argp = (ffi_arg) ecif->rvalue; argp += sizeof(ffi_arg); FIX_ARGP; } p_argv = ecif->avalue; for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++) { size_t z; /* Align if necessary */ if (((*p_arg)->alignment - 1) & (unsigned) argp) { argp = (char *) ALIGN(argp, (*p_arg)->alignment); FIX_ARGP; } #if _MIPS_SIM == _ABIO32 #define OFFSET 0 #else #define OFFSET sizeof(int) #endif z = (*p_arg)->size; if (z < sizeof(ffi_arg)) { z = sizeof(ffi_arg); switch ((*p_arg)->type) { case FFI_TYPE_SINT8: *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv); break; case FFI_TYPE_UINT8: *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv); break; case FFI_TYPE_SINT16: *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv); break; case FFI_TYPE_UINT16: *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv); break; case FFI_TYPE_SINT32: *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv); break; case FFI_TYPE_UINT32: case FFI_TYPE_POINTER: *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT32 *)(* p_argv); break; /* This can only happen with 64bit slots */ case FFI_TYPE_FLOAT: *(float *) argp = *(float *)(* p_argv); break; /* Handle small structures */ case FFI_TYPE_STRUCT: memcpy(argp, *p_argv, (*p_arg)->size); break; default: FFI_ASSERT(0); } } else { #if _MIPS_SIM == _ABIO32 memcpy(argp, *p_argv, z); #else { unsigned end = (unsigned) argp+z; unsigned cap = (unsigned) stack+bytes; /* Check if the data will fit within the register space. Handle it if it doesn't. */ if (end <= cap) memcpy(argp, *p_argv, z); else { unsigned portion = end - cap; memcpy(argp, *p_argv, portion); argp = stack; memcpy(argp, (void*)((unsigned)(*p_argv)+portion), z - portion); } } #endif } p_argv++; argp += z; FIX_ARGP; } return; } #if _MIPS_SIM == _ABIN32 /* 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 is passed in a floating point register. Any other chunk is 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) { unsigned flags = 0; unsigned index = 0; ffi_type *e; while (e = arg->elements[index]) { if (e->type == FFI_TYPE_DOUBLE) { flags += (FFI_TYPE_DOUBLE << *shift); *shift += FFI_FLAG_BITS; } else if (e->type == FFI_TYPE_STRUCT) flags += calc_n32_struct_flags(e, shift); else *shift += FFI_FLAG_BITS; index++; } return flags; } unsigned calc_n32_return_struct_flags(ffi_type *arg) { unsigned flags = 0; unsigned index = 0; unsigned small = FFI_TYPE_SMALLSTRUCT; ffi_type *e; /* Returning structures under n32 is a tricky thing. A struct with only one or two floating point fields is returned in $f0 (and $f2 if necessary). Any other struct results at most 128 bits are returned in $2 (the first 64 bits) and $3 (remainder, if necessary). Larger structs are handled normally. */ if (arg->size > 16) return 0; if (arg->size > 8) small = FFI_TYPE_SMALLSTRUCT2; e = arg->elements[0]; if (e->type == FFI_TYPE_DOUBLE) flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS; else if (e->type == FFI_TYPE_FLOAT) flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS; if (flags && (e = arg->elements[1])) { if (e->type == FFI_TYPE_DOUBLE) flags += FFI_TYPE_DOUBLE; else if (e->type == FFI_TYPE_FLOAT) flags += FFI_TYPE_FLOAT; else return small; if (flags && (arg->elements[2])) { /* There are three arguments and the first two are floats! This must be passed the old way. */ return small; } } else if (!flags) return small; return flags; } #endif /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { cif->flags = 0; #if _MIPS_SIM == _ABIO32 /* Set the flags necessary for O32 processing */ if (cif->rtype->type != FFI_TYPE_STRUCT) { if (cif->nargs > 0) { switch ((cif->arg_types)[0]->type) { case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags += (cif->arg_types)[0]->type; break; default: break; } if (cif->nargs > 1) { /* Only handle the second argument if the first is a float or double. */ if (cif->flags) { switch ((cif->arg_types)[1]->type) { case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS; break; default: break; } } } } } /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: case FFI_TYPE_STRUCT: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); break; default: cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); break; } #endif #if _MIPS_SIM == _ABIN32 /* Set the flags necessary for N32 processing */ { unsigned shift = 0; unsigned count = (cif->nargs < 8) ? cif->nargs : 8; unsigned index = 0; unsigned struct_flags = 0; if (cif->rtype->type == FFI_TYPE_STRUCT) { struct_flags = calc_n32_return_struct_flags(cif->rtype); if (struct_flags == 0) { /* This means that the structure is being passed as a hidden argument */ shift = FFI_FLAG_BITS; count = (cif->nargs < 7) ? cif->nargs : 7; cif->rstruct_flag = !0; } else cif->rstruct_flag = 0; } else cif->rstruct_flag = 0; while (count-- > 0) { 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; break; case FFI_TYPE_STRUCT: cif->flags += calc_n32_struct_flags((cif->arg_types)[index], &shift); break; default: shift += FFI_FLAG_BITS; } index++; } /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_STRUCT: { if (struct_flags == 0) { /* The structure is returned through a hidden first argument. Do nothing, 'cause FFI_TYPE_VOID is 0 */ } else { /* The structure is returned via some tricky mechanism */ cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8)); } break; } case FFI_TYPE_VOID: /* Do nothing, 'cause FFI_TYPE_VOID is 0 */ break; case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8); break; default: cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); break; } } #endif return FFI_OK; } /* Low level routine for calling O32 functions */ extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), extended_cif *, unsigned, unsigned, unsigned *, void (*)()); /* Low level routine for calling N32 functions */ extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), extended_cif *, unsigned, unsigned, unsigned *, void (*)()); void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, 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) && (cif->rtype->type == FFI_TYPE_STRUCT)) ecif.rvalue = alloca(cif->rtype->size); else ecif.rvalue = rvalue; switch (cif->abi) { #if _MIPS_SIM == _ABIO32 case FFI_O32: ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; #endif #if _MIPS_SIM == _ABIN32 case FFI_N32: ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; #endif default: FFI_ASSERT(0); break; } } --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for MIPS. 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 #ifndef LIBFFI_ASM #include <sgidefs.h> #endif #if !defined(_MIPS_SIM) -- something is very wrong -- #else # if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64)) # define FFI_MIPS_N32 # else # if _MIPS_SIM==_ABIO32 && defined(_ABIO32) # define FFI_MIPS_O32 # else -- this is an unsupported platform -- # endif # endif #endif #ifdef FFI_MIPS_O32 /* O32 stack frames have 32bit integer args */ #define FFI_SIZEOF_ARG 4 #else /* N32 and N64 frames have 64bit integer args */ #define FFI_SIZEOF_ARG 8 #endif #define FFI_FLAG_BITS 2 /* SGI's strange assembler requires that we multiply by 4 rather than shift left by FFI_FLAG_BITS */ #define FFI_ARGS_D FFI_TYPE_DOUBLE #define FFI_ARGS_F FFI_TYPE_FLOAT #define FFI_ARGS_DD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE #define FFI_ARGS_FF FFI_TYPE_FLOAT * 4 + FFI_TYPE_FLOAT #define FFI_ARGS_FD FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT #define FFI_ARGS_DF FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE /* Needed for N32 structure returns */ #define FFI_TYPE_SMALLSTRUCT FFI_TYPE_UINT8 #define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8 #if 0 /* The SGI assembler can't handle this.. */ #define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT /* (and so on) */ #else /* ...so we calculate these by hand! */ #define FFI_TYPE_STRUCT_D 61 #define FFI_TYPE_STRUCT_F 45 #define FFI_TYPE_STRUCT_DD 253 #define FFI_TYPE_STRUCT_FF 173 #define FFI_TYPE_STRUCT_FD 237 #define FFI_TYPE_STRUCT_DF 189 #define FFI_TYPE_STRUCT_SMALL 93 #define FFI_TYPE_STRUCT_SMALL2 109 #endif #ifdef LIBFFI_ASM #define v0 $2 #define v1 $3 #define a0 $4 #define a1 $5 #define a2 $6 #define a3 $7 #define a4 $8 #define a5 $9 #define a6 $10 #define a7 $11 #define t0 $8 #define t1 $9 #define t2 $10 #define t3 $11 #define t4 $12 #define t5 $13 #define t6 $14 #define t7 $15 #define t8 $24 #define t9 $25 #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 #else /* !FFI_MIPS_O32 */ #define REG_L ld #define REG_S sd #define SUBU dsubu #define ADDU daddu #define SRL dsrl #define LI dli #endif /* !FFI_MIPS_O32 */ #else /* !LIBFFI_ASM */ #ifdef FFI_MIPS_O32 /* O32 stack frames have 32bit integer args */ typedef unsigned int ffi_arg __attribute__((__mode__(__SI__))); typedef signed int ffi_sarg __attribute__((__mode__(__SI__))); #else /* N32 and N64 frames have 64bit integer args */ typedef unsigned int ffi_arg __attribute__((__mode__(__DI__))); typedef signed int ffi_sarg __attribute__((__mode__(__DI__))); #endif typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_O32, FFI_N32, FFI_N64, #ifdef FFI_MIPS_O32 FFI_DEFAULT_ABI = FFI_O32, #else FFI_DEFAULT_ABI = FFI_N32, #endif FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag #endif /* !LIBFFI_ASM */ /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 0 #define FFI_NATIVE_RAW_API 0 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:24
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/pa In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/pa Added Files: ffi.c ffitarget.h linux.S Log Message: Importing libffi sources and build tools. --- NEW FILE: linux.S --- /* ----------------------------------------------------------------------- linux.S - (c) 2003-2004 Randolph Chung <ta...@de...> HPPA 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .text .align 4 /* void ffi_call_LINUX(void (*)(char *, extended_cif *), extended_cif *ecif, unsigned bytes, unsigned flags, unsigned *rvalue, void (*fn)()); */ .export ffi_call_LINUX,code .import ffi_prep_args_LINUX,code .type ffi_call_LINUX, @function .LFB1: ffi_call_LINUX: .proc .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4 .entry stw %rp, -20(%sp) copy %r3, %r1 .LCFI11: copy %sp, %r3 .LCFI12: /* Setup the stack for calling prep_args... We want the stack to look like this: [ Previous stack ] <- %r3 [ 64-bytes register save area ] <- %r4 [ Stack space for actual call, passed as ] <- %arg0 [ arg0 to ffi_prep_args_LINUX ] [ Stack for calling prep_args ] <- %sp */ stwm %r1, 64(%sp) stw %r4, 12(%r3) .LCFI13: copy %sp, %r4 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 ldo 64(%arg0), %sp ldo -64(%sp), %sp /* now %sp should point where %arg0 was pointing. */ /* Load the arguments that should be passed in registers The fp args were loaded by the prep_args function. */ ldw -36(%sp), %arg0 ldw -40(%sp), %arg1 ldw -44(%sp), %arg2 ldw -48(%sp), %arg3 /* in case the function is going to return a structure we need to give it a place to put the result. */ ldw -52(%r3), %ret0 /* %ret0 <- rvalue */ ldw -56(%r3), %r22 /* %r22 <- function to call */ bl $$dyncall, %r31 /* Call the user function */ copy %r31, %rp /* Prepare to store the result; we need to recover flags and rvalue. */ ldw -48(%r3), %r21 /* r21 <- flags */ ldw -52(%r3), %r20 /* r20 <- rvalue */ /* Store the result according to the return type. */ checksmst1: comib,<>,n FFI_TYPE_SMALL_STRUCT1, %r21, checksmst2 /* There is maybe a better way to handle 3 byte structs. */ sh2add %ret0,0,%ret0 sh2add %ret0,0,%ret0 sh2add %ret0,0,%ret0 sh2add %ret0,0,%ret0 b done stw %ret0, 0(%r20) checksmst2: comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, checkint8 /* Up to now I don't have a way to handle 6/7 byte structs. The values are left bounded in the registers. In the struct itself they are left bounded. */ 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: /* all done, return */ copy %r4, %sp /* pop arg stack */ ldw 12(%r3), %r4 ldwm -64(%sp), %r3 /* .. and pop stack */ ldw -20(%sp), %rp bv %r0(%rp) nop .exit .procend .LFE1: /* void ffi_closure_LINUX(void); Called with closure argument in %r21 */ .export ffi_closure_LINUX,code .import ffi_closure_inner_LINUX,code .type ffi_closure_LINUX, @function .LFB2: ffi_closure_LINUX: .proc .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 .entry stw %rp, -20(%sp) .LCFI20: copy %r3, %r1 .LCFI21: copy %sp, %r3 .LCFI22: stwm %r1, 64(%sp) /* Put arguments onto the stack and call ffi_closure_inner. */ stw %arg0, -36(%r3) stw %arg1, -40(%r3) stw %arg2, -44(%r3) stw %arg3, -48(%r3) copy %r21, %arg0 bl ffi_closure_inner_LINUX, %r2 copy %r3, %arg1 ldwm -64(%sp), %r3 ldw -20(%sp), %rp ldw -36(%sp), %ret0 bv %r0(%r2) ldw -40(%sp), %ret1 .exit .procend .LFE2: .section ".eh_frame",EH_FRAME_FLAGS,@progbits .Lframe1: .word .LECIE1-.LSCIE1 ;# Length of Common Information Entry .LSCIE1: .word 0x0 ;# CIE Identifier Tag .byte 0x1 ;# CIE Version .ascii "\0" ;# CIE Augmentation .uleb128 0x1 ;# CIE Code Alignment Factor .sleb128 4 ;# CIE Data Alignment Factor .byte 0x2 ;# CIE RA Column .byte 0xc ;# DW_CFA_def_cfa .uleb128 0x1e .uleb128 0x0 .align 4 .LECIE1: .LSFDE1: .word .LEFDE1-.LASFDE1 ;# FDE Length .LASFDE1: .word .LASFDE1-.Lframe1 ;# FDE CIE offset .word .LFB1 ;# FDE initial location .word .LFE1-.LFB1 ;# FDE address range .byte 0x4 ;# DW_CFA_advance_loc4 .word .LCFI11-.LFB1 .byte 0x83 ;# DW_CFA_offset, column 0x3 .uleb128 0x0 .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20] .uleb128 0x2 .sleb128 -5 .byte 0x4 ;# DW_CFA_advance_loc4 .word .LCFI12-.LCFI11 .byte 0xd ;# DW_CFA_def_cfa_register = r3 .uleb128 0x3 .byte 0x4 ;# DW_CFA_advance_loc4 .word .LCFI13-.LCFI12 .byte 0x84 ;# DW_CFA_offset, column 0x4 .uleb128 0x3 .align 4 .LEFDE1: .LSFDE2: .word .LEFDE2-.LASFDE2 ;# FDE Length .LASFDE2: .word .LASFDE2-.Lframe1 ;# FDE CIE offset .word .LFB2 ;# FDE initial location .word .LFE2-.LFB2 ;# FDE address range .byte 0x4 ;# DW_CFA_advance_loc4 .word .LCFI21-.LFB2 .byte 0x83 ;# DW_CFA_offset, column 0x3 .uleb128 0x0 .byte 0x11 ;# DW_CFA_offset_extended_sf .uleb128 0x2 .sleb128 -5 .byte 0x4 ;# DW_CFA_advance_loc4 .word .LCFI12-.LCFI11 .byte 0xd ;# DW_CFA_def_cfa_register = r3 .uleb128 0x3 .align 4 .LEFDE2: --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - (c) 2003-2004 Randolph Chung <ta...@de...> HPPA 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> #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 debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0) 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. */ if (sz <= 1) return FFI_TYPE_UINT8; else if (sz == 2) return FFI_TYPE_UINT16; else if (sz == 3) return FFI_TYPE_SMALL_STRUCT1; else if (sz == 4) return FFI_TYPE_UINT32; else if (sz <= 6) return FFI_TYPE_SMALL_STRUCT2; else if (sz <= 8) return FFI_TYPE_UINT64; else return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */ } /* PA has a downward growing stack, which looks like this: Offset [ Variable args ] SP = (4*(n+9)) arg word N ... SP-52 arg word 4 [ Fixed args ] SP-48 arg word 3 SP-44 arg word 2 SP-40 arg word 1 SP-36 arg word 0 [ 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 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@*/ { register unsigned int i; register ffi_type **p_arg; register void **p_argv; unsigned int slot = FIRST_ARG_SLOT - 1; char *dest_cpy; debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, ecif, bytes); p_arg = ecif->cif->arg_types; p_argv = ecif->avalue; for (i = 0; i < ecif->cif->nargs; i++) { int type = (*p_arg)->type; 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); *(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; break; case FFI_TYPE_FLOAT: /* First 4 args go in fr4L - fr7L */ slot++; 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; } break; 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) { slot++; dest_cpy = (char *)(stack - slot); dest_cpy += 4 - (*p_arg)->size; memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size); } else if ((*p_arg)->size <= 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); } break; default: FFI_ASSERT(0); } p_arg++; p_argv++; } /* Make sure we didn't mess up and scribble on the stack. */ { int n; debug(5, "Stack setup:\n"); for (n = 0; n < (bytes + 3) / 4; n++) { if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); } debug(5, "%08x ", *(stack - n)); } debug(5, "\n"); } FFI_ASSERT(slot * 4 <= bytes); return; } static void ffi_size_stack_LINUX(ffi_cif *cif) { ffi_type **ptr; int i; int z = 0; /* # stack slots */ for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++) { int type = (*ptr)->type; switch (type) { case FFI_TYPE_DOUBLE: case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: z += 2 + (z & 1); /* must start on even regs, so we may waste one */ break; case FFI_TYPE_STRUCT: z += 1; /* pass by ptr, callee will copy */ break; default: /* <= 32-bit values */ z++; } } /* We can fit up to 6 args in the default 64-byte stack frame, if we need more, we need more stack. */ if (z <= 6) cif->bytes = MIN_STACK_SIZE; /* min stack size */ else cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE); debug(3, "Calculated stack size is %u bytes\n", cif->bytes); } /* 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: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags = (unsigned) cif->rtype->type; break; 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 in one register. If the size is smaller or equal 8 bytes than we return the result in two registers. But if the size is bigger than 8 bytes, we work with pointers. */ cif->flags = ffi_struct_type(cif->rtype); break; case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: cif->flags = FFI_TYPE_UINT64; break; default: cif->flags = FFI_TYPE_INT; break; } /* Lucky us, because of the unique PA ABI we get to do our own stack sizing. */ switch (cif->abi) { case FFI_LINUX: ffi_size_stack_LINUX(cif); break; default: FFI_ASSERT(0); break; } return FFI_OK; } /*@-declundef@*/ /*@-exportheader@*/ extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned), /*@out@*/ extended_cif *, unsigned, unsigned, /*@out@*/ unsigned *, void (*fn)()); /*@=declundef@*/ /*@=exportheader@*/ void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@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) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-sysunrecog@*/ ecif.rvalue = alloca(cif->rtype->size); /*@=sysunrecog@*/ } else ecif.rvalue = rvalue; 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, cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; default: FFI_ASSERT(0); break; } } #if FFI_CLOSURES /* This is more-or-less an inverse of ffi_call -- we have arguments on 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_cif *cif; void **avalue; void *rvalue; 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; register UINT32 r28 asm("r28"); cif = closure->cif; /* If returning via structure, callee will write to our pointer. */ if (cif->flags == FFI_TYPE_STRUCT) rvalue = (void *)r28; else rvalue = &ret[0]; avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG); avn = cif->nargs; p_arg = cif->arg_types; for (i = 0; i < avn; i++) { int type = (*p_arg)->type; switch (type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: 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++; avalue[i] = (void *)(stack - slot); break; case FFI_TYPE_FLOAT: slot++; switch (slot - FIRST_ARG_SLOT) { case 0: fstw(fr4, (void *)(stack - slot)); break; case 1: fstw(fr5, (void *)(stack - slot)); break; case 2: fstw(fr6, (void *)(stack - slot)); break; case 3: fstw(fr7, (void *)(stack - slot)); break; } avalue[i] = (void *)(stack - slot); break; case FFI_TYPE_DOUBLE: slot += 2; if (slot & 1) slot++; switch (slot - FIRST_ARG_SLOT + 1) { case 2: fstd(fr5, (void *)(stack - slot)); break; case 4: fstd(fr7, (void *)(stack - slot)); break; } avalue[i] = (void *)(stack - slot); break; 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) { 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++; avalue[i] = (void *) *(stack - slot); } break; default: FFI_ASSERT(0); } p_arg++; } /* Invoke the closure. */ (closure->fun) (cif, rvalue, avalue, closure->user_data); debug(3, "after calling function, ret[0] = %d, ret[1] = %d\n", ret[0], ret[1]); /* Store the result */ switch (cif->flags) { case FFI_TYPE_UINT8: *(stack - FIRST_ARG_SLOT) = *(UINT8 *)&ret[0]; break; case FFI_TYPE_SINT8: *(stack - FIRST_ARG_SLOT) = *(SINT8 *)&ret[0]; break; case FFI_TYPE_UINT16: *(stack - FIRST_ARG_SLOT) = *(UINT16 *)&ret[0]; break; case FFI_TYPE_SINT16: *(stack - FIRST_ARG_SLOT) = *(SINT16 *)&ret[0]; break; case FFI_TYPE_INT: case FFI_TYPE_UINT32: *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0]; break; case FFI_TYPE_SINT32: *(stack - FIRST_ARG_SLOT) = *(SINT32 *)&ret[0]; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0]; *(stack - FIRST_ARG_SLOT - 1) = *(UINT32 *)&ret[1]; break; case FFI_TYPE_DOUBLE: fldd(rvalue, fr4); break; case FFI_TYPE_FLOAT: fldw(rvalue, fr4); break; case FFI_TYPE_STRUCT: /* Don't need a return value, done by caller. */ break; case FFI_TYPE_SMALL_STRUCT1: tmp = (void*)(stack - FIRST_ARG_SLOT); tmp += 4 - cif->rtype->size; memcpy((void*)tmp, &ret[0], cif->rtype->size); break; case FFI_TYPE_SMALL_STRUCT2: *(stack - FIRST_ARG_SLOT) = ret[0]; *(stack - FIRST_ARG_SLOT - 1) = ret[1]; break; case FFI_TYPE_POINTER: case FFI_TYPE_VOID: break; default: debug(0, "assert with cif->flags: %d\n",cif->flags); FFI_ASSERT(0); break; } return FFI_OK; } /* Fill in a closure to refer to the specified fun and user_data. cif specifies the argument and result types for fun. The cif must already be prep'ed. */ void ffi_closure_LINUX(void); ffi_status ffi_prep_closure (ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data) { UINT32 *tramp = (UINT32 *)(closure->tramp); FFI_ASSERT (cif->abi == FFI_LINUX); /* 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); /* 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 */)); closure->cif = cif; closure->user_data = user_data; closure->fun = fun; return FFI_OK; } #endif --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for hppa. 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 ----------------------------------- */ #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, #ifdef PA FFI_LINUX, FFI_DEFAULT_ABI = FFI_LINUX, #endif FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 #define FFI_TRAMPOLINE_SIZE 32 #define FFI_TYPE_SMALL_STRUCT1 -1 #define FFI_TYPE_SMALL_STRUCT2 -2 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:24
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/s390 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/s390 Added Files: ffi.c ffitarget.h sysv.S Log Message: Importing libffi sources and build tools. --- NEW FILE: sysv.S --- /* ----------------------------------------------------------------------- sysv.S - Copyright (c) 2000 Software AG S390 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #ifndef __s390x__ .text # r2: cif->bytes # r3: &ecif # r4: ffi_prep_args # r5: ret_type # r6: ecif.rvalue # ov: fn # This assumes we are using gas. .globl ffi_call_SYSV .type ffi_call_SYSV,%function ffi_call_SYSV: .LFB1: stm %r6,%r15,24(%r15) # Save registers .LCFI0: basr %r13,0 # Set up base register .Lbase: lr %r11,%r15 # Set up frame pointer .LCFI1: sr %r15,%r2 ahi %r15,-96-48 # Allocate stack lr %r8,%r6 # Save ecif.rvalue sr %r9,%r9 ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address l %r7,96(%r11) # Load function address st %r11,0(%r15) # Set up back chain ahi %r11,-48 # Register save area .LCFI2: la %r2,96(%r15) # Save area # r3 already holds &ecif basr %r14,%r4 # Call ffi_prep_args lm %r2,%r6,0(%r11) # Load arguments ld %f0,32(%r11) ld %f2,40(%r11) la %r14,0(%r13,%r9) # Set return address br %r7 # ... and call function .LretNone: # Return void l %r4,48+56(%r11) lm %r6,%r15,48+24(%r11) br %r4 .LretFloat: l %r4,48+56(%r11) ste %f0,0(%r8) # Return float lm %r6,%r15,48+24(%r11) br %r4 .LretDouble: l %r4,48+56(%r11) std %f0,0(%r8) # Return double lm %r6,%r15,48+24(%r11) br %r4 .LretInt32: l %r4,48+56(%r11) st %r2,0(%r8) # Return int lm %r6,%r15,48+24(%r11) br %r4 .LretInt64: l %r4,48+56(%r11) stm %r2,%r3,0(%r8) # Return long long lm %r6,%r15,48+24(%r11) br %r4 .Ltable: .byte .LretNone-.Lbase # FFI390_RET_VOID .byte .LretNone-.Lbase # FFI390_RET_STRUCT .byte .LretFloat-.Lbase # FFI390_RET_FLOAT .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE .byte .LretInt32-.Lbase # FFI390_RET_INT32 .byte .LretInt64-.Lbase # FFI390_RET_INT64 .LFE1: .ffi_call_SYSV_end: .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV .globl ffi_closure_SYSV .type ffi_closure_SYSV,%function ffi_closure_SYSV: .LFB2: stm %r12,%r15,48(%r15) # Save registers .LCFI10: basr %r13,0 # Set up base register .Lcbase: stm %r2,%r6,8(%r15) # Save arguments std %f0,64(%r15) std %f2,72(%r15) lr %r1,%r15 # Set up stack frame ahi %r15,-96 .LCFI11: l %r12,.Lchelper-.Lcbase(%r13) # Get helper function lr %r2,%r0 # Closure la %r3,8(%r1) # GPRs la %r4,64(%r1) # FPRs la %r5,96(%r1) # Overflow st %r1,0(%r15) # Set up back chain bas %r14,0(%r12,%r13) # Call helper l %r4,96+56(%r15) ld %f0,96+64(%r15) # Load return registers lm %r2,%r3,96+8(%r15) lm %r12,%r15,96+48(%r15) br %r4 .align 4 .Lchelper: .long ffi_closure_helper_SYSV-.Lcbase .LFE2: .ffi_closure_SYSV_end: .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry .LSCIE1: .4byte 0x0 # CIE Identifier Tag .byte 0x1 # CIE Version .ascii "zR\0" # CIE Augmentation .uleb128 0x1 # CIE Code Alignment Factor .sleb128 -4 # CIE Data Alignment Factor .byte 0xe # CIE RA Column .uleb128 0x1 # Augmentation size .byte 0x1b # FDE Encoding (pcrel sdata4) .byte 0xc # DW_CFA_def_cfa .uleb128 0xf .uleb128 0x60 .align 4 .LECIE1: .LSFDE1: .4byte .LEFDE1-.LASFDE1 # FDE Length .LASFDE1: .4byte .LASFDE1-.Lframe1 # FDE CIE offset .4byte .LFB1-. # FDE initial location .4byte .LFE1-.LFB1 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI0-.LFB1 .byte 0x8f # DW_CFA_offset, column 0xf .uleb128 0x9 .byte 0x8e # DW_CFA_offset, column 0xe .uleb128 0xa .byte 0x8d # DW_CFA_offset, column 0xd .uleb128 0xb .byte 0x8c # DW_CFA_offset, column 0xc .uleb128 0xc .byte 0x8b # DW_CFA_offset, column 0xb .uleb128 0xd .byte 0x8a # DW_CFA_offset, column 0xa .uleb128 0xe .byte 0x89 # DW_CFA_offset, column 0x9 .uleb128 0xf .byte 0x88 # DW_CFA_offset, column 0x8 .uleb128 0x10 .byte 0x87 # DW_CFA_offset, column 0x7 .uleb128 0x11 .byte 0x86 # DW_CFA_offset, column 0x6 .uleb128 0x12 .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI1-.LCFI0 .byte 0xd # DW_CFA_def_cfa_register .uleb128 0xb .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI2-.LCFI1 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 0x90 .align 4 .LEFDE1: .LSFDE2: .4byte .LEFDE2-.LASFDE2 # FDE Length .LASFDE2: .4byte .LASFDE2-.Lframe1 # FDE CIE offset .4byte .LFB2-. # FDE initial location .4byte .LFE2-.LFB2 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI10-.LFB2 .byte 0x8f # DW_CFA_offset, column 0xf .uleb128 0x9 .byte 0x8e # DW_CFA_offset, column 0xe .uleb128 0xa .byte 0x8d # DW_CFA_offset, column 0xd .uleb128 0xb .byte 0x8c # DW_CFA_offset, column 0xc .uleb128 0xc .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI11-.LCFI10 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 0xc0 .align 4 .LEFDE2: #else .text # r2: cif->bytes # r3: &ecif # r4: ffi_prep_args # r5: ret_type # r6: ecif.rvalue # ov: fn # This assumes we are using gas. .globl ffi_call_SYSV .type ffi_call_SYSV,%function ffi_call_SYSV: .LFB1: stmg %r6,%r15,48(%r15) # Save registers .LCFI0: larl %r13,.Lbase # Set up base register lgr %r11,%r15 # Set up frame pointer .LCFI1: sgr %r15,%r2 aghi %r15,-160-80 # Allocate stack lgr %r8,%r6 # Save ecif.rvalue llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address lg %r7,160(%r11) # Load function address stg %r11,0(%r15) # Set up back chain aghi %r11,-80 # Register save area .LCFI2: la %r2,160(%r15) # Save area # r3 already holds &ecif basr %r14,%r4 # Call ffi_prep_args lmg %r2,%r6,0(%r11) # Load arguments ld %f0,48(%r11) ld %f2,56(%r11) ld %f4,64(%r11) ld %f6,72(%r11) la %r14,0(%r13,%r9) # Set return address br %r7 # ... and call function .Lbase: .LretNone: # Return void lg %r4,80+112(%r11) lmg %r6,%r15,80+48(%r11) br %r4 .LretFloat: lg %r4,80+112(%r11) ste %f0,0(%r8) # Return float lmg %r6,%r15,80+48(%r11) br %r4 .LretDouble: lg %r4,80+112(%r11) std %f0,0(%r8) # Return double lmg %r6,%r15,80+48(%r11) br %r4 .LretInt32: lg %r4,80+112(%r11) st %r2,0(%r8) # Return int lmg %r6,%r15,80+48(%r11) br %r4 .LretInt64: lg %r4,80+112(%r11) stg %r2,0(%r8) # Return long lmg %r6,%r15,80+48(%r11) br %r4 .Ltable: .byte .LretNone-.Lbase # FFI390_RET_VOID .byte .LretNone-.Lbase # FFI390_RET_STRUCT .byte .LretFloat-.Lbase # FFI390_RET_FLOAT .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE .byte .LretInt32-.Lbase # FFI390_RET_INT32 .byte .LretInt64-.Lbase # FFI390_RET_INT64 .LFE1: .ffi_call_SYSV_end: .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV .globl ffi_closure_SYSV .type ffi_closure_SYSV,%function ffi_closure_SYSV: .LFB2: stmg %r14,%r15,112(%r15) # Save registers .LCFI10: stmg %r2,%r6,16(%r15) # Save arguments std %f0,128(%r15) std %f2,136(%r15) std %f4,144(%r15) std %f6,152(%r15) lgr %r1,%r15 # Set up stack frame aghi %r15,-160 .LCFI11: lgr %r2,%r0 # Closure la %r3,16(%r1) # GPRs la %r4,128(%r1) # FPRs la %r5,160(%r1) # Overflow stg %r1,0(%r15) # Set up back chain brasl %r14,ffi_closure_helper_SYSV # Call helper lg %r14,160+112(%r15) ld %f0,160+128(%r15) # Load return registers lg %r2,160+16(%r15) la %r15,160(%r15) br %r14 .LFE2: .ffi_closure_SYSV_end: .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry .LSCIE1: .4byte 0x0 # CIE Identifier Tag .byte 0x1 # CIE Version .ascii "zR\0" # CIE Augmentation .uleb128 0x1 # CIE Code Alignment Factor .sleb128 -8 # CIE Data Alignment Factor .byte 0xe # CIE RA Column .uleb128 0x1 # Augmentation size .byte 0x1b # FDE Encoding (pcrel sdata4) .byte 0xc # DW_CFA_def_cfa .uleb128 0xf .uleb128 0xa0 .align 8 .LECIE1: .LSFDE1: .4byte .LEFDE1-.LASFDE1 # FDE Length .LASFDE1: .4byte .LASFDE1-.Lframe1 # FDE CIE offset .4byte .LFB1-. # FDE initial location .4byte .LFE1-.LFB1 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI0-.LFB1 .byte 0x8f # DW_CFA_offset, column 0xf .uleb128 0x5 .byte 0x8e # DW_CFA_offset, column 0xe .uleb128 0x6 .byte 0x8d # DW_CFA_offset, column 0xd .uleb128 0x7 .byte 0x8c # DW_CFA_offset, column 0xc .uleb128 0x8 .byte 0x8b # DW_CFA_offset, column 0xb .uleb128 0x9 .byte 0x8a # DW_CFA_offset, column 0xa .uleb128 0xa .byte 0x89 # DW_CFA_offset, column 0x9 .uleb128 0xb .byte 0x88 # DW_CFA_offset, column 0x8 .uleb128 0xc .byte 0x87 # DW_CFA_offset, column 0x7 .uleb128 0xd .byte 0x86 # DW_CFA_offset, column 0x6 .uleb128 0xe .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI1-.LCFI0 .byte 0xd # DW_CFA_def_cfa_register .uleb128 0xb .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI2-.LCFI1 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 0xf0 .align 8 .LEFDE1: .LSFDE2: .4byte .LEFDE2-.LASFDE2 # FDE Length .LASFDE2: .4byte .LASFDE2-.Lframe1 # FDE CIE offset .4byte .LFB2-. # FDE initial location .4byte .LFE2-.LFB2 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI10-.LFB2 .byte 0x8f # DW_CFA_offset, column 0xf .uleb128 0x5 .byte 0x8e # DW_CFA_offset, column 0xe .uleb128 0x6 .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI11-.LCFI10 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 0x140 .align 8 .LEFDE2: #endif --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 2000 Software AG S390 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 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. ----------------------------------------------------------------------- */ /*====================================================================*/ /* Includes */ /* -------- */ /*====================================================================*/ #include <ffi.h> #include <ffi_common.h> #include <stdlib.h> #include <stdio.h> /*====================== End of Includes =============================*/ /*====================================================================*/ /* Defines */ /* ------- */ /*====================================================================*/ /* Maximum number of GPRs available for argument passing. */ #define MAX_GPRARGS 5 /* Maximum number of FPRs available for argument passing. */ #ifdef __s390x__ #define MAX_FPRARGS 4 #else #define MAX_FPRARGS 2 #endif /* Round to multiple of 16. */ #define ROUND_SIZE(size) (((size) + 15) & ~15) /* If these values change, sysv.S must be adapted! */ #define FFI390_RET_VOID 0 #define FFI390_RET_STRUCT 1 #define FFI390_RET_FLOAT 2 #define FFI390_RET_DOUBLE 3 #define FFI390_RET_INT32 4 #define FFI390_RET_INT64 5 /*===================== End of Defines ===============================*/ /*====================================================================*/ /* Prototypes */ /* ---------- */ /*====================================================================*/ static void ffi_prep_args (unsigned char *, extended_cif *); static int ffi_check_float_struct (ffi_type *); void #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) __attribute__ ((visibility ("hidden"))) #endif ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, unsigned long long *, unsigned long *); /*====================== End of Prototypes ===========================*/ /*====================================================================*/ /* Externals */ /* --------- */ /*====================================================================*/ extern void ffi_call_SYSV(unsigned, extended_cif *, void (*)(unsigned char *, extended_cif *), unsigned, void *, void (*fn)()); extern void ffi_closure_SYSV(void); /*====================== End of Externals ============================*/ /*====================================================================*/ /* */ /* Name - ffi_check_struct_type. */ /* */ /* Function - Determine if a structure can be passed within a */ /* general purpose or floating point register. */ /* */ /*====================================================================*/ static int ffi_check_struct_type (ffi_type *arg) { size_t size = arg->size; /* If the struct has just one element, look at that element to find out whether to consider the struct as floating point. */ while (arg->type == FFI_TYPE_STRUCT && arg->elements[0] && !arg->elements[1]) arg = arg->elements[0]; /* Structs of size 1, 2, 4, and 8 are passed in registers, just like the corresponding int/float types. */ switch (size) { case 1: return FFI_TYPE_UINT8; case 2: return FFI_TYPE_UINT16; case 4: if (arg->type == FFI_TYPE_FLOAT) return FFI_TYPE_FLOAT; else return FFI_TYPE_UINT32; case 8: if (arg->type == FFI_TYPE_DOUBLE) return FFI_TYPE_DOUBLE; else return FFI_TYPE_UINT64; default: break; } /* Other structs are passed via a pointer to the data. */ return FFI_TYPE_POINTER; } /*======================== End of Routine ============================*/ /*====================================================================*/ /* */ /* Name - ffi_prep_args. */ /* */ /* Function - Prepare parameters for call to function. */ /* */ /* ffi_prep_args is called by the assembly routine once stack space */ /* has been allocated for the function's arguments. */ /* */ /*====================================================================*/ static void ffi_prep_args (unsigned char *stack, extended_cif *ecif) { /* The stack space will be filled with those areas: FPR argument register save area (highest addresses) GPR argument register save area temporary struct copies overflow argument area (lowest addresses) We set up the following pointers: p_fpr: bottom of the FPR area (growing upwards) p_gpr: bottom of the GPR area (growing upwards) p_ov: bottom of the overflow area (growing upwards) p_struct: top of the struct copy area (growing downwards) All areas are kept aligned to twice the word size. */ int gpr_off = ecif->cif->bytes; int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long)); unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off); unsigned long *p_gpr = (unsigned long *)(stack + gpr_off); unsigned char *p_struct = (unsigned char *)p_gpr; unsigned long *p_ov = (unsigned long *)stack; int n_fpr = 0; int n_gpr = 0; int n_ov = 0; ffi_type **ptr; void **p_argv = ecif->avalue; int i; /* If we returning a structure then we set the first parameter register to the address of where we are returning this structure. */ if (ecif->cif->flags == FFI390_RET_STRUCT) p_gpr[n_gpr++] = (unsigned long) ecif->rvalue; /* Now for the arguments. */ for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) { void *arg = *p_argv; int type = (*ptr)->type; /* Check how a structure type is passed. */ if (type == FFI_TYPE_STRUCT) { type = ffi_check_struct_type (*ptr); /* If we pass the struct via pointer, copy the data. */ if (type == FFI_TYPE_POINTER) { p_struct -= ROUND_SIZE ((*ptr)->size); memcpy (p_struct, (char *)arg, (*ptr)->size); arg = &p_struct; } } /* Pointers are passed like UINTs of the same size. */ if (type == FFI_TYPE_POINTER) #ifdef __s390x__ type = FFI_TYPE_UINT64; #else type = FFI_TYPE_UINT32; #endif /* Now handle all primitive int/float data types. */ switch (type) { case FFI_TYPE_DOUBLE: if (n_fpr < MAX_FPRARGS) p_fpr[n_fpr++] = *(unsigned long long *) arg; else #ifdef __s390x__ p_ov[n_ov++] = *(unsigned long *) arg; #else p_ov[n_ov++] = ((unsigned long *) arg)[0], p_ov[n_ov++] = ((unsigned long *) arg)[1]; #endif break; case FFI_TYPE_FLOAT: if (n_fpr < MAX_FPRARGS) p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32; else p_ov[n_ov++] = *(unsigned int *) arg; break; case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: #ifdef __s390x__ if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = *(unsigned long *) arg; else p_ov[n_ov++] = *(unsigned long *) arg; #else if (n_gpr == MAX_GPRARGS-1) n_gpr = MAX_GPRARGS; if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = ((unsigned long *) arg)[0], p_gpr[n_gpr++] = ((unsigned long *) arg)[1]; else p_ov[n_ov++] = ((unsigned long *) arg)[0], p_ov[n_ov++] = ((unsigned long *) arg)[1]; #endif break; case FFI_TYPE_UINT32: if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = *(unsigned int *) arg; else p_ov[n_ov++] = *(unsigned int *) arg; break; case FFI_TYPE_INT: case FFI_TYPE_SINT32: if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = *(signed int *) arg; else p_ov[n_ov++] = *(signed int *) arg; break; case FFI_TYPE_UINT16: if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = *(unsigned short *) arg; else p_ov[n_ov++] = *(unsigned short *) arg; break; case FFI_TYPE_SINT16: if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = *(signed short *) arg; else p_ov[n_ov++] = *(signed short *) arg; break; case FFI_TYPE_UINT8: if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = *(unsigned char *) arg; else p_ov[n_ov++] = *(unsigned char *) arg; break; case FFI_TYPE_SINT8: if (n_gpr < MAX_GPRARGS) p_gpr[n_gpr++] = *(signed char *) arg; else p_ov[n_ov++] = *(signed char *) arg; break; default: FFI_ASSERT (0); break; } } } /*======================== End of Routine ============================*/ /*====================================================================*/ /* */ /* Name - ffi_prep_cif_machdep. */ /* */ /* Function - Perform machine dependent CIF processing. */ /* */ /*====================================================================*/ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { size_t struct_size = 0; int n_gpr = 0; int n_fpr = 0; int n_ov = 0; ffi_type **ptr; int i; /* Determine return value handling. */ switch (cif->rtype->type) { /* Void is easy. */ case FFI_TYPE_VOID: cif->flags = FFI390_RET_VOID; break; /* Structures are returned via a hidden pointer. */ case FFI_TYPE_STRUCT: cif->flags = FFI390_RET_STRUCT; n_gpr++; /* We need one GPR to pass the pointer. */ break; /* Floating point values are returned in fpr 0. */ case FFI_TYPE_FLOAT: cif->flags = FFI390_RET_FLOAT; break; case FFI_TYPE_DOUBLE: cif->flags = FFI390_RET_DOUBLE; break; /* Integer values are returned in gpr 2 (and gpr 3 for 64-bit values on 31-bit machines). */ case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: cif->flags = FFI390_RET_INT64; break; case FFI_TYPE_POINTER: case FFI_TYPE_INT: case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: case FFI_TYPE_UINT8: case FFI_TYPE_SINT8: /* These are to be extended to word size. */ #ifdef __s390x__ cif->flags = FFI390_RET_INT64; #else cif->flags = FFI390_RET_INT32; #endif break; default: FFI_ASSERT (0); break; } /* Now for the arguments. */ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) { int type = (*ptr)->type; /* Check how a structure type is passed. */ if (type == FFI_TYPE_STRUCT) { type = ffi_check_struct_type (*ptr); /* If we pass the struct via pointer, we must reserve space to copy its data for proper call-by-value semantics. */ if (type == FFI_TYPE_POINTER) struct_size += ROUND_SIZE ((*ptr)->size); } /* Now handle all primitive int/float data types. */ switch (type) { /* The first MAX_FPRARGS floating point arguments go in FPRs, the rest overflow to the stack. */ case FFI_TYPE_DOUBLE: if (n_fpr < MAX_FPRARGS) n_fpr++; else n_ov += sizeof (double) / sizeof (long); break; case FFI_TYPE_FLOAT: if (n_fpr < MAX_FPRARGS) n_fpr++; else n_ov++; break; /* On 31-bit machines, 64-bit integers are passed in GPR pairs, if one is still available, or else on the stack. If only one register is free, skip the register (it won't be used for any subsequent argument either). */ #ifndef __s390x__ case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: if (n_gpr == MAX_GPRARGS-1) n_gpr = MAX_GPRARGS; if (n_gpr < MAX_GPRARGS) n_gpr += 2; else n_ov += 2; break; #endif /* Everything else is passed in GPRs (until MAX_GPRARGS have been used) or overflows to the stack. */ default: if (n_gpr < MAX_GPRARGS) n_gpr++; else n_ov++; break; } } /* Total stack space as required for overflow arguments and temporary structure copies. */ cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size; return FFI_OK; } /*======================== End of Routine ============================*/ /*====================================================================*/ /* */ /* Name - ffi_call. */ /* */ /* Function - Call the FFI routine. */ /* */ /*====================================================================*/ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) { int ret_type = cif->flags; extended_cif ecif; ecif.cif = cif; ecif.avalue = avalue; ecif.rvalue = rvalue; /* If we don't have a return value, we need to fake one. */ if (rvalue == NULL) { if (ret_type == FFI390_RET_STRUCT) ecif.rvalue = alloca (cif->rtype->size); else ret_type = FFI390_RET_VOID; } switch (cif->abi) { case FFI_SYSV: ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args, ret_type, ecif.rvalue, fn); break; default: FFI_ASSERT (0); break; } } /*======================== End of Routine ============================*/ /*====================================================================*/ /* */ /* Name - ffi_closure_helper_SYSV. */ /* */ /* Function - Call a FFI closure target function. */ /* */ /*====================================================================*/ void ffi_closure_helper_SYSV (ffi_closure *closure, unsigned long *p_gpr, unsigned long long *p_fpr, unsigned long *p_ov) { unsigned long long ret_buffer; void *rvalue = &ret_buffer; void **avalue; void **p_arg; int n_gpr = 0; int n_fpr = 0; int n_ov = 0; ffi_type **ptr; int i; /* Allocate buffer for argument list pointers. */ p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *)); /* If we returning a structure, pass the structure address directly to the target function. Otherwise, have the target function store the return value to the GPR save area. */ if (closure->cif->flags == FFI390_RET_STRUCT) rvalue = (void *) p_gpr[n_gpr++]; /* Now for the arguments. */ for (ptr = closure->cif->arg_types, i = closure->cif->nargs; i > 0; i--, p_arg++, ptr++) { int deref_struct_pointer = 0; int type = (*ptr)->type; /* Check how a structure type is passed. */ if (type == FFI_TYPE_STRUCT) { type = ffi_check_struct_type (*ptr); /* If we pass the struct via pointer, remember to retrieve the pointer later. */ if (type == FFI_TYPE_POINTER) deref_struct_pointer = 1; } /* Pointers are passed like UINTs of the same size. */ if (type == FFI_TYPE_POINTER) #ifdef __s390x__ type = FFI_TYPE_UINT64; #else type = FFI_TYPE_UINT32; #endif /* Now handle all primitive int/float data types. */ switch (type) { case FFI_TYPE_DOUBLE: if (n_fpr < MAX_FPRARGS) *p_arg = &p_fpr[n_fpr++]; else *p_arg = &p_ov[n_ov], n_ov += sizeof (double) / sizeof (long); break; case FFI_TYPE_FLOAT: if (n_fpr < MAX_FPRARGS) *p_arg = &p_fpr[n_fpr++]; else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; break; case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: #ifdef __s390x__ if (n_gpr < MAX_GPRARGS) *p_arg = &p_gpr[n_gpr++]; else *p_arg = &p_ov[n_ov++]; #else if (n_gpr == MAX_GPRARGS-1) n_gpr = MAX_GPRARGS; if (n_gpr < MAX_GPRARGS) *p_arg = &p_gpr[n_gpr], n_gpr += 2; else *p_arg = &p_ov[n_ov], n_ov += 2; #endif break; case FFI_TYPE_INT: case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: if (n_gpr < MAX_GPRARGS) *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4; else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; break; case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: if (n_gpr < MAX_GPRARGS) *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2; else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2; break; case FFI_TYPE_UINT8: case FFI_TYPE_SINT8: if (n_gpr < MAX_GPRARGS) *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1; else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1; break; default: FFI_ASSERT (0); break; } /* If this is a struct passed via pointer, we need to actually retrieve that pointer. */ if (deref_struct_pointer) *p_arg = *(void **)*p_arg; } /* Call the target function. */ (closure->fun) (closure->cif, rvalue, avalue, closure->user_data); /* Convert the return value. */ switch (closure->cif->rtype->type) { /* Void is easy, and so is struct. */ case FFI_TYPE_VOID: case FFI_TYPE_STRUCT: break; /* Floating point values are returned in fpr 0. */ case FFI_TYPE_FLOAT: p_fpr[0] = (long long) *(unsigned int *) rvalue << 32; break; case FFI_TYPE_DOUBLE: p_fpr[0] = *(unsigned long long *) rvalue; break; /* Integer values are returned in gpr 2 (and gpr 3 for 64-bit values on 31-bit machines). */ case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: #ifdef __s390x__ p_gpr[0] = *(unsigned long *) rvalue; #else p_gpr[0] = ((unsigned long *) rvalue)[0], p_gpr[1] = ((unsigned long *) rvalue)[1]; #endif break; case FFI_TYPE_POINTER: case FFI_TYPE_UINT32: case FFI_TYPE_UINT16: case FFI_TYPE_UINT8: p_gpr[0] = *(unsigned long *) rvalue; break; case FFI_TYPE_INT: case FFI_TYPE_SINT32: case FFI_TYPE_SINT16: case FFI_TYPE_SINT8: p_gpr[0] = *(signed long *) rvalue; break; default: FFI_ASSERT (0); break; } } /*======================== End of Routine ============================*/ /*====================================================================*/ /* */ /* Name - ffi_prep_closure. */ /* */ /* 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_ASSERT (cif->abi == FFI_SYSV); #ifndef __s390x__ *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ *(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[12] = (long)&ffi_closure_SYSV; #else *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */ *(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[24] = (long)&ffi_closure_SYSV; #endif closure->cif = cif; closure->user_data = user_data; closure->fun = fun; return FFI_OK; } /*======================== End of Routine ============================*/ --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for S390. 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 #if defined (__s390x__) #define S390X #endif /* ---- System specific configurations ----------------------------------- */ #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #ifdef S390X #define FFI_TRAMPOLINE_SIZE 32 #else #define FFI_TRAMPOLINE_SIZE 16 #endif #define FFI_NATIVE_RAW_API 0 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:24
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/ia64 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/ia64 Added Files: ffi.c ffitarget.h ia64_flags.h unix.S Log Message: Importing libffi sources and build tools. --- NEW FILE: unix.S --- /* ----------------------------------------------------------------------- unix.S - Copyright (c) 1998 Red Hat, Inc. Copyright (c) 2000 Hewlett Packard Company IA64/unix Foreign Function Interface Primary author: Hans Boehm, HP Labs Loosely modeled on Cygnus code for other platforms. 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #include "ia64_flags.h" /* parameters: */ #define callback in0 #define ecifp in1 #define bytes in2 #define flags in3 #define raddr in4 #define fn in5 #define FLOAT_SZ 8 /* in-memory size of fp operands */ /* Allocate an ia64_args structure on the stack; call ffi_prep_args */ /* to fill it in with argument values; copy those to the real */ /* registers, leaving overflow arguments on the stack. Then call fn */ /* and move the result from registers into *raddr. */ .pred.safe_across_calls p1-p5,p16-p63 .text .align 16 .global ffi_call_unix .proc ffi_call_unix ffi_call_unix: .prologue .save ar.pfs,r38 /* loc0 */ alloc loc0=ar.pfs,6,6,8,0 .save rp,loc1 mov loc1=b0; .vframe loc5 mov loc5=sp; .body sub sp=sp,bytes mov loc4=r1 /* Save gp */ ld8 r8=[callback],8 /* code address of callback */ ;; mov out0=sp mov out1=ecifp mov out2=bytes ld8 r1=[callback] /* Set up gp for callback. Unnecessary? */ mov b6=r8 ;; br.call.sptk.many b0 = b6 /* call ffi_prep_args */ cmp.eq p6,p0=0,r8 /* r8 nonzero ==> need fp regs */ ;; (p6) add loc2=32+8*FLOAT_SZ,sp (p6) br.cond.dptk.many fp_done ;; /* Quiets warning; needed? */ add loc2=32,sp add loc3=32+FLOAT_SZ,sp ;; ldfd f8=[loc2],2*FLOAT_SZ ldfd f9=[loc3],2*FLOAT_SZ ;; ldfd f10=[loc2],2*FLOAT_SZ ldfd f11=[loc3],2*FLOAT_SZ ;; ldfd f12=[loc2],2*FLOAT_SZ ldfd f13=[loc3],2*FLOAT_SZ ;; ldfd f14=[loc2],2*FLOAT_SZ ldfd f15=[loc3] ;; fp_done: add r9=16,sp /* Pointer to r8_contents */ /* loc2 points at first integer register value. */ add loc3=8,loc2 ;; ld8 r8=[r9] /* Just in case we return large struct */ ld8 out0=[loc2],16 ld8 out1=[loc3],16 ;; ld8 out2=[loc2],16 ld8 out3=[loc3],16 ;; ld8 out4=[loc2],16 ld8 out5=[loc3],16 ;; ld8 out6=[loc2] ld8 out7=[loc3] /* Set sp to 16 bytes below the first stack parameter. This */ /* is the value currently in loc2. */ mov sp=loc2 ld8 r8=[fn],8 ;; ld8 r1=[fn] /* Set up gp */ mov b6=r8;; br.call.sptk.many b0 = b6 /* call fn */ /* Handle return value. */ cmp.eq p6,p0=0,raddr cmp.eq p7,p0=FFI_TYPE_INT,flags cmp.eq p10,p0=FFI_IS_SMALL_STRUCT2,flags cmp.eq p11,p0=FFI_IS_SMALL_STRUCT3,flags cmp.eq p12,p0=FFI_IS_SMALL_STRUCT4,flags ;; (p6) br.cond.dpnt.few done /* Dont copy ret values if raddr = 0 */ (p7) br.cond.dptk.few copy1 (p10) br.cond.dpnt.few copy2 (p11) br.cond.dpnt.few copy3 (p12) br.cond.dpnt.few copy4 cmp.eq p8,p0=FFI_TYPE_FLOAT,flags cmp.eq p9,p0=FFI_TYPE_DOUBLE,flags tbit.nz p6,p0=flags,FLOAT_FP_AGGREGATE_BIT tbit.nz p7,p0=flags,DOUBLE_FP_AGGREGATE_BIT ;; (p8) stfs [raddr]=f8 (p9) stfd [raddr]=f8 ;; .label_state 1 (p6) br.cond.dpnt.few handle_float_hfa (p7) br.cond.dpnt.few handle_double_hfa br done copy4: add loc3=24,raddr ;; st8 [loc3]=r11 copy3: add loc3=16,raddr ;; st8 [loc3]=r10 copy2: add loc3=8,raddr ;; st8 [loc3]=r9 copy1: st8 [raddr]=r8 /* In the big struct case, raddr was passed as an argument. */ /* In the void case there was nothing to do. */ done: mov r1=loc4 /* Restore gp */ mov ar.pfs = loc0 mov b0 = loc1 .restore sp mov sp = loc5 br.ret.sptk.many b0 handle_double_hfa: .body .copy_state 1 /* Homogeneous floating point array of doubles is returned in */ /* registers f8-f15. Save one at a time to return area. */ and flags=0xf,flags /* Retrieve size */ ;; cmp.eq p6,p0=2,flags cmp.eq p7,p0=3,flags cmp.eq p8,p0=4,flags cmp.eq p9,p0=5,flags cmp.eq p10,p0=6,flags cmp.eq p11,p0=7,flags cmp.eq p12,p0=8,flags ;; (p6) br.cond.dptk.few dhfa2 (p7) br.cond.dptk.few dhfa3 (p8) br.cond.dptk.few dhfa4 (p9) br.cond.dptk.few dhfa5 (p10) br.cond.dptk.few dhfa6 (p11) br.cond.dptk.few dhfa7 dhfa8: add loc3=7*8,raddr ;; stfd [loc3]=f15 dhfa7: add loc3=6*8,raddr ;; stfd [loc3]=f14 dhfa6: add loc3=5*8,raddr ;; stfd [loc3]=f13 dhfa5: add loc3=4*8,raddr ;; stfd [loc3]=f12 dhfa4: add loc3=3*8,raddr ;; stfd [loc3]=f11 dhfa3: add loc3=2*8,raddr ;; stfd [loc3]=f10 dhfa2: add loc3=1*8,raddr ;; stfd [loc3]=f9 stfd [raddr]=f8 br done handle_float_hfa: /* Homogeneous floating point array of floats is returned in */ /* registers f8-f15. Save one at a time to return area. */ and flags=0xf,flags /* Retrieve size */ ;; cmp.eq p6,p0=2,flags cmp.eq p7,p0=3,flags cmp.eq p8,p0=4,flags cmp.eq p9,p0=5,flags cmp.eq p10,p0=6,flags cmp.eq p11,p0=7,flags cmp.eq p12,p0=8,flags ;; (p6) br.cond.dptk.few shfa2 (p7) br.cond.dptk.few shfa3 (p8) br.cond.dptk.few shfa4 (p9) br.cond.dptk.few shfa5 (p10) br.cond.dptk.few shfa6 (p11) br.cond.dptk.few shfa7 shfa8: add loc3=7*4,raddr ;; stfd [loc3]=f15 shfa7: add loc3=6*4,raddr ;; stfd [loc3]=f14 shfa6: add loc3=5*4,raddr ;; stfd [loc3]=f13 shfa5: add loc3=4*4,raddr ;; stfd [loc3]=f12 shfa4: add loc3=3*4,raddr ;; stfd [loc3]=f11 shfa3: add loc3=2*4,raddr ;; stfd [loc3]=f10 shfa2: add loc3=1*4,raddr ;; stfd [loc3]=f9 stfd [raddr]=f8 br done .endp ffi_call_unix .pred.safe_across_calls p1-p5,p16-p63 .text .align 16 .global ffi_closure_UNIX .proc ffi_closure_UNIX ffi_closure_UNIX: .prologue .save ar.pfs,r40 /* loc0 */ alloc loc0=ar.pfs,8,3,2,0 .save rp,loc1 mov loc1=b0 .vframe loc2 mov loc2=sp /* Retrieve closure pointer and real gp. */ mov out0=gp add gp=16,gp ;; ld8 gp=[gp] /* Reserve a structia64_args on the stack such that arguments */ /* past the first 8 are automatically placed in the right */ /* slot. Note that when we start the sp points at 2 8-byte */ /* scratch words, followed by the extra arguments. */ # define BASIC_ARGS_SZ (8*FLOAT_SZ+8*8+2*8) # define FIRST_FP_OFFSET (4*8) add r14=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET),sp add r15=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET-FLOAT_SZ),sp add sp=-BASIC_ARGS_SZ,sp /* r14 points to fp_regs[0], r15 points to fp_regs[1] */ ;; stfd [r14]=f8,2*FLOAT_SZ stfd [r15]=f9,2*FLOAT_SZ ;; stfd [r14]=f10,2*FLOAT_SZ stfd [r15]=f11,2*FLOAT_SZ ;; stfd [r14]=f12,2*FLOAT_SZ stfd [r15]=f13,2*FLOAT_SZ ;; stfd [r14]=f14,2*FLOAT_SZ stfd [r15]=f15,FLOAT_SZ+8 ;; /* r14 points to first parameter register area, r15 to second. */ st8 [r14]=in0,2*8 st8 [r15]=in1,2*8 ;; st8 [r14]=in2,2*8 st8 [r15]=in3,2*8 ;; st8 [r14]=in4,2*8 st8 [r15]=in5,2*8 ;; st8 [r14]=in6,2*8 st8 [r15]=in7,2*8 /* Call ffi_closure_UNIX_inner */ mov out1=sp br.call.sptk.many b0=ffi_closure_UNIX_inner ;; mov b0=loc1 mov ar.pfs=loc0 .restore sp mov sp=loc2 br.ret.sptk.many b0 .endp ffi_closure_UNIX --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1998 Red Hat, Inc. Copyright (c) 2000 Hewlett Packard Company IA64 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 <stdbool.h> #include "ia64_flags.h" /* Memory image of fp register contents. Should eventually be an fp */ /* type long enough to hold an entire register. For now we use double. */ typedef double float80; /* The stack layout at call to ffi_prep_args. Other_args will remain */ /* on the stack for the actual call. Everything else we be transferred */ /* to registers and popped by the assembly code. */ struct ia64_args { long scratch[2]; /* Two scratch words at top of stack. */ /* Allows sp to be passed as arg pointer. */ void * r8_contents; /* Value to be passed in r8 */ long spare; /* Not used. */ float80 fp_regs[8]; /* Contents of 8 floating point argument */ /* registers. */ long out_regs[8]; /* Contents of the 8 out registers used */ /* for integer parameters. */ long other_args[0]; /* Arguments passed on stack, variable size */ /* Treated as continuation of out_regs. */ }; static size_t float_type_size(unsigned short tp) { switch(tp) { case FFI_TYPE_FLOAT: return sizeof(float); case FFI_TYPE_DOUBLE: return sizeof(double); #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: return sizeof(long double); #endif default: FFI_ASSERT(0); } } /* * Is type a struct containing at most n floats, doubles, or extended * doubles, all of the same fp type? * If so, set *element_type to the fp type. */ static bool is_homogeneous_fp_aggregate(ffi_type * type, int n, unsigned short * element_type) { ffi_type **ptr; unsigned short element, struct_element; int type_set = 0; FFI_ASSERT(type != NULL); FFI_ASSERT(type->elements != NULL); ptr = &(type->elements[0]); while ((*ptr) != NULL) { switch((*ptr) -> type) { case FFI_TYPE_FLOAT: if (type_set && element != FFI_TYPE_FLOAT) return 0; if (--n < 0) return false; type_set = 1; element = FFI_TYPE_FLOAT; break; case FFI_TYPE_DOUBLE: if (type_set && element != FFI_TYPE_DOUBLE) return 0; if (--n < 0) return false; type_set = 1; element = FFI_TYPE_DOUBLE; break; case FFI_TYPE_STRUCT: if (!is_homogeneous_fp_aggregate(type, n, &struct_element)) return false; if (type_set && struct_element != element) return false; n -= (type -> size)/float_type_size(element); element = struct_element; if (n < 0) return false; break; /* case FFI_TYPE_LONGDOUBLE: Not yet implemented. */ default: return false; } ptr++; } *element_type = element; return true; } /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments. It fills in the arguments in the structure referenced by stack. Returns nonzero if fp registers are used for arguments. */ static bool ffi_prep_args(struct ia64_args *stack, extended_cif *ecif, int bytes) { register long i, avn; register void **p_argv; register long *argp = stack -> out_regs; register float80 *fp_argp = stack -> fp_regs; register ffi_type **p_arg; /* For big return structs, r8 needs to contain the target address. */ /* Since r8 is otherwise dead, we set it unconditionally. */ stack -> r8_contents = ecif -> rvalue; i = 0; avn = ecif->cif->nargs; p_arg = ecif->cif->arg_types; p_argv = ecif->avalue; while (i < avn) { size_t z; /* z is in units of arg slots or words, not bytes. */ switch ((*p_arg)->type) { case FFI_TYPE_SINT8: z = 1; *(SINT64 *) argp = *(SINT8 *)(* p_argv); break; case FFI_TYPE_UINT8: z = 1; *(UINT64 *) argp = *(UINT8 *)(* p_argv); break; case FFI_TYPE_SINT16: z = 1; *(SINT64 *) argp = *(SINT16 *)(* p_argv); break; case FFI_TYPE_UINT16: z = 1; *(UINT64 *) argp = *(UINT16 *)(* p_argv); break; case FFI_TYPE_SINT32: z = 1; *(SINT64 *) argp = *(SINT32 *)(* p_argv); break; case FFI_TYPE_UINT32: z = 1; *(UINT64 *) argp = *(UINT32 *)(* p_argv); break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: z = 1; *(UINT64 *) argp = *(UINT64 *)(* p_argv); break; case FFI_TYPE_FLOAT: z = 1; if (fp_argp - stack->fp_regs < 8) { /* Note the conversion -- all the fp regs are loaded as doubles. */ *fp_argp++ = *(float *)(* p_argv); } /* Also put it into the integer registers or memory: */ *(UINT64 *) argp = *(UINT32 *)(* p_argv); break; case FFI_TYPE_DOUBLE: z = 1; if (fp_argp - stack->fp_regs < 8) *fp_argp++ = *(double *)(* p_argv); /* Also put it into the integer registers or memory: */ *(double *) argp = *(double *)(* p_argv); break; case FFI_TYPE_STRUCT: { size_t sz = (*p_arg)->size; unsigned short element_type; z = ((*p_arg)->size + FFI_SIZEOF_ARG - 1)/FFI_SIZEOF_ARG; if (is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) { int i; int nelements = sz/float_type_size(element_type); for (i = 0; i < nelements; ++i) { switch (element_type) { case FFI_TYPE_FLOAT: if (fp_argp - stack->fp_regs < 8) *fp_argp++ = ((float *)(* p_argv))[i]; break; case FFI_TYPE_DOUBLE: if (fp_argp - stack->fp_regs < 8) *fp_argp++ = ((double *)(* p_argv))[i]; break; default: /* Extended precision not yet implemented. */ abort(); } } } /* And pass it in integer registers as a struct, with */ /* its actual field sizes packed into registers. */ memcpy(argp, *p_argv, (*p_arg)->size); } break; default: FFI_ASSERT(0); } argp += z; i++, p_arg++, p_argv++; } return (fp_argp != stack -> fp_regs); } /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { long i, avn; bool is_simple = true; long simple_flag = FFI_SIMPLE_V; /* Adjust cif->bytes to include space for the 2 scratch words, r8 register contents, spare word, the 8 fp register contents, and all 8 integer register contents. This will be removed before the call, though 2 scratch words must remain. */ cif->bytes += 4*sizeof(long) + 8 *sizeof(float80); if (cif->bytes < sizeof(struct ia64_args)) cif->bytes = sizeof(struct ia64_args); /* The stack must be double word aligned, so round bytes up appropriately. */ cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*)); avn = cif->nargs; if (avn <= 2) { for (i = 0; i < avn; ++i) { switch(cif -> arg_types[i] -> type) { case FFI_TYPE_SINT32: simple_flag = FFI_ADD_INT_ARG(simple_flag); break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: simple_flag = FFI_ADD_LONG_ARG(simple_flag); break; default: is_simple = false; } } } else { is_simple = false; } /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: cif->flags = FFI_TYPE_VOID; break; case FFI_TYPE_STRUCT: { size_t sz = cif -> rtype -> size; unsigned short element_type; is_simple = false; if (is_homogeneous_fp_aggregate(cif -> rtype, 8, &element_type)) { int nelements = sz/float_type_size(element_type); if (nelements <= 1) { if (0 == nelements) { cif -> flags = FFI_TYPE_VOID; } else { cif -> flags = element_type; } } else { switch(element_type) { case FFI_TYPE_FLOAT: cif -> flags = FFI_IS_FLOAT_FP_AGGREGATE | nelements; break; case FFI_TYPE_DOUBLE: cif -> flags = FFI_IS_DOUBLE_FP_AGGREGATE | nelements; break; default: /* long double NYI */ abort(); } } break; } if (sz <= 32) { if (sz <= 8) { cif->flags = FFI_TYPE_INT; } else if (sz <= 16) { cif->flags = FFI_IS_SMALL_STRUCT2; } else if (sz <= 24) { cif->flags = FFI_IS_SMALL_STRUCT3; } else { cif->flags = FFI_IS_SMALL_STRUCT4; } } else { cif->flags = FFI_TYPE_STRUCT; } } break; case FFI_TYPE_FLOAT: is_simple = false; cif->flags = FFI_TYPE_FLOAT; break; case FFI_TYPE_DOUBLE: is_simple = false; cif->flags = FFI_TYPE_DOUBLE; break; default: cif->flags = FFI_TYPE_INT; /* This seems to depend on little endian mode, and the fact that */ /* the return pointer always points to at least 8 bytes. But */ /* that also seems to be true for other platforms. */ break; } if (is_simple) cif -> flags |= simple_flag; return FFI_OK; } extern int ffi_call_unix(bool (*)(struct ia64_args *, extended_cif *, int), extended_cif *, unsigned, unsigned, unsigned *, void (*)()); void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) { extended_cif ecif; long simple = cif -> flags & FFI_SIMPLE; /* Should this also check for Unix ABI? */ /* This is almost, but not quite, machine independent. Note that */ /* we can get away with not caring about length of the result because */ /* we assume we are little endian, and the result buffer is large */ /* enough. */ /* This needs work for HP/UX. */ if (simple) { long (*lfn)() = (long (*)())fn; long result; switch(simple) { case FFI_SIMPLE_V: result = lfn(); break; case FFI_SIMPLE_I: result = lfn(*(int *)avalue[0]); break; case FFI_SIMPLE_L: result = lfn(*(long *)avalue[0]); break; case FFI_SIMPLE_II: result = lfn(*(int *)avalue[0], *(int *)avalue[1]); break; case FFI_SIMPLE_IL: result = lfn(*(int *)avalue[0], *(long *)avalue[1]); break; case FFI_SIMPLE_LI: result = lfn(*(long *)avalue[0], *(int *)avalue[1]); break; case FFI_SIMPLE_LL: result = lfn(*(long *)avalue[0], *(long *)avalue[1]); break; } if ((cif->flags & ~FFI_SIMPLE) != FFI_TYPE_VOID && 0 != rvalue) { * (long *)rvalue = result; } return; } 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 && cif->rtype->type == FFI_TYPE_STRUCT) ecif.rvalue = alloca(cif->rtype->size); else ecif.rvalue = rvalue; switch (cif->abi) { case FFI_UNIX: ffi_call_unix(ffi_prep_args, &ecif, cif->bytes, cif->flags, rvalue, fn); break; default: FFI_ASSERT(0); break; } } /* * Closures represent a pair consisting of a function pointer, and * some user data. A closure is invoked by reinterpreting the closure * as a function pointer, and branching to it. Thus we can make an * interpreted function callable as a C function: We turn the interpreter * itself, together with a pointer specifying the interpreted procedure, * into a closure. * On X86, the first few words of the closure structure actually contain code, * which will do the right thing. On most other architectures, this * would raise some Icache/Dcache coherence issues (which can be solved, but * often not cheaply). * For IA64, function pointer are already pairs consisting of a code * pointer, and a gp pointer. The latter is needed to access global variables. * Here we set up such a pair as the first two words of the closure (in * the "trampoline" area), but we replace the gp pointer with a pointer * to the closure itself. We also add the real gp pointer to the * closure. This allows the function entry code to both retrieve the * user data, and to restire the correct gp pointer. */ static void ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue, void **avalue, ffi_cif *cif); /* This function is entered with the doctored gp (r1) value. * This code is extremely gcc specific. There is some argument that * it should really be written in assembly code, since it depends on * gcc properties that might change over time. */ /* ffi_closure_UNIX is an assembly routine, which copies the register */ /* state into a struct ia64_args, and then invokes */ /* ffi_closure_UNIX_inner. It also recovers the closure pointer */ /* from its fake gp pointer. */ void ffi_closure_UNIX(); #ifndef __GNUC__ # error This requires gcc #endif void ffi_closure_UNIX_inner (ffi_closure *closure, struct ia64_args * args) /* Hopefully declaring this as a varargs function will force all args */ /* to memory. */ { // this is our return value storage long double res; // our various things... ffi_cif *cif; unsigned short rtype; void *resp; void **arg_area; resp = (void*)&res; 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_UNIX(args, (void**)&resp, arg_area, cif); (closure->fun) (cif, resp, arg_area, closure->user_data); rtype = cif->flags; /* now, do a generic return based on the value of rtype */ if (rtype == FFI_TYPE_INT) { asm volatile ("ld8 r8=[%0]" : : "r" (resp) : "r8"); } else if (rtype == FFI_TYPE_FLOAT) { asm volatile ("ldfs f8=[%0]" : : "r" (resp) : "f8"); } else if (rtype == FFI_TYPE_DOUBLE) { asm volatile ("ldfd f8=[%0]" : : "r" (resp) : "f8"); } else if (rtype == FFI_IS_SMALL_STRUCT2) { asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]" : : "r" (resp), "r" (resp+8) : "r8","r9"); } else if (rtype == FFI_IS_SMALL_STRUCT3) { asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]" : : "r" (resp), "r" (resp+8), "r" (resp+16) : "r8","r9","r10"); } else if (rtype == FFI_IS_SMALL_STRUCT4) { asm volatile ("ld8 r8=[%0]; ld8 r9=[%1]; ld8 r10=[%2]; ld8 r11=[%3]" : : "r" (resp), "r" (resp+8), "r" (resp+16), "r" (resp+24) : "r8","r9","r10","r11"); } else if (rtype != FFI_TYPE_VOID && rtype != FFI_TYPE_STRUCT) { /* Can only happen for homogeneous FP aggregates? */ abort(); } } static void ffi_prep_incoming_args_UNIX(struct ia64_args *args, void **rvalue, void **avalue, ffi_cif *cif) { register unsigned int i; register unsigned int avn; register void **p_argv; register long *argp = args -> out_regs; unsigned fp_reg_num = 0; register ffi_type **p_arg; avn = cif->nargs; p_argv = avalue; for (i = cif->nargs, p_arg = cif->arg_types; i != 0; i--, p_arg++) { size_t z; /* In units of words or argument slots. */ switch ((*p_arg)->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: z = 1; *p_argv = (void *)argp; break; case FFI_TYPE_FLOAT: z = 1; /* Convert argument back to float in place from the saved value */ if (argp - args->out_regs < 8 && fp_reg_num < 8) { *(float *)argp = args -> fp_regs[fp_reg_num++]; } *p_argv = (void *)argp; break; case FFI_TYPE_DOUBLE: z = 1; if (argp - args->out_regs < 8 && fp_reg_num < 8) { *p_argv = args -> fp_regs + fp_reg_num++; } else { *p_argv = (void *)argp; } break; case FFI_TYPE_STRUCT: { size_t sz = (*p_arg)->size; unsigned short element_type; z = ((*p_arg)->size + FFI_SIZEOF_ARG - 1)/FFI_SIZEOF_ARG; if (argp - args->out_regs < 8 && is_homogeneous_fp_aggregate(*p_arg, 8, &element_type)) { int nelements = sz/float_type_size(element_type); if (nelements + fp_reg_num >= 8) { /* hard case NYI. */ abort(); } if (element_type == FFI_TYPE_DOUBLE) { *p_argv = args -> fp_regs + fp_reg_num; fp_reg_num += nelements; break; } if (element_type == FFI_TYPE_FLOAT) { int j; for (j = 0; j < nelements; ++ j) { ((float *)argp)[j] = args -> fp_regs[fp_reg_num + j]; } *p_argv = (void *)argp; fp_reg_num += nelements; break; } abort(); /* Other fp types NYI */ } } break; default: FFI_ASSERT(0); } argp += z; p_argv++; } return; } /* Fill in a closure to refer to the specified fun and user_data. */ /* cif specifies the argument and result types for fun. */ /* the cif must already be prep'ed */ /* The layout of a function descriptor. A C function pointer really */ /* points to one of these. */ typedef struct ia64_fd_struct { void *code_pointer; void *gp; } ia64_fd; ffi_status ffi_prep_closure (ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data) { struct ffi_ia64_trampoline_struct *tramp = (struct ffi_ia64_trampoline_struct *) (closure -> tramp); ia64_fd *fd = (ia64_fd *)(void *)ffi_closure_UNIX; FFI_ASSERT (cif->abi == FFI_UNIX); tramp -> code_pointer = fd -> code_pointer; tramp -> real_gp = fd -> gp; tramp -> fake_gp = closure; closure->cif = cif; closure->user_data = user_data; closure->fun = fun; return FFI_OK; } --- NEW FILE: ia64_flags.h --- /* ----------------------------------------------------------------------- ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company IA64/unix Foreign Function Interface Original author: Hans Boehm, HP Labs 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. ----------------------------------------------------------------------- */ /* Homogeneous Floating Point Aggregates (HFAs) which are returned */ /* in FP registers. The least significant bits specify the size in */ /* words. */ #define FFI_IS_FLOAT_FP_AGGREGATE 0x1000 #define FFI_IS_DOUBLE_FP_AGGREGATE 0x0800 #define FLOAT_FP_AGGREGATE_BIT 12 #define DOUBLE_FP_AGGREGATE_BIT 11 /* Small structures containing N words. If N=1, they are returned */ /* as though they were integers. */ #define FFI_IS_SMALL_STRUCT2 0x40 /* Struct > 8, <=16 bytes */ #define FFI_IS_SMALL_STRUCT3 0x41 /* Struct > 16 <= 24 bytes */ #define FFI_IS_SMALL_STRUCT4 0x42 /* Struct > 24, <=32 bytes */ /* Flag values identifying particularly simple cases, which are */ /* handled specially. We treat functions as simple if they take all */ /* arguments can be passed as 32 or 64 bit integer quantities, there is */ /* either no return value or it can be treated as a 64bit integer, and */ /* if there are at most 2 arguments. */ /* This is OR'ed with the normal flag values. */ #define FFI_SIMPLE_V 0x10000 /* () -> X */ #define FFI_SIMPLE_I 0x20000 /* (int) -> X */ #define FFI_SIMPLE_L 0x30000 /* (long) -> X */ #define FFI_SIMPLE_II 0x40000 /* (int,int) -> X */ #define FFI_SIMPLE_IL 0x50000 /* (int,long) -> X */ #define FFI_SIMPLE_LI 0x60000 /* (long,int) -> X */ #define FFI_SIMPLE_LL 0x70000 /* (long,long) -> X */ /* Mask for all of the FFI_SIMPLE bits: */ #define FFI_SIMPLE 0xf0000 /* An easy way to build FFI_SIMPLE flags from FFI_SIMPLE_V: */ #define FFI_ADD_LONG_ARG(flag) (((flag) << 1) | 0x10000) #define FFI_ADD_INT_ARG(flag) ((flag) << 1) --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for IA-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 #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_UNIX, /* Linux and all Unix variants use the same conventions */ FFI_DEFAULT_ABI = FFI_UNIX, FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */ /* can be interpreted as a C function */ /* descriptor: */ #ifndef LIBFFI_ASM struct ffi_ia64_trampoline_struct { void * code_pointer; /* Pointer to ffi_closure_UNIX */ void * fake_gp; /* Pointer to closure, installed as gp */ void * real_gp; /* Real gp value, reinstalled by */ /* ffi_closure_UNIX. */ }; #endif #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:24
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/x86 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/x86 Added Files: ffi.c ffi64.c ffitarget.h sysv.S unix64.S win32.S Log Message: Importing libffi sources and build tools. --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- 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) /*@=exportheader@*/ { register unsigned int i; register void **p_argv; register char *argp; register ffi_type **p_arg; argp = stack; if (ecif->cif->flags == FFI_TYPE_STRUCT) { *(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: #ifndef X86_WIN32 case FFI_TYPE_STRUCT: #endif 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; #ifdef X86_WIN32 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; } 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@*/ #ifdef X86_WIN32 /*@-declundef@*/ /*@-exportheader@*/ extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), /*@out@*/ extended_cif *, unsigned, unsigned, /*@out@*/ unsigned *, void (*fn)()); /*@=declundef@*/ /*@=exportheader@*/ #endif /* X86_WIN32 */ void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, /*@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) && (cif->flags == FFI_TYPE_STRUCT)) { /*@-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, &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_prep_incoming_args_SYSV (char *stack, void **ret, void** args, ffi_cif* cif); static void ffi_closure_SYSV (ffi_closure *) __attribute__ ((regparm(1))); static void ffi_closure_raw_SYSV (ffi_raw_closure *) __attribute__ ((regparm(1))); /* 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; unsigned short rtype; 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); 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"); } #ifdef X86_WIN32 else if (rtype == FFI_TYPE_SINT8) /* 1-byte struct */ { asm ("movsbl (%0),%%eax" : : "r" (resp) : "eax"); } else if (rtype == FFI_TYPE_SINT16) /* 2-bytes struct */ { asm ("movswl (%0),%%eax" : : "r" (resp) : "eax"); } #endif } /*@-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; /* 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; } /* 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) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-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__ */ --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- 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 /* ---- 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 /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #ifdef X86_64 #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 --- NEW FILE: unix64.S --- /* ----------------------------------------------------------------------- unix64.S - Copyright (c) 2002 Bo Thorsen <bo...@su...> 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. ----------------------------------------------------------------------- */ #ifdef __x86_64__ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .section .rodata .LC0: .string "asm in progress %lld\n" .LC1: .string "asm in progress\n" .text .align 2 .globl ffi_call_UNIX64 .type ffi_call_UNIX64,@function ffi_call_UNIX64: .LFB1: pushq %rbp .LCFI0: movq %rsp, %rbp .LCFI1: /* Save all arguments */ subq $48, %rsp .LCFI2: movq %rdi, -8(%rbp) /* ffi_prep_args */ movq %rsi, -16(%rbp) /* ffi_fill_return_value */ movq %rdx, -24(%rbp) /* ecif */ movq %rcx, -32(%rbp) /* cif->bytes */ movq %r8, -40(%rbp) /* ecif.rvalue */ movq %r9, -48(%rbp) /* fn */ /* Make room for all of the new args and the register args */ addl $176, %ecx .LCFI3: subq %rcx, %rsp .LCFI4: /* Setup the call to ffi_prep_args. */ movq %rdi, %rax /* &ffi_prep_args */ movq %rsp, %rdi /* stackLayout */ movq %rdx, %rsi /* ecif */ call *%rax /* ffi_prep_args(stackLayout, ecif);*/ /* ffi_prep_args have put all the register contents into the */ /* stackLayout struct. Now put the register values in place. */ movq (%rsp), %rdi movq 8(%rsp), %rsi movq 16(%rsp), %rdx movq 24(%rsp), %rcx movq 32(%rsp), %r8 movq 40(%rsp), %r9 movaps 48(%rsp), %xmm0 movaps 64(%rsp), %xmm1 movaps 80(%rsp), %xmm2 movaps 96(%rsp), %xmm3 movaps 112(%rsp), %xmm4 movaps 128(%rsp), %xmm5 movaps 144(%rsp), %xmm6 movaps 160(%rsp), %xmm7 /* Remove space for stackLayout so stack arguments are placed correctly for the call. */ .LCFI5: addq $176, %rsp .LCFI6: /* Call the user function. */ call *-48(%rbp) /* Make stack space for the return_value struct. */ subq $64, %rsp /* Fill in all potential return values to this struct. */ movq %rax, (%rsp) movq %rdx, 8(%rsp) movaps %xmm0, 16(%rsp) movaps %xmm1, 32(%rsp) fstpt 48(%rsp) /* Now call ffi_fill_return_value. */ movq %rsp, %rdi /* struct return_value */ movq -24(%rbp), %rsi /* ecif */ movq -16(%rbp), %rax /* &ffi_fill_return_value */ call *%rax /* call it */ /* And the work is done. */ leave ret .LFE1: .ffi_call_UNIX64_end: .size ffi_call_UNIX64,.ffi_call_UNIX64_end-ffi_call_UNIX64 .text .align 2 .globl float2sse .type float2sse,@function float2sse: /* Save the contents of this sse-float in a pointer. */ movaps %xmm0, (%rdi) ret .align 2 .globl floatfloat2sse .type floatfloat2sse,@function floatfloat2sse: /* Save the contents of these two sse-floats in a pointer. */ movq (%rdi), %xmm0 movaps %xmm0, (%rsi) ret .align 2 .globl double2sse .type double2sse,@function double2sse: /* Save the contents of this sse-double in a pointer. */ movaps %xmm0, (%rdi) ret .align 2 .globl sse2float .type sse2float,@function sse2float: /* Save the contents of this sse-float in a pointer. */ movaps (%rdi), %xmm0 ret .align 2 .globl sse2double .type sse2double,@function sse2double: /* Save the contents of this pointer in a sse-double. */ movaps (%rdi), %xmm0 ret .align 2 .globl sse2floatfloat .type sse2floatfloat,@function sse2floatfloat: /* Save the contents of this pointer in two sse-floats. */ movaps (%rdi), %xmm0 movq %xmm0, (%rsi) ret .align 2 .globl ffi_closure_UNIX64 .type ffi_closure_UNIX64,@function ffi_closure_UNIX64: .LFB2: pushq %rbp .LCFI10: movq %rsp, %rbp .LCFI11: subq $240, %rsp .LCFI12: movq %rdi, -176(%rbp) movq %rsi, -168(%rbp) movq %rdx, -160(%rbp) movq %rcx, -152(%rbp) movq %r8, -144(%rbp) movq %r9, -136(%rbp) /* FIXME: We can avoid all this stashing of XMM registers by (in ffi_prep_closure) computing the number of floating-point args and moving it into %rax before calling this function. Once this is done, uncomment the next few lines and only the essential XMM registers will be written to memory. This is a significant saving. */ /* movzbl %al, %eax */ /* movq %rax, %rdx */ /* leaq 0(,%rdx,4), %rax */ /* leaq 2f(%rip), %rdx */ /* subq %rax, %rdx */ leaq -1(%rbp), %rax /* jmp *%rdx */ movaps %xmm7, -15(%rax) movaps %xmm6, -31(%rax) movaps %xmm5, -47(%rax) movaps %xmm4, -63(%rax) movaps %xmm3, -79(%rax) movaps %xmm2, -95(%rax) movaps %xmm1, -111(%rax) movaps %xmm0, -127(%rax) 2: movl %edi, -180(%rbp) movl $0, -224(%rbp) movl $48, -220(%rbp) leaq 16(%rbp), %rax movq %rax, -216(%rbp) leaq -176(%rbp), %rdx movq %rdx, -208(%rbp) leaq -224(%rbp), %rsi movq %r10, %rdi movq %rsp, %rdx call ffi_closure_UNIX64_inner@PLT cmpl $FFI_TYPE_FLOAT, %eax je 1f cmpl $FFI_TYPE_DOUBLE, %eax je 2f cmpl $FFI_TYPE_LONGDOUBLE, %eax je 3f cmpl $FFI_TYPE_STRUCT, %eax je 4f popq %rax leave ret 1: 2: 3: movaps -240(%rbp), %xmm0 leave ret 4: leave ret .LFE2: .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe0: .long .LECIE1-.LSCIE1 .LSCIE1: .long 0x0 .byte 0x1 .string "zR" .uleb128 0x1 .sleb128 -8 .byte 0x10 .uleb128 0x1 .byte 0x1b .byte 0xc .uleb128 0x7 .uleb128 0x8 .byte 0x90 .uleb128 0x1 .align 8 .LECIE1: .LSFDE1: .long .LEFDE1-.LASFDE1 .LASFDE1: .long .LASFDE1-.Lframe0 .long .LFB1-. .long .LFE1-.LFB1 .uleb128 0x0 .byte 0x4 # DW_CFA_advance_loc4 .long .LCFI0-.LFB1 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 0x10 .byte 0x86 # DW_CFA_offset: r6 at cfa-16 .uleb128 0x2 .byte 0x4 # DW_CFA_advance_loc4 .long .LCFI1-.LCFI0 .byte 0x86 # DW_CFA_offset: r6 at cfa-16 .uleb128 0x2 .byte 0xd # DW_CFA_def_cfa_reg: r6 .uleb128 0x6 .align 8 .LEFDE1: .LSFDE3: .long .LEFDE3-.LASFDE3 # FDE Length .LASFDE3: .long .LASFDE3-.Lframe0 # FDE CIE offset .long .LFB2-. # FDE initial location .long .LFE2-.LFB2 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x4 # DW_CFA_advance_loc4 .long .LCFI10-.LFB2 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 0x10 .byte 0x86 # DW_CFA_offset, column 0x6 .uleb128 0x2 .byte 0x4 # DW_CFA_advance_loc4 .long .LCFI11-.LCFI10 .byte 0xd # DW_CFA_def_cfa_register .uleb128 0x6 .align 8 .LEFDE3: #endif /* __x86_64__ */ --- NEW FILE: win32.S --- /* ----------------------------------------------------------------------- win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc. Copyright (c) 2001 John Beniton Copyright (c) 2002 Ranjit Mathew X86 Foreign Function Interface 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .text .globl ffi_prep_args # This assumes we are using gas. .balign 16 .globl _ffi_call_SYSV _ffi_call_SYSV: pushl %ebp movl %esp,%ebp # Make room for all of the new args. movl 16(%ebp),%ecx subl %ecx,%esp movl %esp,%eax # Place all of the ffi_prep_args in position pushl 12(%ebp) pushl %eax call *8(%ebp) # Return stack to previous state and call the function addl $8,%esp # FIXME: Align the stack to a 128-bit boundary to avoid # potential performance hits. call *28(%ebp) # 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 # 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) retstruct1b: cmpl $FFI_TYPE_SINT8,%ecx jne retstruct2b # 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 # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx movw %ax,0(%ecx) jmp epilogue retstruct: # Nothing to do! noretval: epilogue: movl %ebp,%esp popl %ebp ret .ffi_call_SYSV_end: # This assumes we are using gas. .balign 16 .globl _ffi_call_STDCALL _ffi_call_STDCALL: pushl %ebp movl %esp,%ebp # Make room for all of the new args. movl 16(%ebp),%ecx subl %ecx,%esp movl %esp,%eax # Place all of the ffi_prep_args in position pushl 12(%ebp) pushl %eax call *8(%ebp) # Return stack to previous state and call the function addl $8,%esp # FIXME: Align the stack to a 128-bit boundary to avoid # potential performance hits. call *28(%ebp) # stdcall functions pop arguments off the stack themselves # Load %ecx with the return type code movl 20(%ebp),%ecx # If the return value pointer is NULL, assume no return value. cmpl $0,24(%ebp) jne sc_retint # Even if there is no space for the return value, we are # obliged to handle floating-point values. cmpl $FFI_TYPE_FLOAT,%ecx jne sc_noretval fstp %st(0) jmp sc_epilogue sc_retint: cmpl $FFI_TYPE_INT,%ecx jne sc_retfloat # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx movl %eax,0(%ecx) jmp sc_epilogue sc_retfloat: cmpl $FFI_TYPE_FLOAT,%ecx jne sc_retdouble # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx fstps (%ecx) jmp sc_epilogue sc_retdouble: cmpl $FFI_TYPE_DOUBLE,%ecx jne sc_retlongdouble # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx fstpl (%ecx) jmp sc_epilogue sc_retlongdouble: cmpl $FFI_TYPE_LONGDOUBLE,%ecx jne sc_retint64 # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx fstpt (%ecx) jmp sc_epilogue sc_retint64: cmpl $FFI_TYPE_SINT64,%ecx jne sc_retstruct1b # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx movl %eax,0(%ecx) movl %edx,4(%ecx) sc_retstruct1b: cmpl $FFI_TYPE_SINT8,%ecx jne sc_retstruct2b # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx movb %al,0(%ecx) jmp sc_epilogue sc_retstruct2b: cmpl $FFI_TYPE_SINT16,%ecx jne sc_retstruct # Load %ecx with the pointer to storage for the return value movl 24(%ebp),%ecx movw %ax,0(%ecx) jmp sc_epilogue sc_retstruct: # Nothing to do! sc_noretval: sc_epilogue: movl %ebp,%esp popl %ebp ret .ffi_call_STDCALL_end: --- NEW FILE: sysv.S --- /* ----------------------------------------------------------------------- sysv.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. ----------------------------------------------------------------------- */ #ifndef __x86_64__ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .text .globl ffi_prep_args .align 4 .globl ffi_call_SYSV .type ffi_call_SYSV,@function ffi_call_SYSV: .LFB1: pushl %ebp .LCFI0: movl %esp,%ebp .LCFI1: /* Make room for all of the new args. */ movl 16(%ebp),%ecx subl %ecx,%esp movl %esp,%eax /* Place all of the ffi_prep_args in position */ pushl 12(%ebp) pushl %eax call *8(%ebp) /* Return stack to previous state and call the function */ addl $8,%esp 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 /* 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 retstruct /* Load %ecx with the pointer to storage for the return value */ movl 24(%ebp),%ecx movl %eax,0(%ecx) movl %edx,4(%ecx) retstruct: /* Nothing to do! */ noretval: epilogue: movl %ebp,%esp popl %ebp ret .LFE1: .ffi_call_SYSV_end: .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV .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 /* ifndef __x86_64__ */ --- NEW FILE: ffi64.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 2002 Bo Thorsen <bo...@su...> 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> /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ #ifdef __x86_64__ #define MAX_GPR_REGS 6 #define MAX_SSE_REGS 8 typedef struct { /* Registers for argument passing. */ long gpr[MAX_GPR_REGS]; __int128_t sse[MAX_SSE_REGS]; /* Stack space for arguments. */ char argspace[0]; } stackLayout; /* 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_MEMORY_CLASS }; #define MAX_CLASSES 4 /* 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 or X87UP class, MEMORY is used. */ if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_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[], int *byte_offset) { /* First, align to the right place. */ *byte_offset = ALIGN(*byte_offset, type->alignment); 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) % 8 + 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) % 8) == 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: { const int UNITS_PER_WORD = 8; int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ffi_type **ptr; int i; enum x86_64_reg_class subclasses[MAX_CLASSES]; /* 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++) { int num; num = classify_argument (*ptr, subclasses, byte_offset); if (num == 0) return 0; for (i = 0; i < num; i++) { int pos = *byte_offset / 8; classes[i + pos] = merge_classes (subclasses[i], classes[i + pos]); } if ((*ptr)->type != FFI_TYPE_STRUCT) *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 0 iff parameter should be passed in memory. */ static int examine_argument (ffi_type *type, int in_return, int *int_nregs,int *sse_nregs) { enum x86_64_reg_class class[MAX_CLASSES]; int offset = 0; int n; n = classify_argument (type, class, &offset); if (n == 0) return 0; *int_nregs = 0; *sse_nregs = 0; for (n--; n>=0; n--) switch (class[n]) { case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: (*int_nregs)++; break; case X86_64_SSE_CLASS: case X86_64_SSESF_CLASS: case X86_64_SSEDF_CLASS: (*sse_nregs)++; break; case X86_64_NO_CLASS: case X86_64_SSEUP_CLASS: break; case X86_64_X87_CLASS: case X86_64_X87UP_CLASS: if (!in_return) return 0; break; default: abort (); } return 1; } /* Functions to load floats and double to an SSE register placeholder. */ extern void float2sse (float, __int128_t *); extern void double2sse (double, __int128_t *); extern void floatfloat2sse (void *, __int128_t *); /* Functions to put the floats and doubles back. */ extern float sse2float (__int128_t *); extern double sse2double (__int128_t *); extern void sse2floatfloat(__int128_t *, void *); /*@-exportheader@*/ void ffi_prep_args (stackLayout *stack, extended_cif *ecif) /*@=exportheader@*/ { int gprcount, ssecount, i, g, s; void **p_argv; void *argp = &stack->argspace; ffi_type **p_arg; /* First check if the return value should be passed in memory. If so, pass the pointer as the first argument. */ gprcount = ssecount = 0; if (ecif->cif->rtype->type != FFI_TYPE_VOID && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0) stack->gpr[gprcount++] = (long) ecif->rvalue; for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue; i!=0; i--, p_arg++, p_argv++) { int in_register = 0; switch ((*p_arg)->type) { case FFI_TYPE_SINT8: case FFI_TYPE_SINT16: case FFI_TYPE_SINT32: case FFI_TYPE_SINT64: case FFI_TYPE_UINT8: case FFI_TYPE_UINT16: case FFI_TYPE_UINT32: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: if (gprcount < MAX_GPR_REGS) { stack->gpr[gprcount] = 0; stack->gpr[gprcount++] = *(long long *)(*p_argv); in_register = 1; } break; case FFI_TYPE_FLOAT: if (ssecount < MAX_SSE_REGS) { float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]); in_register = 1; } break; case FFI_TYPE_DOUBLE: if (ssecount < MAX_SSE_REGS) { double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]); in_register = 1; } break; } if (in_register) continue; /* Either all places in registers where filled, or this is a type that potentially goes into a memory slot. */ if (examine_argument (*p_arg, 0, &g, &s) == 0 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) { /* Pass this argument in memory. */ argp = (void *)ALIGN(argp, (*p_arg)->alignment); memcpy (argp, *p_argv, (*p_arg)->size); argp += (*p_arg)->size; } else { /* All easy cases are eliminated. Now fire the big guns. */ enum x86_64_reg_class classes[MAX_CLASSES]; int offset = 0, j, num; void *a; num = classify_argument (*p_arg, classes, &offset); for (j=0, a=*p_argv; j<num; j++, a+=8) { switch (classes[j]) { case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: stack->gpr[gprcount++] = *(long long *)a; break; case X86_64_SSE_CLASS: floatfloat2sse (a, &stack->sse[ssecount++]); break; case X86_64_SSESF_CLASS: float2sse (*(float *)a, &stack->sse[ssecount++]); break; case X86_64_SSEDF_CLASS: double2sse (*(double *)a, &stack->sse[ssecount++]); break; default: abort(); } } } } } /* Perform machine dependent cif processing. */ ffi_status ffi_prep_cif_machdep (ffi_cif *cif) { int gprcount, ssecount, i, g, s; gprcount = ssecount = 0; /* Reset the byte count. We handle this size estimation here. */ cif->bytes = 0; /* If the return value should be passed in memory, pass the pointer as the first argument. The actual memory isn't allocated here. */ if (cif->rtype->type != FFI_TYPE_VOID && examine_argument (cif->rtype, 1, &g, &s) == 0) gprcount = 1; /* 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 (i=0; i<cif->nargs; i++) { if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) { /* This is passed in memory. First align to the basic type. */ cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment); /* Stack arguments are *always* at least 8 byte aligned. */ cif->bytes = ALIGN(cif->bytes, 8); /* Now add the size of this argument. */ cif->bytes += cif->arg_types[i]->size; } else { gprcount += g; ssecount += s; } } /* Set the flag for the closures return. */ switch (cif->rtype->type) { case FFI_TYPE_VOID: case FFI_TYPE_STRUCT: 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; default: cif->flags = FFI_TYPE_INT; break; } return FFI_OK; } typedef struct { long gpr[2]; __int128_t sse[2]; long double st0; } return_value; void ffi_fill_return_value (return_value *rv, extended_cif *ecif) { enum x86_64_reg_class classes[MAX_CLASSES]; int i = 0, num; long *gpr = rv->gpr; __int128_t *sse = rv->sse; signed char sc; signed short ss; /* This is needed because of the way x86-64 handles signed short integers. */ switch (ecif->cif->rtype->type) { case FFI_TYPE_SINT8: sc = *(signed char *)gpr; *(long long *)ecif->rvalue = (long long)sc; return; case FFI_TYPE_SINT16: ss = *(signed short *)gpr; *(long long *)ecif->rvalue = (long long)ss; return; default: /* Just continue. */ ; } num = classify_argument (ecif->cif->rtype, classes, &i); if (num == 0) /* Return in memory. */ ecif->rvalue = (void *) rv->gpr[0]; else if (num == 2 && classes[0] == X86_64_X87_CLASS && classes[1] == X86_64_X87UP_CLASS) /* This is a long double (this is easiest to handle this way instead of an eightbyte at a time as in the loop below. */ *((long double *)ecif->rvalue) = rv->st0; else { void *a; for (i=0, a=ecif->rvalue; i<num; i++, a+=8) { switch (classes[i]) { case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: *(long long *)a = *gpr; gpr++; break; case X86_64_SSE_CLASS: sse2floatfloat (sse++, a); break; case X86_64_SSESF_CLASS: *(float *)a = sse2float (sse++); break; case X86_64_SSEDF_CLASS: *(double *)a = sse2double (sse++); break; default: abort(); } } } } /*@-declundef@*/ /*@-exportheader@*/ extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *), void (*) (return_value *, extended_cif *), /*@out@*/ extended_cif *, unsigned, /*@out@*/ unsigned *, void (*fn)()); /*@=declundef@*/ /*@=exportheader@*/ void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, /*@dependent@*/ void **avalue) { extended_cif ecif; int dummy; 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) && (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0)) { /*@-sysunrecog@*/ ecif.rvalue = alloca(cif->rtype->size); /*@=sysunrecog@*/ } else ecif.rvalue = rvalue; /* Stack must always be 16byte aligned. Make it so. */ cif->bytes = ALIGN(cif->bytes, 16); switch (cif->abi) { case FFI_SYSV: /* Calling 32bit code from 64bit is not possible */ FFI_ASSERT(0); break; case FFI_UNIX64: /*@-usedef@*/ ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif, cif->bytes, ecif.rvalue, fn); /*@=usedef@*/ break; default: FFI_ASSERT(0); break; } } 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) { volatile unsigned short *tramp; /* FFI_ASSERT (cif->abi == FFI_OSF); */ tramp = (volatile unsigned short *) &closure->tramp[0]; tramp[0] = 0xbb49; /* mov <code>, %r11 */ tramp[5] = 0xba49; /* mov <data>, %r10 */ tramp[10] = 0xff49; /* jmp *%r11 */ tramp[11] = 0x00e3; *(void * volatile *) &tramp[1] = ffi_closure_UNIX64; *(void * volatile *) &tramp[6] = closure; closure->cif = cif; closure->fun = fun; closure->user_data = user_data; return FFI_OK; } int ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp) { ffi_cif *cif; void **avalue; ffi_type **arg_types; long i, avn, argn; cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); argn = 0; i = 0; avn = cif->nargs; arg_types = cif->arg_types; /* Grab the addresses of the arguments from the stack frame. */ while (i < avn) { switch (arg_types[i]->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: { if (l->gp_offset > 48-8) { avalue[i] = l->overflow_arg_area; l->overflow_arg_area = (char *)l->overflow_arg_area + 8; } else { avalue[i] = (char *)l->reg_save_area + l->gp_offset; l->gp_offset += 8; } } break; case FFI_TYPE_STRUCT: /* FIXME */ FFI_ASSERT(0); break; case FFI_TYPE_DOUBLE: { if (l->fp_offset > 176-16) { avalue[i] = l->overflow_arg_area; l->overflow_arg_area = (char *)l->overflow_arg_area + 8; } else { avalue[i] = (char *)l->reg_save_area + l->fp_offset; l->fp_offset += 16; } } #if DEBUG_FFI fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]); #endif break; case FFI_TYPE_FLOAT: { if (l->fp_offset > 176-16) { avalue[i] = l->overflow_arg_area; l->overflow_arg_area = (char *)l->overflow_arg_area + 8; } else { avalue[i] = (char *)l->reg_save_area + l->fp_offset; l->fp_offset += 16; } } #if DEBUG_FFI fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]); #endif break; default: FFI_ASSERT(0); } argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; i++; } /* Invoke the closure. */ (closure->fun) (cif, rp, avalue, closure->user_data); /* FIXME: Structs not supported. */ FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT); /* Tell ffi_closure_UNIX64 how to perform return type promotions. */ return cif->rtype->type; } #endif /* ifndef __x86_64__ */ |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:22
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src Added Files: debug.c ffitest.c java_raw_api.c prep_cif.c raw_api.c types.c Log Message: Importing libffi sources and build tools. --- NEW FILE: java_raw_api.c --- /* ----------------------------------------------------------------------- java_raw_api.c - Copyright (c) 1999 Red Hat, Inc. Cloned from raw_api.c Raw_api.c author: Kresten Krab Thorup <kr...@gn...> Java_raw_api.c author: Hans-J. Boehm <hb...@hp...> $Id $ 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 defines a Java- and 64-bit specific variant of the raw API. */ /* It assumes that "raw" argument blocks look like Java stacks on a */ /* 64-bit machine. Arguments that can be stored in a single stack */ /* stack slots (longs, doubles) occupy 128 bits, but only the first */ /* 64 bits are actually used. */ #include <ffi.h> #include <ffi_common.h> #include <stdlib.h> #if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API) size_t ffi_java_raw_size (ffi_cif *cif) { size_t result = 0; int i; ffi_type **at = cif->arg_types; for (i = cif->nargs-1; i >= 0; i--, at++) { switch((*at) -> type) { case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: case FFI_TYPE_DOUBLE: result += 2 * FFI_SIZEOF_ARG; break; case FFI_TYPE_STRUCT: /* No structure parameters in Java. */ abort(); default: result += FFI_SIZEOF_ARG; } } return result; } void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) { unsigned i; ffi_type **tp = cif->arg_types; #if WORDS_BIGENDIAN for (i = 0; i < cif->nargs; i++, tp++, args++) { switch ((*tp)->type) { case FFI_TYPE_UINT8: case FFI_TYPE_SINT8: *args = (void*) ((char*)(raw++) + 3); break; case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: *args = (void*) ((char*)(raw++) + 2); break; #if FFI_SIZEOF_ARG == 8 case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: case FFI_TYPE_DOUBLE: *args = (void *)raw; raw += 2; break; #endif case FFI_TYPE_POINTER: *args = (void*) &(raw++)->ptr; break; default: *args = raw; raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } #else /* WORDS_BIGENDIAN */ #if !PDP /* then assume little endian */ for (i = 0; i < cif->nargs; i++, tp++, args++) { #if FFI_SIZEOF_ARG == 8 switch((*tp)->type) { case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: case FFI_TYPE_DOUBLE: *args = (void*) raw; raw += 2; break; default: *args = (void*) raw++; } #else /* FFI_SIZEOF_ARG != 8 */ *args = (void*) raw; raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); #endif /* FFI_SIZEOF_ARG == 8 */ } #else #error "pdp endian not supported" #endif /* ! PDP */ #endif /* WORDS_BIGENDIAN */ } void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw) { unsigned i; ffi_type **tp = cif->arg_types; for (i = 0; i < cif->nargs; i++, tp++, args++) { switch ((*tp)->type) { case FFI_TYPE_UINT8: #if WORDS_BIGENDIAN *(UINT32*)(raw++) = *(UINT8*) (*args); #else (raw++)->uint = *(UINT8*) (*args); #endif break; case FFI_TYPE_SINT8: #if WORDS_BIGENDIAN *(SINT32*)(raw++) = *(SINT8*) (*args); #else (raw++)->sint = *(SINT8*) (*args); #endif break; case FFI_TYPE_UINT16: #if WORDS_BIGENDIAN *(UINT32*)(raw++) = *(UINT16*) (*args); #else (raw++)->uint = *(UINT16*) (*args); #endif break; case FFI_TYPE_SINT16: #if WORDS_BIGENDIAN *(SINT32*)(raw++) = *(SINT16*) (*args); #else (raw++)->sint = *(SINT16*) (*args); #endif break; case FFI_TYPE_UINT32: #if WORDS_BIGENDIAN *(UINT32*)(raw++) = *(UINT32*) (*args); #else (raw++)->uint = *(UINT32*) (*args); #endif break; case FFI_TYPE_SINT32: #if WORDS_BIGENDIAN *(SINT32*)(raw++) = *(SINT32*) (*args); #else (raw++)->sint = *(SINT32*) (*args); #endif break; case FFI_TYPE_FLOAT: (raw++)->flt = *(FLOAT32*) (*args); break; #if FFI_SIZEOF_ARG == 8 case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: case FFI_TYPE_DOUBLE: raw->uint = *(UINT64*) (*args); raw += 2; break; #endif case FFI_TYPE_POINTER: (raw++)->ptr = **(void***) args; break; default: #if FFI_SIZEOF_ARG == 8 FFI_ASSERT(0); /* Should have covered all cases */ #else memcpy ((void*) raw->data, (void*)*args, (*tp)->size); raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; #endif } } } #if !FFI_NATIVE_RAW_API static void ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue) { #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8 switch (cif->rtype->type) { case FFI_TYPE_UINT8: case FFI_TYPE_UINT16: case FFI_TYPE_UINT32: *(UINT64 *)rvalue <<= 32; break; case FFI_TYPE_SINT8: case FFI_TYPE_SINT16: case FFI_TYPE_SINT32: case FFI_TYPE_INT: *(SINT64 *)rvalue <<= 32; break; default: break; } #endif } static void ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue) { #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8 switch (cif->rtype->type) { case FFI_TYPE_UINT8: case FFI_TYPE_UINT16: case FFI_TYPE_UINT32: *(UINT64 *)rvalue >>= 32; break; case FFI_TYPE_SINT8: case FFI_TYPE_SINT16: case FFI_TYPE_SINT32: case FFI_TYPE_INT: *(SINT64 *)rvalue >>= 32; break; default: break; } #endif } /* This is a generic definition of ffi_raw_call, to be used if the * native system does not provide a machine-specific implementation. * Having this, allows code to be written for the raw API, without * the need for system-specific code to handle input in that format; * these following couple of functions will handle the translation forth * and back automatically. */ void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, /*@dependent@*/ ffi_raw *raw) { void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); ffi_java_raw_to_ptrarray (cif, raw, avalue); ffi_call (cif, fn, rvalue, avalue); ffi_java_rvalue_to_raw (cif, rvalue); } #if FFI_CLOSURES /* base system provides closures */ static void ffi_java_translate_args (ffi_cif *cif, void *rvalue, void **avalue, void *user_data) { ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif)); ffi_raw_closure *cl = (ffi_raw_closure*)user_data; ffi_java_ptrarray_to_raw (cif, avalue, raw); (*cl->fun) (cif, rvalue, raw, cl->user_data); ffi_java_raw_to_rvalue (cif, rvalue); } /* Again, here is the generic version of ffi_prep_raw_closure, which * will install an intermediate "hub" for translation of arguments from * the pointer-array format, to the raw format */ ffi_status ffi_prep_java_raw_closure (ffi_raw_closure* cl, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data) { ffi_status status; status = ffi_prep_closure ((ffi_closure*) cl, cif, &ffi_java_translate_args, (void*)cl); if (status == FFI_OK) { cl->fun = fun; cl->user_data = user_data; } return status; } #endif /* FFI_CLOSURES */ #endif /* !FFI_NATIVE_RAW_API */ #endif /* !FFI_NO_RAW_API */ --- NEW FILE: ffitest.c --- /* ----------------------------------------------------------------------- ffitest.c - Copyright (c) 1996, 1997, 1998, 2002, 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, [...1275 lines suppressed...] CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn3, (void *) 3 /* userdata */) == FFI_OK); CHECK((*((closure_test_type3)pcl)) (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13, 19.19, 21.21, 1) == 135); } (void) puts("\nFinished FFI_CLOSURES\n"); # endif /* If we arrived here, all is good */ (void) puts("\nLooks good. No surprises.\n"); /*@-compdestroy@*/ return 0; } --- NEW FILE: prep_cif.c --- /* ----------------------------------------------------------------------- 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 <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) { ffi_type **ptr; FFI_ASSERT(arg != NULL); /*@-usedef@*/ FFI_ASSERT(arg->elements != NULL); FFI_ASSERT(arg->size == 0); FFI_ASSERT(arg->alignment == 0); 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); arg->size = ALIGN(arg->size, (*ptr)->alignment); arg->size += (*ptr)->size; arg->alignment = (arg->alignment > (*ptr)->alignment) ? arg->alignment : (*ptr)->alignment; 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; else return FFI_OK; /*@=usedef@*/ } /* Perform machine independent ffi_cif preparation, then call machine dependent routine. */ 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) { unsigned bytes = 0; unsigned int i; ffi_type **ptr; FFI_ASSERT(cif != NULL); FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); 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 ) 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; /* Perform a sanity check on the argument type, do this check after the initialization. */ FFI_ASSERT_VALID_TYPE(*ptr); #if !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); } --- NEW FILE: types.c --- /* ----------------------------------------------------------------------- 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 } /* Size and alignment are fake here. They must not be 0. */ FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); 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); #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 FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, 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 #ifdef X86_WIN32 FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); #else FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); #endif FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); #elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); #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 --- NEW FILE: raw_api.c --- /* ----------------------------------------------------------------------- raw_api.c - Copyright (c) 1999 Red Hat, Inc. Author: Kresten Krab Thorup <kr...@gn...> $Id $ 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 defines generic functions for use with the raw api. */ #include <ffi.h> #include <ffi_common.h> #if !FFI_NO_RAW_API size_t ffi_raw_size (ffi_cif *cif) { size_t result = 0; int i; ffi_type **at = cif->arg_types; for (i = cif->nargs-1; i >= 0; i--, at++) { #if !FFI_NO_STRUCTS if ((*at)->type == FFI_TYPE_STRUCT) result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG); else #endif result += ALIGN ((*at)->size, FFI_SIZEOF_ARG); } return result; } void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) { unsigned i; ffi_type **tp = cif->arg_types; #if WORDS_BIGENDIAN for (i = 0; i < cif->nargs; i++, tp++, args++) { switch ((*tp)->type) { case FFI_TYPE_UINT8: case FFI_TYPE_SINT8: *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1); break; case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2); break; #if FFI_SIZEOF_ARG >= 4 case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4); break; #endif #if !FFI_NO_STRUCTS case FFI_TYPE_STRUCT: *args = (raw++)->ptr; break; #endif case FFI_TYPE_POINTER: *args = (void*) &(raw++)->ptr; break; default: *args = raw; raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } #else /* WORDS_BIGENDIAN */ #if !PDP /* then assume little endian */ for (i = 0; i < cif->nargs; i++, tp++, args++) { #if !FFI_NO_STRUCTS if ((*tp)->type == FFI_TYPE_STRUCT) { *args = (raw++)->ptr; } else #endif { *args = (void*) raw; raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); } } #else #error "pdp endian not supported" #endif /* ! PDP */ #endif /* WORDS_BIGENDIAN */ } void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw) { unsigned i; ffi_type **tp = cif->arg_types; for (i = 0; i < cif->nargs; i++, tp++, args++) { switch ((*tp)->type) { case FFI_TYPE_UINT8: (raw++)->uint = *(UINT8*) (*args); break; case FFI_TYPE_SINT8: (raw++)->sint = *(SINT8*) (*args); break; case FFI_TYPE_UINT16: (raw++)->uint = *(UINT16*) (*args); break; case FFI_TYPE_SINT16: (raw++)->sint = *(SINT16*) (*args); break; #if FFI_SIZEOF_ARG >= 4 case FFI_TYPE_UINT32: (raw++)->uint = *(UINT32*) (*args); break; case FFI_TYPE_SINT32: (raw++)->sint = *(SINT32*) (*args); break; #endif #if !FFI_NO_STRUCTS case FFI_TYPE_STRUCT: (raw++)->ptr = *args; break; #endif case FFI_TYPE_POINTER: (raw++)->ptr = **(void***) args; break; default: memcpy ((void*) raw->data, (void*)*args, (*tp)->size); raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } } #if !FFI_NATIVE_RAW_API /* This is a generic definition of ffi_raw_call, to be used if the * native system does not provide a machine-specific implementation. * Having this, allows code to be written for the raw API, without * the need for system-specific code to handle input in that format; * these following couple of functions will handle the translation forth * and back automatically. */ void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@out@*/ void *rvalue, /*@dependent@*/ ffi_raw *raw) { void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); ffi_raw_to_ptrarray (cif, raw, avalue); ffi_call (cif, fn, rvalue, avalue); } #if FFI_CLOSURES /* base system provides closures */ static void ffi_translate_args (ffi_cif *cif, void *rvalue, void **avalue, void *user_data) { ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif)); ffi_raw_closure *cl = (ffi_raw_closure*)user_data; ffi_ptrarray_to_raw (cif, avalue, raw); (*cl->fun) (cif, rvalue, raw, cl->user_data); } /* Again, here is the generic version of ffi_prep_raw_closure, which * will install an intermediate "hub" for translation of arguments from * the pointer-array format, to the raw format */ ffi_status ffi_prep_raw_closure (ffi_raw_closure* cl, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data) { ffi_status status; status = ffi_prep_closure ((ffi_closure*) cl, cif, &ffi_translate_args, (void*)cl); if (status == FFI_OK) { cl->fun = fun; cl->user_data = user_data; } return status; } #endif /* FFI_CLOSURES */ #endif /* !FFI_NATIVE_RAW_API */ #endif /* !FFI_NO_RAW_API */ --- NEW FILE: debug.c --- /* ----------------------------------------------------------------------- debug.c - Copyright (c) 1996 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 <stdlib.h> #include <stdio.h> /* General debugging routines */ void ffi_stop_here(void) { /* This function is only useful for debugging purposes. Place a breakpoint on ffi_stop_here to be notified of significant events. */ } /* This function should only be called via the FFI_ASSERT() macro */ void ffi_assert(char *expr, char *file, int line) { fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line); ffi_stop_here(); abort(); } /* Perform a sanity check on an ffi_type structure */ void ffi_type_test(ffi_type *a, char *file, int line) { FFI_ASSERT_AT(a != NULL, file, line); /*@-usedef@*/ FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line); FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line); FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line); FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line); /*@=usedef@*/ } |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:22
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/arm In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/arm Added Files: ffi.c ffitarget.h sysv.S Log Message: Importing libffi sources and build tools. --- NEW FILE: sysv.S --- /* ----------------------------------------------------------------------- sysv.S - Copyright (c) 1998 Red Hat, Inc. ARM 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #ifdef HAVE_MACHINE_ASM_H #include <machine/asm.h> #else #ifdef __USER_LABEL_PREFIX__ #define CONCAT1(a, b) CONCAT2(a, b) #define CONCAT2(a, b) a ## b /* Use the right prefix for global labels. */ #define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x) #else #define CNAME(x) x #endif #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): #endif .text # a1: ffi_prep_args # a2: &ecif # a3: cif->bytes # a4: fig->flags # sp+0: ecif.rvalue # sp+4: fn # This assumes we are using gas. ENTRY(ffi_call_SYSV) # Save registers stmfd sp!, {a1-a4, fp, lr} mov fp, sp # Make room for all of the new args. sub sp, fp, a3 # Place all of the ffi_prep_args in position mov ip, a1 mov a1, sp # a2 already set # And call mov lr, pc mov pc, ip # move first 4 parameters in registers ldr a1, [sp, #0] ldr a2, [sp, #4] ldr a3, [sp, #8] ldr a4, [sp, #12] # and adjust stack ldr ip, [fp, #8] cmp ip, #16 movge ip, #16 add sp, sp, ip # call function mov lr, pc ldr pc, [fp, #28] # Remove the space we pushed for the args mov sp, fp # Load a3 with the pointer to storage for the return value ldr a3, [sp, #24] # Load a4 with the return type code ldr a4, [sp, #12] # If the return value pointer is NULL, assume no return value. cmp a3, #0 beq epilogue # return INT cmp a4, #FFI_TYPE_INT streq a1, [a3] beq epilogue # return FLOAT cmp a4, #FFI_TYPE_FLOAT #ifdef __SOFTFP__ streq a1, [a3] #else stfeqs f0, [a3] #endif beq epilogue # return DOUBLE or LONGDOUBLE cmp a4, #FFI_TYPE_DOUBLE #ifdef __SOFTFP__ stmeqia a3, {a1, a2} #else stfeqd f0, [a3] #endif epilogue: ldmfd sp!, {a1-a4, fp, pc} .ffi_call_SYSV_end: .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1998 Red Hat, Inc. ARM 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> /* 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; register char *argp; register ffi_type **p_arg; argp = stack; if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) { *(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 (((*p_arg)->alignment - 1) & (unsigned) argp) { argp = (char *) ALIGN(argp, (*p_arg)->alignment); } 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_STRUCT: *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); break; default: FFI_ASSERT(0); } } else if (z == sizeof(int)) { *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); } 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: case FFI_TYPE_STRUCT: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags = (unsigned) cif->rtype->type; break; default: cif->flags = FFI_TYPE_INT; break; } 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@*/ void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@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) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-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, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); /*@=usedef@*/ break; default: FFI_ASSERT(0); break; } } --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for ARM. 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 #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 0 #define FFI_NATIVE_RAW_API 0 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:22
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/powerpc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/powerpc Added Files: aix.S aix_closure.S asm.h darwin.S darwin_closure.S ffi.c ffi_darwin.c ffitarget.h linux64.S linux64_closure.S ppc_closure.S sysv.S Log Message: Importing libffi sources and build tools. --- NEW FILE: aix.S --- /* ----------------------------------------------------------------------- aix.S - Copyright (c) 2002 Free Software Foundation, Inc. based on darwin.S by John Hornkvist 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. ----------------------------------------------------------------------- */ .set r0,0 .set r1,1 .set r2,2 .set r3,3 .set r4,4 .set r5,5 .set r6,6 .set r7,7 .set r8,8 .set r9,9 .set r10,10 .set r11,11 .set r12,12 .set r13,13 .set r14,14 .set r15,15 .set r16,16 .set r17,17 .set r18,18 .set r19,19 .set r20,20 .set r21,21 .set r22,22 .set r23,23 .set r24,24 .set r25,25 .set r26,26 .set r27,27 .set r28,28 .set r29,29 .set r30,30 .set r31,31 .set f0,0 .set f1,1 .set f2,2 .set f3,3 .set f4,4 .set f5,5 .set f6,6 .set f7,7 .set f8,8 .set f9,9 .set f10,10 .set f11,11 .set f12,12 .set f13,13 .set f14,14 .set f15,15 .set f16,16 .set f17,17 .set f18,18 .set f19,19 .set f20,20 .set f21,21 #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #define JUMPTARGET(name) name #define L(x) x .file "aix.S" .toc .csect .text[PR] .align 2 .globl ffi_prep_args .csect .text[PR] .align 2 .globl ffi_call_AIX .globl .ffi_call_AIX .csect ffi_call_AIX[DS] ffi_call_AIX: .long .ffi_call_AIX, TOC[tc0], 0 .csect .text[PR] .ffi_call_AIX: mr r12,r8 // We only need r12 until the call, so it doesn't have to be saved... /* Save the old stack pointer as AP. */ mr r8,r1 /* Allocate the stack space we need. */ stwux r1,r1,r4 /* Save registers we use. */ mflr r9 stw r28,-16(r8) stw r29,-12(r8) stw r30, -8(r8) stw r31, -4(r8) stw r9, 8(r8) stw r2, 20(r1) /* Save arguments over call... */ mr r31,r5 /* flags, */ mr r30,r6 /* rvalue, */ mr r29,r7 /* function address, */ mr r28,r8 /* our AP. */ /* Call ffi_prep_args. */ mr r4,r1 li r9,0 lwz r2,4(r12) lwz r12,0(r12) mtctr r12 // r12 holds address of _ffi_prep_args bctrl lwz r2,20(r1) /* Now do the call. */ lwz r12,0(r29) /* Set up cr1 with bits 4-7 of the flags. */ mtcrf 0x40,r31 stw r2,20(r1) mtctr r12 lwz r2,4(r29) /* Load all those argument registers. */ // We have set up a nice stack frame, just load it into registers. lwz r3, 20+(1*4)(r1) lwz r4, 20+(2*4)(r1) lwz r5, 20+(3*4)(r1) lwz r6, 20+(4*4)(r1) nop lwz r7, 20+(5*4)(r1) lwz r8, 20+(6*4)(r1) lwz r9, 20+(7*4)(r1) lwz r10,20+(8*4)(r1) L1: /* Load all the FP registers. */ bf 6,L2 // 2f + 0x18 lfd f1,-16-(13*8)(r28) lfd f2,-16-(12*8)(r28) lfd f3,-16-(11*8)(r28) lfd f4,-16-(10*8)(r28) nop lfd f5,-16-(9*8)(r28) lfd f6,-16-(8*8)(r28) lfd f7,-16-(7*8)(r28) lfd f8,-16-(6*8)(r28) nop lfd f9,-16-(5*8)(r28) lfd f10,-16-(4*8)(r28) lfd f11,-16-(3*8)(r28) lfd f12,-16-(2*8)(r28) nop lfd f13,-16-(1*8)(r28) L2: /* Make the call. */ bctrl lwz r2,20(r1) /* Now, deal with the return value. */ mtcrf 0x01,r31 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) /* Fall through... */ L(done_return_value): /* Restore the registers we used and return. */ lwz r9, 8(r28) lwz r31, -4(r28) mtlr r9 lwz r30, -8(r28) lwz r29,-12(r28) lwz r28,-16(r28) lwz r1,0(r1) blr L(fp_return_value): bf 28,L(float_return_value) stfd f1,0(r30) b L(done_return_value) L(float_return_value): stfs f1,0(r30) b L(done_return_value) .long 0 .byte 0,0,0,1,128,4,0,0 //END(ffi_call_AIX) .csect .text[PR] .align 2 .globl ffi_call_DARWIN .globl .ffi_call_DARWIN .csect ffi_call_DARWIN[DS] ffi_call_DARWIN: .long .ffi_call_DARWIN, TOC[tc0], 0 .csect .text[PR] .ffi_call_DARWIN: blr .long 0 .byte 0,0,0,0,0,0,0,0 //END(ffi_call_DARWIN) --- NEW FILE: ffi_darwin.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1998 Geoffrey Keating PowerPC Foreign Function Interface Darwin ABI support (c) 2001 John Hornkvist AIX ABI support (c) 2002 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. ----------------------------------------------------------------------- */ #include <ffi.h> #include <ffi_common.h> #include <stdlib.h> extern void ffi_closure_ASM(void); enum { /* The assembly depends on these exact flags. */ FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ FLAG_RETURNS_FP = 1 << (31-29), FLAG_RETURNS_64BITS = 1 << (31-28), 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) }; /* About the DARWIN ABI. */ enum { NUM_GPR_ARG_REGISTERS = 8, NUM_FPR_ARG_REGISTERS = 13 }; enum { ASM_NEEDS_REGISTERS = 4 }; /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments. The stack layout we want looks like this: | Return address from ffi_call_DARWIN | higher addresses |--------------------------------------------| | Previous backchain pointer 4 | stack pointer here |--------------------------------------------|<+ <<< on entry to | Saved r28-r31 4*4 | | ffi_call_DARWIN |--------------------------------------------| | | Parameters (at least 8*4=32) | | |--------------------------------------------| | | Space for GPR2 4 | | |--------------------------------------------| | stack | | Reserved 2*4 | | grows | |--------------------------------------------| | down V | Space for callee's LR 4 | | |--------------------------------------------| | lower addresses | Saved CR 4 | | |--------------------------------------------| | stack pointer here | Current backchain pointer 4 |-/ during |--------------------------------------------| <<< ffi_call_DARWIN */ /*@-exportheader@*/ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) /*@=exportheader@*/ { const unsigned bytes = ecif->cif->bytes; const unsigned flags = ecif->cif->flags; /* 'stacktop' points at the previous backchain pointer. */ unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned)); /* 'fpr_base' points at the space for fpr1, and grows upwards as we use FPR registers. */ double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS; int fparg_count = 0; /* 'next_arg' grows up as we put parameters in it. */ unsigned *next_arg = stack + 6; /* 6 reserved posistions. */ int i = ecif->cif->nargs; double double_tmp; void **p_argv = ecif->avalue; unsigned gprvalue; ffi_type** ptr = ecif->cif->arg_types; char *dest_cpy; unsigned size_al = 0; /* Check that everything starts aligned properly. */ FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0); FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0); FFI_ASSERT((bytes & 0xF) == 0); /* Deal with return values that are actually pass-by-reference. Rule: Return values are referenced by r3, so r4 is the first parameter. */ if (flags & FLAG_RETVAL_REFERENCE) *next_arg++ = (unsigned)(char *)ecif->rvalue; /* Now for the arguments. */ for (; i > 0; i--, ptr++, p_argv++) { switch ((*ptr)->type) { /* If a floating-point parameter appears before all of the general- purpose registers are filled, the corresponding GPRs that match the size of the floating-point parameter are skipped. */ case FFI_TYPE_FLOAT: double_tmp = *(float *)*p_argv; if (fparg_count >= NUM_FPR_ARG_REGISTERS) *(double *)next_arg = double_tmp; else *fpr_base++ = double_tmp; next_arg++; fparg_count++; FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); break; case FFI_TYPE_DOUBLE: double_tmp = *(double *)*p_argv; if (fparg_count >= NUM_FPR_ARG_REGISTERS) *(double *)next_arg = double_tmp; else *fpr_base++ = double_tmp; next_arg += 2; fparg_count++; FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); break; case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: *(long long *)next_arg = *(long long *)*p_argv; next_arg+=2; break; case FFI_TYPE_UINT8: gprvalue = *(unsigned char *)*p_argv; goto putgpr; case FFI_TYPE_SINT8: gprvalue = *(signed char *)*p_argv; goto putgpr; case FFI_TYPE_UINT16: gprvalue = *(unsigned short *)*p_argv; goto putgpr; case FFI_TYPE_SINT16: gprvalue = *(signed short *)*p_argv; goto putgpr; case FFI_TYPE_STRUCT: #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: #endif dest_cpy = (char *) next_arg; /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, SI 4 bytes) are aligned as if they were those modes. Structures with 3 byte in size are padded upwards. */ size_al = (*ptr)->size; /* If the first member of the struct is a double, then align the struct to double-word. Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ if ((*ptr)->elements[0]->type == 3) size_al = ALIGN((*ptr)->size, 8); if (size_al < 3 && ecif->cif->abi == FFI_DARWIN) dest_cpy += 4 - size_al; memcpy((char *)dest_cpy, (char *)*p_argv, size_al); next_arg += (size_al + 3) / 4; break; case FFI_TYPE_INT: case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: case FFI_TYPE_POINTER: gprvalue = *(unsigned *)*p_argv; putgpr: *next_arg++ = gprvalue; break; default: break; } } /* Check that we didn't overrun the stack... */ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); //FFI_ASSERT((unsigned *)fpr_base // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); } /* Perform machine dependent cif processing. */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { /* All this is for the DARWIN ABI. */ int i; ffi_type **ptr; unsigned bytes; int fparg_count = 0, intarg_count = 0; unsigned flags = 0; unsigned size_al = 0; /* All the machine-independent calculation of cif->bytes will be wrong. Redo the calculation for DARWIN. */ /* Space for the frame pointer, callee's LR, CR, etc, and for the asm's temp regs. */ bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); /* Return value handling. The rules are as follows: - 32-bit (or less) integer values are returned in gpr3; - Structures of size <= 4 bytes also returned in gpr3; - 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; - Long double FP (if not equivalent to double) values are returned in fpr1 and fpr2; - Larger structures values are allocated space and a pointer is passed as the first argument. */ switch (cif->rtype->type) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: #endif /* Fall through. */ case FFI_TYPE_DOUBLE: flags |= FLAG_RETURNS_64BITS; /* Fall through. */ case FFI_TYPE_FLOAT: flags |= FLAG_RETURNS_FP; break; case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: flags |= FLAG_RETURNS_64BITS; break; case FFI_TYPE_STRUCT: flags |= FLAG_RETVAL_REFERENCE; flags |= FLAG_RETURNS_NOTHING; intarg_count++; break; case FFI_TYPE_VOID: flags |= FLAG_RETURNS_NOTHING; break; default: /* Returns 32-bit integer, or similar. Nothing to do here. */ break; } /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest goes on the stack. Structures and long doubles (if not equivalent to double) are passed as a pointer to a copy of the structure. Stuff on the stack needs to keep proper alignment. */ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) { switch ((*ptr)->type) { case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: fparg_count++; /* If this FP arg is going on the stack, it must be 8-byte-aligned. */ if (fparg_count > NUM_FPR_ARG_REGISTERS && intarg_count%2 != 0) intarg_count++; break; case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: /* '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 be 8-byte-aligned. */ if (intarg_count == NUM_GPR_ARG_REGISTERS-1 || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)) intarg_count++; intarg_count += 2; break; case FFI_TYPE_STRUCT: #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: #endif size_al = (*ptr)->size; /* If the first member of the struct is a double, then align the struct to double-word. Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ if ((*ptr)->elements[0]->type == 3) size_al = ALIGN((*ptr)->size, 8); intarg_count += (size_al + 3) / 4; break; default: /* Everything else is passed as a 4-byte word in a GPR, either the object itself or a pointer to it. */ intarg_count++; break; } } if (fparg_count != 0) flags |= FLAG_FP_ARGUMENTS; /* Space for the FPR registers, if needed. */ if (fparg_count != 0) bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); /* Stack space. */ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) bytes += (intarg_count + 2 * fparg_count) * sizeof(long); else bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); /* The stack space allocated needs to be a multiple of 16 bytes. */ bytes = (bytes + 15) & ~0xF; cif->flags = flags; cif->bytes = bytes; return FFI_OK; } /*@-declundef@*/ /*@-exportheader@*/ extern void ffi_call_AIX(/*@out@*/ extended_cif *, unsigned, unsigned, /*@out@*/ unsigned *, void (*fn)(), void (*fn2)()); extern void ffi_call_DARWIN(/*@out@*/ extended_cif *, unsigned, unsigned, /*@out@*/ unsigned *, void (*fn)(), void (*fn2)()); /*@=declundef@*/ /*@=exportheader@*/ void ffi_call(/*@dependent@*/ ffi_cif *cif, void (*fn)(), /*@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) && (cif->rtype->type == FFI_TYPE_STRUCT)) { /*@-sysunrecog@*/ ecif.rvalue = alloca(cif->rtype->size); /*@=sysunrecog@*/ } else ecif.rvalue = rvalue; switch (cif->abi) { case FFI_AIX: /*@-usedef@*/ ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn, ffi_prep_args); /*@=usedef@*/ break; case FFI_DARWIN: /*@-usedef@*/ ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn, ffi_prep_args); /*@=usedef@*/ break; default: FFI_ASSERT(0); break; } } static void flush_icache(char *); static void flush_range(char *, int); /* The layout of a function descriptor. A C function pointer really points to one of these. */ typedef struct aix_fd_struct { void *code_pointer; void *toc; } aix_fd; /* here I'd like to add the stack frame layout we use in darwin_closure.S and aix_clsoure.S SP previous -> +---------------------------------------+ <--- child frame | back chain to caller 4 | +---------------------------------------+ 4 | saved CR 4 | +---------------------------------------+ 8 | saved LR 4 | +---------------------------------------+ 12 | reserved for compilers 4 | +---------------------------------------+ 16 | reserved for binders 4 | +---------------------------------------+ 20 | saved TOC pointer 4 | +---------------------------------------+ 24 | always reserved 8*4=32 (previous GPRs)| | according to the linkage convention | | from AIX | +---------------------------------------+ 56 | our FPR area 13*8=104 | | f1 | | . | | f13 | +---------------------------------------+ 160 | result area 8 | +---------------------------------------+ 168 | alignement to the next multiple of 16 | SP current --> +---------------------------------------+ 176 <- parent frame | back chain to caller 4 | +---------------------------------------+ 180 | saved CR 4 | +---------------------------------------+ 184 | saved LR 4 | +---------------------------------------+ 188 | reserved for compilers 4 | +---------------------------------------+ 192 | reserved for binders 4 | +---------------------------------------+ 196 | saved TOC pointer 4 | +---------------------------------------+ 200 | always reserved 8*4=32 we store our | | GPRs here | | r3 | | . | | r10 | +---------------------------------------+ 232 | overflow part | +---------------------------------------+ xxx | ???? | +---------------------------------------+ xxx */ ffi_status ffi_prep_closure (ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data) { unsigned int *tramp; struct ffi_aix_trampoline_struct *tramp_aix; aix_fd *fd; switch (cif->abi) { case FFI_DARWIN: FFI_ASSERT (cif->abi == FFI_DARWIN); tramp = (unsigned int *) &closure->tramp[0]; tramp[0] = 0x7c0802a6; /* mflr r0 */ tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */ tramp[4] = 0x7d6802a6; /* mflr r11 */ tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */ tramp[6] = 0x7c0803a6; /* mtlr r0 */ tramp[7] = 0x7d8903a6; /* mtctr r12 */ 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 */ 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); break; case FFI_AIX: tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp); fd = (aix_fd *)(void *)ffi_closure_ASM; FFI_ASSERT (cif->abi == FFI_AIX); tramp_aix->code_pointer = fd->code_pointer; tramp_aix->toc = fd->toc; tramp_aix->static_chain = closure; closure->cif = cif; closure->fun = fun; closure->user_data = user_data; default: FFI_ASSERT(0); break; } return FFI_OK; } static void flush_icache(char *addr) { #ifndef _AIX __asm__ volatile ( "dcbf 0,%0;" "sync;" "icbi 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory"); #endif } static void flush_range(char * addr1, int size) { #define MIN_LINE_SIZE 32 int i; for (i = 0; i < size; i += MIN_LINE_SIZE) flush_icache(addr1+i); flush_icache(addr1+size-1); } typedef union { float f; double d; } ffi_dblfl; int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*, ffi_dblfl*); /* Basically the trampoline invokes ffi_closure_ASM, and on entry, r11 holds the address of the closure. After storing the registers that could possibly contain parameters to be passed into the stack frame and setting up space for a return value, ffi_closure_ASM invokes the following helper function to do most of the work. */ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, unsigned long * pgr, ffi_dblfl * pfr) { /* rvalue is the pointer to space for return value in closure assembly pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ void ** avalue; ffi_type ** arg_types; long i, avn; long nf; /* number of floating registers already used. */ long ng; /* number of general registers already used. */ ffi_cif * cif; double temp; unsigned size_al; cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); nf = 0; ng = 0; /* Copy the caller's structure return value address so that the closure returns the data directly to the caller. */ if (cif->rtype->type == FFI_TYPE_STRUCT) { rvalue = (void *) *pgr; pgr++; ng++; } i = 0; avn = cif->nargs; arg_types = cif->arg_types; /* Grab the addresses of the arguments from the stack frame. */ while (i < avn) { switch (arg_types[i]->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: avalue[i] = (char *) pgr + 3; ng++; pgr++; break; case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: avalue[i] = (char *) pgr + 2; ng++; pgr++; break; case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_POINTER: avalue[i] = pgr; ng++; pgr++; break; case FFI_TYPE_STRUCT: /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, SI 4 bytes) are aligned as if they were those modes. */ size_al = arg_types[i]->size; /* If the first member of the struct is a double, then align the struct to double-word. Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ if (arg_types[i]->elements[0]->type == 3) size_al = ALIGN(arg_types[i]->size, 8); if (size_al < 3 && cif->abi == FFI_DARWIN) avalue[i] = (void*) pgr + 4 - size_al; else avalue[i] = (void*) pgr; ng += (size_al + 3) / 4; pgr += (size_al + 3) / 4; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: /* Long long ints are passed in two gpr's. */ avalue[i] = pgr; ng += 2; pgr += 2; break; case FFI_TYPE_FLOAT: /* A float value consumes a GPR. There are 13 64bit floating point registers. */ if (nf < NUM_FPR_ARG_REGISTERS) { temp = pfr->d; pfr->f = (float)temp; avalue[i] = pfr; pfr++; } else { avalue[i] = pgr; } nf++; ng++; pgr++; break; case FFI_TYPE_DOUBLE: /* A double value consumes two GPRs. There are 13 64bit floating point registers. */ if (nf < NUM_FPR_ARG_REGISTERS) { avalue[i] = pfr; pfr++; } else { avalue[i] = pgr; } nf++; ng += 2; pgr += 2; break; default: FFI_ASSERT(0); } i++; } (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_ASM to perform return type promotions. */ return cif->rtype->type; } --- NEW FILE: asm.h --- /* ----------------------------------------------------------------------- asm.h - Copyright (c) 1998 Geoffrey Keating PowerPC Assembly glue. $Id: asm.h,v 1.1 2004/06/18 20:07:12 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 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 ASM_GLOBAL_DIRECTIVE .globl #define C_SYMBOL_NAME(name) name /* Macro for a label. */ #ifdef __STDC__ #define C_LABEL(name) name##: #else #define C_LABEL(name) name/**/: #endif /* This seems to always be the case on PPC. */ #define ALIGNARG(log2) log2 /* For ELF we need the `.type' directive to make shared libs work right. */ #define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; #define ASM_SIZE_DIRECTIVE(name) .size name,.-name /* If compiled for profiling, call `_mcount' at the start of each function. */ #ifdef PROF /* The mcount code relies on a the return address being on the stack to locate our caller and so it can restore it; so store one just for its benefit. */ #ifdef PIC #define CALL_MCOUNT \ .pushsection; \ .section ".data"; \ .align ALIGNARG(2); \ 0:.long 0; \ .previous; \ mflr %r0; \ stw %r0,4(%r1); \ bl _GLOBAL_OFFSET_TABLE_@local-4; \ mflr %r11; \ lwz %r0,0b@got(%r11); \ bl JUMPTARGET(_mcount); #else /* PIC */ #define CALL_MCOUNT \ .section ".data"; \ .align ALIGNARG(2); \ 0:.long 0; \ .previous; \ mflr %r0; \ lis %r11,0b@ha; \ stw %r0,4(%r1); \ addi %r0,%r11,0b@l; \ bl JUMPTARGET(_mcount); #endif /* PIC */ #else /* PROF */ #define CALL_MCOUNT /* Do nothing. */ #endif /* PROF */ #define ENTRY(name) \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ .align ALIGNARG(2); \ C_LABEL(name) \ CALL_MCOUNT #define EALIGN_W_0 /* No words to insert. */ #define EALIGN_W_1 nop #define EALIGN_W_2 nop;nop #define EALIGN_W_3 nop;nop;nop #define EALIGN_W_4 EALIGN_W_3;nop #define EALIGN_W_5 EALIGN_W_4;nop #define EALIGN_W_6 EALIGN_W_5;nop #define EALIGN_W_7 EALIGN_W_6;nop /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes past a 2^align boundary. */ #ifdef PROF #define EALIGN(name, alignt, words) \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ .align ALIGNARG(2); \ C_LABEL(name) \ CALL_MCOUNT \ b 0f; \ .align ALIGNARG(alignt); \ EALIGN_W_##words; \ 0: #else /* PROF */ #define EALIGN(name, alignt, words) \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ .align ALIGNARG(alignt); \ EALIGN_W_##words; \ C_LABEL(name) #endif #define END(name) \ ASM_SIZE_DIRECTIVE(name) #ifdef PIC #define JUMPTARGET(name) name##@plt #else #define JUMPTARGET(name) name #endif /* Local labels stripped out by the linker. */ #define L(x) .L##x --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- 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__) #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 FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 #if defined(POWERPC64) || defined(POWERPC_AIX) #define FFI_TRAMPOLINE_SIZE 24 #else /* POWERPC || POWERPC_AIX */ #define FFI_TRAMPOLINE_SIZE 40 #endif #ifndef LIBFFI_ASM #if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) struct ffi_aix_trampoline_struct { void * code_pointer; /* Pointer to ffi_closure_ASM */ void * toc; /* TOC */ void * static_chain; /* Pointer to closure */ }; #endif #endif #endif --- NEW FILE: linux64.S --- /* ----------------------------------------------------------------------- sysv.h - Copyright (c) 2003 Jakub Jelinek <ja...@re...> 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 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> #ifdef __powerpc64__ .hidden ffi_call_LINUX64, .ffi_call_LINUX64 .globl ffi_call_LINUX64, .ffi_call_LINUX64 .section ".opd","aw" .align 3 ffi_call_LINUX64: .quad .ffi_call_LINUX64,.TOC.@tocbase,0 .size ffi_call_LINUX64,24 .type .ffi_call_LINUX64,@function .text .ffi_call_LINUX64: .LFB1: mflr %r0 std %r28, -32(%r1) std %r29, -24(%r1) std %r30, -16(%r1) std %r31, -8(%r1) std %r0, 16(%r1) mr %r28, %r1 /* our AP. */ stdux %r1, %r1, %r4 .LCFI0: mr %r31, %r5 /* flags, */ mr %r30, %r6 /* rvalue, */ mr %r29, %r7 /* function address. */ std %r2, 40(%r1) /* Call ffi_prep_args64. */ mr %r4, %r1 bl .ffi_prep_args64 ld %r0, 0(%r29) ld %r2, 8(%r29) ld %r11, 16(%r29) /* Now do the call. */ /* Set up cr1 with bits 4-7 of the flags. */ mtcrf 0x40, %r31 /* Get the address to call into CTR. */ mtctr %r0 /* Load all those argument registers. */ ld %r3, -32-(8*8)(%r28) ld %r4, -32-(7*8)(%r28) ld %r5, -32-(6*8)(%r28) ld %r6, -32-(5*8)(%r28) bf- 5, 1f ld %r7, -32-(4*8)(%r28) ld %r8, -32-(3*8)(%r28) ld %r9, -32-(2*8)(%r28) ld %r10, -32-(1*8)(%r28) 1: /* Load all the FP registers. */ bf- 6, 2f lfd %f1, -32-(21*8)(%r28) lfd %f2, -32-(20*8)(%r28) lfd %f3, -32-(19*8)(%r28) lfd %f4, -32-(18*8)(%r28) lfd %f5, -32-(17*8)(%r28) lfd %f6, -32-(16*8)(%r28) lfd %f7, -32-(15*8)(%r28) lfd %f8, -32-(14*8)(%r28) lfd %f9, -32-(13*8)(%r28) lfd %f10, -32-(12*8)(%r28) lfd %f11, -32-(11*8)(%r28) lfd %f12, -32-(10*8)(%r28) lfd %f13, -32-(9*8)(%r28) 2: /* Make the call. */ bctrl /* Now, deal with the return value. */ mtcrf 0x01, %r31 bt- 30, .Ldone_return_value bt- 29, .Lfp_return_value std %r3, 0(%r30) /* Fall through... */ .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) mtlr %r0 ld %r29, -24(%r1) ld %r30, -16(%r1) ld %r31, -8(%r1) blr .Lfp_return_value: bf 28, .Lfloat_return_value stfd %f1, 0(%r30) stfd %f2, 8(%r30) /* It might be a long double */ b .Ldone_return_value .Lfloat_return_value: stfs %f1, 0(%r30) b .Ldone_return_value .LFE1: .long 0 .byte 0,12,0,1,128,4,0,0 .size .ffi_call_LINUX64,.-.ffi_call_LINUX64 .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry .LSCIE1: .4byte 0x0 # CIE Identifier Tag .byte 0x1 # CIE Version .ascii "zR\0" # CIE Augmentation .uleb128 0x1 # CIE Code Alignment Factor .sleb128 -8 # CIE Data Alignment Factor .byte 0x41 # CIE RA Column .uleb128 0x1 # Augmentation size .byte 0x14 # FDE Encoding (pcrel udata8) .byte 0xc # DW_CFA_def_cfa .uleb128 0x1 .uleb128 0x0 .align 3 .LECIE1: .LSFDE1: .4byte .LEFDE1-.LASFDE1 # FDE Length .LASFDE1: .4byte .LASFDE1-.Lframe1 # FDE CIE offset .8byte .LFB1-. # FDE initial location .8byte .LFE1-.LFB1 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x2 # DW_CFA_advance_loc1 .byte .LCFI0-.LFB1 .byte 0xd # DW_CFA_def_cfa_register .uleb128 0x1c .byte 0x11 # DW_CFA_offset_extended_sf .uleb128 0x41 .sleb128 -2 .byte 0x9f # DW_CFA_offset, column 0x1f .uleb128 0x1 .byte 0x9e # DW_CFA_offset, column 0x1e .uleb128 0x2 .byte 0x9d # DW_CFA_offset, column 0x1d .uleb128 0x3 .byte 0x9c # DW_CFA_offset, column 0x1c .uleb128 0x4 .align 3 .LEFDE1: #endif --- NEW FILE: aix_closure.S --- /* ----------------------------------------------------------------------- aix_closure.S - Copyright (c) 2002 2003 Free Software Foundation, Inc. based on darwin_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. ----------------------------------------------------------------------- */ .set r0,0 .set r1,1 .set r2,2 .set r3,3 .set r4,4 .set r5,5 .set r6,6 .set r7,7 .set r8,8 .set r9,9 .set r10,10 .set r11,11 .set r12,12 .set r13,13 .set r14,14 .set r15,15 .set r16,16 .set r17,17 .set r18,18 .set r19,19 .set r20,20 .set r21,21 .set r22,22 .set r23,23 .set r24,24 .set r25,25 .set r26,26 .set r27,27 .set r28,28 .set r29,29 .set r30,30 .set r31,31 .set f0,0 .set f1,1 .set f2,2 .set f3,3 .set f4,4 .set f5,5 .set f6,6 .set f7,7 .set f8,8 .set f9,9 .set f10,10 .set f11,11 .set f12,12 .set f13,13 .set f14,14 .set f15,15 .set f16,16 .set f17,17 .set f18,18 .set f19,19 .set f20,20 .set f21,21 #define LIBFFI_ASM #define JUMPTARGET(name) name #define L(x) x .file "aix_closure.S" .toc LC..60: .tc L..60[TC],L..60 .csect .text[PR] .align 2 .csect .text[PR] .align 2 .globl ffi_closure_ASM .globl .ffi_closure_ASM .csect ffi_closure_ASM[DS] ffi_closure_ASM: .long .ffi_closure_ASM, TOC[tc0], 0 .csect .text[PR] .ffi_closure_ASM: mflr r0 /* extract return address */ stw r0, 8(r1) /* save the return address */ /* 24 Bytes (Linkage Area) */ /* 32 Bytes (params) */ /* 104 Bytes (13*8 from FPR) */ /* 8 Bytes (result) */ /* 168 Bytes */ stwu r1,-176(r1) /* skip over caller save area keep stack aligned to 16 */ /* we want to build up an area for the parameters passed */ /* in registers (both floating point and integer) */ /* we store gpr 3 to gpr 10 (aligned to 4) in the parents outgoing area */ stw r3, 200(r1) stw r4, 204(r1) stw r5, 208(r1) stw r6, 212(r1) stw r7, 216(r1) stw r8, 220(r1) stw r9, 224(r1) stw r10, 228(r1) /* next save fpr 1 to fpr 13 (aligned to 8) */ stfd f1, 56(r1) stfd f2, 64(r1) stfd f3, 72(r1) stfd f4, 80(r1) stfd f5, 88(r1) stfd f6, 96(r1) stfd f7, 104(r1) stfd f8, 112(r1) stfd f9, 120(r1) stfd f10, 128(r1) stfd f11, 136(r1) stfd f12, 144(r1) stfd f13, 152(r1) /* set up registers for the routine that actually does the work */ /* get the context pointer from the trampoline */ mr r3,r11 /* now load up the pointer to the result storage */ addi r4,r1,160 /* now load up the pointer to the saved gpr registers */ addi r5,r1,200 /* now load up the pointer to the saved fpr registers */ addi r6,r1,56 /* make the call */ bl .ffi_closure_helper_DARWIN nop /* 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 r5,r1,160 /* get pointer to results area */ lwz r4,LC..60(2) /* get address of jump table */ slwi r3,r3,2 /* now multiply return type by 4 */ lwzx r3,r4,r3 /* get the contents of that table value */ add r3,r3,r4 /* add contents of table to table address */ mtctr r3 bctr /* jump to it */ L..60: .long L..44-L..60 /* FFI_TYPE_VOID */ .long L..50-L..60 /* FFI_TYPE_INT */ .long L..47-L..60 /* FFI_TYPE_FLOAT */ .long L..46-L..60 /* FFI_TYPE_DOUBLE */ .long L..46-L..60 /* FFI_TYPE_LONGDOUBLE */ .long L..56-L..60 /* FFI_TYPE_UINT8 */ .long L..55-L..60 /* FFI_TYPE_SINT8 */ .long L..58-L..60 /* FFI_TYPE_UINT16 */ .long L..57-L..60 /* FFI_TYPE_SINT16 */ .long L..50-L..60 /* FFI_TYPE_UINT32 */ .long L..50-L..60 /* FFI_TYPE_SINT32 */ .long L..48-L..60 /* FFI_TYPE_UINT64 */ .long L..48-L..60 /* FFI_TYPE_SINT64 */ .long L..44-L..60 /* FFI_TYPE_STRUCT */ .long L..50-L..60 /* FFI_TYPE_POINTER */ /* case double */ L..46: lfd f1,0(r5) b L..44 /* case float */ L..47: lfs f1,0(r5) b L..44 /* case long long */ L..48: lwz r3,0(r5) lwz r4,4(r5) b L..44 /* case default / int32 / pointer */ L..50: lwz r3,0(r5) b L..44 /* case signed int8 */ L..55: addi r5,r5,3 lbz r3,0(r5) slwi r3,r3,24 srawi r3,r3,24 b L..44 /* case unsigned int8 */ L..56: addi r5,r5,3 lbz r3,0(r5) b L..44 /* case signed int16 */ L..57: addi r5,r5,2 lhz r3,0(r5) extsh r3,r3 b L..44 /* case unsigned int16 */ L..58: addi r5,r5,2 lhz r3,0(r5) /* case void / done */ L..44: addi r1,r1,176 /* restore stack pointer */ lwz r0,8(r1) /* get return address */ mtlr r0 /* reset link register */ blr /* END(ffi_closure_ASM) */ --- NEW FILE: darwin.S --- /* ----------------------------------------------------------------------- darwin.S - Copyright (c) 2000 John Hornkvist 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> #define JUMPTARGET(name) name #define L(x) x .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: /* Allocate the stack space we need. */ stwux r1,r1,r4 /* Save registers we use. */ mflr r9 stw r28,-16(r8) stw r29,-12(r8) stw r30, -8(r8) stw r31, -4(r8) stw r9, 8(r8) stw r2, 20(r1) LCFI1: /* 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 lwz r2,20(r1) /* Now do the call. Set up cr1 with bits 4-7 of the flags. */ mtcrf 0x40,r31 /* Get the address to call into CTR. */ mtctr r29 /* Load all those argument registers. We have set up a nice stack frame, just load it into registers. */ lwz r3, 20+(1*4)(r1) lwz r4, 20+(2*4)(r1) lwz r5, 20+(3*4)(r1) lwz r6, 20+(4*4)(r1) nop lwz r7, 20+(5*4)(r1) lwz r8, 20+(6*4)(r1) lwz r9, 20+(7*4)(r1) lwz r10,20+(8*4)(r1) L1: /* Load all the FP registers. */ bf 6,L2 // 2f + 0x18 lfd f1,-16-(13*8)(r28) lfd f2,-16-(12*8)(r28) lfd f3,-16-(11*8)(r28) lfd f4,-16-(10*8)(r28) nop lfd f5,-16-(9*8)(r28) lfd f6,-16-(8*8)(r28) lfd f7,-16-(7*8)(r28) lfd f8,-16-(6*8)(r28) nop lfd f9,-16-(5*8)(r28) lfd f10,-16-(4*8)(r28) lfd f11,-16-(3*8)(r28) lfd f12,-16-(2*8)(r28) nop lfd f13,-16-(1*8)(r28) L2: mr r12,r29 /* Put the target address in r12 as specified. */ mtctr r12 nop nop /* Make the call. */ bctrl /* Now, deal with the return value. */ mtcrf 0x01,r31 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) /* Fall through... */ L(done_return_value): /* Restore the registers we used and return. */ lwz r9, 8(r28) lwz r31, -4(r28) mtlr r9 lwz r30, -8(r28) lwz r29,-12(r28) lwz r28,-16(r28) lwz r1,0(r1) blr L(fp_return_value): bf 28,L(float_return_value) stfd f1,0(r30) b L(done_return_value) L(float_return_value): 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) */ .data .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 2 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 .long LLFB0$non_lazy_ptr-. ; FDE initial location .set L$set$3,LFE1-LFB0 .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 2 LEFDE1: .data .align 2 LLFB0$non_lazy_ptr: .long LFB0 --- NEW FILE: linux64_closure.S --- #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .file "linux64_closure.S" #ifdef __powerpc64__ .hidden ffi_closure_LINUX64, .ffi_closure_LINUX64 .globl ffi_closure_LINUX64, .ffi_closure_LINUX64 .section ".opd","aw" .align 3 ffi_closure_LINUX64: .quad .ffi_closure_LINUX64,.TOC.@tocbase,0 .size ffi_closure_LINUX64,24 .type .ffi_closure_LINUX64,@function .text .ffi_closure_LINUX64: .LFB1: # save general regs into parm save area std %r3, 48(%r1) std %r4, 56(%r1) std %r5, 64(%r1) std %r6, 72(%r1) mflr %r0 std %r7, 80(%r1) std %r8, 88(%r1) std %r9, 96(%r1) std %r10, 104(%r1) std %r0, 16(%r1) # mandatory 48 bytes special reg save area + 64 bytes parm save area # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16 stdu %r1, -240(%r1) .LCFI0: # next save fpr 1 to fpr 13 stfd %f1, 128+(0*8)(%r1) stfd %f2, 128+(1*8)(%r1) stfd %f3, 128+(2*8)(%r1) stfd %f4, 128+(3*8)(%r1) stfd %f5, 128+(4*8)(%r1) stfd %f6, 128+(5*8)(%r1) stfd %f7, 128+(6*8)(%r1) stfd %f8, 128+(7*8)(%r1) stfd %f9, 128+(8*8)(%r1) stfd %f10, 128+(9*8)(%r1) stfd %f11, 128+(10*8)(%r1) stfd %f12, 128+(11*8)(%r1) stfd %f13, 128+(12*8)(%r1) # set up registers for the routine that actually does the work # get the context pointer from the trampoline mr %r3, %r11 # now load up the pointer to the result storage addi %r4, %r1, 112 # now load up the pointer to the parameter save area # in the previous frame addi %r5, %r1, 240 + 48 # now load up the pointer to the saved fpr registers */ addi %r6, %r1, 128 # make the call bl .ffi_closure_helper_LINUX64 .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 mflr %r4 # move address of .Lret to r4 sldi %r3, %r3, 4 # now multiply return type by 16 addi %r4, %r4, .Lret_type0 - .Lret ld %r0, 240+16(%r1) add %r3, %r3, %r4 # add contents of table to table address mtctr %r3 bctr # jump to it # 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 .Lret_type0: # case FFI_TYPE_VOID mtlr %r0 addi %r1, %r1, 240 blr nop # case FFI_TYPE_INT lwa %r3, 112+4(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_FLOAT lfs %f1, 112+0(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_DOUBLE lfd %f1, 112+0(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_LONGDOUBLE lfd %f1, 112+0(%r1) mtlr %r0 lfd %f2, 112+8(%r1) b .Lfinish # case FFI_TYPE_UINT8 lbz %r3, 112+7(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_SINT8 lbz %r3, 112+7(%r1) extsb %r3,%r3 mtlr %r0 b .Lfinish # case FFI_TYPE_UINT16 lhz %r3, 112+6(%r1) mtlr %r0 .Lfinish: addi %r1, %r1, 240 blr # case FFI_TYPE_SINT16 lha %r3, 112+6(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_UINT32 lwz %r3, 112+4(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_SINT32 lwa %r3, 112+4(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_UINT64 ld %r3, 112+0(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_SINT64 ld %r3, 112+0(%r1) mtlr %r0 addi %r1, %r1, 240 blr # case FFI_TYPE_STRUCT mtlr %r0 addi %r1, %r1, 240 blr nop # case FFI_TYPE_POINTER ld %r3, 112+0(%r1) mtlr %r0 addi %r1, %r1, 240 blr # esac .LFE1: .long 0 .byte 0,12,0,1,128,0,0,0 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64 .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry .LSCIE1: .4byte 0x0 # CIE Identifier Tag .byte 0x1 # CIE Version .ascii "zR\0" # CIE Augmentation .uleb128 0x1 # CIE Code Alignment Factor .sleb128 -8 # CIE Data Alignment Factor .byte 0x41 # CIE RA Column .uleb128 0x1 # Augmentation size .byte 0x14 # FDE Encoding (pcrel udata8) .byte 0xc # DW_CFA_def_cfa .uleb128 0x1 .uleb128 0x0 .align 3 .LECIE1: .LSFDE1: .4byte .LEFDE1-.LASFDE1 # FDE Length .LASFDE1: .4byte .LASFDE1-.Lframe1 # FDE CIE offset .8byte .LFB1-. # FDE initial location .8byte .LFE1-.LFB1 # FDE address range .uleb128 0x0 # Augmentation size .byte 0x2 # DW_CFA_advance_loc1 .byte .LCFI0-.LFB1 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 240 .byte 0x11 # DW_CFA_offset_extended_sf .uleb128 0x41 .sleb128 -2 .align 3 .LEFDE1: #endif --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1998 Geoffrey Keating PowerPC Foreign Function Interface $Id: ffi.c,v 1.1 2004/06/18 20:07:12 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 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 [...1094 lines suppressed...] } avalue[i] = pst; } pst += 2; break; #endif default: FFI_ASSERT(0); } i++; } (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_LINUX64 how to perform return type promotions. */ return cif->rtype->type; } --- NEW FILE: ppc_closure.S --- #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> #include <powerpc/asm.h> .file "ppc_closure.S" #ifndef __powerpc64__ ENTRY(ffi_closure_SYSV) .LFB1: stwu %r1,-144(%r1) .LCFI0: mflr %r0 .LCFI1: stw %r0,148(%r1) # we want to build up an areas for the parameters passed # in registers (both floating point and integer) # so first save gpr 3 to gpr 10 (aligned to 4) stw %r3, 16(%r1) stw %r4, 20(%r1) stw %r5, 24(%r1) stw %r6, 28(%r1) stw %r7, 32(%r1) stw %r8, 36(%r1) stw %r9, 40(%r1) stw %r10,44(%r1) # next save fpr 1 to fpr 8 (aligned to 8) stfd %f1, 48(%r1) stfd %f2, 56(%r1) stfd %f3, 64(%r1) stfd %f4, 72(%r1) stfd %f5, 80(%r1) stfd %f6, 88(%r1) stfd %f7, 96(%r1) stfd %f8, 104(%r1) # set up registers for the routine that actually does the work # get the context pointer from the trampoline mr %r3,%r11 # now load up the pointer to the result storage addi %r4,%r1,112 # now load up the pointer to the saved gpr registers addi %r5,%r1,16 # now load up the pointer to the saved fpr registers */ addi %r6,%r1,48 # now load up the pointer to the outgoing parameter # stack in the previous frame # i.e. the previous frame pointer + 8 addi %r7,%r1,152 # make the call bl JUMPTARGET(ffi_closure_helper_SYSV) # 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 %r5,%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 mtctr %r3 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 nop # case FFI_TYPE_INT .Lret_type1: lwz %r3,0(%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) b .Lfinish nop nop # case FFI_TYPE_UINT8 .Lret_type5: lbz %r3,3(%r5) b .Lfinish nop nop # case FFI_TYPE_SINT8 .Lret_type6: lbz %r3,3(%r5) extsb %r3,%r3 b .Lfinish nop # case FFI_TYPE_UINT16 .Lret_type7: lhz %r3,2(%r5) b .Lfinish nop nop # case FFI_TYPE_SINT16 .Lret_type8: lha %r3,2(%r5) b .Lfinish nop nop # case FFI_TYPE_UINT32 .Lret_type9: lwz %r3,0(%r5) b .Lfinish nop nop # case FFI_TYPE_SINT32 .Lret_type10: lwz %r3,0(%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: lwz %r3,0(%r5) lwz %r4,4(%r5) b .Lfinish nop # case FFI_TYPE_STRUCT .Lret_type13: b .Lfinish nop nop nop # case FFI_TYPE_POINTER .Lret_type14: lwz %r3,0(%r5) b .Lfinish nop nop # case done .Lfinish: lwz %r0,148(%r1) mtlr %r0 addi %r1,%r1,144 blr END(ffi_closure_SYSV) .section ".eh_frame",EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry .LSCIE1: .4byte 0x0 # CIE Identifier Tag .byte 0x1 # CIE Version #if defined _RELOCATABLE || defined __PIC__ .ascii "zR\0" # CIE Augmentation #else .ascii "\0" # CIE Augmentation #endif .uleb128 0x1 # CIE Code Alignment Factor .sleb128 -4 # CIE Data Alignment Factor .byte 0x41 # CIE RA Column #if defined _RELOCATABLE || defined __PIC__ .uleb128 0x1 # Augmentation size .byte 0x1b # FDE Encoding (pcrel sdata4) #endif .byte 0xc # DW_CFA_def_cfa .uleb128 0x1 .uleb128 0x0 .align 2 .LECIE1: .LSFDE1: .4byte .LEFDE1-.LASFDE1 # FDE Length .LASFDE1: .4byte .LASFDE1-.Lframe1 # FDE CIE offset #if defined _RELOCATABLE || defined __PIC__ .4byte .LFB1-. # FDE initial location #else .4byte .LFB1 # FDE initial location #endif .4byte .LFE1-.LFB1 # FDE address range #if defined _RELOCATABLE || defined __PIC__ .uleb128 0x0 # Augmentation size #endif .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI0-.LFB1 .byte 0xe # DW_CFA_def_cfa_offset .uleb128 144 .byte 0x4 # DW_CFA_advance_loc4 .4byte .LCFI1-.LCFI0 .byte 0x2f # DW_CFA_GNU_negative_offset_extended .uleb128 0x41 .uleb128 0x1 .align 2 .LEFDE1: #endif --- NEW FILE: darwin_closure.S --- /* ----------------------------------------------------------------------- darwin_closure.S - Copyright (c) 2002 2003 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 PURPO... [truncated message content] |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:22
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/m68k In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/m68k Added Files: ffi.c ffitarget.h sysv.S Log Message: Importing libffi sources and build tools. --- NEW FILE: sysv.S --- /* ----------------------------------------------------------------------- sysv.S m68k Foreign Function Interface ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .text .globl ffi_call_SYSV .type ffi_call_SYSV,@function ffi_call_SYSV: link %fp,#0 move.l %d2,-(%sp) | Make room for all of the new args. sub.l 16(%fp),%sp | Call ffi_prep_args move.l 12(%fp),-(%sp) pea 4(%sp) move.l 8(%fp),%a0 jsr (%a0) addq.l #8,%sp | Pass pointer to struct value, if any move.l %a0,%a1 | Call the function move.l 32(%fp),%a0 jsr (%a0) | Remove the space we pushed for the args add.l 16(%fp),%sp | Load the pointer to storage for the return value move.l 28(%fp),%a1 | Load the return type code move.l 20(%fp),%d2 | If the return value pointer is NULL, assume no return value. tst.l %a1 jbeq noretval btst #0,%d2 jbeq retlongint move.l %d0,(%a1) jbra epilogue retlongint: btst #1,%d2 jbeq retfloat move.l %d0,(%a1) move.l %d1,4(%a1) jbra epilogue retfloat: btst #2,%d2 jbeq retdouble fmove.s %fp0,(%a1) jbra epilogue retdouble: btst #3,%d2 jbeq retlongdouble fmove.d %fp0,(%a1) jbra epilogue retlongdouble: btst #4,%d2 jbeq retpointer fmove.x %fp0,(%a1) jbra epilogue retpointer: btst #5,%d2 jbeq retstruct move.l %a0,(%a1) jbra epilogue retstruct: btst #6,%d2 jbeq noretval move.l 24(%fp),%d2 bfins %d0,(%a1){#0,%d2} noretval: epilogue: move.l (%sp)+,%d2 unlk %a6 rts .size ffi_call_SYSV,.-ffi_call_SYSV --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c m68k Foreign Function Interface ----------------------------------------------------------------------- */ #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. */ static void * ffi_prep_args (void *stack, extended_cif *ecif) { unsigned int i; void **p_argv; char *argp; ffi_type **p_arg; void *struct_value_ptr; argp = stack; if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8) struct_value_ptr = ecif->rvalue; else struct_value_ptr = NULL; 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 (((*p_arg)->alignment - 1) & (unsigned) argp) argp = (char *) ALIGN (argp, (*p_arg)->alignment); z = (*p_arg)->size; if (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_STRUCT: memcpy (argp + sizeof (int) - z, *p_argv, z); break; default: FFI_ASSERT (0); } z = sizeof (int); } else memcpy (argp, *p_argv, z); p_argv++; argp += z; } return struct_value_ptr; } #define CIF_FLAGS_INT 1 #define CIF_FLAGS_DINT 2 #define CIF_FLAGS_FLOAT 4 #define CIF_FLAGS_DOUBLE 8 #define CIF_FLAGS_LDOUBLE 16 #define CIF_FLAGS_POINTER 32 #define CIF_FLAGS_STRUCT 64 /* 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: cif->flags = 0; 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; break; case FFI_TYPE_FLOAT: cif->flags = CIF_FLAGS_FLOAT; break; case FFI_TYPE_DOUBLE: cif->flags = CIF_FLAGS_DOUBLE; break; case FFI_TYPE_LONGDOUBLE: cif->flags = CIF_FLAGS_LDOUBLE; break; case FFI_TYPE_POINTER: cif->flags = CIF_FLAGS_POINTER; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: cif->flags = CIF_FLAGS_DINT; break; default: cif->flags = CIF_FLAGS_INT; break; } 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) { 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 && cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size > 8) ecif.rvalue = alloca (cif->rtype->size); else ecif.rvalue = rvalue; switch (cif->abi) { case FFI_SYSV: ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, cif->flags, cif->rtype->size * 8, ecif.rvalue, fn); break; default: FFI_ASSERT (0); break; } } --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for Motorola 68K. 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 #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 0 #define FFI_NATIVE_RAW_API 0 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:21
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/alpha In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/src/alpha Added Files: ffi.c ffitarget.h osf.S Log Message: Importing libffi sources and build tools. --- NEW FILE: osf.S --- /* ----------------------------------------------------------------------- osf.S - Copyright (c) 1998, 2001 Red Hat Alpha/OSF Foreign Function Interface $Id: osf.S,v 1.1 2004/06/18 20:07:09 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 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. ----------------------------------------------------------------------- */ #define LIBFFI_ASM #include <fficonfig.h> #include <ffi.h> .arch ev6 .text /* ffi_call_osf (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_osf .ent ffi_call_osf ffi_call_osf: .frame $15, 32, $26, 0 .mask 0x4008000, -32 $LFB1: addq $16,$17,$1 mov $16, $30 stq $26, 0($1) $LCFI0: stq $15, 8($1) $LCFI1: stq $18, 16($1) mov $1, $15 $LCFI2: .prologue 0 stq $19, 24($1) mov $20, $27 # Load up all of the (potential) argument registers. ldq $16, 0($30) ldt $f16, 0($30) ldt $f17, 8($30) ldq $17, 8($30) ldt $f18, 16($30) ldq $18, 16($30) ldt $f19, 24($30) ldq $19, 24($30) ldt $f20, 32($30) ldq $20, 32($30) ldt $f21, 40($30) ldq $21, 40($30) # Deallocate the register argument area. lda $30, 48($30) jsr $26, ($27), 0 ldgp $29, 0($26) # If the return value pointer is NULL, assume no return value. ldq $19, 24($15) ldq $18, 16($15) ldq $26, 0($15) beq $19, $noretval # Store the return value out in the proper type. cmpeq $18, FFI_TYPE_INT, $1 bne $1, $retint cmpeq $18, FFI_TYPE_FLOAT, $2 bne $2, $retfloat cmpeq $18, FFI_TYPE_DOUBLE, $3 bne $3, $retdouble $noretval: ldq $15, 8($15) ret $retint: stq $0, 0($19) nop ldq $15, 8($15) ret $retfloat: sts $f0, 0($19) nop ldq $15, 8($15) ret $retdouble: stt $f0, 0($19) nop ldq $15, 8($15) ret $LFE1: .end ffi_call_osf /* ffi_closure_osf(...) Receives the closure argument in $1. */ .align 3 .globl ffi_closure_osf .ent ffi_closure_osf ffi_closure_osf: .frame $30, 16*8, $26, 0 .mask 0x4000000, -16*8 $LFB2: ldgp $29, 0($27) subq $30, 16*8, $30 $LCFI5: stq $26, 0($30) $LCFI6: .prologue 1 # Store all of the potential argument registers in va_list format. stt $f16, 4*8($30) stt $f17, 5*8($30) stt $f18, 6*8($30) stt $f19, 7*8($30) stt $f20, 8*8($30) stt $f21, 9*8($30) stq $16, 10*8($30) stq $17, 11*8($30) stq $18, 12*8($30) stq $19, 13*8($30) stq $20, 14*8($30) stq $21, 15*8($30) # Call ffi_closure_osf_inner to do the bulk of the work. mov $1, $16 lda $17, 2*8($30) lda $18, 10*8($30) jsr $26, ffi_closure_osf_inner ldgp $29, 0($26) ldq $26, 0($30) # Load up the return value in the proper type. lda $1, $load_table s4addq $0, $1, $1 ldl $1, 0($1) addq $1, $29, $1 jmp $31, ($1), $load_32 .align 4 $load_none: addq $30, 16*8, $30 ret .align 4 $load_float: lds $f0, 16($30) nop addq $30, 16*8, $30 ret .align 4 $load_double: ldt $f0, 16($30) nop addq $30, 16*8, $30 ret .align 4 $load_u8: #ifdef __alpha_bwx__ ldbu $0, 16($30) nop #else ldq $0, 16($30) and $0, 255, $0 #endif addq $30, 16*8, $30 ret .align 4 $load_s8: #ifdef __alpha_bwx__ ldbu $0, 16($30) sextb $0, $0 #else ldq $0, 16($30) sll $0, 56, $0 sra $0, 56, $0 #endif addq $30, 16*8, $30 ret .align 4 $load_u16: #ifdef __alpha_bwx__ ldwu $0, 16($30) nop #else ldq $0, 16($30) zapnot $0, 3, $0 #endif addq $30, 16*8, $30 ret .align 4 $load_s16: #ifdef __alpha_bwx__ ldwu $0, 16($30) sextw $0, $0 #else ldq $0, 16($30) sll $0, 48, $0 sra $0, 48, $0 #endif addq $30, 16*8, $30 ret .align 4 $load_32: ldl $0, 16($30) nop addq $30, 16*8, $30 ret .align 4 $load_64: ldq $0, 16($30) nop addq $30, 16*8, $30 ret $LFE2: .end ffi_closure_osf #ifdef __ELF__ .section .rodata #else .rdata #endif $load_table: .gprel32 $load_none # FFI_TYPE_VOID .gprel32 $load_32 # FFI_TYPE_INT .gprel32 $load_float # FFI_TYPE_FLOAT .gprel32 $load_double # FFI_TYPE_DOUBLE .gprel32 $load_double # FFI_TYPE_LONGDOUBLE .gprel32 $load_u8 # FFI_TYPE_UINT8 .gprel32 $load_s8 # FFI_TYPE_SINT8 .gprel32 $load_u16 # FFI_TYPE_UINT16 .gprel32 $load_s16 # FFI_TYPE_SINT16 .gprel32 $load_32 # FFI_TYPE_UINT32 .gprel32 $load_32 # FFI_TYPE_SINT32 .gprel32 $load_64 # FFI_TYPE_UINT64 .gprel32 $load_64 # FFI_TYPE_SINT64 .gprel32 $load_none # FFI_TYPE_STRUCT .gprel32 $load_64 # FFI_TYPE_POINTER /* Assert that the table above is in sync with ffi.h. */ #if FFI_TYPE_FLOAT != 2 \ || FFI_TYPE_DOUBLE != 3 \ || FFI_TYPE_UINT8 != 5 \ || FFI_TYPE_SINT8 != 6 \ || FFI_TYPE_UINT16 != 7 \ || FFI_TYPE_SINT16 != 8 \ || FFI_TYPE_UINT32 != 9 \ || FFI_TYPE_SINT32 != 10 \ || FFI_TYPE_UINT64 != 11 \ || FFI_TYPE_SINT64 != 12 \ || FFI_TYPE_STRUCT != 13 \ || FFI_TYPE_POINTER != 14 \ || FFI_TYPE_LAST != 14 #error "osf.S out of sync with ffi.h" #endif #ifdef __ELF__ .section .eh_frame,EH_FRAME_FLAGS,@progbits __FRAME_BEGIN__: .4byte $LECIE1-$LSCIE1 # Length of Common Information Entry $LSCIE1: .4byte 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 0x1a # CIE RA Column .byte 0x1 # uleb128 0x1; Augmentation size .byte 0x1b # FDE Encoding (pcrel sdata4) .byte 0xc # DW_CFA_def_cfa .byte 0x1e # uleb128 0x1e .byte 0x0 # uleb128 0x0 .align 3 $LECIE1: $LSFDE1: .4byte $LEFDE1-$LASFDE1 # FDE Length $LASFDE1: .4byte $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset .4byte $LFB1-. # FDE initial location .4byte $LFE1-$LFB1 # FDE address range .byte 0x0 # uleb128 0x0; Augmentation size .byte 0x4 # DW_CFA_advance_loc4 .4byte $LCFI0-$LFB1 .byte 0xe # DW_CFA_def_cfa_offset .byte 0x30 # uleb128 0x30 .byte 0x4 # DW_CFA_advance_loc4 .4byte $LCFI1-$LCFI0 .byte 0x9a # DW_CFA_offset, column 0x1a .byte 0x6 # uleb128 0x6 .byte 0x8f # DW_CFA_offset, column 0xf .byte 0x5 # uleb128 0x5 .byte 0x4 # DW_CFA_advance_loc4 .4byte $LCFI2-$LCFI1 .byte 0xc # DW_CFA_def_cfa .byte 0xf # uleb128 0xf .byte 0x30 # uleb128 0x30 .align 3 $LEFDE1: $LSFDE3: .4byte $LEFDE3-$LASFDE3 # FDE Length $LASFDE3: .4byte $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset .4byte $LFB2-. # FDE initial location .4byte $LFE2-$LFB2 # FDE address range .byte 0x0 # uleb128 0x0; Augmentation size .byte 0x4 # DW_CFA_advance_loc4 .4byte $LCFI5-$LFB2 .byte 0xe # DW_CFA_def_cfa_offset .byte 0x90,0x1 # uleb128 0x90 .byte 0x4 # DW_CFA_advance_loc4 .4byte $LCFI6-$LCFI5 .byte 0x9a # DW_CFA_offset, column 0x1a .byte 0x12 # uleb128 0x12 .align 3 $LEFDE3: #endif --- NEW FILE: ffi.c --- /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 1998, 2001 Red Hat, Inc. Alpha 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> extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)()); extern void ffi_closure_osf(void); ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { /* Adjust cif->bytes to represent a minimum 6 words for the temporary register argument loading area. */ if (cif->bytes < 6*FFI_SIZEOF_ARG) cif->bytes = 6*FFI_SIZEOF_ARG; /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_STRUCT: case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: cif->flags = cif->rtype->type; break; default: cif->flags = FFI_TYPE_INT; break; } return FFI_OK; } void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) { unsigned long *stack, *argp; long i, avn; ffi_type **arg_types; FFI_ASSERT (cif->abi == FFI_OSF); /* 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->flags == FFI_TYPE_STRUCT) rvalue = alloca(cif->rtype->size); /* Allocate the space for the arguments, plus 4 words of temp space for ffi_call_osf. */ argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG); if (cif->flags == FFI_TYPE_STRUCT) *(void **) argp++ = rvalue; i = 0; avn = cif->nargs; arg_types = cif->arg_types; while (i < avn) { switch ((*arg_types)->type) { case FFI_TYPE_SINT8: *(SINT64 *) argp = *(SINT8 *)(* avalue); break; case FFI_TYPE_UINT8: *(SINT64 *) argp = *(UINT8 *)(* avalue); break; case FFI_TYPE_SINT16: *(SINT64 *) argp = *(SINT16 *)(* avalue); break; case FFI_TYPE_UINT16: *(SINT64 *) argp = *(UINT16 *)(* avalue); break; case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: /* Note that unsigned 32-bit quantities are sign extended. */ *(SINT64 *) argp = *(SINT32 *)(* avalue); break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: *(UINT64 *) argp = *(UINT64 *)(* avalue); break; case FFI_TYPE_FLOAT: if (argp - stack < 6) { /* Note the conversion -- all the fp regs are loaded as doubles. The in-register format is the same. */ *(double *) argp = *(float *)(* avalue); } else *(float *) argp = *(float *)(* avalue); break; case FFI_TYPE_DOUBLE: *(double *) argp = *(double *)(* avalue); break; case FFI_TYPE_STRUCT: memcpy(argp, *avalue, (*arg_types)->size); break; default: FFI_ASSERT(0); } argp += ALIGN((*arg_types)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; i++, arg_types++, avalue++; } ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn); } ffi_status ffi_prep_closure (ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data) { unsigned int *tramp; FFI_ASSERT (cif->abi == FFI_OSF); tramp = (unsigned int *) &closure->tramp[0]; tramp[0] = 0x47fb0401; /* mov $27,$1 */ tramp[1] = 0xa77b0010; /* ldq $27,16($27) */ tramp[2] = 0x6bfb0000; /* jmp $31,($27),0 */ tramp[3] = 0x47ff041f; /* nop */ *(void **) &tramp[4] = ffi_closure_osf; closure->cif = cif; closure->fun = fun; closure->user_data = user_data; /* Flush the Icache. Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal instead, since both Compaq as and gas can handle it. 0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>. */ asm volatile ("call_pal 0x86" : : : "memory"); return FFI_OK; } int ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) { ffi_cif *cif; void **avalue; ffi_type **arg_types; long i, avn, argn; cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); argn = 0; /* Copy the caller's structure return address to that the closure returns the data directly to the caller. */ if (cif->flags == FFI_TYPE_STRUCT) { rvalue = (void *) argp[0]; argn = 1; } i = 0; avn = cif->nargs; arg_types = cif->arg_types; /* Grab the addresses of the arguments from the stack frame. */ while (i < avn) { switch (arg_types[i]->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: case FFI_TYPE_UINT16: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: case FFI_TYPE_STRUCT: avalue[i] = &argp[argn]; break; case FFI_TYPE_FLOAT: if (argn < 6) { /* Floats coming from registers need conversion from double back to float format. */ *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6]; avalue[i] = &argp[argn - 6]; } else avalue[i] = &argp[argn]; break; case FFI_TYPE_DOUBLE: avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)]; break; default: FFI_ASSERT(0); } argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; i++; } /* Invoke the closure. */ (closure->fun) (cif, rvalue, avalue, closure->user_data); /* Tell ffi_closure_osf how to perform return type promotions. */ return cif->rtype->type; } --- NEW FILE: ffitarget.h --- /* -----------------------------------------------------------------*-C-*- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for Alpha. 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 #ifndef LIBFFI_ASM typedef unsigned long ffi_arg; 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_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 #define FFI_TRAMPOLINE_SIZE 24 #define FFI_NATIVE_RAW_API 0 #endif |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:21
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi/include Added Files: Makefile.am Makefile.in ffi.h.in ffi_common.h Log Message: Importing libffi sources and build tools. --- NEW FILE: Makefile.in --- # Makefile.in generated by automake 1.8.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004 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@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ 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 $(toollibffi_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../config/accross.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__installdirs = "$(DESTDIR)$(hackdir)" "$(DESTDIR)$(toollibffidir)" hackDATA_INSTALL = $(INSTALL_DATA) DATA = $(hack_DATA) toollibffiHEADERS_INSTALL = $(INSTALL_HEADER) HEADERS = $(toollibffi_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ ALPHA_FALSE = @ALPHA_FALSE@ ALPHA_TRUE = @ALPHA_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@ ARM_FALSE = @ARM_FALSE@ ARM_TRUE = @ARM_TRUE@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@ IA64_FALSE = @IA64_FALSE@ IA64_TRUE = @IA64_TRUE@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ M68K_FALSE = @M68K_FALSE@ M68K_TRUE = @M68K_TRUE@ MAINT = @MAINT@ MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MIPS_IRIX_FALSE = @MIPS_IRIX_FALSE@ MIPS_IRIX_TRUE = @MIPS_IRIX_TRUE@ MIPS_LINUX_FALSE = @MIPS_LINUX_FALSE@ MIPS_LINUX_TRUE = @MIPS_LINUX_TRUE@ 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@ PA_FALSE = @PA_FALSE@ PA_TRUE = @PA_TRUE@ POWERPC_AIX_FALSE = @POWERPC_AIX_FALSE@ POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@ POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@ POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@ POWERPC_FALSE = @POWERPC_FALSE@ POWERPC_TRUE = @POWERPC_TRUE@ RANLIB = @RANLIB@ S390_FALSE = @S390_FALSE@ S390_TRUE = @S390_TRUE@ SET_MAKE = @SET_MAKE@ SH64_FALSE = @SH64_FALSE@ SH64_TRUE = @SH64_TRUE@ SHELL = @SHELL@ SH_FALSE = @SH_FALSE@ SH_TRUE = @SH_TRUE@ SPARC_FALSE = @SPARC_FALSE@ SPARC_TRUE = @SPARC_TRUE@ STRIP = @STRIP@ TARGET = @TARGET@ TARGETDIR = @TARGETDIR@ TESTSUBDIR_FALSE = @TESTSUBDIR_FALSE@ TESTSUBDIR_TRUE = @TESTSUBDIR_TRUE@ VERSION = @VERSION@ X86_64_FALSE = @X86_64_FALSE@ X86_64_TRUE = @X86_64_TRUE@ X86_FALSE = @X86_FALSE@ X86_TRUE = @X86_TRUE@ X86_WIN32_FALSE = @X86_WIN32_FALSE@ X86_WIN32_TRUE = @X86_WIN32_TRUE@ ac_ct_CC = @ac_ct_CC@ ac_ct_RANLIB = @ac_ct_RANLIB@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ gcc_version = @gcc_version@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ multi_basedir = @multi_basedir@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ tool_include_dir = @tool_include_dir@ toolexecdir = @toolexecdir@ toolexeclibdir = @toolexeclibdir@ AUTOMAKE_OPTIONS = foreign DISTCLEANFILES = ffitarget.h EXTRA_DIST = ffi.h.in ffi_common.h hackdir = $(includedir) hack_DATA = ffi.h toollibffidir = @tool_include_dir@/libffi toollibffi_HEADERS = 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 distclean-libtool: -rm -f libtool uninstall-info-am: install-hackDATA: $(hack_DATA) @$(NORMAL_INSTALL) test -z "$(hackdir)" || $(mkdir_p) "$(DESTDIR)$(hackdir)" @list='$(hack_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(hackDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(hackdir)/$$f'"; \ $(hackDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(hackdir)/$$f"; \ done uninstall-hackDATA: @$(NORMAL_UNINSTALL) @list='$(hack_DATA)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f '$(DESTDIR)$(hackdir)/$$f'"; \ rm -f "$(DESTDIR)$(hackdir)/$$f"; \ done install-toollibffiHEADERS: $(toollibffi_HEADERS) @$(NORMAL_INSTALL) test -z "$(toollibffidir)" || $(mkdir_p) "$(DESTDIR)$(toollibffidir)" @list='$(toollibffi_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " $(toollibffiHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(toollibffidir)/$$f'"; \ $(toollibffiHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(toollibffidir)/$$f"; \ done uninstall-toollibffiHEADERS: @$(NORMAL_UNINSTALL) @list='$(toollibffi_HEADERS)'; for p in $$list; do \ f="`echo $$p | sed -e 's|^.*/||'`"; \ echo " rm -f '$(DESTDIR)$(toollibffidir)/$$f'"; \ rm -f "$(DESTDIR)$(toollibffidir)/$$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)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ 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 $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(hackdir)" "$(DESTDIR)$(toollibffidir)"; 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: -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-libtool \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-hackDATA install-toollibffiHEADERS install-exec-am: install-info: install-info-am install-man: 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-hackDATA uninstall-info-am \ uninstall-toollibffiHEADERS .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-exec install-exec-am install-hackDATA \ install-info install-info-am install-man install-strip \ install-toollibffiHEADERS 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-hackDATA \ uninstall-info-am uninstall-toollibffiHEADERS # 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: --- NEW FILE: ffi_common.h --- /* ----------------------------------------------------------------------- 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 /*@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 #define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+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 { /*@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 --- NEW FILE: ffi.h.in --- /* -----------------------------------------------------------------*-C-*- libffi @VERSION@ - 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 cloure 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. */ #define @TARGET@ /* ---- System configuration information --------------------------------- */ #include <ffitarget.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_OK = 0, FFI_BAD_TYPEDEF, FFI_BAD_ABI } ffi_status; typedef unsigned FFI_TYPE; typedef struct { 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)(), /*@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)(), /*@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 { 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*, ffi_cif *, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data); 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_raw*,void*); void *user_data; } ffi_raw_closure; ffi_status ffi_prep_raw_closure (ffi_raw_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*, 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)(), /*@out@*/ void *rvalue, /*@dependent@*/ void **avalue); /* Useful for eliminating compiler warnings */ #define FFI_FN(f) ((void (*)())f) /* ---- Definitions shared with assembly code ---------------------------- */ #endif /* 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 #if @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 --- NEW FILE: Makefile.am --- ## Process this with automake to create Makefile.in AUTOMAKE_OPTIONS=foreign DISTCLEANFILES=ffitarget.h EXTRA_DIST=ffi.h.in ffi_common.h hackdir=$(includedir) hack_DATA= ffi.h toollibffidir = @tool_include_dir@/libffi toollibffi_HEADERS = ffitarget.h |
From: Thomas H. <th...@us...> - 2004-06-18 20:07:16
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12302/gcc/libffi Added Files: .cvsignore ChangeLog ChangeLog.libgcj ChangeLog.v1 LICENSE Makefile.am Makefile.in README acinclude.m4 aclocal.m4 configure configure.ac fficonfig.h.in libtool-version stamp-h.in Log Message: Importing libffi sources and build tools. --- NEW FILE: .cvsignore --- autom4te.cache --- NEW FILE: ChangeLog.v1 --- The libffi version 1 ChangeLog archive. Version 1 of libffi had per-directory ChangeLogs. Current and future versions have a single ChangeLog file in the root directory. The version 1 ChangeLogs have all been concatonated into this file for future reference only. --- libffi ---------------------------------------------------------------- Mon Oct 5 02:17:50 1998 Anthony Green <gr...@cy...> * configure.in: Boosted rev. * configure, Makefile.in, aclocal.m4: Rebuilt. * README: Boosted rev and updated release notes. Mon Oct 5 01:03:03 1998 Anthony Green <gr...@cy...> * configure.in: Boosted rev. * configure, Makefile.in, aclocal.m4: Rebuilt. * README: Boosted rev and updated release notes. 1998-07-25 Andreas Schwab <sc...@is...> * m68k/ffi.c (ffi_prep_cif_machdep): Use bitmask for cif->flags. Correctly handle small structures. (ffi_prep_args): Also handle small structures. (ffi_call): Pass size of return type to ffi_call_SYSV. * m68k/sysv.S: Adjust for above changes. Correctly align small structures in the return value. * types.c (uint64, sint64) [M68K]: Change alignment to 4. Fri Apr 17 17:26:58 1998 Anthony Green <gr...@ho...> * configure.in: Boosted rev. * configure,Makefile.in,aclocal.m4: Rebuilt. * README: Boosted rev and added release notes. Sun Feb 22 00:50:41 1998 Geoff Keating <ge...@oz...> * configure.in: Add PowerPC config bits. 1998-02-14 Andreas Schwab <sc...@is...> * configure.in: Add m68k config bits. Change AC_CANONICAL_SYSTEM to AC_CANONICAL_HOST, this is not a compiler. Use $host instead of $target. Remove AC_CHECK_SIZEOF(char), we already know the result. Fix argument of AC_ARG_ENABLE. * configure, fficonfig.h.in: Rebuilt. Tue Feb 10 20:53:40 1998 Richard Henderson <rt...@cy...> * configure.in: Add Alpha config bits. Tue May 13 13:39:20 1997 Anthony Green <gr...@ho...> * README: Updated dates and reworded Irix comments. * configure.in: Removed AC_PROG_RANLIB. * Makefile.in, aclocal.m4, config.guess, config.sub, configure, ltmain.sh, */Makefile.in: libtoolized again and rebuilt with automake and autoconf. Sat May 10 18:44:50 1997 Tom Tromey <tr...@cy...> * configure, aclocal.m4: Rebuilt. * configure.in: Don't compute EXTRADIST; now handled in src/Makefile.in. Removed macros implied by AM_INIT_AUTOMAKE. Don't run AM_MAINTAINER_MODE. Thu May 8 14:34:05 1997 Anthony Green <gr...@ho...> * missing, ltmain.sh, ltconfig.sh: Created. These are new files required by automake and libtool. * README: Boosted rev to 1.14. Added notes. * acconfig.h: Moved PACKAGE and VERSION for new automake. * configure.in: Changes for libtool. * Makefile.am (check): make test now make check. Uses libtool now. * Makefile.in, configure.in, aclocal.h, fficonfig.h.in: Rebuilt. Thu May 1 16:27:07 1997 Anthony Green <gr...@ho...> * missing: Added file required by new automake. Tue Nov 26 14:10:42 1996 Anthony Green <gr...@cs...> * acconfig.h: Added USING_PURIFY flag. This is defined when --enable-purify-safety was used at configure time. * configure.in (allsources): Added --enable-purify-safety switch. (VERSION): Boosted rev to 1.13. * configure: Rebuilt. Fri Nov 22 06:46:12 1996 Anthony Green <gr...@rt...> * configure.in (VERSION): Boosted rev to 1.12. Removed special CFLAGS hack for gcc. * configure: Rebuilt. * README: Boosted rev to 1.12. Added notes. * Many files: Cygnus Support changed to Cygnus Solutions. Wed Oct 30 11:15:25 1996 Anthony Green <gr...@rt...> * configure.in (VERSION): Boosted rev to 1.11. * configure: Rebuilt. * README: Boosted rev to 1.11. Added notes about GNU make. Tue Oct 29 12:25:12 1996 Anthony Green <gr...@rt...> * configure.in: Fixed -Wall trick. (VERSION): Boosted rev. * configure: Rebuilt * acconfig.h: Needed for --enable-debug configure switch. * README: Boosted rev to 1.09. Added more notes on building libffi, and LCLint. * configure.in: Added --enable-debug switch. Boosted rev to 1.09. * configure: Rebuilt Tue Oct 15 13:11:28 1996 Anthony Green <gr...@ho...> * configure.in (VERSION): Boosted rev to 1.08 * configure: Rebuilt. * README: Added n32 bug fix notes. * Makefile.am: Added "make lint" production. * Makefile.in: Rebuilt. Mon Oct 14 10:54:46 1996 Anthony Green <gr...@rt...> * README: Added web page reference. * configure.in, README: Boosted rev to 1.05 * configure: Rebuilt. * README: Fixed n32 sample code. Fri Oct 11 17:09:28 1996 Anthony Green <gr...@rt...> * README: Added sparc notes. * configure.in, README: Boosted rev to 1.04. * configure: Rebuilt. Thu Oct 10 10:31:03 1996 Anthony Green <gr...@rt...> * configure.in, README: Boosted rev to 1.03. * configure: Rebuilt. * README: Added struct notes. * Makefile.am (EXTRA_DIST): Added LICENSE to distribution. * Makefile.in: Rebuilt. * README: Removed Linux section. No special notes now because aggregates arg/return types work. Wed Oct 9 16:16:42 1996 Anthony Green <gr...@rt...> * README, configure.in (VERSION): Boosted rev to 1.02 * configure: Rebuilt. Tue Oct 8 11:56:33 1996 Anthony Green <gr...@rt...> * README (NOTE): Added n32 notes. * Makefile.am: Added test production. * Makefile: Rebuilt * README: spell checked! * configure.in (VERSION): Boosted rev to 1.01 * configure: Rebuilt. Mon Oct 7 15:50:22 1996 Anthony Green <gr...@rt...> * configure.in: Added nasty bit to support SGI tools. * configure: Rebuilt. * README: Added SGI notes. Added note about automake bug. Mon Oct 7 11:00:28 1996 Anthony Green <gr...@ho...> * README: Rewrote intro, and fixed examples. Fri Oct 4 10:19:55 1996 Anthony Green <gr...@ho...> * configure.in: -D$TARGET is no longer used as a compiler switch. It is now inserted into ffi.h at configure time. * configure: Rebuilt. * FFI_ABI and FFI_STATUS are now ffi_abi and ffi_status. Thu Oct 3 13:47:34 1996 Anthony Green <gr...@ho...> * README, LICENSE: Created. Wrote some docs. * configure.in: Don't barf on i586-unknown-linuxaout. Added EXTRADIST code for "make dist". * configure: Rebuilt. * */Makefile.in: Rebuilt with patched automake. Tue Oct 1 17:12:25 1996 Anthony Green <gr...@rt...> * Makefile.am, aclocal.m4, config.guess, config.sub, configure.in, fficonfig.h.in, install-sh, mkinstalldirs, stamp-h.in: Created * Makefile.in, configure: Generated --- libffi/include -------------------------------------------------------- Tue Feb 24 13:09:36 1998 Anthony Green <gr...@ge...> * ffi_mips.h: Updated FFI_TYPE_STRUCT_* values based on ffi.h.in changes. This is a work-around for SGI's "simple" assembler. Sun Feb 22 00:51:55 1998 Geoff Keating <ge...@oz...> * ffi.h.in: PowerPC support. 1998-02-14 Andreas Schwab <sc...@is...> * ffi.h.in: Add m68k support. (FFI_TYPE_LONGDOUBLE): Make it a separate value. Tue Feb 10 20:55:16 1998 Richard Henderson <rt...@cy...> * ffi.h.in (SIZEOF_ARG): Use a pointer type by default. * ffi.h.in: Alpha support. Fri Nov 22 06:48:45 1996 Anthony Green <gr...@rt...> * ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions. Wed Nov 20 22:31:01 1996 Anthony Green <gr...@ho...> * ffi.h.in: Added ffi_type_void definition. Tue Oct 29 12:22:40 1996 Anthony Green <gr...@rt...> * Makefile.am (hack_DATA): Always install ffi_mips.h. * ffi.h.in: Removed FFI_DEBUG. It's now in the correct place (acconfig.h). Added #include <stddef.h> for size_t definition. Tue Oct 15 17:23:35 1996 Anthony Green <gr...@ho...> * ffi.h.in, ffi_common.h, ffi_mips.h: More clean up. Commented out #define of FFI_DEBUG. Tue Oct 15 13:01:06 1996 Anthony Green <gr...@rt...> * ffi_common.h: Added bool definition. * ffi.h.in, ffi_common.h: Clean up based on LCLint output. Added funny /*@...@*/ comments to annotate source. Mon Oct 14 12:29:23 1996 Anthony Green <gr...@rt...> * ffi.h.in: Interface changes based on feedback from Jim Blandy. Fri Oct 11 16:49:35 1996 Anthony Green <gr...@rt...> * ffi.h.in: Small change for sparc support. Thu Oct 10 14:53:37 1996 Anthony Green <gr...@rt...> * ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for special structure return types. Wed Oct 9 13:55:57 1996 Anthony Green <gr...@rt...> * ffi.h.in: Added SIZEOF_ARG definition for X86 Tue Oct 8 11:40:36 1996 Anthony Green <gr...@rt...> * ffi.h.in (FFI_FN): Added macro for eliminating compiler warnings. Use it to case your function pointers to the proper type. * ffi_mips.h (SIZEOF_ARG): Added magic to fix type promotion bug. * Makefile.am (EXTRA_DIST): Added ffi_mips.h to EXTRA_DIST. * Makefile: Rebuilt. * ffi_mips.h: Created. Moved all common mips definitions here. Mon Oct 7 10:58:12 1996 Anthony Green <gr...@ho...> * ffi.h.in: The SGI assember is very picky about parens. Redefined some macros to avoid problems. * ffi.h.in: Added FFI_DEFAULT_ABI definitions. Also added externs for pointer, and 64bit integral ffi_types. Fri Oct 4 09:51:37 1996 Anthony Green <gr...@ho...> * ffi.h.in: Added FFI_ABI member to ffi_cif and changed function prototypes accordingly. Added #define @TARGET@. Now programs including ffi.h don't have to specify this themselves. Thu Oct 3 15:36:44 1996 Anthony Green <gr...@ho...> * ffi.h.in: Changed ffi_prep_cif's values from void* to void** * Makefile.am (EXTRA_DIST): Added EXTRA_DIST for "make dist" to work. * Makefile.in: Regenerated. Wed Oct 2 10:16:59 1996 Anthony Green <gr...@ho...> * Makefile.am: Created * Makefile.in: Generated * ffi_common.h: Added rcsid comment Tue Oct 1 17:13:51 1996 Anthony Green <gr...@rt...> * ffi.h.in, ffi_common.h: Created --- libffi/src ------------------------------------------------------------ Mon Oct 5 02:17:50 1998 Anthony Green <gr...@cy...> * arm/ffi.c, arm/sysv.S: Created. * Makefile.am: Added arm files. * Makefile.in: Rebuilt. Mon Oct 5 01:41:38 1998 Anthony Green <gr...@rt...> * Makefile.am (libffi_la_LDFLAGS): Incremented revision. Sun Oct 4 16:27:17 1998 Anthony Green <gr...@cy...> * alpha/osf.S (ffi_call_osf): Patch for DU assembler. * ffitest.c (main): long long and long double return values work for x86. Fri Apr 17 11:50:58 1998 Anthony Green <gr...@ho...> * Makefile.in: Rebuilt. * ffitest.c (main): Floating point tests not executed for systems with broken lond double (SunOS 4 w/ GCC). * types.c: Fixed x86 alignment info for long long types. Thu Apr 16 07:15:28 1998 Anthony Green <gr...@ad...> * ffitest.c: Added more notes about GCC bugs under Irix 6. Wed Apr 15 08:42:22 1998 Anthony Green <gr...@ho...> * ffitest.c (struct5): New test function. (main): New test with struct5. Thu Mar 5 10:48:11 1998 Anthony Green <gr...@to...> * prep_cif.c (initialize_aggregate): Fix assertion for nested structures. Tue Feb 24 16:33:41 1998 Anthony Green <gr...@ho...> * prep_cif.c (ffi_prep_cif): Added long double support for sparc. Sun Feb 22 00:52:18 1998 Geoff Keating <ge...@oz...> * powerpc/asm.h: New file. * powerpc/ffi.c: New file. * powerpc/sysv.S: New file. * Makefile.am: PowerPC port. * ffitest.c (main): Allow all tests to run even in presence of gcc bug on PowerPC. 1998-02-17 Anthony Green <gr...@ho...> * mips/ffi.c: Fixed comment typo. * x86/ffi.c (ffi_prep_cif_machdep), x86/sysv.S (retfloat): Fixed x86 long double return handling. * types.c: Fixed x86 long double alignment info. 1998-02-14 Andreas Schwab <sc...@is...> * types.c: Add m68k support. * ffitest.c (floating): Add long double parameter. (return_ll, ldblit): New functions to test long long and long double return value. (main): Fix type error in assignment of ts[1-4]_type.elements. Add tests for long long and long double arguments and return values. * prep_cif.c (ffi_prep_cif) [M68K]: Don't allocate argument for struct value pointer. * m68k/ffi.c, m68k/sysv.S: New files. * Makefile.am: Add bits for m68k port. Add kludge to work around automake deficiency. (test): Don't require "." in $PATH. * Makefile.in: Rebuilt. Wed Feb 11 07:36:50 1998 Anthony Green <gr...@ho...> * Makefile.in: Rebuilt. Tue Feb 10 20:56:00 1998 Richard Henderson <rt...@cy...> * alpha/ffi.c, alpha/osf.S: New files. * Makefile.am: Alpha port. Tue Nov 18 14:12:07 1997 Anthony Green <gr...@ho...> * mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag for n32. Tue Jun 3 17:18:20 1997 Anthony Green <gr...@ho...> * ffitest.c (main): Added hack to get structure tests working correctly. Sat May 10 19:06:42 1997 Tom Tromey <tr...@cy...> * Makefile.in: Rebuilt. * Makefile.am (EXTRA_DIST): Explicitly list all distributable files in subdirs. (VERSION, CC): Removed. Thu May 8 17:19:01 1997 Anthony Green <gr...@ho...> * Makefile.am: Many changes for new automake and libtool. * Makefile.in: Rebuilt. Fri Nov 22 06:57:56 1996 Anthony Green <gr...@rt...> * ffitest.c (main): Fixed test case for non mips machines. Wed Nov 20 22:31:59 1996 Anthony Green <gr...@ho...> * types.c: Added ffi_type_void declaration. Tue Oct 29 13:07:19 1996 Anthony Green <gr...@rt...> * ffitest.c (main): Fixed character constants. (main): Emit warning for structure test 3 failure on Sun. * Makefile.am (VPATH): Fixed VPATH def'n so automake won't strip it out. Moved distdir hack from libffi to automake. (ffitest): Added missing -c for $(COMPILE) (change in automake). * Makefile.in: Rebuilt. Tue Oct 15 13:08:20 1996 Anthony Green <gr...@ho...> * Makefile.am: Added "make lint" production. * Makefile.in: Rebuilt. * prep_cif.c (STACK_ARG_SIZE): Improved STACK_ARG_SIZE macro. Clean up based on LCLint output. Added funny /*@...@*/ comments to annotate source. * ffitest.c, debug.c: Cleaned up code. Mon Oct 14 12:26:56 1996 Anthony Green <gr...@rt...> * ffitest.c: Changes based on interface changes. * prep_cif.c (ffi_prep_cif): Cleaned up interface based on feedback from Jim Blandy. Fri Oct 11 15:53:18 1996 Anthony Green <gr...@rt...> * ffitest.c: Reordered tests while porting to sparc. Made changes to handle lame structure passing for sparc. Removed calls to fflush(). * prep_cif.c (ffi_prep_cif): Added special case for sparc aggregate type arguments. Thu Oct 10 09:56:51 1996 Anthony Green <gr...@rt...> * ffitest.c (main): Added structure passing/returning tests. * prep_cif.c (ffi_prep_cif): Perform proper initialization of structure return types if needed. (initialize_aggregate): Bug fix Wed Oct 9 16:04:20 1996 Anthony Green <gr...@rt...> * types.c: Added special definitions for x86 (double doesn't need double word alignment). * ffitest.c: Added many tests Tue Oct 8 09:19:22 1996 Anthony Green <gr...@rt...> * prep_cif.c (ffi_prep_cif): Fixed assertion. * debug.c (ffi_assert): Must return a non void now. * Makefile.am: Added test production. * Makefile: Rebuilt. * ffitest.c (main): Created. * types.c: Created. Stripped common code out of */ffi.c. * prep_cif.c: Added missing stdlib.h include. * debug.c (ffi_type_test): Used "a" to eliminate compiler warnings in non-debug builds. Included ffi_common.h. Mon Oct 7 15:36:42 1996 Anthony Green <gr...@rt...> * Makefile.am: Added a rule for .s -> .o This is required by the SGI compiler. * Makefile: Rebuilt. Fri Oct 4 09:51:08 1996 Anthony Green <gr...@ho...> * prep_cif.c (initialize_aggregate): Moved abi specification to ffi_prep_cif(). Thu Oct 3 15:37:37 1996 Anthony Green <gr...@ho...> * prep_cif.c (ffi_prep_cif): Changed values from void* to void**. (initialize_aggregate): Fixed aggregate type initialization. * Makefile.am (EXTRA_DIST): Added support code for "make dist". * Makefile.in: Regenerated. Wed Oct 2 11:41:57 1996 Anthony Green <gr...@ho...> * debug.c, prep_cif: Created. * Makefile.am: Added debug.o and prep_cif.o to OBJ. * Makefile.in: Regenerated. * Makefile.am (INCLUDES): Added missing -I../include * Makefile.in: Regenerated. Tue Oct 1 17:11:51 1996 Anthony Green <gr...@rt...> * error.c, Makefile.am: Created. * Makefile.in: Generated. --- libffi/src/x86 -------------------------------------------------------- Sun Oct 4 16:27:17 1998 Anthony Green <gr...@cy...> * sysv.S (retlongdouble): Fixed long long return value support. * ffi.c (ffi_prep_cif_machdep): Ditto. Wed May 13 04:30:33 1998 Anthony Green <gr...@ra...> * ffi.c (ffi_prep_cif_machdep): Fixed long double return value support. Wed Apr 15 08:43:20 1998 Anthony Green <gr...@ho...> * ffi.c (ffi_prep_args): small struct support was missing. Thu May 8 16:53:58 1997 Anthony Green <gr...@ho...> * objects.mak: Removed. Mon Dec 2 15:12:58 1996 Tom Tromey <tr...@cy...> * sysv.S: Use .balign, for a.out Linux boxes. Tue Oct 15 13:06:50 1996 Anthony Green <gr...@ho...> * ffi.c: Clean up based on LCLint output. Added funny /*@...@*/ comments to annotate source. Fri Oct 11 16:43:38 1996 Anthony Green <gr...@rt...> * ffi.c (ffi_call): Added assertion for bad ABIs. Wed Oct 9 13:57:27 1996 Anthony Green <gr...@rt...> * sysv.S (retdouble): Fixed double return problems. * ffi.c (ffi_call): Corrected fn arg definition. (ffi_prep_cif_machdep): Fixed double return problems Tue Oct 8 12:12:49 1996 Anthony Green <gr...@rt...> * ffi.c: Moved ffi_type definitions to types.c. (ffi_prep_args): Fixed type promotion bug. Mon Oct 7 15:53:06 1996 Anthony Green <gr...@rt...> * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' Fri Oct 4 09:54:53 1996 Anthony Green <gr...@ho...> * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped remaining args. Wed Oct 2 10:07:05 1996 Anthony Green <gr...@ho...> * ffi.c, sysv.S, objects.mak: Created. (ffi_prep_cif): cif->rvalue no longer initialized to NULL. (ffi_prep_cif_machdep): Moved machine independent cif processing to src/prep_cif.c. Introduced ffi_prep_cif_machdep(). --- libffi/src/mips ------------------------------------------------------- Tue Feb 17 17:18:07 1998 Anthony Green <gr...@ho...> * o32.S: Fixed typo in comment. * ffi.c (ffi_prep_cif_machdep): Fixed argument processing. Thu May 8 16:53:58 1997 Anthony Green <gr...@ho...> * o32.s, n32.s: Wrappers for SGI tool support. * objects.mak: Removed. Tue Oct 29 14:37:45 1996 Anthony Green <gr...@rt...> * ffi.c (ffi_prep_args): Changed int z to size_t z. Tue Oct 15 13:17:25 1996 Anthony Green <gr...@ho...> * n32.S: Fixed bad stack munging. * ffi.c: Moved prototypes for ffi_call_?32() to here from ffi_mips.h because extended_cif is not defined in ffi_mips.h. Mon Oct 14 12:42:02 1996 Anthony Green <gr...@rt...> * ffi.c: Interface changes based on feedback from Jim Blandy. Thu Oct 10 11:22:16 1996 Anthony Green <gr...@rt...> * n32.S, ffi.c: Lots of changes to support passing and returning structures with the n32 calling convention. * n32.S: Fixed fn pointer bug. * ffi.c (ffi_prep_cif_machdep): Fix for o32 structure return values. (ffi_prep_args): Fixed n32 structure passing when structures partially fit in registers. Wed Oct 9 13:49:25 1996 Anthony Green <gr...@rt...> * objects.mak: Added n32.o. * n32.S: Created. * ffi.c (ffi_prep_args): Added magic to support proper n32 processing. Tue Oct 8 10:37:35 1996 Anthony Green <gr...@rt...> * ffi.c: Moved ffi_type definitions to types.c. (ffi_prep_args): Fixed type promotion bug. * o32.S: This code is only built for o32 compiles. A lot of the #define cruft has moved to ffi_mips.h. * ffi.c (ffi_prep_cif_machdep): Fixed arg flags. Second arg is only processed if the first is either a float or double. Mon Oct 7 15:33:59 1996 Anthony Green <gr...@rt...> * o32.S: Modified to compile under each of o32, n32 and n64. * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' Fri Oct 4 09:53:25 1996 Anthony Green <gr...@ho...> * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped remaining args. Wed Oct 2 17:41:22 1996 Anthony Green <gr...@rt...> * o32.S: Removed crufty definitions. Wed Oct 2 12:53:42 1996 Anthony Green <gr...@ho...> * ffi.c (ffi_prep_cif): cif->rvalue no longer initialized to NULL. (ffi_prep_cif_machdep): Moved all machine independent cif processing to src/prep_cif.c. Introduced ffi_prep_cif_machdep. Return types of FFI_TYPE_STRUCT are no different than FFI_TYPE_INT. Tue Oct 1 17:11:02 1996 Anthony Green <gr...@rt...> * ffi.c, o32.S, object.mak: Created --- libffi/src/sparc ------------------------------------------------------ Tue Feb 24 16:33:18 1998 Anthony Green <gr...@ho...> * ffi.c (ffi_prep_args): Added long double support. Thu May 8 16:53:58 1997 Anthony Green <gr...@ho...> * objects.mak: Removed. Thu May 1 16:07:56 1997 Anthony Green <gr...@ho...> * v8.S: Fixed minor portability problem reported by Russ McManus <mc...@eq...>. Tue Nov 26 14:12:43 1996 Anthony Green <gr...@cs...> * v8.S: Used STACKFRAME define elsewhere. * ffi.c (ffi_prep_args): Zero out space when USING_PURIFY is set. (ffi_prep_cif_machdep): Allocate the correct stack frame space for functions with < 6 args. Tue Oct 29 15:08:55 1996 Anthony Green <gr...@rt...> * ffi.c (ffi_prep_args): int z is now size_t z. Mon Oct 14 13:31:24 1996 Anthony Green <gr...@rt...> * v8.S (ffi_call_V8): Gordon rewrites this again. It looks great now. * ffi.c (ffi_call): The comment about hijacked registers is no longer valid after gordoni hacked v8.S. * v8.S (ffi_call_V8): Rewrote with gordoni. Much simpler. * v8.S, ffi.c: ffi_call() had changed to accept more than two args, so v8.S had to change (because it hijacks incoming arg registers). * ffi.c: Interface changes based on feedback from Jim Blandy. Thu Oct 10 17:48:16 1996 Anthony Green <gr...@rt...> * ffi.c, v8.S, objects.mak: Created. --- NEW FILE: stamp-h.in --- timestamp --- NEW FILE: configure --- #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for libffi 2.1. # # Report bugs to <http://gcc.gnu.org/bugs.html>. # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. [...8263 lines suppressed...] # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi --- NEW FILE: LICENSE --- 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. --- NEW FILE: ChangeLog --- 2004-06-17 Matthias Klose <do...@de...> * libtool-version: New. * Makefile.am (libffi_la_LDFLAGS): Use -version-info for soname. * Makefile.in: Regenerate. 2004-06-15 Paolo Bonzini <bo...@gn...> * Makefile.am: Remove useless multilib rules. * Makefile.in: Regenerate. * aclocal.m4: Regenerate with automake 1.8.5. * configure.ac: Remove useless multilib configury. * configure: Regenerate. 2004-06-15 Paolo Bonzini <bo...@gn...> * .cvsignore: New file. 2004-06-10 Jakub Jelinek <ja...@re...> [...1617 lines suppressed...] * Makefile.in: Rebuilt. * aclocal.m4, config.guess, config.sub, ltconfig, ltmain.sh: Upgraded to new autoconf, automake, libtool. * README: Tweaks. * LICENSE: Update copyright date. * src/Makefile.am, src/Makefile.in: Removed. 1998-11-29 Anthony Green <gr...@cy...> * include/ChangeLog: Removed. * src/ChangeLog: Removed. * src/mips/ChangeLog: Removed. * src/sparc/ChangeLog: Remboved. * src/x86/ChangeLog: Removed. * ChangeLog.v1: Created. --- NEW FILE: Makefile.in --- # Makefile.in generated by automake 1.8.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004 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@ SOURCES = $(libffi_la_SOURCES) $(nodist_libffi_la_SOURCES) $(libffi_convenience_la_SOURCES) $(nodist_libffi_convenience_la_SOURCES) srcdir = @srcdir@ [...1429 lines suppressed...] clean-toolexeclibLTLIBRARIES ctags ctags-recursive dist \ dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip \ distcheck distclean distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-multi \ distclean-recursive distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-multi install-strip install-toolexeclibLTLIBRARIES \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic \ maintainer-clean-multi maintainer-clean-recursive mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ mostlyclean-multi mostlyclean-recursive pdf pdf-am ps ps-am \ tags tags-recursive uninstall uninstall-am uninstall-info-am \ uninstall-toolexeclibLTLIBRARIES # 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: --- NEW FILE: fficonfig.h.in --- /* fficonfig.h.in. Generated from configure.ac by autoheader. */ /* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ #undef BYTEORDER /* 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. */ #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 /* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H /* 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 <inttypes.h> header file. */ #undef HAVE_INTTYPES_H /* Define if you have the long double type and it is bigger than a double */ #undef HAVE_LONG_DOUBLE /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mmap' function. */ #undef HAVE_MMAP /* Define if mmap with MAP_ANON(YMOUS) works. */ #undef HAVE_MMAP_ANON /* Define if mmap of /dev/zero works. */ #undef HAVE_MMAP_DEV_ZERO /* Define if read-only mmap of a plain file works. */ #undef HAVE_MMAP_FILE /* Define if .eh_frame sections should be read-only. */ #undef HAVE_RO_EH_FRAME /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the <strings.h> header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the <sys/mman.h> header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H /* Define if the host machine stores words of multi-word integers in big-endian order. */ #undef HOST_WORDS_BIG_ENDIAN /* 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 /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* The number of bytes in type double */ #undef SIZEOF_DOUBLE /* The number of bytes in type long double */ #undef SIZEOF_LONG_DOUBLE /* 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. */ #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 /* whether byteorder is bigendian */ #undef WORDS_BIGENDIAN --- NEW FILE: aclocal.m4 --- # generated automatically by aclocal 1.8.5 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 # Free Software Foundation, Inc. # This file 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. # -*- Autoconf -*- # Copyright (C) 2002, 2003 Free Software Foundation, Inc. # Generated from amversion.in; do not edit by hand. # 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 [...1051 lines suppressed...] # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) m4_include([acinclude.m4]) --- NEW FILE: acinclude.m4 --- sinclude(../libtool.m4) dnl The lines below arrange for aclocal not to bring libtool.m4 dnl AC_PROG_LIBTOOL into aclocal.m4, while still arranging for automake dnl to add a definition of LIBTOOL to Makefile.in. ifelse(yes,no,[ AC_DEFUN([AC_PROG_LIBTOOL],) AC_DEFUN([AM_PROG_LIBTOOL],) AC_SUBST(LIBTOOL) ]) # 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], [if test $ac_cv_header_sys_mman_h != yes \ || test $ac_cv_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 ]) sinclude(../config/accross.m4) --- NEW FILE: configure.ac --- dnl Process this with autoconf to create configure AC_PREREQ(2.59) AC_INIT([libffi], [2.1], [http://gcc.gnu.org/bugs.html]) AC_CONFIG_HEADERS([fficonfig.h]) AM_ENABLE_MULTILIB(, ..) AC_CANONICAL_SYSTEM target_alias=${target_alias-$host_alias} 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 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 i*86-*-linux*) TARGET=X86; TARGETDIR=x86;; i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;; i*86-*-beos*) TARGET=X86; TARGETDIR=x86;; i*86-*-freebsd*) TARGET=X86; TARGETDIR=x86;; i*86-*-netbsdelf*) 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;; sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;; sparc*-sun-*) TARGET=SPARC; TARGETDIR=sparc;; sparc-*-linux* | sparc-*-netbsdelf*) TARGET=SPARC; TARGETDIR=sparc;; sparc64-*-linux* | sparc64-*-netbsd*) TARGET=SPARC; TARGETDIR=sparc;; alpha*-*-linux* | alpha*-*-osf* | alpha*-*-freebsd* | alpha*-*-netbsd*) TARGET=ALPHA; TARGETDIR=alpha;; ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;; 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;; rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;; arm*-*-netbsdelf*) TARGET=ARM; TARGETDIR=arm;; s390-*-linux-*) TARGET=S390; TARGETDIR=s390;; s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;; x86_64-*-linux* | x86_64-*-freebsd*) TARGET=X86_64; TARGETDIR=x86;; sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;; sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;; hppa-*-linux* | parisc-*-linux*) TARGET=PA; TARGETDIR=pa;; esac AC_SUBST(AM_RUNTESTFLAGS) if test $TARGETDIR = unknown; then AC_MSG_ERROR(["libffi has not been ported to $host."]) fi AM_CONDITIONAL(MIPS_IRIX, test x$TARGET = xMIPS_IRIX) AM_CONDITIONAL(MIPS_LINUX, test x$TARGET = xMIPS_LINUX) AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC) AM_CONDITIONAL(X86, test x$TARGET = xX86) AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32) AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA) AM_CONDITIONAL(IA64, test x$TARGET = xIA64) 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(ARM, test x$TARGET = xARM) 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, test x$TARGET = xPA) case x$TARGET in xMIPS*) TARGET=MIPS ;; *) ;; esac AC_HEADER_STDC AC_CHECK_FUNCS(memcpy) AC_FUNC_ALLOCA AC_COMPILE_CHECK_SIZEOF(double) AC_COMPILE_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]) fi fi AC_SUBST(HAVE_LONG_DOUBLE) AC_C_BIGENDIAN_CROSS if test x$TARGET = xSPARC; then AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs], libffi_cv_as_sparc_ua_pcrel, [ save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS -fpic" LDFLAGS="$LDFLAGS -shared" AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],, [libffi_cv_as_sparc_ua_pcrel=yes], [libffi_cv_as_sparc_ua_pcrel=no]) CFLAGS="$save_CFLAGS" LDFLAGS="$save_LDFLAGS"]) if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1, [Define if your assembler and linker support unaligned PC relative relocs.]) fi AC_CACHE_CHECK([assembler .register pseudo-op support], libffi_cv_as_register_pseudo_op, [ libffi_cv_as_register_pseudo_op=unknown # Check if we have .register AC_TRY_COMPILE([asm (".register %g2, #scratch");],, [libffi_cv_as_register_pseudo_op=yes], [libffi_cv_as_register_pseudo_op=no]) ]) if test "x$libffi_cv_as_register_pseudo_op" = xyes; then AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1, [Define if your assembler supports .register.]) fi fi AC_CACHE_CHECK([whether .eh_frame section should be read-only], libffi_cv_ro_eh_frame, [ libffi_cv_ro_eh_frame=no echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then libffi_cv_ro_eh_frame=yes elif grep '.section.*eh_frame.*#alloc' conftest.c \ | grep -v '#write' > /dev/null; then libffi_cv_ro_eh_frame=yes fi fi rm -f conftest.* ]) if test "x$libffi_cv_ro_eh_frame" = xyes; then AC_DEFINE(HAVE_RO_EH_FRAME, 1, [Define if .eh_frame sections should be read-only.]) AC_DEFINE(EH_FRAME_FLAGS, "a", [Define to the flags needed for the .section .eh_frame directive.]) else AC_DEFINE(EH_FRAME_FLAGS, "aw", [Define to the flags needed for the .section .eh_frame directive.]) fi AC_SUBST(TARGET) AC_SUBST(TARGETDIR) AC_SUBST(SHELL) 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) #Figure out where generated headers like ffitarget.h get installed. changequote(,)dnl gcc_version_trigger=${srcdir}/../gcc/version.c gcc_version_full=`grep version_string ${gcc_version_trigger} | sed -e 's/.*\"\([^\"]*\)\".*/\1/'` gcc_version=`echo ${gcc_version_full} | sed -e 's/\([^ ]*\) .*/\1/'` tool_include_dir='$(libdir)/gcc/$(target_alias)/'${gcc_version}/include changequote([,])dnl AC_SUBST(tool_include_dir) AC_SUBST(gcc_version) 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, [ test -d src || mkdir src test -d src/$TARGETDIR || mkdir src/$TARGETDIR ], [TARGETDIR="$TARGETDIR"]) AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h) AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile) AC_OUTPUT --- NEW FILE: Makefile.am --- ## Process this with automake to create Makefile.in AUTOMAKE_OPTIONS = foreign no-dependencies subdir-objects SUBDIRS = include testsuite EXTRA_DIST = LICENSE ChangeLog.v1 \ 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/mips/ffi.c src/mips/n32.S src/mips/o32.S \ src/mips/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/ffi.c src/x86/sysv.S src/x86/win32.S \ src/x86/ffi64.c src/x86/unix64.S src/x86/ffitarget.h \ src/pa/ffi.c src/pa/linux.S ## ################################################################ ## ## 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)" \ "LIBCFLAGS=$(LIBCFLAGS)" \ "NM=$(NM)" \ "PICFLAG=$(PICFLAG)" \ "RANLIB=$(RANLIB)" \ "DESTDIR=$(DESTDIR)" MAKEOVERRIDES= toolexeclib_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 nodist_libffi_la_SOURCES = if MIPS_IRIX nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S endif if MIPS_LINUX nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S endif if X86 nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S endif if X86_WIN32 nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.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 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 ARM nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/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 nodist_libffi_la_SOURCES += src/pa/linux.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) --- NEW FILE: README --- 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_poin... [truncated message content] |
From: Thomas H. <th...@us...> - 2004-06-18 20:04:28
|
Update of /cvsroot/ctypes/ctypes/source/gcc/libffi/src/x86 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10588/gcc/libffi/src/x86 Log Message: Directory /cvsroot/ctypes/ctypes/source/gcc/libffi/src/x86 added to the repository |