2
0
Эх сурвалжийг харах

2001-08-02 Alex Graveley <[email protected]>

        * libffi/*: Import libffi CVS version, with minor changes to make it
          compile.

        * mono/interpreter/Makefile.am: Link against
          ../../libffi/.libs/libffi.a.

        * Makefile.am: Add libffi

        * autogen.sh: Replace with adapted gnome autogen.sh

        * configure.in: Add AC_CONFIG_SUBDIRS(libffi).

svn path=/trunk/mono/; revision=383
Alex Graveley 24 жил өмнө
parent
commit
44162175c8
56 өөрчлөгдсөн 11732 нэмэгдсэн , 16 устгасан
  1. 14 0
      ChangeLog
  2. 1 1
      Makefile.am
  3. 141 6
      autogen.sh
  4. 1 2
      configure.in
  5. 432 0
      libffi/ChangeLog
  6. 764 0
      libffi/ChangeLog.v1
  7. 20 0
      libffi/LICENSE
  8. 46 0
      libffi/Makefile.am
  9. 513 0
      libffi/README
  10. 12 0
      libffi/acconfig.h
  11. 97 0
      libffi/acinclude.m4
  12. 247 0
      libffi/alpha/ffi.c
  13. 278 0
      libffi/alpha/osf.S
  14. 183 0
      libffi/arm/ffi.c
  15. 111 0
      libffi/arm/sysv.S
  16. 6 0
      libffi/autogen.sh
  17. 849 0
      libffi/config-ml.in
  18. 167 0
      libffi/configure.in
  19. 65 0
      libffi/debug.c
  20. 736 0
      libffi/ffitest.c
  21. 670 0
      libffi/ia64/ffi.c
  22. 301 0
      libffi/ia64/unix.S
  23. 6 0
      libffi/include/Makefile.am
  24. 393 0
      libffi/include/ffi.h
  25. 168 0
      libffi/include/ffi_private.h
  26. 77 0
      libffi/include/fficonfig.h
  27. 269 0
      libffi/java_raw_api.c
  28. 184 0
      libffi/m68k/ffi.c
  29. 96 0
      libffi/m68k/sysv.S
  30. 469 0
      libffi/mips/ffi.c
  31. 320 0
      libffi/mips/n32.S
  32. 173 0
      libffi/mips/o32.S
  33. 680 0
      libffi/powerpc/ffi.c
  34. 148 0
      libffi/powerpc/ppc_closure.S
  35. 119 0
      libffi/powerpc/sysv.S
  36. 146 0
      libffi/prep_cif.c
  37. 240 0
      libffi/raw_api.c
  38. 589 0
      libffi/s390/ffi.c
  39. 161 0
      libffi/s390/sysv.S
  40. 422 0
      libffi/sparc/ffi.c
  41. 94 0
      libffi/sparc/v8.S
  42. 126 0
      libffi/sparc/v9.S
  43. 1 0
      libffi/stamp-h.in
  44. 15 0
      libffi/testsuite/Makefile.am
  45. 1 0
      libffi/testsuite/config/default.exp
  46. 44 0
      libffi/testsuite/lib/libffi.exp
  47. 13 0
      libffi/testsuite/libffi.call/call.exp
  48. 4 0
      libffi/testsuite/libffi.call/ffitest.h
  49. 55 0
      libffi/testsuite/libffi.call/float.c
  50. 63 0
      libffi/testsuite/libffi.call/many.c
  51. 38 0
      libffi/testsuite/libffi.call/strlen.c
  52. 153 0
      libffi/types.c
  53. 508 0
      libffi/x86/ffi.c
  54. 167 0
      libffi/x86/sysv.S
  55. 125 0
      libffi/x86/win32.S
  56. 11 7
      mono/interpreter/Makefile.am

+ 14 - 0
ChangeLog

@@ -1,3 +1,17 @@
+2001-08-02  Alex Graveley  <[email protected]>
+
+        * libffi/*: Import libffi CVS version, with minor changes to make it 
+          compile.
+
+        * mono/interpreter/Makefile.am: Link against 
+          ../../libffi/.libs/libffi.a.
+
+        * Makefile.am: Add libffi
+
+        * autogen.sh: Replace with adapted gnome autogen.sh
+
+        * configure.in: Add AC_CONFIG_SUBDIRS(libffi).
+
 2001-08-02  Dietmar Maurer  <[email protected]>
 
 	* mono/tests/pinvoke.cs: impl.

+ 1 - 1
Makefile.am

@@ -1 +1 @@
-SUBDIRS = mono doc
+SUBDIRS = libffi mono doc

+ 141 - 6
autogen.sh

@@ -1,6 +1,141 @@
-libtoolize --automake
-automake -a
-autoheader
-aclocal $ACLOCAL_FLAGS
-autoconf
-./configure $*
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+# Ripped off from GNOME macros version
+
+DIE=0
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+if [ -n "$MONO_PATH" ]; then
+	ACLOCAL_FLAGS="-I $MONO_PATH/share/aclocal $ACLOCAL_FLAGS"
+	PATH="$MONO_PATH/bin:$PATH"
+	export PATH
+fi
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+  echo
+  echo "**Error**: You must have \`autoconf' installed to compile Mono."
+  echo "Download the appropriate package for your distribution,"
+  echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+  DIE=1
+}
+
+(grep "^AM_PROG_LIBTOOL" $srcdir/configure.in >/dev/null) && {
+  (libtool --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "**Error**: You must have \`libtool' installed to compile Mono."
+    echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz"
+    echo "(or a newer version if it is available)"
+    DIE=1
+  }
+}
+
+grep "^AM_GNU_GETTEXT" $srcdir/configure.in >/dev/null && {
+  grep "sed.*POTFILES" $srcdir/configure.in >/dev/null || \
+  (gettext --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "**Error**: You must have \`gettext' installed to compile Mono."
+    echo "Get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
+    echo "(or a newer version if it is available)"
+    DIE=1
+  }
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+  echo
+  echo "**Error**: You must have \`automake' installed to compile Mono."
+  echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
+  echo "(or a newer version if it is available)"
+  DIE=1
+  NO_AUTOMAKE=yes
+}
+
+
+# if no automake, don't bother testing for aclocal
+test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
+  echo
+  echo "**Error**: Missing \`aclocal'.  The version of \`automake'"
+  echo "installed doesn't appear recent enough."
+  echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
+  echo "(or a newer version if it is available)"
+  DIE=1
+}
+
+if test "$DIE" -eq 1; then
+  exit 1
+fi
+
+if test -z "$*"; then
+  echo "**Warning**: I am going to run \`configure' with no arguments."
+  echo "If you wish to pass any to it, please specify them on the"
+  echo \`$0\'" command line."
+  echo
+fi
+
+case $CC in
+xlc )
+  am_opt=--include-deps;;
+esac
+
+for coin in `find $srcdir -name configure.in -print`
+do 
+  dr=`dirname $coin`
+  if test -f $dr/NO-AUTO-GEN; then
+    echo skipping $dr -- flagged as no auto-gen
+  else
+    echo processing $dr
+    macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
+    ( cd $dr
+      macrosdir=`find . -name macros -print`
+      if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
+	if grep "sed.*POTFILES" configure.in >/dev/null; then
+	  : do nothing -- we still have an old unmodified configure.in
+	else
+	  echo "Creating $dr/aclocal.m4 ..."
+	  test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
+	  echo "Running gettextize...  Ignore non-fatal messages."
+	  echo "no" | gettextize --force --copy
+	  echo "Making $dr/aclocal.m4 writable ..."
+	  test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
+        fi
+      fi
+      if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
+	if test -z "$NO_LIBTOOLIZE" ; then 
+	  echo "Running libtoolize..."
+	  libtoolize --force --copy
+	fi
+      fi
+      echo "Running aclocal $aclocalinclude ..."
+      aclocal $aclocalinclude || {
+	echo
+	echo "**Error**: aclocal failed. This may mean that you have not"
+	echo "installed all of the packages you need, or you may need to"
+	echo "set ACLOCAL_FLAGS to include \"-I \$prefix/share/aclocal\""
+	echo "for the prefix where you installed the packages whose"
+	echo "macros were not found"
+	exit 1
+      }
+
+      if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
+	echo "Running autoheader..."
+	autoheader || { echo "**Error**: autoheader failed."; exit 1; }
+      fi
+      echo "Running automake --gnu $am_opt ..."
+      automake --add-missing --gnu $am_opt ||
+	{ echo "**Error**: automake failed."; exit 1; }
+      echo "Running autoconf ..."
+      autoconf || { echo "**Error**: autoconf failed."; exit 1; }
+    ) || exit 1
+  fi
+done
+
+conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
+
+if test x$NOCONFIGURE = x; then
+  echo Running $srcdir/configure $conf_flags "$@" ...
+  $srcdir/configure $conf_flags "$@" \
+  && echo Now type \`make\' to compile $PKG_NAME || exit 1
+else
+  echo Skipping configure process.
+fi

+ 1 - 2
configure.in

@@ -29,8 +29,7 @@ GMODULE_LIBS=`glib-config --libs gmodule`
 AC_SUBST(GMODULE_CFLAGS)
 AC_SUBST(GMODULE_LIBS)
 
-AC_CHECK_LIB(ffi, ffi_prep_cif, ,[
-AC_MSG_ERROR(libffi 1.20 or higher is required.  You can get this from http://sources.redhat.com/libffi)])
+AC_CONFIG_SUBDIRS(libffi)
 
 CFLAGS='-g -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations'
 AC_SUBST(CFLAGS)

+ 432 - 0
libffi/ChangeLog

@@ -0,0 +1,432 @@
+Sun Apr 22 15:50:08 2001  Anthony Green  <[email protected]>
+
+	* include/ffi_common.h: Delete, after moving contents to...
+	* include/ffi_private.h: Subsume contents of ffi_common.h.
+	* include/Makefile.am (noinst_HEADERS): Remove ffi_common.h.
+	* include/Makefile.in: Rebuilt.
+	* arm/ffi.c, m68k/ffi.c, mips/ffi.c, powerpc/ffi.c, s390/ffi.c,
+	ia64/ffi.c: Include ffi_private.h, not ffi_common.h.
+	* alpha/ffi.c, sparc/ffi.c, x86/ffi.c: Don't include ffi_common.h.
+	* types.c, raw_api.c, java_raw_api.c, prep_cif.c: Don't include
+	ffi_common.h.
+	* debug.c: Include ffi_private.h instead of ffi_common.h.
+
+	* mips/ffi.c (calc_n32_struct_flags): Make static.
+	(FIX_ARGP): Remove call to debugging routine ffi_stop_here.
+
+	* mips/n32.S: Include ffi_private.h.
+	* mips/o32.S: Include ffi_private.h.
+
+Sun Apr 22 12:37:44 2001  Anthony Green  <[email protected]>
+
+	* README: Update some comments.
+
+	* Makefile.am (SUBDIRS): Add include so ffi.h gets installed.
+	* Makefile.in: Rebuilt.
+
+	* include/ffi.h: Change ALPHA to __alpha__ and SPARC to __sparc__.
+	* types.c: Ditto.
+	* prep_cif.c (ffi_prep_cif): Ditto.
+
+	* alpha/ffi.c, alpha/osf.S, sparc/ffi.c, sparc/v8.S, sparc/v9.S:
+	Include ffi_private.h.
+
+	* include/ffi_private.h (FFI_TYPE_LAST): Define.
+
+Sun Apr 22 11:41:55 2001  Anthony Green  <[email protected]>
+
+	* Revolutionary changes.  Target independent ffi.h.  dejagnu
+	testing infrastructure.  Moved source files around.  Configure no
+	longer depends on run tests.
+
+Sat Apr 14 20:49:46 2001  Anthony Green  <[email protected]>
+
+	* mips/ffi.c: Include mips/mips.h.
+	* mips/o32.S: Ditto.
+	* mips/n32.S: Ditto.
+	* mips/o32.s: Deleted.
+	* mips/n32.s: Deleted.
+
+Sat Apr 14 20:47:13 2001  Anthony Green  <[email protected]>
+
+	* mips/mips.h: Moved from include/ffi_mips.h.
+
+Sat Apr 14 20:09:05 2001  Anthony Green  <[email protected]>
+
+	* powerpc/asm.h: Remove rcs id.
+
+Sat Apr 14 15:04:08 2001  Anthony Green  <[email protected]>
+
+	* configure.in: Use AC_COMPILE_CHECK_SIZEOF and
+	AC_C_BIGENDIAN_CROSS.
+
+Sat Apr 14 15:02:53 2001  Anthony Green  <[email protected]>
+
+	* aclocal.m4: Rebuilt.
+	* acinclude.m4: New file.  Add AC_COMPILE_CHECK_SIZEOF and
+	AC_C_BIGENDIAN_CROSS.
+
+2001-04-8  Neale Ferguson <[email protected]>
+
+	* src/s390/ffi.c: New file.
+	* src/s390/sysv.S: New file.
+	* include/ffi.h: Add s390 bits.
+	* configure.in: Ditto.
+	* configure: Rebuild.
+
+2001-03-29  Bryce McKinlay  <[email protected]>
+
+	* configure.in: Use different syntax for subdirectory creation.
+	* configure: Rebuilt.
+
+2001-03-27  Jon Beniston  <[email protected]>
+
+	* configure.in: Added X86_WIN32 target (Win32, CygWin, MingW).
+	* configure: Rebuilt.
+	* Makefile.am: Added X86_WIN32 target support.
+	* Makefile.in: Rebuilt.
+
+	* include/ffi.h.in: Added X86_WIN32 target support.
+
+	* src/ffitest.c: Doesn't run structure tests for X86_WIN32 targets.
+	* src/types.c: Added X86_WIN32 target support.
+
+	* src/x86/win32.S: New file. Based on sysv.S, but with EH
+	stuff removed and made to work with CygWin's gas.
+
+2001-03-26  Bryce McKinlay  <[email protected]>
+
+	* configure.in: Make target subdirectory in build dir.
+	* Makefile.am: Override suffix based rules to specify correct output
+	subdirectory.
+	* Makefile.in: Rebuilt.
+	* configure: Rebuilt.
+
+2001-03-23  Kevin B Hendricks  <[email protected]>
+
+	* src/powerpc/ppc_closure.S: New file.
+	* src/powerpc/ffi.c (ffi_prep_args): Fixed ABI compatibility bug
+	involving long long and register pairs.
+	(ffi_prep_closure): New function.
+	(flush_icache): Likewise.
+	(ffi_closure_helper_SYSV): Likewise.
+	* include/ffi.h.in (FFI_CLOSURES): Define on PPC.
+	(FFI_TRAMPOLINE_SIZE): Likewise.
+	(FFI_NATIVE_RAW_API): Likewise.
+	* Makefile.in: Rebuilt.
+	* Makefile.am (EXTRA_DIST): Added src/powerpc/ppc_closure.S.
+	(TARGET_SRC_POWERPC): Likewise.
+
+2001-03-19  Tom Tromey  <[email protected]>
+
+	* Makefile.in: Rebuilt.
+	* Makefile.am (ffitest_LDFLAGS): New macro.
+
+2001-03-02  Nick Clifton  <[email protected]>
+
+	* include/ffi.h.in: Remove RCS ident string.
+	* include/ffi_mips.h: Remove RCS ident string.
+	* src/debug.c: Remove RCS ident string.
+	* src/ffitest.c: Remove RCS ident string.
+	* src/prep_cif.c: Remove RCS ident string.
+	* src/types.c: Remove RCS ident string.
+	* src/alpha/ffi.c: Remove RCS ident string.
+	* src/alpha/osf.S: Remove RCS ident string.
+	* src/arm/ffi.c: Remove RCS ident string.
+	* src/arm/sysv.S: Remove RCS ident string.
+	* src/mips/ffi.c: Remove RCS ident string.
+	* src/mips/n32.S: Remove RCS ident string.
+	* src/mips/o32.S: Remove RCS ident string.
+	* src/sparc/ffi.c: Remove RCS ident string.
+	* src/sparc/v8.S: Remove RCS ident string.
+	* src/sparc/v9.S: Remove RCS ident string.
+	* src/x86/ffi.c: Remove RCS ident string.
+	* src/x86/sysv.S: Remove RCS ident string.
+
+2001-02-08  Joseph S. Myers  <[email protected]>
+
+	* include/ffi.h.in: Change sourceware.cygnus.com references to
+	gcc.gnu.org.
+
+2000-12-09  Richard Henderson  <[email protected]>
+
+	* src/alpha/ffi.c (ffi_call): Simplify struct return test.
+	(ffi_closure_osf_inner): Index rather than increment avalue
+	and arg_types.  Give ffi_closure_osf the raw return value type.
+	* src/alpha/osf.S (ffi_closure_osf): Handle return value type
+	promotion.
+
+2000-12-07  Richard Henderson  <[email protected]>
+
+	* src/raw_api.c (ffi_translate_args): Fix typo.
+	(ffi_prep_closure): Likewise.
+
+	* include/ffi.h.in [ALPHA]: Define FFI_CLOSURES and
+	FFI_TRAMPOLINE_SIZE.
+	* src/alpha/ffi.c (ffi_prep_cif_machdep): Adjust minimal
+	cif->bytes for new ffi_call_osf implementation.
+	(ffi_prep_args): Absorb into ...
+	(ffi_call): ... here.  Do all stack allocation here and
+	avoid a callback function.
+	(ffi_prep_closure, ffi_closure_osf_inner): New.
+	* src/alpha/osf.S (ffi_call_osf): Reimplement with no callback.
+	(ffi_closure_osf): New.
+
+2000-09-10  Alexandre Oliva  <[email protected]>
+
+	* config.guess, config.sub, install-sh: Removed.
+	* ltconfig, ltmain.sh, missing, mkinstalldirs: Likewise.
+	* Makefile.in: Rebuilt.
+
+	* acinclude.m4: Include libtool macros from the top level.
+	* aclocal.m4, configure: Rebuilt.
+
+2000-08-22  Alexandre Oliva  <[email protected]>
+
+	* configure.in [i*86-*-freebsd*] (TARGET, TARGETDIR): Set.
+	* configure: Rebuilt.
+
+2000-05-11  Scott Bambrough  <[email protected]>
+
+	* libffi/src/arm/sysv.S (ffi_call_SYSV): Doubles are not saved to 
+	memory correctly.  Use conditional instructions, not branches where 
+	possible.
+
+2000-05-04  Tom Tromey  <[email protected]>
+
+	* configure: Rebuilt.
+	* configure.in: Match `arm*-*-linux-*'.
+	From Chris Dornan <[email protected]>.
+
+2000-04-28  Jakub Jelinek  <[email protected]>
+
+	* Makefile.am (SUBDIRS): Define.
+	(AM_MAKEFLAGS): Likewise.
+	(Multilib support.): Add section.
+	* Makefile.in: Rebuilt.
+	* ltconfig (extra_compiler_flags, extra_compiler_flags_value):
+        New variables. Set for gcc using -print-multi-lib. Export them
+        to libtool.
+        (sparc64-*-linux-gnu*): Use libsuff 64 for search paths.
+        * ltmain.sh (B|b|V): Don't throw away gcc's -B, -b and -V options
+        for -shared links.
+        (extra_compiler_flags_value, extra_compiler_flags): Check these
+        for extra compiler options which need to be passed down in
+        compiler_flags.
+
+2000-04-16  Anthony Green  <[email protected]>
+
+	* README: Credit updates.  Update supported platorms.
+
+	* include/ffi.h.in: Important size fixes from William Knottenblet
+	([email protected]).
+
+2000-04-16  Anthony Green  <[email protected]>
+
+	* configure: Rebuilt.
+	* configure.in: Change i*86-pc-linux* to i*86-*-linux*.
+
+2000-04-14  Jakub Jelinek  <[email protected]>
+
+        * include/ffi.h.in (SPARC64): Define for 64bit SPARC builds.
+	Set SPARC FFI_DEFAULT_ABI based on SPARC64 define.
+	* src/sparc/ffi.c (ffi_prep_args_v8): Renamed from ffi_prep_args.
+	Replace all void * sizeofs with sizeof(int).
+	Only compare type with FFI_TYPE_LONGDOUBLE if LONGDOUBLE is
+	different than DOUBLE.
+	Remove FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases (handled elsewhere).
+	(ffi_prep_args_v9): New function.
+	(ffi_prep_cif_machdep): Handle V9 ABI and long long on V8.
+	(ffi_V9_return_struct): New function.
+	(ffi_call): Handle FFI_V9 ABI from 64bit code and FFI_V8 ABI from
+	32bit code (not yet cross-arch calls).
+	* src/sparc/v8.S: Add struct return delay nop.
+	Handle long long.
+	* src/sparc/v9.S: New file.
+	* src/prep_cif.c (ffi_prep_cif): Return structure pointer
+	is used on sparc64 only for structures larger than 32 bytes.
+	Pass by reference for structures is done for structure arguments
+	larger than 16 bytes.
+	* src/ffitest.c (main): Use 64bit rint on sparc64.
+	Run long long tests on sparc.
+	* src/types.c (FFI_TYPE_POINTER): Pointer is 64bit on alpha and
+	sparc64.
+	(FFI_TYPE_LONGDOUBLE): long double is 128 bit aligned to 128 bits
+	on sparc64.
+	* configure.in (sparc-*-linux*): New supported target.
+	(sparc64-*-linux*): Likewise.
+	* configure: Rebuilt.
+	* Makefile.am: Add v9.S to SPARC files.
+	* Makefile.in: Likewise.
+	(LINK): Surround $(CCLD) into double quotes, so that multilib
+	compiles work correctly.
+
+2000-04-04  Alexandre Petit-Bianco  <[email protected]>
+
+	* configure: Rebuilt.
+
+	* configure.in: (i*86-*-solaris*): New libffi target. Patch
+	proposed by Bryce McKinlay.
+
+2000-03-20  Tom Tromey  <[email protected]>
+
+	* Makefile.in: Hand edit for java_raw_api.lo.
+
+2000-03-08  Bryce McKinlay  <[email protected]>
+
+	* config.guess, config.sub: Update from the gcc tree.
+	Fix for PR libgcj/168.
+
+2000-03-03  Tom Tromey  <[email protected]>
+
+	* Makefile.in: Fixed ia64 by hand.
+
+	* configure: Rebuilt.
+	* configure.in (--enable-multilib): New option.
+	(libffi_basedir): New subst.
+	(AC_OUTPUT): Added multilib code.
+
+2000-03-02  Tom Tromey  <[email protected]>
+
+	* Makefile.in: Rebuilt.
+	* Makefile.am (TARGET_SRC_IA64): Use `ia64', not `alpha', as
+	directory name.
+
+2000-02-25  Hans Boehm <[email protected]>
+
+	* src/ia64/ffi.c, src/ia64/ia64_flags.h, src/ia64/unix.S: New
+	files.
+	* src/raw_api.c (ffi_translate_args): Fixed typo in argument
+	list.
+	(ffi_prep_raw_closure): Use ffi_translate_args, not
+	ffi_closure_translate.
+	* src/java_raw_api.c: New file.
+	* src/ffitest.c (closure_test_fn): New function.
+	(main): Define `rint' as long long on IA64.  Added new test when
+	FFI_CLOSURES is defined.
+	* include/ffi.h.in (ALIGN): Use size_t, not unsigned.
+	(ffi_abi): Recognize IA64.
+	(ffi_raw): Added `flt' field.
+	Added "Java raw API" code.
+	* configure.in: Recognize ia64.
+	* Makefile.am (TARGET_SRC_IA64): New macro.
+	(libffi_la_common_SOURCES): Added java_raw_api.c.
+	(libffi_la_SOURCES): Define in IA64 case.
+
+2000-01-04  Tom Tromey  <[email protected]>
+
+	* Makefile.in: Rebuilt with newer automake.
+
+1999-12-31  Tom Tromey  <[email protected]>
+
+	* Makefile.am (INCLUDES): Added -I$(top_srcdir)/src.
+
+1999-09-01  Tom Tromey  <[email protected]>
+
+	* include/ffi.h.in: Removed PACKAGE and VERSION defines and
+	undefs.
+	* fficonfig.h.in: Rebuilt.
+	* configure: Rebuilt.
+	* configure.in: Pass 3rd argument to AM_INIT_AUTOMAKE.
+	Use AM_PROG_LIBTOOL (automake 1.4 compatibility).
+	* acconfig.h: Don't #undef PACKAGE or VERSION.
+
+1999-08-09  Anthony Green  <[email protected]>
+
+	* include/ffi.h.in: Try to work around messy header problem
+	with PACKAGE and VERSION.
+
+	* configure: Rebuilt.
+	* configure.in: Change version to 2.00-beta.
+
+        * fficonfig.h.in: Rebuilt.
+	* acconfig.h (FFI_NO_STRUCTS, FFI_NO_RAW_API): Define.
+
+	* src/x86/ffi.c (ffi_raw_call): Rename.
+
+Mon Aug  9 18:33:38 1999  Rainer Orth  <[email protected]>
+
+	* include/Makefile.in: Rebuilt.
+	* Makefile.in: Rebuilt
+	* Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native
+	builds.
+	Use USE_LIBDIR.
+
+	* configure: Rebuilt.
+	* configure.in (USE_LIBDIR): Define for native builds.
+	Use lowercase in configure --help explanations.
+
+1999-08-08  Anthony Green  <[email protected]>
+
+	* include/ffi.h.in (FFI_FN): Remove `...'.
+
+1999-08-08  Anthony Green  <[email protected]>
+
+	* Makefile.in: Rebuilt.
+	* Makefile.am (AM_CFLAGS): Compile with -fexceptions.
+
+	* src/x86/sysv.S: Add exception handling metadata.
+
+1999-08-02  Kresten Krab Thorup  <[email protected]>
+
+	* src/x86/ffi.c (ffi_closure_SYSV): New function.
+	(ffi_prep_incoming_args_SYSV): Ditto.
+	(ffi_prep_closure): Ditto.
+	(ffi_closure_raw_SYSV): Ditto.
+	(ffi_prep_raw_closure): More ditto.
+	(ffi_call_raw): Final ditto.
+
+	* include/ffi.h.in: Add definitions for closure and raw API.
+
+	* src/x86/ffi.c (ffi_prep_cif_machdep): Added case for
+	FFI_TYPE_UINT64.  
+
+	* Makefile.am (libffi_la_common_SOURCES): Added raw_api.c
+
+	* src/raw_api.c: New file.
+
+	* include/ffi.h.in (ffi_raw): New type.
+	(UINT_ARG, SINT_ARG): New defines.
+	(ffi_closure, ffi_raw_closure): New types.
+	(ffi_prep_closure, ffi_prep_raw_closure): New declarations.
+	
+	* configure.in: Add check for endianness and sizeof void*.
+
+	* src/x86/sysv.S (ffi_call_SYSV): Call fixup routine via argument,
+	instead of directly.
+
+	* configure: Rebuilt.
+
+Thu Jul  8 14:28:42 1999  Anthony Green  <[email protected]>
+
+	* configure.in: Add x86 and powerpc BeOS configurations.
+	From Makoto Kato <[email protected]>.
+
+1999-05-09  Anthony Green  <[email protected]>
+
+	* configure.in: Add warning about this being beta code.
+	Remove src/Makefile.am from the picture.
+	* configure: Rebuilt.
+
+	* Makefile.am: Move logic from src/Makefile.am.  Add changes
+	to support libffi as a target library.
+	* 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  <[email protected]>
+
+	* include/ChangeLog: Removed.
+	* src/ChangeLog: Removed.
+	* src/mips/ChangeLog: Removed.
+	* src/sparc/ChangeLog: Remboved.
+	* src/x86/ChangeLog: Removed.
+
+	* ChangeLog.v1: Created.

+ 764 - 0
libffi/ChangeLog.v1

@@ -0,0 +1,764 @@
+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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* configure.in: Boosted rev.
+	* configure, Makefile.in, aclocal.m4: Rebuilt.
+	* README: Boosted rev and updated release notes.
+
+1998-07-25  Andreas Schwab  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* configure.in: Add PowerPC config bits.
+
+1998-02-14  Andreas Schwab  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* configure.in: Add Alpha config bits.
+
+Tue May 13 13:39:20 1997  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* missing: Added file required by new automake.
+
+Tue Nov 26 14:10:42 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* README: Added sparc notes.
+
+	* configure.in, README: Boosted rev to 1.04.
+	* configure: Rebuilt.
+
+Thu Oct 10 10:31:03 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* README, configure.in (VERSION): Boosted rev to 1.02
+	* configure: Rebuilt.
+
+Tue Oct  8 11:56:33 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* README: Rewrote intro, and fixed examples.
+
+Fri Oct  4 10:19:55 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.h.in: PowerPC support.
+
+1998-02-14  Andreas Schwab  <[email protected]>
+
+	* ffi.h.in: Add m68k support.
+	(FFI_TYPE_LONGDOUBLE): Make it a separate value.
+
+Tue Feb 10 20:55:16 1998  Richard Henderson  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions.
+
+Wed Nov 20 22:31:01 1996  Anthony Green  <[email protected]>
+
+	* ffi.h.in: Added ffi_type_void definition.
+
+Tue Oct 29 12:22:40 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.h.in: Interface changes based on feedback from Jim
+	Blandy.
+
+Fri Oct 11 16:49:35 1996  Anthony Green  <[email protected]>
+
+	* ffi.h.in: Small change for sparc support.
+
+Thu Oct 10 14:53:37 1996  Anthony Green  <[email protected]>
+
+	* ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for 
+	special structure return types.
+
+Wed Oct  9 13:55:57 1996  Anthony Green  <[email protected]>
+
+	* ffi.h.in: Added SIZEOF_ARG definition for X86
+
+Tue Oct  8 11:40:36 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* Makefile.am: Created
+	* Makefile.in: Generated
+
+	* ffi_common.h: Added rcsid comment
+
+Tue Oct  1 17:13:51 1996  Anthony Green  <[email protected]>
+
+	* ffi.h.in, ffi_common.h: Created
+
+--- libffi/src ------------------------------------------------------------
+
+Mon Oct  5 02:17:50 1998  Anthony Green  <[email protected]>
+
+	* arm/ffi.c, arm/sysv.S: Created.
+
+	* Makefile.am: Added arm files.
+	* Makefile.in: Rebuilt.
+
+Mon Oct  5 01:41:38 1998  Anthony Green  <[email protected]>
+
+	* Makefile.am (libffi_la_LDFLAGS): Incremented revision.
+
+Sun Oct  4 16:27:17 1998  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffitest.c: Added more notes about GCC bugs under Irix 6.
+
+Wed Apr 15 08:42:22 1998  Anthony Green  <[email protected]>
+
+	* ffitest.c (struct5): New test function.
+	(main): New test with struct5.
+
+Thu Mar  5 10:48:11 1998  Anthony Green  <[email protected]>
+
+	* prep_cif.c (initialize_aggregate): Fix assertion for
+	nested structures.
+
+Tue Feb 24 16:33:41 1998  Anthony Green  <[email protected]>
+
+	* prep_cif.c (ffi_prep_cif): Added long double support for sparc.
+
+Sun Feb 22 00:52:18 1998  Geoff Keating  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* Makefile.in: Rebuilt.
+
+Tue Feb 10 20:56:00 1998  Richard Henderson  <[email protected]>
+
+	* alpha/ffi.c, alpha/osf.S: New files.
+	* Makefile.am: Alpha port.
+
+Tue Nov 18 14:12:07 1997  Anthony Green  <[email protected]>
+
+	* mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag
+	for n32.
+
+Tue Jun  3 17:18:20 1997  Anthony Green  <[email protected]>
+
+	* ffitest.c (main): Added hack to get structure tests working
+	correctly.
+
+Sat May 10 19:06:42 1997  Tom Tromey  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* Makefile.am: Many changes for new automake and libtool.
+	* Makefile.in: Rebuilt.
+
+Fri Nov 22 06:57:56 1996  Anthony Green  <[email protected]>
+
+	* ffitest.c (main): Fixed test case for non mips machines.
+
+Wed Nov 20 22:31:59 1996  Anthony Green  <[email protected]>
+
+	* types.c: Added ffi_type_void declaration.
+
+Tue Oct 29 13:07:19 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* prep_cif.c (initialize_aggregate): Moved abi specification
+	to ffi_prep_cif().
+
+Thu Oct  3 15:37:37 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* error.c, Makefile.am: Created.
+	* Makefile.in: Generated.
+
+--- libffi/src/x86 --------------------------------------------------------
+
+Sun Oct  4 16:27:17 1998  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.c (ffi_prep_cif_machdep): Fixed long double return value
+	support.
+
+Wed Apr 15 08:43:20 1998  Anthony Green  <[email protected]>
+
+	* ffi.c (ffi_prep_args): small struct support was missing.
+
+Thu May  8 16:53:58 1997  Anthony Green  <[email protected]>
+
+	* objects.mak: Removed.
+
+Mon Dec  2 15:12:58 1996  Tom Tromey  <[email protected]>
+
+	* sysv.S: Use .balign, for a.out Linux boxes.
+
+Tue Oct 15 13:06:50 1996  Anthony Green  <[email protected]>
+
+	* ffi.c: Clean up based on LCLint output.
+	Added funny /*@...@*/ comments to annotate source.
+
+Fri Oct 11 16:43:38 1996  Anthony Green  <[email protected]>
+
+	* ffi.c (ffi_call): Added assertion for bad ABIs.
+
+Wed Oct  9 13:57:27 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.c (FFI_*_TYPEDEF): Removed redundant ';'
+
+Fri Oct  4 09:54:53 1996  Anthony Green  <[email protected]>
+
+	* ffi.c (ffi_call): Removed FFI_ABI arg, and swapped
+	remaining args.
+
+Wed Oct  2 10:07:05 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* o32.S: Fixed typo in comment.
+
+	* ffi.c (ffi_prep_cif_machdep): Fixed argument processing.
+
+Thu May  8 16:53:58 1997  Anthony Green  <[email protected]>
+
+	* o32.s, n32.s: Wrappers for SGI tool support.
+
+	* objects.mak: Removed.
+
+Tue Oct 29 14:37:45 1996  Anthony Green  <[email protected]>
+
+	* ffi.c (ffi_prep_args): Changed int z to size_t z.
+
+Tue Oct 15 13:17:25 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.c: Interface changes based on feedback from Jim Blandy.
+
+Thu Oct 10 11:22:16 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.c (ffi_call): Removed FFI_ABI arg, and swapped
+	remaining args.
+
+Wed Oct  2 17:41:22 1996  Anthony Green  <[email protected]>
+
+	* o32.S: Removed crufty definitions.
+
+Wed Oct  2 12:53:42 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.c, o32.S, object.mak: Created
+	
+--- libffi/src/sparc ------------------------------------------------------
+
+Tue Feb 24 16:33:18 1998  Anthony Green  <[email protected]>
+
+	* ffi.c (ffi_prep_args): Added long double support.
+
+Thu May  8 16:53:58 1997  Anthony Green  <[email protected]>
+
+	* objects.mak: Removed.
+
+Thu May  1 16:07:56 1997  Anthony Green  <[email protected]>
+
+	* v8.S: Fixed minor portability problem reported by 
+	Russ McManus <[email protected]>.
+
+Tue Nov 26 14:12:43 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.c (ffi_prep_args): int z is now size_t z.
+
+Mon Oct 14 13:31:24 1996  Anthony Green  <[email protected]>
+
+	* 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  <[email protected]>
+
+	* ffi.c, v8.S, objects.mak: Created.
+	
+

+ 20 - 0
libffi/LICENSE

@@ -0,0 +1,20 @@
+libffi - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001  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.

+ 46 - 0
libffi/Makefile.am

@@ -0,0 +1,46 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign no-installinfo
+
+if TESTSUBDIR
+SUBDIRS = include testsuite
+else
+SUBDIRS = include
+endif
+
+EXTRA_DIST = LICENSE README ChangeLog.v1 alpha/ffi.c arm/ffi.c	\
+   ia64/ffi.c m68k/ffi.c mips/ffi.c powerpc/ffi.c s390/ffi.c	\
+   sparc/ffi.c x86/ffi.c alpha/osf.S arm/sysv.S ia64/unix.S	\
+   m68k/sysv.S mips/n32.S mips/o32.S				\
+   powerpc/sysv.S s390/sysv.S sparc/v8.S sparc/v9.S x86/win32.S	\
+   x86/sysv.S
+
+# Multilib support variables.
+MULTISRCTOP =
+MULTIBUILDTOP =
+MULTIDIRS =
+MULTISUBDIR =
+MULTIDO = true
+MULTICLEAN = true
+
+## Install a library built with a cross compiler in tooldir, not
+## libdir.
+if USE_LIBDIR
+toolexeclibdir = $(libdir)$(MULTISUBDIR)
+else
+toolexecdir = $(exec_prefix)/$(target_alias)
+toolexeclibdir = $(toolexecdir)/lib$(MULTISUBDIR)
+endif
+
+toolexeclib_LTLIBRARIES = libffi.la
+
+## Work around automake deficiency
+nodist_libffi_la_SOURCES = t-ffi.c t-asm.S
+libffi_la_SOURCES = debug.c prep_cif.c types.c \
+		raw_api.c java_raw_api.c $(nodist_libffi_la_SOURCES)
+
+AM_CFLAGS = -fexceptions
+
+libffi_la_LDFLAGS = -release $(VERSION) 
+
+INCLUDES = -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src

+ 513 - 0
libffi/README

@@ -0,0 +1,513 @@
+README for libffi-2.00
+
+libffi-2.00 has not been released yet! This is a development snapshot!
+
+libffi-1.20 was released on [SOME FUTURE DAY]. Check the libffi web
+page for updates: <URL:http://sourceware.cygnus.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:
+
+	Alpha - Linux and OSF/1
+
+	ARM - Linux (System V ABI)
+
+	IA-32 - Linux, Solaris, and BeOS (System V ABI)
+
+	IA-64 - Linux (System V ABI)
+
+	m68k - Linux (System V ABI)
+
+	MIPS, 32- and 64-bit - Irix (System V/o32 and n32)
+
+	PowerPC - Linux (System V ABI)
+
+	S390 - Linux (System V ABI)
+
+	Sparc, 32-bit - SunOS 4.1.3, Solaris 2.x, and Linux (Sparc v8)
+
+	Sparc, 64-bit - Linux (Sparc v9)
+
+
+Libffi has been tested with GCC 3.00 and newer compilers. 
+
+You must use GNU make to build libffi.
+	
+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, AIX).
+
+
+Installing libffi
+=================
+
+[Note: before actually performing any of these installation steps,
+ you may wish to read the "Platform Specific Notes" below.]
+
+First you must configure the distribution for your particular
+system. Go to the directory you wish to build libffi in and run the
+"configure" program found in the root directory of the libffi source
+distribution.
+
+You may want to tell configure where to install the libffi library and
+header files. To do that, use the --prefix configure switch.  Libffi
+will install under /usr/local by default. 
+
+If you want to enable extra run-time debugging checks use the the
+--enable-debug configure switch. This is useful when your program dies
+mysteriously while using libffi. 
+
+Another useful configure switch is --enable-purify-safety. Using this
+will add some extra code which will suppress certain warnings when you
+are using Purify with libffi. Only use this switch when using 
+Purify, as it will slow down the library.
+
+Configure has many other options. Use "configure --help" to see them all.
+
+Once configure has finished, type "make". Note that you must be using
+GNU make. SGI's make will not work.  Sun's probably won't either.
+You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
+
+To ensure that libffi is working as advertised, type "make test".
+
+To install the library and header files, type "make install".
+
+
+Using libffi
+============
+
+	The Basics
+	----------
+
+Libffi assumes that you have a pointer to the function you wish to
+call and that you know the number and types of arguments to pass it,
+as well as the return type of the function.
+
+The first thing you must do is create an ffi_cif object that matches
+the signature of the function you wish to call. The cif in ffi_cif
+stands for Call InterFace. To prepare a call interface object, use the
+following function:
+
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
+			unsigned int nargs, 
+			ffi_type *rtype, ffi_type **atypes);
+
+	CIF is a pointer to the call interface object you wish
+		to initialize.
+
+	ABI is an enum that specifies the calling convention 
+		to use for the call. FFI_DEFAULT_ABI defaults
+		to the system's native calling convention. Other
+		ABI's may be used with care. They are system
+		specific.
+
+	NARGS is the number of arguments this function accepts.	
+		libffi does not yet support vararg functions.
+
+	RTYPE is a pointer to an ffi_type structure that represents
+		the return type of the function. Ffi_type objects
+		describe the types of values. libffi provides
+		ffi_type objects for many of the native C types:
+		signed int, unsigned int, signed char, unsigned char,
+		etc. There is also a pointer ffi_type object and
+		a void ffi_type. Use &ffi_type_void for functions that 
+		don't return values.
+
+	ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
+		If NARGS is 0, this is ignored.
+
+
+ffi_prep_cif will return a status code that you are responsible 
+for checking. It will be one of the following:
+
+	FFI_OK - All is good.
+
+	FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
+		came across is bad.
+
+
+Before making the call, the VALUES vector should be initialized 
+with pointers to the appropriate argument values.
+
+To call the the function using the initialized ffi_cif, use the
+ffi_call function:
+
+void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
+
+	CIF is a pointer to the ffi_cif initialized specifically
+		for this function.
+
+	FN is a pointer to the function you want to call.
+
+	RVALUE is a pointer to a chunk of memory that is to hold the
+		result of the function call. Currently, it must be
+		at least one word in size (except for the n32 version
+		under Irix 6.x, which must be a pointer to an 8 byte 
+		aligned value (a long long). It must also be at least 
+		word aligned (depending on the return type, and the
+		system's alignment requirements). If RTYPE is 
+		&ffi_type_void, this is ignored. If RVALUE is NULL, 
+		the return value is discarded.
+
+	AVALUES is a vector of void* that point to the memory locations
+		holding the argument values for a call.
+		If NARGS is 0, this is ignored.
+
+
+If you are expecting a return value from FN it will have been stored
+at RVALUE.
+
+
+
+	An Example
+	----------
+
+Here is a trivial example that calls puts() a few times.
+
+    #include <stdio.h>
+    #include <ffi.h>
+    
+    int main()
+    {
+      ffi_cif cif;
+      ffi_type *args[1];
+      void *values[1];
+      char *s;
+      int rc;
+      
+      /* Initialize the argument info vectors */    
+      args[0] = &ffi_type_uint;
+      values[0] = &s;
+      
+      /* Initialize the cif */
+      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+    		       &ffi_type_uint, args) == FFI_OK)
+        {
+          s = "Hello World!";
+          ffi_call(&cif, puts, &rc, values);
+          /* rc now holds the result of the call to puts */
+          
+          /* values holds a pointer to the function's arg, so to 
+	     call puts() again all we need to do is change the 
+             value of s */
+          s = "This is cool!";
+          ffi_call(&cif, puts, &rc, values);
+        }
+      
+      return 0;
+    }
+
+
+
+	Aggregate Types
+	---------------
+
+Although libffi has no special support for unions or bit-fields, it is
+perfectly happy passing structures back and forth. You must first
+describe the structure to libffi by creating a new ffi_type object
+for it. Here is the definition of ffi_type:
+
+    typedef struct _ffi_type
+    {
+      unsigned size;
+      short alignment;
+      short type;
+      struct _ffi_type **elements;
+    } ffi_type;
+    
+All structures must have type set to FFI_TYPE_STRUCT.  You may set
+size and alignment to 0. These will be calculated and reset to the
+appropriate values by ffi_prep_cif().
+
+elements is a NULL terminated array of pointers to ffi_type objects
+that describe the type of the structure elements. These may, in turn,
+be structure elements.
+
+The following example initializes a ffi_type object representing the
+tm struct from Linux's time.h:
+
+				    struct tm {
+					int tm_sec;
+					int tm_min;
+					int tm_hour;
+					int tm_mday;
+					int tm_mon;
+					int tm_year;
+					int tm_wday;
+					int tm_yday;
+					int tm_isdst;
+					/* Those are for future use. */
+					long int __tm_gmtoff__;
+					__const char *__tm_zone__;
+				    };
+
+    {
+      ffi_type tm_type;
+      ffi_type *tm_type_elements[12];
+      int i;
+
+      tm_type.size = tm_type.alignment = 0;
+      tm_type.elements = &tm_type_elements;
+    
+      for (i = 0; i < 9; i++)
+          tm_type_elements[i] = &ffi_type_sint;
+
+      tm_type_elements[9] = &ffi_type_slong;
+      tm_type_elements[10] = &ffi_type_pointer;
+      tm_type_elements[11] = NULL;
+
+      /* tm_type can now be used to represent tm argument types and
+	 return types for ffi_prep_cif() */
+    }
+
+
+
+Platform Specific Notes
+=======================
+
+	Intel x86
+	---------
+
+There are no known problems with the x86 port.
+
+	Sun Sparc - SunOS 4.1.3 & Solaris 2.x
+	-------------------------------------
+
+There's a bug in the structure passing code for sparc processors.
+Struct arguments that are passed in value actually end up being passed
+by reference. This will be fixed Real Soon Now.
+
+"long long" values are not supported yet.
+
+You must use GNU Make to build libffi on Sun platforms.
+
+	MIPS - Irix 5.3 & 6.x
+	---------------------
+
+Irix 6.2 and better supports three different calling conventions: o32,
+n32 and n64. Currently, libffi only supports both o32 and n32 under
+Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
+configured for whichever calling convention it was built for.
+
+By default, the configure script will try to build libffi with the GNU
+development tools. To build libffi with the SGI development tools, set
+the environment variable CC to either "cc -32" or "cc -n32" before
+running configure under Irix 6.x (depending on whether you want an o32
+or n32 library), or just "cc" for Irix 5.3.
+
+With the n32 calling convention, when returning structures smaller
+than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
+Here's one way of forcing this:
+
+	double struct_storage[2];
+	my_small_struct *s = (my_small_struct *) struct_storage;  
+	/* Use s for RVALUE */
+
+If you don't do this you are liable to get spurious bus errors. 
+
+"long long" values are not supported yet.
+
+You must use GNU Make to build libffi on SGI platforms.
+
+	ARM - System V ABI
+	------------------
+
+The ARM port was performed on a NetWinder running ARM Linux ELF
+(2.0.31) and gcc 2.8.1.  config.sub still does not recognize the
+machine name sa110-unknown-linux-gnu (currently returned by
+NetWinder).  In the mean time the package can be configured by running
+'configure arm-linux'.
+
+
+
+	PowerPC System V ABI
+	--------------------
+
+There are two `System V ABI's which libffi implements for PowerPC.
+They differ only in how small structures are returned from functions.
+
+In the FFI_SYSV version, structures that are 8 bytes or smaller are
+returned in registers.  This is what GCC does when it is configured
+for solaris, and is what the System V ABI I have (dated September
+1995) says.
+
+In the FFI_GCC_SYSV version, all structures are returned the same way:
+by passing a pointer as the first argument to the function.  This is
+what GCC does when it is configured for linux or a generic sysv
+target.
+
+EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
+inconsistency with the SysV ABI: When a procedure is called with many
+floating-point arguments, some of them get put on the stack.  They are
+all supposed to be stored in double-precision format, even if they are
+only single-precision, but EGCS stores single-precision arguments as
+single-precision anyway.  This causes one test to fail (the `many
+arguments' test).
+
+
+History
+=======
+
+2.00 ???-??-01
+
+	Many configure improvements.  No more run tests required at
+        configure time so cross compiling should work well.  ffi.h is
+        target independent now and may be installed safely anywhere.
+        ffitest replaced with dejagnu testing infrastructure.  s390
+        port from ????.  ia64 port from Hans Boehm.  General
+        performance improvements.  Closures designed and implemented
+        by Kresten Krab Thorup and ported to ia64 and powerpc by Hans
+        Boehm and ???? respectively.
+
+1.20 Oct-5-98
+	Raffaele Sena produces ARM port.
+
+1.19 Oct-5-98
+	Fixed x86 long double and long long return support.
+	m68k bug fixes from Andreas Schwab.
+	Patch for DU assembler compatibility for the Alpha from Richard
+	Henderson.
+
+1.18 Apr-17-98
+	Bug fixes and MIPS configuration changes.
+
+1.17 Feb-24-98
+	Bug fixes and m68k port from Andreas Schwab. PowerPC port from
+	Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
+
+1.16 Feb-11-98
+	Richard Henderson produces Alpha port.
+
+1.15 Dec-4-97
+	Fixed an n32 ABI bug. New libtool, auto* support.
+
+1.14 May-13-97
+	libtool is now used to generate shared and static libraries.
+	Fixed a minor portability problem reported by Russ McManus
+	<[email protected]>.
+
+1.13 Dec-2-96
+	Added --enable-purify-safety to keep Purify from complaining
+	about certain low level code.
+	Sparc fix for calling functions with < 6 args.
+	Linux x86 a.out fix.
+
+1.12 Nov-22-96
+	Added missing ffi_type_void, needed for supporting void return 
+	types. Fixed test case for non MIPS machines. Cygnus Support 
+	is now Cygnus Solutions. 
+
+1.11 Oct-30-96
+	Added notes about GNU make.
+
+1.10 Oct-29-96
+	Added configuration fix for non GNU compilers.
+
+1.09 Oct-29-96
+	Added --enable-debug configure switch. Clean-ups based on LCLint 
+	feedback. ffi_mips.h is always installed. Many configuration 
+	fixes. Fixed ffitest.c for sparc builds.
+
+1.08 Oct-15-96
+	Fixed n32 problem. Many clean-ups.
+
+1.07 Oct-14-96
+	Gordon Irlam rewrites v8.S again. Bug fixes.
+
+1.06 Oct-14-96
+	Gordon Irlam improved the sparc port. 
+
+1.05 Oct-14-96
+	Interface changes based on feedback.
+
+1.04 Oct-11-96
+	Sparc port complete (modulo struct passing bug).
+
+1.03 Oct-10-96
+	Passing struct args, and returning struct values works for
+	all architectures/calling conventions. Expanded tests.
+
+1.02 Oct-9-96
+	Added SGI n32 support. Fixed bugs in both o32 and Linux support.
+	Added "make test".
+
+1.01 Oct-8-96
+	Fixed float passing bug in mips version. Restructured some
+	of the code. Builds cleanly with SGI tools.
+
+1.00 Oct-7-96
+	First release. No public announcement.
+
+
+Authors & Credits
+=================
+
+libffi was written by Anthony Green <[email protected]>.
+
+Portions of libffi were derived from Gianni Mariani's free gencall
+library for Silicon Graphics machines.
+
+The closure mechanism was designed and implemented on IA-32 by Kresten
+Krab Thorup.
+
+The initial Sparc port was derived from code contributed by the fine
+folks at Visible Decisions Inc.  Further enhancements were made by
+Gordon Irlam while at Cygnus Solutions.
+
+The Alpha port was written by Richard Henderson at Cygnus Solutions/Red Hat.
+
+Andreas Schwab ported libffi to m68k Linux and provided a number of
+bug fixes.
+
+Geoffrey Keating ported libffi to the PowerPC.
+
+Raffaele Sena ported libffi to the ARM.
+
+Hans Boehm ported libffi to IA-64.
+
+Jakub Jelinek ported libffi to 32- and 64-bit Sparc Linux.
+
+Jesper Skov and Andrew Haley both did more than their fair share of
+stepping through the code and tracking down bugs.
+
+Thanks also to Tom Tromey for bug fixes and configuration help.
+
+Thanks to Jim Blandy, who provided some useful feedback on the libffi
+interface.
+
+If you have a problem, or have found a bug, please send a note to
[email protected].

+ 12 - 0
libffi/acconfig.h

@@ -0,0 +1,12 @@
+/* Define this if you want extra debugging */
+#undef FFI_DEBUG
+
+/* Define this if you are using Purify and want to suppress 
+   spurious messages. */
+#undef USING_PURIFY
+
+/* Define this is you do not want support for aggregate types.  */
+#undef FFI_NO_STRUCTS
+
+/* Define this is you do not want support for the raw API.  */
+#undef FFI_NO_RAW_API

+ 97 - 0
libffi/acinclude.m4

@@ -0,0 +1,97 @@
+AC_DEFUN([AC_COMPILE_CHECK_SIZEOF],
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $1)
+AC_CACHE_VAL(AC_CV_NAME,
+[for ac_size in 4 8 1 2 16 12 $2 ; do # List sizes in rough order of prevalence.
+  AC_TRY_COMPILE([#include "confdefs.h"
+#include <sys/types.h>
+$2
+], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size)
+  if test x$AC_CV_NAME != x ; then break; fi
+done
+])
+if test x$AC_CV_NAME = x ; then
+  AC_MSG_ERROR([cannot determine a size for $1])
+fi
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1])
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
+
+
+AC_DEFUN([AC_C_BIGENDIAN_CROSS],
+[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian,
+[ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif], [# It does; now see whether it defined to BIG_ENDIAN or not.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)])
+if test $ac_cv_c_bigendian = unknown; then
+AC_TRY_RUN([main () {
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes,
+[ echo $ac_n "cross-compiling... " 2>&AC_FD_MSG ])
+fi])
+if test $ac_cv_c_bigendian = unknown; then
+AC_MSG_CHECKING(to probe for byte ordering)
+[
+cat >conftest.c <<EOF
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii() { char* s = (char*) ascii_mm; s = (char*) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic() { char* s = (char*) ebcdic_mm; s = (char*) ebcdic_ii; }
+int main() { _ascii (); _ebcdic (); return 0; }
+EOF
+] if test -f conftest.c ; then
+     if ${CC-cc} ${CFLAGS} conftest.c -o conftest.o && test -f conftest.o ; then
+        if test `grep -l BIGenDianSyS conftest.o` ; then
+           echo $ac_n ' big endian probe OK, ' 1>&AC_FD_MSG
+           ac_cv_c_bigendian=yes
+        fi
+        if test `grep -l LiTTleEnDian conftest.o` ; then
+           echo $ac_n ' little endian probe OK, ' 1>&AC_FD_MSG
+           if test $ac_cv_c_bigendian = yes ; then
+            ac_cv_c_bigendian=unknown;
+           else
+            ac_cv_c_bigendian=no
+           fi
+        fi
+        echo $ac_n 'guessing bigendian ...  ' >&AC_FD_MSG
+     fi
+  fi
+AC_MSG_RESULT($ac_cv_c_bigendian)
+fi
+if test $ac_cv_c_bigendian = yes; then
+  AC_DEFINE(WORDS_BIGENDIAN, 1, [whether byteorder is bigendian])
+  BYTEORDER=4321
+else
+  BYTEORDER=1234
+fi
+AC_DEFINE_UNQUOTED(BYTEORDER, $BYTEORDER, [1234 = LIL_ENDIAN, 4321 = BIGENDIAN])
+if test $ac_cv_c_bigendian = unknown; then
+  AC_MSG_ERROR(unknown endianess - sorry, please pre-set ac_cv_c_bigendian)
+fi
+])
+

+ 247 - 0
libffi/alpha/ffi.c

@@ -0,0 +1,247 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Cygnus Solutions
+   
+   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_private.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*SIZEOF_ARG)
+    cif->bytes = 6*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*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, SIZEOF_ARG) / 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.  */
+  asm volatile ("imb" : : : "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, SIZEOF_ARG) / 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;
+}

+ 278 - 0
libffi/alpha/osf.S

@@ -0,0 +1,278 @@
+/* -----------------------------------------------------------------------
+   osf.S - Copyright (c) 1998 Cygnus Solutions
+   
+   Alpha/OSF 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 <ffi.h>
+#include <ffi_private.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
+	addq	$16,$17,$1
+	mov	$16, $30
+	stq	$26, 0($1)
+	stq	$15, 8($1)
+	stq	$18, 16($1)
+	mov	$1, $15
+	.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
+
+	.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
+	ldgp	$29, 0($27)
+	subq	$30, 16*8, $30
+	stq	$26, 0($30)
+	.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
+
+	.end	ffi_closure_osf
+
+.section .rodata
+$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

+ 183 - 0
libffi/arm/ffi.c

@@ -0,0 +1,183 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998  Cygnus Solutions
+   
+   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_private.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 int tmp;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  tmp = 0;
+  argp = stack;
+
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
+    *(void **) argp = ecif->rvalue;
+    argp += 4;
+  }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0) && (avn != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
+	argp = (char *) ALIGN(argp, (*p_arg)->alignment);
+      }
+
+      if (avn != 0) 
+	{
+	  avn--;
+	  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;
+    }
+}

+ 111 - 0
libffi/arm/sysv.S

@@ -0,0 +1,111 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1998 Cygnus Solutions
+   
+   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 <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
+	
+.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
+	stfeqs  f0, [a3]
+	beq     epilogue
+
+# return DOUBLE or LONGDOUBLE
+	cmp     a4, #FFI_TYPE_DOUBLE
+	stfeqd  f0, [a3]
+
+epilogue:
+        ldmfd sp!, {a1-a4, fp, pc}
+
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+

+ 6 - 0
libffi/autogen.sh

@@ -0,0 +1,6 @@
+libtoolize --automake
+automake -a
+autoheader
+aclocal $ACLOCAL_FLAGS
+autoconf
+./configure $*

+ 849 - 0
libffi/config-ml.in

@@ -0,0 +1,849 @@
+# Configure fragment invoked in the post-target section for subdirs
+# wanting multilib support.
+#
+# It is advisable to support a few --enable/--disable options to let the
+# user select which libraries s/he really wants.
+#
+# Subdirectories wishing to use multilib should put the following lines
+# in the "post-target" section of configure.in.
+#
+# if [ "${srcdir}" = "." ] ; then
+#   if [ "${with_target_subdir}" != "." ] ; then
+#     . ${with_multisrctop}../../config-ml.in
+#   else
+#     . ${with_multisrctop}../config-ml.in
+#   fi
+# else
+#   . ${srcdir}/../config-ml.in
+# fi
+#
+#
+# Things are complicated because 6 separate cases must be handled:
+# 2 (native, cross) x 3 (absolute-path, relative-not-dot, dot) = 6.
+#
+# srcdir=. is special.  It must handle make programs that don't handle VPATH.
+# To implement this, a symlink tree is built for each library and for each
+# multilib subdir.
+#
+# The build tree is layed out as
+#
+# ./
+#   newlib
+#   m68020/
+#          newlib
+#          m68881/
+#                 newlib
+#
+# The nice feature about this arrangement is that inter-library references
+# in the build tree work without having to care where you are.  Note that
+# inter-library references also work in the source tree because symlink trees
+# are built when srcdir=.
+#
+# Unfortunately, trying to access the libraries in the build tree requires
+# the user to manually choose which library to use as GCC won't be able to
+# find the right one.  This is viewed as the lesser of two evils.
+#
+# Configure variables:
+# ${with_target_subdir} = "." for native, or ${target_alias} for cross.
+# Set by top level Makefile.
+# ${with_multisrctop} = how many levels of multilibs there are in the source
+# tree.  It exists to handle the case of configuring in the source tree:
+# ${srcdir} is not constant.
+# ${with_multisubdir} = name of multilib subdirectory (eg: m68020/m68881).
+#
+# Makefile variables:
+# MULTISRCTOP = number of multilib levels in source tree (+1 if cross)
+# (FIXME: note that this is different than ${with_multisrctop}.  Check out.).
+# MULTIBUILDTOP = number of multilib levels in build tree
+# MULTIDIRS = list of multilib subdirs (eg: m68000 m68020 ...)
+# (only defined in each library's main Makefile).
+# MULTISUBDIR = installed subdirectory name with leading '/' (eg: /m68000)
+# (only defined in each multilib subdir).
+
+# FIXME: Multilib is currently disabled by default for everything other than
+# newlib.  It is up to each target to turn on multilib support for the other
+# libraries as desired.
+
+# We have to handle being invoked by both Cygnus configure and Autoconf.
+#
+# Cygnus configure incoming variables:
+# srcdir, subdir, host, arguments
+#
+# Autoconf incoming variables:
+# srcdir, host, ac_configure_args
+#
+# We *could* figure srcdir and host out, but we'd have to do work that
+# our caller has already done to figure them out and requiring these two
+# seems reasonable.
+# Note that `host' in this case is GCC's `target'.  Target libraries are
+# configured for a particular host.
+
+if [ -n "${ac_configure_args}" ]; then
+  Makefile=${ac_file-Makefile}
+  ml_config_shell=${CONFIG_SHELL-/bin/sh}
+  ml_arguments="${ac_configure_args}"
+  ml_realsrcdir=${srcdir}
+else
+  Makefile=${Makefile-Makefile}
+  ml_config_shell=${config_shell-/bin/sh}
+  ml_arguments="${arguments}"
+  if [ -n "${subdir}" -a "${subdir}" != "." ] ; then
+    ml_realsrcdir=${srcdir}/${subdir}
+  else
+    ml_realsrcdir=${srcdir}
+  fi
+fi
+
+# Scan all the arguments and set all the ones we need.
+
+ml_verbose=--verbose
+for option in ${ml_arguments}
+do
+  case $option in
+  --*) ;;
+  -*) option=-$option ;;
+  esac
+
+  case $option in
+  --*=*)
+	optarg=`echo $option | sed -e 's/^[^=]*=//'`
+	;;
+  esac
+
+  case $option in
+  --disable-*)
+	enableopt=`echo ${option} | sed 's:^--disable-:enable_:;s:-:_:g'`
+	eval $enableopt=no
+	;;
+  --enable-*)
+	case "$option" in
+	*=*)	;;
+	*)	optarg=yes ;;
+	esac
+	enableopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'`
+	eval $enableopt="$optarg"
+	;;
+  --norecursion | --no*)
+	ml_norecursion=yes
+	;;
+  --silent | --sil* | --quiet | --q*)
+	ml_verbose=--silent
+	;;
+  --verbose | --v | --verb*)
+	ml_verbose=--verbose
+	;;
+  --with-*)
+	case "$option" in
+	*=*)	;;
+	*)	optarg=yes ;;
+	esac
+	withopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'`
+	eval $withopt="$optarg"
+	;;
+  --without-*)
+	withopt=`echo ${option} | sed 's:^--::;s:out::;s:-:_:g'`
+	eval $withopt=no
+	;;
+  esac
+done
+
+# Only do this if --enable-multilib.
+if [ "${enable_multilib}" = yes ]; then
+
+# Compute whether this is the library's top level directory
+# (ie: not a multilib subdirectory, and not a subdirectory like newlib/src).
+# ${with_multisubdir} tells us we're in the right branch, but we could be
+# in a subdir of that.
+# ??? The previous version could void this test by separating the process into
+# two files: one that only the library's toplevel configure.in ran (to
+# configure the multilib subdirs), and another that all configure.in's ran to
+# update the Makefile.  It seemed reasonable to collapse all multilib support
+# into one file, but it does leave us with having to perform this test.
+ml_toplevel_p=no
+if [ -z "${with_multisubdir}" ]; then
+  if [ "${srcdir}" = "." ]; then
+    # Use ${ml_realsrcdir} instead of ${srcdir} here to account for ${subdir}.
+    # ${with_target_subdir} = "." for native, otherwise target alias.
+    if [ "${with_target_subdir}" = "." ]; then
+      if [ -f ${ml_realsrcdir}/../config-ml.in ]; then
+	ml_toplevel_p=yes
+      fi
+    else
+      if [ -f ${ml_realsrcdir}/../../config-ml.in ]; then
+	ml_toplevel_p=yes
+      fi
+    fi
+  else
+    # Use ${ml_realsrcdir} instead of ${srcdir} here to account for ${subdir}.
+    if [ -f ${ml_realsrcdir}/../config-ml.in ]; then
+      ml_toplevel_p=yes
+    fi
+  fi
+fi
+
+# If this is the library's top level directory, set multidirs to the
+# multilib subdirs to support.  This lives at the top because we need
+# `multidirs' set right away.
+
+if [ "${ml_toplevel_p}" = yes ]; then
+
+multidirs=
+for i in `${CC-gcc} --print-multi-lib 2>/dev/null`; do
+  dir=`echo $i | sed -e 's/;.*$//'`
+  if [ "${dir}" = "." ]; then
+    true
+  else
+    if [ -z "${multidirs}" ]; then
+      multidirs="${dir}"
+    else
+      multidirs="${multidirs} ${dir}"
+    fi
+  fi
+done
+
+# Target libraries are configured for the host they run on, so we check
+# $host here, not $target.
+
+case "${host}" in
+arc-*-elf*)
+	if [ x$enable_biendian != xyes ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *be*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+arm-*-*)
+	if [ x"$enable_fpu" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *fpu*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_26bit" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *26bit*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_underscore" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *under*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_interwork" = xno ]
+	then
+	  old_multidirs=${multidirs}
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "${x}" in
+	      *interwork*) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_biendian = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *le* ) : ;;
+	      *be* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x"$enable_nofmult" = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *nofmult* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+m68*-*-*)
+	if [ x$enable_softfloat = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *soft-float* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_m68881 = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *m68881* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_m68000 = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *m68000* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_m68020 = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *m68020* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+mips*-*-*)
+	if [ x$enable_single_float = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *single* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_biendian = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *el* ) : ;;
+	      *eb* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_softfloat = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *soft-float* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	case " $multidirs " in
+	*" mabi=64 "*)
+	  # We will not be able to create libraries with -mabi=64 if
+	  # we cannot even link a trivial program.  It usually
+	  # indicates the 64bit libraries are missing.
+	  if echo 'main() {}' > conftest.c &&
+	     ${CC-gcc} -mabi=64 conftest.c -o conftest; then
+	    :
+	  else
+	    echo Could not link program with -mabi=64, disabling it.
+	    old_multidirs="${multidirs}"
+	    multidirs=""
+	    for x in ${old_multidirs}; do
+	      case "$x" in
+	      *mabi=64* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	      esac
+	    done
+	  fi
+	  rm -f conftest.c conftest
+	  ;;
+	esac
+	;;
+powerpc*-*-* | rs6000*-*-*)
+	if [ x$enable_softfloat = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *soft-float* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_powercpu = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      power | */power | */power/* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_powerpccpu = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *powerpc* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_powerpcos = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *mcall-linux* | *mcall-solaris* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_biendian = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *mlittle* | *mbig* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_sysv = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *mcall-sysv* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	if [ x$enable_aix = xno ]
+	then
+	  old_multidirs="${multidirs}"
+	  multidirs=""
+	  for x in ${old_multidirs}; do
+	    case "$x" in
+	      *mcall-aix* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	    esac
+	  done
+	fi
+	;;
+sparc*-*-*)
+	case " $multidirs " in
+	*" m64 "*)
+	  # We will not be able to create libraries with -m64 if
+	  # we cannot even link a trivial program.  It usually
+	  # indicates the 64bit libraries are missing.
+	  if echo 'main() {}' > conftest.c &&
+	     ${CC-gcc} -m64 conftest.c -o conftest; then
+	    :
+	  else
+	    echo Could not link program with -m64, disabling it.
+	    old_multidirs="${multidirs}"
+	    multidirs=""
+	    for x in ${old_multidirs}; do
+	      case "$x" in
+	      *m64* ) : ;;
+	      *) multidirs="${multidirs} ${x}" ;;
+	      esac
+	    done
+	  fi
+	  rm -f conftest.c conftest
+	  ;;
+	esac
+	;;
+esac
+
+# Remove extraneous blanks from multidirs.
+# Tests like `if [ -n "$multidirs" ]' require it.
+multidirs=`echo "$multidirs" | sed -e 's/^[ ][ ]*//' -e 's/[ ][ ]*$//' -e 's/[ ][ ]*/ /g'`
+
+# Add code to library's top level makefile to handle building the multilib
+# subdirs.
+
+cat > Multi.tem <<\EOF
+
+# FIXME: There should be an @-sign in front of the `if'.
+# Leave out until this is tested a bit more.
+multi-do:
+	if [ -z "$(MULTIDIRS)" ]; then \
+	  true; \
+	else \
+	  rootpre=`pwd`/; export rootpre; \
+	  srcrootpre=`cd $(srcdir); pwd`/; export srcrootpre; \
+	  lib=`echo $${rootpre} | sed -e 's,^.*/\([^/][^/]*\)/$$,\1,'`; \
+	  compiler="$(CC)"; \
+	  for i in `$${compiler} --print-multi-lib 2>/dev/null`; do \
+	    dir=`echo $$i | sed -e 's/;.*$$//'`; \
+	    if [ "$${dir}" = "." ]; then \
+	      true; \
+	    else \
+	      if [ -d ../$${dir}/$${lib} ]; then \
+		flags=`echo $$i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \
+		if (cd ../$${dir}/$${lib}; $(MAKE) $(FLAGS_TO_PASS) \
+				CFLAGS="$(CFLAGS) $${flags}" \
+				prefix="$(prefix)" \
+				exec_prefix="$(exec_prefix)" \
+				GCJFLAGS="$(GCJFLAGS) $${flags}" \
+				CXXFLAGS="$(CXXFLAGS) $${flags}" \
+				LIBCFLAGS="$(LIBCFLAGS) $${flags}" \
+				LIBCXXFLAGS="$(LIBCXXFLAGS) $${flags}" \
+				LDFLAGS="$(LDFLAGS) $${flags}" \
+				$(DO)); then \
+		  true; \
+		else \
+		  exit 1; \
+		fi; \
+	      else true; \
+	      fi; \
+	    fi; \
+	  done; \
+	fi
+
+# FIXME: There should be an @-sign in front of the `if'.
+# Leave out until this is tested a bit more.
+multi-clean:
+	if [ -z "$(MULTIDIRS)" ]; then \
+	  true; \
+	else \
+	  lib=`pwd | sed -e 's,^.*/\([^/][^/]*\)$$,\1,'`; \
+	  for dir in Makefile $(MULTIDIRS); do \
+	    if [ -f ../$${dir}/$${lib}/Makefile ]; then \
+	      if (cd ../$${dir}/$${lib}; $(MAKE) $(FLAGS_TO_PASS) $(DO)); \
+	      then true; \
+	      else exit 1; \
+	      fi; \
+	    else true; \
+	    fi; \
+	  done; \
+	fi
+EOF
+
+cat ${Makefile} Multi.tem > Makefile.tem
+rm -f ${Makefile} Multi.tem
+mv Makefile.tem ${Makefile}
+
+fi # ${ml_toplevel_p} = yes
+
+if [ "${ml_verbose}" = --verbose ]; then
+  echo "Adding multilib support to Makefile in ${ml_realsrcdir}"
+  if [ "${ml_toplevel_p}" = yes ]; then
+    echo "multidirs=${multidirs}"
+  fi
+  echo "with_multisubdir=${with_multisubdir}"
+fi
+
+if [ "${srcdir}" = "." ]; then
+  if [ "${with_target_subdir}" != "." ]; then
+    ml_srcdotdot="../"
+  else
+    ml_srcdotdot=""
+  fi
+else
+  ml_srcdotdot=""
+fi
+
+if [ -z "${with_multisubdir}" ]; then
+  ml_subdir=
+  ml_builddotdot=
+  : # ml_srcdotdot= # already set
+else
+  ml_subdir="/${with_multisubdir}"
+  # The '[^/][^/]*' appears that way to work around a SunOS sed bug.
+  ml_builddotdot=`echo ${with_multisubdir} | sed -e 's:[^/][^/]*:..:g'`/
+  if [ "$srcdir" = "." ]; then
+    ml_srcdotdot=${ml_srcdotdot}${ml_builddotdot}
+  else
+    : # ml_srcdotdot= # already set
+  fi
+fi
+
+if [ "${ml_toplevel_p}" = yes ]; then
+  ml_do='$(MAKE)'
+  ml_clean='$(MAKE)'
+else
+  ml_do=true
+  ml_clean=true
+fi
+
+# TOP is used by newlib and should not be used elsewhere for this purpose.
+# MULTI{SRC,BUILD}TOP are the proper ones to use.  MULTISRCTOP is empty
+# when srcdir != builddir.  MULTIBUILDTOP is always some number of ../'s.
+# FIXME: newlib needs to be updated to use MULTI{SRC,BUILD}TOP so we can
+# delete TOP.  Newlib may wish to continue to use TOP for its own purposes
+# of course.
+# MULTIDIRS is non-empty for the cpu top level Makefile (eg: newlib/Makefile)
+# and lists the subdirectories to recurse into.
+# MULTISUBDIR is non-empty in each cpu subdirectory's Makefile
+# (eg: newlib/h8300h/Makefile) and is the installed subdirectory name with
+# a leading '/'.
+# MULTIDO is used for targets like all, install, and check where
+# $(FLAGS_TO_PASS) augmented with the subdir's compiler option is needed.
+# MULTICLEAN is used for the *clean targets.
+#
+# ??? It is possible to merge MULTIDO and MULTICLEAN into one.  They are
+# currently kept separate because we don't want the *clean targets to require
+# the existence of the compiler (which MULTIDO currently requires) and
+# therefore we'd have to record the directory options as well as names
+# (currently we just record the names and use --print-multi-lib to get the
+# options).
+
+sed -e "s:^TOP[ 	]*=[ 	]*\([./]*\)[ 	]*$:TOP = ${ml_builddotdot}\1:" \
+    -e "s:^MULTISRCTOP[ 	]*=.*$:MULTISRCTOP = ${ml_srcdotdot}:" \
+    -e "s:^MULTIBUILDTOP[ 	]*=.*$:MULTIBUILDTOP = ${ml_builddotdot}:" \
+    -e "s:^MULTIDIRS[ 	]*=.*$:MULTIDIRS = ${multidirs}:" \
+    -e "s:^MULTISUBDIR[ 	]*=.*$:MULTISUBDIR = ${ml_subdir}:" \
+    -e "s:^MULTIDO[ 	]*=.*$:MULTIDO = $ml_do:" \
+    -e "s:^MULTICLEAN[ 	]*=.*$:MULTICLEAN = $ml_clean:" \
+	${Makefile} > Makefile.tem
+rm -f ${Makefile}
+mv Makefile.tem ${Makefile}
+
+# If this is the library's top level, configure each multilib subdir.
+# This is done at the end because this is the loop that runs configure
+# in each multilib subdir and it seemed reasonable to finish updating the
+# Makefile before going on to configure the subdirs.
+
+if [ "${ml_toplevel_p}" = yes ]; then
+
+# We must freshly configure each subdirectory.  This bit of code is
+# actually partially stolen from the main configure script.  FIXME.
+
+if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
+
+  if [ "${ml_verbose}" = --verbose ]; then
+    echo "Running configure in multilib subdirs ${multidirs}"
+    echo "pwd: `pwd`"
+  fi
+
+  ml_origdir=`pwd`
+  ml_libdir=`echo $ml_origdir | sed -e 's,^.*/,,'`
+  # cd to top-level-build-dir/${with_target_subdir}
+  cd ..
+
+  for ml_dir in ${multidirs}; do
+
+    if [ "${ml_verbose}" = --verbose ]; then
+      echo "Running configure in multilib subdir ${ml_dir}"
+      echo "pwd: `pwd`"
+    fi
+
+    if [ -d ${ml_dir} ]; then true; else
+      # ``mkdir -p ${ml_dir}'' See also mkinstalldirs.
+      pathcomp=""
+      for d in `echo ":${ml_dir}" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`; do
+        pathcomp="$pathcomp$d"
+        case "$pathcomp" in
+          -* ) pathcomp=./$pathcomp ;;
+        esac
+        if test ! -d "$pathcomp"; then
+           echo "mkdir $pathcomp" 1>&2
+           mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
+        fi
+        if test ! -d "$pathcomp"; then
+	   exit $lasterr
+        fi
+        pathcomp="$pathcomp/"
+      done
+    fi
+    if [ -d ${ml_dir}/${ml_libdir} ]; then true; else mkdir ${ml_dir}/${ml_libdir}; fi
+
+    # Eg: if ${ml_dir} = m68000/m68881, dotdot = ../../
+    dotdot=../`echo ${ml_dir} | sed -e 's|[^/]||g' -e 's|/|../|g'`
+
+    case ${srcdir} in
+    ".")
+      echo Building symlink tree in `pwd`/${ml_dir}/${ml_libdir}
+      if [ "${with_target_subdir}" != "." ]; then
+	ml_unsubdir="../"
+      else
+	ml_unsubdir=""
+      fi
+      (cd ${ml_dir}/${ml_libdir};
+       ../${dotdot}${ml_unsubdir}symlink-tree ../${dotdot}${ml_unsubdir}${ml_libdir} "")
+      if [ -f ${ml_dir}/${ml_libdir}/Makefile ]; then
+	if [ x"${MAKE}" = x ]; then
+	  (cd ${ml_dir}/${ml_libdir}; make distclean)
+	else
+	  (cd ${ml_dir}/${ml_libdir}; ${MAKE} distclean)
+	fi
+      fi
+      ml_newsrcdir="."
+      ml_srcdiroption=
+      multisrctop=${dotdot}
+      ;;
+    *)
+      case "${srcdir}" in
+      /* | [A-Za-z]:[\\/]* ) # absolute path
+        ml_newsrcdir=${srcdir}
+        ;;
+      *) # otherwise relative
+        ml_newsrcdir=${dotdot}${srcdir}
+        ;;
+      esac
+      ml_srcdiroption="-srcdir=${ml_newsrcdir}"
+      multisrctop=
+      ;;
+    esac
+
+    case "${progname}" in
+    /* | [A-Za-z]:[\\/]* )     ml_recprog=${progname} ;;
+    *)      ml_recprog=${dotdot}${progname} ;;
+    esac
+
+    # FIXME: POPDIR=${PWD=`pwd`} doesn't work here.
+    ML_POPDIR=`pwd`
+    cd ${ml_dir}/${ml_libdir}
+
+    if [ -f ${ml_newsrcdir}/configure ]; then
+      ml_recprog="${ml_newsrcdir}/configure --cache-file=../config.cache"
+    fi
+
+    # find compiler flag corresponding to ${ml_dir}
+    for i in `${CC-gcc} --print-multi-lib 2>/dev/null`; do 
+      dir=`echo $i | sed -e 's/;.*$//'`
+      if [ "${dir}" = "${ml_dir}" ]; then
+        flags=`echo $i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`
+        break
+      fi
+    done
+    ml_config_env='CC="${CC_}$flags" CXX="${CXX_}$flags" GCJ="${GCJ_}$flags"'
+
+    if [ "${with_target_subdir}" = "." ]; then
+	CC_=$CC' '
+	CXX_=$CXX' '
+	GCJ_=$GCJ' '
+    else
+	# Create a regular expression that matches any string as long
+	# as ML_POPDIR.
+	popdir_rx=`echo ${ML_POPDIR} | sed 's,.,.,g'`
+	CC_=
+	for arg in ${CC}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    CC_="${CC_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    CC_="${CC_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    CC_="${CC_}${arg} " ;;
+	  esac
+	done
+
+	CXX_=
+	for arg in ${CXX}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    CXX_="${CXX_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    CXX_="${CXX_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    CXX_="${CXX_}${arg} " ;;
+	  esac
+	done
+
+	GCJ_=
+	for arg in ${GCJ}; do
+	  case $arg in
+	  -[BIL]"${ML_POPDIR}"/*)
+	    GCJ_="${GCJ_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  "${ML_POPDIR}"/*)
+	    GCJ_="${GCJ_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
+	  *)
+	    GCJ_="${GCJ_}${arg} " ;;
+	  esac
+	done
+
+	if test "x${LD_LIBRARY_PATH+set}" = xset; then
+	  LD_LIBRARY_PATH_=
+	  for arg in `echo "$LD_LIBRARY_PATH" | tr ':' ' '`; do
+	    case "$arg" in
+	    "${ML_POPDIR}"/*)
+	      arg=`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`
+	      ;;
+	    esac
+	    if test "x$LD_LIBRARY_PATH_" != x; then
+	      LD_LIBRARY_PATH_=$LD_LIBRARY_PATH_:$arg
+	    else
+	      LD_LIBRARY_PATH_=$arg
+	    fi
+          done
+	  ml_config_env="$ml_config_env LD_LIBRARY_PATH=$LD_LIBRARY_PATH_"
+	fi
+
+	if test "x${SHLIB_PATH+set}" = xset; then
+	  SHLIB_PATH_=
+	  for arg in `echo "$SHLIB_PATH" | tr ':' ' '`; do
+	    case "$arg" in
+	    "${ML_POPDIR}"/*)
+	      arg=`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`
+	      ;;
+	    esac
+	    if test "x$SHLIB_PATH_" != x; then
+	      SHLIB_PATH_=$SHLIB_PATH_:$arg
+	    else
+	      SHLIB_PATH_=$arg
+	    fi
+          done
+	  ml_config_env="$ml_config_env SHLIB_PATH=$SHLIB_PATH_"
+	fi
+    fi
+
+    if eval ${ml_config_env} ${ml_config_shell} ${ml_recprog} \
+	--with-multisubdir=${ml_dir} --with-multisrctop=${multisrctop} \
+	${ml_arguments} ${ml_srcdiroption} ; then
+      true
+    else
+      exit 1
+    fi
+
+    cd ${ML_POPDIR}
+
+  done
+
+  cd ${ml_origdir}
+fi
+
+fi # ${ml_toplevel_p} = yes
+fi # ${enable_multilib} = yes

+ 167 - 0
libffi/configure.in

@@ -0,0 +1,167 @@
+dnl Process this with autoconf to create configure
+AC_INIT(fficonfig.h.in)
+AM_CONFIG_HEADER(fficonfig.h)
+
+dnl Default to --enable-multilib
+AC_ARG_ENABLE(multilib,
+[  --enable-multilib       build many library versions (default)],
+[case "${enableval}" in
+  yes) multilib=yes ;;
+  no)  multilib=no ;;
+  *)   AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
+ esac], [multilib=yes])dnl
+
+dnl We may get other options which we don't document:
+dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
+
+### I don't understand this, so comment it out for now
+#if test "${srcdir}" = "."; then
+#  if test "${with_target_subdir}" != "."; then
+#    libffi_basedir="${srcdir}/${with_multisrctop}.."
+#  else
+#    libffi_basedir="${srcdir}/${with_multisrctop}"
+#  fi
+#else
+  libffi_basedir="${srcdir}"
+#fi
+AC_SUBST(libffi_basedir)
+
+AC_CANONICAL_HOST
+
+AM_INIT_AUTOMAKE(libffi,2.00-beta,no-define)
+
+AC_EXEEXT
+AM_MAINTAINER_MODE
+
+AC_PROG_CC
+AC_PROG_LIBTOOL
+AM_PROG_LIBTOOL
+AC_PROG_LN_S
+
+dnl The -no-testsuite modules omit the test subdir.
+AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
+
+TARGET="unknown"
+case "$host" in
+  alpha*-*-linux* | alpha*-*-osf*)
+	TARGET=ALPHA;
+	$LN_S ${srcdir}/alpha/ffi.c t-ffi.c;
+	$LN_S $srcdir/alpha/osf.S t-asm.S;;
+  arm*-*-linux-*)
+	TARGET=ARM;
+	$LN_S $srcdir/arm/ffi.c t-ffi.c;
+	$LN_S $srcdir/arm/ffi.S t-asm.S;;
+  i*86-*-beos*|i*86-*-freebsd*|i*86-*-linux*|i*86-*-solaris*)
+	TARGET=X86; 
+	$LN_S $srcdir/x86/ffi.c t-ffi.c;
+	$LN_S $srcdir/x86/sysv.S t-asm.S;;
+  i*86-*-cygwin*|i*86-*-mingw*|i*86-*-win32*)
+	TARGET=X86_WIN32;
+	$LN_S $srcdir/x86/ffi.c t-ffi.c;
+	$LN_S $srcdir/x86/win32.S t-asm.S;;
+  ia64*-*-*)
+	TARGET=IA64;
+	$LN_S $srcdir/ia64/ffi.c t-ffi.c;
+	$LN_S $srcdir/ia64/unix.S t-asm.S;;
+  m68k-*-linux*)
+	TARGET=M68K;
+	$LN_S $srcdir/m68k/ffi.c t-ffi.c;
+	$LN_S $srcdir/m68k/unix.S t-asm.S;;
+  mips-*-elf)
+	TARGET=MIPS;
+	$LN_S $srcdir/mips/ffi.c t-ffi.c;
+	$LN_S $srcdir/mips/o32.S t-asm.S;;
+  mips-sgi-irix5.*)
+	TARGET=MIPS;
+	$LN_S $srcdir/mips/ffi.c t-ffi.c;
+	$LN_S $srcdir/mips/o32.S t-asm.S;;
+  mips-sgi-irix6.*)
+	TARGET=MIPS;
+	$LN_S $srcdir/mips/ffi.c t-ffi.c;
+	$LN_S $srcdir/mips/n32.S t-asm.S;;
+  powerpc-*-linux* | powerpc-*-sysv* | powerpc-*-beos*) 
+	TARGET=POWERPC;
+	$LN_S $srcdir/powerpc/ffi.c t-ffi.c;
+	$LN_S $srcdir/powerpc/sysv.S t-asm.S;;
+  s390-*-linux*)
+	TARGET=S390;
+	$LN_S $srcdir/s390/ffi.c t-ffi.c;
+	$LN_S $srcdir/s390/v8.S t-asm.S;;
+  sparc-*-linux*|sparc-sun-*)
+	TARGET=SPARC;
+	$LN_S $srcdir/sparc/ffi.c t-ffi.c;
+	$LN_S $srcdir/sparc/v8.S t-asm.S;;
+  sparc64-*-linux*)
+	TARGET=SPARC;
+	$LN_S $srcdir/sparc/ffi.c t-ffi.c;
+	$LN_S $srcdir/sparc/v9.S t-asm.S;;
+esac
+
+AC_SUBST(AM_RUNTESTFLAGS)
+
+if test ${TARGET} = unknown; then
+  AC_ERROR("libffi has not been ported to $host.")
+fi
+
+AC_HEADER_STDC
+AC_CHECK_FUNCS(memcpy)
+AC_FUNC_ALLOCA
+
+dnl AC_CHECK_SIZEOF(char)
+AC_COMPILE_CHECK_SIZEOF(short)
+AC_COMPILE_CHECK_SIZEOF(int)
+AC_COMPILE_CHECK_SIZEOF(long)
+AC_COMPILE_CHECK_SIZEOF(long long)
+AC_COMPILE_CHECK_SIZEOF(float)
+AC_COMPILE_CHECK_SIZEOF(double)
+AC_COMPILE_CHECK_SIZEOF(long double)
+
+AC_COMPILE_CHECK_SIZEOF(void *)
+AC_C_BIGENDIAN_CROSS
+
+AC_SUBST(TARGET)
+AC_SUBST(TARGETDIR)
+
+AC_SUBST(SHELL)
+
+AC_ARG_ENABLE(debug,[  --enable-debug          debugging mode], AC_DEFINE(FFI_DEBUG))
+
+AC_ARG_ENABLE(debug,[  --disable-structs       omit code for struct support], AC_DEFINE(FFI_NO_STRUCTS))
+
+AC_ARG_ENABLE(debug,[  --disable-raw-api       make the raw api unavailable], AC_DEFINE(FFI_NO_RAW_API))
+
+AC_ARG_ENABLE(purify-safety,
+[  --enable-purify-safety  purify-safe mode], AC_DEFINE(USING_PURIFY))
+
+AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+AC_OUTPUT(include/Makefile testsuite/Makefile Makefile,
+[
+if test -n "$CONFIG_FILES"; then
+   ac_file=Makefile . ${libffi_basedir}/config-ml.in
+fi
+],
+srcdir=${srcdir}
+host=${host}
+target=${target}
+with_multisubdir=${with_multisubdir}
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+libffi_basedir=${libffi_basedir}
+CC="${CC}"
+DEFS="$DEFS"
+test ! -d include && mkdir include
+test ! -f include/fficonfig.h && cp fficonfig.h include/fficonfig.h
+if cmp -s fficonfig.h include/fficonfig.h 2>/dev/null; then 
+	echo fficonfig.h unchanged
+else
+	echo Moving fficonfig.h to include/fficonfig.h
+	cp fficonfig.h include/fficonfig.h
+fi
+)

+ 65 - 0
libffi/debug.c

@@ -0,0 +1,65 @@
+/* -----------------------------------------------------------------------
+   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 RED HAT 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_private.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 */
+
+int ffi_assert(char *file, int line)
+{
+  fprintf(stderr, "ASSERTION FAILURE: %s line %d\n", file, line);
+  ffi_stop_here();
+  abort();
+
+  /* This has to return something for the compiler not to complain */
+  /*@notreached@*/
+  return 0;
+}
+
+/* Perform a sanity check on an ffi_type structure */
+
+bool ffi_type_test(ffi_type *a)
+{
+  /*@-usedef@*/
+  FFI_ASSERT(a->type <= FFI_TYPE_LAST);
+  FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->size > 0 : 1);
+  FFI_ASSERT(a->type > FFI_TYPE_VOID ? a->alignment > 0 : 1);
+  FFI_ASSERT(a->type == FFI_TYPE_STRUCT ? a->elements != NULL : 1);
+  /*@=usedef@*/
+
+  /* This is a silly thing to return, but it keeps the compiler from
+     issuing warnings about "a" not being used in non-debug builds. */
+  return (a != NULL);
+}

+ 736 - 0
libffi/ffitest.c

@@ -0,0 +1,736 @@
+/* -----------------------------------------------------------------------
+   ffitest.c - Copyright (c) 1996, 1997, 1998  Cygnus Solutions
+
+   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 RED HAT 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+/* This is lame. Long double support is barely there under SunOS 4.x  */
+#if defined(__sparc__) && (SIZEOF_LONG_DOUBLE != 16)
+#define BROKEN_LONG_DOUBLE
+#endif
+
+#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0 
+
+static int fail(char *file, int line)
+{
+  fprintf(stderr, "Test failure: %s line %d\n", file, line);
+  exit(EXIT_FAILURE);
+  /*@notreached@*/
+  return 0;
+}
+
+#define MAX_ARGS 256
+
+static size_t my_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+static int promotion(signed char sc, signed short ss, 
+		     unsigned char uc, unsigned short us)
+{
+  int r = (int) sc + (int) ss + (int) uc + (int) us;
+
+  return r;
+}
+
+static signed char return_sc(signed char sc)
+{
+  return sc;
+}
+
+static unsigned char return_uc(unsigned char uc)
+{
+  return uc;
+}
+
+static long long return_ll(long long ll)
+{
+  return ll;
+}
+
+static int floating(int a, float b, double c, long double d, int e)
+{
+  int i;
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+  printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
+#endif
+
+  i = (int) ((float)a/b + ((float)c/(float)d));
+
+  return i;
+}
+
+static float many(float f1,
+		  float f2,
+		  float f3,
+		  float f4,
+		  float f5,
+		  float f6,
+		  float f7,
+		  float f8,
+		  float f9,
+		  float f10,
+		  float f11,
+		  float f12,
+		  float f13)
+{
+#if 0
+  printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+	 (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, 
+	 (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+	 (double) f11, (double) f12, (double) f13);
+#endif
+
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+static double dblit(float f)
+{
+  return f/3.0;
+}
+
+static long double ldblit(float f)
+{
+  return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+typedef struct
+{
+  double d1;
+  double d2;
+} test_structure_2;
+
+typedef struct
+{
+  int si;
+} test_structure_3;
+
+typedef struct
+{
+  unsigned ui1;
+  unsigned ui2;
+  unsigned ui3;
+} test_structure_4;
+
+typedef struct
+{
+  char c1;
+  char c2;
+} test_structure_5;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  /*@-type@*/
+  ts.uc++;
+  /*@=type@*/
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+static test_structure_2 struct2(test_structure_2 ts)
+{
+  ts.d1--;
+  ts.d2--;
+
+  return ts;
+}
+
+static test_structure_3 struct3(test_structure_3 ts)
+{
+  ts.si = -(ts.si*2);
+
+  return ts;
+}
+
+static test_structure_4 struct4(test_structure_4 ts)
+{
+  ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
+
+  return ts;
+}
+
+static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
+{
+  ts1.c1 += ts2.c1;
+  ts1.c2 -= ts2.c2;
+
+  return ts1;
+}
+
+/* Take an int and a float argument, together with int userdata, and 	*/
+/* return the sum.							*/
+static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
+{
+    *(int*)resp =
+	 *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
+}
+
+typedef int (*closure_test_type)(int, float);
+
+int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  char *s;
+  signed char sc;
+  unsigned char uc;
+  signed short ss;
+  unsigned short us;
+  unsigned long ul;
+  long long ll;
+  float f;
+  double d;
+  long double ld;
+  signed int si1;
+  signed int si2;
+
+#if defined(__alpha__) || defined(IA64) || defined(SPARC64) || (defined(__mips__) && (_MIPS_SIM == _ABIN32))
+  long long rint;
+#else
+  int rint;
+#endif
+  long long rlonglong;
+
+  ffi_type ts1_type;
+  ffi_type ts2_type;
+  ffi_type ts3_type;
+  ffi_type ts4_type;  
+  ffi_type ts5_type;
+  ffi_type *ts1_type_elements[4];
+  ffi_type *ts2_type_elements[3];
+  ffi_type *ts3_type_elements[2];
+  ffi_type *ts4_type_elements[4];
+  ffi_type *ts5_type_elements[3];
+
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+
+  ts2_type.size = 0;
+  ts2_type.alignment = 0;
+  ts2_type.type = FFI_TYPE_STRUCT;
+
+  ts3_type.size = 0;
+  ts3_type.alignment = 0;
+  ts3_type.type = FFI_TYPE_STRUCT;
+
+  ts4_type.size = 0;
+  ts4_type.alignment = 0;
+  ts4_type.type = FFI_TYPE_STRUCT;
+
+  ts5_type.size = 0;
+  ts5_type.alignment = 0;
+  ts5_type.type = FFI_TYPE_STRUCT;
+
+  /*@-immediatetrans@*/
+  ts1_type.elements = ts1_type_elements;
+  ts2_type.elements = ts2_type_elements;
+  ts3_type.elements = ts3_type_elements;
+  ts4_type.elements = ts4_type_elements;
+  ts5_type.elements = ts5_type_elements;
+  /*@=immediatetrans@*/
+  
+  ts1_type_elements[0] = &ffi_type_uchar;
+  ts1_type_elements[1] = &ffi_type_double;
+  ts1_type_elements[2] = &ffi_type_uint;
+  ts1_type_elements[3] = NULL;
+  
+  ts2_type_elements[0] = &ffi_type_double;
+  ts2_type_elements[1] = &ffi_type_double;
+  ts2_type_elements[2] = NULL;
+
+  ts3_type_elements[0] = &ffi_type_sint;
+  ts3_type_elements[1] = NULL;
+
+  ts4_type_elements[0] = &ffi_type_uint;
+  ts4_type_elements[1] = &ffi_type_uint;
+  ts4_type_elements[2] = &ffi_type_uint;
+  ts4_type_elements[3] = NULL;
+
+  ts5_type_elements[0] = &ffi_type_schar;
+  ts5_type_elements[1] = &ffi_type_schar;
+  ts5_type_elements[2] = NULL;
+
+  ul = 0;
+
+  /* return value tests */
+  {
+#if defined(__mips__) /* || defined(ARM) */
+    puts ("long long tests not run. This is a known bug on this architecture.");
+#else
+    args[0] = &ffi_type_sint64;
+    values[0] = &ll;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ffi_type_sint64, args) == FFI_OK);
+
+    for (ll = 0LL; ll < 100LL; ll++)
+      {
+	ul++;
+	ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+	CHECK(rlonglong == ll);
+      }
+
+    for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+      {
+	ul++;
+	ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+	CHECK(rlonglong == ll);
+      }
+#endif
+
+    args[0] = &ffi_type_schar;
+    values[0] = &sc;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ffi_type_schar, args) == FFI_OK);
+
+    for (sc = (signed char) -127; 
+	 sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
+      {
+	ul++;
+	ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+	CHECK(rint == (int) sc);
+      }
+
+    args[0] = &ffi_type_uchar;
+    values[0] = &uc;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ffi_type_uchar, args) == FFI_OK);
+
+    for (uc = (unsigned char) '\x00'; 
+	 uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
+      {
+	ul++;
+	ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+	CHECK(rint == (signed int) uc);
+      }
+
+    printf("%lu return value tests run\n", ul);
+  }
+
+#ifdef BROKEN_LONG_DOUBLE
+  printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
+#else
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_float;
+    values[0] = &f;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ffi_type_longdouble, args) == FFI_OK);
+
+    f = 3.14159;
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+    printf ("%Lf\n", ldblit(f));
+#endif
+    ld = 666;
+    ffi_call(&cif, FFI_FN(ldblit), &ld, values);
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+    printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
+#endif
+
+    /* These are not always the same!! Check for a reasonable delta */
+    /*@-realcompare@*/
+    if (ld - ldblit(f) < LDBL_EPSILON)
+    /*@=realcompare@*/
+	puts("long double return value tests ok!");
+    else
+        CHECK(0);
+  }
+
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_sint;
+    values[0] = &si1;
+    args[1] = &ffi_type_float;
+    values[1] = &f;
+    args[2] = &ffi_type_double;
+    values[2] = &d;
+    args[3] = &ffi_type_longdouble;
+    values[3] = &ld;
+    args[4] = &ffi_type_sint;
+    values[4] = &si2;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
+		       &ffi_type_sint, args) == FFI_OK);
+
+    si1 = 6;
+    f = 3.14159;
+    d = (double)1.0/(double)3.0;
+    ld = 2.71828182846L;
+    si2 = 10;
+
+    floating (si1, f, d, ld, si2);
+
+    ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+    printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
+
+    CHECK(rint == floating(si1, f, d, ld, si2));
+
+    printf("float arg tests ok!\n");
+  }
+#endif
+
+  /* strlen tests */
+  {
+    args[0] = &ffi_type_pointer;
+    values[0] = (void*) &s;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ffi_type_sint, args) == FFI_OK);
+
+    s = "a";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 1);
+
+    s = "1234567";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 7);
+
+    s = "1234567890123456789012345";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 25);
+
+    printf("strlen tests passed\n");
+  }
+
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_float;
+    values[0] = &f;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ffi_type_double, args) == FFI_OK);
+
+    f = 3.14159;
+
+    ffi_call(&cif, FFI_FN(dblit), &d, values);
+
+    /* These are not always the same!! Check for a reasonable delta */
+    /*@-realcompare@*/
+    CHECK(d - dblit(f) < DBL_EPSILON);
+    /*@=realcompare@*/
+
+    printf("double return value tests ok!\n");
+  }
+
+  /* many arg tests */
+  {
+    float ff;
+    float fa[13];
+    
+    for (ul = 0; ul < 13; ul++)
+      {
+	args[ul] = &ffi_type_float;
+	values[ul] = &fa[ul];
+	fa[ul] = (float) ul;
+      }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+		       &ffi_type_float, args) == FFI_OK);
+
+    /*@-usedef@*/
+    ff =  many(fa[0], fa[1],
+	       fa[2], fa[3],
+	       fa[4], fa[5],
+	       fa[6], fa[7],
+	       fa[8], fa[9],
+	       fa[10],fa[11],fa[12]);
+    /*@=usedef@*/
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    /*@-realcompare@*/
+    if (f - ff < FLT_EPSILON)
+    /*@=realcompare@*/
+	printf("many arg tests ok!\n");
+    else
+#ifdef POWERPC
+	printf("many arg tests failed!  This is a gcc bug.\n");
+#else
+        CHECK(0);
+#endif
+  }
+
+  /* promotion tests */
+  {
+    args[0] = &ffi_type_schar;
+    args[1] = &ffi_type_sshort;
+    args[2] = &ffi_type_uchar;
+    args[3] = &ffi_type_ushort;
+    values[0] = &sc;
+    values[1] = &ss;
+    values[2] = &uc;
+    values[3] = &us;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, 
+		       &ffi_type_sint, args) == FFI_OK);
+
+    us = 0;
+    ul = 0;
+
+    for (sc = (signed char) -127; 
+	 sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
+      for (ss = -30000; ss <= 30000; ss += 10000)
+	for (uc = (unsigned char) 0; 
+	     uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
+	  for (us = 0; us <= 60000; us += 10000)
+	    {
+	      ul++;
+	      ffi_call(&cif, FFI_FN(promotion), &rint, values);
+	      CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
+	    }
+    printf("%lu promotion tests run\n", ul);
+  }
+
+#ifndef X86_WIN32 /* Structures dont work on Win32 */
+
+  /* struct tests */
+  {
+    test_structure_1 ts1_arg;
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_1 *ts1_result = 
+      (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+    args[0] = &ts1_type;
+    values[0] = &ts1_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ts1_type, args) == FFI_OK);
+
+    ts1_arg.uc = '\x01';
+    ts1_arg.d = 3.14159;
+    ts1_arg.ui = 555;
+
+    ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+    CHECK(ts1_result->ui == 556);
+    CHECK(ts1_result->d == 3.14159 - 1);
+
+    puts ("structure test 1 ok!\n");
+
+    free (ts1_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_2 ts2_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_2 *ts2_result = 
+      (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+    args[0] = &ts2_type;
+    values[0] = &ts2_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ts2_type, args) == FFI_OK);
+
+    ts2_arg.d1 = 5.55;
+    ts2_arg.d2 = 6.66;
+
+    printf ("%g\n", ts2_result->d1);
+    printf ("%g\n", ts2_result->d2);
+
+    ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
+
+    printf ("%g\n", ts2_result->d1);
+    printf ("%g\n", ts2_result->d2);
+    
+    CHECK(ts2_result->d1 == 5.55 - 1);
+    CHECK(ts2_result->d2 == 6.66 - 1);
+
+    printf("structure test 2 ok!\n");
+
+    free (ts2_result);
+  }
+
+  /* struct tests */
+  {
+    int compare_value;
+    test_structure_3 ts3_arg;
+    test_structure_3 *ts3_result = 
+      (test_structure_3 *) malloc (sizeof(test_structure_3));
+
+    args[0] = &ts3_type;
+    values[0] = &ts3_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ts3_type, args) == FFI_OK);
+
+    ts3_arg.si = -123;
+    compare_value = ts3_arg.si;
+
+    ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
+
+    printf ("%d %d\n", ts3_result->si, -(compare_value*2));
+
+    if (ts3_result->si == -(ts3_arg.si*2))
+	puts ("structure test 3 ok!");
+    else
+      {
+	puts ("Structure test 3 found structure passing bug.");
+	puts ("  Current versions of GCC are not 100% compliant with the");
+	puts ("  n32 ABI.  There is a known problem related to passing");
+	puts ("  small structures.  Send a bug report to the gcc maintainers.");
+      }
+
+    free (ts3_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_4 ts4_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_4 *ts4_result = 
+      (test_structure_4 *) malloc (sizeof(test_structure_4));
+
+    args[0] = &ts4_type;
+    values[0] = &ts4_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		       &ts4_type, args) == FFI_OK);
+
+    ts4_arg.ui1 = 2;
+    ts4_arg.ui2 = 3;
+    ts4_arg.ui3 = 4;
+
+    ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
+    
+    if (ts4_result->ui3 == 2U * 3U * 4U)
+      puts ("structure test 4 ok!");
+    else
+      puts ("Structure test 4 found GCC's structure passing bug.");
+
+    free (ts4_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_5 ts5_arg1, ts5_arg2;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_5 *ts5_result = 
+      (test_structure_5 *) malloc (sizeof(test_structure_5));
+
+    args[0] = &ts5_type;
+    args[1] = &ts5_type;
+    values[0] = &ts5_arg1;
+    values[1] = &ts5_arg2;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
+		       &ts5_type, args) == FFI_OK);
+
+    ts5_arg1.c1 = 2;
+    ts5_arg1.c2 = 6;
+    ts5_arg2.c1 = 5;
+    ts5_arg2.c2 = 3;
+
+    ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
+    
+    if (ts5_result->c1 == 7 
+	&& ts5_result->c2 == 3)
+      puts ("structure test 5 ok!");
+    else
+      puts ("Structure test 5 found GCC's structure passing bug.");
+
+    free (ts5_result);
+  }
+
+#else
+  printf("Structure passing doesn't work on Win32.\n");
+#endif /* X86_WIN32 */
+
+# if FFI_CLOSURES
+  /* A simple closure test */
+    {
+      ffi_closure cl;
+      ffi_type * cl_arg_types[3];
+
+      cl_arg_types[0] = &ffi_type_sint;
+      cl_arg_types[1] = &ffi_type_float;
+      cl_arg_types[2] = NULL;
+      
+      /* Initialize the cif */
+      CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
+	    	         &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+      CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
+			     (void *) 3 /* userdata */)
+	    == FFI_OK);
+      CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
+    }
+# endif
+
+  /* If we arrived here, all is good */
+  (void) puts("\nLooks good. No surprises.\n");
+
+  /*@-compdestroy@*/
+
+  return 0;
+}
+

+ 670 - 0
libffi/ia64/ffi.c

@@ -0,0 +1,670 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Cygnus Solutions
+	   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_private.h>
+
+#include <stdlib.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_regs.  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 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.  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 + SIZEOF_ARG - 1)/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 s struct ia64_args, and the 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 declarint 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 unsigned 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 (fp_reg_num < 8) {
+	      *(float *)argp = args -> fp_regs[fp_reg_num++];
+	  } else {
+	      *(float *)argp = *(double *)argp;
+	  }
+	  *p_argv = (void *)argp;
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  z = 1;
+	  if (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 + SIZEOF_ARG - 1)/SIZEOF_ARG;
+	      if (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;
+}
+
+

+ 301 - 0
libffi/ia64/unix.S

@@ -0,0 +1,301 @@
+/* -----------------------------------------------------------------------
+   unix.S - Copyright (c) 1998 Cygnus Solutions
+            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 <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	*/
+
+.text
+        .align 16
+        .global ffi_call_unix#
+        .proc ffi_call_unix#
+ffi_call_unix:
+	alloc   loc0=ar.pfs,6,5,8,0
+	mov 	loc1=b0;
+	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],16
+	ld8	out7=[loc3]
+	/* loc2 points at first stack parameter.  Set sp to 16 bytes	*/
+	/* below that.							*/
+	add	sp=-16,loc2
+	
+	ld8 	r8=[fn],8
+	;;
+	ld8	r1=[fn]		/* Set up gp */
+	mov	b6=r8;;
+	br.call.sptk.many b0 = b6	/* call ffi_prep_args	*/
+	
+	/* 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
+	;;
+(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
+	br.ret.sptk.many b0
+
+handle_double_hfa:
+	/* 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
+
+
+.text
+        .align 16
+        .global ffi_closure_UNIX
+        .proc ffi_closure_UNIX
+ffi_closure_UNIX:
+	alloc   loc0=ar.pfs,8,2,2,0
+	mov	loc1=b0
+	/* 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,FLOAT_SZ+8
+	stfd	[r15]=f15,2*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
+	br.ret.sptk.many b0
+	.endp ffi_closure_UNIX
+	
+

+ 6 - 0
libffi/include/Makefile.am

@@ -0,0 +1,6 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+noinst_HEADERS=ffi_private.h
+include_HEADERS=ffi.h

+ 393 - 0
libffi/include/ffi.h

@@ -0,0 +1,393 @@
+/* -----------------------------------------------------------------*-C-*-
+   libffi 2.0.0 - Copyright (C) 1996, 1997, 1998, 1999, 2000, 
+                                2001  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 RED HAT 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 FFI_H
+#define FFI_H
+
+#if !defined(__ASSEMBLER__) && !defined(__GNUC__)
+#error --- ffi.h requires GNU C ---
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(LIBFFI_ASM)
+#include <stddef.h>
+#if defined(FFI_DEBUG) 
+#include <stdio.h>
+#endif
+#endif
+
+#ifndef LIBFFI_ASM
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+typedef enum ffi_abi {
+
+  /* Leave this for debugging purposes */
+  FFI_FIRST_ABI = 0,
+
+  /* ---- Sparc -------------------- */
+#ifdef __sparc__
+  FFI_V8,
+  FFI_V8PLUS,
+  FFI_V9,
+#if defined(__arch64__) || defined(__sparcv9)
+  FFI_DEFAULT_ABI = FFI_V9,
+#else
+  FFI_DEFAULT_ABI = FFI_V8,
+#endif
+#endif
+
+  /* ---- Intel x86 ---------------- */
+#ifdef __i386__
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
+  /* ---- Intel ia64 ---------------- */
+#ifdef __ia64__
+  FFI_UNIX,   	/* Linux and all Unix variants use the same conventions	*/
+  FFI_DEFAULT_ABI = FFI_UNIX,
+#endif
+
+  /* ---- Mips --------------------- */
+#ifdef __mips__
+  FFI_O32,
+  FFI_N32,
+  FFI_N64,
+
+# if defined(__mips_eabi)
+#   define FFI_MIPS_EABI
+#   define FFI_MIPS_O32
+# else
+#   if !defined(_MIPS_SIM)
+#error -- something is very wrong --
+#   else
+#     if _MIPS_SIM==_ABIN32 && defined(_ABIN32)
+#       define FFI_MIPS_N32
+#     else
+#       define FFI_MIPS_O32
+#     endif
+#   endif
+# endif
+# if defined(FFI_MIPS_O32)
+  FFI_DEFAULT_ABI = FFI_O32,
+# else
+  FFI_DEFAULT_ABI = FFI_N32,
+# endif
+
+#endif
+
+  /* ---- Alpha -------------------- */
+#ifdef __alpha__
+  FFI_OSF,
+  FFI_DEFAULT_ABI = FFI_OSF,
+#endif
+
+  /* ---- Motorola m68k ------------ */
+#ifdef __m68k__
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
+  /* ---- PowerPC ------------------ */
+#ifdef __powerpc__
+  FFI_SYSV,
+  FFI_GCC_SYSV,
+  FFI_DEFAULT_ABI = FFI_GCC_SYSV,
+#endif
+
+  /* ---- ARM  --------------------- */
+#ifdef __arm__
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
+  /* ---- S390 --------------------- */
+#ifdef __S390__
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
+  /* Leave this for debugging purposes */
+  FFI_LAST_ABI
+
+} ffi_abi;
+
+typedef struct _ffi_type
+{
+  size_t size;
+  unsigned short alignment;
+  unsigned short type;
+  struct _ffi_type **elements;
+} ffi_type;
+
+/* These are defined in ffi.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;
+
+extern ffi_type ffi_type_ushort;
+extern ffi_type ffi_type_sint; 
+extern ffi_type ffi_type_uint; 
+extern ffi_type ffi_type_slong; 
+extern ffi_type ffi_type_ulong;
+
+typedef enum {
+  FFI_OK = 0,
+  FFI_BAD_TYPEDEF,
+  FFI_BAD_ABI 
+} ffi_status;
+
+typedef unsigned FFI_TYPE;
+
+typedef struct {
+  ffi_abi abi;
+  unsigned nargs;
+  ffi_type **arg_types;
+  ffi_type *rtype;
+  unsigned bytes;
+  unsigned flags;
+
+#ifdef __mips__
+#if _MIPS_SIM == _ABIN32
+  unsigned rstruct_flag;
+#endif
+#endif
+
+} ffi_cif;
+
+/* ---- Definitions for the raw API -------------------------------------- */
+
+#if !FFI_NO_RAW_API
+
+typedef union {
+#if _MIPS_SIM==_ABIN32 && defined(_ABIN32)
+  long          sint;
+  unsigned long uint;
+#else
+  int      sint;
+  unsigned uint;
+#endif
+  float	   flt;
+  char     data[sizeof(void*)];
+  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);
+
+#if !NO_JAVA_RAW_API
+
+/* 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);
+
+#endif /* !NO_JAVA_RAW_API */
+
+#endif /* !FFI_NO_RAW_API */
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#ifdef __i386__
+
+#define FFI_CLOSURES 1		/* x86 supports closures */
+#define FFI_TRAMPOLINE_SIZE 10
+#define FFI_NATIVE_RAW_API 1	/* and has native raw api support */
+
+#elif defined(X86_WIN32)
+
+#define FFI_CLOSURES 1		/* x86 supports closures */
+#define FFI_TRAMPOLINE_SIZE 10
+#define FFI_NATIVE_RAW_API 1	/* and has native raw api support */
+
+#elif defined(IA64)
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24  /* Really the following struct, which 	*/
+				/* can be interpreted as a C function	*/
+				/* decriptor:				*/
+
+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.			*/
+};
+#define FFI_NATIVE_RAW_API 0
+
+#elif defined(__alpha__)
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+
+#elif defined(POWERPC)
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 40
+#define FFI_NATIVE_RAW_API 0
+
+#else 
+
+#define FFI_CLOSURES 0
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
+
+
+#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);
+
+#if !FFI_NO_RAW_API
+
+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);
+
+#ifndef NO_JAVA_RAW_API
+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
+
+#endif /* !FFI_NO_RAW_API */
+#endif /* FFI_CLOSURES */
+
+/* ---- Public interface definition -------------------------------------- */
+
+ffi_status ffi_prep_cif (ffi_cif *cif, 
+			 ffi_abi abi,
+			 unsigned int nargs, 
+			 ffi_type *rtype, 
+			 ffi_type **atypes);
+
+void ffi_call (ffi_cif *cif, 
+	       void (*fn)(), 
+	       void *rvalue, 
+	       void **avalue);
+
+/* Useful for eliminating compiler warnings */
+#define FFI_FN(f) ((void (*)())f)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 168 - 0
libffi/include/ffi_private.h

@@ -0,0 +1,168 @@
+/* -----------------------------------------------------------------*-C-*-
+   libffi 2.0.0 - Copyright (C) 1996, 1997, 1998, 1999, 2000, 
+                                2001  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 RED HAT 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 <fficonfig.h>
+
+#define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#define FLOAT32 float
+#define FLOAT64 double
+#define FLOAT80 long double
+
+#define UINT8   unsigned char
+#define SINT8   signed char
+
+#if SIZEOF_INT == 2
+
+#define UINT16	unsigned int
+#define SINT16  int
+
+#else 
+#if SIZEOF_SHORT == 2
+
+#define UINT16  unsigned short
+#define SINT16  short
+
+#endif
+#endif
+
+#if SIZEOF_INT == 4
+
+#define UINT32	unsigned int
+#define SINT32  int
+
+#else 
+#if SIZEOF_SHORT == 4
+
+#define UINT32  unsigned short
+#define SINT32  short
+
+#else
+#if SIZEOF_LONG == 4
+
+#define UINT32  unsigned long
+#define SINT32  long
+
+#endif
+#endif
+#endif
+
+#if SIZEOF_INT == 8
+
+#define UINT64  unsigned int
+#define SINT64  int
+
+#else
+#if SIZEOF_LONG == 8
+
+#define UINT64  unsigned long
+#define SINT64  long
+
+#else
+#if SIZEOF_LONG_LONG == 8
+
+#define UINT64  unsigned long long
+#define SINT64  long long
+
+#endif
+#endif
+#endif
+
+#define FFI_TYPE_VOID       0    
+#define FFI_TYPE_INT        1
+#define FFI_TYPE_FLOAT      2    
+#define FFI_TYPE_DOUBLE     3
+#if SIZEOF_LONG_DOUBLE == SIZEOF_DOUBLE
+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
+#else
+#define FFI_TYPE_LONGDOUBLE 4
+#endif
+#define FFI_TYPE_UINT8      5   /* If this changes, update ffi_mips.h. */
+#define FFI_TYPE_SINT8      6   /* If this changes, update ffi_mips.h. */
+#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  /* If this changes, update ffi_mips.h. */
+#define FFI_TYPE_POINTER    14
+#define FFI_TYPE_LAST       14
+
+#if _MIPS_SIM==_ABIN32 && defined(_ABIN32)
+#define SIZEOF_ARG 8
+#else
+#define SIZEOF_ARG SIZEOF_VOID_P
+#endif
+
+#ifndef __ASSEMBLER__
+/* This part of the private header file is only for C code.  */
+
+/* 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
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+#ifndef __cplusplus
+/* bool is a keyword in C++ */
+typedef int bool;
+#endif
+
+#ifdef FFI_DEBUG
+/* Debugging functions */
+void ffi_stop_here(void);
+bool ffi_type_test(ffi_type *a);
+#define FFI_ASSERT(x) ((x) ? 0 : ffi_assert(__FILE__,__LINE__))
+#else
+#define FFI_ASSERT(x) 
+#endif
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
+
+/* Extended cif, used in callback from assembly routine */
+typedef struct
+{
+  ffi_cif *cif;
+  void *rvalue;
+  void **avalue;
+} extended_cif;
+
+#endif /* __ASSEMBLER__ */
+

+ 77 - 0
libffi/include/fficonfig.h

@@ -0,0 +1,77 @@
+/* fficonfig.h.  Generated automatically by configure.  */
+/* fficonfig.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if using alloca.c.  */
+/* #undef C_ALLOCA */
+
+/* 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 if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#define HAVE_ALLOCA_H 1
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define this if you want extra debugging */
+/* #undef FFI_DEBUG */
+
+/* Define this if you are using Purify and want to suppress 
+   spurious messages. */
+/* #undef USING_PURIFY */
+
+/* Define this is you do not want support for aggregate types.  */
+/* #undef FFI_NO_STRUCTS */
+
+/* Define this is you do not want support for the raw API.  */
+/* #undef FFI_NO_RAW_API */
+
+/* Define if you have the memcpy function.  */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the <dlfcn.h> header file.  */
+#define HAVE_DLFCN_H 1
+
+/* The number of bytes in type short */
+#define SIZEOF_SHORT 2
+
+/* The number of bytes in type int */
+#define SIZEOF_INT 4
+
+/* The number of bytes in type long */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in type long long */
+#define SIZEOF_LONG_LONG 8
+
+/* The number of bytes in type float */
+#define SIZEOF_FLOAT 4
+
+/* The number of bytes in type double */
+#define SIZEOF_DOUBLE 8
+
+/* The number of bytes in type long double */
+#define SIZEOF_LONG_DOUBLE 12
+
+/* The number of bytes in type void * */
+#define SIZEOF_VOID_P 4
+
+/* whether byteorder is bigendian */
+/* #undef WORDS_BIGENDIAN */
+
+/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
+#define BYTEORDER 1234
+

+ 269 - 0
libffi/java_raw_api.c

@@ -0,0 +1,269 @@
+/* -----------------------------------------------------------------------
+   java_raw_api.c - Copyright (c) 1999  Cygnus Solutions
+
+   Cloned from raw_api.c
+
+   Raw_api.c author: Kresten Krab Thorup <[email protected]>
+   Java_raw_api.c author: Hans-J. Boehm <[email protected]>
+
+   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 RED HAT 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_private.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:
+	  result += 2 * SIZEOF_ARG;
+	  break;
+	case FFI_TYPE_STRUCT:
+	  /* No structure parameters in Java.	*/
+	  abort();
+	default:
+	  result += 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++) + SIZEOF_ARG - 1);
+	  break;
+	  
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	  *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
+	  break;
+
+#if SIZEOF_ARG >= 4	  
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	  *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
+	  break;
+#endif
+	
+#if 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, SIZEOF_ARG) / SIZEOF_ARG;
+	}
+    }
+
+#else /* WORDS_BIGENDIAN */
+
+#if !PDP
+
+  /* then assume little endian */
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+#if 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 /* SIZEOF_ARG != 8 */
+	*args = (void*) raw;
+	raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
+#endif /* 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:
+	  (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 SIZEOF_ARG >= 4
+	case FFI_TYPE_UINT32:
+	  (raw++)->uint = *(UINT32*) (*args);
+	  break;
+
+	case FFI_TYPE_SINT32:
+	  (raw++)->sint = *(SINT32*) (*args);
+	  break;
+#endif
+        case FFI_TYPE_FLOAT:
+	  (raw++)->flt = *(FLOAT32*) (*args);
+	  break;
+
+#if 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 SIZEOF_ARG == 8
+	  FFI_ASSERT(FALSE);	/* Should have covered all cases */
+#else	
+	  memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
+	  raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
+#endif
+	}
+    }
+}
+
+#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_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);
+}
+
+#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);
+}
+
+/* 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 */

+ 184 - 0
libffi/m68k/ffi.c

@@ -0,0 +1,184 @@
+/* -----------------------------------------------------------------------
+   ffi.c
+   
+   m68k Foreign Function Interface 
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_private.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;
+  int tmp;
+  unsigned int avn;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+  void *struct_value_ptr;
+
+  tmp = 0;
+  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;
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0 && avn != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary.  */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp)
+	argp = (char *) ALIGN (argp, (*p_arg)->alignment);
+
+      if (avn != 0) 
+	{
+	  avn--;
+	  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;
+    }
+}

+ 96 - 0
libffi/m68k/sysv.S

@@ -0,0 +1,96 @@
+/* -----------------------------------------------------------------------
+   sysv.S
+   
+   m68k Foreign Function Interface 
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM	
+#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

+ 469 - 0
libffi/mips/ffi.c

@@ -0,0 +1,469 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 2001 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_private.h>
+#include <mips/mips.h>
+
+#include <stdlib.h>
+
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+#define FIX_ARGP \
+FFI_ASSERT(argp <= &stack[bytes]); \
+if (argp == &stack[bytes]) \
+{ \
+  argp = stack; \
+}
+#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 int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+  /* 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 * SIZEOF_ARG)
+    argp = &stack[bytes - (8 * SIZEOF_ARG)];
+  else
+    argp = stack;
+#else
+  argp = stack;
+#endif
+
+  memset(stack, 0, bytes);
+
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+  if ( ecif->cif->rstruct_flag != 0 )
+#else
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
+#endif  
+    {
+      *(SLOT_TYPE_UNSIGNED *) argp = (SLOT_TYPE_UNSIGNED) ecif->rvalue;
+      argp += sizeof(SLOT_TYPE_UNSIGNED);
+      FIX_ARGP;
+    }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i && avn;
+       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 == _MIPS_SIM_ABI32
+#define OFFSET 0
+#else
+#define OFFSET sizeof(int)
+#endif      
+
+      if (avn) 
+	{
+	  avn--;
+	  z = (*p_arg)->size;
+	  if (z < sizeof(SLOT_TYPE_UNSIGNED))
+	    {
+	      z = sizeof(SLOT_TYPE_UNSIGNED);
+
+	      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 == _MIPS_SIM_ABI32	      
+	      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 == _MIPS_SIM_NABI32
+
+/* 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. */
+
+static 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 == _MIPS_SIM_ABI32
+  /* 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 == _MIPS_SIM_NABI32
+  /* 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 == _MIPS_SIM_ABI32
+    case FFI_O32:
+      ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
+		   cif->flags, ecif.rvalue, fn);
+      break;
+#endif
+
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+    case FFI_N32:
+      ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, 
+		   cif->flags, ecif.rvalue, fn);
+      break;
+#endif
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}

+ 320 - 0
libffi/mips/n32.S

@@ -0,0 +1,320 @@
+/* -----------------------------------------------------------------------
+   n32.S - Copyright (c) 1996, 1998, 2001  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 <ffi.h>
+#include <ffi_private.h>
+#include <mips/mips.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 * 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*SIZEOF_ARG($sp)	# Save frame pointer
+	REG_S	ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp)	# Save return address
+	move	$fp, $sp
+
+	move	t9, callback	# callback function pointer
+	REG_S	bytes, 2*SIZEOF_ARG($fp) # bytes
+	REG_S	flags, 3*SIZEOF_ARG($fp) # flags
+	REG_S	raddr, 4*SIZEOF_ARG($fp) # raddr
+	REG_S	fn,    5*SIZEOF_ARG($fp) # fn
+
+	# Allocate at least 4 words in the argstack
+	move	v0, bytes
+	bge	bytes, 4 * SIZEOF_ARG, bigger	
+	LI	v0, 4 * SIZEOF_ARG
+	b	sixteen
+
+	bigger:	
+	ADDU	t4, v0, 2 * SIZEOF_ARG -1	# make sure it is aligned 
+	and	v0, t4, -2 * 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 * SIZEOF_ARG
+	ADDU	a3, $fp, 3 * SIZEOF_ARG
+
+	# Call ffi_prep_args
+	jal	t9
+	
+	#	ADDU	$sp, $sp, 4 * 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*SIZEOF_ARG($fp)
+
+	# Is it bigger than 8 * SIZEOF_ARG?
+	dadd	t7, $0, 8 * SIZEOF_ARG
+	dsub	t8, t6, t7
+	bltz	t8, loadregs
+
+	add	t9, t9, t8
+	
+loadregs:	
+
+	REG_L	t4, 3*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*SIZEOF_ARG(t9)
+	b	arg1_next
+arg1_floatp:	
+	bne	t4, FFI_TYPE_FLOAT, arg1_doublep
+	l.s	$f12, 0*SIZEOF_ARG(t9)
+	b	arg1_next
+arg1_doublep:	
+	l.d	$f12, 0*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*SIZEOF_ARG(t9)
+	b	arg2_next
+arg2_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg2_doublep
+	l.s	$f13, 1*SIZEOF_ARG(t9)	
+	b	arg2_next
+arg2_doublep:	
+	l.d	$f13, 1*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*SIZEOF_ARG(t9)
+	b	arg3_next
+arg3_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg3_doublep
+	l.s	$f14, 2*SIZEOF_ARG(t9)	
+	b	arg3_next
+arg3_doublep:	
+	l.d	$f14, 2*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*SIZEOF_ARG(t9)
+	b	arg4_next
+arg4_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg4_doublep
+	l.s	$f15, 3*SIZEOF_ARG(t9)	
+	b	arg4_next
+arg4_doublep:	
+	l.d	$f15, 3*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*SIZEOF_ARG(t9)
+	b	arg5_next
+arg5_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg5_doublep
+	l.s	$f16, 4*SIZEOF_ARG(t9)	
+	b	arg5_next
+arg5_doublep:	
+	l.d	$f16, 4*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*SIZEOF_ARG(t9)
+	b	arg6_next
+arg6_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg6_doublep
+	l.s	$f17, 5*SIZEOF_ARG(t9)	
+	b	arg6_next
+arg6_doublep:	
+	l.d	$f17, 5*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*SIZEOF_ARG(t9)
+	b	arg7_next
+arg7_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg7_doublep
+	l.s	$f18, 6*SIZEOF_ARG(t9)	
+	b	arg7_next
+arg7_doublep:	
+	l.d	$f18, 6*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*SIZEOF_ARG(t9)
+	b	arg8_next
+arg8_floatp:
+	bne	t4, FFI_TYPE_FLOAT, arg8_doublep
+ 	l.s	$f19, 7*SIZEOF_ARG(t9)	
+	b	arg8_next
+arg8_doublep:	
+ 	l.d	$f19, 7*SIZEOF_ARG(t9)	
+arg8_next:	
+
+callit:		
+	# Load the function pointer
+	REG_L	t9, 5*SIZEOF_ARG($fp)
+
+	# If the return value pointer is NULL, assume no return value.
+	REG_L	t5, 4*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*SIZEOF_ARG($fp)
+	REG_S	v0, 0(t4)
+	b	epilogue
+
+retfloat:
+	bne     t6, FFI_TYPE_FLOAT, retdouble
+	jal	t9
+	REG_L	t4, 4*SIZEOF_ARG($fp)
+	s.s	$f0, 0(t4)
+	b	epilogue
+
+retdouble:	
+	bne	t6, FFI_TYPE_DOUBLE, retstruct_d
+	jal	t9
+	REG_L	t4, 4*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*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*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*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*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*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*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*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*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*SIZEOF_ARG($sp) # Restore frame pointer
+	REG_L	ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp)  # Restore return address
+	ADDU	$sp, SIZEOF_FRAME		      # Fix stack pointer
+	j	ra
+
+	.end	ffi_call_N32
+	
+#endif

+ 173 - 0
libffi/mips/o32.S

@@ -0,0 +1,173 @@
+/* -----------------------------------------------------------------------
+   o32.S - Copyright (c) 1996, 1998, 2001  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 <ffi.h>
+#include <ffi_private.h>
+#include <mips/mips.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 * SIZEOF_ARG + 2 * 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*SIZEOF_ARG($sp)	# Save frame pointer
+	REG_S	ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp)	# Save return address
+	move	$fp, $sp
+
+	move	t9, callback	# callback function pointer
+	REG_S	flags, SIZEOF_FRAME + 3*SIZEOF_ARG($fp) # flags
+
+	# Allocate at least 4 words in the argstack
+	move	v0, bytes
+	bge	bytes, 4 * SIZEOF_ARG, bigger	
+	LI	v0, 4 * SIZEOF_ARG
+	b	sixteen
+
+bigger:	
+	ADDU	t0, v0, 2 * SIZEOF_ARG -1	# make sure it is aligned 
+	and	v0, t0, -2 * 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 * SIZEOF_ARG
+	ADDU	a3, $fp, SIZEOF_FRAME + 3*SIZEOF_ARG
+
+	jal	t9
+	
+	REG_L	t0, SIZEOF_FRAME + 3*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 * SIZEOF_ARG	# adjust $sp to new args
+
+	bnez	t0, pass_d			# make it quick for int
+	REG_L	a0, 0*SIZEOF_ARG($sp)		# just go ahead and load the
+	REG_L	a1, 1*SIZEOF_ARG($sp)		# four regs.
+	REG_L	a2, 2*SIZEOF_ARG($sp)
+	REG_L	a3, 3*SIZEOF_ARG($sp)
+	b	call_it
+
+pass_d:
+	bne	t0, FFI_ARGS_D, pass_f
+	l.d	$f12, 0*SIZEOF_ARG($sp)	# load $fp regs from args
+	REG_L	a2,   2*SIZEOF_ARG($sp)	# passing a double
+	REG_L	a3,   3*SIZEOF_ARG($sp)
+	b	call_it
+
+pass_f:	
+	bne	t0, FFI_ARGS_F, pass_d_d
+	l.s	$f12, 0*SIZEOF_ARG($sp)	# load $fp regs from args
+	REG_L	a1,   1*SIZEOF_ARG($sp)	# passing a float
+	REG_L	a2,   2*SIZEOF_ARG($sp)
+	REG_L	a3,   3*SIZEOF_ARG($sp)
+	b	call_it		
+
+pass_d_d:		
+	bne	t0, FFI_ARGS_DD, pass_f_f
+	l.d	$f12, 0*SIZEOF_ARG($sp)	# load $fp regs from args
+	l.d	$f14, 2*SIZEOF_ARG($sp)	# passing two doubles
+	b	call_it
+
+pass_f_f:	
+	bne	t0, FFI_ARGS_FF, pass_d_f
+	l.s	$f12, 0*SIZEOF_ARG($sp)	# load $fp regs from args
+	l.s	$f14, 1*SIZEOF_ARG($sp)	# passing two floats
+	REG_L	a2,   2*SIZEOF_ARG($sp)
+	REG_L	a3,   3*SIZEOF_ARG($sp)
+	b	call_it
+
+pass_d_f:		
+	bne	t0, FFI_ARGS_DF, pass_f_d
+	l.d	$f12, 0*SIZEOF_ARG($sp)	# load $fp regs from args
+	l.s	$f14, 2*SIZEOF_ARG($sp)	# passing double and float
+	REG_L	a3,   3*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*SIZEOF_ARG($sp)	# load $fp regs from args
+	l.d	$f14, 2*SIZEOF_ARG($sp)	# passing double and float
+
+call_it:	
+	# Load the function pointer
+	REG_L	t9, SIZEOF_FRAME + 5*SIZEOF_ARG($fp)
+
+	# If the return value pointer is NULL, assume no return value.
+	REG_L	t1, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
+	beqz	t1, noretval
+
+	bne     t2, FFI_TYPE_INT, retfloat
+	jal	t9
+	REG_L	t0, SIZEOF_FRAME + 4*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*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*SIZEOF_ARG($fp)
+	s.d	$f0, 0(t0)
+	b	epilogue
+	
+noretval:	
+	jal	t9
+	
+	# Epilogue
+epilogue:	
+	move	$sp, $fp	
+	REG_L	$fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
+	REG_L	ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp)  # Restore return address
+	ADDU	$sp, SIZEOF_FRAME		      # Fix stack pointer
+	j	ra
+
+	.end	ffi_call_O32
+	
+#endif

+ 680 - 0
libffi/powerpc/ffi.c

@@ -0,0 +1,680 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Geoffrey Keating
+   
+   PowerPC Foreign Function Interface 
+
+   $Id: ffi.c,v 1.1 2001/08/02 19:31:55 orph 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.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_private.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+extern void ffi_closure_SYSV(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 SYSV ABI.  */
+enum {
+  NUM_GPR_ARG_REGISTERS = 8,
+  NUM_FPR_ARG_REGISTERS = 8
+};
+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_SYSV 4bytes	|	higher addresses
+   |--------------------------------------------|
+   |   Previous backchain pointer	4	| 	stack pointer here
+   |--------------------------------------------|<+ <<<	on entry to
+   |   Saved r28-r31			4*4	| |	ffi_call_SYSV
+   |--------------------------------------------| |
+   |   GPR registers r3-r10		8*4	| |	ffi_call_SYSV
+   |--------------------------------------------| |
+   |   FPR registers f1-f8 (optional)	8*8	| |
+   |--------------------------------------------| |	stack	|
+   |   Space for copied structures		| |	grows	|
+   |--------------------------------------------| |	down    V
+   |   Parameters that didn't fit in registers  | |
+   |--------------------------------------------| |	lower addresses
+   |   Space for callee's LR		4	| |
+   |--------------------------------------------| |	stack pointer here
+   |   Current backchain pointer	4	|-/	during
+   |--------------------------------------------|   <<<	ffi_call_SYSV
+
+   */
+
+/*@-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));
+
+  /* 'gpr_base' points at the space for gpr3, and grows upwards as
+     we use GPR registers.  */
+  unsigned *gpr_base = stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
+  int intarg_count = 0;
+
+  /* 'fpr_base' points at the space for fpr1, and grows upwards as
+     we use FPR registers.  */
+  double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS;
+  int fparg_count = 0;
+
+  /* 'copy_space' grows down as we put structures in it.  It should
+     stay 16-byte aligned.  */
+  char *copy_space = ((flags & FLAG_FP_ARGUMENTS)
+		      ? (char *)fpr_base
+		      : (char *)gpr_base);
+
+  /* 'next_arg' grows up as we put parameters in it.  */
+  unsigned *next_arg = stack + 2;
+
+  int i;
+  ffi_type **ptr;
+  double double_tmp;
+  void **p_argv;
+  size_t struct_copy_size;
+  unsigned gprvalue;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
+  FFI_ASSERT(((unsigned)(char *)copy_space & 0xF) == 0);
+  FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
+  FFI_ASSERT((bytes & 0xF) == 0);
+  FFI_ASSERT(copy_space >= (char *)next_arg);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+  {
+    *gpr_base++ = (unsigned)(char *)ecif->rvalue;
+    intarg_count++;
+  }
+
+  /* Now for the arguments.  */
+  p_argv = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      switch ((*ptr)->type)
+	{
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+	  if ((*ptr)->type == FFI_TYPE_FLOAT)
+	    double_tmp = *(float *)*p_argv;
+	  else
+	    double_tmp = *(double *)*p_argv;
+
+	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+	    {
+	      if (intarg_count%2 != 0)
+		{
+		  intarg_count++;
+		  next_arg++;
+		}
+	      *(double *)next_arg = double_tmp;
+	      next_arg += 2;
+	    }
+	  else
+	    *fpr_base++ = double_tmp;
+	  fparg_count++;
+	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+	  break;
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
+	    intarg_count++;
+	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+	    {
+	      if (intarg_count%2 != 0)
+		{
+		  intarg_count++;
+		  next_arg++;
+		}
+	      *(long long *)next_arg = *(long long *)*p_argv;
+	      next_arg += 2;
+	    }
+	  else
+	    {
+              /* whoops: abi states only certain register pairs
+               * can be used for passing long long int
+               * specifically (r3,r4), (r5,r6), (r7,r8), 
+               * (r9,r10) and if next arg is long long but
+               * not correct starting register of pair then skip
+               * until the proper starting register
+	       */
+              if (intarg_count%2 != 0)
+                {
+                  intarg_count ++;
+                  gpr_base++;
+                }
+	      *(long long *)gpr_base = *(long long *)*p_argv;
+	      gpr_base += 2;
+	    }
+	  intarg_count += 2;
+	  break;
+
+	case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+#endif
+	  struct_copy_size = ((*ptr)->size + 15) & ~0xF;
+	  copy_space -= struct_copy_size;
+	  memcpy(copy_space, (char *)*p_argv, (*ptr)->size);
+	  
+	  gprvalue = (unsigned)copy_space;
+
+	  FFI_ASSERT(copy_space > (char *)next_arg);
+	  FFI_ASSERT(flags & FLAG_ARG_NEEDS_COPY);
+	  goto putgpr;
+
+	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_INT:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+	  gprvalue = *(unsigned *)*p_argv;
+	putgpr:
+	  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+	    *next_arg++ = gprvalue;
+	  else
+	    *gpr_base++ = gprvalue;
+	  intarg_count++;
+	  break;
+	}
+    }
+
+  /* Check that we didn't overrun the stack...  */
+  FFI_ASSERT(copy_space >= (char *)next_arg);
+  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 SYSV ABI.  */
+  int i;
+  ffi_type **ptr;
+  unsigned bytes;
+  int fparg_count = 0, intarg_count = 0;
+  unsigned flags = 0;
+  unsigned struct_copy_size = 0;
+  
+  /* All the machine-independent calculation of cif->bytes will be wrong.
+     Redo the calculation for SYSV.  */
+
+  /* Space for the frame pointer, callee's LR, and the asm's temp regs.  */
+  bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof(int);
+
+  /* Space for the GPR registers.  */
+  bytes += NUM_GPR_ARG_REGISTERS * sizeof(int);
+
+  /* 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;
+     - Larger structures and long double (if not equivalent to double) values
+       are allocated space and a pointer is passed as the first argument.  */
+  switch (cif->rtype->type)
+    {
+    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:
+      if (cif->abi != FFI_GCC_SYSV)
+	if (cif->rtype->size <= 4)
+	  break;
+	else if (cif->rtype->size <= 8)
+	  {
+	    flags |= FLAG_RETURNS_64BITS;
+	    break;
+	  }
+      /* else fall through.  */
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+#endif
+      intarg_count++;
+      flags |= FLAG_RETVAL_REFERENCE;
+      /* Fall through.  */
+    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
+	  /* We must allocate space for a copy of these to enforce
+	     pass-by-value.  Pad the space up to a multiple of 16
+	     bytes (the maximum alignment required for anything under
+	     the SYSV ABI).  */
+	  struct_copy_size += ((*ptr)->size + 15) & ~0xF;
+	  /* Fall through (allocate space for the pointer).  */
+
+	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;
+  if (intarg_count > 4)
+    flags |= FLAG_4_GPR_ARGUMENTS;
+  if (struct_copy_size != 0)
+    flags |= FLAG_ARG_NEEDS_COPY;
+  
+  /* Space for the FPR registers, if needed.  */
+  if (fparg_count != 0)
+    bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
+
+  /* Stack space.  */
+  if (intarg_count > NUM_GPR_ARG_REGISTERS)
+    bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof(int);
+  if (fparg_count > NUM_FPR_ARG_REGISTERS)
+    bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof(double);
+
+  /* The stack space allocated needs to be a multiple of 16 bytes.  */
+  bytes = (bytes + 15) & ~0xF;
+
+  /* Add in the space for the copied structures.  */
+  bytes += struct_copy_size;
+
+  cif->flags = flags;
+  cif->bytes = bytes;
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(/*@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:
+    case FFI_GCC_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(&ecif, -cif->bytes, 
+		    cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+
+static void flush_icache(char *, int);
+
+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];
+  tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
+  tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */
+  tramp[4] = 0x7d6802a6;  /*   mflr    r11 */
+  tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */
+  tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */
+  tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */
+  tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */
+  tramp[9] = 0x4e800420;  /*   bctr */
+  *(void **) &tramp[2] = (void *)ffi_closure_SYSV; /* function */
+  *(void **) &tramp[3] = (void *)closure;          /* context */
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the icache.  */
+  flush_icache(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
+
+  return FFI_OK;
+}
+
+
+#define MIN_CACHE_LINE_SIZE 8
+
+static void flush_icache(char * addr1, int size)
+{
+  int i;
+  char * addr;
+  for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) {
+     addr = addr1 + i;
+     __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr) : "memory");
+  }
+  addr = addr1 + size - 1;
+  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr) : "memory");
+}
+
+
+int ffi_closure_helper_SYSV (ffi_closure*, void*, unsigned long*, 
+                                     unsigned long*, unsigned long*);
+
+/* Basically the trampoline invokes ffi_closure_SYSV, 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_SYSV invokes the 
+ * following helper function to do most of the work
+ */
+
+int
+ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, 
+            unsigned long * pgr, unsigned long * pfr, 
+            unsigned long * pst)
+{
+  /* 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_SYSV */
+  /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV  */
+  /* pst is the pointer to outgoing parameter stack in original caller */
+
+  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; 
+
+  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 = *pgr;
+      ng++;
+      pgr++;
+    }
+
+  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:
+	/* there are 8 gpr registers used to pass values */
+          if (ng < 8) {
+	     avalue[i] = (((char *)pgr)+3);
+             ng++;
+             pgr++;
+          } else {
+             avalue[i] = (((char *)pst)+3);
+             pst++;
+          }
+	  break;
+           
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	/* there are 8 gpr registers used to pass values */
+          if (ng < 8) {
+	     avalue[i] = (((char *)pgr)+2);
+             ng++;
+             pgr++;
+          } else {
+             avalue[i] = (((char *)pst)+2);
+             pst++;
+          }
+	  break;
+
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_POINTER:
+	case FFI_TYPE_STRUCT:
+	/* there are 8 gpr registers used to pass values */
+          if (ng < 8) {
+	     avalue[i] = pgr;
+             ng++;
+             pgr++;
+          } else {
+             avalue[i] = pst;
+             pst++;
+          }
+	  break;
+
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  /* passing long long ints are complex, they must
+           * be passed in suitable register pairs such as
+           * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
+           * and if the entire pair aren't available then the outgoing
+           * parameter stack is used for both but an alignment of 8
+           * must will be kept.  So we must either look in pgr
+           * or pst to find the correct address for this type
+           * of parameter.
+           */
+           if (ng < 7) {
+              if (ng & 0x01) {
+		/* skip r4, r6, r8 as starting points */
+                  ng++;
+                  pgr++;
+              }
+              avalue[i] = pgr;
+              ng+=2;
+              pgr+=2;
+           } else {
+              if (((long)pst) & 4) pst++;
+              avalue[i] = pst;
+              pst+=2;
+           }
+           break;
+
+	case FFI_TYPE_FLOAT:
+	    /* unfortunately float values are stored as doubles
+             * in the ffi_closure_SYSV code (since we don't check
+             * the type in that routine).  This is also true
+             * of floats passed on the outgoing parameter stack.
+             * Also, on the outgoing stack all values are aligned
+             * to 8
+             *
+             * Don't you just love the simplicity of this ABI!
+             */
+
+          /* there are 8 64bit floating point registers */
+
+          if (nf < 8) {
+	     temp = *(double*)pfr;
+             *(float*)pfr = (float)temp;
+	     avalue[i] = pfr;
+             nf++;
+             pfr+=2;
+          } else {
+	    /* FIXME? here we are really changing the values
+             * stored in the original calling routines outgoing
+             * parameter stack.  This is probably a really
+             * naughty thing to do but...
+             */
+	     if (((long)pst) & 4) pst++;
+	     temp = *(double*)pst;
+             *(float*)pst = (float)temp;
+	     avalue[i] = pst;
+             nf++;
+             pst+=2;
+          }
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  /* On the outgoing stack all values are aligned to 8 */
+          /* there are 8 64bit floating point registers */
+
+          if (nf < 8) {
+	     avalue[i] = pfr;
+             nf++;
+             pfr+=2;
+          } else {
+	     if (((long)pst) & 4) pst++;
+	     avalue[i] = pst;
+             nf++;
+             pst+=2;
+          }
+	  break;
+
+	default:
+	  FFI_ASSERT(0);
+	}
+
+      i++;
+    }
+
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_osf how to perform return type promotions.  */
+  return cif->rtype->type;
+
+}
+
+
+
+
+

+ 148 - 0
libffi/powerpc/ppc_closure.S

@@ -0,0 +1,148 @@
+#define LIBFFI_ASM
+#include <powerpc/asm.h>
+
+.globl	ffi_closure_helper_SYSV
+
+ENTRY(ffi_closure_SYSV)
+	stwu %r1,-144(%r1)
+	mflr %r0
+	stw %r31,140(%r1)
+	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
+	addis %r4,0,.L60@ha  # get address of jump table
+	addi %r4,%r4,.L60@l
+	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
+	.align 2
+.L60:
+	.long .L44-.L60    # FFI_TYPE_VOID
+	.long .L50-.L60    # FFI_TYPE_INT
+	.long .L47-.L60    # FFI_TYPE_FLOAT
+	.long .L46-.L60    # FFI_TYPE_DOUBLE
+	.long .L46-.L60    # FFI_TYPE_LONGDOUBLE
+	.long .L56-.L60    # FFI_TYPE_UINT8
+	.long .L55-.L60    # FFI_TYPE_SINT8
+	.long .L58-.L60    # FFI_TYPE_UINT16
+	.long .L57-.L60    # FFI_TYPE_SINT16
+	.long .L50-.L60    # FFI_TYPE_UINT32
+	.long .L50-.L60    # FFI_TYPE_SINT32
+	.long .L48-.L60    # FFI_TYPE_UINT64
+	.long .L48-.L60    # FFI_TYPE_SINT64
+	.long .L44-.L60    # FFI_TYPE_STRUCT
+	.long .L50-.L60    # FFI_TYPE_POINTER
+
+
+# case double
+.L46:   
+        lfd %f1,0(%r5)
+	b .L44
+
+# case float
+.L47:
+	lfs %f1,0(%r5)
+	b .L44
+	
+# case long long
+.L48:
+	lwz %r3,0(%r5)
+	lwz %r4,4(%r5)
+	b .L44
+	
+# case default / int32 / pointer
+.L50:
+	lwz %r3,0(%r5)
+	b .L44
+	
+# case signed int8	
+.L55:
+	addi %r5,%r5,3
+	lbz %r3,0(%r5)
+	extsb %r3,%r3
+	b .L44
+
+# case unsigned int8	
+.L56:
+	addi %r5,%r5,3
+        lbz %r3,0(%r5)
+	b .L44
+
+# case signed int16
+.L57:
+	addi %r5,%r5,2
+	lhz %r3,0(%r5)
+	extsh %r3,%r3
+	b .L44
+
+#case unsigned int16
+.L58:	
+	addi %r5,%r5,2
+	lhz %r3,0(%r5)
+
+# case void / done	
+.L44:
+	
+	lwz %r11,0(%r1)
+	lwz %r0,4(%r11)
+	mtlr %r0
+	lwz %r31,-4(%r11)
+	mr %r1,%r11
+	blr
+END(ffi_closure_SYSV)
+
+
+
+

+ 119 - 0
libffi/powerpc/sysv.S

@@ -0,0 +1,119 @@
+/* -----------------------------------------------------------------------
+   sysv.h - Copyright (c) 1998 Geoffrey Keating
+   
+   PowerPC Assembly glue.
+
+   $Id: sysv.S,v 1.1 2001/08/02 19:31:55 orph 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 LIBFFI_ASM	
+#include <ffi.h>
+#include <powerpc/asm.h>
+
+	.globl ffi_prep_args
+ENTRY(ffi_call_SYSV)
+	/* 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,   4(%r8)
+
+	/* 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
+	bl	JUMPTARGET(ffi_prep_args)
+
+	/* 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.  */
+	lwz	%r3,-16-(8*4)(%r28)
+	lwz	%r4,-16-(7*4)(%r28)
+	lwz	%r5,-16-(6*4)(%r28)
+	lwz	%r6,-16-(5*4)(%r28)
+	bf-	5,1f
+	nop
+	lwz	%r7,-16-(4*4)(%r28)
+	lwz	%r8,-16-(3*4)(%r28)
+	lwz	%r9,-16-(2*4)(%r28)
+	lwz	%r10,-16-(1*4)(%r28)
+	nop
+1:
+
+	/* Load all the FP registers.  */
+	bf-	6,2f
+	lfd	%f1,-16-(8*4)-(8*8)(%r28)
+	lfd	%f2,-16-(8*4)-(7*8)(%r28)
+	lfd	%f3,-16-(8*4)-(6*8)(%r28)
+	lfd	%f4,-16-(8*4)-(5*8)(%r28)
+	nop
+	lfd	%f5,-16-(8*4)-(4*8)(%r28)
+	lfd	%f6,-16-(8*4)-(3*8)(%r28)
+	lfd	%f7,-16-(8*4)-(2*8)(%r28)
+	lfd	%f8,-16-(8*4)-(1*8)(%r28)
+2:
+
+	/* 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,   4(%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)
+END(ffi_call_SYSV)

+ 146 - 0
libffi/prep_cif.c

@@ -0,0 +1,146 @@
+/* -----------------------------------------------------------------------
+   prep_cif.c - Copyright (c) 1996, 1998  Cygnus Solutions
+
+   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 RED HAT 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_private.h>
+#include <stdlib.h>
+
+
+/* Round up to SIZEOF_ARG. */
+
+#define STACK_ARG_SIZE(x) ALIGN(x, 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(ffi_type_test((*ptr)));
+
+      arg->size = ALIGN(arg->size, (*ptr)->alignment);
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ? 
+	arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  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_LAST_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(ffi_type_test(cif->rtype));
+
+#ifndef M68K
+  /* 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++)
+    {
+      /* Perform a sanity check on the argument type */
+      FFI_ASSERT(ffi_type_test(*ptr));
+
+      /* Initialize any uninitialized aggregate type definitions */
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+	return FFI_BAD_TYPEDEF;
+
+#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);
+	}
+    }
+
+  cif->bytes = bytes;
+
+  /* Perform machine dependent cif processing */
+  return ffi_prep_cif_machdep(cif);
+}

+ 240 - 0
libffi/raw_api.c

@@ -0,0 +1,240 @@
+/* -----------------------------------------------------------------------
+   raw_api.c - Copyright (c) 1999  Cygnus Solutions
+
+   Author: Kresten Krab Thorup <[email protected]>
+
+   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 RED HAT 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_private.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*), SIZEOF_ARG);
+      else
+#endif
+	result += ALIGN ((*at)->size, 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++) + SIZEOF_ARG - 1);
+	  break;
+	  
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT16:
+	  *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
+	  break;
+
+#if SIZEOF_ARG >= 4	  
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	  *args = (void*) ((char*)(raw++) + 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, SIZEOF_ARG) / 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 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, SIZEOF_ARG) / 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 */

+ 589 - 0
libffi/s390/ffi.c

@@ -0,0 +1,589 @@
+/* -----------------------------------------------------------------------
+   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_private.h>
+ 
+#include <stdlib.h>
+#include <stdio.h>
+ 
+/*====================== End of Includes =============================*/
+ 
+/*====================================================================*/
+/*                           Defines                                  */
+/*                           -------                                  */
+/*====================================================================*/
+ 
+#define MAX_GPRARGS 5        /* Max. no. of GPR available             */
+#define MAX_FPRARGS 2        /* Max. no. of FPR available             */
+ 
+#define STR_GPR     1        /* Structure will fit in 1 or 2 GPR      */
+#define STR_FPR     2        /* Structure will fit in a FPR           */
+#define STR_STACK   3        /* Structure needs to go on stack        */
+ 
+/*===================== End of Defines ===============================*/
+ 
+/*====================================================================*/
+/*                            Types                                   */
+/*                            -----                                   */
+/*====================================================================*/
+ 
+typedef struct stackLayout
+{
+  int   *backChain;
+  int   *endOfStack;
+  int   glue[2];
+  int   scratch[2];
+  int   gprArgs[MAX_GPRARGS];
+  int   notUsed;
+  union
+  {
+    float  f;
+    double d;
+  } fprArgs[MAX_FPRARGS];
+  int   unUsed[8];
+  int   outArgs[100];
+} stackLayout;
+ 
+/*======================== End of Types ==============================*/
+ 
+/*====================================================================*/
+/*                          Prototypes                                */
+/*                          ----------                                */
+/*====================================================================*/
+ 
+void ffi_prep_args(stackLayout *, extended_cif *);
+static int  ffi_check_struct(ffi_type *, unsigned int *);
+static void ffi_insert_int(int, stackLayout *, int *, int *);
+static void ffi_insert_int64(long long, stackLayout *, int *, int *);
+static void ffi_insert_double(double, stackLayout *, int *, int *);
+ 
+/*====================== End of Prototypes ===========================*/
+ 
+/*====================================================================*/
+/*                          Externals                                 */
+/*                          ---------                                 */
+/*====================================================================*/
+ 
+extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *),
+			  extended_cif *,
+			  unsigned, unsigned,
+			  unsigned *,
+			  void (*fn)());
+ 
+/*====================== End of Externals ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_check_struct.                                       */
+/*                                                                    */
+/* Function - Determine if a structure can be passed within a         */
+/*            general or floating point register.                     */
+/*                                                                    */
+/*====================================================================*/
+ 
+int
+ffi_check_struct(ffi_type *arg, unsigned int *strFlags)
+{
+ ffi_type *element;
+ int      i_Element;
+ 
+ for (i_Element = 0; arg->elements[i_Element]; i_Element++) {
+   element = arg->elements[i_Element];
+   switch (element->type) {
+   case FFI_TYPE_DOUBLE :
+     *strFlags |= STR_FPR;
+     break;
+     
+   case FFI_TYPE_STRUCT :
+     *strFlags |= ffi_check_struct(element, strFlags);
+     break;
+     
+   default :
+     *strFlags |= STR_GPR;
+   }
+ }
+ return (*strFlags);
+}
+ 
+/*======================== End of Routine ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_insert_int.                                         */
+/*                                                                    */
+/* Function - Insert an integer parameter in a register if there are  */
+/*            spares else on the stack.                               */
+/*                                                                    */
+/*====================================================================*/
+ 
+void
+ffi_insert_int(int gprValue, stackLayout *stack,
+               int *intArgC, int *outArgC)
+{
+  if (*intArgC < MAX_GPRARGS) {
+    stack->gprArgs[*intArgC] = gprValue;
+    *intArgC += 1;
+  }
+  else {
+    stack->outArgs[*outArgC++] = gprValue;
+    *outArgC += 1;
+  }
+}
+ 
+/*======================== End of Routine ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_insert_int64.                                       */
+/*                                                                    */
+/* Function - Insert a long long parameter in registers if there are  */
+/*            spares else on the stack.                               */
+/*                                                                    */
+/*====================================================================*/
+ 
+void
+ffi_insert_int64(long long llngValue, stackLayout *stack,
+                 int *intArgC, int *outArgC)
+{
+ 
+  if (*intArgC < (MAX_GPRARGS-1)) {
+    memcpy(&stack->gprArgs[*intArgC],
+	   &llngValue, sizeof(long long));	
+    *intArgC += 2;
+  }
+  else {
+    memcpy(&stack->outArgs[*outArgC],
+	   &llngValue, sizeof(long long));
+    *outArgC += 2;
+  }
+ 
+}
+ 
+/*======================== End of Routine ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_insert_double.                                      */
+/*                                                                    */
+/* Function - Insert a double parameter in a FP register if there is  */
+/*            a spare else on the stack.                              */
+/*                                                                    */
+/*====================================================================*/
+ 
+void
+ffi_insert_double(double dblValue, stackLayout *stack,
+                  int *fprArgC, int *outArgC)
+{
+ 
+  if (*fprArgC < MAX_FPRARGS) {
+    stack->fprArgs[*fprArgC].d = dblValue;
+    *fprArgC += 1;
+  }
+  else {
+    memcpy(&stack->outArgs[*outArgC],
+	   &dblValue,sizeof(double));
+    *outArgC += 2;
+  }
+ 
+}
+ 
+/*======================== 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.                   */
+/*                                                                    */
+/* The stack layout we want looks like this:                          */
+/* *------------------------------------------------------------*     */
+/* |  0     | Back chain (a 0 here signifies end of back chain) |     */
+/* +--------+---------------------------------------------------+     */
+/* |  4     | EOS (end of stack, not used on Linux for S390)    |     */
+/* +--------+---------------------------------------------------+     */
+/* |  8     | Glue used in other linkage formats                |     */
+/* +--------+---------------------------------------------------+     */
+/* | 12     | Glue used in other linkage formats                |     */
+/* +--------+---------------------------------------------------+     */
+/* | 16     | Scratch area                                      |     */
+/* +--------+---------------------------------------------------+     */
+/* | 20     | Scratch area                                      |     */
+/* +--------+---------------------------------------------------+     */
+/* | 24     | GPR parameter register 1                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 28     | GPR parameter register 2                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 32     | GPR parameter register 3                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 36     | GPR parameter register 4                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 40     | GPR parameter register 5                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 44     | Unused                                            |     */
+/* +--------+---------------------------------------------------+     */
+/* | 48     | FPR parameter register 1                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 56     | FPR parameter register 2                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 64     | Unused                                            |     */
+/* +--------+---------------------------------------------------+     */
+/* | 96     | Outgoing args (length x)                          |     */
+/* +--------+---------------------------------------------------+     */
+/* | 96+x   | Copy area for structures (length y)               |     */
+/* +--------+---------------------------------------------------+     */
+/* | 96+x+y | Possible stack alignment                          |     */
+/* *------------------------------------------------------------*     */
+/*                                                                    */
+/*====================================================================*/
+ 
+void
+ffi_prep_args(stackLayout *stack, extended_cif *ecif)
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+ 
+  /*----------------------------------------------------------*/
+  /* Pointer to the copy area on stack for structures         */
+  /*----------------------------------------------------------*/
+  char *copySpace = (char *) stack + bytes + sizeof(stackLayout);
+ 
+  /*----------------------------------------------------------*/
+  /* Count of general and floating point register usage       */
+  /*----------------------------------------------------------*/
+  int intArgC = 0,
+    fprArgC = 0,
+    outArgC = 0;
+ 
+  int      i;
+  ffi_type **ptr;
+  void     **p_argv;
+  size_t   structCopySize;
+  unsigned gprValue, strFlags = 0;
+  unsigned long long llngValue;
+  double   dblValue;
+ 
+  /* Now for the arguments.  */
+  p_argv  = ecif->avalue;
+ 
+  /*----------------------------------------------------------------------*/
+  /* If we returning a structure then we set the first parameter register */
+  /* to the address of where we are returning this structure              */
+  /*----------------------------------------------------------------------*/
+  if (flags == FFI_TYPE_STRUCT)
+    stack->gprArgs[intArgC++] = (int) ecif->rvalue;
+ 
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      switch ((*ptr)->type) {
+ 
+      case FFI_TYPE_FLOAT:
+	if (fprArgC < MAX_FPRARGS)
+	  stack->fprArgs[fprArgC++].f = *(float *) *p_argv;
+	else
+	  stack->outArgs[outArgC++] = *(int *) *p_argv;
+	break;
+ 
+      case FFI_TYPE_DOUBLE:
+	dblValue = *(double *) *p_argv;
+	ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
+	break;
+	
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+	llngValue = *(unsigned long long *) *p_argv;
+	ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
+	break;
+ 
+      case FFI_TYPE_UINT8:
+	gprValue = *(unsigned char *)*p_argv;
+	ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+	break;
+ 
+      case FFI_TYPE_SINT8:
+	gprValue = *(signed char *)*p_argv;
+	ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+	break;
+ 
+      case FFI_TYPE_UINT16:
+	gprValue = *(unsigned short *)*p_argv;
+	ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+	break;
+ 
+      case FFI_TYPE_SINT16:
+	gprValue = *(signed short *)*p_argv;
+	ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+	break;
+ 
+      case FFI_TYPE_STRUCT:
+	/*--------------------------------------------------*/
+	/* If structure > 8 bytes then it goes on the stack */
+	/*--------------------------------------------------*/
+	if (((*ptr)->size > 8) ||
+	    ((*ptr)->size > 4  &&
+	     (*ptr)->size < 8))
+	  strFlags = STR_STACK;
+	else
+	  strFlags = ffi_check_struct((ffi_type *) *ptr, &strFlags);
+ 
+	switch (strFlags) {
+	/*-------------------------------------------*/
+	/* Structure that will fit in one or two GPR */
+	/*-------------------------------------------*/
+	case STR_GPR :
+	  if ((*ptr)->size <= 4) {
+	    gprValue = *(unsigned int *) *p_argv;
+	    gprValue = gprValue >> ((4 - (*ptr)->size) * 8);
+	    ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+	  }
+	  else {
+	    llngValue = *(unsigned long long *) *p_argv;
+	    ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
+	  }
+	  break;
+ 
+	/*-------------------------------------------*/
+	/* Structure that will fit in one FPR        */
+	/*-------------------------------------------*/
+	case STR_FPR :
+	  dblValue = *(double *) *p_argv;
+	  ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
+	  break;
+ 
+	/*-------------------------------------------*/
+	/* Structure that must be copied to stack    */
+	/*-------------------------------------------*/
+	default :
+	  structCopySize = (((*ptr)->size + 15) & ~0xF);
+	  copySpace -= structCopySize;
+	  memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
+	  gprValue = (unsigned) copySpace;
+	  if (intArgC < MAX_GPRARGS)
+	    stack->gprArgs[intArgC++] = gprValue;
+	  else
+	    stack->outArgs[outArgC++] = gprValue;
+	}
+	break;
+ 
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      case FFI_TYPE_LONGDOUBLE:
+	structCopySize = (((*ptr)->size + 15) & ~0xF);
+	copySpace -= structCopySize;
+	memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
+	gprValue = (unsigned) copySpace;
+	if (intArgC < MAX_GPRARGS)
+	  stack->gprArgs[intArgC++] = gprValue;
+	else
+	  stack->outArgs[outArgC++] = gprValue;
+	break;
+#endif
+ 
+      case FFI_TYPE_INT:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_POINTER:
+	gprValue = *(unsigned *)*p_argv;
+	if (intArgC < MAX_GPRARGS)
+	  stack->gprArgs[intArgC++] = gprValue;
+	else
+	  stack->outArgs[outArgC++] = gprValue;
+	break;
+ 
+      }
+    }
+}
+ 
+/*======================== End of Routine ============================*/
+ 
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_prep_cif_machdep.                                   */
+/*                                                                    */
+/* Function - Perform machine dependent CIF processing.               */
+/*                                                                    */
+/*====================================================================*/
+ 
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i;
+  ffi_type **ptr;
+  unsigned bytes;
+  int fpArgC  = 0,
+    intArgC = 0;
+  unsigned flags = 0;
+  unsigned structCopySize = 0;
+ 
+  /*-----------------------------------------------------------------*/
+  /* Extra space required in stack for overflow parameters.          */
+  /*-----------------------------------------------------------------*/
+  bytes = 0;
+ 
+  /*--------------------------------------------------------*/
+  /* Return value handling.  The rules are as follows:	    */
+  /* - 32-bit (or less) integer values are returned in gpr2 */
+  /* - Structures are returned as pointers in gpr2	    */
+  /* - 64-bit integer values are returned in gpr2 and 3	    */
+  /* - Single/double FP values are returned in fpr0	    */
+  /*--------------------------------------------------------*/
+  flags = cif->rtype->type;
+ 
+  /*------------------------------------------------------------------------*/
+  /* The first MAX_GPRARGS words of integer arguments, and the      	    */
+  /* first MAX_FPRARGS floating point 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:
+	  fpArgC++;
+	  if (fpArgC > MAX_FPRARGS && intArgC%2 != 0)
+	    intArgC++;
+	  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 ((intArgC == MAX_GPRARGS-1) ||
+	      (intArgC >= MAX_GPRARGS)   &&
+	      (intArgC%2 != 0))
+	    intArgC++;
+	  intArgC += 2;
+	  break;
+ 
+	case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+#endif
+	  /*----------------------------------------------------*/
+	  /* We must allocate space for a copy of these to      */
+	  /* enforce pass-by-value. Pad the space up to a       */
+	  /* multiple of 16 bytes (the maximum alignment 	      */
+	  /* required for anything under the SYSV ABI). 	      */
+	  /*----------------------------------------------------*/
+	  structCopySize += ((*ptr)->size + 15) & ~0xF;
+	  /*----------------------------------------------------*/
+	  /* Fall through (allocate space for the pointer).     */
+	  /*----------------------------------------------------*/
+ 
+	default:
+	  /*----------------------------------------------------*/
+	  /* Everything else is passed as a 4-byte word in a    */
+	  /* GPR either the object itself or a pointer to it.   */
+	  /*----------------------------------------------------*/
+	  intArgC++;
+	  break;
+	}
+    }
+ 
+  /*-----------------------------------------------------------------*/
+  /* Stack space.                                                    */
+  /*-----------------------------------------------------------------*/
+  if (intArgC > MAX_GPRARGS)
+    bytes += (intArgC - MAX_GPRARGS) * sizeof(int);
+  if (fpArgC > MAX_FPRARGS)
+    bytes += (fpArgC - MAX_FPRARGS) * sizeof(double);
+ 
+  /*-----------------------------------------------------------------*/
+  /* The stack space allocated needs to be a multiple of 16 bytes.   */
+  /*-----------------------------------------------------------------*/
+  bytes = (bytes + 15) & ~0xF;
+ 
+  /*-----------------------------------------------------------------*/
+  /* Add in the space for the copied structures.                     */
+  /*-----------------------------------------------------------------*/
+  bytes += structCopySize;
+ 
+  cif->flags = flags;
+  cif->bytes = bytes;
+ 
+  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)
+{
+  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)
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args,
+		    &ecif, cif->bytes,
+		    cif->flags, ecif.rvalue, fn);
+      break;
+ 
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+ 
+/*======================== End of Routine ============================*/

+ 161 - 0
libffi/s390/sysv.S

@@ -0,0 +1,161 @@
+/* -----------------------------------------------------------------------
+   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 <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#endif
+	
+.text
+ 
+	# r2:	ffi_prep_args
+	# r3:	&ecif
+	# r4:	cif->bytes
+	# r5:	fig->flags
+	# r6:	ecif.rvalue
+	# sp+0: fn
+ 
+	# This assumes we are using gas.
+	.globl	ffi_call_SYSV
+	.type	ffi_call_SYSV,%function
+ffi_call_SYSV:
+	# Save registers
+	stm	%r7,%r15,28(%r15)
+	l	%r7,96(%r15)	       # Get A(fn)
+	lr	%r0,%r15
+	ahi	%r15,-128	       # Make room for my args
+	st	%r0,0(%r15)	       # Set backchain
+	lr	%r11,%r15	       # Establish my stack register
+	sr	%r15,%r4	       # Make room for fn args
+	ahi	%r15,-96	       # Make room for new frame
+	lr	%r10,%r15	       # Establish stack build area
+	ahi	%r15,-96	       # Stack for next call
+	lr	%r1,%r7
+	stm	%r2,%r7,96(%r11)       # Save args on my stack
+ 
+#------------------------------------------------------------------
+#	move first 3 parameters in registers
+#------------------------------------------------------------------
+	lr	%r9,%r2		       # r9:	 &ffi_prep_args
+	lr	%r2,%r10	       # Parm 1: &stack Parm 2: &ecif
+	basr	%r14,%r9	       # call ffi_prep_args
+ 
+#------------------------------------------------------------------
+#	load  first 5 parameter registers
+#------------------------------------------------------------------
+	lm	%r2,%r6,24(%r10)
+ 
+#------------------------------------------------------------------
+#	load  fp parameter registers
+#------------------------------------------------------------------
+	ld	%f0,48(%r10)
+	ld	%f2,56(%r10)
+ 
+#------------------------------------------------------------------
+#	call  function
+#------------------------------------------------------------------
+	lr	%r15,%r10	       # Set new stack
+	l	%r9,116(%r11)	       # Get &fn
+	basr	%r14,%r9	       # Call function
+ 
+#------------------------------------------------------------------
+#	On return:
+#	   r2: Return value (r3: Return value + 4 for long long)
+#------------------------------------------------------------------
+ 
+#------------------------------------------------------------------
+#	If the return value pointer is NULL, assume no return value.
+#------------------------------------------------------------------
+	icm	%r6,15,112(%r11)
+	jz	.Lepilogue
+ 
+	l	%r5,108(%r11)	       # Get return type
+#------------------------------------------------------------------
+#	return INT
+#------------------------------------------------------------------
+	chi	%r5,FFI_TYPE_INT
+	jne	.Lchk64
+ 
+	st	%r2,0(%r6)
+	j	.Lepilogue
+ 
+.Lchk64:
+#------------------------------------------------------------------
+#	return LONG LONG (signed/unsigned)
+#------------------------------------------------------------------
+	chi	%r5,FFI_TYPE_UINT64
+	je	.LdoLongLong
+ 
+	chi	%r5,FFI_TYPE_SINT64
+	jne	.LchkFloat
+ 
+.LdoLongLong:
+	stm	%r2,%r3,0(%r6)
+	j	.Lepilogue
+ 
+.LchkFloat:
+#------------------------------------------------------------------
+#	return FLOAT
+#------------------------------------------------------------------
+	chi	%r5,FFI_TYPE_FLOAT
+	jne	.LchkDouble
+ 
+	std	%f0,0(%r6)
+	j	.Lepilogue
+ 
+.LchkDouble:
+#------------------------------------------------------------------
+#	return DOUBLE or LONGDOUBLE
+#------------------------------------------------------------------
+	chi	%r5,FFI_TYPE_DOUBLE
+	jne	.LchkStruct
+ 
+	std	%f0,0(%r6)
+	std	%f2,8(%r6)
+	j	.Lepilogue
+ 
+.LchkStruct:
+#------------------------------------------------------------------
+# Structure - rvalue already set as sent as 1st parm to routine
+#------------------------------------------------------------------
+	chi	%r5,FFI_TYPE_STRUCT
+	je	.Lepilogue
+ 
+.Ldefault:
+#------------------------------------------------------------------
+#	return a pointer
+#------------------------------------------------------------------
+	st	%r2,0(%r6)
+	j	.Lepilogue
+ 
+.Lepilogue:
+	l	%r15,0(%r11)
+	l	%r4,56(%r15)
+	lm	%r7,%r15,28(%r15)
+	br	%r4
+ 
+.ffi_call_SYSV_end:
+	.size	 ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV

+ 422 - 0
libffi/sparc/ffi.c

@@ -0,0 +1,422 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996 Cygnus Solutions
+   
+   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_private.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;
+  int tmp;
+  int avn;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  tmp = 0;
+
+  /* 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
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i && avn;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      if (avn) 
+	{
+	  avn--;
+	  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;
+      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_return_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_return_struct(*ptr, off, ret, intg, flt);
+	  break;
+	case FFI_TYPE_FLOAT:
+	case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+	case FFI_TYPE_LONGDOUBLE:
+#endif
+	  memcpy(ret + off, flt + off, (*ptr)->size);
+	  off += (*ptr)->size;
+	  break;
+	default:
+	  memcpy(ret + off, intg + off, (*ptr)->size);
+	  off += (*ptr)->size;
+	  break;
+	}
+      ptr++;
+    }
+  return off;
+}
+
+extern int ffi_call_V8(void *, extended_cif *, unsigned, 
+		       unsigned, unsigned *, void (*fn)());
+extern int ffi_call_V9(void *, extended_cif *, unsigned, 
+		       unsigned, unsigned *, void (*fn)());
+
+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_return_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;
+    }
+
+}

+ 94 - 0
libffi/sparc/v8.S

@@ -0,0 +1,94 @@
+/* -----------------------------------------------------------------------
+   v8.S - Copyright (c) 1996, 1997 Cygnus Solutions
+   
+   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 <ffi.h>
+#include <ffi_private.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:
+	save	%sp, -STACKFRAME, %sp
+	
+	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
+
+.ffi_call_V8_end:
+        .size    ffi_call_V8,.ffi_call_V8_end-ffi_call_V8
+

+ 126 - 0
libffi/sparc/v9.S

@@ -0,0 +1,126 @@
+/* -----------------------------------------------------------------------
+   v9.S - Copyright (c) 2000 Cygnus Solutions
+   
+   Sparc 64bit 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 <ffi.h>
+#include <ffi_private.h>
+	
+#if defined(__arch64__) || defined(__sparcv9)
+/* 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:
+	save	%sp, -STACKFRAME, %sp
+	
+	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]	! (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
+
+.ffi_call_V9_end:
+        .size    ffi_call_V9,.ffi_call_V9_end-ffi_call_V9
+
+#endif

+ 1 - 0
libffi/stamp-h.in

@@ -0,0 +1 @@
+timestamp

+ 15 - 0
libffi/testsuite/Makefile.am

@@ -0,0 +1,15 @@
+## 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`
+
+RUNTESTFLAGS = @AM_RUNTESTFLAGS@
+

+ 1 - 0
libffi/testsuite/config/default.exp

@@ -0,0 +1 @@
+load_lib "standard.exp"

+ 44 - 0
libffi/testsuite/lib/libffi.exp

@@ -0,0 +1,44 @@
+# Copyright (C) 2001  Red Hat, Inc.
+
+load_lib "libgloss.exp"
+
+global tmpdir
+
+if ![info exists tmpdir] {
+    set tmpdir "/tmp"
+}
+
+proc test_libffi {src} {
+
+    global tmpdir srcdir
+
+    set executable $tmpdir/[file tail [file rootname $src].x]
+
+    regsub "^$srcdir/?" $src "" testcase
+    # If we couldn't rip $srcdir out of `src' then just do the best we can.
+    # The point is to reduce the unnecessary noise in the logs.  Don't strip
+    # out too much because different testcases with the same name can confuse
+    # `test-tool'.
+    if [string match "/*" $testcase] {
+	set testcase "[file tail [file dirname $src]]/[file tail $src]"
+    }
+
+    remote_file build delete $executable;
+    verbose "Testing $testcase" 1
+
+    set comp_output [target_compile $src $executable executable "additional_flags=-g additional_flags=-I$srcdir/../include libs=../.libs/libffi.a"]
+
+    set result [libffi_load "$executable" "" ""]
+    set status [lindex $result 0];
+    set output [lindex $result 1];
+
+    $status "$testcase"
+
+#    if { $status == "pass" } {
+#	remote_file build delete $executable;
+#    }
+} 
+
+# Local Variables:
+# tcl-indent-level:4
+# End:

+ 13 - 0
libffi/testsuite/libffi.call/call.exp

@@ -0,0 +1,13 @@
+global srcdir subdir
+
+catch "glob -nocomplain ${srcdir}/${subdir}/*.c" srcfiles
+verbose "srcfiles are $srcfiles"
+
+set prefix ""
+foreach x $srcfiles {
+    test_libffi $x
+}
+
+# Local Variables:
+# tcl-indent-level:4
+# End:

+ 4 - 0
libffi/testsuite/libffi.call/ffitest.h

@@ -0,0 +1,4 @@
+#include <ffi.h>
+
+#define CHECK(x) !(x) ? abort() : 0 
+

+ 55 - 0
libffi/testsuite/libffi.call/float.c

@@ -0,0 +1,55 @@
+#include "ffitest.h"
+
+static int floating(int a, float b, double c, long double d, int e)
+{
+  int i;
+
+  i = (int) ((float)a/b + ((float)c/(float)d));
+
+  return i;
+}
+
+int 
+main ()
+{
+  ffi_cif cif;
+  ffi_type *args[5];
+  void *values[5];
+  int si1, si2;
+  float f;
+  double d;
+  long double ld;
+  int rint __attribute__((aligned(8)));
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si1;
+  args[1] = &ffi_type_float;
+  values[1] = &f;
+  args[2] = &ffi_type_double;
+  values[2] = &d;
+  args[3] = &ffi_type_longdouble;
+  values[3] = &ld;
+  args[4] = &ffi_type_sint;
+  values[4] = &si2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
+		     &ffi_type_sint, args) == FFI_OK);
+  
+  si1 = 6;
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+  si2 = 10;
+  
+  floating (si1, f, d, ld, si2);
+  
+  ffi_call(&cif, FFI_FN(floating), &rint, values);
+  
+  printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
+  
+  CHECK(rint == floating(si1, f, d, ld, si2));
+  
+  exit (0);
+}
+  

+ 63 - 0
libffi/testsuite/libffi.call/many.c

@@ -0,0 +1,63 @@
+#include "ffitest.h"
+
+#include <float.h>
+
+static float many(float f1,
+		  float f2,
+		  float f3,
+		  float f4,
+		  float f5,
+		  float f6,
+		  float f7,
+		  float f8,
+		  float f9,
+		  float f10,
+		  float f11,
+		  float f12,
+		  float f13)
+{
+#if 1
+  printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+	 (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, 
+	 (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+	 (double) f11, (double) f12, (double) f13);
+#endif
+
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int 
+main ()
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  float fa[13];
+  float f, ff;
+  int i;
+
+  for (i = 0; i < 13; i++)
+    {
+      args[i] = &ffi_type_float;
+      values[i] = &fa[i];
+      fa[i] = (float) i;
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+		       &ffi_type_float, args) == FFI_OK);
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    ff =  many(fa[0], fa[1],
+	       fa[2], fa[3],
+	       fa[4], fa[5],
+	       fa[6], fa[7],
+	       fa[8], fa[9],
+	       fa[10],fa[11],fa[12]);
+
+    if (f - ff < FLT_EPSILON)
+      exit(0);
+    else
+      abort();
+}

+ 38 - 0
libffi/testsuite/libffi.call/strlen.c

@@ -0,0 +1,38 @@
+#include "ffitest.h"
+
+static size_t my_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+int 
+main ()
+{
+  ffi_cif cif;
+  ffi_type *args[1];
+  void *values[1];
+  int rint __attribute__((aligned(8)));
+  char *s;
+
+  args[0] = &ffi_type_pointer;
+  values[0] = (void*) &s;
+    
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+		     &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 7);
+  
+  s = "1234567890123456789012345";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 25);
+  
+  exit (0);
+}
+  

+ 153 - 0
libffi/types.c

@@ -0,0 +1,153 @@
+/* -----------------------------------------------------------------------
+   types.c - Copyright (c) 1996, 1998  Cygnus Solutions
+   
+   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 RED HAT 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_private.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
+
+FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
+
+#endif
+
+#ifdef __i386__
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#elif defined X86_WIN32
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#elif defined ARM
+
+FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
+FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
+
+#elif defined M68K
+
+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
+
+
+#ifdef __i386__
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined X86_WIN32
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined ARM
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
+
+#elif defined M68K
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 12, 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
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
+
+#endif
+
+#if SIZEOF_SHORT==1
+extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint8")));
+extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint8")));
+#elif SIZEOF_SHORT==2
+extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint16")));
+extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint16")));
+#elif SIZEOF_SHORT==4
+extern ffi_type ffi_type_sshort __attribute__((alias("ffi_type_sint32")));
+extern ffi_type ffi_type_ushort __attribute__((alias("ffi_type_uint32")));
+#endif
+
+#if SIZEOF_INT==2
+extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint16")));
+extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint16")));
+#elif SIZEOF_INT==4
+extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint32")));
+extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint32")));
+#elif SIZEOF_INT==8
+extern ffi_type ffi_type_sint __attribute__((alias("ffi_type_sint64")));
+extern ffi_type ffi_type_uint __attribute__((alias("ffi_type_uint64")));
+#endif
+
+#if SIZEOF_LONG==4
+extern ffi_type ffi_type_slong __attribute__((alias("ffi_type_sint32")));
+extern ffi_type ffi_type_ulong __attribute__((alias("ffi_type_uint32")));
+#elif SIZEOF_INT==8
+extern ffi_type ffi_type_slong __attribute__((alias("ffi_type_sint64")));
+extern ffi_type ffi_type_ulong __attribute__((alias("ffi_type_uint64")));
+#endif
+

+ 508 - 0
libffi/x86/ffi.c

@@ -0,0 +1,508 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 1998, 1999  Cygnus Solutions
+   
+   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.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_private.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 int tmp;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  tmp = 0;
+  argp = stack;
+
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
+    *(void **) argp = ecif->rvalue;
+    argp += 4;
+  }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0) && (avn != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
+	argp = (char *) ALIGN(argp, (*p_arg)->alignment);
+      }
+
+      if (avn != 0) 
+	{
+	  avn--;
+	  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:
+    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;
+}
+
+/*@-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;
+    }
+}
+
+
+/** private members **/
+
+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
+					 void** args, ffi_cif* cif);
+static void ffi_closure_SYSV ();
+static void ffi_closure_raw_SYSV ();
+
+/* This function is jumped to by the trampoline, on entry, %ecx (a
+ * caller-save register) holds the address of the closure.  
+ * Clearly, this requires __GNUC__, so perhaps we should translate this
+ * into an assembly file if this is to be distributed with ffi.
+ */
+
+static void
+ffi_closure_SYSV ()
+{
+  // this is our return value storage
+  long double    res;
+
+  // our various things...
+  void          *args;
+  ffi_cif       *cif;
+  void         **arg_area;
+  ffi_closure   *closure;
+  unsigned short rtype;
+  void          *resp = (void*)&res;
+
+  /* grab the trampoline context pointer */
+  asm ("movl %%ecx,%0" : "=r" (closure));
+  
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+  asm ("leal 8(%%ebp),%0" : "=q" (args));  
+
+  /* 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");
+    }
+}
+
+/*@-exportheader@*/
+static void 
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
+			    void **avalue, ffi_cif *cif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register int tmp;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  tmp = 0;
+  argp = stack;
+
+  if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
+    *rvalue = *(void **) argp;
+    argp += 4;
+  }
+
+  avn = cif->nargs;
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types;
+       (i != 0) && (avn != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
+	argp = (char *) ALIGN(argp, (*p_arg)->alignment);
+      }
+
+      if (avn != 0) 
+	{
+	  avn--;
+	  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 + 10); \
+   *(unsigned char*) &__tramp[0] = 0xb9; \
+   *(unsigned int*)  &__tramp[1] = __ctx; \
+   *(unsigned char*) &__tramp[5] = 0xe9; \
+   *(unsigned int*)  &__tramp[6] = __dis; \
+ })
+
+
+/* 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 ()
+{
+  // this is our return value storage
+  long double    res;
+
+  // our various things...
+  void            *args;
+  ffi_raw         *raw_args;
+  ffi_cif         *cif;
+  ffi_raw_closure *closure;
+  unsigned short   rtype;
+  void            *resp = (void*)&res;
+
+  /* grab the trampoline context pointer */
+  asm ("movl %%ecx,%0" : "=r" (closure));
+
+  /* take the argument pointer */
+  asm ("leal 8(%%ebp),%0" : "=q" (args));  
+
+  /* get the cif */
+  cif = closure->cif;
+
+  /* the SYSV/X86 abi matches the RAW API exactly, well.. almost */
+  raw_args = (ffi_raw*) args;
+
+  (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 seperate 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)());
+
+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;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#endif

+ 167 - 0
libffi/x86/sysv.S

@@ -0,0 +1,167 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1996, 1998  Cygnus Solutions
+   
+   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 <ffi.h>
+#include <ffi_private.h>
+
+.text
+
+.globl ffi_prep_args
+
+	# This assumes we are using gas.
+        .balign 16
+.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,"aw",@progbits
+__FRAME_BEGIN__:
+	.4byte	.LLCIE1
+.LSCIE1:
+	.4byte	0x0
+	.byte	0x1
+	.byte	0x0
+	.byte	0x1
+	.byte	0x7c
+	.byte	0x8
+	.byte	0xc
+	.byte	0x4
+	.byte	0x4
+	.byte	0x88
+	.byte	0x1
+	.align 4
+.LECIE1:
+	.set	.LLCIE1,.LECIE1-.LSCIE1
+	.4byte	.LLFDE1
+.LSFDE1:
+	.4byte	.LSFDE1-__FRAME_BEGIN__
+	.4byte	.LFB1
+	.4byte	.LFE1-.LFB1
+	.byte	0x4
+	.4byte	.LCFI0-.LFB1
+	.byte	0xe
+	.byte	0x8
+	.byte	0x85
+	.byte	0x2
+	.byte	0x4
+	.4byte	.LCFI1-.LCFI0
+	.byte	0xd
+	.byte	0x5
+	.align 4
+.LEFDE1:
+	.set	.LLFDE1,.LEFDE1-.LSFDE1

+ 125 - 0
libffi/x86/win32.S

@@ -0,0 +1,125 @@
+/* -----------------------------------------------------------------------
+   win32.S - Copyright (c) 1996, 1998, 2001  Cygnus Solutions
+ 
+   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 <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
+ 
+        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
+ 
+.ffi_call_SYSV_end:

+ 11 - 7
mono/interpreter/Makefile.am

@@ -1,16 +1,20 @@
-INCLUDES = $(GLIB_CFLAGS) $(GMODULE_CFLAGS) -I$(top_srcdir)
+INCLUDES = 				\
+	-I$(top_srcdir)			\
+	-I$(top_srcdir)/libffi/include	\
+	$(GLIB_CFLAGS)			\
+	$(GMODULE_CFLAGS)
 
 bin_PROGRAMS = mono-int
 
 mono_int_SOURCES =	\
-	interp.c	\
-	hacks.h	\
-	interp.h
+	hacks.h		\
+	interp.h	\
+	interp.c
 
-mono_int_LDADD =	\
+mono_int_LDADD =			\
 	../metadata/libmetadata.a	\
 	../cli/libmonocli.a		\
+	../../libffi/.libs/libffi.a	\
 	$(GMODULE_LIBS)			\
 	$(GLIB_LIBS)			\
-	-lffi -lm
-
+	-lm